diff --git a/reactos/Makefile b/reactos/Makefile index 3a1f685749c..f31ae65724a 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -26,23 +26,21 @@ $(ROS_INTERMEDIATE): ${nmkdir} $(ROS_INTERMEDIATE) endif -Makefile.auto: rmkdir buildno wmc rbuild - tools$(SEP)rbuild$(SEP)rbuild$(EXEPOSTFIX) mingw -# $(MAKE) $(MAKECMDGOALS) +include tools/Makefile +-include Makefile.auto -init:: \ +Makefile.auto: $(RMKDIR_TARGET) $(BUILDNO_TARGET) $(NCI_SERVICE_FILES) $(WMC_TARGET) $(RBUILD_TARGET) + tools$(SEP)rbuild$(SEP)rbuild$(EXEPOSTFIX) mingw + $(MAKE) $(MAKECMDGOALS) + +init: \ include$(SEP)reactos$(SEP)bugcodes.h \ ntoskrnl$(SEP)bugcodes.rc \ include$(SEP)reactos$(SEP)errcodes.h \ lib$(SEP)kernel32$(SEP)errcodes.rc -include$(SEP)reactos$(SEP)bugcodes.h ntoskrnl$(SEP)bugcodes.rc: ntoskrnl$(SEP)ntoskrnl.mc - $(WMC_TARGET) -H include$(SEP)reactos$(SEP)bugcodes.h -o ntoskrnl$(SEP)bugcodes.rc bugcodes$(SEP)ntoskrnl.mc +include$(SEP)reactos$(SEP)bugcodes.h ntoskrnl$(SEP)bugcodes.rc: $(WMC_TARGET) ntoskrnl$(SEP)ntoskrnl.mc + $(WMC_TARGET) -H include$(SEP)reactos$(SEP)bugcodes.h -o ntoskrnl$(SEP)bugcodes.rc ntoskrnl$(SEP)ntoskrnl.mc -include$(SEP)reactos$(SEP)errcodes.h lib$(SEP)kernel32$(SEP)errcodes.rc: lib$(SEP)kernel32$(SEP)kernel32.mc +include$(SEP)reactos$(SEP)errcodes.h lib$(SEP)kernel32$(SEP)errcodes.rc: $(WMC_TARGET) lib$(SEP)kernel32$(SEP)kernel32.mc $(WMC_TARGET) -H include$(SEP)reactos$(SEP)errcodes.h -o lib$(SEP)kernel32$(SEP)errcodes.rc lib$(SEP)kernel32$(SEP)kernel32.mc - -include tools/Makefile -include tools/rbuild/makefile - -#-include Makefile.auto diff --git a/reactos/ReactOS.xml b/reactos/ReactOS.xml index 019f3a9771c..954593c4e11 100644 --- a/reactos/ReactOS.xml +++ b/reactos/ReactOS.xml @@ -36,14 +36,6 @@ - - - - - - - - diff --git a/reactos/apps/utils/Makefile b/reactos/apps/utils/Makefile index 43d5be5c94b..92a1d5157f1 100644 --- a/reactos/apps/utils/Makefile +++ b/reactos/apps/utils/Makefile @@ -11,7 +11,7 @@ include $(PATH_TO_TOP)/rules.mak # cabman cat net objdir partinfo pice ps sc stats UTIL_APPS = cat objdir partinfo pnpdump sc shutdown stats tickcount consw rundll32 ps -UTIL_NET_APPS = arp finger ipconfig netstat ping route telnet whois +UTIL_NET_APPS = arp finger ftp ipconfig netstat ping route telnet whois all: $(UTIL_APPS) $(UTIL_NET_APPS) diff --git a/reactos/apps/utils/net/directory.xml b/reactos/apps/utils/net/directory.xml index 57b9d6a1365..a0b63207a20 100644 --- a/reactos/apps/utils/net/directory.xml +++ b/reactos/apps/utils/net/directory.xml @@ -4,6 +4,9 @@ + + + @@ -13,6 +16,9 @@ + + + diff --git a/reactos/apps/utils/net/ftp/cmds.c b/reactos/apps/utils/net/ftp/cmds.c new file mode 100644 index 00000000000..c88e3a0f7f8 --- /dev/null +++ b/reactos/apps/utils/net/ftp/cmds.c @@ -0,0 +1,2376 @@ +/* + * Copyright (c) 1985, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmds.c 5.18 (Berkeley) 4/20/89"; +#endif /* not lint */ + +/* + * FTP User Program -- Command Routines. + */ +//#include +//#include +#include +#if !defined(WIN32) +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" +#include "pathnames.h" +#include "prototypes.h" + +extern char *globerr; +extern char **glob(); +extern char home[]; +extern char *remglob(); +extern char *getenv(); +extern int allbinary; +extern off_t restart_point; +extern char reply_string[]; + +char *mname; +jmp_buf jabort; +char *dotrans(), *domap(); + +extern short portnum; +extern char *hostname; +extern int autologin; +/* + * Connect to peer server and + * auto-login, if possible. + */ +void setpeer(int argc, char *argv[]) +{ + char *host, *hookup(); + + if (connected) { + printf("Already connected to %s, use close first.\n", + hostname); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 2) { + (void) strcat(line, " "); + printf("(to) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc > 3) { + printf("usage: %s host-name [port]\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (argc > 2) { + portnum = atoi(argv[2]); + if (portnum <= 0) { + printf("%s: bad port number-- %s\n", argv[1], argv[2]); + printf ("usage: %s host-name [port]\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + portnum = htons(portnum); + } + host = hookup(argv[1], portnum); + if (host) { +#if defined(unix) && NBBY == 8 + int overbose; +#endif + connected = 1; + if (autologin) + (void) login(argv[1]); + +#if defined(unix) && NBBY == 8 +/* + * this ifdef is to keep someone form "porting" this to an incompatible + * system and not checking this out. This way they have to think about it. + */ + overbose = verbose; + if (debug == 0) + verbose = -1; + allbinary = 0; + if (command("SYST") == COMPLETE && overbose) { + register char *cp, c; + cp = index(reply_string+4, ' '); + if (cp == NULL) + cp = index(reply_string+4, '\r'); + if (cp) { + if (cp[-1] == '.') + cp--; + c = *cp; + *cp = '\0'; + } + + printf("Remote system type is %s.\n", + reply_string+4); + if (cp) + *cp = c; + } + if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { + setbinary(); + /* allbinary = 1; this violates the RFC */ + if (overbose) + printf("Using %s mode to transfer files.\n", + typename); + } else if (overbose && + !strncmp(reply_string, "215 TOPS20", 10)) { + printf( +"Remember to set tenex mode when transfering binary files from this machine.\n"); + } + verbose = overbose; +#endif /* unix */ + } + (void) fflush(stdout); +} + +struct types { + char *t_name; + char *t_mode; + int t_type; + char *t_arg; +} types[] = { + { "ascii", "A", TYPE_A, 0 }, + { "binary", "I", TYPE_I, 0 }, + { "image", "I", TYPE_I, 0 }, + { "ebcdic", "E", TYPE_E, 0 }, + { "tenex", "L", TYPE_L, bytename }, + 0 +}; + +/* + * Set transfer type. + */ +void settype(argc, argv) + char *argv[]; +{ + register struct types *p; + int comret; + + if (argc > 2) { + char *sep; + + printf("usage: %s [", argv[0]); + sep = " "; + for (p = types; p->t_name; p++) { + printf("%s%s", sep, p->t_name); + if (*sep == ' ') + sep = " | "; + } + printf(" ]\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 2) { + printf("Using %s mode to transfer files.\n", typename); + (void) fflush(stdout); + code = 0; + return; + } + for (p = types; p->t_name; p++) + if (strcmp(argv[1], p->t_name) == 0) + break; + if (p->t_name == 0) { + printf("%s: unknown mode\n", argv[1]); + (void) fflush(stdout); + code = -1; + return; + } + if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) + comret = command ("TYPE %s %s", p->t_mode, p->t_arg); + else + comret = command("TYPE %s", p->t_mode); + if (comret == COMPLETE) { + (void) strcpy(typename, p->t_name); + type = p->t_type; + } +} + +char *stype[] = { + "type", + "", + 0 +}; + +/* + * Set binary transfer type. + */ +/*VARARGS*/ +void setbinary() +{ + stype[1] = "binary"; + settype(2, stype); +} + +/* + * Set ascii transfer type. + */ +/*VARARGS*/ +void setascii() +{ + stype[1] = "ascii"; + settype(2, stype); +} + +/* + * Set tenex transfer type. + */ +/*VARARGS*/ +void settenex() +{ + stype[1] = "tenex"; + settype(2, stype); +} + +/* + * Set ebcdic transfer type. + */ +/*VARARGS*/ +void setebcdic() +{ + stype[1] = "ebcdic"; + settype(2, stype); +} + +/* + * Set file transfer mode. + */ +#if 0 +/*ARGSUSED*/ +void setmode(argc, argv) + char *argv[]; +{ + + printf("We only support %s mode, sorry.\n", modename); + (void) fflush(stdout); + code = -1; +} +#endif + +/* + * Set file transfer format. + */ +/*ARGSUSED*/ +void setform(argc, argv) + char *argv[]; +{ + + printf("We only support %s format, sorry.\n", formname); + (void) fflush(stdout); + code = -1; +} + +/* + * Set file transfer structure. + */ +/*ARGSUSED*/ +void setstruct(argc, argv) + char *argv[]; +{ + + printf("We only support %s structure, sorry.\n", structname); + (void) fflush(stdout); + code = -1; +} + +/* + * Send a single file. + */ +void put(argc, argv) + int argc; + char *argv[]; +{ + char *cmd; + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2) { + (void) strcat(line, " "); + printf("(local-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { +usage: + printf("usage:%s local-file remote-file\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(remote-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) + goto usage; + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[1])) { + code = -1; + return; + } + /* + * If "globulize" modifies argv[1], and argv[2] is a copy of + * the old argv[1], make it a copy of the new argv[1]. + */ + if (argv[1] != oldargv1 && argv[2] == oldargv1) { + argv[2] = argv[1]; + } + cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); + if (loc && ntflag) { + argv[2] = dotrans(argv[2]); + } + if (loc && mapflag) { + argv[2] = domap(argv[2]); + } + sendrequest(cmd, argv[1], argv[2], + argv[1] != oldargv1 || argv[2] != oldargv2); +} + +/* + * Send multiple files. + */ +void mput(argc, argv) + char *argv[]; +{ + register int i; + int ointer; + void mabort(); + extern jmp_buf jabort; + char *tp; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(local-files) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s local-files\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; +// oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + if (proxy) { + char *cp, *tp2, tmpbuf[MAXPATHLEN]; + + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == 0) { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = cp; + tp2 = tmpbuf; + while ((*tp2 = *tp) != (int) NULL) { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + } + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, cp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } +// (void) signal(SIGINT, oldintr); + mflag = 0; + return; + } + for (i = 1; i < argc; i++) { + register char **cpp, **gargs; + + if (!doglob) { + if (mflag && confirm(argv[0], argv[i])) { + tp = (ntflag) ? dotrans(argv[i]) : argv[i]; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + argv[i], tp, tp != argv[i] || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + continue; + } + gargs = glob(argv[i]); + if (globerr != NULL) { + printf("%s\n", globerr); + (void) fflush(stdout); + if (gargs) { + blkfree(gargs); + free((char *)gargs); + } + continue; + } + for (cpp = gargs; cpp && *cpp != NULL; cpp++) { + if (mflag && confirm(argv[0], *cpp)) { + tp = (ntflag) ? dotrans(*cpp) : *cpp; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + *cpp, tp, *cpp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + if (gargs != NULL) { + blkfree(gargs); + free((char *)gargs); + } + } +// (void) signal(SIGINT, oldintr); + mflag = 0; +} + +void reget(argc, argv) + char *argv[]; +{ + (void) getit(argc, argv, 1, "r+w"); +} + +void get(argc, argv) + char *argv[]; +{ + (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); +} + +/* + * Receive one file. + */ +int getit(argc, argv, restartit, mode) + char *argv[]; + char *mode; +{ + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { +usage: + printf("usage: %s remote-file [ local-file ]\n", argv[0]); + (void) fflush(stdout); + code = -1; + return (0); + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(local-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) + goto usage; + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[2])) { + code = -1; + return (0); + } + if (loc && mcase) { + char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; + + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = argv[2]; + tp2 = tmpbuf; + while ((*tp2 = *tp) != (int) NULL) { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + argv[2] = tmpbuf; + } + } + if (loc && ntflag) + argv[2] = dotrans(argv[2]); + if (loc && mapflag) + argv[2] = domap(argv[2]); + if (restartit) { + struct stat stbuf; + int ret; + + ret = stat(argv[2], &stbuf); + if (restartit == 1) { + if (ret < 0) { + perror(argv[2]); + return (0); + } + restart_point = stbuf.st_size; + } else { + if (ret == 0) { + int overbose; + + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + struct tm *tm; + verbose = overbose; + sscanf(reply_string, + "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec); + tm = gmtime(&stbuf.st_mtime); + tm->tm_mon++; + if (tm->tm_year > yy%100) + return (1); + else if (tm->tm_year == yy%100) { + if (tm->tm_mon > mo) + return (1); + } else if (tm->tm_mon == mo) { + if (tm->tm_mday > day) + return (1); + } else if (tm->tm_mday == day) { + if (tm->tm_hour > hour) + return (1); + } else if (tm->tm_hour == hour) { + if (tm->tm_min > min) + return (1); + } else if (tm->tm_min == min) { + if (tm->tm_sec > sec) + return (1); + } + } else { + printf("%s\n", reply_string); + (void) fflush(stdout); + verbose = overbose; + return (0); + } + } + } + } + + recvrequest("RETR", argv[2], argv[1], mode, + argv[1] != oldargv1 || argv[2] != oldargv2); + restart_point = 0; + return (0); +} + +void +mabort() +{ + int ointer; + extern jmp_buf jabort; + + printf("\n"); + (void) fflush(stdout); + if (mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", mname)) { + interactive = ointer; + longjmp(jabort,0); + } + interactive = ointer; + } + mflag = 0; + longjmp(jabort,0); +} + +/* + * Get multiple files. + */ +void mget(argc, argv) + char *argv[]; +{ + char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; + int ointer; + void mabort(); + extern jmp_buf jabort; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-files) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s remote-files\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; +// oldintr = signal(SIGINT,mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv,proxy)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = cp; + tp2 = tmpbuf; + while ((*tp2 = *tp) != (int) NULL) { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + } + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + recvrequest("RETR", tp, cp, "w", + tp != cp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mget")) { + mflag++; + } + interactive = ointer; + } + } + } +// (void) signal(SIGINT,oldintr); + mflag = 0; +} + +char * +remglob(argv,doswitch) + char *argv[]; + int doswitch; +{ + char temp[16]; + static char buf[MAXPATHLEN]; + static FILE *ftemp = NULL; + static char **args; + int oldverbose, oldhash; + char *cp, *mode; + + if (!mflag) { + if (!doglob) { + args = NULL; + } + else { + if (ftemp) { + (void) fclose(ftemp); + ftemp = NULL; + } + } + return(NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + (void) strcpy(temp, _PATH_TMP); + (void) mktemp(temp); + oldverbose = verbose, verbose = 0; + oldhash = hash, hash = 0; + if (doswitch) { + pswitch(!proxy); + } + for (mode = "w"; *++argv != NULL; mode = "a") + recvrequest ("NLST", temp, *argv, mode, 0); + if (doswitch) { + pswitch(!proxy); + } + verbose = oldverbose; hash = oldhash; + ftemp = fopen(temp, "r"); + (void) unlink(temp); + if (ftemp == NULL) { + printf("can't find list of remote files, oops\n"); + (void) fflush(stdout); + return (NULL); + } + } + if (fgets(buf, sizeof (buf), ftemp) == NULL) { + (void) fclose(ftemp), ftemp = NULL; + return (NULL); + } + if ((cp = index(buf, '\n')) != NULL) + *cp = '\0'; + return (buf); +} + +char * +onoff(bool) + int bool; +{ + + return (bool ? "on" : "off"); +} + +/* + * Show status. + */ +/*ARGSUSED*/ +void status(argc, argv) + char *argv[]; +{ + int i; + + if (connected) + printf("Connected to %s.\n", hostname); + else + printf("Not connected.\n"); + if (!proxy) { + pswitch(1); + if (connected) { + printf("Connected for proxy commands to %s.\n", hostname); + } + else { + printf("No proxy connection.\n"); + } + pswitch(0); + } + printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", + modename, typename, formname, structname); + printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", + onoff(verbose), onoff(bell), onoff(interactive), + onoff(doglob)); + printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), + onoff(runique)); + printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); + if (ntflag) { + printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); + } + else { + printf("Ntrans: off\n"); + } + if (mapflag) { + printf("Nmap: (in) %s (out) %s\n", mapin, mapout); + } + else { + printf("Nmap: off\n"); + } + printf("Hash mark printing: %s; Use of PORT cmds: %s\n", + onoff(hash), onoff(sendport)); + if (macnum > 0) { + printf("Macros:\n"); + for (i=0; i 1) { + val = atoi(argv[1]); + if (val < 0) { + printf("%s: bad debugging value.\n", argv[1]); + (void) fflush(stdout); + code = -1; + return; + } + } else + val = !debug; + debug = val; + if (debug) + options |= SO_DEBUG; + else + options &= ~SO_DEBUG; + printf("Debugging %s (debug=%d).\n", onoff(debug), debug); + (void) fflush(stdout); + code = debug > 0; +} + +/* + * Set current working directory + * on remote machine. + */ +void cd(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-directory) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s remote-directory\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (command("CWD %s", argv[1]) == ERROR && code == 500) { + if (verbose) { + printf("CWD command not recognized, trying XCWD\n"); + (void) fflush(stdout); + } + (void) command("XCWD %s", argv[1]); + } +} + +/* + * Set current working directory + * on local machine. + */ +void lcd(argc, argv) + char *argv[]; +{ + char buf[MAXPATHLEN]; + + if (argc < 2) + argc++, argv[1] = home; + if (argc != 2) { + printf("usage:%s local-directory\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (!globulize(&argv[1])) { + code = -1; + return; + } + if (chdir(argv[1]) < 0) { + perror(argv[1]); + code = -1; + return; + } + printf("Local directory now %s\n", getcwd(buf,sizeof(buf))); + (void) fflush(stdout); + code = 0; +} + +/* + * Delete a single file. + */ +void delete(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s remote-file\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + (void) command("DELE %s", argv[1]); +} + +/* + * Delete multiple files. + */ +void mdelete(argc, argv) + char *argv[]; +{ + char *cp; + int ointer; + void mabort(); + extern jmp_buf jabort; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-files) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s remote-files\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; +// oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + (void) command("DELE %s", cp); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mdelete")) { + mflag++; + } + interactive = ointer; + } + } + } +// (void) signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Rename a remote file. + */ +void renamefile(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(from-name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { +usage: + printf("%s from-name to-name\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(to-name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) + goto usage; + if (command("RNFR %s", argv[1]) == CONTINUE) + (void) command("RNTO %s", argv[2]); +} + +/* + * Get a directory listing + * of remote files. + */ +void ls(argc, argv) + char *argv[]; +{ + char *cmd; + + if (argc < 2) + argc++, argv[1] = NULL; + if (argc < 3) + argc++, argv[2] = "-"; + if (argc > 3) { + printf("usage: %s remote-directory local-file\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; +// cmd = argv[0][0] == 'n' ? "NLST -CF" : "NLST -CF"; + if (strcmp(argv[2], "-") && !globulize(&argv[2])) { + code = -1; + return; + } + if (strcmp(argv[2], "-") && *argv[2] != '|') + if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { + code = -1; + return; + } + recvrequest(cmd, argv[2], argv[1], "w", 0); +} + +/* + * Get a directory listing + * of multiple remote files. + */ +void mls(argc, argv) + char *argv[]; +{ + char *cmd, mode[1], *dest; + int ointer, i; + void mabort(); + extern jmp_buf jabort; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(remote-files) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(local-file) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) { + printf("usage:%s remote-files local-file\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + dest = argv[argc - 1]; + argv[argc - 1] = NULL; + if (strcmp(dest, "-") && *dest != '|') + if (!globulize(&dest) || !confirm("output to local-file:", dest)) { + code = -1; + return; + } + cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; + mname = argv[0]; + mflag = 1; +// oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + for (i = 1; mflag && i < argc-1; ++i) { + *mode = (i == 1) ? 'w' : 'a'; + recvrequest(cmd, dest, argv[i], mode, 0); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", argv[0])) { + mflag ++; + } + interactive = ointer; + } + } +// (void) signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Do a shell escape + */ +/*ARGSUSED*/ +shell(argc, argv) + char *argv[]; +{ +#if 0 + int pid; + sig_t (*old1)(), (*old2)(); + char shellnam[40], *shell, *namep; + union wait status; + + old1 = signal (SIGINT, SIG_IGN); + old2 = signal (SIGQUIT, SIG_IGN); + if ((pid = fork()) == 0) { + for (pid = 3; pid < 20; pid++) + (void) close(pid); + (void) signal(SIGINT, SIG_DFL); + (void) signal(SIGQUIT, SIG_DFL); + shell = getenv("SHELL"); + if (shell == NULL) + shell = _PATH_BSHELL; + namep = rindex(shell,'/'); + if (namep == NULL) + namep = shell; + (void) strcpy(shellnam,"-"); + (void) strcat(shellnam, ++namep); + if (strcmp(namep, "sh") != 0) + shellnam[0] = '+'; + if (debug) { + printf ("%s\n", shell); + (void) fflush (stdout); + } + if (argc > 1) { + execl(shell,shellnam,"-c",altarg,(char *)0); + } + else { + execl(shell,shellnam,(char *)0); + } + perror(shell); + code = -1; + exit(1); + } + if (pid > 0) + while (wait(&status) != pid) + ; + (void) signal(SIGINT, old1); + (void) signal(SIGQUIT, old2); + if (pid == -1) { + perror("Try again later"); + code = -1; + } + else { + code = 0; + } +#endif + + char * AppName; + char ShellCmd[MAX_PATH]; + char CmdLine[MAX_PATH]; + int i; + PROCESS_INFORMATION ProcessInformation; + BOOL Result; + STARTUPINFO StartupInfo; + char ShellName[] = "COMSPEC"; + int NumBytes; + + NumBytes = GetEnvironmentVariable( ShellName, ShellCmd, MAX_PATH); + + if (NumBytes == 0) + { + return(-1); + } + + AppName = ShellCmd; + strcpy( CmdLine, ShellCmd ); + + if (argc > 1) + { + strncat(CmdLine, " /C", MAX_PATH); + } + + for (i=1; i 4) { + printf("usage: %s username [password] [account]\n", argv[0]); + (void) fflush(stdout); + code = -1; + return (0); + } + n = command("USER %s", argv[1]); + if (n == CONTINUE) { + if (argc < 3 ) + argv[2] = getpass("Password: "), argc++; + n = command("PASS %s", argv[2]); + } + if (n == CONTINUE) { + if (argc < 4) { + printf("Account: "); (void) fflush(stdout); + (void) fflush(stdout); + (void) fgets(acct, sizeof(acct) - 1, stdin); + acct[strlen(acct) - 1] = '\0'; + argv[3] = acct; argc++; + } + n = command("ACCT %s", argv[3]); + aflag++; + } + if (n != COMPLETE) { + fprintf(stdout, "Login failed.\n"); + (void) fflush(stdout); + return (0); + } + if (!aflag && argc == 4) { + (void) command("ACCT %s", argv[3]); + } + return (1); +} + +/* + * Print working directory. + */ +/*VARARGS*/ +void pwd() +{ + int oldverbose = verbose; + + /* + * If we aren't verbose, this doesn't do anything! + */ + verbose = 1; + if (command("PWD") == ERROR && code == 500) { + printf("PWD command not recognized, trying XPWD\n"); + (void) fflush(stdout); + (void) command("XPWD"); + } + verbose = oldverbose; +} + +/* + * Make a directory. + */ +void makedir(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(directory-name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage: %s directory-name\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (command("MKD %s", argv[1]) == ERROR && code == 500) { + if (verbose) { + printf("MKD command not recognized, trying XMKD\n"); + (void) fflush(stdout); + } + (void) command("XMKD %s", argv[1]); + } +} + +/* + * Remove a directory. + */ +void removedir(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(directory-name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage: %s directory-name\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (command("RMD %s", argv[1]) == ERROR && code == 500) { + if (verbose) { + printf("RMD command not recognized, trying XRMD\n"); + (void) fflush(stdout); + } + (void) command("XRMD %s", argv[1]); + } +} + +/* + * Send a line, verbatim, to the remote machine. + */ +void quote(argc, argv) + char *argv[]; +{ + int i; + char buf[BUFSIZ]; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(command line to send) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage: %s line-to-send\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + (void) strcpy(buf, argv[1]); + for (i = 2; i < argc; i++) { + (void) strcat(buf, " "); + (void) strcat(buf, argv[i]); + } + if (command(buf) == PRELIM) { + while (getreply(0) == PRELIM); + } +} + +/* + * Send a SITE command to the remote machine. The line + * is sent almost verbatim to the remote machine, the + * first argument is changed to SITE. + */ + +void site(argc, argv) + char *argv[]; +{ + int i; + char buf[BUFSIZ]; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(arguments to SITE command) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage: %s line-to-send\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + (void) strcpy(buf, "SITE "); + (void) strcat(buf, argv[1]); + for (i = 2; i < argc; i++) { + (void) strcat(buf, " "); + (void) strcat(buf, argv[i]); + } + if (command(buf) == PRELIM) { + while (getreply(0) == PRELIM); + } +} + +void do_chmod(argc, argv) + char *argv[]; +{ + if (argc == 2) { + printf("usage: %s mode file-name\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(mode and file-name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc != 3) { + printf("usage: %s mode file-name\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + (void)command("SITE CHMOD %s %s", argv[1], argv[2]); +} + +void do_umask(argc, argv) + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); + verbose = oldverbose; +} + +void idle(argc, argv) + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); + verbose = oldverbose; +} + +/* + * Ask the other side for help. + */ +void rmthelp(argc, argv) + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); + verbose = oldverbose; +} + +/* + * Terminate session and exit. + */ +/*VARARGS*/ +void quit() +{ + + if (connected) + disconnect(); + pswitch(1); + if (connected) { + disconnect(); + } + exit(0); +} + +/* + * Terminate session, but don't exit. + */ +void disconnect() +{ + extern int cout; + extern int data; + + if (!connected) + return; + (void) command("QUIT"); + cout = (int) NULL; + connected = 0; + data = -1; + if (!proxy) { + macnum = 0; + } +} + +confirm(cmd, file) + char *cmd, *file; +{ + char line[BUFSIZ]; + + if (!interactive) + return (1); + printf("%s %s? ", cmd, file); + (void) fflush(stdout); + (void) gets(line); + return (*line != 'n' && *line != 'N'); +} + +void fatal(msg) + char *msg; +{ + + fprintf(stderr, "ftp: %s\n", msg); + exit(1); +} + +/* + * Glob a local file name specification with + * the expectation of a single return value. + * Can't control multiple values being expanded + * from the expression, we return only the first. + */ +globulize(cpp) + char **cpp; +{ + char **globbed; + + if (!doglob) + return (1); + globbed = glob(*cpp); + if (globerr != NULL) { + printf("%s: %s\n", *cpp, globerr); + (void) fflush(stdout); + if (globbed) { + blkfree(globbed); + free((char *)globbed); + } + return (0); + } + if (globbed) { + *cpp = *globbed++; + /* don't waste too much memory */ + if (*globbed) { + blkfree(globbed); + free((char *)globbed); + } + } + return (1); +} + +void account(argc,argv) + int argc; + char **argv; +{ + char acct[50], *getpass(), *ap; + + if (argc > 1) { + ++argv; + --argc; + (void) strncpy(acct,*argv,49); + acct[49] = '\0'; + while (argc > 1) { + --argc; + ++argv; + (void) strncat(acct,*argv, 49-strlen(acct)); + } + ap = acct; + } + else { + ap = getpass("Account:"); + } + (void) command("ACCT %s", ap); +} + +jmp_buf abortprox; + +void +proxabort() +{ + extern int proxy; + + if (!proxy) { + pswitch(1); + } + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + longjmp(abortprox,1); +} + +void doproxy(argc,argv) + int argc; + char *argv[]; +{ + void proxabort(); + register struct cmd *c; + struct cmd *getcmd(); + extern struct cmd cmdtab[]; + extern jmp_buf abortprox; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(command) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s command\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + c = getcmd(argv[1]); + if (c == (struct cmd *) -1) { + printf("?Ambiguous command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (c == 0) { + printf("?Invalid command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (!c->c_proxy) { + printf("?Invalid proxy command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (setjmp(abortprox)) { + code = -1; + return; + } +// oldintr = signal(SIGINT, proxabort); + pswitch(1); + if (c->c_conn && !connected) { + printf("Not connected\n"); + (void) fflush(stdout); + pswitch(0); +// (void) signal(SIGINT, oldintr); + code = -1; + return; + } + (*c->c_handler)(argc-1, argv+1); + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); +// (void) signal(SIGINT, oldintr); +} + +void setcase() +{ + mcase = !mcase; + printf("Case mapping %s.\n", onoff(mcase)); + (void) fflush(stdout); + code = mcase; +} + +void setcr() +{ + crflag = !crflag; + printf("Carriage Return stripping %s.\n", onoff(crflag)); + (void) fflush(stdout); + code = crflag; +} + +void setntrans(argc,argv) + int argc; + char *argv[]; +{ + if (argc == 1) { + ntflag = 0; + printf("Ntrans off.\n"); + (void) fflush(stdout); + code = ntflag; + return; + } + ntflag++; + code = ntflag; + (void) strncpy(ntin, argv[1], 16); + ntin[16] = '\0'; + if (argc == 2) { + ntout[0] = '\0'; + return; + } + (void) strncpy(ntout, argv[2], 16); + ntout[16] = '\0'; +} + +char * +dotrans(name) + char *name; +{ + static char new[MAXPATHLEN]; + char *cp1, *cp2 = new; + register int i, ostop, found; + + for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); + for (cp1 = name; *cp1; cp1++) { + found = 0; + for (i = 0; *(ntin + i) && i < 16; i++) { + if (*cp1 == *(ntin + i)) { + found++; + if (i < ostop) { + *cp2++ = *(ntout + i); + } + break; + } + } + if (!found) { + *cp2++ = *cp1; + } + } + *cp2 = '\0'; + return(new); +} + + +void +setpassive(argc, argv) + int argc; + char *argv[]; +{ + passivemode = !passivemode; + printf("Passive mode %s.\n", onoff(passivemode)); + (void) fflush(stdout); + code = passivemode; +} + +void setnmap(argc, argv) + int argc; + char *argv[]; +{ + char *cp; + + if (argc == 1) { + mapflag = 0; + printf("Nmap off.\n"); + (void) fflush(stdout); + code = mapflag; + return; + } + if (argc < 3) { + (void) strcat(line, " "); + printf("(mapout) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 3) { + printf("Usage: %s [mapin mapout]\n",argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + mapflag = 1; + code = 1; + cp = index(altarg, ' '); + if (proxy) { + while(*++cp == ' '); + altarg = cp; + cp = index(altarg, ' '); + } + *cp = '\0'; + (void) strncpy(mapin, altarg, MAXPATHLEN - 1); + while (*++cp == ' '); + (void) strncpy(mapout, cp, MAXPATHLEN - 1); +} + +char * +domap(name) + char *name; +{ + static char new[MAXPATHLEN]; + register char *cp1 = name, *cp2 = mapin; + char *tp[9], *te[9]; + int i, toks[9], toknum = 0, match = 1; + + for (i=0; i < 9; ++i) { + toks[i] = 0; + } + while (match && *cp1 && *cp2) { + switch (*cp2) { + case '\\': + if (*++cp2 != *cp1) { + match = 0; + } + break; + case '$': + if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { + if (*cp1 != *(++cp2+1)) { + toks[toknum = *cp2 - '1']++; + tp[toknum] = cp1; + while (*++cp1 && *(cp2+1) + != *cp1); + te[toknum] = cp1; + } + cp2++; + break; + } + /* FALLTHROUGH */ + default: + if (*cp2 != *cp1) { + match = 0; + } + break; + } + if (match && *cp1) { + cp1++; + } + if (match && *cp2) { + cp2++; + } + } + if (!match && *cp1) /* last token mismatch */ + { + toks[toknum] = 0; + } + cp1 = new; + *cp1 = '\0'; + cp2 = mapout; + while (*cp2) { + match = 0; + switch (*cp2) { + case '\\': + if (*(cp2 + 1)) { + *cp1++ = *++cp2; + } + break; + case '[': +LOOP: + if (*++cp2 == '$' && isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + match = 1; + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + match = 1; + } + } + else { + while (*cp2 && *cp2 != ',' && + *cp2 != ']') { + if (*cp2 == '\\') { + cp2++; + } + else if (*cp2 == '$' && + isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = + *cp2 - '1']) { + char *cp3=tp[toknum]; + + while (cp3 != + te[toknum]) { + *cp1++ = *cp3++; + } + } + } + else if (*cp2) { + *cp1++ = *cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + (void) fflush(stdout); + return(name); + } + match = 1; + cp2--; + } + if (match) { + while (*++cp2 && *cp2 != ']') { + if (*cp2 == '\\' && *(cp2 + 1)) { + cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + (void) fflush(stdout); + return(name); + } + break; + } + switch (*++cp2) { + case ',': + goto LOOP; + case ']': + break; + default: + cp2--; + goto LOOP; + } + break; + case '$': + if (isdigit(*(cp2 + 1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + } + break; + } + /* intentional drop through */ + default: + *cp1++ = *cp2; + break; + } + cp2++; + } + *cp1 = '\0'; + if (!*new) { + return(name); + } + return(new); +} + +void setsunique() +{ + sunique = !sunique; + printf("Store unique %s.\n", onoff(sunique)); + (void) fflush(stdout); + code = sunique; +} + +void setrunique() +{ + runique = !runique; + printf("Receive unique %s.\n", onoff(runique)); + (void) fflush(stdout); + code = runique; +} + +/* change directory to perent directory */ +void cdup() +{ + if (command("CDUP") == ERROR && code == 500) { + if (verbose) { + printf("CDUP command not recognized, trying XCUP\n"); + (void) fflush(stdout); + } + (void) command("XCUP"); + } +} + +/* restart transfer at specific point */ +void restart(argc, argv) + int argc; + char *argv[]; +{ + extern long atol(); + if (argc != 2) + printf("restart: offset not specified\n"); + else { + restart_point = atol(argv[1]); + printf("restarting at %ld. %s\n", restart_point, + "execute get, put or append to initiate transfer"); + } + (void) fflush(stdout); +} + +/* show remote system type */ +void syst() +{ + (void) command("SYST"); +} + +void macdef(argc, argv) + int argc; + char *argv[]; +{ + char *tmp; + int c; + + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (argc < 2) { + (void) strcat(line, " "); + printf("(macro name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc != 2) { + printf("Usage: %s macro_name\n",argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + if (interactive) { + printf("Enter macro line by line, terminating it with a null line\n"); + (void) fflush(stdout); + } + (void) strncpy(macros[macnum].mac_name, argv[1], 8); + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf+4096) { + if ((c = getchar()) == EOF) { + printf("macdef:end of file encountered\n"); + (void) fflush(stdout); + code = -1; + return; + } + if ((*tmp = c) == '\n') { + if (tmp == macros[macnum].mac_start) { + macros[macnum++].mac_end = tmp; + code = 0; + return; + } + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + code = 0; + return; + } + *tmp = '\0'; + } + tmp++; + } + while (1) { + while ((c = getchar()) != '\n' && c != EOF) + /* LOOP */; + if (c == EOF || getchar() == '\n') { + printf("Macro not defined - 4k buffer exceeded\n"); + (void) fflush(stdout); + code = -1; + return; + } + } +} + +/* + * get size of file on remote machine + */ +void sizecmd(argc, argv) + char *argv[]; +{ + + if (argc < 2) { + (void) strcat(line, " "); + printf("(filename) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s filename\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + (void) command("SIZE %s", argv[1]); +} + +/* + * get last modification time of file on remote machine + */ +void modtime(argc, argv) + char *argv[]; +{ + int overbose; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(filename) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("usage:%s filename\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, + &day, &hour, &min, &sec); + /* might want to print this in local time */ + printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], + mo, day, yy, hour, min, sec); + } else + printf("%s\n", reply_string); + verbose = overbose; + (void) fflush(stdout); +} + +/* + * show status on reomte machine + */ +void rmtstatus(argc, argv) + char *argv[]; +{ + (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); +} + +/* + * get file if modtime is more recent than current file + */ +void newer(argc, argv) + char *argv[]; +{ + if (getit(argc, argv, -1, "w")) { + printf("Local file \"%s\" is newer than remote file \"%s\"\n", + argv[1], argv[2]); + (void) fflush(stdout); + } +} diff --git a/reactos/apps/utils/net/ftp/cmdtab.c b/reactos/apps/utils/net/ftp/cmdtab.c new file mode 100644 index 00000000000..5dd04ff340f --- /dev/null +++ b/reactos/apps/utils/net/ftp/cmdtab.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1985, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmdtab.c 5.9 (Berkeley) 3/21/89"; +#endif /* not lint */ + +#include "ftp_var.h" + +/* + * User FTP -- Command Tables. + */ +int setascii(), setbell(), setbinary(), setdebug(), setform(); +int setglob(), sethash(), setmode(), setpeer(), setpassive(), setport(); +int setprompt(), setstruct(); +int settenex(), settrace(), settype(), setverbose(); +int disconnect(), restart(), reget(), syst(); +int cd(), lcd(), delete(), mdelete(), user(); +int ls(), mls(), get(), mget(), help(), append(), put(), mput(); +int quit(), renamefile(), status(); +int quote(), rmthelp(), shell(), site(); +int pwd(), makedir(), removedir(), setcr(); +int account(), doproxy(), reset(), setcase(), setntrans(), setnmap(); +int setsunique(), setrunique(), cdup(), macdef(), domacro(); +int sizecmd(), modtime(), newer(), rmtstatus(); +int do_chmod(), do_umask(), idle(); + +char accounthelp[] = "send account command to remote server"; +char appendhelp[] = "append to a file"; +char asciihelp[] = "set ascii transfer type"; +char beephelp[] = "beep when command completed"; +char binaryhelp[] = "set binary transfer type"; +char casehelp[] = "toggle mget upper/lower case id mapping"; +char cdhelp[] = "change remote working directory"; +char cduphelp[] = "change remote working directory to parent directory"; +char chmodhelp[] = "change file permissions of remote file"; +char connecthelp[] = "connect to remote tftp"; +char crhelp[] = "toggle carriage return stripping on ascii gets"; +char deletehelp[] = "delete remote file"; +char debughelp[] = "toggle/set debugging mode"; +char dirhelp[] = "list contents of remote directory"; +char disconhelp[] = "terminate ftp session"; +char domachelp[] = "execute macro"; +char formhelp[] = "set file transfer format"; +char globhelp[] = "toggle metacharacter expansion of local file names"; +char hashhelp[] = "toggle printing `#' for each buffer transferred"; +char helphelp[] = "print local help information"; +char idlehelp[] = "get (set) idle timer on remote side"; +char lcdhelp[] = "change local working directory"; +char lshelp[] = "list contents of remote directory"; +char macdefhelp[] = "define a macro"; +char mdeletehelp[] = "delete multiple files"; +char mdirhelp[] = "list contents of multiple remote directories"; +char mgethelp[] = "get multiple files"; +char mkdirhelp[] = "make directory on the remote machine"; +char mlshelp[] = "list contents of multiple remote directories"; +char modtimehelp[] = "show last modification time of remote file"; +char modehelp[] = "set file transfer mode"; +char mputhelp[] = "send multiple files"; +char newerhelp[] = "get file if remote file is newer than local file "; +char nlisthelp[] = "nlist contents of remote directory"; +char nmaphelp[] = "set templates for default file name mapping"; +char ntranshelp[] = "set translation table for default file name mapping"; +char porthelp[] = "toggle use of PORT cmd for each data connection"; +char prompthelp[] = "force interactive prompting on multiple commands"; +char proxyhelp[] = "issue command on alternate connection"; +char pwdhelp[] = "print working directory on remote machine"; +char quithelp[] = "terminate ftp session and exit"; +char quotehelp[] = "send arbitrary ftp command"; +char receivehelp[] = "receive file"; +char regethelp[] = "get file restarting at end of local file"; +char remotehelp[] = "get help from remote server"; +char renamehelp[] = "rename file"; +char restarthelp[]= "restart file transfer at bytecount"; +char rmdirhelp[] = "remove directory on the remote machine"; +char rmtstatushelp[]="show status of remote machine"; +char runiquehelp[] = "toggle store unique for local files"; +char resethelp[] = "clear queued command replies"; +char sendhelp[] = "send one file"; +char passivehelp[] = "enter passive transfer mode"; +char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information"; +char shellhelp[] = "escape to the shell"; +char sizecmdhelp[] = "show size of remote file"; +char statushelp[] = "show current status"; +char structhelp[] = "set file transfer structure"; +char suniquehelp[] = "toggle store unique on remote machine"; +char systemhelp[] = "show remote system type"; +char tenexhelp[] = "set tenex file transfer type"; +char tracehelp[] = "toggle packet tracing"; +char typehelp[] = "set file transfer type"; +char umaskhelp[] = "get (set) umask on remote side"; +char userhelp[] = "send new user information"; +char verbosehelp[] = "toggle verbose mode"; + +struct cmd cmdtab[] = { + { "!", shellhelp, 0, 0, 0, shell }, + { "$", domachelp, 1, 0, 0, domacro }, + { "account", accounthelp, 0, 1, 1, account}, + { "append", appendhelp, 1, 1, 1, put }, + { "ascii", asciihelp, 0, 1, 1, setascii }, + { "bell", beephelp, 0, 0, 0, setbell }, + { "binary", binaryhelp, 0, 1, 1, setbinary }, + { "bye", quithelp, 0, 0, 0, quit }, + { "case", casehelp, 0, 0, 1, setcase }, + { "cd", cdhelp, 0, 1, 1, cd }, + { "cdup", cduphelp, 0, 1, 1, cdup }, + { "chmod", chmodhelp, 0, 1, 1, do_chmod }, + { "close", disconhelp, 0, 1, 1, disconnect }, + { "cr", crhelp, 0, 0, 0, setcr }, + { "delete", deletehelp, 0, 1, 1, delete }, + { "debug", debughelp, 0, 0, 0, setdebug }, + { "dir", dirhelp, 1, 1, 1, ls }, + { "disconnect", disconhelp, 0, 1, 1, disconnect }, + { "form", formhelp, 0, 1, 1, setform }, + { "get", receivehelp, 1, 1, 1, get }, + { "glob", globhelp, 0, 0, 0, setglob }, + { "hash", hashhelp, 0, 0, 0, sethash }, + { "help", helphelp, 0, 0, 1, help }, + { "idle", idlehelp, 0, 1, 1, idle }, + { "image", binaryhelp, 0, 1, 1, setbinary }, + { "lcd", lcdhelp, 0, 0, 0, lcd }, + { "ls", lshelp, 1, 1, 1, ls }, + { "macdef", macdefhelp, 0, 0, 0, macdef }, + { "mdelete", mdeletehelp, 1, 1, 1, mdelete }, + { "mdir", mdirhelp, 1, 1, 1, mls }, + { "mget", mgethelp, 1, 1, 1, mget }, + { "mkdir", mkdirhelp, 0, 1, 1, makedir }, + { "mls", mlshelp, 1, 1, 1, mls }, + { "mode", modehelp, 0, 1, 1, setmode }, + { "modtime", modtimehelp, 0, 1, 1, modtime }, + { "mput", mputhelp, 1, 1, 1, mput }, + { "newer", newerhelp, 1, 1, 1, newer }, + { "nmap", nmaphelp, 0, 0, 1, setnmap }, + { "nlist", nlisthelp, 1, 1, 1, ls }, + { "ntrans", ntranshelp, 0, 0, 1, setntrans }, + { "open", connecthelp, 0, 0, 1, setpeer }, + { "passive",passivehelp,0, 0, 0, setpassive }, + { "prompt", prompthelp, 0, 0, 0, setprompt }, + { "proxy", proxyhelp, 0, 0, 1, doproxy }, + { "sendport", porthelp, 0, 0, 0, setport }, + { "put", sendhelp, 1, 1, 1, put }, + { "pwd", pwdhelp, 0, 1, 1, pwd }, + { "quit", quithelp, 0, 0, 0, quit }, + { "quote", quotehelp, 1, 1, 1, quote }, + { "recv", receivehelp, 1, 1, 1, get }, + { "reget", regethelp, 1, 1, 1, reget }, + { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus }, + { "rhelp", remotehelp, 0, 1, 1, rmthelp }, + { "rename", renamehelp, 0, 1, 1, renamefile }, + { "reset", resethelp, 0, 1, 1, reset }, + { "restart", restarthelp, 1, 1, 1, restart }, + { "rmdir", rmdirhelp, 0, 1, 1, removedir }, + { "runique", runiquehelp, 0, 0, 1, setrunique }, + { "send", sendhelp, 1, 1, 1, put }, + { "site", sitehelp, 0, 1, 1, site }, + { "size", sizecmdhelp, 1, 1, 1, sizecmd }, + { "status", statushelp, 0, 0, 1, status }, + { "struct", structhelp, 0, 1, 1, setstruct }, + { "system", systemhelp, 0, 1, 1, syst }, + { "sunique", suniquehelp, 0, 0, 1, setsunique }, + { "tenex", tenexhelp, 0, 1, 1, settenex }, + { "trace", tracehelp, 0, 0, 0, settrace }, + { "type", typehelp, 0, 1, 1, settype }, + { "user", userhelp, 0, 1, 1, user }, + { "umask", umaskhelp, 0, 1, 1, do_umask }, + { "verbose", verbosehelp, 0, 0, 0, setverbose }, + { "?", helphelp, 0, 0, 1, help }, + { 0 }, +}; + +int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1; diff --git a/reactos/apps/utils/net/ftp/domacro.c b/reactos/apps/utils/net/ftp/domacro.c new file mode 100644 index 00000000000..a4eeed1914a --- /dev/null +++ b/reactos/apps/utils/net/ftp/domacro.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)domacro.c 1.6 (Berkeley) 2/28/89"; +#endif /* not lint */ + +#include "ftp_var.h" +#include "prototypes.h" + +#include +#include +//#include +#include +//#include + +void domacro(argc, argv) + int argc; + char *argv[]; +{ + register int i, j; + register char *cp1, *cp2; + int count = 2, loopflg = 0; + char line2[200]; + extern char **glob(), *globerr; + struct cmd *getcmd(), *c; + extern struct cmd cmdtab[]; + + if (argc < 2) { + (void) strcat(line, " "); + printf("(macro name) "); + (void) fflush(stdout); + (void) gets(&line[strlen(line)]); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + printf("Usage: %s macro_name.\n", argv[0]); + (void) fflush(stdout); + code = -1; + return; + } + for (i = 0; i < macnum; ++i) { + if (!strncmp(argv[1], macros[i].mac_name, 9)) { + break; + } + } + if (i == macnum) { + printf("'%s' macro not found.\n", argv[1]); + (void) fflush(stdout); + code = -1; + return; + } + (void) strcpy(line2, line); +TOP: + cp1 = macros[i].mac_start; + while (cp1 != macros[i].mac_end) { + while (isspace(*cp1)) { + cp1++; + } + cp2 = line; + while (*cp1 != '\0') { + switch(*cp1) { + case '\\': + *cp2++ = *++cp1; + break; + case '$': + if (isdigit(*(cp1+1))) { + j = 0; + while (isdigit(*++cp1)) { + j = 10*j + *cp1 - '0'; + } + cp1--; + if (argc - 2 >= j) { + (void) strcpy(cp2, argv[j+1]); + cp2 += strlen(argv[j+1]); + } + break; + } + if (*(cp1+1) == 'i') { + loopflg = 1; + cp1++; + if (count < argc) { + (void) strcpy(cp2, argv[count]); + cp2 += strlen(argv[count]); + } + break; + } + /* intentional drop through */ + default: + *cp2++ = *cp1; + break; + } + if (*cp1 != '\0') { + cp1++; + } + } + *cp2 = '\0'; + makeargv(); + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + code = -1; + } + else if (c == 0) { + printf("?Invalid command\n"); + code = -1; + } + else if (c->c_conn && !connected) { + printf("Not connected.\n"); + code = -1; + } + else { + if (verbose) { + printf("%s\n",line); + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) { + (void) putchar('\007'); + } + (void) strcpy(line, line2); + makeargv(); + argc = margc; + argv = margv; + } + if (cp1 != macros[i].mac_end) { + cp1++; + } + (void) fflush(stdout); + } + if (loopflg && ++count < argc) { + goto TOP; + } +} diff --git a/reactos/apps/utils/net/ftp/fake.c b/reactos/apps/utils/net/ftp/fake.c new file mode 100644 index 00000000000..24f549f25a3 --- /dev/null +++ b/reactos/apps/utils/net/ftp/fake.c @@ -0,0 +1,344 @@ +#include +#include +#include +#include "prototypes.h" + +#define MAX_ASCII 100 + +int checkRecv(SOCKET s); + +int checkRecv(SOCKET s) +{ + int testVal; + fd_set sSet; + struct timeval timeout; + timeout.tv_sec = 60; + + FD_ZERO(&sSet); + + FD_SET(s, &sSet); + + testVal = select(0, &sSet, NULL, NULL, &timeout); + + if (testVal == SOCKET_ERROR) + fprintf(stderr, "Socket Error"); + + return testVal; +} + +void blkfree(char **av0) +{ + register char **av = av0; + + while (*av) + free(*av++); +} + +char *glob(register char *v) +{ + return NULL; +} + + +int sleep(int time) +{ + return time; +} + +int herror(char *string) +{ + return 0; +} +#if 0 + +int gettimeofday(struct timeval *timenow, + struct timezone *zone) +{ + time_t t; + + t = clock(); + + timenow->tv_usec = t; + timenow->tv_sec = t / CLK_TCK; + + return 0; +} + +int fgetcSocket(int s) +{ + int c; + char buffer[10]; + +// checkRecv(s); + + c = recv(s, buffer, 1, 0); + +#ifdef DEBUG_IN + printf("%c", buffer[0]); +#endif + + if (c == INVALID_SOCKET) + return c; + + if (c == 0) + return EOF; + + return buffer[0]; +} + +#else + +int fgetcSocket(int s) +{ + static int index = 0; + static int total = 0; + static unsigned char buffer[4096]; + + if (index == total) + { + index = 0; + total = recv(s, buffer, sizeof(buffer), 0); + + if (total == INVALID_SOCKET) + { + total = 0; + return ERROR; + } + + if (total == 0) + return EOF; + } + return buffer[index++]; +} + +#endif + +char *fprintfSocket(int s, char *format, ...) +{ + va_list argptr; + char buffer[10009]; + + va_start(argptr, format); + vsprintf(buffer, format, argptr); + va_end(argptr); + + send(s, buffer, strlen(buffer), 0); + + return NULL; +} + +char *fputsSocket(char *format, int s) +{ + send(s, format, strlen(format), 0); + + return NULL; +} + +int fputcSocket(int s, char putChar) +{ + char buffer[2]; + + buffer[0] = putChar; + buffer[1] = '\0'; + + if(SOCKET_ERROR==send(s, buffer, 1, 0)) { + int iret=WSAGetLastError (); + fprintf(stdout,"fputcSocket: %d\n",iret); + return 0; + } + else { + return putChar; + } +} +int fputSocket(int s, char *buffer, int len) +{ + int iret; + while(len) { + if(SOCKET_ERROR==(iret=send(s, buffer, len, 0))) + { + iret=WSAGetLastError (); + fprintf(stdout,"fputcSocket: %d\n",iret); + return 0; + } + else { + return len-=iret; + } + } + return 0; +} + +char *fgetsSocket(int s, char *string) +{ + char buffer[2] = {0}; + int i, count; + + for (i = 0, count = 1; count != 0 && buffer[0] != '\n'; i++) + { + checkRecv(s); + + count = recv(s, buffer, 1, 0); + + if (count == SOCKET_ERROR) + { + printf("Error in fgetssocket"); + return NULL; + } + + if (count == 1) + { + string[i] = buffer[0]; + + if (i == MAX_ASCII - 3) + { + count = 0; + string[++i] = '\n'; + string[++i] = '\0'; + } + } + else + { + if (i == 0) + return NULL; + else + { + string[i] = '\n'; + string[i + 1] = '\0'; // This is risky + return string; + } + + } + + } + string[i] = '\0'; + +#ifdef DEBUG_IN + printf("%s", string); +#endif + return string; +} + + +#if 0 +char *getpass(const char *prompt) +{ + static char string[64]; + + printf("%s", prompt); + + gets(string); + + return string; +} +#endif +char *getpass (const char * prompt) +{ + static char input[256]; + HANDLE in; + HANDLE err; + int count; + + in = GetStdHandle (STD_INPUT_HANDLE); + err = GetStdHandle (STD_ERROR_HANDLE); + + if (in == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE) + return NULL; + + if (WriteFile (err, prompt, strlen (prompt), &count, NULL)) + { + int istty = (GetFileType (in) == FILE_TYPE_CHAR); + DWORD old_flags; + int rc; + + if (istty) + { + if (GetConsoleMode (in, &old_flags)) + SetConsoleMode (in, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); + else + istty = 0; + } + /* Need to read line one byte at time to avoid blocking, if not a + tty, so always do it this way. */ + count = 0; + while (1) + { + DWORD dummy; + char one_char; + + rc = ReadFile (in, &one_char, 1, &dummy, NULL); + if (rc == 0) + break; + if (one_char == '\r') + { + /* CR is always followed by LF if reading from tty. */ + if (istty) + continue; + else + break; + } + if (one_char == '\n') + break; + /* Silently truncate password string if overly long. */ + if (count < sizeof (input) - 1) + input[count++] = one_char; + } + input[count] = '\0'; + + WriteFile (err, "\r\n", 2, &count, NULL); + if (istty) + SetConsoleMode (in, old_flags); + if (rc) + return input; + } + + return NULL; +} + +// Stubbed out here. Should be changed in Source code... +int access(const char *filename, int accessmethod) +{ + return 0; +} + +#ifndef __GNUC__ +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + +struct timezone { + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +__inline int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + static int tzflag; + + if (tv) + { + GetSystemTimeAsFileTime(&ft); + //li.LowPart = ft.dwLowDateTime; + //li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + } + + if (tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} diff --git a/reactos/apps/utils/net/ftp/fake.h b/reactos/apps/utils/net/ftp/fake.h new file mode 100644 index 00000000000..816c7818064 --- /dev/null +++ b/reactos/apps/utils/net/ftp/fake.h @@ -0,0 +1,10 @@ +#define bcopy(s,d,l) memcpy((d),(s),(l)) +#define bzero(cp,l) memset((cp),0,(l)) + +#define rindex strrchr +#define index strchr + +#define getwd getcwd + +#define strcasecmp strcmp +#define strncasecmp strnicmp diff --git a/reactos/apps/utils/net/ftp/ftp.c b/reactos/apps/utils/net/ftp/ftp.c new file mode 100644 index 00000000000..34d443be6a5 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp.c @@ -0,0 +1,1805 @@ +#define L_SET SEEK_SET +#define L_INCR SEEK_CUR +#define caddr_t void * +/* + * Copyright (c) 1985, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ftp.c 5.28 (Berkeley) 4/20/89"; +#endif /* not lint */ +#include + +#include + +#if !defined(WIN32) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include "ftp_var.h" +#include "prototypes.h" +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#ifdef NOVFPRINTF +#define vfprintf(a,b,c) _doprnt(b,c,a) +#endif + +#ifdef sun +/* FD_SET wasn't defined until 4.0. its a cheap test for uid_t presence */ +#ifndef FD_SET +#define NBBY 8 /* number of bits in a byte */ +/* + * Select uses bit masks of file descriptors in longs. + * These macros manipulate such bit fields (the filesystem macros use chars). + * FD_SETSIZE may be defined by the user, but the default here + * should be >= NOFILE (param.h). + */ +#ifndef FD_SETSIZE +#define FD_SETSIZE 256 +#endif + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) + +typedef int uid_t; +typedef int gid_t; +#endif +#endif + +struct sockaddr_in hisctladdr; +struct sockaddr_in data_addr; +int data = -1; +int abrtflag = 0; +int ptflag = 0; +int allbinary; +struct sockaddr_in myctladdr; +uid_t getuid(); +sig_t lostpeer(); +off_t restart_point = 0; + +int cin, cout; +int dataconn(char *mode); + +int command(char *fmt, ...); + +char *hostname; + +typedef void (*Sig_t)(int); + +// Signal Handlers + +void psabort(int sig); + +char *hookup(char *host, int port) +{ + register struct hostent *hp = 0; + int s,len; + static char hostnamebuf[80]; + + bzero((char *)&hisctladdr, sizeof (hisctladdr)); + hisctladdr.sin_addr.s_addr = inet_addr(host); + if (hisctladdr.sin_addr.s_addr != -1) { + hisctladdr.sin_family = AF_INET; + (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + } else { + hp = gethostbyname(host); + if (hp == NULL) { + fprintf(stderr, "ftp: %s: ", host); + herror((char *)NULL); + code = -1; + return((char *) 0); + } + hisctladdr.sin_family = hp->h_addrtype; + bcopy(hp->h_addr_list[0], + (caddr_t)&hisctladdr.sin_addr, hp->h_length); + (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); + } + hostname = hostnamebuf; + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + perror("ftp: socket"); + code = -1; + return (0); + } + hisctladdr.sin_port = port; + while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { + if (hp && hp->h_addr_list[1]) { + int oerrno = errno; + + fprintf(stderr, "ftp: connect to address %s: ", + inet_ntoa(hisctladdr.sin_addr)); + errno = oerrno; + perror((char *) 0); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], + (caddr_t)&hisctladdr.sin_addr, hp->h_length); + fprintf(stdout, "Trying %s...\n", + inet_ntoa(hisctladdr.sin_addr)); + (void) fflush(stdout); + (void) close(s); + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + perror("ftp: socket"); + code = -1; + return (0); + } + continue; + } + perror("ftp: connect"); + code = -1; + goto bad; + } + len = sizeof (myctladdr); + if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { + perror("ftp: getsockname"); + code = -1; + goto bad; + } + cin = cout = s; + if (verbose) { + printf("Connected to %s.\n", hostname); + (void) fflush(stdout); + } + if (getreply(0) > 2) { /* read startup message from server */ + closesocket(cin); + code = -1; + goto bad; + } +#ifdef SO_OOBINLINE + { + int on = 1; + + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (const char *) &on, sizeof(on)) + < 0 && debug) { + perror("ftp: setsockopt"); + } + } +#endif //SO_OOBINLINE + + return (hostname); +bad: + (void) close(s); + return ((char *)0); +} + +int login(char *host) +{ + char tmp[80]; + char *user, *pass, *acct; + int n, aflag = 0; + + user = pass = acct = 0; + if (ruserpass(host, &user, &pass, &acct) < 0) { + code = -1; + return(0); + } + while (user == NULL) { + char *myname = "none"; // This needs to become the usename env + + if (myname) + printf("Name (%s:%s): ", host, myname); + else + printf("Name (%s): ", host); + (void) fflush(stdout); + (void) fgets(tmp, sizeof(tmp) - 1, stdin); + tmp[strlen(tmp) - 1] = '\0'; + if (*tmp == '\0') + user = myname; + else + user = tmp; + } + n = command("USER %s", user); + if (n == CONTINUE) { + if (pass == NULL) + pass = getpass("Password:"); + n = command("PASS %s", pass); + fflush(stdin); + } + if (n == CONTINUE) { + aflag++; + acct = getpass("Account:"); + n = command("ACCT %s", acct); + } + if (n != COMPLETE) { + fprintf(stderr, "Login failed.\n"); + return (0); + } + if (!aflag && acct != NULL) + (void) command("ACCT %s", acct); + if (proxy) + return(1); + for (n = 0; n < macnum; ++n) { + if (!strcmp("init", macros[n].mac_name)) { + (void) strcpy(line, "$init"); + makeargv(); + domacro(margc, margv); + break; + } + } + return (1); +} + +void +cmdabort(int sig) +{ + extern jmp_buf ptabort; + + printf("\n"); + (void) fflush(stdout); + abrtflag++; + if (ptflag) + longjmp(ptabort,1); +} + +/*VARARGS1*/ +int command(char *fmt, ...) +{ + va_list ap; + int r; + void (*oldintr)(int), cmdabort(int); + + abrtflag = 0; + if (debug) { + printf("---> "); + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); + printf("\n"); + (void) fflush(stdout); + } + if (cout == (int) NULL) { + perror ("No control connection for command"); + code = -1; + return (0); + } + oldintr = signal(SIGINT,cmdabort); + { + char buffer[1024]; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); +//DLJ: to work through firewalls - send the command as a single message + strcat(buffer,"\r\n"); + fprintfSocket(cout, buffer); + } +//DLJ: the following two lines are replaced by the strcat above - seems to +// make it work through firewalls. +// fprintfSocket(cout, "\r\n"); +// (void) fflush(cout); + cpend = 1; + r = getreply(!strcmp(fmt, "QUIT")); + if (abrtflag && oldintr != SIG_IGN) + (*oldintr)(SIGINT); +// (void) signal(SIGINT, oldintr); + return(r); +} + +char reply_string[BUFSIZ]; /* last line of previous reply */ + +#include + +getreply(expecteof) + int expecteof; +{ + register int c, n; + register int dig; + register char *cp; + int originalcode = 0, continuation = 0; + void (*oldintr)(int), cmdabort(int); + int pflag = 0; + char *pt = pasv; + + oldintr = signal(SIGINT,cmdabort); + for (;;) { + dig = n = code = 0; + cp = reply_string; + while ((c = fgetcSocket(cin)) != '\n') { + if (c == IAC) { /* handle telnet commands */ + switch (c = fgetcSocket(cin)) { + case WILL: + case WONT: + c = fgetcSocket(cin); + fprintfSocket(cout, "%c%c%c",IAC,DONT,c); + break; + case DO: + case DONT: + c = fgetcSocket(cin); + fprintfSocket(cout, "%c%c%c",IAC,WONT,c); + break; + default: + break; + } + continue; + } + dig++; + if (c == EOF) { + if (expecteof) { +// (void) signal(SIGINT,oldintr); + code = 221; + return (0); + } + lostpeer(); + if (verbose) { + printf("421 Service not available, remote server has closed connection\n"); + (void) fflush(stdout); + } + code = 421; + return(4); + } + if (c != '\r' && (verbose > 0 || + (verbose > -1 && n == '5' && dig > 4))) { + if (proxflag && + (dig == 1 || dig == 5 && verbose == 0)) + printf("%s:",hostname); + (void) putchar(c); + (void) fflush(stdout); + } + if (dig < 4 && isdigit(c)) + code = code * 10 + (c - '0'); + if (!pflag && code == 227) + pflag = 1; + if (dig > 4 && pflag == 1 && isdigit(c)) + pflag = 2; + if (pflag == 2) { + if (c != '\r' && c != ')') + *pt++ = c; + else { + *pt = '\0'; + pflag = 3; + } + } + if (dig == 4 && c == '-') { + if (continuation) + code = 0; + continuation++; + } + if (n == 0) + n = c; + if (cp < &reply_string[sizeof(reply_string) - 1]) + *cp++ = c; + } + if (verbose > 0 || verbose > -1 && n == '5') { + (void) putchar(c); + (void) fflush (stdout); + } + if (continuation && code != originalcode) { + if (originalcode == 0) + originalcode = code; + continue; + } + *cp = '\0'; + if (n != '1') + cpend = 0; + (void) signal(SIGINT,oldintr); + if (code == 421 || originalcode == 421) + lostpeer(); + if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) + (*oldintr)(SIGINT); + return (n - '0'); + } +} + +empty(mask, sec) + struct fd_set *mask; + int sec; +{ + struct timeval t; + + t.tv_sec = (long) sec; + t.tv_usec = 0; + return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); +} + +jmp_buf sendabort; + +void abortsend() +{ + + mflag = 0; + abrtflag = 0; + printf("\nsend aborted\n"); + (void) fflush(stdout); + longjmp(sendabort, 1); +} + +#define HASHBYTES 1024 + +void sendrequest(char *cmd, char *local, char *remote, int printnames) +{ + FILE *fin; + int dout = 0; + int (*closefunc)(), _pclose(), fclose(); + sig_t (*oldintr)(), (*oldintp)(); + void abortsend(); + char buf[BUFSIZ], *bufp; + long bytes = 0, hashbytes = HASHBYTES; + register int c, d; + struct stat st; + struct timeval start, stop; + char *mode; + + if (verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + (void) fflush(stdout); + } + if (proxy) { + proxtrans(cmd, local, remote); + return; + } + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + mode = "w"; + if (setjmp(sendabort)) { + while (cpend) { + (void) getreply(0); + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (oldintr) +null();// (void) signal(SIGINT,oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE,oldintp); + code = -1; + return; + } +null();// oldintr = signal(SIGINT, abortsend); + if (strcmp(local, "-") == 0) + fin = stdin; + else if (*local == '|') { +null();// oldintp = signal(SIGPIPE,SIG_IGN); + fin = _popen(local + 1, "r"); + if (fin == NULL) { + perror(local + 1); +null();// (void) signal(SIGINT, oldintr); +null();// (void) signal(SIGPIPE, oldintp); + code = -1; + return; + } + closefunc = _pclose; + } else { + fin = fopen(local, "r"); + if (fin == NULL) { + perror(local); +null();// (void) signal(SIGINT, oldintr); + code = -1; + return; + } + closefunc = fclose; + if (fstat(fileno(fin), &st) < 0 || + (st.st_mode&S_IFMT) != S_IFREG) { + fprintf(stdout, "%s: not a plain file.\n", local); + (void) fflush(stdout); +null();// (void) signal(SIGINT, oldintr); + fclose(fin); + code = -1; + return; + } + } + if (initconn()) { +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + code = -1; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (setjmp(sendabort)) + goto abort; + + if (restart_point && + (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + if (fseek(fin, (long) restart_point, 0) < 0) { + perror(local); + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (command("REST %ld", (long) restart_point) + != CONTINUE) { + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + restart_point = 0; + mode = "r+w"; + } + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + } else + if (command("%s", cmd) != PRELIM) { +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + dout = dataconn(mode); + if (dout == (int)NULL) + goto abort; + (void) gettimeofday(&start, (struct timezone *)0); +null();// oldintp = signal(SIGPIPE, SIG_IGN); + switch (type) { + + case TYPE_I: + case TYPE_L: + errno = d = 0; + while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { + bytes += c; + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = send(dout, bufp, c, 0)) <= 0) + break; + if (hash) { + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); + } + } + if (hash && bytes > 0) { + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (c < 0) + perror(local); + if (d <= 0) { + if (d == 0) + fprintf(stderr, "netout: write returned 0?\n"); + else if (errno != EPIPE) + perror("netout"); + bytes = -1; + } + break; + + case TYPE_A: + { + char buf[1024]; + static int bufsize = 1024; + int ipos=0; + + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + while (hash && (bytes >= hashbytes)) { + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; + } +// Szurgot: The following code is unncessary on Win32. +// (void) fputcSocket(dout, '\r'); +// bytes++; + } + + if (ipos >= bufsize) { + fputSocket(dout,buf,ipos); + if(!hash) (void) putchar('.'); + ipos=0; + } + buf[ipos]=c; ++ipos; + bytes++; + } + if (ipos) { + fputSocket(dout,buf,ipos); + ipos=0; + } + if (hash) { + if (bytes < hashbytes) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + else { + (void) putchar('.'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (ferror(fin)) + perror(local); +// if (ferror(dout)) { +// if (errno != EPIPE) +// perror("netout"); +// bytes = -1; +// } + break; + } + } + (void) gettimeofday(&stop, (struct timezone *)0); + if (closefunc != NULL) + (*closefunc)(fin); + if(closesocket(dout)) { + int iret=WSAGetLastError (); + fprintf(stdout,"Error closing socket(%d)\n",iret); + (void) fflush(stdout); + } + (void) getreply(0); +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); + return; +abort: + (void) gettimeofday(&stop, (struct timezone *)0); +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + if (!cpend) { + code = -1; + return; + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (dout) + if(closesocket(dout)) { + int iret=WSAGetLastError (); + fprintf(stdout,"Error closing socket(%d)\n",iret); + (void) fflush(stdout); + } + + (void) getreply(0); + code = -1; + if (closefunc != NULL && fin != NULL) + (*closefunc)(fin); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); +} + +jmp_buf recvabort; + + +void abortrecv() +{ + + mflag = 0; + abrtflag = 0; + printf("\n"); + (void) fflush(stdout); + longjmp(recvabort, 1); +} + +void recvrequest(char *cmd, char *local, char *remote, char *mode, + int printnames) +{ + FILE *fout; + int din = 0; + int (*closefunc)(), _pclose(), fclose(); + void (*oldintr)(int), (*oldintp)(int); + void abortrecv(); + int oldverbose, oldtype = 0, is_retr, tcrflag, nfnd, bare_lfs = 0; + char *gunique(), msg; +// static char *buf; // Szurgot: Shouldn't this go SOMEWHERE? + char buf[1024]; + static int bufsize = 1024; + long bytes = 0, hashbytes = HASHBYTES; +// struct + fd_set mask; + register int c, d; + struct timeval start, stop; +// struct stat st; + extern void *malloc(); + + is_retr = strcmp(cmd, "RETR") == 0; + if (is_retr && verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + (void) fflush(stdout); + } + if (proxy && is_retr) { + proxtrans(cmd, local, remote); + return; + } + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + tcrflag = !crflag && is_retr; + if (setjmp(recvabort)) { + while (cpend) { + (void) getreply(0); + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (oldintr) +null();// (void) signal(SIGINT, oldintr); + code = -1; + return; + } +null();// oldintr = signal(SIGINT, abortrecv); + if (strcmp(local, "-") && *local != '|') { +#ifndef __WIN32__ +// This whole thing is a problem... access Won't work on non-existent files + if (access(local, 2) < 0) { + char *dir = rindex(local, '/'); + + if (errno != ENOENT && errno != EACCES) { + perror(local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (dir != NULL) + *dir = 0; + d = access(dir ? local : ".", 2); + if (dir != NULL) + *dir = '/'; + if (d < 0) { + perror(local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (!runique && errno == EACCES && + chmod(local, 0600) < 0) { + perror(local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (runique && errno == EACCES && + (local = gunique(local)) == NULL) { + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + } + else if (runique && (local = gunique(local)) == NULL) { + (void) signal(SIGINT, oldintr); + code = -1; + return; + } +#endif + } + if (initconn()) { +null();// (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (setjmp(recvabort)) + goto abort; + if (!is_retr) { + if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) { + oldtype = type; + oldverbose = verbose; + if (!debug) + verbose = 0; + setascii(); + verbose = oldverbose; + } + } else if (restart_point) { + if (command("REST %ld", (long) restart_point) != CONTINUE) + return; + } + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { +null();// (void) signal(SIGINT, oldintr); + if (oldtype) { + if (!debug) + verbose = 0; + switch (oldtype) { + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + verbose = oldverbose; + } + return; + } + } else { + if (command("%s", cmd) != PRELIM) { +null();// (void) signal(SIGINT, oldintr); + if (oldtype) { + if (!debug) + verbose = 0; + switch (oldtype) { + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + verbose = oldverbose; + } + return; + } + } + din = dataconn("r"); + if (din == (int)NULL) + goto abort; + if (strcmp(local, "-") == 0) + fout = stdout; + else if (*local == '|') { +null();// oldintp = signal(SIGPIPE, SIG_IGN); + fout = _popen(local + 1, "w"); + if (fout == NULL) { + perror(local+1); + goto abort; + } + closefunc = _pclose; + } else { + fout = fopen(local, mode); + if (fout == NULL) { + perror(local); + goto abort; + } + closefunc = fclose; + } + (void) gettimeofday(&start, (struct timezone *)0); + switch (type) { + + case TYPE_I: + case TYPE_L: + if (restart_point && + lseek(fileno(fout), (long) restart_point, L_SET) < 0) { + perror(local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + errno = d = 0; +// while ((c = recv(din, buf, bufsize, 1)) > 0) { +// if ((d = write(fileno(fout), buf, c)) != c) +// if ((d = write(fileno(fout), buf, c)) != c) +// break; + while ((c = recv(din, buf, bufsize, 0)) > 0) { + write(fileno(fout), buf, c); + bytes += c; + if (hash) { + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); + } + } + if (hash && bytes > 0) { + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } +// if (c < 0) { +// if (errno != EPIPE) +// perror("netin"); +// bytes = -1; +// } +// if (d < c) { +// if (d < 0) +// perror(local); +// else +// fprintf(stderr, "%s: short write\n", local); +// } + break; + + case TYPE_A: + if (restart_point) { + register int i, n, c; + + if (fseek(fout, 0L, L_SET) < 0) + goto done; + n = restart_point; + i = 0; + while (i++ < n) { + if ((c=getc(fout)) == EOF) + goto done; + if (c == '\n') + i++; + } + if (fseek(fout, 0L, L_INCR) < 0) { +done: + perror(local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + } + while ((c = fgetcSocket(din)) != EOF) { + if (c == '\n') + bare_lfs++; + while (c == '\r') { + while (hash && (bytes >= hashbytes)) { + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; + } + bytes++; + if ((c = fgetcSocket(din)) != '\n' || tcrflag) { + if (ferror(fout)) + goto break2; + (void) putc('\r', fout); + if (c == '\0') { + bytes++; + goto contin2; + } + if (c == EOF) + goto contin2; + } + } + (void) putc(c, fout); + bytes++; + contin2: ; + } +break2: + if (bare_lfs) { + printf("WARNING! %d bare linefeeds received in ASCII mode\n"); + printf("File may not have transferred correctly.\n"); + (void) fflush(stdout); + } + if (hash) { + if (bytes < hashbytes) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } +// if (ferror(din)) { +// if (errno != EPIPE) +// perror("netin"); +// bytes = -1; +// } + if (ferror(fout)) + perror(local); + break; + } + if (closefunc != NULL) + (*closefunc)(fout); +null();// (void) signal(SIGINT, oldintr); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintp); + (void) gettimeofday(&stop, (struct timezone *)0); + if(closesocket(din)) { + int iret=WSAGetLastError (); + fprintf(stdout,"Error closing socket(%d)\n",iret); + (void) fflush(stdout); + } + + (void) getreply(0); + if (bytes > 0 && is_retr) + ptransfer("received", bytes, &start, &stop); + if (oldtype) { + if (!debug) + verbose = 0; + switch (oldtype) { + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + verbose = oldverbose; + } + return; +abort: + +/* abort using RFC959 recommended IP,SYNC sequence */ + + (void) gettimeofday(&stop, (struct timezone *)0); + if (oldintp) +null();// (void) signal(SIGPIPE, oldintr); +null();// (void) signal(SIGINT,SIG_IGN); + if (oldtype) { + if (!debug) + verbose = 0; + switch (oldtype) { + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + verbose = oldverbose; + } + if (!cpend) { + code = -1; +null();// (void) signal(SIGINT,oldintr); + return; + } + + fprintfSocket(cout,"%c%c",IAC,IP); + msg = (char)IAC; +/* send IAC in urgent mode instead of DM because UNIX places oob mark */ +/* after urgent byte rather than before as now is protocol */ + if (send(cout,&msg,1,MSG_OOB) != 1) { + perror("abort"); + } + fprintfSocket(cout,"%cABOR\r\n",DM); + FD_ZERO(&mask); + FD_SET(cin, &mask); // Need to correct this + if (din) { + FD_SET(din, &mask); // Need to correct this + } + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + code = -1; + lostpeer(); + } + if (din && FD_ISSET(din, &mask)) { + while ((c = recv(din, buf, bufsize, 0)) > 0) + ; + } + if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ + if (data >= 0) { + (void) close(data); + data = -1; + } + (void) getreply(0); + } + (void) getreply(0); + code = -1; + if (data >= 0) { + (void) close(data); + data = -1; + } + if (closefunc != NULL && fout != NULL) + (*closefunc)(fout); + if (din) + if(closesocket(din)) { + int iret=WSAGetLastError (); + fprintf(stdout,"Error closing socket(%d)\n",iret); + (void) fflush(stdout); + } + + if (bytes > 0) + ptransfer("received", bytes, &start, &stop); +null();// (void) signal(SIGINT,oldintr); +} + +/* + * Need to start a listen on the data channel + * before we send the command, otherwise the + * server's connect may fail. + */ +int sendport = -1; + +initconn() +{ + register char *p, *a; + int result, len, tmpno = 0; + int on = 1; + int a0, a1, a2, a3, p0, p1; + + + if (passivemode) { + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + perror("ftp: socket"); + return(1); + } + if ((options & SO_DEBUG) && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, + sizeof (on)) < 0) + perror("ftp: setsockopt (ignored)"); + if (command("PASV") != COMPLETE) { + printf("Passive mode refused.\n"); + goto bad; + } + + /* + * What we've got at this point is a string of comma + * separated one-byte unsigned integer values. + * The first four are the an IP address. The fifth is + * the MSB of the port number, the sixth is the LSB. + * From that we'll prepare a sockaddr_in. + */ + + if (sscanf(pasv,"%d,%d,%d,%d,%d,%d", + &a0, &a1, &a2, &a3, &p0, &p1) != 6) { + printf("Passive mode address scan failure. Shouldn't happen!\n"); + goto bad; + } + + bzero(&data_addr, sizeof(data_addr)); + data_addr.sin_family = AF_INET; + a = (char *)&data_addr.sin_addr.s_addr; + a[0] = a0 & 0xff; + a[1] = a1 & 0xff; + a[2] = a2 & 0xff; + a[3] = a3 & 0xff; + p = (char *)&data_addr.sin_port; + p[0] = p0 & 0xff; + p[1] = p1 & 0xff; + + if (connect(data, (struct sockaddr *)&data_addr, + sizeof(data_addr)) < 0) { + perror("ftp: connect"); + goto bad; + } + return(0); + } + + +noport: + data_addr = myctladdr; + if (sendport) + data_addr.sin_port = 0; /* let system pick one */ + if (data != -1) + (void) close (data); + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + perror("ftp: socket"); + if (tmpno) + sendport = 1; + return (1); + } + if (!sendport) + if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { + perror("ftp: setsockopt (reuse address)"); + goto bad; + } + if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { + perror("ftp: bind"); + goto bad; + } + if (options & SO_DEBUG && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) + perror("ftp: setsockopt (ignored)"); + len = sizeof (data_addr); + if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { + perror("ftp: getsockname"); + goto bad; + } + if (listen(data, 1) < 0) + perror("ftp: listen"); + if (sendport) { + a = (char *)&data_addr.sin_addr; + p = (char *)&data_addr.sin_port; +#define UC(b) (((int)b)&0xff) + result = + command("PORT %d,%d,%d,%d,%d,%d", + UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), + UC(p[0]), UC(p[1])); + if (result == ERROR && sendport == -1) { + sendport = 0; + tmpno = 1; + goto noport; + } + return (result != COMPLETE); + } + if (tmpno) + sendport = 1; + return (0); +bad: + (void) fflush(stdout); + (void) close(data), data = -1; + if (tmpno) + sendport = 1; + return (1); +} + +int dataconn(char *mode) +{ + struct sockaddr_in from; + int s, fromlen = sizeof (from); + + if (passivemode) + return (data); + + s = accept(data, (struct sockaddr *) &from, &fromlen); + if (s < 0) { + perror("ftp: accept"); + (void) closesocket(data), data = -1; + return (int) (NULL); + } + if(closesocket(data)) { + int iret=WSAGetLastError (); + fprintf(stdout,"Error closing socket(%d)\n",iret); + (void) fflush(stdout); + } + + data = s; + return (data); +} + +void ptransfer(direction, bytes, t0, t1) + char *direction; + long bytes; + struct timeval *t0, *t1; +{ + struct timeval td; + double s, bs; + + if (verbose) { + tvsub(&td, t1, t0); + s = td.tv_sec + (td.tv_usec / 1000000.); +#define nz(x) ((x) == 0 ? 1 : (x)) + bs = bytes / nz(s); + printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", + bytes, direction, s, bs / 1024.); + (void) fflush(stdout); + } +} + +/*tvadd(tsum, t0) + struct timeval *tsum, *t0; +{ + + tsum->tv_sec += t0->tv_sec; + tsum->tv_usec += t0->tv_usec; + if (tsum->tv_usec > 1000000) + tsum->tv_sec++, tsum->tv_usec -= 1000000; +} */ + +void tvsub(tdiff, t1, t0) + struct timeval *tdiff, *t1, *t0; +{ + + tdiff->tv_sec = t1->tv_sec - t0->tv_sec; + tdiff->tv_usec = t1->tv_usec - t0->tv_usec; + if (tdiff->tv_usec < 0) + tdiff->tv_sec--, tdiff->tv_usec += 1000000; +} + +void psabort(int flag) +{ + extern int abrtflag; + + abrtflag++; +} + +void pswitch(int flag) +{ + extern int proxy, abrtflag; + Sig_t oldintr; + static struct comvars { + int connect; + char name[MAXHOSTNAMELEN]; + struct sockaddr_in mctl; + struct sockaddr_in hctl; + FILE *in; + FILE *out; + int tpe; + int cpnd; + int sunqe; + int runqe; + int mcse; + int ntflg; + char nti[17]; + char nto[17]; + int mapflg; + char mi[MAXPATHLEN]; + char mo[MAXPATHLEN]; + } proxstruct, tmpstruct; + struct comvars *ip, *op; + + abrtflag = 0; + oldintr = signal(SIGINT, psabort); + if (flag) { + if (proxy) + return; + ip = &tmpstruct; + op = &proxstruct; + proxy++; + } + else { + if (!proxy) + return; + ip = &proxstruct; + op = &tmpstruct; + proxy = 0; + } + ip->connect = connected; + connected = op->connect; + if (hostname) { + (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); + ip->name[strlen(ip->name)] = '\0'; + } else + ip->name[0] = 0; + hostname = op->name; + ip->hctl = hisctladdr; + hisctladdr = op->hctl; + ip->mctl = myctladdr; + myctladdr = op->mctl; + (int) ip->in = cin; // What the hell am I looking at...? + cin = (int) op->in; + (int) ip->out = cout; // Same again... + cout = (int) op->out; + ip->tpe = type; + type = op->tpe; + if (!type) + type = 1; + ip->cpnd = cpend; + cpend = op->cpnd; + ip->sunqe = sunique; + sunique = op->sunqe; + ip->runqe = runique; + runique = op->runqe; + ip->mcse = mcase; + mcase = op->mcse; + ip->ntflg = ntflag; + ntflag = op->ntflg; + (void) strncpy(ip->nti, ntin, 16); + (ip->nti)[strlen(ip->nti)] = '\0'; + (void) strcpy(ntin, op->nti); + (void) strncpy(ip->nto, ntout, 16); + (ip->nto)[strlen(ip->nto)] = '\0'; + (void) strcpy(ntout, op->nto); + ip->mapflg = mapflag; + mapflag = op->mapflg; + (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); + (ip->mi)[strlen(ip->mi)] = '\0'; + (void) strcpy(mapin, op->mi); + (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); + (ip->mo)[strlen(ip->mo)] = '\0'; + (void) strcpy(mapout, op->mo); +// (void) signal(SIGINT, oldintr); + if (abrtflag) { + abrtflag = 0; + (*oldintr)(1); + } +} + +jmp_buf ptabort; +int ptabflg; + +void +abortpt() +{ + printf("\n"); + (void) fflush(stdout); + ptabflg++; + mflag = 0; + abrtflag = 0; + longjmp(ptabort, 1); +} + +void proxtrans(cmd, local, remote) + char *cmd, *local, *remote; +{ +// void (*oldintr)(int); + //void abortpt(int); + int tmptype, oldtype = 0, secndflag = 0, nfnd; + extern jmp_buf ptabort; + char *cmd2; +// struct + fd_set mask; + + if (strcmp(cmd, "RETR")) + cmd2 = "RETR"; + else + cmd2 = runique ? "STOU" : "STOR"; + if (command("PASV") != COMPLETE) { + printf("proxy server does not support third part transfers.\n"); + (void) fflush(stdout); + return; + } + tmptype = type; + pswitch(0); + if (!connected) { + printf("No primary connection\n"); + (void) fflush(stdout); + pswitch(1); + code = -1; + return; + } + if (type != tmptype) { + oldtype = type; + switch (tmptype) { + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + } + if (command("PORT %s", pasv) != COMPLETE) { + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + pswitch(1); + return; + } + if (setjmp(ptabort)) + goto abort; +null();// oldintr = signal(SIGINT, abortpt); + if (command("%s %s", cmd, remote) != PRELIM) { +null();// (void) signal(SIGINT, oldintr); + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + pswitch(1); + return; + } + sleep(2); + pswitch(1); + secndflag++; + if (command("%s %s", cmd2, local) != PRELIM) + goto abort; + ptflag++; + (void) getreply(0); + pswitch(0); + (void) getreply(0); +null();// (void) signal(SIGINT, oldintr); + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + pswitch(1); + ptflag = 0; + printf("local: %s remote: %s\n", local, remote); + (void) fflush(stdout); + return; +abort: +null();// (void) signal(SIGINT, SIG_IGN); + ptflag = 0; + if (strcmp(cmd, "RETR") && !proxy) + pswitch(1); + else if (!strcmp(cmd, "RETR") && proxy) + pswitch(0); + if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + if (cpend) { + char msg[2]; + + fprintfSocket(cout,"%c%c",IAC,IP); + *msg = (char) IAC; + *(msg+1) = (char) DM; + if (send(cout,msg,2,MSG_OOB) != 2) + perror("abort"); + fprintfSocket(cout,"ABOR\r\n"); + FD_ZERO(&mask); +// FD_SET(fileno(cin), &mask); // Chris: Need to correct this + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + } + pswitch(1); + if (ptabflg) + code = -1; +null();// (void) signal(SIGINT, oldintr); + return; + } + if (cpend) { + char msg[2]; + + fprintfSocket(cout,"%c%c",IAC,IP); + *msg = (char)IAC; + *(msg+1) = (char)DM; + if (send(cout,msg,2,MSG_OOB) != 2) + perror("abort"); + fprintfSocket(cout,"ABOR\r\n"); + FD_ZERO(&mask); +// FD_SET(fileno(cin), &mask); // Chris: Need to correct this... + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + pswitch(!proxy); + if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + if (cpend) { + char msg[2]; + + fprintfSocket(cout,"%c%c",IAC,IP); + *msg = (char)IAC; + *(msg+1) = (char)DM; + if (send(cout,msg,2,MSG_OOB) != 2) + perror("abort"); + fprintfSocket(cout,"ABOR\r\n"); + FD_ZERO(&mask); +// FD_SET(fileno(cin), &mask); // Chris: + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + pswitch(1); + if (ptabflg) + code = -1; +null();// (void) signal(SIGINT, oldintr); + return; + } + } + if (cpend) { + char msg[2]; + + fprintfSocket(cout,"%c%c",IAC,IP); + *msg = (char)IAC; + *(msg+1) = (char)DM; + if (send(cout,msg,2,MSG_OOB) != 2) + perror("abort"); + fprintfSocket(cout,"ABOR\r\n"); + FD_ZERO(&mask); +// FD_SET(fileno(cin), &mask); // Chris: + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + pswitch(!proxy); + if (cpend) { + FD_ZERO(&mask); +// FD_SET(fileno(cin), &mask); // Chris: + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + if (proxy) + pswitch(0); + switch (oldtype) { + case 0: + break; + case TYPE_A: + setascii(); + break; + case TYPE_I: + setbinary(); + break; + case TYPE_E: + setebcdic(); + break; + case TYPE_L: + settenex(); + break; + } + pswitch(1); + if (ptabflg) + code = -1; +null();// (void) signal(SIGINT, oldintr); +} + +void reset() +{ +// struct + fd_set mask; + int nfnd = 1; + + FD_ZERO(&mask); + while (nfnd > 0) { +// FD_SET(fileno(cin), &mask); // Chris + if ((nfnd = empty(&mask,0)) < 0) { + perror("reset"); + code = -1; + lostpeer(); + } + else if (nfnd) { + (void) getreply(0); + } + } +} + +char * +gunique(local) + char *local; +{ + static char new[MAXPATHLEN]; + char *cp = rindex(local, '/'); + int d, count=0; + char ext = '1'; + + if (cp) + *cp = '\0'; + d = access(cp ? local : ".", 2); + if (cp) + *cp = '/'; + if (d < 0) { + perror(local); + return((char *) 0); + } + (void) strcpy(new, local); + cp = new + strlen(new); + *cp++ = '.'; + while (!d) { + if (++count == 100) { + printf("runique: can't find unique file name.\n"); + (void) fflush(stdout); + return((char *) 0); + } + *cp++ = ext; + *cp = '\0'; + if (ext == '9') + ext = '0'; + else + ext++; + if ((d = access(new, 0)) < 0) + break; + if (ext != '0') + cp--; + else if (*(cp - 2) == '.') + *(cp - 1) = '1'; + else { + *(cp - 2) = *(cp - 2) + 1; + cp--; + } + } + return(new); +} + +int null(void) +{ + return 0; +} diff --git a/reactos/apps/utils/net/ftp/ftp.mak b/reactos/apps/utils/net/ftp/ftp.mak new file mode 100644 index 00000000000..084404f1927 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp.mak @@ -0,0 +1,372 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ftp.dsp +!IF "$(CFG)" == "" +CFG=ftp - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ftp - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ftp - Win32 Release" && "$(CFG)" != "ftp - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ftp.mak" CFG="ftp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ftp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ftp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "ftp - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ftp.exe" + +!ELSE + +ALL : "$(OUTDIR)\ftp.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\cmds.obj" + -@erase "$(INTDIR)\cmdtab.obj" + -@erase "$(INTDIR)\domacro.obj" + -@erase "$(INTDIR)\fake.obj" + -@erase "$(INTDIR)\ftp.obj" + -@erase "$(INTDIR)\main.obj" + -@erase "$(INTDIR)\ruserpass.obj" + -@erase "$(INTDIR)\vc*.idb" + -@erase "$(OUTDIR)\ftp.exe" + -@erase "$(OUTDIR)\ftp.pch" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" \ + /D "HAVE_TIMEVAL" /Fp"$(INTDIR)\ftp.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Release/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ftp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib wsock32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)\ftp.pdb" /machine:I386 /out:"$(OUTDIR)\ftp.exe" +LINK32_OBJS= \ + "$(INTDIR)\cmds.obj" \ + "$(INTDIR)\cmdtab.obj" \ + "$(INTDIR)\domacro.obj" \ + "$(INTDIR)\fake.obj" \ + "$(INTDIR)\ftp.obj" \ + "$(INTDIR)\main.obj" \ + "$(INTDIR)\ruserpass.obj" + +"$(OUTDIR)\ftp.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\ftp.exe +InputPath=.\Release\ftp.exe +SOURCE=$(InputPath) + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ftp.exe" + +!ELSE + +ALL : "$(OUTDIR)\ftp.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\cmds.obj" + -@erase "$(INTDIR)\cmdtab.obj" + -@erase "$(INTDIR)\domacro.obj" + -@erase "$(INTDIR)\fake.obj" + -@erase "$(INTDIR)\ftp.obj" + -@erase "$(INTDIR)\main.obj" + -@erase "$(INTDIR)\ruserpass.obj" + -@erase "$(INTDIR)\vc*.idb" + -@erase "$(INTDIR)\vc*.pdb" + -@erase "$(OUTDIR)\ftp.exe" + -@erase "$(OUTDIR)\ftp.ilk" + -@erase "$(OUTDIR)\ftp.pdb" + -@erase "$(OUTDIR)\ftp.pch" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS"\ + /Fp"$(INTDIR)\ftp.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ftp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib wsock32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)\ftp.pdb" /debug /machine:I386 /out:"$(OUTDIR)\ftp.exe"\ + /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\cmds.obj" \ + "$(INTDIR)\cmdtab.obj" \ + "$(INTDIR)\domacro.obj" \ + "$(INTDIR)\fake.obj" \ + "$(INTDIR)\ftp.obj" \ + "$(INTDIR)\main.obj" \ + "$(INTDIR)\ruserpass.obj" + +"$(OUTDIR)\ftp.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\ftp.exe +InputPath=.\Debug\ftp.exe +SOURCE=$(InputPath) + +!ENDIF + + +!IF "$(CFG)" == "ftp - Win32 Release" || "$(CFG)" == "ftp - Win32 Debug" +SOURCE=.\cmds.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_CMDS_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\pathnames.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\cmds.obj" : $(SOURCE) $(DEP_CPP_CMDS_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_CMDS_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\pathnames.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\cmds.obj" : $(SOURCE) $(DEP_CPP_CMDS_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\cmdtab.c +DEP_CPP_CMDTA=\ + ".\fake.h"\ + ".\ftp_var.h"\ + + +"$(INTDIR)\cmdtab.obj" : $(SOURCE) $(DEP_CPP_CMDTA) "$(INTDIR)" + + +SOURCE=.\domacro.c +DEP_CPP_DOMAC=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\domacro.obj" : $(SOURCE) $(DEP_CPP_DOMAC) "$(INTDIR)" + + +SOURCE=.\fake.c +DEP_CPP_FAKE_=\ + ".\prototypes.h"\ + + +"$(INTDIR)\fake.obj" : $(SOURCE) $(DEP_CPP_FAKE_) "$(INTDIR)" + + +SOURCE=.\ftp.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_FTP_C=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\ftp.obj" : $(SOURCE) $(DEP_CPP_FTP_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_FTP_C=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\ftp.obj" : $(SOURCE) $(DEP_CPP_FTP_C) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\main.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_MAIN_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_MAIN_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ruserpass.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_RUSER=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\ruserpass.obj" : $(SOURCE) $(DEP_CPP_RUSER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_RUSER=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\ruserpass.obj" : $(SOURCE) $(DEP_CPP_RUSER) "$(INTDIR)" + + +!ENDIF + + +!ENDIF diff --git a/reactos/apps/utils/net/ftp/ftp.mak.orig b/reactos/apps/utils/net/ftp/ftp.mak.orig new file mode 100644 index 00000000000..b482649d551 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp.mak.orig @@ -0,0 +1,400 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ftp.dsp +!IF "$(CFG)" == "" +CFG=ftp - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ftp - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ftp - Win32 Release" && "$(CFG)" != "ftp - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ftp.mak" CFG="ftp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ftp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ftp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "ftp - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ftp.exe" "\emacs-19.34\bin\ftp.exe" + +!ELSE + +ALL : "$(OUTDIR)\ftp.exe" "\emacs-19.34\bin\ftp.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\cmds.obj" + -@erase "$(INTDIR)\cmdtab.obj" + -@erase "$(INTDIR)\domacro.obj" + -@erase "$(INTDIR)\fake.obj" + -@erase "$(INTDIR)\ftp.obj" + -@erase "$(INTDIR)\main.obj" + -@erase "$(INTDIR)\ruserpass.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ftp.exe" + -@erase "\emacs-19.34\bin\ftp.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "C:\emacs-19.34\nt\inc" /I\ + "C:\emacs-19.34\src" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D\ + "HAVE_TIMEVAL" /Fp"$(INTDIR)\ftp.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Release/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ftp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)\ftp.pdb" /machine:I386 /out:"$(OUTDIR)\ftp.exe" +LINK32_OBJS= \ + "$(INTDIR)\cmds.obj" \ + "$(INTDIR)\cmdtab.obj" \ + "$(INTDIR)\domacro.obj" \ + "$(INTDIR)\fake.obj" \ + "$(INTDIR)\ftp.obj" \ + "$(INTDIR)\main.obj" \ + "$(INTDIR)\ruserpass.obj" \ + "d:\Program Files\DevStudio\VC\lib\WSOCK32.LIB" + +"$(OUTDIR)\ftp.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\ftp.exe +InputPath=.\Release\ftp.exe +SOURCE=$(InputPath) + +"\emacs-19.34\bin\ftp.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" +# copy $(TargetPath) \emacs-19.34\bin + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ftp.exe" "\emacs-19.34\bin\ftp.exe" + +!ELSE + +ALL : "$(OUTDIR)\ftp.exe" "\emacs-19.34\bin\ftp.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\cmds.obj" + -@erase "$(INTDIR)\cmdtab.obj" + -@erase "$(INTDIR)\domacro.obj" + -@erase "$(INTDIR)\fake.obj" + -@erase "$(INTDIR)\ftp.obj" + -@erase "$(INTDIR)\main.obj" + -@erase "$(INTDIR)\ruserpass.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ftp.exe" + -@erase "$(OUTDIR)\ftp.ilk" + -@erase "$(OUTDIR)\ftp.pdb" + -@erase "\emacs-19.34\bin\ftp.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "C:\emacs-19.34\nt\inc" /I\ + "C:\emacs-19.34\src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS"\ + /Fp"$(INTDIR)\ftp.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ftp.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)\ftp.pdb" /debug /machine:I386 /out:"$(OUTDIR)\ftp.exe"\ + /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\cmds.obj" \ + "$(INTDIR)\cmdtab.obj" \ + "$(INTDIR)\domacro.obj" \ + "$(INTDIR)\fake.obj" \ + "$(INTDIR)\ftp.obj" \ + "$(INTDIR)\main.obj" \ + "$(INTDIR)\ruserpass.obj" \ + "d:\Program Files\DevStudio\VC\lib\WSOCK32.LIB" + +"$(OUTDIR)\ftp.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\ftp.exe +InputPath=.\Debug\ftp.exe +SOURCE=$(InputPath) + +"\emacs-19.34\bin\ftp.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" +# copy $(TargetPath) \emacs-19.34\bin + +!ENDIF + + +!IF "$(CFG)" == "ftp - Win32 Release" || "$(CFG)" == "ftp - Win32 Debug" +SOURCE=.\cmds.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_CMDS_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\pathnames.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\cmds.obj" : $(SOURCE) $(DEP_CPP_CMDS_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_CMDS_=\ + "..\..\..\emacs-19.34\nt\inc\netdb.h"\ + "..\..\..\emacs-19.34\nt\inc\netinet\in.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\socket.h"\ + "..\..\..\emacs-19.34\src\nt.h"\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\pathnames.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\cmds.obj" : $(SOURCE) $(DEP_CPP_CMDS_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\cmdtab.c +DEP_CPP_CMDTA=\ + ".\fake.h"\ + ".\ftp_var.h"\ + + +"$(INTDIR)\cmdtab.obj" : $(SOURCE) $(DEP_CPP_CMDTA) "$(INTDIR)" + + +SOURCE=.\domacro.c +DEP_CPP_DOMAC=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\domacro.obj" : $(SOURCE) $(DEP_CPP_DOMAC) "$(INTDIR)" + + +SOURCE=.\fake.c +DEP_CPP_FAKE_=\ + ".\prototypes.h"\ + + +"$(INTDIR)\fake.obj" : $(SOURCE) $(DEP_CPP_FAKE_) "$(INTDIR)" + + +SOURCE=.\ftp.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_FTP_C=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\ftp.obj" : $(SOURCE) $(DEP_CPP_FTP_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_FTP_C=\ + "..\..\..\emacs-19.34\nt\inc\netdb.h"\ + "..\..\..\emacs-19.34\nt\inc\netinet\in.h"\ + "..\..\..\emacs-19.34\nt\inc\pwd.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\file.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\ioctl.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\param.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\socket.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\time.h"\ + "..\..\..\emacs-19.34\src\nt.h"\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\ftp.obj" : $(SOURCE) $(DEP_CPP_FTP_C) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\main.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_MAIN_=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_MAIN_=\ + "..\..\..\emacs-19.34\nt\inc\netdb.h"\ + "..\..\..\emacs-19.34\nt\inc\pwd.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\ioctl.h"\ + "..\..\..\emacs-19.34\nt\inc\sys\socket.h"\ + "..\..\..\emacs-19.34\src\nt.h"\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\main.obj" : $(SOURCE) $(DEP_CPP_MAIN_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ruserpass.c + +!IF "$(CFG)" == "ftp - Win32 Release" + +DEP_CPP_RUSER=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + + +"$(INTDIR)\ruserpass.obj" : $(SOURCE) $(DEP_CPP_RUSER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ftp - Win32 Debug" + +DEP_CPP_RUSER=\ + ".\fake.h"\ + ".\ftp_var.h"\ + ".\prototypes.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + + +"$(INTDIR)\ruserpass.obj" : $(SOURCE) $(DEP_CPP_RUSER) "$(INTDIR)" + + +!ENDIF + + +!ENDIF diff --git a/reactos/apps/utils/net/ftp/ftp.rc b/reactos/apps/utils/net/ftp/ftp.rc new file mode 100644 index 00000000000..505a9fe9d25 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp.rc @@ -0,0 +1,6 @@ +/* $Id: route.rc 11816 2004-11-26 06:51:47Z arty $ */ + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 FTP Client\0" +#define REACTOS_STR_INTERNAL_NAME "ftp\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ftp.exe\0" +#include diff --git a/reactos/apps/utils/net/ftp/ftp.xml b/reactos/apps/utils/net/ftp/ftp.xml new file mode 100644 index 00000000000..c5a07d34a64 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp.xml @@ -0,0 +1,15 @@ + + . + + kernel32 + ws2_32 + iphlpapi + cmds.c + cmdtab.c + domacro.c + fake.c + ftp.c + main.c + ruserpass.c + ftp.rc + diff --git a/reactos/apps/utils/net/ftp/ftp_var.h b/reactos/apps/utils/net/ftp/ftp_var.h new file mode 100644 index 00000000000..7c33434a7e7 --- /dev/null +++ b/reactos/apps/utils/net/ftp/ftp_var.h @@ -0,0 +1,181 @@ +#include "fake.h" +#include +#include + +//typedef void (*Sig_t)(int); + +int fgetcSocket(int s); +char *fputsSocket(char *format, int s); + +char *fprintfSocket(int s, char *format, ...); + +int fputcSocket(int s, char putChar); +int fputSocket(int s, char *putChar, int len); +char *fgetsSocket(int s, char *string); + +/* The following defines are from ftp.h and telnet.h from bsd.h */ +/* All relevent copyrights below apply. */ + +#define IAC 255 +#define DONT 254 +#define DO 253 +#define WONT 252 +#define WILL 251 +#define SB 250 +#define GA 249 +#define EL 248 +#define EC 247 +#define AYT 246 +#define AO 245 +#define IP 244 +#define BREAK 243 +#define DM 242 +#define NOP 241 +#define SE 240 +#define EOR 239 +#define ABORT 238 +#define SUSP 237 +#define xEOF 236 + + +#define MAXPATHLEN 255 +#define TYPE_A 'A' +#define TYPE_I 'I' +#define TYPE_E 'E' +#define TYPE_L 'L' + +#define PRELIM 1 +#define COMPLETE 2 +#define CONTINUE 3 +#define TRANSIENT 4 + +#define MODE_S 1 +#define MODE_B 2 +#define MODE_C 3 + +#define STRU_F 1 +#define STRU_R 2 +#define STRU_P 3 + +#define SIGQUIT 1 +#define SIGPIPE 2 +#define SIGALRM 3 + + +#define FORM_N 1 +#define FORM_T 2 +#define FORM_C 3 + + +/* + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)ftp_var.h 5.5 (Berkeley) 6/29/88 + */ + +/* + * FTP global variables. + */ + +/* + * Options and other state info. + */ +extern int trace; /* trace packets exchanged */ +extern int hash; /* print # for each buffer transferred */ +extern int sendport; /* use PORT cmd for each data connection */ +extern int verbose; /* print messages coming back from server */ +extern int connected; /* connected to server */ +extern int fromatty; /* input is from a terminal */ +extern int interactive; /* interactively prompt on m* cmds */ +extern int debug; /* debugging level */ +extern int bell; /* ring bell on cmd completion */ +extern int doglob; /* glob local file names */ +extern int proxy; /* proxy server connection active */ +extern int proxflag; /* proxy connection exists */ +extern int sunique; /* store files on server with unique name */ +extern int runique; /* store local files with unique name */ +extern int mcase; /* map upper to lower case for mget names */ +extern int ntflag; /* use ntin ntout tables for name translation */ +extern int mapflag; /* use mapin mapout templates on file names */ +extern int code; /* return/reply code for ftp command */ +extern int crflag; /* if 1, strip car. rets. on ascii gets */ +extern char pasv[64]; /* passive port for proxy data connection */ +extern int passivemode; /* passive mode enabled */ +extern char *altarg; /* argv[1] with no shell-like preprocessing */ +extern char ntin[17]; /* input translation table */ +extern char ntout[17]; /* output translation table */ + +extern char mapin[MAXPATHLEN]; /* input map template */ +extern char mapout[MAXPATHLEN]; /* output map template */ +extern char typename[32]; /* name of file transfer type */ +extern int type; /* file transfer type */ +extern char structname[32]; /* name of file transfer structure */ +extern int stru; /* file transfer structure */ +extern char formname[32]; /* name of file transfer format */ +extern int form; /* file transfer format */ +extern char modename[32]; /* name of file transfer mode */ +extern int mode; /* file transfer mode */ +extern char bytename[32]; /* local byte size in ascii */ +extern int bytesize; /* local byte size in binary */ + +extern jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +extern char line[200]; /* input line buffer */ +extern char *stringbase; /* current scan point in line buffer */ +extern char argbuf[200]; /* argument storage buffer */ +extern char *argbase; /* current storage point in arg buffer */ +extern int margc; /* count of arguments on input line */ +extern char *margv[20]; /* args parsed from input line */ +extern int cpend; /* flag: if != 0, then pending server reply */ +extern int mflag; /* flag: if != 0, then active multi command */ + +extern int options; /* used during socket creation */ + +/* + * Format of command table. + */ +struct cmd { + char *c_name; /* name of command */ + char *c_help; /* help string */ + char c_bell; /* give bell when command completes */ + char c_conn; /* must be connected to use command */ + char c_proxy; /* proxy server may execute */ + int (*c_handler)(); /* function to call */ +}; + +struct macel { + char mac_name[9]; /* macro name */ + char *mac_start; /* start of macro in macbuf */ + char *mac_end; /* end of macro in macbuf */ +}; + +int macnum; /* number of defined macros */ +struct macel macros[16]; +char macbuf[4096]; + +extern char *tail(); +extern char *remglob(); +extern int errno; +extern char *mktemp(); + +#if defined(__ANSI__) || defined(sparc) +typedef void sig_t; +#else +typedef int sig_t; +#endif + +typedef int uid_t; +int herror(char *s); diff --git a/reactos/apps/utils/net/ftp/main.c b/reactos/apps/utils/net/ftp/main.c new file mode 100644 index 00000000000..fd6c506b2b2 --- /dev/null +++ b/reactos/apps/utils/net/ftp/main.c @@ -0,0 +1,602 @@ +/* + * Copyright (c) 1985, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c based on 5.13 (Berkeley) 3/14/89"; +#endif /* not lint */ + +/* + * FTP User Program -- Command Interface. + */ +#if !defined(WIN32) +#include +#include +#include +#include +#include +#include +#endif +#include "ftp_var.h" +#include "prototypes.h" +#include + +#include +#include + +#include +#include +#include +#include + + +#if defined(sun) && !defined(FD_SET) +typedef int uid_t; +#endif + +uid_t getuid(); +void intr(); +void lostpeer(); +char *getlogin(); + +short portnum; + +char home[128]; +char *globerr; +int autologin; + + + +/* Lot's of options... */ +/* + * Options and other state info. + */ +int trace; /* trace packets exchanged */ +int hash; /* print # for each buffer transferred */ +int sendport; /* use PORT cmd for each data connection */ +int verbose; /* print messages coming back from server */ +int connected; /* connected to server */ +int fromatty; /* input is from a terminal */ +int interactive; /* interactively prompt on m* cmds */ +int debug; /* debugging level */ +int bell; /* ring bell on cmd completion */ +int doglob; /* glob local file names */ +int proxy; /* proxy server connection active */ +int passivemode; +int proxflag; /* proxy connection exists */ +int sunique; /* store files on server with unique name */ +int runique; /* store local files with unique name */ +int mcase; /* map upper to lower case for mget names */ +int ntflag; /* use ntin ntout tables for name translation */ +int mapflag; /* use mapin mapout templates on file names */ +int code; /* return/reply code for ftp command */ +int crflag; /* if 1, strip car. rets. on ascii gets */ +char pasv[64]; /* passive port for proxy data connection */ +char *altarg; /* argv[1] with no shell-like preprocessing */ +char ntin[17]; /* input translation table */ +char ntout[17]; /* output translation table */ +// #include +char mapin[MAXPATHLEN]; /* input map template */ +char mapout[MAXPATHLEN]; /* output map template */ +char typename[32]; /* name of file transfer type */ +int type; /* file transfer type */ +char structname[32]; /* name of file transfer structure */ +int stru; /* file transfer structure */ +char formname[32]; /* name of file transfer format */ +int form; /* file transfer format */ +char modename[32]; /* name of file transfer mode */ +int mode; /* file transfer mode */ +char bytename[32]; /* local byte size in ascii */ +int bytesize; /* local byte size in binary */ + +jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +char line[200]; /* input line buffer */ +char *stringbase; /* current scan point in line buffer */ +char argbuf[200]; /* argument storage buffer */ +char *argbase; /* current storage point in arg buffer */ +int margc; /* count of arguments on input line */ +char *margv[20]; /* args parsed from input line */ +int cpend; /* flag: if != 0, then pending server reply */ +int mflag; /* flag: if != 0, then active multi command */ + +int options; /* used during socket creation */ + + + +int main(int argc, char *argv[]) +{ + register char *cp; + int top; + struct passwd *pw = NULL; +#if 0 + char homedir[MAXPATHLEN]; +#endif + + int err; + WORD wVerReq; + + WSADATA WSAData; + struct servent *sp; /* service spec for tcp/ftp */ + + /* Disable output buffering, for the benefit of Emacs. */ + //setbuf(stdout, NULL); + + _fmode = O_BINARY; // This causes an error somewhere. + + wVerReq = MAKEWORD(1,1); + + err = WSAStartup(wVerReq, &WSAData); + if (err != 0) + { + fprintf(stderr, "Could not initialize Windows socket interface."); + exit(1); + } + + sp = getservbyname("ftp", "tcp"); + if (sp == 0) { + fprintf(stderr, "ftp: ftp/tcp: unknown service\n"); + exit(1); + } + + portnum = sp->s_port; + + + doglob = 1; + interactive = 1; + autologin = 1; + argc--, argv++; + while (argc > 0 && **argv == '-') { + for (cp = *argv + 1; *cp; cp++) + switch (*cp) { + + case 'd': + options |= SO_DEBUG; + debug++; + break; + + case 'v': + verbose++; + break; + + case 't': + trace++; + break; + + case 'i': + interactive = 0; + break; + + case 'n': + autologin = 0; + break; + + case 'g': + doglob = 0; + break; + + default: + fprintf(stdout, + "ftp: %c: unknown option\n", *cp); + exit(1); + } + argc--, argv++; + } +// fromatty = isatty(fileno(stdin)); + fromatty = 1; // Strengthen this test + /* + * Set up defaults for FTP. + */ + (void) strcpy(typename, "ascii"), type = TYPE_A; + (void) strcpy(formname, "non-print"), form = FORM_N; + (void) strcpy(modename, "stream"), mode = MODE_S; + (void) strcpy(structname, "file"), stru = STRU_F; + (void) strcpy(bytename, "8"), bytesize = 8; + if (fromatty) + verbose++; + cpend = 0; /* no pending replies */ + proxy = 0; /* proxy not active */ + passivemode = 1; /* passive mode *is* active */ + crflag = 1; /* strip c.r. on ascii gets */ + /* + * Set up the home directory in case we're globbing. + */ +#if 0 + cp = getlogin(); + if (cp != NULL) { + pw = getpwnam(cp); + } + if (pw == NULL) + pw = getpwuid(getuid()); + if (pw != NULL) { + home = homedir; + (void) strcpy(home, pw->pw_dir); + } +#endif + strcpy(home, "C:/"); + if (argc > 0) { + if (setjmp(toplevel)) + exit(0); +// (void) signal(SIGINT, intr); +// (void) signal(SIGPIPE, lostpeer); + setpeer(argc + 1, argv - 1); + } + top = setjmp(toplevel) == 0; + if (top) { +// (void) signal(SIGINT, intr); +// (void) signal(SIGPIPE, lostpeer); + } + for (;;) { + cmdscanner(top); + top = 1; + } +} + +void +intr() +{ + + longjmp(toplevel, 1); +} + +void lostpeer(void) +{ + extern int cout; + extern int data; + + if (connected) { + if (cout != (int) NULL) { + closesocket(cout); + cout = (int) NULL; + } + if (data >= 0) { + (void) shutdown(data, 1+1); + (void) close(data); + data = -1; + } + connected = 0; + } + pswitch(1); + if (connected) { + if (cout != (int)NULL) { + closesocket(cout); + cout = (int) NULL; + } + connected = 0; + } + proxflag = 0; + pswitch(0); +} + +/*char * +tail(filename) + char *filename; +{ + register char *s; + + while (*filename) { + s = rindex(filename, '/'); + if (s == NULL) + break; + if (s[1]) + return (s + 1); + *s = '\0'; + } + return (filename); +} +*/ +/* + * Command parser. + */ +void cmdscanner(top) + int top; +{ + register struct cmd *c; + struct cmd *getcmd(); + extern int help(); + + if (!top) + (void) putchar('\n'); + for (;;) { + (void) fflush(stdout); + if (fromatty) { + printf("ftp> "); + (void) fflush(stdout); + } + if (gets(line) == 0) { + if (feof(stdin) || ferror(stdin)) + quit(); + break; + } + if (line[0] == 0) + break; + makeargv(); + if (margc == 0) { + continue; + } + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_conn && !connected) { + printf ("Not connected.\n"); + continue; + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) + (void) putchar('\007'); + if (c->c_handler != help) + break; + } + (void) fflush(stdout); +// (void) signal(SIGINT, intr); +// (void) signal(SIGPIPE, lostpeer); +} + +struct cmd * +getcmd(name) + register char *name; +{ + extern struct cmd cmdtab[]; + register char *p, *q; + register struct cmd *c, *found; + register int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; p = c->c_name; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return (c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return ((struct cmd *)-1); + return (found); +} + +/* + * Slice a string up into argc/argv. + */ + +int slrflag; + +void makeargv() +{ + char **argp; + char *slurpstring(); + + margc = 0; + argp = margv; + stringbase = line; /* scan from first of buffer */ + argbase = argbuf; /* store from first of buffer */ + slrflag = 0; + while (*argp++ = slurpstring()) + margc++; +} + +/* + * Parse string into argbuf; + * implemented with FSM to + * handle quoting and strings + */ +char * +slurpstring() +{ + int got_one = 0; + register char *sb = stringbase; + register char *ap = argbase; + char *tmp = argbase; /* will return this if token found */ + + if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */ + switch (slrflag) { /* and $ as token for macro invoke */ + case 0: + slrflag++; + stringbase++; + return ((*sb == '!') ? "!" : "$"); + /* NOTREACHED */ + case 1: + slrflag++; + altarg = stringbase; + break; + default: + break; + } + } + +S0: + switch (*sb) { + + case '\0': + goto OUT1; + + case ' ': + case '\t': + sb++; goto S0; + + default: + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = sb; + break; + default: + break; + } + goto S1; + } + +S1: + switch (*sb) { + + case ' ': + case '\t': + case '\0': + goto OUT1; /* end of token */ + + case '\\': + sb++; goto S2; /* slurp next character */ + + case '"': + sb++; goto S3; /* slurp quoted string */ + + default: + *ap++ = *sb++; /* add character to token */ + got_one = 1; + goto S1; + } + +S2: + switch (*sb) { + + case '\0': + goto OUT1; + + default: + *ap++ = *sb++; + got_one = 1; + goto S1; + } + +S3: + switch (*sb) { + + case '\0': + goto OUT1; + + case '"': + sb++; goto S1; + + default: + *ap++ = *sb++; + got_one = 1; + goto S3; + } + +OUT1: + if (got_one) + *ap++ = '\0'; + argbase = ap; /* update storage pointer */ + stringbase = sb; /* update scan pointer */ + if (got_one) { + return(tmp); + } + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = (char *) 0; + break; + default: + break; + } + return((char *)0); +} + +#define HELPINDENT (sizeof ("directory")) + +/* + * Help command. + * Call each command handler with argc == 0 and argv[0] == name. + */ +int help(argc, argv) + int argc; + char *argv[]; +{ + extern struct cmd cmdtab[]; + register struct cmd *c; + + if (argc == 1) { + register int i, j, w, k; + int columns, width = 0, lines; + extern int NCMDS; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + if (c->c_name && (!proxy || c->c_proxy)) { + printf("%s", c->c_name); + } + else if (c->c_name) { + for (k=0; k < (int) strlen(c->c_name); k++) { + (void) putchar(' '); + } + } + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + (void) putchar('\t'); + } + } + } + (void) fflush(stdout); + return 0; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } + (void) fflush(stdout); + return 0; +} diff --git a/reactos/apps/utils/net/ftp/makefile b/reactos/apps/utils/net/ftp/makefile new file mode 100644 index 00000000000..a32c246c310 --- /dev/null +++ b/reactos/apps/utils/net/ftp/makefile @@ -0,0 +1,27 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = ftp + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ws2_32.a iphlpapi.a +# ntdll.a + +TARGET_OBJECTS = \ + cmds.o \ + cmdtab.o \ + domacro.o \ + fake.o \ + ftp.o \ + main.o \ + ruserpass.o + +TARGET_GCCLIBS = + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/apps/utils/net/ftp/pathnames.h b/reactos/apps/utils/net/ftp/pathnames.h new file mode 100644 index 00000000000..676aa507daf --- /dev/null +++ b/reactos/apps/utils/net/ftp/pathnames.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * %W% (Berkeley) %G% + */ + +#define _PATH_TMP "/tmp/ftpXXXXXX" +#define _PATH_BSHELL "/bin/sh" diff --git a/reactos/apps/utils/net/ftp/prototypes.h b/reactos/apps/utils/net/ftp/prototypes.h new file mode 100644 index 00000000000..3bff115d48f --- /dev/null +++ b/reactos/apps/utils/net/ftp/prototypes.h @@ -0,0 +1,32 @@ + +int getreply(int expecteof); +int ruserpass(char *host, char **aname, char **apass, char **aacct); +char *getpass(const char *prompt); +void makeargv(void); +void domacro(int argc, char *argv[]); +void proxtrans(char *cmd, char *local, char *remote); +int null(void); +int initconn(void); +void disconnect(void); +void ptransfer(char *direction, long bytes, struct timeval *t0, struct timeval *t1); +void setascii(void); +void setbinary(void); +void setebcdic(void); +void settenex(void); +void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0); +void setpassive(int argc, char *argv[]); +void setpeer(int argc, char *argv[]); +void cmdscanner(int top); +void pswitch(int flag); +void quit(void); +int login(char *host); +int command(char *fmt, ...); +int globulize(char **cpp); +void sendrequest(char *cmd, char *local, char *remote, int printnames); +void recvrequest(char *cmd, char *local, char *remote, char *mode, + int printnames); +int confirm(char *cmd, char *file); +void blkfree(char **av0); +int getit(int argc, char *argv[], int restartit, char *mode); +static int token(void); +int sleep(int time); diff --git a/reactos/apps/utils/net/ftp/ruserpass.c b/reactos/apps/utils/net/ftp/ruserpass.c new file mode 100644 index 00000000000..ea6751bae0e --- /dev/null +++ b/reactos/apps/utils/net/ftp/ruserpass.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ruserpass.c 5.1 (Berkeley) 3/1/89"; +#endif /* not lint */ + +#include +#include +//#include +#include +#include +#include +#include "ftp_var.h" +#include "prototypes.h" +#include + +char *renvlook(), *index(), *getenv(), *getpass(), *getlogin(); +void *malloc(); +char *strcpy(); +struct utmp *getutmp(); +static FILE *cfile; + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#define ID 10 +#define MACH 11 + +static char tokval[100]; + +static struct toktab { + char *tokstr; + int tval; +} toktab[]= { + "default", DEFAULT, + "login", LOGIN, + "password", PASSWD, + "passwd", PASSWD, + "account", ACCOUNT, + "machine", MACH, + "macdef", MACDEF, + 0, 0 +}; + +extern char *hostname; + +int ruserpass(char *host, char **aname, char **apass, char **aacct) +{ + char *hdir, buf[BUFSIZ], *tmp; + char myname[MAXHOSTNAMELEN], *mydomain; + int t, i, c, usedefault = 0; + struct stat stb; + extern int errno; + + hdir = getenv("HOME"); + if (hdir == NULL) + hdir = "."; + (void) sprintf(buf, "%s/.netrc", hdir); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + perror(buf); + return(0); + } + + + if (gethostname(myname, sizeof(myname)) < 0) + myname[0] = '\0'; + if ((mydomain = index(myname, '.')) == NULL) + mydomain = ""; +next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if (strcasecmp(hostname, tokval) == 0) + goto match; + if ((tmp = index(hostname, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(hostname, tokval, tmp - hostname) == 0 && + tokval[tmp - hostname] == '\0') + goto match; + if ((tmp = index(host, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) + if (*aname == 0) { + *aname = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aname, tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + break; + case PASSWD: + if (strcmp(*aname, "anonymous") && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + fprintf(stderr, "Error - .netrc file not correct mode.\n"); + fprintf(stderr, "Remove password or correct mode.\n"); + goto bad; + } + if (token() && *apass == 0) { + *apass = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*apass, tokval); + } + break; + case ACCOUNT: + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + fprintf(stderr, "Error - .netrc file not correct mode.\n"); + fprintf(stderr, "Remove account or correct mode.\n"); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aacct, tokval); + } + break; + case MACDEF: + if (proxy) { + (void) fclose(cfile); + return(0); + } + while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc(cfile)) != EOF && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + break; + } + *tmp = '\0'; + } + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } + break; + default: + fprintf(stderr, "Unknown .netrc keyword %s\n", tokval); + break; + } + goto done; + } +done: + (void) fclose(cfile); + return(0); +bad: + (void) fclose(cfile); + return(-1); +} + +static int token(void) +{ + char *cp; + int c; + struct toktab *t; + + if (feof(cfile)) + return (0); + while ((c = getc(cfile)) != EOF && + (c == '\r' || c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',' && c != '\r') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } + *cp = 0; + if (tokval[0] == 0) + return (0); + for (t = toktab; t->tokstr; t++) + if (!strcmp(t->tokstr, tokval)) + return (t->tval); + return (ID); +} diff --git a/reactos/apps/utils/net/ping/ping.c b/reactos/apps/utils/net/ping/ping.c index 0b241fa1662..5cab24632b7 100644 --- a/reactos/apps/utils/net/ping/ping.c +++ b/reactos/apps/utils/net/ping/ping.c @@ -331,7 +331,7 @@ BOOL Setup(VOID) } if (phe != NULL) { - CopyMemory(&Target.sin_addr, phe->h_addr_list, phe->h_length); + CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length); } else { Target.sin_addr.s_addr = Addr; } @@ -391,19 +391,9 @@ VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time) LARGE_INTEGER LargeTime; LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart; + _i64toa(LargeTime.QuadPart, Convstr, 10); strcpy(String, Convstr); - strcat(String, ","); - - LargeTime.QuadPart = (Time.QuadPart % TicksPerMs.QuadPart) / TicksPerUs.QuadPart; - _i64toa(LargeTime.QuadPart, Convstr, 10); - Length = strlen(Convstr); - if (Length < 4) { - for (i = 0; i < 4 - Length; i++) - strcat(String, "0"); - } - - strcat(String, Convstr); strcat(String, "ms"); } @@ -417,6 +407,7 @@ BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from) CHAR Time[100]; LARGE_INTEGER RelativeTime; LARGE_INTEGER LargeTime; + CHAR Sign[1]; IpHeader = (PIPv4_HEADER)buffer; @@ -449,10 +440,17 @@ BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from) RelativeTime.QuadPart = (LargeTime.QuadPart - Icmp->Timestamp.QuadPart); - TimeToMsString(Time, RelativeTime); + if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1) { + strcpy(Sign, "<"); + strcpy(Time, "1ms"); + } else { + strcpy(Sign, "="); + TimeToMsString(Time, RelativeTime); + } - printf("Reply from %s: bytes=%d time=%s TTL=%d\n", inet_ntoa(from->sin_addr), - size - IphLength - sizeof(ICMP_ECHO_PACKET), Time, IpHeader->TTL); + + printf("Reply from %s: bytes=%d time%s%s TTL=%d\n", inet_ntoa(from->sin_addr), + size - IphLength - sizeof(ICMP_ECHO_PACKET), Sign, Time, IpHeader->TTL); if (RelativeTime.QuadPart < MinRTT.QuadPart) { MinRTT.QuadPart = RelativeTime.QuadPart; MinRTTSet = TRUE; diff --git a/reactos/apps/utils/net/route/route.xml b/reactos/apps/utils/net/route/route.xml new file mode 100644 index 00000000000..c1a435eb7e6 --- /dev/null +++ b/reactos/apps/utils/net/route/route.xml @@ -0,0 +1,8 @@ + + . + kernel32 + ws2_32 + iphlpapi + route.c + route.rc + diff --git a/reactos/apps/utils/net/tracert/ip.h b/reactos/apps/utils/net/tracert/ip.h new file mode 100644 index 00000000000..6463b72dcc4 --- /dev/null +++ b/reactos/apps/utils/net/tracert/ip.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.2 (Berkeley) 6/1/94 + * $FreeBSD: src/sys/netinet/ip.h,v 1.16 1999/08/28 00:49:19 peter Exp $ + */ + +#ifndef _NETINET_IP_H_ +#define _NETINET_IP_H_ + +/* + * Definitions for internet protocol version 4. + * Per RFC 791, September 1981. + */ +#define IPVERSION 4 + +/* A little magic to make the Windows build happy. */ +#if defined(_MSC_VER) || defined(__MINGW32__) +#include +#include +#include + +typedef u_short n_short; +typedef u_int n_long; +typedef u_int n_time; + +#define EMSGSIZE WSAEMSGSIZE +#define ENETUNREACH WSAENETUNREACH +#define EHOSTUNREACH WSAEHOSTUNREACH +#endif + +/* + * Structure of an internet header, naked of options. + */ +struct ip { +#ifdef _IP_VHL + u_char ip_vhl; /* version << 4 | header length >> 2 */ +#else +#if BYTE_ORDER == LITTLE_ENDIAN + u_int ip_hl:4, /* header length */ + ip_v:4; /* version */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int ip_v:4, /* version */ + ip_hl:4; /* header length */ +#endif +#endif /* not _IP_VHL */ + u_char ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* don't fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_char ip_ttl; /* time to live */ + u_char ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src,ip_dst; /* source and dest address */ +}; + +#ifdef _IP_VHL +#define IP_MAKE_VHL(v, hl) ((v) << 4 | (hl)) +#define IP_VHL_HL(vhl) ((vhl) & 0x0f) +#define IP_VHL_V(vhl) ((vhl) >> 4) +#define IP_VHL_BORING 0x45 +#endif + +#define IP_MAXPACKET 65535 /* maximum packet size */ + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_MINCOST 0x02 + +/* + * Definitions for IP precedence (also in ip_tos) (hopefully unused) + */ +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + +/* + * Definitions for options. + */ +#define IPOPT_COPIED(o) ((o)&0x80) +#define IPOPT_CLASS(o) ((o)&0x60) +#define IPOPT_NUMBER(o) ((o)&0x1f) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_DEBMEAS 0x40 +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_EOL 0 /* end of option list */ +#define IPOPT_NOP 1 /* no operation */ + +#define IPOPT_RR 7 /* record packet route */ +#define IPOPT_TS 68 /* timestamp */ +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ +#define IPOPT_LSRR 131 /* loose source route */ +#define IPOPT_SATID 136 /* satnet id */ +#define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_RA 148 /* router alert */ + +/* + * Offsets to fields in options other than EOL and NOP. + */ +#define IPOPT_OPTVAL 0 /* option ID */ +#define IPOPT_OLEN 1 /* option length */ +#define IPOPT_OFFSET 2 /* offset within option */ +#define IPOPT_MINOFF 4 /* min value of above */ + +/* + * Time stamp option structure. + */ +struct ip_timestamp { + u_char ipt_code; /* IPOPT_TS */ + u_char ipt_len; /* size of structure (variable) */ + u_char ipt_ptr; /* index of current entry */ +#if BYTE_ORDER == LITTLE_ENDIAN + u_int ipt_flg:4, /* flags, see below */ + ipt_oflw:4; /* overflow counter */ +#endif +#if BYTE_ORDER == BIG_ENDIAN + u_int ipt_oflw:4, /* overflow counter */ + ipt_flg:4; /* flags, see below */ +#endif + union ipt_timestamp { + n_long ipt_time[1]; + struct ipt_ta { + struct in_addr ipt_addr; + n_long ipt_time; + } ipt_ta[1]; + } ipt_timestamp; +}; + +/* flag bits for ipt_flg */ +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +/* bits for security (not byte swapped) */ +#define IPOPT_SECUR_UNCLASS 0x0000 +#define IPOPT_SECUR_CONFID 0xf135 +#define IPOPT_SECUR_EFTO 0x789a +#define IPOPT_SECUR_MMMM 0xbc4d +#define IPOPT_SECUR_RESTR 0xaf13 +#define IPOPT_SECUR_SECRET 0xd788 +#define IPOPT_SECUR_TOPSECRET 0x6bc5 + +/* + * Internet implementation parameters. + */ +#define MAXTTL 255 /* maximum time to live (seconds) */ +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ +#define IPTTLDEC 1 /* subtracted when forwarding */ + +#define IP_MSS 576 /* default maximum segment size */ + +#endif diff --git a/reactos/apps/utils/net/tracert/ip_icmp.h b/reactos/apps/utils/net/tracert/ip_icmp.h new file mode 100644 index 00000000000..2b3ee2eb280 --- /dev/null +++ b/reactos/apps/utils/net/tracert/ip_icmp.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/netinet/ip_icmp.h,v 1.13 1999/08/28 00:49:24 peter Exp $ + */ + +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ + +/* + * Interface Control Message Protocol Definitions. + * Per RFC 792, September 1981. + */ + +/* + * Internal of an ICMP Router Advertisement + */ +struct icmp_ra_addr { + u_int32_t ira_addr; + u_int32_t ira_preference; +}; + +/* + * Structure of an icmp header. + */ +struct icmp { + u_char icmp_type; /* type of message, see below */ + u_char icmp_code; /* type sub code */ + u_short icmp_cksum; /* ones complement cksum of struct */ + union { + u_char ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ + struct ih_idseq { + n_short icd_id; + n_short icd_seq; + } ih_idseq; + int ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu { + n_short ipm_void; + n_short ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + u_char irt_num_addrs; + u_char irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union { + struct id_ts { + n_time its_otime; + n_time its_rtime; + n_time its_ttime; + } id_ts; + struct id_ip { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + struct icmp_ra_addr id_radv; + u_int32_t id_mask; + char id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_radv +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +}; + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enough to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#ifndef _IP_VHL +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ +#else +#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8) + /* N.B.: must separately check that header length >= 5 */ +#endif + +/* + * Definition of type and code field values. + */ +#define ICMP_ECHOREPLY 0 /* echo reply */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_REDIRECT 5 /* shorter route, codes: */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_ECHO 8 /* echo service */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ + +#define ICMP_MAXTYPE 18 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef KERNEL +void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *)); +void icmp_input __P((struct mbuf *, int)); +#endif + +#endif diff --git a/reactos/apps/utils/net/tracert/makefile b/reactos/apps/utils/net/tracert/makefile new file mode 100644 index 00000000000..09c6c498f24 --- /dev/null +++ b/reactos/apps/utils/net/tracert/makefile @@ -0,0 +1,20 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = tracert + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ws2_32.a iphlpapi.a ntdll.a + +TARGET_OBJECTS = \ +$(TARGET_NAME).o + +TARGET_GCCLIBS = + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/apps/utils/net/tracert/tracert.c b/reactos/apps/utils/net/tracert/tracert.c new file mode 100644 index 00000000000..fb5297b1de0 --- /dev/null +++ b/reactos/apps/utils/net/tracert/tracert.c @@ -0,0 +1,957 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * traceroute host - trace the route ip packets follow going to "host". + * + * Attempt to trace the route an ip packet would follow to some + * internet host. We find out intermediate hops by launching probe + * packets with a small ttl (time to live) then listening for an + * icmp "time exceeded" reply from a gateway. We start our probes + * with a ttl of one and increase by one until we get an icmp "port + * unreachable" (which means we got to "host") or hit a max (which + * defaults to 30 hops & can be changed with the -m flag). Three + * probes (change with -q flag) are sent at each ttl setting and a + * line is printed showing the ttl, address of the gateway and + * round trip time of each probe. If the probe answers come from + * different gateways, the address of each responding system will + * be printed. If there is no response within a 5 sec. timeout + * interval (changed with the -w flag), a "*" is printed for that + * probe. + * + * Probe packets are UDP format. We don't want the destination + * host to process them so the destination port is set to an + * unlikely value (if some clod on the destination is using that + * value, it can be changed with the -p flag). + * + * A sample use might be: + * + * [yak 71]% traceroute nis.nsf.net. + * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet + * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms + * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms + * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms + * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms + * + * Note that lines 2 & 3 are the same. This is due to a buggy + * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards + * packets with a zero ttl. + * + * A more interesting example is: + * + * [yak 72]% traceroute allspice.lcs.mit.edu. + * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms + * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms + * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms + * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms + * 12 * * * + * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms + * 14 * * * + * 15 * * * + * 16 * * * + * 17 * * * + * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms + * + * (I start to see why I'm having so much trouble with mail to + * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away + * either don't send ICMP "time exceeded" messages or send them + * with a ttl too small to reach us. 14 - 17 are running the + * MIT C Gateway code that doesn't send "time exceeded"s. God + * only knows what's going on with 12. + * + * The silent gateway 12 in the above may be the result of a bug in + * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) + * sends an unreachable message using whatever ttl remains in the + * original datagram. Since, for gateways, the remaining ttl is + * zero, the icmp "time exceeded" is guaranteed to not make it back + * to us. The behavior of this bug is slightly more interesting + * when it appears on the destination system: + * + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms + * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms + * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms + * 7 * * * + * 8 * * * + * 9 * * * + * 10 * * * + * 11 * * * + * 12 * * * + * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! + * + * Notice that there are 12 "gateways" (13 is the final + * destination) and exactly the last half of them are "missing". + * What's really happening is that rip (a Sun-3 running Sun OS3.5) + * is using the ttl from our arriving datagram as the ttl in its + * icmp reply. So, the reply will time out on the return path + * (with no notice sent to anyone since icmp's aren't sent for + * icmp's) until we probe with a ttl that's at least twice the path + * length. I.e., rip is really only 7 hops away. A reply that + * returns with a ttl of 1 is a clue this problem exists. + * Traceroute prints a "!" after the time if the ttl is <= 1. + * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or + * non-standard (HPUX) software, expect to see this problem + * frequently and/or take care picking the target host of your + * probes. + * + * Other possible annotations after the time are !H, !N, !P (got a host, + * network or protocol unreachable, respectively), !S or !F (source + * route failed or fragmentation needed -- neither of these should + * ever occur and the associated gateway is busted if you see one). If + * almost all the probes result in some kind of unreachable, traceroute + * will give up and exit. + * + * Notes + * ----- + * This program must be run by root or be setuid. (I suggest that + * you *don't* make it setuid -- casual use could result in a lot + * of unnecessary traffic on our poor, congested nets.) + * + * This program requires a kernel mod that does not appear in any + * system available from Berkeley: A raw ip socket using proto + * IPPROTO_RAW must interpret the data sent as an ip datagram (as + * opposed to data to be wrapped in a ip datagram). See the README + * file that came with the source to this program for a description + * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may + * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE + * MODIFIED TO RUN THIS PROGRAM. + * + * The udp port usage may appear bizarre (well, ok, it is bizarre). + * The problem is that an icmp message only contains 8 bytes of + * data from the original datagram. 8 bytes is the size of a udp + * header so, if we want to associate replies with the original + * datagram, the necessary information must be encoded into the + * udp header (the ip id could be used but there's no way to + * interlock with the kernel's assignment of ip id's and, anyway, + * it would have taken a lot more kernel hacking to allow this + * code to set the ip id). So, to allow two or more users to + * use traceroute simultaneously, we use this task's pid as the + * source port (the high bit is set to move the port number out + * of the "likely" range). To keep track of which probe is being + * replied to (so times and/or hop counts don't get confused by a + * reply that was delayed in transit), we increment the destination + * port number before each probe. + * + * Don't use this as a coding example. I was trying to find a + * routing problem and this code sort-of popped out after 48 hours + * without sleep. I was amazed it ever compiled, much less ran. + * + * I stole the idea for this program from Steve Deering. Since + * the first release, I've learned that had I attended the right + * IETF working group meetings, I also could have stolen it from Guy + * Almes or Matt Mathis. I don't know (or care) who came up with + * the idea first. I envy the originators' perspicacity and I'm + * glad they didn't keep the idea a secret. + * + * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or + * enhancements to the original distribution. + * + * I've hacked up a round-trip-route version of this that works by + * sending a loose-source-routed udp datagram through the destination + * back to yourself. Unfortunately, SO many gateways botch source + * routing, the thing is almost worthless. Maybe one day... + * + * -- Van Jacobson (van@helios.ee.lbl.gov) + * Tue Dec 20 03:50:13 PST 1988 + */ + +#define caddr_t void * + +#include +#include +#include +#include +#include + +#include + + +#include +#include +#include + +//void print(buf, cc, from); +char * inetname(struct in_addr); +double deltaT(struct timeval *, struct timeval *); +void usage(); +void send_probe(int, int); + +#define bzero( ptr, count ) memset( ptr, 0, count ) +#define bcopy(src,dest,len) memcpy(dest,src,len) + +// setlinebuf is equivalent to the setvbuf call below. +inline int setlinebuf(FILE *stream) +{ + return setvbuf( stream, (char*)0, _IONBF, 0 ); +} + +#ifndef __GNUC__ +#define EPOCHFILETIME (116444736000000000i64) +#else +#define EPOCHFILETIME (116444736000000000LL) +#endif + +struct timezone { + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + static int tzflag; + + if (tv) + { + GetSystemTimeAsFileTime(&ft); + //li.LowPart = ft.dwLowDateTime; + //li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + } + + if (tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} + + + +/* Set up endiannes macros for the ip and ip_icmp BSD headers */ +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BYTE_ORDER +#ifdef WORDS_BIGENDIAN +#define BYTE_ORDER BIG_ENDIAN +#else +#define BYTE_ORDER LITTLE_ENDIAN +#endif +#endif /* BYTE_ORDER */ + +#define u_int16_t WORD +#define u_int32_t DWORD + +/* These are BSD headers. We use these here because they are needed on + * libc5 Linux systems. On other platforms they are usually simply more + * complete than the native stuff, and cause less portability problems + * so we use them anyway. + */ +#include "ip.h" +#include "ip_icmp.h" + + +#define MAXPACKET 65535 /* max ip packet size */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#ifndef FD_SET +#define NFDBITS (8*sizeof(fd_set)) +#define FD_SETSIZE NFDBITS +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +#define Fprintf (void)fprintf +#define Sprintf (void)sprintf +#define Printf (void)printf + +/* + * Define the UDP header + */ +typedef struct udphdr { + u_short uh_dport; + u_short uh_sport; + u_short uh_sum; + u_short uh_ulen; +} udphdr; + +/* + * format of a (udp) probe packet. + */ +struct opacket { + struct ip ip; + udphdr udp; + u_char seq; /* sequence number of this packet */ + u_char ttl; /* ttl packet left with */ + struct timeval tv; /* time packet left */ +}; + +u_char packet[512]; /* last inbound (icmp) packet */ +struct opacket *outpacket; /* last output (udp) packet */ + +#if 0 +int wait_for_reply __P((int, struct sockaddr_in *)); +void send_probe __P((int, int)); +double deltaT __P((struct timeval *, struct timeval *)); +int packet_ok __P((u_char *, int, struct sockaddr_in *, int)); +//void print __P((u_char *, int, struct sockaddr_in *)); +void tvsub __P((struct timeval *, struct timeval *)); +char *inetname __P((struct in_addr)); +void usage __P(()); +#endif + +int s; /* receive (icmp) socket file descriptor */ +int sndsock; /* send (udp) socket file descriptor */ +struct timezone tz; /* leftover */ + +struct sockaddr whereto; /* Who to try to reach */ +int datalen; /* How much data */ + +char *source = 0; +char *hostname; + +int nprobes = 3; +int max_ttl = 30; +u_short ident; +u_short port = 32768+666; /* start udp dest port # for probe packets */ +int options; /* socket options */ +int verbose; +int waittime = 5; /* time to wait for response (in seconds) */ +int nflag; /* print addresses numerically */ + +void +print(buf, cc, from) + u_char *buf; + int cc; + struct sockaddr_in *from; +{ + struct ip *ip; + int hlen; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + cc -= hlen; + + if (nflag) + Printf(" %s", inet_ntoa(from->sin_addr)); + else + Printf(" %s (%s)", inetname(from->sin_addr), + inet_ntoa(from->sin_addr)); + + if (verbose) + Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); +} + + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + struct hostent *hp; + struct protoent *pe; + struct sockaddr_in from, *to; + int ch, i, on, probe, seq, tos, ttl; + WSADATA wsadata; + INT status; + + on = 1; + seq = tos = 0; + to = (struct sockaddr_in *)&whereto; + while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) + switch(ch) { + case 'd': + options |= SO_DEBUG; + break; + case 'm': + max_ttl = atoi(optarg); + if (max_ttl <= 1) { + Fprintf(stderr, + "traceroute: max ttl must be >1.\n"); + WSACleanup(); + exit(1); + } + break; + case 'n': + nflag++; + break; + case 'p': + port = atoi(optarg); + if (port < 1) { + Fprintf(stderr, + "traceroute: port must be >0.\n"); + WSACleanup(); + exit(1); + } + break; + case 'q': + nprobes = atoi(optarg); + if (nprobes < 1) { + Fprintf(stderr, + "traceroute: nprobes must be >0.\n"); + WSACleanup(); + exit(1); + } + break; + case 'r': + options |= SO_DONTROUTE; + break; + case 's': + /* + * set the ip source address of the outbound + * probe (e.g., on a multi-homed host). + */ + source = optarg; + break; + case 't': + tos = atoi(optarg); + if (tos < 0 || tos > 255) { + Fprintf(stderr, + "traceroute: tos must be 0 to 255.\n"); + WSACleanup(); + exit(1); + } + break; + case 'v': + verbose++; + break; + case 'w': + waittime = atoi(optarg); + if (waittime <= 1) { + Fprintf(stderr, + "traceroute: wait must be >1 sec.\n"); + WSACleanup(); + exit(1); + } + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + status = WSAStartup(MAKEWORD(2, 2), &wsadata); + if (status != 0) { + printf("Could not initialize winsock dll.\n"); + return FALSE; + } + + setlinebuf (stdout); + + (void) bzero((char *)&whereto, sizeof(struct sockaddr)); + to->sin_family = AF_INET; + to->sin_addr.s_addr = inet_addr(*argv); + if (to->sin_addr.s_addr != -1) + hostname = *argv; + else { + hp = gethostbyname(*argv); + if (hp) { + to->sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); + hostname = hp->h_name; + } else { + (void)fprintf(stderr, + "traceroute: unknown host %s\n", *argv); + WSACleanup(); + exit(1); + } + } + if (*++argv) + datalen = atoi(*argv); + if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) { + Fprintf(stderr, + "traceroute: packet size must be 0 <= s < %ld.\n", + MAXPACKET - sizeof(struct opacket)); + WSACleanup(); + exit(1); + } + datalen += sizeof(struct opacket); + outpacket = (struct opacket *)malloc((unsigned)datalen); + if (! outpacket) { + perror("traceroute: malloc"); + WSACleanup(); + exit(1); + } + (void) bzero((char *)outpacket, datalen); + outpacket->ip.ip_dst = to->sin_addr; + outpacket->ip.ip_tos = tos; + outpacket->ip.ip_v = IPVERSION; + outpacket->ip.ip_id = 0; + + ident = (getpid() & 0xffff) | 0x8000; + + if ((pe = getprotobyname("icmp")) == NULL) { + Fprintf(stderr, "icmp: unknown protocol\n"); + WSACleanup(); + exit(10); + } + if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) { + perror("traceroute: icmp socket"); + WSACleanup(); + exit(5); + } + if (options & SO_DEBUG) + (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)); + if (options & SO_DONTROUTE) + (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)); + + if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { + perror("traceroute: raw socket"); + WSACleanup(); + exit(5); + } +#ifdef SO_SNDBUF + if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, + sizeof(datalen)) < 0) { + perror("traceroute: SO_SNDBUF"); + WSACleanup(); + exit(6); + } +#endif /* SO_SNDBUF */ +#ifdef IP_HDRINCL + if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, + sizeof(on)) < 0) { + perror("traceroute: IP_HDRINCL"); + WSACleanup(); + exit(6); + } +#endif /* IP_HDRINCL */ + if (options & SO_DEBUG) + (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)); + if (options & SO_DONTROUTE) + (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)); + + if (source) { + (void) bzero((char *)&from, sizeof(struct sockaddr)); + from.sin_family = AF_INET; + from.sin_addr.s_addr = inet_addr(source); + if (from.sin_addr.s_addr == -1) { + Printf("traceroute: unknown host %s\n", source); + WSACleanup(); + exit(1); + } + outpacket->ip.ip_src = from.sin_addr; +#ifndef IP_HDRINCL + if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) { + perror ("traceroute: bind:"); + WSACleanup(); + exit (1); + } +#endif /* IP_HDRINCL */ + } + + Fprintf(stderr, "traceroute to %s (%s)", hostname, + inet_ntoa(to->sin_addr)); + if (source) + Fprintf(stderr, " from %s", source); + Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); + (void) fflush(stderr); + + for (ttl = 1; ttl <= max_ttl; ++ttl) { + u_long lastaddr = 0; + int got_there = 0; + int unreachable = 0; + + Printf("%2d ", ttl); + for (probe = 0; probe < nprobes; ++probe) { + int cc; + struct timeval t1, t2; + struct timezone tz; + struct ip *ip; + + (void) gettimeofday(&t1, &tz); + send_probe(++seq, ttl); + while (cc = wait_for_reply(s, &from)) { + (void) gettimeofday(&t2, &tz); + if ((i = packet_ok(packet, cc, &from, seq))) { + if (from.sin_addr.s_addr != lastaddr) { + print(packet, cc, &from); + lastaddr = from.sin_addr.s_addr; + } + Printf(" %g ms", deltaT(&t1, &t2)); + switch(i - 1) { + case ICMP_UNREACH_PORT: +#ifndef ARCHAIC + ip = (struct ip *)packet; + if (ip->ip_ttl <= 1) + Printf(" !"); +#endif /* ARCHAIC */ + ++got_there; + break; + case ICMP_UNREACH_NET: + ++unreachable; + Printf(" !N"); + break; + case ICMP_UNREACH_HOST: + ++unreachable; + Printf(" !H"); + break; + case ICMP_UNREACH_PROTOCOL: + ++got_there; + Printf(" !P"); + break; + case ICMP_UNREACH_NEEDFRAG: + ++unreachable; + Printf(" !F"); + break; + case ICMP_UNREACH_SRCFAIL: + ++unreachable; + Printf(" !S"); + break; + } + break; + } + } + if (cc == 0) + Printf(" *"); + (void) fflush(stdout); + } + putchar('\n'); + if (got_there || unreachable >= nprobes-1) { + WSACleanup(); + exit(0); + } + } + + WSACleanup(); + return 0; +} + +int +wait_for_reply(sock, from) + int sock; + struct sockaddr_in *from; +{ + fd_set fds; + struct timeval wait; + int cc = 0; + int fromlen = sizeof (*from); + + FD_ZERO(&fds); + FD_SET(sock, &fds); + wait.tv_sec = waittime; wait.tv_usec = 0; + + if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0) + cc=recvfrom(s, (char *)packet, sizeof(packet), 0, + (struct sockaddr *)from, &fromlen); + + return(cc); +} + + +void +send_probe(seq, ttl) + int seq, ttl; +{ + struct opacket *op = outpacket; + struct ip *ip = &op->ip; + struct udphdr *up = &op->udp; + int i; + + ip->ip_off = 0; + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_UDP; + ip->ip_len = datalen; + ip->ip_ttl = ttl; + ip->ip_v = IPVERSION; + ip->ip_id = htons(ident+seq); + + up->uh_sport = htons(ident); + up->uh_dport = htons(port+seq); + up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip))); + up->uh_sum = 0; + + op->seq = seq; + op->ttl = ttl; + (void) gettimeofday(&op->tv, &tz); + + i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto, + sizeof(struct sockaddr)); + if (i < 0 || i != datalen) { + if (i<0) + perror("sendto"); + Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, + datalen, i); + (void) fflush(stdout); + } +} + + +double +deltaT(t1p, t2p) + struct timeval *t1p, *t2p; +{ + register double dt; + + dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + + (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; + return (dt); +} + + +/* + * Convert an ICMP "type" field to a printable string. + */ +char * +pr_type(t) + u_char t; +{ + static char *ttab[] = { + "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", + "Source Quench", "Redirect", "ICMP 6", "ICMP 7", + "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", + "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", + "Info Reply" + }; + + if(t > 16) + return("OUT-OF-RANGE"); + + return(ttab[t]); +} + + +int +packet_ok(buf, cc, from, seq) + u_char *buf; + int cc; + struct sockaddr_in *from; + int seq; +{ + register struct icmp *icp; + u_char type, code; + int hlen; +#ifndef ARCHAIC + struct ip *ip; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + if (cc < hlen + ICMP_MINLEN) { + if (verbose) + Printf("packet too short (%d bytes) from %s\n", cc, + inet_ntoa(from->sin_addr)); + return (0); + } + cc -= hlen; + icp = (struct icmp *)(buf + hlen); +#else + icp = (struct icmp *)buf; +#endif /* ARCHAIC */ + type = icp->icmp_type; code = icp->icmp_code; + if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || + type == ICMP_UNREACH) { + struct ip *hip; + struct udphdr *up; + + hip = &icp->icmp_ip; + hlen = hip->ip_hl << 2; + up = (struct udphdr *)((u_char *)hip + hlen); + if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP && + up->uh_sport == htons(ident) && + up->uh_dport == htons(port+seq)) + if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP) + return (type == ICMP_TIMXCEED? -1 : code+1); + } +#ifndef ARCHAIC + if (verbose) { + int i; + u_long *lp = (u_long *)&icp->icmp_ip; + + Printf("\n%d bytes from %s to %s", cc, + inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst)); + Printf(": icmp type %d (%s) code %d\n", type, pr_type(type), + icp->icmp_code); + for (i = 4; i < cc ; i += sizeof(long)) + Printf("%2d: x%8.8lx\n", i, *lp++); + } +#endif /* ARCHAIC */ + return(0); +} + +#ifdef notyet +/* + * Checksum routine for Internet Protocol family headers (C Version) + */ +u_short +in_cksum(addr, len) + u_short *addr; + int len; +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register int sum = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) + sum += *(u_char *)w; + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} +#endif /* notyet */ + +/* + * Subtract 2 timeval structs: out = out - in. + * Out is assumed to be >= in. + */ +void +tvsub(out, in) + register struct timeval *out, *in; +{ + if ((out->tv_usec -= in->tv_usec) < 0) { + out->tv_sec--; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + + +/* + * Construct an Internet address representation. + * If the nflag has been supplied, give + * numeric value, otherwise try for symbolic name. + */ +char * +inetname(in) + struct in_addr in; +{ + register char *cp; + static char line[50]; + struct hostent *hp; + static char domain[MAXHOSTNAMELEN + 1]; + static int first = 1; + + if (first && !nflag) { + first = 0; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = strrchr(domain, '.'))) + (void) strcpy(domain, cp + 1); + else + domain[0] = 0; + } + cp = 0; + if (!nflag && in.s_addr != INADDR_ANY) { + hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); + if (hp) { + if ((cp = strrchr(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = 0; + cp = hp->h_name; + } + } + if (cp) + (void) strcpy(line, cp); + else { + in.s_addr = ntohl(in.s_addr); +#define C(x) ((x) & 0xff) + Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24), + C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); + } + return (line); +} + +void +usage() +{ + (void)fprintf(stderr, +"usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\ +[-s src_addr] [-t tos] [-w wait] host [data size]\n"); + exit(1); +} diff --git a/reactos/apps/utils/net/tracert/tracert.rc b/reactos/apps/utils/net/tracert/tracert.rc new file mode 100644 index 00000000000..f1351caf1a0 --- /dev/null +++ b/reactos/apps/utils/net/tracert/tracert.rc @@ -0,0 +1,6 @@ +/* $Id: route.rc 11816 2004-11-26 06:51:47Z arty $ */ + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Traceroute\0" +#define REACTOS_STR_INTERNAL_NAME "tracert\0" +#define REACTOS_STR_ORIGINAL_FILENAME "tracert.exe\0" +#include diff --git a/reactos/apps/utils/net/whois/whois.rc b/reactos/apps/utils/net/whois/whois.rc index 3346e8e9ca1..e706ac8d0d8 100644 --- a/reactos/apps/utils/net/whois/whois.rc +++ b/reactos/apps/utils/net/whois/whois.rc @@ -3,5 +3,4 @@ #define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 Whois\0" #define REACTOS_STR_INTERNAL_NAME "whois\0" #define REACTOS_STR_ORIGINAL_FILENAME "whois.exe\0" -#define REACTOS_STR_ORIGINAL_COPYRIGHT "Steven Edwards (Isolation@users.sourceforge.net)\0" #include diff --git a/reactos/apps/utils/objdir/objdir.c b/reactos/apps/utils/objdir/objdir.c index 15e63ad4cb2..82516fdb309 100644 --- a/reactos/apps/utils/objdir/objdir.c +++ b/reactos/apps/utils/objdir/objdir.c @@ -79,10 +79,14 @@ StatusToName (NTSTATUS Status) return "STATUS_PATH_SYNTAX_BAD"; case STATUS_NO_MORE_ENTRIES: return "STATUS_NO_MORE_ENTRIES"; + case STATUS_MORE_ENTRIES: + return "STATUS_MORE_ENTRIES"; case STATUS_ACCESS_DENIED: return "STATUS_ACCESS_DENIED"; case STATUS_UNSUCCESSFUL: return "STATUS_UNSUCCESSFUL"; + case STATUS_INVALID_HANDLE: + return "STATUS_INVALID_HANDLE"; } sprintf (RawValue, "0x%08lx", Status); return (const char *) RawValue; @@ -173,8 +177,9 @@ ListDirectory ( OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE DirectoryHandle; - BYTE DirectoryEntry [MAX_DIR_ENTRY * sizeof(DIRECTORY_BASIC_INFORMATION)]; - PDIRECTORY_BASIC_INFORMATION pDirectoryEntry = (PDIRECTORY_BASIC_INFORMATION) DirectoryEntry; + BYTE DirectoryEntry [512]; + POBJECT_DIRECTORY_INFORMATION pDirectoryEntry = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry; + POBJECT_DIRECTORY_INFORMATION pDirectoryEntries = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry; ULONG Context = 0; ULONG ReturnLength = 0; ULONG EntryCount = 0; @@ -217,25 +222,23 @@ ListDirectory ( return (FALSE); } printf ("\n Directory of %s\n\n", DirectoryNameA); + + for(;;) + { /* * Enumerate each item in the directory. */ Status = NtQueryDirectoryObject ( DirectoryHandle, - pDirectoryEntry, + pDirectoryEntries, sizeof DirectoryEntry, FALSE,/* ReturnSingleEntry */ - TRUE, /* RestartScan */ + FALSE, /* RestartScan */ & Context, & ReturnLength ); - if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status) && Status != STATUS_NO_MORE_ENTRIES) { - if (STATUS_NO_MORE_ENTRIES == Status) - { - NtClose (DirectoryHandle); - return TRUE; - } printf ( "Failed to query directory object (Status: %s)\n", StatusToName (Status) @@ -243,12 +246,17 @@ ListDirectory ( NtClose (DirectoryHandle); return (FALSE); } - while (0 != pDirectoryEntry->ObjectTypeName.Length) + if (Status == STATUS_NO_MORE_ENTRIES) + { + break; + } + pDirectoryEntry = pDirectoryEntries; + while (EntryCount < Context) { CHAR ObjectNameA [MAX_PATH]; CHAR TypeNameA [MAX_PATH]; CHAR TargetNameA [MAX_PATH]; - + if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer)) { if (TRUE == ExpandSymbolicLink ( @@ -258,7 +266,7 @@ ListDirectory ( ) ) { - + printf ( "%-16s %s -> %s\n", RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA), @@ -283,9 +291,10 @@ ListDirectory ( RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA) ); } - ++ EntryCount; ++ pDirectoryEntry; + ++ EntryCount; } + }; printf ("\n\t%lu object(s)\n", EntryCount); /* * Free any resource. @@ -296,7 +305,7 @@ ListDirectory ( */ if (FALSE != Recurse) { - pDirectoryEntry = (PDIRECTORY_BASIC_INFORMATION) DirectoryEntry; + pDirectoryEntry = (POBJECT_DIRECTORY_INFORMATION) DirectoryEntry; while (0 != pDirectoryEntry->ObjectTypeName.Length) { if (0 == wcscmp (L"Directory", pDirectoryEntry->ObjectTypeName.Buffer)) diff --git a/reactos/apps/utils/rosperf/Makefile b/reactos/apps/utils/rosperf/Makefile new file mode 100644 index 00000000000..d14bdf4227a --- /dev/null +++ b/reactos/apps/utils/rosperf/Makefile @@ -0,0 +1,24 @@ +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = rosperf + +TARGET_SDKLIBS = version.a gdi32.a user32.a kernel32.a ntdll.a + +TARGET_OBJECTS = rosperf.o testlist.o fill.o lines.o + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# Automatic dependency tracking +DEP_OBJECTS := $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/tools/depend.mk + +# EOF diff --git a/reactos/apps/utils/rosperf/fill.c b/reactos/apps/utils/rosperf/fill.c new file mode 100644 index 00000000000..422be8d982e --- /dev/null +++ b/reactos/apps/utils/rosperf/fill.c @@ -0,0 +1,60 @@ +/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "rosperf.h" + +void +FillProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + + for (Rep = 0; Rep < Reps; Rep++) + { + PatBlt((Rep & 0x100) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, 0, 0, + PerfInfo->WndWidth, PerfInfo->WndHeight, PATCOPY); + } +} + +void +FillSmallProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ +#define SMALL_SIZE 16 + unsigned Rep; + unsigned x, y; + + x = 0; + y = 0; + + for (Rep = 0; Rep < Reps; Rep++) + { + PatBlt((Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, x, y, + SMALL_SIZE, SMALL_SIZE, PATCOPY); + x += SMALL_SIZE + 1; + if (PerfInfo->WndWidth < x + SMALL_SIZE) + { + x = 0; + y += SMALL_SIZE + 1; + if (PerfInfo->WndHeight < y + SMALL_SIZE) + { + y = 0; + } + } + } +} +/* EOF */ diff --git a/reactos/apps/utils/rosperf/lines.c b/reactos/apps/utils/rosperf/lines.c new file mode 100644 index 00000000000..14824c950ab --- /dev/null +++ b/reactos/apps/utils/rosperf/lines.c @@ -0,0 +1,97 @@ +/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "rosperf.h" + +void +LinesProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + int Dest; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (Dest = 2; Dest < PerfInfo->WndHeight && Rep < Reps; Rep++, Dest += 2) + { + MoveToEx(Dc, 0, 0, NULL); + LineTo(Dc, PerfInfo->WndWidth, Dest); + } + + for (Dest = PerfInfo->WndWidth - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2) + { + MoveToEx(Dc, PerfInfo->WndWidth, 0, NULL); + LineTo(Dc, Dest, PerfInfo->WndHeight); + } + + for (Dest = PerfInfo->WndHeight - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2) + { + MoveToEx(Dc, PerfInfo->WndWidth, PerfInfo->WndHeight, NULL); + LineTo(Dc, 0, Dest); + } + + for (Dest = 2; Dest < PerfInfo->WndWidth && Rep < Reps; Rep++, Dest += 2) + { + MoveToEx(Dc, 0, PerfInfo->WndHeight, NULL); + LineTo(Dc, Dest, 0); + } + } +} + +void +LinesHorizontalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + unsigned y; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (y = 0; y < PerfInfo->WndHeight && Rep < Reps; Rep++, y += 3) + { + MoveToEx(Dc, 0, y, NULL); + LineTo(Dc, PerfInfo->WndWidth, y); + } + } +} + +void +LinesVerticalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + unsigned x; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (x = 0; x < PerfInfo->WndWidth && Rep < Reps; Rep++, x += 3) + { + MoveToEx(Dc, x, 0, NULL); + LineTo(Dc, x, PerfInfo->WndHeight); + } + } +} + +/* EOF */ diff --git a/reactos/apps/utils/rosperf/rosperf.c b/reactos/apps/utils/rosperf/rosperf.c new file mode 100644 index 00000000000..de47d6bec84 --- /dev/null +++ b/reactos/apps/utils/rosperf/rosperf.c @@ -0,0 +1,923 @@ +/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Ideas copied from x11perf: + * + * Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "rosperf.h" + +#define MAINWND_WIDTH 400 +#define MAINWND_HEIGHT 400 + +static HWND LabelWnd; + +unsigned +NullInit(void **Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + *Context = NULL; + + return Reps; +} + +void +NullCleanup(void *Context, PPERF_INFO PerfInfo) +{ +} + +static void +ProcessMessages(void) +{ + MSG Msg; + + while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) + { + if (WM_QUIT == Msg.message) + { + exit(Msg.wParam); + } + TranslateMessage(&Msg); + DispatchMessageW(&Msg); + } +} + +static void +ClearWindow(PPERF_INFO PerfInfo) +{ + InvalidateRect(PerfInfo->Wnd, NULL, TRUE); + UpdateWindow(PerfInfo->Wnd); +} + +static unsigned +CalibrateTest(PTEST Test, PPERF_INFO PerfInfo) +{ +#define GOAL 2500 /* Try to get up to 2.5 seconds */ +#define ENOUGH 2000 /* But settle for 2.0 seconds */ +#define TICK 10 /* Assume clock not faster than .01 seconds */ + + unsigned Reps, DidReps; /* Reps desired, reps performed */ + unsigned Exponent; + void *Context; + DWORD StartTick; + DWORD Duration; + + /* Attempt to get an idea how long each rep lasts by getting enough + reps to last more than ENOUGH. Then scale that up to the number of + seconds desired. + + If init call to test ever fails, return False and test will be skipped. + */ + + Reps = 1; + for (;;) + { + ClearWindow(PerfInfo); + DidReps = (*Test->Init)(&Context, PerfInfo, Reps); + ProcessMessages(); + if (0 == DidReps) + { + return 0; + } + StartTick = GetTickCount(); + (*Test->Proc)(Context, PerfInfo, Reps); + Duration = GetTickCount() - StartTick; + (*Test->PassCleanup) (Context, PerfInfo); + (*Test->Cleanup)(Context, PerfInfo); + ProcessMessages(); + + if (DidReps != Reps) + { + /* The test can't do the number of reps as we asked for. + Give up */ + return DidReps; + } + /* Did we go long enough? */ + if (ENOUGH <= Duration) + { + break; + } + + /* Don't let too short a clock make new reps wildly high */ + if (Duration <= TICK) + { + Reps *= 10; + } + else + { + /* Try to get up to GOAL seconds. */ + Reps = (int)(GOAL * (double) Reps / (double) Duration) + 1; + } + } + + Reps = (int) ((double) PerfInfo->Seconds * 1000.0 * (double) Reps / (double) Duration) + 1; + + /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking + numbers of repetitions. */ + Reps--; + Exponent = 1; + while (9 < Reps) + { + Reps /= 10; + Exponent *= 10; + } + Reps = (Reps + 1) * Exponent; + + return Reps; +} + +static void +DisplayStatus(HWND Label, LPCWSTR Message, LPCWSTR Test, int Try) +{ + WCHAR Status[128]; + + snwprintf(Status, sizeof(Status) / sizeof(Status[0]), L"%d %s %s", Try, Message, Test); + SetWindowTextW(Label, Status); + InvalidateRect(Label, NULL, TRUE); + UpdateWindow(Label); +} + +static double +RoundTo3Digits(double d) +{ + /* It's kind of silly to print out things like ``193658.4/sec'' so just + junk all but 3 most significant digits. */ + + double exponent, sign; + + exponent = 1.0; + /* the code below won't work if d should happen to be non-positive. */ + if (d < 0.0) + { + d = -d; + sign = -1.0; + } + else + { + sign = 1.0; + } + + if (1000.0 <= d) + { + do + { + exponent *= 10.0; + } + while (1000.0 <= d / exponent); + d = (double)((int)(d / exponent + 0.5)); + d *= exponent; + } + else + { + if (0.0 != d) + { + while (d * exponent < 100.0) + { + exponent *= 10.0; + } + } + d = (double)((int)(d * exponent + 0.5)); + d /= exponent; + } + + return d * sign; +} + +static void +ReportTimes(DWORD Time, int Reps, LPCWSTR Label, BOOL Average) +{ + double MSecsPerObj, ObjsPerSec; + + if (0 != Time) + { + MSecsPerObj = (double) Time / (double) Reps; + ObjsPerSec = (double) Reps * 1000.0 / (double) Time; + + /* Round obj/sec to 3 significant digits. Leave msec untouched, to + allow averaging results from several repetitions. */ + ObjsPerSec = RoundTo3Digits(ObjsPerSec); + + wprintf(L"%7d %s @ %8.4f msec (%8.1f/sec): %s\n", + Reps, Average ? L"trep" : L"reps", MSecsPerObj, ObjsPerSec, Label); + } + else + { + wprintf(L"%6d %sreps @ 0.0 msec (unmeasurably fast): %s\n", + Reps, Average ? L"t" : L"", Label); + } + +} + +static void +ProcessTest(PTEST Test, PPERF_INFO PerfInfo) +{ + unsigned Reps; + unsigned Repeat; + void *Context; + DWORD StartTick; + DWORD Time, TotalTime; + + DisplayStatus(LabelWnd, L"Calibrating", Test->Label, 0); + Reps = CalibrateTest(Test, PerfInfo); + if (0 == Reps) + { + return; + } + + Reps = Test->Init(&Context, PerfInfo, Reps); + if (0 == Reps) + { + return; + } + TotalTime = 0; + for (Repeat = 0; Repeat < PerfInfo->Repeats; Repeat++) + { + DisplayStatus(LabelWnd, L"Testing", Test->Label, Repeat + 1); + ClearWindow(PerfInfo); + StartTick = GetTickCount(); + (*Test->Proc)(Context, PerfInfo, Reps); + Time = GetTickCount() - StartTick; + ProcessMessages(); + TotalTime += Time; + ReportTimes(Time, Reps, Test->Label, FALSE); + (*Test->PassCleanup)(Context, PerfInfo); + ProcessMessages(); + } + (*Test->Cleanup)(Context, PerfInfo); + ReportTimes(TotalTime, Repeat * Reps, Test->Label, TRUE); + ProcessMessages(); +} + +static void +PrintOSVersion(void) +{ +#define BUFSIZE 160 + OSVERSIONINFOEXW VersionInfo; + BOOL OsVersionInfoEx; + HKEY hKey; + WCHAR ProductType[BUFSIZE]; + DWORD BufLen; + LONG Ret; + unsigned RosVersionLen; + LPWSTR RosVersion; + + /* Try calling GetVersionEx using the OSVERSIONINFOEX structure. + * If that fails, try using the OSVERSIONINFO structure. */ + + ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFOEXW)); + VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + + OsVersionInfoEx = GetVersionExW((OSVERSIONINFOW *) &VersionInfo); + if (! OsVersionInfoEx) + { + VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionExW((OSVERSIONINFOW *) &VersionInfo)) + { + return; + } + } + + RosVersion = VersionInfo.szCSDVersion + wcslen(VersionInfo.szCSDVersion) + 1; + RosVersionLen = sizeof(VersionInfo.szCSDVersion) / sizeof(VersionInfo.szCSDVersion[0]) - + (RosVersion - VersionInfo.szCSDVersion); + if (7 <= RosVersionLen && 0 == wcsnicmp(RosVersion, L"ReactOS", 7)) + { + wprintf(L"Running on %s\n", RosVersion); + return; + } + + switch (VersionInfo.dwPlatformId) + { + /* Test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + + /* Test for the specific product. */ + if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows Server 2003, "); + } + else if (5 == VersionInfo.dwMajorVersion && 1 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows XP "); + } + else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 2000 "); + } + else if (VersionInfo.dwMajorVersion <= 4 ) + { + wprintf(L"Running on Microsoft Windows NT "); + } + + /* Test for specific product on Windows NT 4.0 SP6 and later. */ + if (OsVersionInfoEx) + { + /* Test for the workstation type. */ + if (VER_NT_WORKSTATION == VersionInfo.wProductType) + { + if (4 == VersionInfo.dwMajorVersion) + { + wprintf(L"Workstation 4.0 "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_PERSONAL)) + { + wprintf(L"Home Edition "); + } + else + { + wprintf(L"Professional "); + } + } + + /* Test for the server type. */ + else if (VER_NT_SERVER == VersionInfo.wProductType || + VER_NT_DOMAIN_CONTROLLER == VersionInfo.wProductType) + { + if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion) + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER)) + { + wprintf(L"Datacenter Edition "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Enterprise Edition "); + } + else if (VER_SUITE_BLADE == VersionInfo.wSuiteMask) + { + wprintf(L"Web Edition "); + } + else + { + wprintf(L"Standard Edition "); + } + } + + else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER)) + { + wprintf(L"Datacenter Server "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Advanced Server " ); + } + else + { + wprintf(L"Server " ); + } + } + + else /* Windows NT 4.0 */ + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Server 4.0, Enterprise Edition "); + } + else + { + wprintf(L"Server 4.0 "); + } + } + } + } + else /* Test for specific product on Windows NT 4.0 SP5 and earlier */ + { + BufLen = BUFSIZE; + + Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_QUERY_VALUE, &hKey); + if (ERROR_SUCCESS != Ret) + { + return; + } + + Ret = RegQueryValueExW(hKey, L"ProductType", NULL, NULL, + (LPBYTE) ProductType, &BufLen); + if (ERROR_SUCCESS != Ret || BUFSIZE < BufLen) + { + return; + } + + RegCloseKey(hKey); + + if (0 == lstrcmpiW(L"WINNT", ProductType)) + { + wprintf(L"Workstation "); + } + else if (0 == lstrcmpiW(L"LANMANNT", ProductType)) + { + wprintf(L"Server "); + } + else if (0 == lstrcmpiW(L"SERVERNT", ProductType)) + { + wprintf(L"Advanced Server "); + } + + wprintf(L"%d.%d ", VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion); + } + + /* Display service pack (if any) and build number. */ + + if (4 == VersionInfo.dwMajorVersion && + 0 == lstrcmpiW(VersionInfo.szCSDVersion, L"Service Pack 6")) + { + /* Test for SP6 versus SP6a. */ + Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", + 0, KEY_QUERY_VALUE, &hKey); + if (ERROR_SUCCESS == Ret) + { + wprintf(L"Service Pack 6a (Build %d)\n", VersionInfo.dwBuildNumber & 0xFFFF); + } + else /* Windows NT 4.0 prior to SP6a */ + { + wprintf(L"%s (Build %d)\n", + VersionInfo.szCSDVersion, + VersionInfo.dwBuildNumber & 0xFFFF); + } + + RegCloseKey(hKey); + } + else /* not Windows NT 4.0 */ + { + wprintf(L"%s (Build %d)\n", + VersionInfo.szCSDVersion, + VersionInfo.dwBuildNumber & 0xFFFF); + } + + + break; + + /* Test for the Windows Me/98/95. A bit silly since we're using Unicode... */ + case VER_PLATFORM_WIN32_WINDOWS: + + if (4 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 95 "); + if (L'C' == VersionInfo.szCSDVersion[1] || L'B' == VersionInfo.szCSDVersion[1]) + { + wprintf(L"OSR2"); + } + } + + else if (4 == VersionInfo.dwMajorVersion && 10 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 98 "); + if (L'A' == VersionInfo.szCSDVersion[1]) + { + wprintf(L"SE"); + } + } + + else if (4 == VersionInfo.dwMajorVersion && 90 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows Millennium Edition"); + } + wprintf(L"\n"); + break; + + case VER_PLATFORM_WIN32s: /* Even silier... */ + + wprintf(L"Running on Microsoft Win32s\n"); + break; + } +} + +static void +PrintAppVersion(void) +{ + wprintf(L"RosPerf %S (Build %S)\n", KERNEL_VERSION_STR, KERNEL_VERSION_BUILD_STR); +} + +static void +PrintDisplayInfo(void) +{ + HDC Dc; + + Dc = GetDC(NULL); + if (NULL == Dc) + { + return; + } + + wprintf(L"Display settings %d * %d * %d\n", GetDeviceCaps(Dc, HORZRES), + GetDeviceCaps(Dc, VERTRES), GetDeviceCaps(Dc, BITSPIXEL) * GetDeviceCaps(Dc, PLANES)); + + ReleaseDC(NULL, Dc); +} + +static void +PrintStartupInfo(void) +{ + PrintAppVersion(); + PrintOSVersion(); + PrintDisplayInfo(); +} + +static LRESULT CALLBACK +MainWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT Ps; + HDC Dc; + LRESULT Result; + + switch (Msg) + { + case WM_DESTROY: + PostQuitMessage(0); + Result = 0; + break; + + case WM_PAINT: + Dc = BeginPaint(Wnd, &Ps); + EndPaint (Wnd, &Ps); + Result = 0; + break; + + default: + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + } + + return Result; +} + +static LRESULT CALLBACK +LabelWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT Ps; + HDC Dc; + RECT ClientRect, WindowRect; + TEXTMETRICW Tm; + LRESULT Result; + WCHAR Title[80]; + + switch (Msg) + { + case WM_CREATE: + /* Make text fit */ + Dc = GetDC(Wnd); + if (NULL != Dc && GetClientRect(Wnd, &ClientRect) && GetWindowRect(Wnd, &WindowRect) + && GetTextMetricsW(Dc, &Tm)) + { + if (Tm.tmHeight != ClientRect.bottom) + { + SetWindowPos(Wnd, NULL, 0, 0, WindowRect.right - WindowRect.left, + (WindowRect.bottom - WindowRect.top) + (Tm.tmHeight - ClientRect.bottom), + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); + } + } + if (NULL != Dc) + { + ReleaseDC(Wnd, Dc); + } + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + + case WM_PAINT: + Dc = BeginPaint(Wnd, &Ps); + GetWindowTextW(Wnd, Title, sizeof(Title) / sizeof(Title[0])); + TextOutW(Dc, 0, 0, Title, wcslen(Title)); + EndPaint (Wnd, &Ps); + Result = 0; + break; + + default: + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + } + + return Result; +} + +static HWND +CreatePerfWindows(HINSTANCE hInstance, PPERF_INFO PerfInfo) +{ + WNDCLASSW wc; + HWND MainWnd; + + wc.lpszClassName = L"RosPerfMain"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION); + wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = CreateSolidBrush(PerfInfo->BackgroundColor); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClassW(&wc) == 0) + { + fwprintf(stderr, L"Failed to register RosPerfMain (last error %d)\n", + GetLastError()); + return NULL; + } + + wc.lpszClassName = L"RosPerfLabel"; + wc.lpfnWndProc = LabelWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION); + wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClassW(&wc) == 0) + { + fwprintf(stderr, L"Failed to register RosPerfLabel (last error %d)\n", + GetLastError()); + return NULL; + } + + MainWnd = CreateWindowW(L"RosPerfMain", + L"ReactOS performance test", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, + 0, + MAINWND_WIDTH, + MAINWND_HEIGHT, + NULL, + NULL, + hInstance, + NULL); + if (NULL == MainWnd) + { + fwprintf(stderr, L"Failed to create main window (last error %d)\n", + GetLastError()); + return NULL; + } + + LabelWnd = CreateWindowW(L"RosPerfLabel", + L"", + WS_POPUP | WS_THICKFRAME | WS_VISIBLE, + 0, + MAINWND_HEIGHT + 10, + MAINWND_WIDTH, + 20, + MainWnd, + NULL, + hInstance, + NULL); + if (NULL == LabelWnd) + { + fwprintf(stderr, L"Failed to create label window (last error 0x%lX)\n", + GetLastError()); + return NULL; + } + + SetActiveWindow(MainWnd); + + return MainWnd; +} + +static BOOL +ProcessCommandLine(PPERF_INFO PerfInfo, unsigned *TestCount, PTEST *Tests) +{ + int ArgC, Arg; + LPWSTR *ArgV; + LPWSTR EndPtr; + PTEST AllTests; + BOOL *DoTest; + BOOL DoAll; + unsigned AllTestCount, i, j; + + ArgV = CommandLineToArgvW(GetCommandLineW(), &ArgC); + if (NULL == ArgV) + { + fwprintf(stderr, L"CommandLineToArgvW failed\n"); + return FALSE; + } + + GetTests(&AllTestCount, &AllTests); + DoTest = malloc(AllTestCount * sizeof(BOOL)); + if (NULL == DoTest) + { + fwprintf(stderr, L"Out of memory\n"); + return FALSE; + } + DoAll = TRUE; + + for (Arg = 1; Arg < ArgC; Arg++) + { + if (L'/' == ArgV[Arg][0] || L'-' == ArgV[Arg][0]) + { + if (0 == wcsicmp(ArgV[Arg] + 1, L"repeat")) + { + if (ArgC <= Arg + 1) + { + fwprintf(stderr, L"%s needs a repeat count\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + Arg++; + PerfInfo->Repeats = wcstoul(ArgV[Arg], &EndPtr, 0); + if (L'\0' != *EndPtr || (long) PerfInfo->Repeats <= 0 || ULONG_MAX == PerfInfo->Repeats) + { + fwprintf(stderr, L"Invalid repeat count %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else if (0 == wcsicmp(ArgV[Arg] + 1, L"seconds")) + { + if (ArgC <= Arg + 1) + { + fwprintf(stderr, L"%s needs a number of seconds\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + Arg++; + PerfInfo->Seconds = wcstoul(ArgV[Arg], &EndPtr, 0); + if (L'\0' != *EndPtr || (long) PerfInfo->Seconds < 0 || ULONG_MAX == PerfInfo->Seconds) + { + fwprintf(stderr, L"Invalid duration %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else + { + fwprintf(stderr, L"Unrecognized option %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else + { + if (DoAll) + { + for (i = 0; i < AllTestCount; i++) + { + DoTest[i] = FALSE; + } + DoAll = FALSE; + } + for (i = 0; i < AllTestCount; i++) + { + if (0 == wcsicmp(ArgV[Arg], AllTests[i].Option)) + { + DoTest[i] = TRUE; + break; + } + } + if (AllTestCount <= i) + { + fwprintf(stderr, L"Unrecognized test %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + } + + GlobalFree(ArgV); + + if (DoAll) + { + for (i = 0; i < AllTestCount; i++) + { + DoTest[i] = TRUE; + } + } + + *TestCount = 0; + for (i = 0; i < AllTestCount; i++) + { + if (DoTest[i]) + { + (*TestCount)++; + } + } + *Tests = malloc(*TestCount * sizeof(TEST)); + if (NULL == *Tests) + { + fwprintf(stderr, L"Out of memory\n"); + free(DoTest); + return FALSE; + } + j = 0; + for (i = 0; i < AllTestCount; i++) + { + if (DoTest[i]) + { + (*Tests)[j] = AllTests[i]; + j++; + } + } + free(DoTest); + + return TRUE; +} + +int WINAPI +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + PTEST Tests; + unsigned TestCount; + unsigned CurrentTest; + RECT Rect; + PERF_INFO PerfInfo; + + PrintStartupInfo(); + + PerfInfo.Seconds = 15; + PerfInfo.Repeats = 4; + PerfInfo.ForegroundColor = RGB(0, 0, 0); + PerfInfo.BackgroundColor = RGB(255, 255, 255); + + if (! ProcessCommandLine(&PerfInfo, &TestCount, &Tests)) + { + exit(1); + } + + PerfInfo.Wnd = CreatePerfWindows(hInstance, &PerfInfo); + if (NULL == PerfInfo.Wnd) + { + exit(1); + } + + GetClientRect(PerfInfo.Wnd, &Rect); + PerfInfo.WndWidth = Rect.right - Rect.left; + PerfInfo.WndHeight = Rect.bottom - Rect.top; + PerfInfo.ForegroundDc = GetDC(PerfInfo.Wnd); + PerfInfo.BackgroundDc = GetDC(PerfInfo.Wnd); + if (NULL == PerfInfo.ForegroundDc || NULL == PerfInfo.BackgroundDc) + { + fwprintf(stderr, L"Failed to create device contexts (last error %d)\n", + GetLastError()); + exit(1); + } + SelectObject(PerfInfo.ForegroundDc, CreateSolidBrush(PerfInfo.ForegroundColor)); + SelectObject(PerfInfo.ForegroundDc, CreatePen(PS_SOLID, 0, PerfInfo.ForegroundColor)); + SelectObject(PerfInfo.BackgroundDc, CreateSolidBrush(PerfInfo.BackgroundColor)); + SelectObject(PerfInfo.BackgroundDc, CreatePen(PS_SOLID, 0, PerfInfo.BackgroundColor)); + + ProcessMessages(); + + /* Move cursor out of the way */ + GetWindowRect(LabelWnd, &Rect); + SetCursorPos(Rect.right, Rect.bottom); + + for (CurrentTest = 0; CurrentTest < TestCount; CurrentTest++) + { + wprintf(L"\n"); + ProcessTest(Tests + CurrentTest, &PerfInfo); + } + + GlobalFree(Tests); + + return 0; +} + +/* EOF */ diff --git a/reactos/apps/utils/rosperf/rosperf.h b/reactos/apps/utils/rosperf/rosperf.h new file mode 100644 index 00000000000..4eb1144a797 --- /dev/null +++ b/reactos/apps/utils/rosperf/rosperf.h @@ -0,0 +1,64 @@ +/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef ROSPERF_H_INCLUDED +#define ROSPERF_H_INCLUDED + +typedef struct tagPERF_INFO +{ + HWND Wnd; + unsigned Seconds; + unsigned Repeats; + COLORREF ForegroundColor; + COLORREF BackgroundColor; + HDC ForegroundDc; + HDC BackgroundDc; + ULONG WndWidth; + ULONG WndHeight; +} PERF_INFO, *PPERF_INFO; + +typedef unsigned (*INITTESTPROC)(void **Context, PPERF_INFO PerfInfo, unsigned Reps); +typedef void (*TESTPROC)(void *Context, PPERF_INFO PerfInfo, unsigned Reps); +typedef void (*CLEANUPTESTPROC)(void *Context, PPERF_INFO PerfInfo); + +typedef struct tagTEST +{ + LPCWSTR Option; + LPCWSTR Label; + INITTESTPROC Init; + TESTPROC Proc; + CLEANUPTESTPROC PassCleanup; + CLEANUPTESTPROC Cleanup; +} TEST, *PTEST; + +void GetTests(unsigned *TestCount, PTEST *Tests); + +/* Tests */ +unsigned NullInit(void **Context, PPERF_INFO PerfInfo, unsigned Reps); +void NullCleanup(void *Context, PPERF_INFO PerfInfo); + +void FillProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps); +void FillSmallProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps); + +void LinesHorizontalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps); +void LinesVerticalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps); +void LinesProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps); + +#endif /* ROSPERF_H_INCLUDED */ + +/* EOF */ diff --git a/reactos/apps/utils/rosperf/rosperf.rc b/reactos/apps/utils/rosperf/rosperf.rc new file mode 100644 index 00000000000..26841ca1d03 --- /dev/null +++ b/reactos/apps/utils/rosperf/rosperf.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS performance tester\0" +#define REACTOS_STR_INTERNAL_NAME "rosperf\0" +#define REACTOS_STR_ORIGINAL_FILENAME "rosperf.exe\0" +#include diff --git a/reactos/apps/utils/rosperf/testlist.c b/reactos/apps/utils/rosperf/testlist.c new file mode 100644 index 00000000000..6b86e7d7ea1 --- /dev/null +++ b/reactos/apps/utils/rosperf/testlist.c @@ -0,0 +1,39 @@ +/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "rosperf.h" + +static TEST TestList[] = + { + { L"fill", L"Fill", NullInit, FillProc, NullCleanup, NullCleanup }, + { L"smallfill", L"Small Fill", NullInit, FillSmallProc, NullCleanup, NullCleanup }, + { L"hlines", L"Horizontal Lines", NullInit, LinesHorizontalProc, NullCleanup, NullCleanup }, + { L"vlines", L"Vertical Lines", NullInit, LinesVerticalProc, NullCleanup, NullCleanup }, + { L"lines", L"Lines", NullInit, LinesProc, NullCleanup, NullCleanup } + }; + + +void +GetTests(unsigned *TestCount, PTEST *Tests) + { + *TestCount = sizeof(TestList) / sizeof(TEST); + *Tests = TestList; + } + +/* EOF */ diff --git a/reactos/apps/utils/shutdown/shutdown.c b/reactos/apps/utils/shutdown/shutdown.c index 2f999898d1f..4bec4789434 100644 --- a/reactos/apps/utils/shutdown/shutdown.c +++ b/reactos/apps/utils/shutdown/shutdown.c @@ -146,7 +146,6 @@ _tmain(int argc, TCHAR *argv[]) if (! AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0) || ERROR_SUCCESS != GetLastError()) { - CloseHandle(hToken); if (ERROR_NOT_ALL_ASSIGNED == GetLastError()) { _ftprintf(stderr, _T("You are not authorized to shutdown the system\n")); @@ -155,6 +154,7 @@ _tmain(int argc, TCHAR *argv[]) { _ftprintf(stderr, _T("AdjustTokenPrivileges failed with error %d\n"), (int) GetLastError()); } + CloseHandle(hToken); exit(1); } CloseHandle(hToken); diff --git a/reactos/apps/utils/tickcount/makefile b/reactos/apps/utils/tickcount/makefile index 9e8a3e042fb..37fd9534e7a 100644 --- a/reactos/apps/utils/tickcount/makefile +++ b/reactos/apps/utils/tickcount/makefile @@ -12,7 +12,7 @@ TARGET_SDKLIBS = kernel32.a TARGET_OBJECTS = tickcount.o -TARGET_CFLAGS = -Wall -Werror +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/apps/utils/tickcount/tickcount.c b/reactos/apps/utils/tickcount/tickcount.c index d64a515fb96..9ee52a43e0e 100644 --- a/reactos/apps/utils/tickcount/tickcount.c +++ b/reactos/apps/utils/tickcount/tickcount.c @@ -1,30 +1,32 @@ /* $Id$ */ /* - tickcount -- Display the kernel tick count in human-readable format + tickcount -- Display the kernel tick count (or any tick count passed as an + argument or as input) in human-readable format This is public domain software */ #include #include +#include #include #include -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; +typedef __int64 int64_; +typedef unsigned __int64 uint64_; -#define TICKS_YEAR (TICKS_DAY * ((uint64_t)365)) -#define TICKS_MONTH (TICKS_DAY * ((uint64_t)30)) -#define TICKS_WEEK (TICKS_DAY * ((uint64_t)7)) -#define TICKS_DAY (TICKS_HOUR * ((uint64_t)24)) -#define TICKS_HOUR (TICKS_MINUTE * ((uint64_t)60)) -#define TICKS_MINUTE (TICKS_SECOND * ((uint64_t)60)) -#define TICKS_SECOND ((uint64_t)1000) +#define TICKS_YEAR (TICKS_DAY * ((uint64_)365)) +#define TICKS_MONTH (TICKS_DAY * ((uint64_)30)) +#define TICKS_WEEK (TICKS_DAY * ((uint64_)7)) +#define TICKS_DAY (TICKS_HOUR * ((uint64_)24)) +#define TICKS_HOUR (TICKS_MINUTE * ((uint64_)60)) +#define TICKS_MINUTE (TICKS_SECOND * ((uint64_)60)) +#define TICKS_SECOND ((uint64_)1000) #define SLICES_COUNT (sizeof(ticks_per_slice) / sizeof(ticks_per_slice[0])) -uint64_t ticks_per_slice[] = +uint64_ ticks_per_slice[] = { TICKS_YEAR, TICKS_MONTH, @@ -36,7 +38,7 @@ uint64_t ticks_per_slice[] = 1 }; -_TCHAR * slice_names_singular[] = +_TCHAR * slice_names_singular[SLICES_COUNT] = { _T("year"), _T("month"), @@ -48,7 +50,7 @@ _TCHAR * slice_names_singular[] = _T("millisecond") }; -_TCHAR * slice_names_plural[] = +_TCHAR * slice_names_plural[SLICES_COUNT] = { _T("years"), _T("months"), @@ -62,16 +64,16 @@ _TCHAR * slice_names_plural[] = void print_uptime ( - uint64_t tickcount, - uint64_t prevsliceval, + uint64_ tickcount, + uint64_ prevsliceval, _TCHAR * prevsliceunit, int curslice ) { - uint64_t tick_cur = tickcount / ticks_per_slice[curslice]; - uint64_t tick_residual = tickcount % ticks_per_slice[curslice]; + uint64_ tick_cur = tickcount / ticks_per_slice[curslice]; + uint64_ tick_residual = tickcount % ticks_per_slice[curslice]; - assert(tick_cur <= (~((uint64_t)0))); + assert(tick_cur <= (~((uint64_)0))); if(tick_residual == 0) { @@ -134,9 +136,56 @@ void print_uptime } } -int _tmain() +int parse_print(const _TCHAR * str) { - print_uptime((uint64_t)GetTickCount(), 0, NULL, 0); + int64_ tickcount; + + tickcount = _ttoi64(str); + + if(tickcount < 0) + tickcount = - tickcount; + else if(tickcount == 0) + return 1; + + print_uptime(tickcount, 0, NULL, 0); _puttc(_T('\n'), stdout); + + return 0; +} + +int _tmain(int argc, _TCHAR * argv[]) +{ + int r; + + if(argc <= 1) + { + print_uptime((uint64_)GetTickCount(), 0, NULL, 0); + _puttc(_T('\n'), stdout); + } + else if(argc == 2 && argv[1][0] == _T('-') && argv[1][1] == 0) + { + while(!feof(stdin)) + { + _TCHAR buf[23]; + _TCHAR * str; + + str = _fgetts(buf, 22, stdin); + + if(str == NULL) + return 0; + + if((r = parse_print(str)) != 0) + return r; + } + } + else + { + int i; + + for(i = 1; i < argc; ++ i) + if((r = parse_print(argv[i])) != 0) + return r; + } + return 0; } diff --git a/reactos/baseaddress.cfg b/reactos/baseaddress.cfg index ef506fde45f..1d8b8b6168a 100644 --- a/reactos/baseaddress.cfg +++ b/reactos/baseaddress.cfg @@ -88,9 +88,9 @@ TARGET_BASE_LIB_VERSION =0x77a90000 TARGET_BASE_LIB_ADVAPI32 =0x77dc0000 TARGET_BASE_LIB_USER32 =0x77e60000 TARGET_BASE_LIB_GDI32 =0x77ed0000 -TARGET_BASE_LIB_DNSAPI =0x78000000 +TARGET_BASE_LIB_DNSAPI =0x77f00000 TARGET_BASE_LIB_MSVCRT =0x78000000 -TARGET_BASE_LIB_MSVCRT20 =0x78000000 +TARGET_BASE_LIB_MSVCRT20 =0x78500000 TARGET_BASE_LIB_EXPAT =0x79000000 TARGET_BASE_LIB_KERNEL32 =0x7C800000 TARGET_BASE_LIB_NTDLL =0x7C900000 diff --git a/reactos/boot/freeldr/freeldr/CHANGELOG b/reactos/boot/freeldr/freeldr/CHANGELOG index 7b1a3de91b0..d232950622b 100644 --- a/reactos/boot/freeldr/freeldr/CHANGELOG +++ b/reactos/boot/freeldr/freeldr/CHANGELOG @@ -1,3 +1,9 @@ +Changes in v2.0.0 (02/07/2005) (alex ionesco) + +- PE loading of ntoskrnl.exe +- Work on 3GB support +- w32api conversion + Changes in v1.8.26 (10/30/2004) (chorns) - Print stack frames on crashes. diff --git a/reactos/boot/freeldr/freeldr/Makefile b/reactos/boot/freeldr/freeldr/Makefile index 13612b2d29d..b44ba98a800 100644 --- a/reactos/boot/freeldr/freeldr/Makefile +++ b/reactos/boot/freeldr/freeldr/Makefile @@ -83,7 +83,7 @@ setup_loader : setupldr.sys $(CP) setupldr.sys $(BOOTCD_DIR)/disk/loader/setupldr.sys -COMPILER_OPTIONS = -Wall -Werror -nostdlib -nostdinc -ffreestanding -fno-builtin -fno-inline \ +COMPILER_OPTIONS = -Wall -Werror -nostdlib -ffreestanding -fno-builtin -fno-inline \ -fno-zero-initialized-in-bss -O1 -MD # FreeLoader does not use any of the standard libraries, includes, or built-in functions @@ -95,7 +95,7 @@ endif COMPILER_DEFINES = -D__$(TARGET)__ $(COMPILER_DEBUG_DEFINES) -COMPILER_INCLUDES = -I$(SRCDIR)/include +COMPILER_INCLUDES = -I$(SRCDIR)/include -I$(PATH_TO_TOP)/w32api/include -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include CFLAGS = $(COMPILER_OPTIONS) \ $(COMPILER_DEFINES) \ @@ -262,9 +262,9 @@ all : freeldr.sys setupldr.sys @echo Make ALL done. -freeldr.sys : $(ALL_OBJS) +freeldr.sys : $(ALL_OBJS) $(PATH_TO_TOP)/dk/w32/lib/librossym.a @echo ===================================================== LINKING $@ - @$(LD) $(LFLAGS) -o freeldr.exe $(F_OBJS) + @$(LD) $(LFLAGS) -o freeldr.exe $(F_OBJS) $(PATH_TO_TOP)/dk/w32/lib/librossym.a ifeq ($(FULL_MAP),yes) @$(OBJDUMP) -d -S freeldr.exe > freeldr.map else diff --git a/reactos/boot/freeldr/freeldr/arch/i386/archmach.c b/reactos/boot/freeldr/freeldr/arch/i386/archmach.c index ad503bd2e05..347d8f56e22 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/archmach.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/archmach.c @@ -29,14 +29,14 @@ VOID MachInit(VOID) { - U32 PciId; + ULONG PciId; memset(&MachVtbl, 0, sizeof(MACHVTBL)); /* Check for Xbox by identifying device at PCI 0:0:0, if it's * 0x10de/0x02a5 then we're running on an Xbox */ - WRITE_PORT_ULONG((U32*) 0xcf8, CONFIG_CMD(0, 0, 0)); - PciId = READ_PORT_ULONG((U32*) 0xcfc); + WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0)); + PciId = READ_PORT_ULONG((ULONG*) 0xcfc); if (0x02a510de == PciId) { XboxMachInit(); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c index afb2a376baf..71876f10abf 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hardware.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hardware.c @@ -89,96 +89,43 @@ #define CONTROLLER_TIMEOUT 250 -typedef struct _CM_INT13_DRIVE_PARAMETER -{ - U16 DriveSelect; - U32 MaxCylinders; - U16 SectorsPerTrack; - U16 MaxHeads; - U16 NumberDrives; -} CM_INT13_DRIVE_PARAMETER, *PCM_INT13_DRIVE_PARAMETER; - - typedef struct _CM_DISK_GEOMETRY_DEVICE_DATA { - U32 BytesPerSector; - U32 NumberOfCylinders; - U32 SectorsPerTrack; - U32 NumberOfHeads; + ULONG BytesPerSector; + ULONG NumberOfCylinders; + ULONG SectorsPerTrack; + ULONG NumberOfHeads; } CM_DISK_GEOMETRY_DEVICE_DATA, *PCM_DISK_GEOMETRY_DEVICE_DATA; typedef struct _CM_PNP_BIOS_DEVICE_NODE { - U16 Size; - U8 Node; - U32 ProductId; - U8 DeviceType[3]; - U16 DeviceAttributes; + USHORT Size; + UCHAR Node; + ULONG ProductId; + UCHAR DeviceType[3]; + USHORT DeviceAttributes; } __attribute__((packed)) CM_PNP_BIOS_DEVICE_NODE, *PCM_PNP_BIOS_DEVICE_NODE; typedef struct _CM_PNP_BIOS_INSTALLATION_CHECK { - U8 Signature[4]; - U8 Revision; - U8 Length; - U16 ControlField; - U8 Checksum; - U32 EventFlagAddress; - U16 RealModeEntryOffset; - U16 RealModeEntrySegment; - U16 ProtectedModeEntryOffset; - U32 ProtectedModeCodeBaseAddress; - U32 OemDeviceId; - U16 RealModeDataBaseAddress; - U32 ProtectedModeDataBaseAddress; + UCHAR Signature[4]; + UCHAR Revision; + UCHAR Length; + USHORT ControlField; + UCHAR Checksum; + ULONG EventFlagAddress; + USHORT RealModeEntryOffset; + USHORT RealModeEntrySegment; + USHORT ProtectedModeEntryOffset; + ULONG ProtectedModeCodeBaseAddress; + ULONG OemDeviceId; + USHORT RealModeDataBaseAddress; + ULONG ProtectedModeDataBaseAddress; } __attribute__((packed)) CM_PNP_BIOS_INSTALLATION_CHECK, *PCM_PNP_BIOS_INSTALLATION_CHECK; -typedef struct _CM_SERIAL_DEVICE_DATA -{ - U16 Version; - U16 Revision; - U32 BaudClock; -} __attribute__((packed)) CM_SERIAL_DEVICE_DATA, *PCM_SERIAL_DEVICE_DATA; - - -typedef struct _CM_FLOPPY_DEVICE_DATA -{ - U16 Version; - U16 Revision; - CHAR Size[8]; - U32 MaxDensity; - U32 MountDensity; - - /* Version 2.0 data */ - U8 StepRateHeadUnloadTime; - U8 HeadLoadTime; - U8 MotorOffTime; - U8 SectorLengthCode; - U8 SectorPerTrack; - U8 ReadWriteGapLength; - U8 DataTransferLength; - U8 FormatGapLength; - U8 FormatFillCharacter; - U8 HeadSettleTime; - U8 MotorSettleTime; - U8 MaximumTrackValue; - U8 DataTransferRate; -} __attribute__((packed)) CM_FLOPPY_DEVICE_DATA, *PCM_FLOPPY_DEVICE_DATA; - - -typedef struct _CM_KEYBOARD_DEVICE_DATA -{ - U16 Version; - U16 Revision; - U8 Type; - U8 Subtype; - U16 KeyboardFlags; -} __attribute__((packed)) CM_KEYBOARD_DEVICE_DATA, *PCM_KEYBOARD_DEVICE_DATA; - - static char Hex[] = "0123456789ABCDEF"; static unsigned int delay_count = 1; @@ -187,28 +134,28 @@ static unsigned int delay_count = 1; static VOID -__KeStallExecutionProcessor(U32 Loops) +__StallExecutionProcessor(ULONG Loops) { register unsigned int i; for (i = 0; i < Loops; i++); } -VOID KeStallExecutionProcessor(U32 Microseconds) +VOID StallExecutionProcessor(ULONG Microseconds) { - U64 LoopCount = ((U64)delay_count * (U64)Microseconds) / 1000ULL; - __KeStallExecutionProcessor((U32)LoopCount); + ULONGLONG LoopCount = ((ULONGLONG)delay_count * (ULONGLONG)Microseconds) / 1000ULL; + __StallExecutionProcessor((ULONG)LoopCount); } -static U32 +static ULONG Read8254Timer(VOID) { - U32 Count; + ULONG Count; - WRITE_PORT_UCHAR((PU8)0x43, 0x00); - Count = READ_PORT_UCHAR((PU8)0x40); - Count |= READ_PORT_UCHAR((PU8)0x40) << 8; + WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00); + Count = READ_PORT_UCHAR((PUCHAR)0x40); + Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8; return Count; } @@ -217,9 +164,9 @@ Read8254Timer(VOID) static VOID WaitFor8254Wraparound(VOID) { - U32 CurCount; - U32 PrevCount = ~0; - S32 Delta; + ULONG CurCount; + ULONG PrevCount = ~0; + LONG Delta; CurCount = Read8254Timer(); @@ -242,14 +189,14 @@ WaitFor8254Wraparound(VOID) VOID HalpCalibrateStallExecution(VOID) { - U32 i; - U32 calib_bit; - U32 CurCount; + ULONG i; + ULONG calib_bit; + ULONG CurCount; /* Initialise timer interrupt with MILLISECOND ms interval */ - WRITE_PORT_UCHAR((PU8)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ - WRITE_PORT_UCHAR((PU8)0x40, LATCH & 0xff); /* LSB */ - WRITE_PORT_UCHAR((PU8)0x40, LATCH >> 8); /* MSB */ + WRITE_PORT_UCHAR((PUCHAR)0x43, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ + WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH & 0xff); /* LSB */ + WRITE_PORT_UCHAR((PUCHAR)0x40, LATCH >> 8); /* MSB */ /* Stage 1: Coarse calibration */ @@ -262,7 +209,7 @@ HalpCalibrateStallExecution(VOID) WaitFor8254Wraparound(); - __KeStallExecutionProcessor(delay_count); /* Do the delay */ + __StallExecutionProcessor(delay_count); /* Do the delay */ CurCount = Read8254Timer(); } while (CurCount > LATCH / 2); @@ -281,7 +228,7 @@ HalpCalibrateStallExecution(VOID) WaitFor8254Wraparound(); - __KeStallExecutionProcessor(delay_count); /* Do the delay */ + __StallExecutionProcessor(delay_count); /* Do the delay */ CurCount = Read8254Timer(); if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ @@ -294,13 +241,13 @@ HalpCalibrateStallExecution(VOID) VOID -SetComponentInformation(HKEY ComponentKey, - U32 Flags, - U32 Key, - U32 Affinity) +SetComponentInformation(FRLDRHKEY ComponentKey, + ULONG Flags, + ULONG Key, + ULONG Affinity) { CM_COMPONENT_INFORMATION CompInfo; - S32 Error; + LONG Error; CompInfo.Flags = Flags; CompInfo.Version = 0; @@ -311,7 +258,7 @@ SetComponentInformation(HKEY ComponentKey, Error = RegSetValue(ComponentKey, "Component Information", REG_BINARY, - (PU8)&CompInfo, + (PUCHAR)&CompInfo, sizeof(CM_COMPONENT_INFORMATION)); if (Error != ERROR_SUCCESS) { @@ -321,23 +268,23 @@ SetComponentInformation(HKEY ComponentKey, static VOID -DetectPnpBios(HKEY SystemKey, U32 *BusNumber) +DetectPnpBios(FRLDRHKEY SystemKey, ULONG *BusNumber) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PNP_BIOS_DEVICE_NODE DeviceNode; PCM_PNP_BIOS_INSTALLATION_CHECK InstData; char Buffer[80]; - HKEY BusKey; - U32 x; - U32 NodeSize = 0; - U32 NodeCount = 0; - U8 NodeNumber; - U32 FoundNodeCount; + FRLDRHKEY BusKey; + ULONG x; + ULONG NodeSize = 0; + ULONG NodeCount = 0; + UCHAR NodeNumber; + ULONG FoundNodeCount; int i; - U32 PnpBufferSize; - U32 Size; + ULONG PnpBufferSize; + ULONG Size; char *Ptr; - S32 Error; + LONG Error; InstData = (PCM_PNP_BIOS_INSTALLATION_CHECK)PnpBiosSupported(); if (InstData == NULL || strncmp(InstData->Signature, "$PnP", 4)) @@ -351,6 +298,9 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) x = PnpBiosGetDeviceNodeCount(&NodeSize, &NodeCount); + NodeCount &= 0xFF; // needed since some fscked up BIOSes return + // wrong info (e.g. Mac Virtual PC) + // e.g. look: http://my.execpc.com/~geezer/osd/pnp/pnp16.c if (x != 0 || NodeSize == 0 || NodeCount == 0) { DbgPrint((DPRINT_HWDETECT, "PnP-BIOS failed to enumerate device nodes\n")); @@ -385,7 +335,7 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BusKey, "Identifier", REG_SZ, - (PU8)"PNP BIOS", + (PUCHAR)"PNP BIOS", 9); if (Error != ERROR_SUCCESS) { @@ -425,7 +375,7 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) PnpBufferSize = sizeof(CM_PNP_BIOS_INSTALLATION_CHECK); for (i = 0; i < 0xFF; i++) { - NodeNumber = (U8)i; + NodeNumber = (UCHAR)i; x = PnpBiosGetDeviceNode(&NodeNumber, (PVOID)DISKREADBUFFER); if (x == 0) @@ -463,7 +413,7 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BusKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -477,15 +427,15 @@ DetectPnpBios(HKEY SystemKey, U32 *BusNumber) static VOID -SetHarddiskConfigurationData(HKEY DiskKey, - U32 DriveNumber) +SetHarddiskConfigurationData(FRLDRHKEY DiskKey, + ULONG DriveNumber) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry; EXTENDED_GEOMETRY ExtGeometry; GEOMETRY Geometry; - U32 Size; - S32 Error; + ULONG Size; + LONG Error; /* Set 'Configuration Data' value */ Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + @@ -545,7 +495,7 @@ SetHarddiskConfigurationData(HKEY DiskKey, Error = RegSetValue(DiskKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -558,16 +508,16 @@ SetHarddiskConfigurationData(HKEY DiskKey, static VOID -SetHarddiskIdentifier(HKEY DiskKey, - U32 DriveNumber) +SetHarddiskIdentifier(FRLDRHKEY DiskKey, + ULONG DriveNumber) { PMASTER_BOOT_RECORD Mbr; - U32 *Buffer; - U32 i; - U32 Checksum; - U32 Signature; + ULONG *Buffer; + ULONG i; + ULONG Checksum; + ULONG Signature; char Identifier[20]; - S32 Error; + LONG Error; /* Read the MBR */ if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER)) @@ -576,7 +526,7 @@ SetHarddiskIdentifier(HKEY DiskKey, return; } - Buffer = (U32*)DISKREADBUFFER; + Buffer = (ULONG*)DISKREADBUFFER; Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER; Signature = Mbr->Signature; @@ -618,7 +568,7 @@ SetHarddiskIdentifier(HKEY DiskKey, Error = RegSetValue(DiskKey, "Identifier", REG_SZ, - (PU8) Identifier, + (PUCHAR) Identifier, 20); if (Error != ERROR_SUCCESS) { @@ -630,18 +580,18 @@ SetHarddiskIdentifier(HKEY DiskKey, static VOID -DetectBiosDisks(HKEY SystemKey, - HKEY BusKey) +DetectBiosDisks(FRLDRHKEY SystemKey, + FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_INT13_DRIVE_PARAMETER Int13Drives; GEOMETRY Geometry; CHAR Buffer[80]; - HKEY DiskKey; - U32 DiskCount; - U32 Size; - U32 i; - S32 Error; + FRLDRHKEY DiskKey; + ULONG DiskCount; + ULONG Size; + ULONG i; + LONG Error; BOOL Changed; /* Count the number of visible drives */ @@ -723,7 +673,7 @@ DetectBiosDisks(HKEY SystemKey, Error = RegSetValue(SystemKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -759,10 +709,10 @@ DetectBiosDisks(HKEY SystemKey, } -static U32 +static ULONG GetFloppyCount(VOID) { - U8 Data; + UCHAR Data; WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10); Data = READ_PORT_UCHAR((PUCHAR)0x71); @@ -771,10 +721,10 @@ GetFloppyCount(VOID) } -static U8 -GetFloppyType(U8 DriveNumber) +static UCHAR +GetFloppyType(UCHAR DriveNumber) { - U8 Data; + UCHAR Data; WRITE_PORT_UCHAR((PUCHAR)0x70, 0x10); Data = READ_PORT_UCHAR((PUCHAR)0x71); @@ -791,28 +741,28 @@ GetFloppyType(U8 DriveNumber) static PVOID GetInt1eTable(VOID) { - PU16 SegPtr = (PU16)0x7A; - PU16 OfsPtr = (PU16)0x78; + PUSHORT SegPtr = (PUSHORT)0x7A; + PUSHORT OfsPtr = (PUSHORT)0x78; - return (PVOID)(((U32)(*SegPtr)) << 4) + (U32)(*OfsPtr); + return (PVOID)(((ULONG)(*SegPtr)) << 4) + (ULONG)(*OfsPtr); } static VOID -DetectBiosFloppyPeripheral(HKEY ControllerKey) +DetectBiosFloppyPeripheral(FRLDRHKEY ControllerKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_FLOPPY_DEVICE_DATA FloppyData; char KeyName[32]; char Identifier[20]; - HKEY PeripheralKey; - U32 Size; - S32 Error; - U32 FloppyNumber; - U8 FloppyType; - U32 MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880}; - PU8 Ptr; + FRLDRHKEY PeripheralKey; + ULONG Size; + LONG Error; + ULONG FloppyNumber; + UCHAR FloppyType; + ULONG MaxDensity[6] = {0, 360, 1200, 720, 1440, 2880}; + PUCHAR Ptr; for (FloppyNumber = 0; FloppyNumber < 2; FloppyNumber++) { @@ -879,7 +829,7 @@ DetectBiosFloppyPeripheral(HKEY ControllerKey) Error = RegSetValue(PeripheralKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -895,7 +845,7 @@ DetectBiosFloppyPeripheral(HKEY ControllerKey) Error = RegSetValue(PeripheralKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -908,15 +858,15 @@ DetectBiosFloppyPeripheral(HKEY ControllerKey) static VOID -DetectBiosFloppyController(HKEY SystemKey, - HKEY BusKey) +DetectBiosFloppyController(FRLDRHKEY SystemKey, + FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - HKEY ControllerKey; - U32 Size; - S32 Error; - U32 FloppyCount; + FRLDRHKEY ControllerKey; + ULONG Size; + LONG Error; + ULONG FloppyCount; FloppyCount = GetFloppyCount(); DbgPrint((DPRINT_HWDETECT, @@ -964,7 +914,8 @@ DetectBiosFloppyController(HKEY SystemKey, PartialDescriptor->Type = CmResourceTypePort; PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start = (U64)0x03F0; + PartialDescriptor->u.Port.Start.LowPart = 0x03F0; + PartialDescriptor->u.Port.Start.HighPart = 0x0; PartialDescriptor->u.Port.Length = 8; /* Set Interrupt */ @@ -988,7 +939,7 @@ DetectBiosFloppyController(HKEY SystemKey, Error = RegSetValue(ControllerKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -1004,8 +955,8 @@ DetectBiosFloppyController(HKEY SystemKey, static VOID -InitializeSerialPort(U32 Port, - U32 LineControl) +InitializeSerialPort(ULONG Port, + ULONG LineControl) { WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0x80); /* set DLAB on */ WRITE_PORT_UCHAR((PUCHAR)Port, 0x60); /* speed LO byte */ @@ -1017,18 +968,18 @@ InitializeSerialPort(U32 Port, } -static U32 -DetectSerialMouse(U32 Port) +static ULONG +DetectSerialMouse(ULONG Port) { CHAR Buffer[4]; - U32 i; - U32 TimeOut = 200; - U8 LineControl; + ULONG i; + ULONG TimeOut = 200; + UCHAR LineControl; /* Shutdown mouse or something like that */ LineControl = READ_PORT_UCHAR((PUCHAR)Port + 4); WRITE_PORT_UCHAR((PUCHAR)Port + 4, (LineControl & ~0x02) | 0x01); - KeStallExecutionProcessor(100000); + StallExecutionProcessor(100000); /* Clear buffer */ while (READ_PORT_UCHAR((PUCHAR)Port + 5) & 0x01) @@ -1041,14 +992,14 @@ DetectSerialMouse(U32 Port) WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b); /* Wait 10 milliseconds for the mouse getting ready */ - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); /* Read first four bytes, which contains Microsoft Mouse signs */ for (i = 0; i < 4; i++) { while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0)) { - KeStallExecutionProcessor(1000); + StallExecutionProcessor(1000); --TimeOut; if (TimeOut == 0) return MOUSE_TYPE_NONE; @@ -1104,29 +1055,29 @@ DetectSerialMouse(U32 Port) } -static U32 -GetSerialMousePnpId(U32 Port, char *Buffer) +static ULONG +GetSerialMousePnpId(ULONG Port, char *Buffer) { - U32 TimeOut; - U32 i = 0; + ULONG TimeOut; + ULONG i = 0; char c; char x; WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x09); /* Wait 10 milliseconds for the mouse getting ready */ - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b); - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); for (;;) { TimeOut = 200; while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0)) { - KeStallExecutionProcessor(1000); + StallExecutionProcessor(1000); --TimeOut; if (TimeOut == 0) { @@ -1147,7 +1098,7 @@ GetSerialMousePnpId(U32 Port, char *Buffer) TimeOut = 200; while (((READ_PORT_UCHAR((PUCHAR)Port + 5) & 1) == 0) && (TimeOut > 0)) { - KeStallExecutionProcessor(1000); + StallExecutionProcessor(1000); --TimeOut; if (TimeOut == 0) return 0; @@ -1165,18 +1116,18 @@ GetSerialMousePnpId(U32 Port, char *Buffer) static VOID -DetectSerialPointerPeripheral(HKEY ControllerKey, - U32 Base) +DetectSerialPointerPeripheral(FRLDRHKEY ControllerKey, + ULONG Base) { CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; char Buffer[256]; char Identifier[256]; - HKEY PeripheralKey; - U32 MouseType; - U32 Length; - U32 i; - U32 j; - S32 Error; + FRLDRHKEY PeripheralKey; + ULONG MouseType; + ULONG Length; + ULONG i; + ULONG j; + LONG Error; DbgPrint((DPRINT_HWDETECT, "DetectSerialPointerPeripheral()\n")); @@ -1329,7 +1280,7 @@ DetectSerialPointerPeripheral(HKEY ControllerKey, Error = RegSetValue(PeripheralKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8)&FullResourceDescriptor, + (PUCHAR)&FullResourceDescriptor, sizeof(CM_FULL_RESOURCE_DESCRIPTOR) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); if (Error != ERROR_SUCCESS) @@ -1343,7 +1294,7 @@ DetectSerialPointerPeripheral(HKEY ControllerKey, Error = RegSetValue(PeripheralKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -1356,28 +1307,28 @@ DetectSerialPointerPeripheral(HKEY ControllerKey, static VOID -DetectSerialPorts(HKEY BusKey) +DetectSerialPorts(FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_SERIAL_DEVICE_DATA SerialDeviceData; - U32 Irq[4] = {4, 3, 4, 3}; - U32 Base; + ULONG Irq[4] = {4, 3, 4, 3}; + ULONG Base; char Buffer[80]; - PU16 BasePtr; - U32 ControllerNumber = 0; - HKEY ControllerKey; - U32 i; - S32 Error; - U32 Size; + PUSHORT BasePtr; + ULONG ControllerNumber = 0; + FRLDRHKEY ControllerKey; + ULONG i; + LONG Error; + ULONG Size; DbgPrint((DPRINT_HWDETECT, "DetectSerialPorts()\n")); ControllerNumber = 0; - BasePtr = (PU16)0x400; + BasePtr = (PUSHORT)0x400; for (i = 0; i < 4; i++, BasePtr++) { - Base = (U32)*BasePtr; + Base = (ULONG)*BasePtr; if (Base == 0) continue; @@ -1430,7 +1381,8 @@ DetectSerialPorts(HKEY BusKey) PartialDescriptor->Type = CmResourceTypePort; PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start = (U64)Base; + PartialDescriptor->u.Port.Start.LowPart = Base; + PartialDescriptor->u.Port.Start.HighPart = 0x0; PartialDescriptor->u.Port.Length = 7; /* Set Interrupt */ @@ -1457,7 +1409,7 @@ DetectSerialPorts(HKEY BusKey) Error = RegSetValue(ControllerKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -1474,7 +1426,7 @@ DetectSerialPorts(HKEY BusKey) Error = RegSetValue(ControllerKey, "Identifier", REG_SZ, - (PU8)Buffer, + (PUCHAR)Buffer, strlen(Buffer) + 1); if (Error != ERROR_SUCCESS) { @@ -1496,27 +1448,27 @@ DetectSerialPorts(HKEY BusKey) static VOID -DetectParallelPorts(HKEY BusKey) +DetectParallelPorts(FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - U32 Irq[3] = {7, 5, (U32)-1}; + ULONG Irq[3] = {7, 5, (ULONG)-1}; char Buffer[80]; - HKEY ControllerKey; - PU16 BasePtr; - U32 Base; - U32 ControllerNumber; - U32 i; - S32 Error; - U32 Size; + FRLDRHKEY ControllerKey; + PUSHORT BasePtr; + ULONG Base; + ULONG ControllerNumber; + ULONG i; + LONG Error; + ULONG Size; DbgPrint((DPRINT_HWDETECT, "DetectParallelPorts() called\n")); ControllerNumber = 0; - BasePtr = (PU16)0x408; + BasePtr = (PUSHORT)0x408; for (i = 0; i < 3; i++, BasePtr++) { - Base = (U32)*BasePtr; + Base = (ULONG)*BasePtr; if (Base == 0) continue; @@ -1548,7 +1500,7 @@ DetectParallelPorts(HKEY BusKey) /* Build full device descriptor */ Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR); - if (Irq[i] != (U32)-1) + if (Irq[i] != (ULONG)-1) Size += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); FullResourceDescriptor = MmAllocateMemory(Size); @@ -1563,18 +1515,19 @@ DetectParallelPorts(HKEY BusKey) /* Initialize resource descriptor */ FullResourceDescriptor->InterfaceType = Isa; FullResourceDescriptor->BusNumber = 0; - FullResourceDescriptor->PartialResourceList.Count = (Irq[i] != (U32)-1) ? 2 : 1; + FullResourceDescriptor->PartialResourceList.Count = (Irq[i] != (ULONG)-1) ? 2 : 1; /* Set IO Port */ PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0]; PartialDescriptor->Type = CmResourceTypePort; PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start = (U64)Base; + PartialDescriptor->u.Port.Start.LowPart = Base; + PartialDescriptor->u.Port.Start.HighPart = 0x0; PartialDescriptor->u.Port.Length = 3; /* Set Interrupt */ - if (Irq[i] != (U32)-1) + if (Irq[i] != (ULONG)-1) { PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[1]; PartialDescriptor->Type = CmResourceTypeInterrupt; @@ -1589,7 +1542,7 @@ DetectParallelPorts(HKEY BusKey) Error = RegSetValue(ControllerKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -1606,7 +1559,7 @@ DetectParallelPorts(HKEY BusKey) Error = RegSetValue(ControllerKey, "Identifier", REG_SZ, - (PU8)Buffer, + (PUCHAR)Buffer, strlen(Buffer) + 1); if (Error != ERROR_SUCCESS) { @@ -1635,7 +1588,7 @@ DetectKeyboardDevice(VOID) WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 0xF2); - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); if ((Status & 0x01) != 0x01) @@ -1651,7 +1604,7 @@ DetectKeyboardDevice(VOID) return FALSE; } - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); if ((Status & 0x01) != 0x01) { @@ -1666,7 +1619,7 @@ DetectKeyboardDevice(VOID) return FALSE; } - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); if ((Status & 0x01) != 0x01) { @@ -1687,15 +1640,15 @@ DetectKeyboardDevice(VOID) static VOID -DetectKeyboardPeripheral(HKEY ControllerKey) +DetectKeyboardPeripheral(FRLDRHKEY ControllerKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PCM_KEYBOARD_DEVICE_DATA KeyboardData; - HKEY PeripheralKey; + FRLDRHKEY PeripheralKey; char Buffer[80]; - U32 Size; - S32 Error; + ULONG Size; + LONG Error; if (DetectKeyboardDevice()) { @@ -1749,7 +1702,7 @@ DetectKeyboardPeripheral(HKEY ControllerKey) Error = RegSetValue(PeripheralKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8)FullResourceDescriptor, + (PUCHAR)FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -1765,7 +1718,7 @@ DetectKeyboardPeripheral(HKEY ControllerKey) Error = RegSetValue(ControllerKey, "Identifier", REG_SZ, - (PU8)Buffer, + (PUCHAR)Buffer, strlen(Buffer) + 1); if (Error != ERROR_SUCCESS) { @@ -1778,13 +1731,13 @@ DetectKeyboardPeripheral(HKEY ControllerKey) static VOID -DetectKeyboardController(HKEY BusKey) +DetectKeyboardController(FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - HKEY ControllerKey; - U32 Size; - S32 Error; + FRLDRHKEY ControllerKey; + ULONG Size; + LONG Error; /* Create controller key */ Error = RegCreateKey(BusKey, @@ -1834,7 +1787,8 @@ DetectKeyboardController(HKEY BusKey) PartialDescriptor->Type = CmResourceTypePort; PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start = (U64)0x60; + PartialDescriptor->u.Port.Start.LowPart = 0x60; + PartialDescriptor->u.Port.Start.HighPart = 0x0; PartialDescriptor->u.Port.Length = 1; /* Set IO Port 0x64 */ @@ -1842,14 +1796,15 @@ DetectKeyboardController(HKEY BusKey) PartialDescriptor->Type = CmResourceTypePort; PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive; PartialDescriptor->Flags = CM_RESOURCE_PORT_IO; - PartialDescriptor->u.Port.Start = (U64)0x64; + PartialDescriptor->u.Port.Start.LowPart = 0x64; + PartialDescriptor->u.Port.Start.HighPart = 0x0; PartialDescriptor->u.Port.Length = 1; /* Set 'Configuration Data' value */ Error = RegSetValue(ControllerKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8)FullResourceDescriptor, + (PUCHAR)FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -1867,8 +1822,8 @@ DetectKeyboardController(HKEY BusKey) static VOID PS2ControllerWait(VOID) { - U32 Timeout; - U8 Status; + ULONG Timeout; + UCHAR Status; for (Timeout = 0; Timeout < CONTROLLER_TIMEOUT; Timeout++) { @@ -1877,7 +1832,7 @@ PS2ControllerWait(VOID) return; /* Sleep for one millisecond */ - KeStallExecutionProcessor(1000); + StallExecutionProcessor(1000); } } @@ -1885,9 +1840,9 @@ PS2ControllerWait(VOID) static BOOLEAN DetectPS2AuxPort(VOID) { - U32 Loops; - U8 Scancode; - U8 Status; + ULONG Loops; + UCHAR Scancode; + UCHAR Status; /* Put the value 0x5A in the output buffer using the * "WriteAuxiliary Device Output Buffer" command (0xD3). @@ -1919,7 +1874,7 @@ DetectPS2AuxPort(VOID) break; } - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); } return FALSE; @@ -1929,8 +1884,8 @@ DetectPS2AuxPort(VOID) static BOOLEAN DetectPS2AuxDevice(VOID) { - U8 Scancode; - U8 Status; + UCHAR Scancode; + UCHAR Status; PS2ControllerWait(); WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_CONTROL, @@ -1941,7 +1896,7 @@ DetectPS2AuxDevice(VOID) WRITE_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_DATA, 0xF2); - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0) @@ -1953,7 +1908,7 @@ DetectPS2AuxDevice(VOID) if (Scancode != 0xFA) return FALSE; - KeStallExecutionProcessor(10000); + StallExecutionProcessor(10000); Status = READ_PORT_UCHAR((PUCHAR)CONTROLLER_REGISTER_STATUS); if ((Status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) == 0) @@ -1970,12 +1925,12 @@ DetectPS2AuxDevice(VOID) static VOID -DetectPS2Mouse(HKEY BusKey) +DetectPS2Mouse(FRLDRHKEY BusKey) { CM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; - HKEY ControllerKey; - HKEY PeripheralKey; - S32 Error; + FRLDRHKEY ControllerKey; + FRLDRHKEY PeripheralKey; + LONG Error; if (DetectPS2AuxPort()) { @@ -2017,7 +1972,7 @@ DetectPS2Mouse(HKEY BusKey) Error = RegSetValue(ControllerKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8)&FullResourceDescriptor, + (PUCHAR)&FullResourceDescriptor, sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); if (Error != ERROR_SUCCESS) { @@ -2059,7 +2014,7 @@ DetectPS2Mouse(HKEY BusKey) Error = RegSetValue(PeripheralKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8)&FullResourceDescriptor, + (PUCHAR)&FullResourceDescriptor, sizeof(CM_FULL_RESOURCE_DESCRIPTOR) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); if (Error != ERROR_SUCCESS) @@ -2074,7 +2029,7 @@ DetectPS2Mouse(HKEY BusKey) Error = RegSetValue(PeripheralKey, "Identifier", REG_SZ, - (PU8)"MICROSOFT PS2 MOUSE", + (PUCHAR)"MICROSOFT PS2 MOUSE", 20); if (Error != ERROR_SUCCESS) { @@ -2089,12 +2044,12 @@ DetectPS2Mouse(HKEY BusKey) static VOID -DetectDisplayController(HKEY BusKey) +DetectDisplayController(FRLDRHKEY BusKey) { CHAR Buffer[80]; - HKEY ControllerKey; - U16 VesaVersion; - S32 Error; + FRLDRHKEY ControllerKey; + USHORT VesaVersion; + LONG Error; Error = RegCreateKey(BusKey, "DisplayController\\0", @@ -2143,7 +2098,7 @@ DetectDisplayController(HKEY BusKey) Error = RegSetValue(ControllerKey, "Identifier", REG_SZ, - (PU8)Buffer, + (PUCHAR)Buffer, strlen(Buffer) + 1); if (Error != ERROR_SUCCESS) { @@ -2158,13 +2113,13 @@ DetectDisplayController(HKEY BusKey) static VOID -DetectIsaBios(HKEY SystemKey, U32 *BusNumber) +DetectIsaBios(FRLDRHKEY SystemKey, ULONG *BusNumber) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; char Buffer[80]; - HKEY BusKey; - U32 Size; - S32 Error; + FRLDRHKEY BusKey; + ULONG Size; + LONG Error; /* Create new bus key */ sprintf(Buffer, @@ -2191,7 +2146,7 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BusKey, "Identifier", REG_SZ, - (PU8)"ISA", + (PUCHAR)"ISA", 4); if (Error != ERROR_SUCCESS) { @@ -2220,7 +2175,7 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BusKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -2253,9 +2208,9 @@ DetectIsaBios(HKEY SystemKey, U32 *BusNumber) VOID PcHwDetect(VOID) { - HKEY SystemKey; - U32 BusNumber = 0; - S32 Error; + FRLDRHKEY SystemKey; + ULONG BusNumber = 0; + LONG Error; DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n")); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hardware.h b/reactos/boot/freeldr/freeldr/arch/i386/hardware.h index fe5720a5f29..49a39dd893d 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hardware.h +++ b/reactos/boot/freeldr/freeldr/arch/i386/hardware.h @@ -25,91 +25,6 @@ #include "../../reactos/registry.h" #endif -typedef enum -{ - InterfaceTypeUndefined = -1, - Internal, - Isa, - Eisa, - MicroChannel, - TurboChannel, - PCIBus, - VMEBus, - NuBus, - PCMCIABus, - CBus, - MPIBus, - MPSABus, - ProcessorInternal, - InternalPowerBus, - PNPISABus, - MaximumInterfaceType -} INTERFACE_TYPE, *PINTERFACE_TYPE; - - -typedef enum _CM_RESOURCE_TYPE -{ - CmResourceTypeNull = 0, - CmResourceTypePort, - CmResourceTypeInterrupt, - CmResourceTypeMemory, - CmResourceTypeDma, - CmResourceTypeDeviceSpecific, - CmResourceTypeMaximum -} CM_RESOURCE_TYPE; - - -typedef enum _CM_SHARE_DISPOSITION -{ - CmResourceShareUndetermined = 0, - CmResourceShareDeviceExclusive, - CmResourceShareDriverExclusive, - CmResourceShareShared -} CM_SHARE_DISPOSITION; - - -typedef U64 PHYSICAL_ADDRESS; - - -typedef struct -{ - U8 Type; - U8 ShareDisposition; - U16 Flags; - union - { - struct - { - PHYSICAL_ADDRESS Start; - U32 Length; - } __attribute__((packed)) Port; - struct - { - U32 Level; - U32 Vector; - U32 Affinity; - } __attribute__((packed)) Interrupt; - struct - { - PHYSICAL_ADDRESS Start; - U32 Length; - } __attribute__((packed)) Memory; - struct - { - U32 Channel; - U32 Port; - U32 Reserved1; - } __attribute__((packed)) Dma; - struct - { - U32 DataSize; - U32 Reserved1; - U32 Reserved2; - } __attribute__((packed)) DeviceSpecificData; - } __attribute__((packed)) u; -} __attribute__((packed)) CM_PARTIAL_RESOURCE_DESCRIPTOR, *PCM_PARTIAL_RESOURCE_DESCRIPTOR; - - /* CM_PARTIAL_RESOURCE_DESCRIPTOR.Flags */ #define CM_RESOURCE_PORT_MEMORY 0x0000 #define CM_RESOURCE_PORT_IO 0x0001 @@ -117,30 +32,12 @@ typedef struct #define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0x0000 #define CM_RESOURCE_INTERRUPT_LATCHED 0x0001 - -typedef struct -{ - U16 Version; - U16 Revision; - U32 Count; - CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; -} __attribute__((packed))CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST; - - -typedef struct -{ - INTERFACE_TYPE InterfaceType; - U32 BusNumber; - CM_PARTIAL_RESOURCE_LIST PartialResourceList; -} __attribute__((packed)) CM_FULL_RESOURCE_DESCRIPTOR, *PCM_FULL_RESOURCE_DESCRIPTOR; - - typedef struct _CM_COMPONENT_INFORMATION { - U32 Flags; - U32 Version; - U32 Key; - U32 Affinity; + ULONG Flags; + ULONG Version; + ULONG Key; + ULONG Affinity; } __attribute__((packed)) CM_COMPONENT_INFORMATION, *PCM_COMPONENT_INFORMATION; @@ -154,46 +51,48 @@ typedef struct _CM_COMPONENT_INFORMATION #define Output 0x00000040 #define CONFIG_CMD(bus, dev_fn, where) \ - (0x80000000 | (((U32)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3)) + (0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3)) /* PROTOTYPES ***************************************************************/ /* hardware.c */ -VOID HalpCalibrateStallExecution(VOID); -VOID KeStallExecutionProcessor(U32 Microseconds); -VOID SetComponentInformation(HKEY ComponentKey, - U32 Flags, - U32 Key, - U32 Affinity); +VOID StallExecutionProcessor(ULONG Microseconds); + +VOID HalpCalibrateStallExecution(VOID); + +VOID SetComponentInformation(FRLDRHKEY ComponentKey, + ULONG Flags, + ULONG Key, + ULONG Affinity); /* hwacpi.c */ -VOID DetectAcpiBios(HKEY SystemKey, U32 *BusNumber); +VOID DetectAcpiBios(FRLDRHKEY SystemKey, ULONG *BusNumber); /* hwapm.c */ -VOID DetectApmBios(HKEY SystemKey, U32 *BusNumber); +VOID DetectApmBios(FRLDRHKEY SystemKey, ULONG *BusNumber); /* hwcpu.c */ -VOID DetectCPUs(HKEY SystemKey); +VOID DetectCPUs(FRLDRHKEY SystemKey); /* hwpci.c */ -VOID DetectPciBios(HKEY SystemKey, U32 *BusNumber); +VOID DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber); /* i386cpu.S */ -U32 CpuidSupported(VOID); -VOID GetCpuid(U32 Level, - U32 *eax, - U32 *ebx, - U32 *ecx, - U32 *edx); -U64 RDTSC(VOID); +ULONG CpuidSupported(VOID); +VOID GetCpuid(ULONG Level, + ULONG *eax, + ULONG *ebx, + ULONG *ecx, + ULONG *edx); +ULONGLONG RDTSC(VOID); /* i386pnp.S */ -U32 PnpBiosSupported(VOID); -U32 PnpBiosGetDeviceNodeCount(U32 *NodeSize, - U32 *NodeCount); -U32 PnpBiosGetDeviceNode(U8 *NodeId, - U8 *NodeBuffer); +ULONG PnpBiosSupported(VOID); +ULONG PnpBiosGetDeviceNodeCount(ULONG *NodeSize, + ULONG *NodeCount); +ULONG PnpBiosGetDeviceNode(UCHAR *NodeId, + UCHAR *NodeBuffer); #endif /* __I386_HARDWARE_H_ */ diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c b/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c index c8dacbc1a68..733f71a8a36 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c @@ -32,11 +32,11 @@ static BOOL FindAcpiBios(VOID) { - PU8 Ptr; + PUCHAR Ptr; /* Find the 'Root System Descriptor Table Pointer' */ - Ptr = (PU8)0xE0000; - while ((U32)Ptr < 0x100000) + Ptr = (PUCHAR)0xE0000; + while ((ULONG)Ptr < 0x100000) { if (!memcmp(Ptr, "RSD PTR ", 8)) { @@ -45,7 +45,7 @@ FindAcpiBios(VOID) return TRUE; } - Ptr = (PU8)((U32)Ptr + 0x10); + Ptr = (PUCHAR)((ULONG)Ptr + 0x10); } DbgPrint((DPRINT_HWDETECT, "ACPI not supported\n")); @@ -55,11 +55,11 @@ FindAcpiBios(VOID) VOID -DetectAcpiBios(HKEY SystemKey, U32 *BusNumber) +DetectAcpiBios(FRLDRHKEY SystemKey, ULONG *BusNumber) { char Buffer[80]; - HKEY BiosKey; - S32 Error; + FRLDRHKEY BiosKey; + LONG Error; if (FindAcpiBios()) { @@ -90,7 +90,7 @@ DetectAcpiBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BiosKey, "Identifier", REG_SZ, - (PU8)"ACPI BIOS", + (PUCHAR)"ACPI BIOS", 10); if (Error != ERROR_SUCCESS) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hwapm.c b/reactos/boot/freeldr/freeldr/arch/i386/hwapm.c index 7da6d7d48f4..a4c43b18247 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hwapm.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hwapm.c @@ -60,11 +60,11 @@ FindApmBios(VOID) VOID -DetectApmBios(HKEY SystemKey, U32 *BusNumber) +DetectApmBios(FRLDRHKEY SystemKey, ULONG *BusNumber) { char Buffer[80]; - HKEY BiosKey; - S32 Error; + FRLDRHKEY BiosKey; + LONG Error; if (FindApmBios()) { @@ -95,7 +95,7 @@ DetectApmBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BiosKey, "Identifier", REG_SZ, - (PU8)"APM", + (PUCHAR)"APM", 4); if (Error != ERROR_SUCCESS) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hwcpu.c b/reactos/boot/freeldr/freeldr/arch/i386/hwcpu.c index 80ed3f482ed..072d60d7b7d 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hwcpu.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hwcpu.c @@ -35,60 +35,60 @@ typedef struct _MP_FLOATING_POINT_TABLE { - U32 Signature; /* "_MP_" */ - U32 PhysicalAddressPointer; - U8 Length; - U8 SpecRev; - U8 Checksum; - U8 FeatureByte[5]; + ULONG Signature; /* "_MP_" */ + ULONG PhysicalAddressPointer; + UCHAR Length; + UCHAR SpecRev; + UCHAR Checksum; + UCHAR FeatureByte[5]; } PACKED MP_FLOATING_POINT_TABLE, *PMP_FLOATING_POINT_TABLE; typedef struct _MPS_CONFIG_TABLE_HEADER { - U32 Signature; /* "PCMP" */ - U16 BaseTableLength; - U8 SpecRev; - U8 Checksum; - U8 OemIdString[8]; - U8 ProductIdString[12]; - U32 OemTablePointer; - U16 OemTableLength; - U16 EntryCount; - U32 AddressOfLocalAPIC; - U16 ExtendedTableLength; - U8 ExtendedTableChecksum; - U8 Reserved; + ULONG Signature; /* "PCMP" */ + USHORT BaseTableLength; + UCHAR SpecRev; + UCHAR Checksum; + UCHAR OemIdString[8]; + UCHAR ProductIdString[12]; + ULONG OemTablePointer; + USHORT OemTableLength; + USHORT EntryCount; + ULONG AddressOfLocalAPIC; + USHORT ExtendedTableLength; + UCHAR ExtendedTableChecksum; + UCHAR Reserved; } PACKED MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE; typedef struct _MP_PROCESSOR_ENTRY { - U8 EntryType; - U8 LocalApicId; - U8 LocalApicVersion; - U8 CpuFlags; - U32 CpuSignature; - U32 FeatureFlags; - U32 Reserved1; - U32 Reserved2; + UCHAR EntryType; + UCHAR LocalApicId; + UCHAR LocalApicVersion; + UCHAR CpuFlags; + ULONG CpuSignature; + ULONG FeatureFlags; + ULONG Reserved1; + ULONG Reserved2; } PACKED MP_PROCESSOR_ENTRY, *PMP_PROCESSOR_ENTRY; /* FUNCTIONS ****************************************************************/ -static U32 +static ULONG GetCpuSpeed(VOID) { - U64 Timestamp1; - U64 Timestamp2; - U64 Diff; + ULONGLONG Timestamp1; + ULONGLONG Timestamp2; + ULONGLONG Diff; /* Read TSC (Time Stamp Counter) */ Timestamp1 = RDTSC(); /* Wait for 0.1 seconds (= 100 milliseconds = 100000 microseconds)*/ - KeStallExecutionProcessor(100000); + StallExecutionProcessor(100000); /* Read TSC (Time Stamp Counter) again */ Timestamp2 = RDTSC(); @@ -100,30 +100,30 @@ GetCpuSpeed(VOID) } else { - Diff = Timestamp2 + (((U64)-1) - Timestamp1); + Diff = Timestamp2 + (((ULONGLONG)-1) - Timestamp1); } - return (U32)(Diff / 100000); + return (ULONG)(Diff / 100000); } static VOID -DetectCPU(HKEY CpuKey, - HKEY FpuKey) +DetectCPU(FRLDRHKEY CpuKey, + FRLDRHKEY FpuKey) { char VendorIdentifier[13]; char Identifier[64]; - U32 FeatureSet; - HKEY CpuInstKey; - HKEY FpuInstKey; - U32 eax = 0; - U32 ebx = 0; - U32 ecx = 0; - U32 edx = 0; - U32 *Ptr; - S32 Error; + ULONG FeatureSet; + FRLDRHKEY CpuInstKey; + FRLDRHKEY FpuInstKey; + ULONG eax = 0; + ULONG ebx = 0; + ULONG ecx = 0; + ULONG edx = 0; + ULONG *Ptr; + LONG Error; BOOL SupportTSC = FALSE; - U32 CpuSpeed; + ULONG CpuSpeed; /* Create the CPU instance key */ @@ -154,7 +154,7 @@ DetectCPU(HKEY CpuKey, /* Get vendor identifier */ GetCpuid(0, &eax, &ebx, &ecx, &edx); VendorIdentifier[12] = 0; - Ptr = (U32*)&VendorIdentifier[0]; + Ptr = (ULONG*)&VendorIdentifier[0]; *Ptr = ebx; Ptr++; *Ptr = edx; @@ -195,8 +195,8 @@ DetectCPU(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "FeatureSet", REG_DWORD, - (PU8)&FeatureSet, - sizeof(U32)); + (PUCHAR)&FeatureSet, + sizeof(ULONG)); if (Error != ERROR_SUCCESS) { DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); @@ -208,7 +208,7 @@ DetectCPU(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -218,7 +218,7 @@ DetectCPU(HKEY CpuKey, Error = RegSetValue(FpuInstKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -231,7 +231,7 @@ DetectCPU(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "VendorIdentifier", REG_SZ, - (PU8)VendorIdentifier, + (PUCHAR)VendorIdentifier, strlen(VendorIdentifier) + 1); if (Error != ERROR_SUCCESS) { @@ -250,8 +250,8 @@ DetectCPU(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "~MHz", REG_DWORD, - (PU8)&CpuSpeed, - sizeof(U32)); + (PUCHAR)&CpuSpeed, + sizeof(ULONG)); if (Error != ERROR_SUCCESS) { DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); @@ -261,23 +261,23 @@ DetectCPU(HKEY CpuKey, static VOID -SetMpsProcessor(HKEY CpuKey, - HKEY FpuKey, +SetMpsProcessor(FRLDRHKEY CpuKey, + FRLDRHKEY FpuKey, PMP_PROCESSOR_ENTRY CpuEntry) { char VendorIdentifier[13]; char Identifier[64]; char Buffer[8]; - U32 FeatureSet; - HKEY CpuInstKey; - HKEY FpuInstKey; - U32 eax = 0; - U32 ebx = 0; - U32 ecx = 0; - U32 edx = 0; - U32 *Ptr; - S32 Error; - U32 CpuSpeed; + ULONG FeatureSet; + FRLDRHKEY CpuInstKey; + FRLDRHKEY FpuInstKey; + ULONG eax = 0; + ULONG ebx = 0; + ULONG ecx = 0; + ULONG edx = 0; + ULONG *Ptr; + LONG Error; + ULONG CpuSpeed; /* Get processor instance number */ sprintf(Buffer, "%u", CpuEntry->LocalApicId); @@ -305,7 +305,7 @@ SetMpsProcessor(HKEY CpuKey, /* Get 'VendorIdentifier' */ GetCpuid(0, &eax, &ebx, &ecx, &edx); VendorIdentifier[12] = 0; - Ptr = (U32*)&VendorIdentifier[0]; + Ptr = (ULONG*)&VendorIdentifier[0]; *Ptr = ebx; Ptr++; *Ptr = edx; @@ -315,9 +315,9 @@ SetMpsProcessor(HKEY CpuKey, /* Get 'Identifier' */ sprintf(Identifier, "x86 Family %u Model %u Stepping %u", - (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), - (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), - (U32)(CpuEntry->CpuSignature & 0x0F)); + (ULONG)((CpuEntry->CpuSignature >> 8) & 0x0F), + (ULONG)((CpuEntry->CpuSignature >> 4) & 0x0F), + (ULONG)(CpuEntry->CpuSignature & 0x0F)); /* Get FeatureSet */ FeatureSet = CpuEntry->FeatureFlags; @@ -339,8 +339,8 @@ SetMpsProcessor(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "FeatureSet", REG_DWORD, - (PU8)&FeatureSet, - sizeof(U32)); + (PUCHAR)&FeatureSet, + sizeof(ULONG)); if (Error != ERROR_SUCCESS) { DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); @@ -352,7 +352,7 @@ SetMpsProcessor(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -362,7 +362,7 @@ SetMpsProcessor(HKEY CpuKey, Error = RegSetValue(FpuInstKey, "Identifier", REG_SZ, - (PU8)Identifier, + (PUCHAR)Identifier, strlen(Identifier) + 1); if (Error != ERROR_SUCCESS) { @@ -375,7 +375,7 @@ SetMpsProcessor(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "VendorIdentifier", REG_SZ, - (PU8)VendorIdentifier, + (PUCHAR)VendorIdentifier, strlen(VendorIdentifier) + 1); if (Error != ERROR_SUCCESS) { @@ -394,8 +394,8 @@ SetMpsProcessor(HKEY CpuKey, Error = RegSetValue(CpuInstKey, "~MHz", REG_DWORD, - (PU8)&CpuSpeed, - sizeof(U32)); + (PUCHAR)&CpuSpeed, + sizeof(ULONG)); if (Error != ERROR_SUCCESS) { DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error)); @@ -409,12 +409,12 @@ GetMpFloatingPointTable(VOID) { PMP_FLOATING_POINT_TABLE FpTable; char *Ptr; - U8 Sum; - U32 Length; - U32 i; + UCHAR Sum; + ULONG Length; + ULONG i; FpTable = (PMP_FLOATING_POINT_TABLE)0xF0000; - while ((U32)FpTable < 0x100000) + while ((ULONG)FpTable < 0x100000) { if (FpTable->Signature == MP_FP_SIGNATURE) { @@ -440,7 +440,7 @@ GetMpFloatingPointTable(VOID) return FpTable; } - FpTable = (PMP_FLOATING_POINT_TABLE)((U32)FpTable + 0x10); + FpTable = (PMP_FLOATING_POINT_TABLE)((ULONG)FpTable + 0x10); } return NULL; @@ -452,9 +452,9 @@ GetMpConfigurationTable(PMP_FLOATING_POINT_TABLE FpTable) { PMP_CONFIGURATION_TABLE ConfigTable; char *Ptr; - U8 Sum; - U32 Length; - U32 i; + UCHAR Sum; + ULONG Length; + ULONG i; if (FpTable->FeatureByte[0] != 0 || FpTable->PhysicalAddressPointer == 0) @@ -466,7 +466,7 @@ GetMpConfigurationTable(PMP_FLOATING_POINT_TABLE FpTable) DbgPrint((DPRINT_HWDETECT, "MP Configuration Table at: %x\n", - (U32)ConfigTable)); + (ULONG)ConfigTable)); /* Calculate base table checksum */ Length = ConfigTable->BaseTableLength; @@ -498,14 +498,14 @@ GetMpConfigurationTable(PMP_FLOATING_POINT_TABLE FpTable) static BOOL -DetectMps(HKEY CpuKey, - HKEY FpuKey) +DetectMps(FRLDRHKEY CpuKey, + FRLDRHKEY FpuKey) { PMP_FLOATING_POINT_TABLE FpTable; PMP_CONFIGURATION_TABLE ConfigTable; PMP_PROCESSOR_ENTRY CpuEntry; char *Ptr; - U32 Offset; + ULONG Offset; /* Get floating point table */ FpTable = GetMpFloatingPointTable(); @@ -514,7 +514,7 @@ DetectMps(HKEY CpuKey, DbgPrint((DPRINT_HWDETECT, "MP Floating Point Table at: %x\n", - (U32)FpTable)); + (ULONG)FpTable)); if (FpTable->FeatureByte[0] == 0) { @@ -530,7 +530,7 @@ DetectMps(HKEY CpuKey, Offset = sizeof(MP_CONFIGURATION_TABLE); while (Offset < ConfigTable->BaseTableLength) { - Ptr = (char*)((U32)ConfigTable + Offset); + Ptr = (char*)((ULONG)ConfigTable + Offset); switch (*Ptr) { @@ -548,9 +548,9 @@ DetectMps(HKEY CpuKey, DbgPrint((DPRINT_HWDETECT, "Processor %u: x86 Family %u Model %u Stepping %u\n", CpuEntry->LocalApicId, - (U32)((CpuEntry->CpuSignature >> 8) & 0x0F), - (U32)((CpuEntry->CpuSignature >> 4) & 0x0F), - (U32)(CpuEntry->CpuSignature & 0x0F))); + (ULONG)((CpuEntry->CpuSignature >> 8) & 0x0F), + (ULONG)((CpuEntry->CpuSignature >> 4) & 0x0F), + (ULONG)(CpuEntry->CpuSignature & 0x0F))); SetMpsProcessor(CpuKey, FpuKey, CpuEntry); Offset += 0x14; @@ -577,7 +577,7 @@ DetectMps(HKEY CpuKey, break; default: - DbgPrint((DPRINT_HWDETECT, "Unknown Entry %u\n",(U32)*Ptr)); + DbgPrint((DPRINT_HWDETECT, "Unknown Entry %u\n",(ULONG)*Ptr)); return FALSE; } } @@ -599,11 +599,11 @@ DetectMps(HKEY CpuKey, VOID -DetectCPUs(HKEY SystemKey) +DetectCPUs(FRLDRHKEY SystemKey) { - HKEY CpuKey; - HKEY FpuKey; - S32 Error; + FRLDRHKEY CpuKey; + FRLDRHKEY FpuKey; + LONG Error; /* Create the 'CentralProcessor' key */ Error = RegCreateKey(SystemKey, diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hwpci.c b/reactos/boot/freeldr/freeldr/arch/i386/hwpci.c index 2285a7f9391..c4cba0ad12c 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hwpci.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hwpci.c @@ -30,40 +30,40 @@ typedef struct _ROUTING_SLOT { - U8 BusNumber; - U8 DeviceNumber; - U8 LinkA; - U16 BitmapA; - U8 LinkB; - U16 BitmapB; - U8 LinkC; - U16 BitmapC; - U8 LinkD; - U16 BitmapD; - U8 SlotNumber; - U8 Reserved; + UCHAR BusNumber; + UCHAR DeviceNumber; + UCHAR LinkA; + USHORT BitmapA; + UCHAR LinkB; + USHORT BitmapB; + UCHAR LinkC; + USHORT BitmapC; + UCHAR LinkD; + USHORT BitmapD; + UCHAR SlotNumber; + UCHAR Reserved; } __attribute__((packed)) ROUTING_SLOT, *PROUTING_SLOT; typedef struct _PCI_IRQ_ROUTING_TABLE { - U32 Signature; - U16 Version; - U16 Size; - U8 RouterBus; - U8 RouterSlot; - U16 ExclusiveIRQs; - U32 CompatibleRouter; - U32 MiniportData; - U8 Reserved[11]; - U8 Checksum; + ULONG Signature; + USHORT Version; + USHORT Size; + UCHAR RouterBus; + UCHAR RouterSlot; + USHORT ExclusiveIRQs; + ULONG CompatibleRouter; + ULONG MiniportData; + UCHAR Reserved[11]; + UCHAR Checksum; ROUTING_SLOT Slot[1]; } __attribute__((packed)) PCI_IRQ_ROUTING_TABLE, *PPCI_IRQ_ROUTING_TABLE; typedef struct _CM_PCI_BUS_DATA { - U8 BusCount; - U16 PciVersion; - U8 HardwareMechanism; + UCHAR BusCount; + USHORT PciVersion; + UCHAR HardwareMechanism; } __attribute__((packed)) CM_PCI_BUS_DATA, *PCM_PCI_BUS_DATA; @@ -71,19 +71,19 @@ static PPCI_IRQ_ROUTING_TABLE GetPciIrqRoutingTable(VOID) { PPCI_IRQ_ROUTING_TABLE Table; - PU8 Ptr; - U32 Sum; - U32 i; + PUCHAR Ptr; + ULONG Sum; + ULONG i; Table = (PPCI_IRQ_ROUTING_TABLE)0xF0000; - while ((U32)Table < 0x100000) + while ((ULONG)Table < 0x100000) { if (Table->Signature == 0x52495024) { DbgPrint((DPRINT_HWDETECT, "Found signature\n")); - Ptr = (PU8)Table; + Ptr = (PUCHAR)Table; Sum = 0; for (i = 0; i < Table->Size; i++) { @@ -103,7 +103,7 @@ GetPciIrqRoutingTable(VOID) return Table; } - Table = (PPCI_IRQ_ROUTING_TABLE)((U32)Table + 0x10); + Table = (PPCI_IRQ_ROUTING_TABLE)((ULONG)Table + 0x10); } return NULL; @@ -145,14 +145,14 @@ FindPciBios(PCM_PCI_BUS_DATA BusData) static VOID -DetectPciIrqRoutingTable(HKEY BusKey) +DetectPciIrqRoutingTable(FRLDRHKEY BusKey) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PPCI_IRQ_ROUTING_TABLE Table; - HKEY TableKey; - U32 Size; - S32 Error; + FRLDRHKEY TableKey; + ULONG Size; + LONG Error; Table = GetPciIrqRoutingTable(); if (Table != NULL) @@ -178,7 +178,7 @@ DetectPciIrqRoutingTable(HKEY BusKey) Error = RegSetValue(TableKey, "Identifier", REG_SZ, - (PU8)"PCI Real-mode IRQ Routing Table", + (PUCHAR)"PCI Real-mode IRQ Routing Table", 32); if (Error != ERROR_SUCCESS) { @@ -216,7 +216,7 @@ DetectPciIrqRoutingTable(HKEY BusKey) Error = RegSetValue(TableKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -231,17 +231,17 @@ DetectPciIrqRoutingTable(HKEY BusKey) VOID -DetectPciBios(HKEY SystemKey, U32 *BusNumber) +DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber) { PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; CM_PCI_BUS_DATA BusData; char Buffer[80]; - HKEY BiosKey; - U32 Size; - S32 Error; + FRLDRHKEY BiosKey; + ULONG Size; + LONG Error; #if 0 - HKEY BusKey; - U32 i; + FRLDRHKEY BusKey; + ULONG i; #endif /* Report the PCI BIOS */ @@ -272,7 +272,7 @@ DetectPciBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BiosKey, "Identifier", REG_SZ, - (PU8)"PCI BIOS", + (PUCHAR)"PCI BIOS", 9); if (Error != ERROR_SUCCESS) { @@ -301,7 +301,7 @@ DetectPciBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BiosKey, "Configuration Data", REG_FULL_RESOURCE_DESCRIPTOR, - (PU8) FullResourceDescriptor, + (PUCHAR) FullResourceDescriptor, Size); MmFreeMemory(FullResourceDescriptor); if (Error != ERROR_SUCCESS) @@ -322,7 +322,7 @@ DetectPciBios(HKEY SystemKey, U32 *BusNumber) */ /* Report PCI buses */ - for (i = 0; i < (U32)BusData.BusCount; i++) + for (i = 0; i < (ULONG)BusData.BusCount; i++) { sprintf(Buffer, "MultifunctionAdapter\\%u", *BusNumber); @@ -350,7 +350,7 @@ DetectPciBios(HKEY SystemKey, U32 *BusNumber) Error = RegSetValue(BusKey, "Identifier", REG_SZ, - (PU8)"PCI", + (PUCHAR)"PCI", 4); if (Error != ERROR_SUCCESS) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/i386disk.c b/reactos/boot/freeldr/freeldr/arch/i386/i386disk.c index 46c3116cc58..cc0bdb3ffc7 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/i386disk.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/i386disk.c @@ -18,13 +18,7 @@ */ #include "freeldr.h" -#include "disk.h" -#include "rtl.h" -#include "arch.h" #include "debug.h" -#include "portio.h" -#include "machine.h" - ///////////////////////////////////////////////////////////////////////////////////////////// // FUNCTIONS @@ -32,7 +26,7 @@ #ifdef __i386__ -BOOL DiskResetController(U32 DriveNumber) +BOOL DiskResetController(ULONG DriveNumber) { REGS RegsIn; REGS RegsOut; @@ -55,7 +49,7 @@ BOOL DiskResetController(U32 DriveNumber) return INT386_SUCCESS(RegsOut); } -BOOL DiskInt13ExtensionsSupported(U32 DriveNumber) +BOOL DiskInt13ExtensionsSupported(ULONG DriveNumber) { REGS RegsIn; REGS RegsOut; @@ -133,11 +127,11 @@ VOID DiskStopFloppyMotor(VOID) WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0); } -BOOL DiskGetExtendedDriveParameters(U32 DriveNumber, PVOID Buffer, U16 BufferSize) +BOOL DiskGetExtendedDriveParameters(ULONG DriveNumber, PVOID Buffer, USHORT BufferSize) { REGS RegsIn; REGS RegsOut; - PU16 Ptr = (PU16)(BIOSCALLBUFFER); + PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER); DbgPrint((DPRINT_DISK, "DiskGetExtendedDriveParameters()\n")); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/i386rtl.c b/reactos/boot/freeldr/freeldr/arch/i386/i386rtl.c index 281ffa37901..0612acee30e 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/i386rtl.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/i386rtl.c @@ -18,9 +18,6 @@ */ #include -#include -#include -#include void beep(void) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/i386vid.c b/reactos/boot/freeldr/freeldr/arch/i386/i386vid.c index 59f5af2652f..6ee0e0a59e1 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/i386vid.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/i386vid.c @@ -30,31 +30,31 @@ typedef struct { - U8 Signature[4]; // (ret) signature ("VESA") + UCHAR Signature[4]; // (ret) signature ("VESA") // (call) VESA 2.0 request signature ("VBE2"), required to receive // version 2.0 info - U16 VesaVersion; // VESA version number (one-digit minor version -- 0102h = v1.2) - U32 OemNamePtr; // pointer to OEM name + USHORT VesaVersion; // VESA version number (one-digit minor version -- 0102h = v1.2) + ULONG OemNamePtr; // pointer to OEM name // "761295520" for ATI - U32 Capabilities; // capabilities flags (see #00078) - U32 SupportedModeListPtr; // pointer to list of supported VESA and OEM video modes + ULONG Capabilities; // capabilities flags (see #00078) + ULONG SupportedModeListPtr; // pointer to list of supported VESA and OEM video modes // (list of words terminated with FFFFh) - U16 TotalVideoMemory; // total amount of video memory in 64K blocks + USHORT TotalVideoMemory; // total amount of video memory in 64K blocks // ---VBE v1.x --- - //U8 Reserved[236]; + //UCHAR Reserved[236]; // ---VBE v2.0 --- - U16 OemSoftwareVersion; // OEM software version (BCD, high byte = major, low byte = minor) - U32 VendorNamePtr; // pointer to vendor name - U32 ProductNamePtr; // pointer to product name - U32 ProductRevisionStringPtr; // pointer to product revision string - U16 VBE_AF_Version; // (if capabilities bit 3 set) VBE/AF version (BCD) + USHORT OemSoftwareVersion; // OEM software version (BCD, high byte = major, low byte = minor) + ULONG VendorNamePtr; // pointer to vendor name + ULONG ProductNamePtr; // pointer to product name + ULONG ProductRevisionStringPtr; // pointer to product revision string + USHORT VBE_AF_Version; // (if capabilities bit 3 set) VBE/AF version (BCD) // 0100h for v1.0P - U32 AcceleratedModeListPtr; // (if capabilities bit 3 set) pointer to list of supported + ULONG AcceleratedModeListPtr; // (if capabilities bit 3 set) pointer to list of supported // accelerated video modes (list of words terminated with FFFFh) - U8 Reserved[216]; // reserved for VBE implementation - U8 ScratchPad[256]; // OEM scratchpad (for OEM strings, etc.) + UCHAR Reserved[216]; // reserved for VBE implementation + UCHAR ScratchPad[256]; // OEM scratchpad (for OEM strings, etc.) } PACKED VESA_SVGA_INFO, *PVESA_SVGA_INFO; // Bitfields for VESA capabilities: @@ -106,11 +106,11 @@ VOID BiosSetVideoFont8x16(VOID) Int386(0x10, &Regs, &Regs); } -VOID VideoSetTextCursorPosition(U32 X, U32 Y) +VOID VideoSetTextCursorPosition(ULONG X, ULONG Y) { } -U32 VideoGetTextCursorPositionX(VOID) +ULONG VideoGetTextCursorPositionX(VOID) { REGS Regs; @@ -135,7 +135,7 @@ U32 VideoGetTextCursorPositionX(VOID) return Regs.b.dl; } -U32 VideoGetTextCursorPositionY(VOID) +ULONG VideoGetTextCursorPositionY(VOID) { REGS Regs; @@ -160,13 +160,13 @@ U32 VideoGetTextCursorPositionY(VOID) return Regs.b.dh; } -U16 BiosIsVesaSupported(VOID) +USHORT BiosIsVesaSupported(VOID) { REGS Regs; PVESA_SVGA_INFO SvgaInfo = (PVESA_SVGA_INFO)BIOSCALLBUFFER; #ifdef DEBUG - //U16* VideoModes; - //U16 Index; + //USHORT* VideoModes; + //USHORT Index; #endif // defined DEBUG DbgPrint((DPRINT_UI, "BiosIsVesaSupported()\n")); @@ -227,7 +227,7 @@ U16 BiosIsVesaSupported(VOID) DbgPrint((DPRINT_UI, "SvgaInfo->VBE/AF Version = 0x%x (BCD WORD)\n", SvgaInfo->VBE_AF_Version)); //DbgPrint((DPRINT_UI, "\nSupported VESA and OEM video modes:\n")); - //VideoModes = (U16*)SvgaInfo->SupportedModeListPtr; + //VideoModes = (USHORT*)SvgaInfo->SupportedModeListPtr; //for (Index=0; VideoModes[Index]!=0xFFFF; Index++) //{ // DbgPrint((DPRINT_UI, "Mode %d: 0x%x\n", Index, VideoModes[Index])); @@ -236,7 +236,7 @@ U16 BiosIsVesaSupported(VOID) //if (SvgaInfo->VesaVersion >= 0x0200) //{ // DbgPrint((DPRINT_UI, "\nSupported accelerated video modes (VESA v2.0):\n")); - // VideoModes = (U16*)SvgaInfo->AcceleratedModeListPtr; + // VideoModes = (USHORT*)SvgaInfo->AcceleratedModeListPtr; // for (Index=0; VideoModes[Index]!=0xFFFF; Index++) // { // DbgPrint((DPRINT_UI, "Mode %d: 0x%x\n", Index, VideoModes[Index])); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/machpc.h b/reactos/boot/freeldr/freeldr/arch/i386/machpc.h index 656bf451d9b..5462a10effa 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/machpc.h +++ b/reactos/boot/freeldr/freeldr/arch/i386/machpc.h @@ -32,28 +32,28 @@ VOID PcConsPutChar(int Ch); BOOL PcConsKbHit(); int PcConsGetCh(); -VOID PcVideoClearScreen(U8 Attr); +VOID PcVideoClearScreen(UCHAR Attr); VIDEODISPLAYMODE PcVideoSetDisplayMode(char *DisplayMode, BOOL Init); -VOID PcVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth); -U32 PcVideoGetBufferSize(VOID); -VOID PcVideoSetTextCursorPosition(U32 X, U32 Y); +VOID PcVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth); +ULONG PcVideoGetBufferSize(VOID); +VOID PcVideoSetTextCursorPosition(ULONG X, ULONG Y); VOID PcVideoHideShowTextCursor(BOOL Show); -VOID PcVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y); +VOID PcVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y); VOID PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer); BOOL PcVideoIsPaletteFixed(VOID); -VOID PcVideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue); -VOID PcVideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue); +VOID PcVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue); +VOID PcVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue); VOID PcVideoSync(VOID); VOID PcVideoPrepareForReactOS(VOID); -U32 PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize); +ULONG PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize); -BOOL PcDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); -BOOL PcDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); -BOOL PcDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry); -U32 PcDiskGetCacheableBlockCount(U32 DriveNumber); +BOOL PcDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); +BOOL PcDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); +BOOL PcDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry); +ULONG PcDiskGetCacheableBlockCount(ULONG DriveNumber); -VOID PcRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second); +VOID PcRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); VOID PcHwDetect(VOID); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/machxbox.h b/reactos/boot/freeldr/freeldr/arch/i386/machxbox.h index 13ce64c94e5..845f242e8b0 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/machxbox.h +++ b/reactos/boot/freeldr/freeldr/arch/i386/machxbox.h @@ -24,7 +24,7 @@ #include "mm.h" #endif -U8 XboxFont8x16[256 * 16]; +UCHAR XboxFont8x16[256 * 16]; VOID XboxMachInit(VOID); @@ -33,30 +33,30 @@ BOOL XboxConsKbHit(); int XboxConsGetCh(); VOID XboxVideoInit(VOID); -VOID XboxVideoClearScreen(U8 Attr); +VOID XboxVideoClearScreen(UCHAR Attr); VIDEODISPLAYMODE XboxVideoSetDisplayMode(char *DisplayModem, BOOL Init); -VOID XboxVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth); -U32 XboxVideoGetBufferSize(VOID); -VOID XboxVideoSetTextCursorPosition(U32 X, U32 Y); +VOID XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth); +ULONG XboxVideoGetBufferSize(VOID); +VOID XboxVideoSetTextCursorPosition(ULONG X, ULONG Y); VOID XboxVideoHideShowTextCursor(BOOL Show); -VOID XboxVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y); +VOID XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y); VOID XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer); BOOL XboxVideoIsPaletteFixed(VOID); -VOID XboxVideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue); -VOID XboxVideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue); +VOID XboxVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue); +VOID XboxVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue); VOID XboxVideoSync(VOID); VOID XboxVideoPrepareForReactOS(VOID); VOID XboxMemInit(VOID); -PVOID XboxMemReserveMemory(U32 MbToReserve); -U32 XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize); +PVOID XboxMemReserveMemory(ULONG MbToReserve); +ULONG XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize); -BOOL XboxDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); -BOOL XboxDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); -BOOL XboxDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry); -U32 XboxDiskGetCacheableBlockCount(U32 DriveNumber); +BOOL XboxDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); +BOOL XboxDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); +BOOL XboxDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry); +ULONG XboxDiskGetCacheableBlockCount(ULONG DriveNumber); -VOID XboxRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second); +VOID XboxRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); VOID XboxHwDetect(VOID); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/mb.S b/reactos/boot/freeldr/freeldr/arch/i386/mb.S index e77b380f4bb..78a3f49aeb2 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/mb.S +++ b/reactos/boot/freeldr/freeldr/arch/i386/mb.S @@ -29,116 +29,29 @@ * This boots the kernel */ .code32 -EXTERN(_boot_reactos) - call _MachVideoPrepareForReactOS + .globl _PageDirectoryStart + + .globl _startup_pagedirectory + .globl _lowmem_pagetable + .globl _kernel_pagetable + .globl _hyperspace_pagetable + .globl _apic_pagetable + .globl _kpcr_pagetable - call _multi_boot - - // Should never get here - cli -bootloop: - hlt - jmp bootloop - - - /* - * After you have setup the _mb_header and _mb_info structures - * then call this routine to transfer control to the kernel. - */ -EXTERN(_multi_boot) - - cli - - /* - * Load the absolute address of the multiboot information structure - */ - movl $_mb_info,%ebx - - /* - * Initalize eflags - */ - pushl $0 - popfl - - /* - * Load the multiboot magic value into eax - */ - movl $0x2badb002,%eax - - /* - * Jump to start of 32 bit code at 0xc0000000 + 0x1000 - */ - - pushl $KERNEL_CS - pushl _mb_entry_addr - lretl - - -EXTERN(_mb_header) -_mb_magic: - .long 0 // unsigned long magic; -_mb_flags: - .long 0 // unsigned long flags; -_mb_checksum: - .long 0 // unsigned long checksum; -_mb_header_addr: - .long 0 // unsigned long header_addr; -_mb_load_addr: - .long 0 // unsigned long load_addr; -_mb_load_end_addr: - .long 0 // unsigned long load_end_addr; -_mb_bss_end_addr: - .long 0 // unsigned long bss_end_addr; -_mb_entry_addr: - .long 0 // unsigned long entry_addr; + .globl _startup_pagedirectorytable_pae + .globl _startup_pagedirectory_pae + .globl _lowmem_pagetable_pae + .globl _kernel_pagetable_pae + .globl _hyperspace_pagetable_pae + .globl _apic_pagetable_pae + .globl _kpcr_pagetable_pae + + .globl _PageDirectoryEnd // // Boot information structure // -EXTERN(_mb_info) -_multiboot_flags: - .long 0 -_multiboot_mem_lower: - .long 0 -_multiboot_mem_upper: - .long 0 -_multiboot_boot_device: - .long 0 -_multiboot_cmdline: - .long 0 -_multiboot_mods_count: - .long 0 -_multiboot_mods_addr: - .long 0 -_multiboot_syms: - .rept 12 - .byte 0 - .endr -_multiboot_mmap_length: - .long 0 -_multiboot_mmap_addr: - .long 0 -_multiboot_drives_count: - .long 0 -_multiboot_drives_addr: - .long 0 -_multiboot_config_table: - .long 0 -_multiboot_boot_loader_name: - .long 0 -_multiboot_apm_table: - .long 0 - -EXTERN(_multiboot_modules) - .rept (64 * /*multiboot_module_size*/ 16) - .byte 0 - .endr -EXTERN(_multiboot_module_strings) - .rept (64*256) - .byte 0 - .endr - EXTERN(_multiboot_memory_map_descriptor_size) .long 0 @@ -147,7 +60,44 @@ EXTERN(_multiboot_memory_map) .byte 0 .endr -EXTERN(_multiboot_kernel_cmdline) - .rept 255 - .byte 0 - .endr +.bss +_PageDirectoryStart: +_startup_pagedirectory: + .fill 4096, 1, 0 + +_lowmem_pagetable: + .fill 4096, 1, 0 + +_kernel_pagetable: + .fill 2*4096, 1, 0 + +_hyperspace_pagetable: + .fill 4096, 1, 0 + +_apic_pagetable: + .fill 4096, 1, 0 + +_kpcr_pagetable: + .fill 4096, 1, 0 + +_startup_pagedirectory_pae: + .fill 4 * 4096, 1, 0 + +_lowmem_pagetable_pae: + .fill 2 * 4096, 1, 0 + +_kernel_pagetable_pae: + .fill 3*4096, 1, 0 + +_hyperspace_pagetable_pae: + .fill 2*4096, 1, 0 + +_apic_pagetable_pae: + .fill 2*4096, 1, 0 + +_kpcr_pagetable_pae: + .fill 4*4096, 1, 0 + +_startup_pagedirectorytable_pae: + .fill 4096, 1, 0 +_PageDirectoryEnd: diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c b/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c index b915141c399..5e344bbe3cf 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcdisk.c @@ -29,13 +29,13 @@ typedef struct { - U8 PacketSize; // 00h - Size of packet (10h or 18h) - U8 Reserved; // 01h - Reserved (0) - U16 LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD) - U16 TransferBufferOffset; // 04h - Transfer buffer offset (seg:off) - U16 TransferBufferSegment; // Transfer buffer segment (seg:off) - U64 LBAStartBlock; // 08h - Starting absolute block number - U64 TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer + UCHAR PacketSize; // 00h - Size of packet (10h or 18h) + UCHAR Reserved; // 01h - Reserved (0) + USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD) + USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off) + USHORT TransferBufferSegment; // Transfer buffer segment (seg:off) + ULONGLONG LBAStartBlock; // 08h - Starting absolute block number + ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer // used if DWORD at 04h is FFFFh:FFFFh } PACKED I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET; @@ -43,7 +43,7 @@ typedef struct // FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////// -static BOOL PcDiskResetController(U32 DriveNumber) +static BOOL PcDiskResetController(ULONG DriveNumber) { REGS RegsIn; REGS RegsOut; @@ -66,11 +66,11 @@ static BOOL PcDiskResetController(U32 DriveNumber) return INT386_SUCCESS(RegsOut); } -static BOOL PcDiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +static BOOL PcDiskReadLogicalSectorsLBA(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) { REGS RegsIn; REGS RegsOut; - U32 RetryCount; + ULONG RetryCount; PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER); DbgPrint((DPRINT_DISK, "PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer)); @@ -86,8 +86,8 @@ static BOOL PcDiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 S Packet->PacketSize = sizeof(I386_DISK_ADDRESS_PACKET); Packet->Reserved = 0; Packet->LBABlockCount = SectorCount; - Packet->TransferBufferOffset = ((U32)Buffer) & 0x0F; - Packet->TransferBufferSegment = ((U32)Buffer) >> 4; + Packet->TransferBufferOffset = ((ULONG)Buffer) & 0x0F; + Packet->TransferBufferSegment = ((ULONG)Buffer) >> 4; Packet->LBAStartBlock = SectorNumber; Packet->TransferBuffer64 = 0; @@ -130,23 +130,25 @@ static BOOL PcDiskReadLogicalSectorsLBA(U32 DriveNumber, U64 SectorNumber, U32 S return FALSE; } -static BOOL PcDiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +static BOOL PcDiskReadLogicalSectorsCHS(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) { - U32 PhysicalSector; - U32 PhysicalHead; - U32 PhysicalTrack; + ULONG PhysicalSector; + ULONG PhysicalHead; + ULONG PhysicalTrack; GEOMETRY DriveGeometry; - U32 NumberOfSectorsToRead; + ULONG NumberOfSectorsToRead; REGS RegsIn; REGS RegsOut; - U32 RetryCount; + ULONG RetryCount; DbgPrint((DPRINT_DISK, "PcDiskReadLogicalSectorsCHS()\n")); // // Get the drive geometry // - if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry)) + if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) || + DriveGeometry.Sectors == 0 || + DriveGeometry.Heads == 0) { return FALSE; } @@ -213,8 +215,8 @@ static BOOL PcDiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 S RegsIn.b.cl = (PhysicalSector + ((PhysicalTrack & 0x300) >> 2)); RegsIn.b.dh = PhysicalHead; RegsIn.b.dl = DriveNumber; - RegsIn.w.es = ((U32)Buffer) >> 4; - RegsIn.w.bx = ((U32)Buffer) & 0x0F; + RegsIn.w.es = ((ULONG)Buffer) >> 4; + RegsIn.w.bx = ((ULONG)Buffer) & 0x0F; // // Perform the read @@ -264,9 +266,9 @@ static BOOL PcDiskReadLogicalSectorsCHS(U32 DriveNumber, U64 SectorNumber, U32 S return TRUE; } -static BOOL PcDiskInt13ExtensionsSupported(U32 DriveNumber) +static BOOL PcDiskInt13ExtensionsSupported(ULONG DriveNumber) { - static U32 LastDriveNumber = 0xffffffff; + static ULONG LastDriveNumber = 0xffffffff; static BOOL LastSupported; REGS RegsIn; REGS RegsOut; @@ -353,7 +355,7 @@ static BOOL PcDiskInt13ExtensionsSupported(U32 DriveNumber) return TRUE; } -BOOL PcDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +BOOL PcDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) { DbgPrint((DPRINT_DISK, "PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer)); @@ -383,18 +385,18 @@ BOOL PcDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount } BOOL -PcDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +PcDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { /* Just use the standard routine */ return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); } BOOL -PcDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY Geometry) +PcDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY Geometry) { REGS RegsIn; REGS RegsOut; - U32 Cylinders; + ULONG Cylinders; DbgPrint((DPRINT_DISK, "DiskGetDriveGeometry()\n")); @@ -440,8 +442,8 @@ PcDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY Geometry) return TRUE; } -U32 -PcDiskGetCacheableBlockCount(U32 DriveNumber) +ULONG +PcDiskGetCacheableBlockCount(ULONG DriveNumber) { GEOMETRY Geometry; diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c index bb5b409ef64..e9da602bab6 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c @@ -28,12 +28,12 @@ #include "portio.h" #include "rtl.h" -static U32 +static ULONG PcMemGetExtendedMemorySize(VOID) { REGS RegsIn; REGS RegsOut; - U32 MemorySize; + ULONG MemorySize; DbgPrint((DPRINT_MEMORY, "GetExtendedMemorySize()\n")); @@ -119,7 +119,7 @@ PcMemGetExtendedMemorySize(VOID) return MemorySize; } -static U32 +static ULONG PcMemGetConventionalMemorySize(VOID) { REGS Regs; @@ -141,14 +141,14 @@ PcMemGetConventionalMemorySize(VOID) DbgPrint((DPRINT_MEMORY, "Int12h\n")); DbgPrint((DPRINT_MEMORY, "AX = 0x%x\n\n", Regs.w.ax)); - return (U32)Regs.w.ax; + return (ULONG)Regs.w.ax; } -static U32 -PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) +static ULONG +PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) { REGS Regs; - U32 MapCount; + ULONG MapCount; DbgPrint((DPRINT_MEMORY, "GetBiosMemoryMap()\n")); @@ -225,10 +225,10 @@ PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) return MapCount; } -U32 -PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) +ULONG +PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) { - U32 EntryCount; + ULONG EntryCount; EntryCount = PcMemGetBiosMemoryMap(BiosMemoryMap, MaxMemoryMapSize); diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcrtc.c b/reactos/boot/freeldr/freeldr/arch/i386/pcrtc.c index c6823d064e5..aad76981444 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcrtc.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcrtc.c @@ -25,7 +25,7 @@ #define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f)) VOID -PcRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second) +PcRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second) { REGS Regs; @@ -55,7 +55,7 @@ PcRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, if (NULL != Year) { - *Year = 100 * BCD_INT(Regs.b.cl) + BCD_INT(Regs.b.ch); + *Year = 100 * BCD_INT(Regs.b.ch) + BCD_INT(Regs.b.cl); } if (NULL != Month) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/pcvideo.c b/reactos/boot/freeldr/freeldr/arch/i386/pcvideo.c index a4bf82079dd..2baac362952 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/pcvideo.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/pcvideo.c @@ -56,69 +56,69 @@ typedef struct { - U16 ModeAttributes; /* mode attributes (see #00080) */ - U8 WindowAttributesA; /* window attributes, window A (see #00081) */ - U8 WindowsAttributesB; /* window attributes, window B (see #00081) */ - U16 WindowGranularity; /* window granularity in KB */ - U16 WindowSize; /* window size in KB */ - U16 WindowAStartSegment; /* start segment of window A (0000h if not supported) */ - U16 WindowBStartSegment; /* start segment of window B (0000h if not supported) */ - U32 WindowPositioningFunction; /* -> FAR window positioning function (equivalent to AX=4F05h) */ - U16 BytesPerScanLine; /* bytes per scan line */ + USHORT ModeAttributes; /* mode attributes (see #00080) */ + UCHAR WindowAttributesA; /* window attributes, window A (see #00081) */ + UCHAR WindowsAttributesB; /* window attributes, window B (see #00081) */ + USHORT WindowGranularity; /* window granularity in KB */ + USHORT WindowSize; /* window size in KB */ + USHORT WindowAStartSegment; /* start segment of window A (0000h if not supported) */ + USHORT WindowBStartSegment; /* start segment of window B (0000h if not supported) */ + ULONG WindowPositioningFunction; /* -> FAR window positioning function (equivalent to AX=4F05h) */ + USHORT BytesPerScanLine; /* bytes per scan line */ /* ---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes--- */ - U16 WidthInPixels; /* width in pixels (graphics) or characters (text) */ - U16 HeightInPixels; /* height in pixels (graphics) or characters (text) */ - U8 CharacterWidthInPixels; /* width of character cell in pixels */ - U8 CharacterHeightInPixels; /* height of character cell in pixels */ - U8 NumberOfMemoryPlanes; /* number of memory planes */ - U8 BitsPerPixel; /* number of bits per pixel */ - U8 NumberOfBanks; /* number of banks */ - U8 MemoryModel; /* memory model type (see #00082) */ - U8 BankSize; /* size of bank in KB */ - U8 NumberOfImagePanes; /* number of image pages (less one) that will fit in video RAM */ - U8 Reserved1; /* reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) */ + USHORT WidthInPixels; /* width in pixels (graphics) or characters (text) */ + USHORT HeightInPixels; /* height in pixels (graphics) or characters (text) */ + UCHAR CharacterWidthInPixels; /* width of character cell in pixels */ + UCHAR CharacterHeightInPixels; /* height of character cell in pixels */ + UCHAR NumberOfMemoryPlanes; /* number of memory planes */ + UCHAR BitsPerPixel; /* number of bits per pixel */ + UCHAR NumberOfBanks; /* number of banks */ + UCHAR MemoryModel; /* memory model type (see #00082) */ + UCHAR BankSize; /* size of bank in KB */ + UCHAR NumberOfImagePanes; /* number of image pages (less one) that will fit in video RAM */ + UCHAR Reserved1; /* reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) */ /* ---VBE v1.2+ --- */ - U8 RedMaskSize; /* red mask size */ - U8 RedMaskPosition; /* red field position */ - U8 GreenMaskSize; /* green mask size */ - U8 GreenMaskPosition; /* green field size */ - U8 BlueMaskSize; /* blue mask size */ - U8 BlueMaskPosition; /* blue field size */ - U8 ReservedMaskSize; /* reserved mask size */ - U8 ReservedMaskPosition; /* reserved mask position */ - U8 DirectColorModeInfo; /* direct color mode info */ + UCHAR RedMaskSize; /* red mask size */ + UCHAR RedMaskPosition; /* red field position */ + UCHAR GreenMaskSize; /* green mask size */ + UCHAR GreenMaskPosition; /* green field size */ + UCHAR BlueMaskSize; /* blue mask size */ + UCHAR BlueMaskPosition; /* blue field size */ + UCHAR ReservedMaskSize; /* reserved mask size */ + UCHAR ReservedMaskPosition; /* reserved mask position */ + UCHAR DirectColorModeInfo; /* direct color mode info */ /* bit 0:Color ramp is programmable */ /* bit 1:Bytes in reserved field may be used by application */ /* ---VBE v2.0+ --- */ - U32 LinearVideoBufferAddress; /* physical address of linear video buffer */ - U32 OffscreenMemoryPointer; /* pointer to start of offscreen memory */ - U16 OffscreenMemorySize; /* KB of offscreen memory */ + ULONG LinearVideoBufferAddress; /* physical address of linear video buffer */ + ULONG OffscreenMemoryPointer; /* pointer to start of offscreen memory */ + USHORT OffscreenMemorySize; /* KB of offscreen memory */ /* ---VBE v3.0 --- */ - U16 LinearBytesPerScanLine; /* bytes per scan line in linear modes */ - U8 BankedNumberOfImages; /* number of images (less one) for banked video modes */ - U8 LinearNumberOfImages; /* number of images (less one) for linear video modes */ - U8 LinearRedMaskSize; /* linear modes:Size of direct color red mask (in bits) */ - U8 LinearRedMaskPosition; /* linear modes:Bit position of red mask LSB (e.g. shift count) */ - U8 LinearGreenMaskSize; /* linear modes:Size of direct color green mask (in bits) */ - U8 LinearGreenMaskPosition; /* linear modes:Bit position of green mask LSB (e.g. shift count) */ - U8 LinearBlueMaskSize; /* linear modes:Size of direct color blue mask (in bits) */ - U8 LinearBlueMaskPosition; /* linear modes:Bit position of blue mask LSB (e.g. shift count) */ - U8 LinearReservedMaskSize; /* linear modes:Size of direct color reserved mask (in bits) */ - U8 LinearReservedMaskPosition; /* linear modes:Bit position of reserved mask LSB */ - U32 MaximumPixelClock; /* maximum pixel clock for graphics video mode, in Hz */ - U8 Reserved2[190]; /* 190 BYTEs reserved (0) */ + USHORT LinearBytesPerScanLine; /* bytes per scan line in linear modes */ + UCHAR BankedNumberOfImages; /* number of images (less one) for banked video modes */ + UCHAR LinearNumberOfImages; /* number of images (less one) for linear video modes */ + UCHAR LinearRedMaskSize; /* linear modes:Size of direct color red mask (in bits) */ + UCHAR LinearRedMaskPosition; /* linear modes:Bit position of red mask LSB (e.g. shift count) */ + UCHAR LinearGreenMaskSize; /* linear modes:Size of direct color green mask (in bits) */ + UCHAR LinearGreenMaskPosition; /* linear modes:Bit position of green mask LSB (e.g. shift count) */ + UCHAR LinearBlueMaskSize; /* linear modes:Size of direct color blue mask (in bits) */ + UCHAR LinearBlueMaskPosition; /* linear modes:Bit position of blue mask LSB (e.g. shift count) */ + UCHAR LinearReservedMaskSize; /* linear modes:Size of direct color reserved mask (in bits) */ + UCHAR LinearReservedMaskPosition; /* linear modes:Bit position of reserved mask LSB */ + ULONG MaximumPixelClock; /* maximum pixel clock for graphics video mode, in Hz */ + UCHAR Reserved2[190]; /* 190 BYTEs reserved (0) */ } PACKED SVGA_MODE_INFORMATION, *PSVGA_MODE_INFORMATION; -static U32 BiosVideoMode; /* Current video mode as known by BIOS */ -static U32 ScreenWidth = 80; /* Screen Width in characters */ -static U32 ScreenHeight = 25; /* Screen Height in characters */ -static U32 BytesPerScanLine = 160; /* Number of bytes per scanline (delta) */ +static ULONG BiosVideoMode; /* Current video mode as known by BIOS */ +static ULONG ScreenWidth = 80; /* Screen Width in characters */ +static ULONG ScreenHeight = 25; /* Screen Height in characters */ +static ULONG BytesPerScanLine = 160; /* Number of bytes per scanline (delta) */ static VIDEODISPLAYMODE DisplayMode = VideoTextMode; /* Current display mode */ static BOOL VesaVideoMode = FALSE; /* Are we using a VESA mode? */ static SVGA_MODE_INFORMATION VesaVideoModeInformation; /* Only valid when in VESA mode */ -static U32 CurrentMemoryBank = 0; /* Currently selected VESA bank */ +static ULONG CurrentMemoryBank = 0; /* Currently selected VESA bank */ -static U32 +static ULONG PcVideoDetectVideoCard(VOID) { REGS Regs; @@ -192,7 +192,7 @@ PcVideoDetectVideoCard(VOID) } } -static VOID PcVideoSetBiosMode(U32 VideoMode) +static VOID PcVideoSetBiosMode(ULONG VideoMode) { REGS Regs; @@ -297,7 +297,7 @@ VOID PcVideoDisableCursorEmulation(VOID) } static VOID -PcVideoDefineCursor(U32 StartScanLine, U32 EndScanLine) +PcVideoDefineCursor(ULONG StartScanLine, ULONG EndScanLine) { REGS Regs; @@ -333,7 +333,7 @@ PcVideoDefineCursor(U32 StartScanLine, U32 EndScanLine) } static VOID -PcVideoSetVerticalResolution(U32 ScanLines) +PcVideoSetVerticalResolution(ULONG ScanLines) { REGS Regs; @@ -439,7 +439,7 @@ PcVideoSetDisplayEnd(VOID) } static BOOL -PcVideoVesaGetSVGAModeInformation(U16 Mode, PSVGA_MODE_INFORMATION ModeInformation) +PcVideoVesaGetSVGAModeInformation(USHORT Mode, PSVGA_MODE_INFORMATION ModeInformation) { REGS Regs; @@ -511,7 +511,7 @@ PcVideoVesaGetSVGAModeInformation(U16 Mode, PSVGA_MODE_INFORMATION ModeInformati } static BOOL -PcVideoSetBiosVesaMode(U16 Mode) +PcVideoSetBiosVesaMode(USHORT Mode) { REGS Regs; @@ -697,7 +697,7 @@ PcVideoSetMode80x60(VOID) } static BOOL -PcVideoSetMode(U32 NewMode) +PcVideoSetMode(ULONG NewMode) { CurrentMemoryBank = 0; @@ -735,7 +735,7 @@ PcVideoSetMode(U32 NewMode) { /* 640x480x16 */ PcVideoSetBiosMode(NewMode); - WRITE_PORT_USHORT((U16*)0x03CE, 0x0F01); /* For some reason this is necessary? */ + WRITE_PORT_USHORT((USHORT*)0x03CE, 0x0F01); /* For some reason this is necessary? */ ScreenWidth = 640; ScreenHeight = 480; BytesPerScanLine = 80; @@ -830,7 +830,7 @@ PcVideoSetBlinkBit(BOOL Enable) } static VOID -PcVideoSetMemoryBank(U16 BankNumber) +PcVideoSetMemoryBank(USHORT BankNumber) { REGS Regs; @@ -870,7 +870,7 @@ PcVideoSetMemoryBank(U16 BankNumber) VIDEODISPLAYMODE PcVideoSetDisplayMode(char *DisplayModeName, BOOL Init) { - U32 VideoMode = VIDEOMODE_NORMAL_TEXT; + ULONG VideoMode = VIDEOMODE_NORMAL_TEXT; if (NULL == DisplayModeName || '\0' == *DisplayModeName) { @@ -927,7 +927,7 @@ PcVideoSetDisplayMode(char *DisplayModeName, BOOL Init) } VOID -PcVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth) +PcVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) { *Width = ScreenWidth; *Height = ScreenHeight; @@ -950,14 +950,14 @@ PcVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth) } } -U32 +ULONG PcVideoGetBufferSize(VOID) { return ScreenHeight * BytesPerScanLine; } VOID -PcVideoSetTextCursorPosition(U32 X, U32 Y) +PcVideoSetTextCursorPosition(ULONG X, ULONG Y) { REGS Regs; @@ -997,10 +997,10 @@ PcVideoHideShowTextCursor(BOOL Show) VOID PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer) { - U32 BanksToCopy; - U32 BytesInLastBank; - U32 CurrentBank; - U32 BankSize; + ULONG BanksToCopy; + ULONG BytesInLastBank; + ULONG CurrentBank; + ULONG BankSize; /* PcVideoWaitForVerticalRetrace(); */ @@ -1036,14 +1036,14 @@ PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer) } VOID -PcVideoClearScreen(U8 Attr) +PcVideoClearScreen(UCHAR Attr) { - U16 AttrChar; - U16 *BufPtr; + USHORT AttrChar; + USHORT *BufPtr; - AttrChar = ((U16) Attr << 8) | ' '; - for (BufPtr = (U16 *) VIDEOTEXT_MEM_ADDRESS; - BufPtr < (U16 *) (VIDEOTEXT_MEM_ADDRESS + VIDEOTEXT_MEM_SIZE); + AttrChar = ((USHORT) Attr << 8) | ' '; + for (BufPtr = (USHORT *) VIDEOTEXT_MEM_ADDRESS; + BufPtr < (USHORT *) (VIDEOTEXT_MEM_ADDRESS + VIDEOTEXT_MEM_SIZE); BufPtr++) { *BufPtr = AttrChar; @@ -1051,12 +1051,12 @@ PcVideoClearScreen(U8 Attr) } VOID -PcVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y) +PcVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) { - U16 *BufPtr; + USHORT *BufPtr; - BufPtr = (U16 *) (VIDEOTEXT_MEM_ADDRESS + Y * BytesPerScanLine + X * 2); - *BufPtr = ((U16) Attr << 8) | (Ch & 0xff); + BufPtr = (USHORT *) (VIDEOTEXT_MEM_ADDRESS + Y * BytesPerScanLine + X * 2); + *BufPtr = ((USHORT) Attr << 8) | (Ch & 0xff); } BOOL @@ -1066,27 +1066,27 @@ PcVideoIsPaletteFixed(VOID) } VOID -PcVideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue) +PcVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue) { - WRITE_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_WRITE, Color); - WRITE_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA, Red); - WRITE_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA, Green); - WRITE_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA, Blue); + WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_WRITE, Color); + WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Red); + WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Green); + WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Blue); } VOID -PcVideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue) +PcVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue) { - WRITE_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_READ, Color); - *Red = READ_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA); - *Green = READ_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA); - *Blue = READ_PORT_UCHAR((U8*) VIDEOPORT_PALETTE_DATA); + WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_READ, Color); + *Red = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); + *Green = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); + *Blue = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); } VOID PcVideoSync(VOID) { - while (1 == (READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) + while (1 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) { /* * Keep reading the port until bit 3 is clear @@ -1096,7 +1096,7 @@ PcVideoSync(VOID) */ } - while (0 == (READ_PORT_UCHAR((U8*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) + while (0 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) { /* * Keep reading the port until bit 3 is set diff --git a/reactos/boot/freeldr/freeldr/arch/i386/portio.c b/reactos/boot/freeldr/freeldr/arch/i386/portio.c index ba3361aa4df..feebd228414 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/portio.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/portio.c @@ -51,37 +51,45 @@ #define SLOW_DOWN_IO __SLOW_DOWN_IO #endif -VOID /*STDCALL*/ +#undef READ_PORT_BUFFER_UCHAR +VOID +STDCALL READ_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Buffer, - U32 Count) + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; insb\n\t" : "=D" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -VOID /*STDCALL*/ -READ_PORT_BUFFER_USHORT (U16* Port, - U16* Buffer, - U32 Count) +#undef READ_PORT_BUFFER_USHORT +VOID +STDCALL +READ_PORT_BUFFER_USHORT (USHORT* Port, + USHORT* Buffer, + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; insw" : "=D" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -VOID /*STDCALL*/ -READ_PORT_BUFFER_ULONG (U32* Port, - U32* Buffer, - U32 Count) +#undef READ_PORT_BUFFER_ULONG +VOID +STDCALL +READ_PORT_BUFFER_ULONG (ULONG* Port, + ULONG* Buffer, + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; insl" : "=D" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -UCHAR /*STDCALL*/ +#undef READ_PORT_UCHAR +UCHAR +STDCALL READ_PORT_UCHAR (PUCHAR Port) { UCHAR Value; @@ -93,10 +101,12 @@ READ_PORT_UCHAR (PUCHAR Port) return(Value); } -U16 /*STDCALL*/ -READ_PORT_USHORT (U16* Port) +#undef READ_PORT_USHORT +USHORT +STDCALL +READ_PORT_USHORT (USHORT* Port) { - U16 Value; + USHORT Value; __asm__("inw %w1, %0\n\t" : "=a" (Value) @@ -105,10 +115,12 @@ READ_PORT_USHORT (U16* Port) return(Value); } -U32 /*STDCALL*/ -READ_PORT_ULONG (U32* Port) +#undef READ_PORT_ULONG +ULONG +STDCALL +READ_PORT_ULONG (ULONG* Port) { - U32 Value; + ULONG Value; __asm__("inl %w1, %0\n\t" : "=a" (Value) @@ -117,37 +129,45 @@ READ_PORT_ULONG (U32* Port) return(Value); } -VOID /*STDCALL*/ +#undef WRITE_PORT_BUFFER_UCHAR +VOID +STDCALL WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Buffer, - U32 Count) + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; outsb" : "=S" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -VOID /*STDCALL*/ -WRITE_PORT_BUFFER_USHORT (U16* Port, - U16* Buffer, - U32 Count) +#undef WRITE_PORT_BUFFER_USHORT +VOID +STDCALL +WRITE_PORT_BUFFER_USHORT (USHORT* Port, + USHORT* Buffer, + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; outsw" : "=S" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -VOID /*STDCALL*/ -WRITE_PORT_BUFFER_ULONG (U32* Port, - U32* Buffer, - U32 Count) +#undef WRITE_PORT_BUFFER_ULONG +VOID +STDCALL +WRITE_PORT_BUFFER_ULONG (ULONG* Port, + ULONG* Buffer, + ULONG Count) { __asm__ __volatile__ ("cld ; rep ; outsl" : "=S" (Buffer), "=c" (Count) : "d" (Port),"0" (Buffer),"1" (Count)); } -VOID /*STDCALL*/ +#undef WRITE_PORT_UCHAR +VOID +STDCALL WRITE_PORT_UCHAR (PUCHAR Port, UCHAR Value) { @@ -158,9 +178,11 @@ WRITE_PORT_UCHAR (PUCHAR Port, SLOW_DOWN_IO; } -VOID /*STDCALL*/ -WRITE_PORT_USHORT (U16* Port, - U16 Value) +#undef WRITE_PORT_USHORT +VOID +STDCALL +WRITE_PORT_USHORT (USHORT* Port, + USHORT Value) { __asm__("outw %0, %w1\n\t" : @@ -169,9 +191,11 @@ WRITE_PORT_USHORT (U16* Port, SLOW_DOWN_IO; } -VOID /*STDCALL*/ -WRITE_PORT_ULONG (U32* Port, - U32 Value) +#undef WRITE_PORT_ULONG +VOID +STDCALL +WRITE_PORT_ULONG (ULONG* Port, + ULONG Value) { __asm__("outl %0, %w1\n\t" : diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxcons.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxcons.c index 179b9f85cdf..d803144bc27 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxcons.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxcons.c @@ -28,9 +28,9 @@ static unsigned CurrentAttr = 0x0f; VOID XboxConsPutChar(int c) { - U32 Width; - U32 Height; - U32 Depth; + ULONG Width; + ULONG Height; + ULONG Depth; if ('\r' == c) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxdisk.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxdisk.c index 7fb1cd6fc4d..68d805b4ab2 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxdisk.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxdisk.c @@ -38,9 +38,9 @@ static struct { - U32 SectorCountBeforePartition; - U32 PartitionSectorCount; - U8 SystemIndicator; + ULONG SectorCountBeforePartition; + ULONG PartitionSectorCount; + UCHAR SystemIndicator; } XboxPartitions[] = { /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */ @@ -155,17 +155,17 @@ static struct * Data block read and write commands */ #define IDEReadBlock(Address, Buffer, Count) \ - (READ_PORT_BUFFER_USHORT((PU16)((Address) + IDE_REG_DATA_PORT), (PU16)(Buffer), (Count) / 2)) + (READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) #define IDEWriteBlock(Address, Buffer, Count) \ - (WRITE_PORT_BUFFER_USHORT((PU16)((Address) + IDE_REG_DATA_PORT), (PU16)(Buffer), (Count) / 2)) + (WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) #define IDEReadBlock32(Address, Buffer, Count) \ - (READ_PORT_BUFFER_ULONG((PU32)((Address) + IDE_REG_DATA_PORT), (PU32)(Buffer), (Count) / 4)) + (READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4)) #define IDEWriteBlock32(Address, Buffer, Count) \ - (WRITE_PORT_BUFFER_ULONG((PU32)((Address) + IDE_REG_DATA_PORT), (PU32)(Buffer), (Count) / 4)) + (WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4)) #define IDEReadWord(Address) \ - (READ_PORT_USHORT((PU16)((Address) + IDE_REG_DATA_PORT))) + (READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT))) /* * Access macros for control registers @@ -180,64 +180,64 @@ static struct typedef struct _IDE_DRIVE_IDENTIFY { - U16 ConfigBits; /*00*/ - U16 LogicalCyls; /*01*/ - U16 Reserved02; /*02*/ - U16 LogicalHeads; /*03*/ - U16 BytesPerTrack; /*04*/ - U16 BytesPerSector; /*05*/ - U16 SectorsPerTrack; /*06*/ - U8 InterSectorGap; /*07*/ - U8 InterSectorGapSize; - U8 Reserved08H; /*08*/ - U8 BytesInPLO; - U16 VendorUniqueCnt; /*09*/ + USHORT ConfigBits; /*00*/ + USHORT LogicalCyls; /*01*/ + USHORT Reserved02; /*02*/ + USHORT LogicalHeads; /*03*/ + USHORT BytesPerTrack; /*04*/ + USHORT BytesPerSector; /*05*/ + USHORT SectorsPerTrack; /*06*/ + UCHAR InterSectorGap; /*07*/ + UCHAR InterSectorGapSize; + UCHAR Reserved08H; /*08*/ + UCHAR BytesInPLO; + USHORT VendorUniqueCnt; /*09*/ char SerialNumber[20]; /*10*/ - U16 ControllerType; /*20*/ - U16 BufferSize; /*21*/ - U16 ECCByteCnt; /*22*/ + USHORT ControllerType; /*20*/ + USHORT BufferSize; /*21*/ + USHORT ECCByteCnt; /*22*/ char FirmwareRev[8]; /*23*/ char ModelNumber[40]; /*27*/ - U16 RWMultImplemented; /*47*/ - U16 DWordIo; /*48*/ - U16 Capabilities; /*49*/ + USHORT RWMultImplemented; /*47*/ + USHORT DWordIo; /*48*/ + USHORT Capabilities; /*49*/ #define IDE_DRID_STBY_SUPPORTED 0x2000 #define IDE_DRID_IORDY_SUPPORTED 0x0800 #define IDE_DRID_IORDY_DISABLE 0x0400 #define IDE_DRID_LBA_SUPPORTED 0x0200 #define IDE_DRID_DMA_SUPPORTED 0x0100 - U16 Reserved50; /*50*/ - U16 MinPIOTransTime; /*51*/ - U16 MinDMATransTime; /*52*/ - U16 TMFieldsValid; /*53*/ - U16 TMCylinders; /*54*/ - U16 TMHeads; /*55*/ - U16 TMSectorsPerTrk; /*56*/ - U16 TMCapacityLo; /*57*/ - U16 TMCapacityHi; /*58*/ - U16 RWMultCurrent; /*59*/ - U16 TMSectorCountLo; /*60*/ - U16 TMSectorCountHi; /*61*/ - U16 DmaModes; /*62*/ - U16 MultiDmaModes; /*63*/ - U16 Reserved64[5]; /*64*/ - U16 Reserved69[2]; /*69*/ - U16 Reserved71[4]; /*71*/ - U16 MaxQueueDepth; /*75*/ - U16 Reserved76[4]; /*76*/ - U16 MajorRevision; /*80*/ - U16 MinorRevision; /*81*/ - U16 SupportedFeatures82; /*82*/ - U16 SupportedFeatures83; /*83*/ - U16 SupportedFeatures84; /*84*/ - U16 EnabledFeatures85; /*85*/ - U16 EnabledFeatures86; /*86*/ - U16 EnabledFeatures87; /*87*/ - U16 UltraDmaModes; /*88*/ - U16 Reserved89[11]; /*89*/ - U16 Max48BitAddress[4]; /*100*/ - U16 Reserved104[151]; /*104*/ - U16 Checksum; /*255*/ + USHORT Reserved50; /*50*/ + USHORT MinPIOTransTime; /*51*/ + USHORT MinDMATransTime; /*52*/ + USHORT TMFieldsValid; /*53*/ + USHORT TMCylinders; /*54*/ + USHORT TMHeads; /*55*/ + USHORT TMSectorsPerTrk; /*56*/ + USHORT TMCapacityLo; /*57*/ + USHORT TMCapacityHi; /*58*/ + USHORT RWMultCurrent; /*59*/ + USHORT TMSectorCountLo; /*60*/ + USHORT TMSectorCountHi; /*61*/ + USHORT DmaModes; /*62*/ + USHORT MultiDmaModes; /*63*/ + USHORT Reserved64[5]; /*64*/ + USHORT Reserved69[2]; /*69*/ + USHORT Reserved71[4]; /*71*/ + USHORT MaxQueueDepth; /*75*/ + USHORT Reserved76[4]; /*76*/ + USHORT MajorRevision; /*80*/ + USHORT MinorRevision; /*81*/ + USHORT SupportedFeatures82; /*82*/ + USHORT SupportedFeatures83; /*83*/ + USHORT SupportedFeatures84; /*84*/ + USHORT EnabledFeatures85; /*85*/ + USHORT EnabledFeatures86; /*86*/ + USHORT EnabledFeatures87; /*87*/ + USHORT UltraDmaModes; /*88*/ + USHORT Reserved89[11]; /*89*/ + USHORT Max48BitAddress[4]; /*100*/ + USHORT Reserved104[151]; /*104*/ + USHORT Checksum; /*255*/ } IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; /* XboxDiskPolledRead @@ -249,15 +249,15 @@ typedef struct _IDE_DRIVE_IDENTIFY * PASSIVE_LEVEL * * ARGUMENTS: - * U32 CommandPort Address of command port for drive - * U32 ControlPort Address of control port for drive - * U8 PreComp Value to write to precomp register - * U8 SectorCnt Value to write to sectorCnt register - * U8 SectorNum Value to write to sectorNum register - * U8 CylinderLow Value to write to CylinderLow register - * U8 CylinderHigh Value to write to CylinderHigh register - * U8 DrvHead Value to write to Drive/Head register - * U8 Command Value to write to Command register + * ULONG CommandPort Address of command port for drive + * ULONG ControlPort Address of control port for drive + * UCHAR PreComp Value to write to precomp register + * UCHAR SectorCnt Value to write to sectorCnt register + * UCHAR SectorNum Value to write to sectorNum register + * UCHAR CylinderLow Value to write to CylinderLow register + * UCHAR CylinderHigh Value to write to CylinderHigh register + * UCHAR DrvHead Value to write to Drive/Head register + * UCHAR Command Value to write to Command register * PVOID Buffer Buffer for output data * * RETURNS: @@ -265,21 +265,21 @@ typedef struct _IDE_DRIVE_IDENTIFY */ static BOOL -XboxDiskPolledRead(U32 CommandPort, - U32 ControlPort, - U8 PreComp, - U8 SectorCnt, - U8 SectorNum, - U8 CylinderLow, - U8 CylinderHigh, - U8 DrvHead, - U8 Command, +XboxDiskPolledRead(ULONG CommandPort, + ULONG ControlPort, + UCHAR PreComp, + UCHAR SectorCnt, + UCHAR SectorNum, + UCHAR CylinderLow, + UCHAR CylinderHigh, + UCHAR DrvHead, + UCHAR Command, PVOID Buffer) { - U32 SectorCount = 0; - U32 RetryCount; + ULONG SectorCount = 0; + ULONG RetryCount; BOOL Junk = FALSE; - U8 Status; + UCHAR Status; /* Wait for BUSY to clear */ for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) @@ -289,7 +289,7 @@ XboxDiskPolledRead(U32 CommandPort, { break; } - KeStallExecutionProcessor(10); + StallExecutionProcessor(10); } DbgPrint((DPRINT_DISK, "status=0x%x\n", Status)); DbgPrint((DPRINT_DISK, "waited %d usecs for busy to clear\n", RetryCount * 10)); @@ -301,11 +301,11 @@ XboxDiskPolledRead(U32 CommandPort, /* Write Drive/Head to select drive */ IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead); - KeStallExecutionProcessor(500); + StallExecutionProcessor(500); /* Disable interrupts */ IDEWriteDriveControl(ControlPort, IDE_DC_nIEN); - KeStallExecutionProcessor(500); + StallExecutionProcessor(500); /* Issue command to drive */ if (DrvHead & IDE_DH_LBA) @@ -338,7 +338,7 @@ XboxDiskPolledRead(U32 CommandPort, /* Issue the command */ IDEWriteCommand(CommandPort, Command); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); /* wait for DRQ or error */ for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++) @@ -349,7 +349,7 @@ XboxDiskPolledRead(U32 CommandPort, if (Status & IDE_SR_ERR) { IDEWriteDriveControl(ControlPort, 0); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); IDEReadStatus(CommandPort); return FALSE; @@ -362,20 +362,20 @@ XboxDiskPolledRead(U32 CommandPort, else { IDEWriteDriveControl(ControlPort, 0); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); IDEReadStatus(CommandPort); return FALSE; } } - KeStallExecutionProcessor(10); + StallExecutionProcessor(10); } /* timed out */ if (RetryCount >= IDE_MAX_POLL_RETRIES) { IDEWriteDriveControl(ControlPort, 0); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); IDEReadStatus(CommandPort); return FALSE; @@ -405,7 +405,7 @@ XboxDiskPolledRead(U32 CommandPort, if (Status & IDE_SR_ERR) { IDEWriteDriveControl(ControlPort, 0); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); IDEReadStatus(CommandPort); return FALSE; @@ -427,7 +427,7 @@ XboxDiskPolledRead(U32 CommandPort, SectorCount - SectorCnt)); } IDEWriteDriveControl(ControlPort, 0); - KeStallExecutionProcessor(50); + StallExecutionProcessor(50); IDEReadStatus(CommandPort); return TRUE; @@ -438,10 +438,10 @@ XboxDiskPolledRead(U32 CommandPort, } BOOL -XboxDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +XboxDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) { - U32 StartSector; - U8 Count; + ULONG StartSector; + UCHAR Count; if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f)) { @@ -456,7 +456,7 @@ XboxDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, P return FALSE; } - StartSector = (U32) SectorNumber; + StartSector = (ULONG) SectorNumber; while (0 < SectorCount) { Count = (SectorCount <= 255 ? SectorCount : 255); @@ -481,9 +481,9 @@ XboxDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, P } BOOL -XboxDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +XboxDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { - U8 SectorData[IDE_SECTOR_BUF_SZ]; + UCHAR SectorData[IDE_SECTOR_BUF_SZ]; /* This is the Xbox, chances are that there is a Xbox-standard partitionless * disk in it so let's check that first */ @@ -491,7 +491,7 @@ XboxDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) && MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData)) { - if (*((PU32) SectorData) == XBOX_SIGNATURE) + if (*((PULONG) SectorData) == XBOX_SIGNATURE) { memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY)); PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator; @@ -506,10 +506,10 @@ XboxDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE } BOOL -XboxDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY Geometry) +XboxDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY Geometry) { IDE_DRIVE_IDENTIFY DrvParms; - U32 i; + ULONG i; BOOL Atapi; Atapi = FALSE; /* FIXME */ @@ -565,8 +565,8 @@ XboxDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY Geometry) return TRUE; } -U32 -XboxDiskGetCacheableBlockCount(U32 DriveNumber) +ULONG +XboxDiskGetCacheableBlockCount(ULONG DriveNumber) { /* 64 seems a nice number, it is used by the machpc code for LBA devices */ return 64; diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxfont.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxfont.c index 359baac9174..b07a81b01cc 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxfont.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxfont.c @@ -23,7 +23,7 @@ #include "machine.h" #include "machxbox.h" -U8 XboxFont8x16[256 * 16] = +UCHAR XboxFont8x16[256 * 16] = { 0x00,0x00,0x00,0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, /* 0x00 */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xa5,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, /* 0x01 */ diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c index 1f5aad57c72..67e244a9a8f 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c @@ -29,8 +29,8 @@ #include "machxbox.h" #include "portio.h" -static U32 InstalledMemoryMb = 0; -static U32 AvailableMemoryMb = 0; +static ULONG InstalledMemoryMb = 0; +static ULONG AvailableMemoryMb = 0; #define TEST_SIZE 0x200 #define TEST_PATTERN1 0xaa @@ -39,15 +39,15 @@ static U32 AvailableMemoryMb = 0; VOID XboxMemInit(VOID) { - U8 ControlRegion[TEST_SIZE]; + UCHAR ControlRegion[TEST_SIZE]; PVOID MembaseTop = (PVOID)(64 * 1024 * 1024); PVOID MembaseLow = (PVOID)0; - (*(PU32)(0xfd000000 + 0x100200)) = 0x03070103 ; - (*(PU32)(0xfd000000 + 0x100204)) = 0x11448000 ; + (*(PULONG)(0xfd000000 + 0x100200)) = 0x03070103 ; + (*(PULONG)(0xfd000000 + 0x100204)) = 0x11448000 ; - WRITE_PORT_ULONG((U32*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); - WRITE_PORT_ULONG((U32*) 0xcfc, 0x7ffffff); /* Prep hardware for 128 Mb */ + WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); + WRITE_PORT_ULONG((ULONG*) 0xcfc, 0x7ffffff); /* Prep hardware for 128 Mb */ InstalledMemoryMb = 64; memset(ControlRegion, TEST_PATTERN1, TEST_SIZE); @@ -76,16 +76,16 @@ XboxMemInit(VOID) } /* Set hardware for amount of memory detected */ - WRITE_PORT_ULONG((U32*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); - WRITE_PORT_ULONG((U32*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1); + WRITE_PORT_ULONG((ULONG*) 0xcf8, CONFIG_CMD(0, 0, 0x84)); + WRITE_PORT_ULONG((ULONG*) 0xcfc, InstalledMemoryMb * 1024 * 1024 - 1); AvailableMemoryMb = InstalledMemoryMb; } -U32 -XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) +ULONG +XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) { - U32 EntryCount = 0; + ULONG EntryCount = 0; /* Synthesize memory map */ if (1 <= MaxMemoryMapSize) @@ -110,7 +110,7 @@ XboxMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) } PVOID -XboxMemReserveMemory(U32 MbToReserve) +XboxMemReserveMemory(ULONG MbToReserve) { if (0 == InstalledMemoryMb) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxrtc.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxrtc.c index 0e869841013..d6000b7cf93 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxrtc.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxrtc.c @@ -41,7 +41,7 @@ HalpQueryCMOS(UCHAR Reg) } VOID -XboxRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second) +XboxRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second) { while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP) { diff --git a/reactos/boot/freeldr/freeldr/arch/i386/xboxvideo.c b/reactos/boot/freeldr/freeldr/arch/i386/xboxvideo.c index 8457b2beb80..fdcb67aaf0b 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/xboxvideo.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/xboxvideo.c @@ -30,10 +30,10 @@ #define I2C_IO_BASE 0xc000 static PVOID FrameBuffer; -static U32 ScreenWidth; -static U32 ScreenHeight; -static U32 BytesPerPixel; -static U32 Delta; +static ULONG ScreenWidth; +static ULONG ScreenHeight; +static ULONG BytesPerPixel; +static ULONG Delta; #define CHAR_WIDTH 8 #define CHAR_HEIGHT 16 @@ -45,16 +45,16 @@ static U32 Delta; #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff)) static VOID -XboxVideoOutputChar(U8 Char, unsigned X, unsigned Y, U32 FgColor, U32 BgColor) +XboxVideoOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgColor) { - PU8 FontPtr; - PU32 Pixel; - U8 Mask; + PUCHAR FontPtr; + PULONG Pixel; + UCHAR Mask; unsigned Line; unsigned Col; FontPtr = XboxFont8x16 + Char * 16; - Pixel = (PU32) ((char *) FrameBuffer + (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * Delta + Pixel = (PULONG) ((char *) FrameBuffer + (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * Delta + X * CHAR_WIDTH * BytesPerPixel); for (Line = 0; Line < CHAR_HEIGHT; Line++) { @@ -64,14 +64,14 @@ XboxVideoOutputChar(U8 Char, unsigned X, unsigned Y, U32 FgColor, U32 BgColor) Pixel[Col] = (0 != (FontPtr[Line] & Mask) ? FgColor : BgColor); Mask = Mask >> 1; } - Pixel = (PU32) ((char *) Pixel + Delta); + Pixel = (PULONG) ((char *) Pixel + Delta); } } -static U32 -XboxVideoAttrToSingleColor(U8 Attr) +static ULONG +XboxVideoAttrToSingleColor(UCHAR Attr) { - U8 Intensity; + UCHAR Intensity; Intensity = (0 == (Attr & 0x08) ? 127 : 255); @@ -82,21 +82,21 @@ XboxVideoAttrToSingleColor(U8 Attr) } static VOID -XboxVideoAttrToColors(U8 Attr, U32 *FgColor, U32 *BgColor) +XboxVideoAttrToColors(UCHAR Attr, ULONG *FgColor, ULONG *BgColor) { *FgColor = XboxVideoAttrToSingleColor(Attr & 0xf); *BgColor = XboxVideoAttrToSingleColor((Attr >> 4) & 0xf); } static VOID -XboxVideoClearScreenColor(U32 Color, BOOL FullScreen) +XboxVideoClearScreenColor(ULONG Color, BOOL FullScreen) { - U32 Line, Col; - PU32 p; + ULONG Line, Col; + PULONG p; for (Line = 0; Line < ScreenHeight - (FullScreen ? 0 : 2 * TOP_BOTTOM_LINES); Line++) { - p = (PU32) ((char *) FrameBuffer + (Line + (FullScreen ? 0 : TOP_BOTTOM_LINES)) * Delta); + p = (PULONG) ((char *) FrameBuffer + (Line + (FullScreen ? 0 : TOP_BOTTOM_LINES)) * Delta); for (Col = 0; Col < ScreenWidth; Col++) { *p++ = Color; @@ -105,9 +105,9 @@ XboxVideoClearScreenColor(U32 Color, BOOL FullScreen) } VOID -XboxVideoClearScreen(U8 Attr) +XboxVideoClearScreen(UCHAR Attr) { - U32 FgColor, BgColor; + ULONG FgColor, BgColor; XboxVideoAttrToColors(Attr, &FgColor, &BgColor); @@ -115,9 +115,9 @@ XboxVideoClearScreen(U8 Attr) } VOID -XboxVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y) +XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) { - U32 FgColor, BgColor; + ULONG FgColor, BgColor; XboxVideoAttrToColors(Attr, &FgColor, &BgColor); @@ -125,11 +125,11 @@ XboxVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y) } static BOOL -ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, U32 *Data_to_smbus) +ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, ULONG *Data_to_smbus) { int nRetriesToLive=50; - while (0 != (READ_PORT_USHORT((PU16) (I2C_IO_BASE + 0)) & 0x0800)) + while (0 != (READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800)) { ; /* Franz's spin while bus busy with any master traffic */ } @@ -142,8 +142,8 @@ ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, U32 *Data_to_smbus) WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1); WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 8), bRegister); - temp = READ_PORT_USHORT((U16 *) (I2C_IO_BASE + 0)); - WRITE_PORT_USHORT((PU16) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */ + temp = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 0)); + WRITE_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */ switch (Size) { @@ -186,7 +186,7 @@ ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, U32 *Data_to_smbus) READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9)); break; case 2: - *Data_to_smbus = READ_PORT_USHORT((U16 *) (I2C_IO_BASE + 6)); + *Data_to_smbus = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 6)); break; default: *Data_to_smbus = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6)); @@ -203,7 +203,7 @@ ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, U32 *Data_to_smbus) static BOOL -I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, U32 *Return) +I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, ULONG *Return) { return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return); } @@ -212,9 +212,9 @@ I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, U32 *Re VOID XboxVideoInit(VOID) { - U32 AvMode; + ULONG AvMode; - FrameBuffer = (PVOID)((U32) XboxMemReserveMemory(FB_SIZE_MB) | 0xf0000000); + FrameBuffer = (PVOID)((ULONG) XboxMemReserveMemory(FB_SIZE_MB) | 0xf0000000); if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode)) { @@ -247,7 +247,7 @@ XboxVideoInit(VOID) XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE); /* Tell the nVidia controller about the framebuffer */ - *((PU32) 0xfd600800) = (U32) FrameBuffer; + *((PULONG) 0xfd600800) = (ULONG) FrameBuffer; } VIDEODISPLAYMODE @@ -258,21 +258,21 @@ XboxVideoSetDisplayMode(char *DisplayMode, BOOL Init) } VOID -XboxVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth) +XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) { *Width = ScreenWidth / CHAR_WIDTH; *Height = (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; *Depth = 0; } -U32 +ULONG XboxVideoGetBufferSize(VOID) { return (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT * (ScreenWidth / CHAR_WIDTH) * 2; } VOID -XboxVideoSetTextCursorPosition(U32 X, U32 Y) +XboxVideoSetTextCursorPosition(ULONG X, ULONG Y) { /* We don't have a cursor yet */ } @@ -286,8 +286,8 @@ XboxVideoHideShowTextCursor(BOOL Show) VOID XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer) { - PU8 OffScreenBuffer = (PU8) Buffer; - U32 Col, Line; + PUCHAR OffScreenBuffer = (PUCHAR) Buffer; + ULONG Col, Line; for (Line = 0; Line < (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++) { @@ -306,13 +306,13 @@ XboxVideoIsPaletteFixed(VOID) } VOID -XboxVideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue) +XboxVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue) { /* Not supported */ } VOID -XboxVideoGetPaletteColor(U8 Color, U8* Red, U8* Green, U8* Blue) +XboxVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue) { /* Not supported */ } diff --git a/reactos/boot/freeldr/freeldr/bootmgr.c b/reactos/boot/freeldr/freeldr/bootmgr.c index 23fc12ed148..01cd5212462 100644 --- a/reactos/boot/freeldr/freeldr/bootmgr.c +++ b/reactos/boot/freeldr/freeldr/bootmgr.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - + #include #include #include @@ -41,13 +41,13 @@ VOID RunLoader(VOID) { UCHAR SettingName[80]; UCHAR SettingValue[80]; - U32 SectionId; - U32 OperatingSystemCount; + ULONG SectionId; + ULONG OperatingSystemCount; PUCHAR *OperatingSystemSectionNames; PUCHAR *OperatingSystemDisplayNames; - U32 DefaultOperatingSystem; - S32 TimeOut; - U32 SelectedOperatingSystem; + ULONG DefaultOperatingSystem; + LONG TimeOut; + ULONG SelectedOperatingSystem; if (!IniFileInitialize()) { @@ -70,14 +70,14 @@ VOID RunLoader(VOID) MachConsGetCh(); return; } - + if (!InitOperatingSystemList(&OperatingSystemSectionNames, &OperatingSystemDisplayNames, &OperatingSystemCount)) { UiMessageBox("Press ENTER to reboot.\n"); goto reboot; } - + if (OperatingSystemCount == 0) { UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot."); @@ -85,7 +85,7 @@ VOID RunLoader(VOID) } DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemSectionNames, OperatingSystemCount); - + // // Find all the message box settings and run them // @@ -93,12 +93,13 @@ VOID RunLoader(VOID) for (;;) { - + /* If Timeout is 0, don't even bother loading any gui */ if (!UserInterfaceUp) { + SelectedOperatingSystem = DefaultOperatingSystem; goto NoGui; } - + // Redraw the backdrop UiDrawBackdrop(); @@ -108,10 +109,9 @@ VOID RunLoader(VOID) UiMessageBox("Press ENTER to reboot.\n"); goto reboot; } - + NoGui: TimeOut = -1; - DefaultOperatingSystem = SelectedOperatingSystem; // Try to open the operating system section in the .ini file if (!IniOpenSection(OperatingSystemSectionNames[SelectedOperatingSystem], &SectionId)) @@ -153,19 +153,19 @@ NoGui: } } - + reboot: UiUnInitialize("Rebooting..."); return; } -U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSystemCount) +ULONG GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount) { UCHAR DefaultOSText[80]; char* DefaultOSName; - U32 SectionId; - U32 DefaultOS = 0; - U32 Idx; + ULONG SectionId; + ULONG DefaultOS = 0; + ULONG Idx; if (!IniOpenSection("FreeLoader", &SectionId)) { @@ -196,11 +196,11 @@ U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSyste return DefaultOS; } -S32 GetTimeOut(VOID) +LONG GetTimeOut(VOID) { UCHAR TimeOutText[20]; - S32 TimeOut; - U32 SectionId; + LONG TimeOut; + ULONG SectionId; TimeOut = CmdLineGetTimeOut(); if (0 <= TimeOut) @@ -225,7 +225,7 @@ S32 GetTimeOut(VOID) return TimeOut; } -BOOL MainBootMenuKeyPressFilter(U32 KeyPress) +BOOL MainBootMenuKeyPressFilter(ULONG KeyPress) { if (KeyPress == KEY_F8) { diff --git a/reactos/boot/freeldr/freeldr/cache/blocklist.c b/reactos/boot/freeldr/freeldr/cache/blocklist.c index 2a9cb6acce5..81b3cb61b9d 100644 --- a/reactos/boot/freeldr/freeldr/cache/blocklist.c +++ b/reactos/boot/freeldr/freeldr/cache/blocklist.c @@ -30,7 +30,7 @@ // Returns a pointer to a CACHE_BLOCK structure // Adds the block to the cache manager block list // in cache memory if it isn't already there -PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, U32 BlockNumber) +PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber) { PCACHE_BLOCK CacheBlock = NULL; @@ -55,7 +55,7 @@ PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, U32 BlockNumb return CacheBlock; } -PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, U32 BlockNumber) +PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber) { PCACHE_BLOCK CacheBlock = NULL; @@ -93,7 +93,7 @@ PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, U32 BlockNumber) return NULL; } -PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, U32 BlockNumber) +PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber) { PCACHE_BLOCK CacheBlock = NULL; @@ -195,7 +195,7 @@ BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive) VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive) { - U32 NewCacheSize; + ULONG NewCacheSize; DbgPrint((DPRINT_CACHE, "CacheInternalCheckCacheSizeLimits()\n")); diff --git a/reactos/boot/freeldr/freeldr/cache/cache.c b/reactos/boot/freeldr/freeldr/cache/cache.c index 363653f13d4..2344e1ee7fd 100644 --- a/reactos/boot/freeldr/freeldr/cache/cache.c +++ b/reactos/boot/freeldr/freeldr/cache/cache.c @@ -34,11 +34,11 @@ CACHE_DRIVE CacheManagerDrive; BOOL CacheManagerInitialized = FALSE; BOOL CacheManagerDataInvalid = FALSE; -U32 CacheBlockCount = 0; -U32 CacheSizeLimit = 0; -U32 CacheSizeCurrent = 0; +ULONG CacheBlockCount = 0; +ULONG CacheSizeLimit = 0; +ULONG CacheSizeCurrent = 0; -BOOL CacheInitializeDrive(U32 DriveNumber) +BOOL CacheInitializeDrive(ULONG DriveNumber) { PCACHE_BLOCK NextCacheBlock; GEOMETRY DriveGeometry; @@ -116,16 +116,16 @@ VOID CacheInvalidateCacheData(VOID) CacheManagerDataInvalid = TRUE; } -BOOL CacheReadDiskSectors(U32 DiskNumber, U32 StartSector, U32 SectorCount, PVOID Buffer) +BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer) { PCACHE_BLOCK CacheBlock; - U32 StartBlock; - U32 SectorOffsetInStartBlock; - U32 CopyLengthInStartBlock; - U32 EndBlock; - U32 SectorOffsetInEndBlock; - U32 BlockCount; - U32 Idx; + ULONG StartBlock; + ULONG SectorOffsetInStartBlock; + ULONG CopyLengthInStartBlock; + ULONG EndBlock; + ULONG SectorOffsetInEndBlock; + ULONG BlockCount; + ULONG Idx; DbgPrint((DPRINT_CACHE, "CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer)); @@ -248,13 +248,13 @@ BOOL CacheReadDiskSectors(U32 DiskNumber, U32 StartSector, U32 SectorCount, PVOI return TRUE; } -BOOL CacheForceDiskSectorsIntoCache(U32 DiskNumber, U32 StartSector, U32 SectorCount) +BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount) { PCACHE_BLOCK CacheBlock; - U32 StartBlock; - U32 EndBlock; - U32 BlockCount; - U32 Idx; + ULONG StartBlock; + ULONG EndBlock; + ULONG BlockCount; + ULONG Idx; DbgPrint((DPRINT_CACHE, "CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount)); @@ -294,9 +294,9 @@ BOOL CacheForceDiskSectorsIntoCache(U32 DiskNumber, U32 StartSector, U32 SectorC return TRUE; } -BOOL CacheReleaseMemory(U32 MinimumAmountToRelease) +BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease) { - U32 AmountReleased; + ULONG AmountReleased; DbgPrint((DPRINT_CACHE, "CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease)); diff --git a/reactos/boot/freeldr/freeldr/cache/cm.h b/reactos/boot/freeldr/freeldr/cache/cm.h index 6780fff6b07..fd47241e866 100644 --- a/reactos/boot/freeldr/freeldr/cache/cm.h +++ b/reactos/boot/freeldr/freeldr/cache/cm.h @@ -38,9 +38,9 @@ typedef struct { LIST_ITEM ListEntry; // Doubly linked list synchronization member - U32 BlockNumber; // Track index for CHS, 64k block index for LBA + ULONG BlockNumber; // Track index for CHS, 64k block index for LBA BOOL LockedInCache; // Indicates that this block is locked in cache memory - U32 AccessCount; // Access count for this block + ULONG AccessCount; // Access count for this block PVOID BlockData; // Pointer to block data @@ -55,10 +55,10 @@ typedef struct /////////////////////////////////////////////////////////////////////////////////////// typedef struct { - U32 DriveNumber; - U32 BytesPerSector; + ULONG DriveNumber; + ULONG BytesPerSector; - U32 BlockSize; // Block size (in sectors) + ULONG BlockSize; // Block size (in sectors) PCACHE_BLOCK CacheBlockHead; } CACHE_DRIVE, *PCACHE_DRIVE; @@ -71,18 +71,18 @@ typedef struct /////////////////////////////////////////////////////////////////////////////////////// extern CACHE_DRIVE CacheManagerDrive; extern BOOL CacheManagerInitialized; -extern U32 CacheBlockCount; -extern U32 CacheSizeLimit; -extern U32 CacheSizeCurrent; +extern ULONG CacheBlockCount; +extern ULONG CacheSizeLimit; +extern ULONG CacheSizeCurrent; /////////////////////////////////////////////////////////////////////////////////////// // // Internal functions // /////////////////////////////////////////////////////////////////////////////////////// -PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, U32 BlockNumber); // Returns a pointer to a CACHE_BLOCK structure given a block number -PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, U32 BlockNumber); // Searches the block list for a particular block -PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, U32 BlockNumber); // Adds a block to the cache's block list +PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Returns a pointer to a CACHE_BLOCK structure given a block number +PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Searches the block list for a particular block +PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber); // Adds a block to the cache's block list BOOL CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive); // Removes a block from the cache's block list & frees the memory VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive); // Checks the cache size limits to see if we can add a new block, if not calls CacheInternalFreeBlock() VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive); // Dumps the list of cached blocks to the debug output port diff --git a/reactos/boot/freeldr/freeldr/cmdline.c b/reactos/boot/freeldr/freeldr/cmdline.c index f45a1cfe248..a18002c4d20 100644 --- a/reactos/boot/freeldr/freeldr/cmdline.c +++ b/reactos/boot/freeldr/freeldr/cmdline.c @@ -112,7 +112,7 @@ CmdLineGetDefaultOS(void) return CmdLineInfo.DefaultOperatingSystem; } -S32 +LONG CmdLineGetTimeOut(void) { return CmdLineInfo.TimeOut; diff --git a/reactos/boot/freeldr/freeldr/comm/rs232.c b/reactos/boot/freeldr/freeldr/comm/rs232.c index f203655fbfd..e814b0335ce 100644 --- a/reactos/boot/freeldr/freeldr/comm/rs232.c +++ b/reactos/boot/freeldr/freeldr/comm/rs232.c @@ -61,8 +61,8 @@ /* STATIC VARIABLES *********************************************************/ -static U32 Rs232ComPort = 0; -static U32 Rs232BaudRate = 0; +static ULONG Rs232ComPort = 0; +static ULONG Rs232BaudRate = 0; static PUCHAR Rs232PortBase = (PUCHAR)0; /* The com port must only be initialized once! */ @@ -73,8 +73,8 @@ static BOOLEAN PortInitialized = FALSE; static BOOL Rs232DoesComPortExist(PUCHAR BaseAddress) { BOOLEAN found; - U8 mcr; - U8 msr; + UCHAR mcr; + UCHAR msr; found = FALSE; @@ -118,12 +118,12 @@ static BOOL Rs232DoesComPortExist(PUCHAR BaseAddress) /* FUNCTIONS *********************************************************/ -BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) +BOOL Rs232PortInitialize(ULONG ComPort, ULONG BaudRate) { - U32 BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; + ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; //char buffer[80]; - U32 divisor; - U8 lcr; + ULONG divisor; + UCHAR lcr; if (PortInitialized == FALSE) { @@ -146,7 +146,7 @@ BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, - (U32)PortBase); + (ULONG)PortBase); HalDisplayString (buffer); #endif*/ /* NDEBUG */ } @@ -158,7 +158,7 @@ BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, - (U32)PortBase); + (ULONG)PortBase); HalDisplayString (buffer); #endif*/ /* NDEBUG */ } @@ -180,7 +180,7 @@ BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) sprintf (buffer, "\nSerial port COM%ld found at 0x%lx\n", ComPort, - (U32)PortBase); + (ULONG)PortBase); HalDisplayString (buffer); #endif*/ /* NDEBUG */ } @@ -222,7 +222,7 @@ BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) /* * set global info */ - //KdComPortInUse = (U32)PortBase; + //KdComPortInUse = (ULONG)PortBase; /* * print message to blue screen @@ -230,7 +230,7 @@ BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate) /*sprintf (buffer, "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n", ComPort, - (U32)PortBase, + (ULONG)PortBase, BaudRate); HalDisplayString (buffer);*/ diff --git a/reactos/boot/freeldr/freeldr/custom.c b/reactos/boot/freeldr/freeldr/custom.c index f3899ba86a7..da0da4198d8 100644 --- a/reactos/boot/freeldr/freeldr/custom.c +++ b/reactos/boot/freeldr/freeldr/custom.c @@ -46,8 +46,8 @@ UCHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup."; VOID OptionMenuCustomBoot(VOID) { PUCHAR CustomBootMenuList[] = { "Disk", "Partition", "Boot Sector File", "ReactOS", "Linux" }; - U32 CustomBootMenuCount = sizeof(CustomBootMenuList) / sizeof(CustomBootMenuList[0]); - U32 SelectedMenuItem; + ULONG CustomBootMenuCount = sizeof(CustomBootMenuList) / sizeof(CustomBootMenuList[0]); + ULONG SelectedMenuItem; if (!UiDisplayMenu(CustomBootMenuList, CustomBootMenuCount, 0, -1, &SelectedMenuItem, TRUE, NULL)) { @@ -79,8 +79,8 @@ VOID OptionMenuCustomBootDisk(VOID) { UCHAR SectionName[100]; UCHAR BootDriveString[20]; - U32 SectionId; - U32 Year, Month, Day, Hour, Minute, Second; + ULONG SectionId; + ULONG Year, Month, Day, Hour, Minute, Second; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); @@ -122,8 +122,8 @@ VOID OptionMenuCustomBootPartition(VOID) UCHAR SectionName[100]; UCHAR BootDriveString[20]; UCHAR BootPartitionString[20]; - U32 SectionId; - U32 Year, Month, Day, Hour, Minute, Second; + ULONG SectionId; + ULONG Year, Month, Day, Hour, Minute, Second; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); @@ -178,8 +178,8 @@ VOID OptionMenuCustomBootBootSectorFile(VOID) UCHAR BootDriveString[20]; UCHAR BootPartitionString[20]; UCHAR BootSectorFileString[200]; - U32 SectionId; - U32 Year, Month, Day, Hour, Minute, Second; + ULONG SectionId; + ULONG Year, Month, Day, Hour, Minute, Second; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); @@ -248,8 +248,8 @@ VOID OptionMenuCustomBootReactOS(VOID) UCHAR ReactOSSystemPath[200]; UCHAR ReactOSARCPath[200]; UCHAR ReactOSOptions[200]; - U32 SectionId; - U32 Year, Month, Day, Hour, Minute, Second; + ULONG SectionId; + ULONG Year, Month, Day, Hour, Minute, Second; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); @@ -321,8 +321,8 @@ VOID OptionMenuCustomBootLinux(VOID) UCHAR LinuxKernelString[200]; UCHAR LinuxInitrdString[200]; UCHAR LinuxCommandLineString[200]; - U32 SectionId; - U32 Year, Month, Day, Hour, Minute, Second; + ULONG SectionId; + ULONG Year, Month, Day, Hour, Minute, Second; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c index abd8ec38aab..93193ceaf01 100644 --- a/reactos/boot/freeldr/freeldr/debug.c +++ b/reactos/boot/freeldr/freeldr/debug.c @@ -33,22 +33,22 @@ #define DEBUG_NONE #if defined (DEBUG_ALL) -U32 DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | - DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS | - DPRINT_LINUX; +ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | + DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS | + DPRINT_LINUX | DPRINT_HWDETECT; #elif defined (DEBUG_INIFILE) -U32 DebugPrintMask = DPRINT_INIFILE; +ULONG DebugPrintMask = DPRINT_INIFILE; #elif defined (DEBUG_REACTOS) -U32 DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY; +ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY; #elif defined (DEBUG_CUSTOM) -U32 DebugPrintMask = DPRINT_WARNING|DPRINT_FILESYSTEM|DPRINT_MEMORY|DPRINT_LINUX; +ULONG DebugPrintMask = DPRINT_WARNING|DPRINT_FILESYSTEM|DPRINT_MEMORY|DPRINT_LINUX; #else //#elif defined (DEBUG_NONE) -U32 DebugPrintMask = 0; +ULONG DebugPrintMask = 0; #endif -#define SCREEN 0 -#define RS232 1 -#define BOCHS 2 +#define SCREEN 1 +#define RS232 2 +#define BOCHS 4 #define COM1 1 #define COM2 2 @@ -57,12 +57,13 @@ U32 DebugPrintMask = 0; #define BOCHS_OUTPUT_PORT 0xe9 -U32 DebugPort = RS232; -//U32 DebugPort = SCREEN; -//U32 DebugPort = BOCHS; -U32 ComPort = COM1; -//U32 BaudRate = 19200; -U32 BaudRate = 115200; +ULONG DebugPort = RS232; +//ULONG DebugPort = SCREEN; +//ULONG DebugPort = BOCHS; +//ULONG DebugPort = SCREEN|BOCHS; +ULONG ComPort = COM1; +//ULONG BaudRate = 19200; +ULONG BaudRate = 115200; BOOL DebugStartOfLine = TRUE; @@ -81,7 +82,7 @@ VOID DebugPrintChar(UCHAR Character) DebugStartOfLine = TRUE; } - if (DebugPort == RS232) + if (DebugPort & RS232) { if (Character == '\n') { @@ -89,17 +90,17 @@ VOID DebugPrintChar(UCHAR Character) } Rs232PortPutByte(Character); } - else if (DebugPort == BOCHS) + if (DebugPort & BOCHS) { WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character); } - else + if (DebugPort & SCREEN) { MachConsPutChar(Character); } } -VOID DebugPrintHeader(U32 Mask) +VOID DebugPrintHeader(ULONG Mask) { /* No header */ if (Mask == 0) @@ -257,7 +258,7 @@ static VOID DebugPrintV(char *format, int *dataptr) switch (c = *(format++)) { case 'd': case 'u': case 'x': - + if (ll) { *convert_i64_to_ascii(str, c, *((unsigned long long*) dataptr)) = 0; @@ -308,10 +309,10 @@ static VOID DebugPrintV(char *format, int *dataptr) } -VOID DebugPrint(U32 Mask, char *format, ...) +VOID DebugPrint(ULONG Mask, char *format, ...) { int *dataptr = (int *) &format; - + // Mask out unwanted debug messages if (!(Mask & DebugPrintMask)) { @@ -335,12 +336,12 @@ VOID DebugPrint1(char *format, ...) DebugPrintV(format, ++dataptr); } -VOID DebugDumpBuffer(U32 Mask, PVOID Buffer, U32 Length) +VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length) { PUCHAR BufPtr = (PUCHAR)Buffer; - U32 Idx; - U32 Idx2; - + ULONG Idx; + ULONG Idx2; + // Mask out unwanted debug messages if (!(Mask & DebugPrintMask)) { diff --git a/reactos/boot/freeldr/freeldr/disk/disk.c b/reactos/boot/freeldr/freeldr/disk/disk.c index c298b51079e..9a3e6835096 100644 --- a/reactos/boot/freeldr/freeldr/disk/disk.c +++ b/reactos/boot/freeldr/freeldr/disk/disk.c @@ -39,7 +39,7 @@ VOID DiskReportError (BOOL bError) bReportError = bError; } -VOID DiskError(PUCHAR ErrorString, U32 ErrorCode) +VOID DiskError(PUCHAR ErrorString, ULONG ErrorCode) { UCHAR ErrorCodeString[200]; @@ -53,7 +53,7 @@ VOID DiskError(PUCHAR ErrorString, U32 ErrorCode) UiMessageBox(ErrorCodeString); } -PUCHAR DiskGetErrorCodeString(U32 ErrorCode) +PUCHAR DiskGetErrorCodeString(ULONG ErrorCode) { switch (ErrorCode) { @@ -89,9 +89,9 @@ PUCHAR DiskGetErrorCodeString(U32 ErrorCode) } // This function is in arch/i386/i386disk.c -//BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +//BOOL DiskReadLogicalSectors(ULONG DriveNumber, U64 SectorNumber, ULONG SectorCount, PVOID Buffer) -BOOL DiskIsDriveRemovable(U32 DriveNumber) +BOOL DiskIsDriveRemovable(ULONG DriveNumber) { // Hard disks use drive numbers >= 0x80 // So if the drive number indicates a hard disk @@ -109,4 +109,4 @@ BOOL DiskIsDriveRemovable(U32 DriveNumber) //VOID DiskStopFloppyMotor(VOID) // This function is in arch/i386/i386disk.c -//U32 DiskGetCacheableBlockCount(U32 DriveNumber) +//ULONG DiskGetCacheableBlockCount(ULONG DriveNumber) diff --git a/reactos/boot/freeldr/freeldr/disk/partition.c b/reactos/boot/freeldr/freeldr/disk/partition.c index 0a0e4e4a922..4c1aa01c035 100644 --- a/reactos/boot/freeldr/freeldr/disk/partition.c +++ b/reactos/boot/freeldr/freeldr/disk/partition.c @@ -26,9 +26,9 @@ #include -BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { - U32 BootablePartitionCount = 0; + ULONG BootablePartitionCount = 0; MASTER_BOOT_RECORD MasterBootRecord; // Read master boot record @@ -77,13 +77,13 @@ BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY Partiti return TRUE; } -BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +BOOL DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { MASTER_BOOT_RECORD MasterBootRecord; PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry; - U32 ExtendedPartitionNumber; - U32 ExtendedPartitionOffset; - U32 Index; + ULONG ExtendedPartitionNumber; + ULONG ExtendedPartitionOffset; + ULONG Index; // Read master boot record if (!DiskReadBootRecord(DriveNumber, 0, &MasterBootRecord)) @@ -157,7 +157,7 @@ BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABL BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) { - U32 Index; + ULONG Index; for (Index=0; Index<4; Index++) { @@ -178,7 +178,7 @@ BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry) { - U32 Index; + ULONG Index; for (Index=0; Index<4; Index++) { @@ -195,11 +195,11 @@ BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PP return FALSE; } -BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) +BOOL DiskReadBootRecord(ULONG DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord) { char ErrMsg[64]; #ifdef DEBUG - U32 Index; + ULONG Index; #endif // Read master boot record diff --git a/reactos/boot/freeldr/freeldr/drivemap.c b/reactos/boot/freeldr/freeldr/drivemap.c index f32fd718661..5a5ff3d0d0e 100644 --- a/reactos/boot/freeldr/freeldr/drivemap.c +++ b/reactos/boot/freeldr/freeldr/drivemap.c @@ -26,9 +26,9 @@ #include BOOL DriveMapInstalled = FALSE; // Tells us if we have already installed our drive map int 13h handler code -U32 OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler -U32 DriveMapHandlerAddress = 0; // Linear address of our drive map handler -U32 DriveMapHandlerSegOff = 0; // Segment:offset style address of our drive map handler +ULONG OldInt13HandlerAddress = 0; // Address of BIOS int 13h handler +ULONG DriveMapHandlerAddress = 0; // Linear address of our drive map handler +ULONG DriveMapHandlerSegOff = 0; // Segment:offset style address of our drive map handler VOID DriveMapMapDrivesInSection(PUCHAR SectionName) { @@ -37,10 +37,10 @@ VOID DriveMapMapDrivesInSection(PUCHAR SectionName) UCHAR ErrorText[260]; UCHAR Drive1[80]; UCHAR Drive2[80]; - U32 SectionId; - U32 SectionItemCount; - U32 Index; - U32 Index2; + ULONG SectionId; + ULONG SectionItemCount; + ULONG Index; + ULONG Index2; DRIVE_MAP_LIST DriveMapList; RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST)); @@ -119,7 +119,7 @@ VOID DriveMapMapDrivesInSection(PUCHAR SectionName) BOOL DriveMapIsValidDriveString(PUCHAR DriveString) { - U32 Index; + ULONG Index; // Now verify that the user has given us appropriate strings if ((strlen(DriveString) < 3) || @@ -147,9 +147,9 @@ BOOL DriveMapIsValidDriveString(PUCHAR DriveString) return TRUE; } -U32 DriveMapGetBiosDriveNumber(PUCHAR DeviceName) +ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName) { - U32 BiosDriveNumber = 0; + ULONG BiosDriveNumber = 0; // If they passed in a number string then just // convert it to decimal and return it @@ -174,8 +174,8 @@ U32 DriveMapGetBiosDriveNumber(PUCHAR DeviceName) VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap) { - U32* RealModeIVT = (U32*)0x00000000; - U16* BiosLowMemorySize = (U16*)0x00000413; + ULONG* RealModeIVT = (ULONG*)0x00000000; + USHORT* BiosLowMemorySize = (USHORT*)0x00000413; if (!DriveMapInstalled) { @@ -186,7 +186,7 @@ VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap) (*BiosLowMemorySize)--; // Get linear address for drive map handler - DriveMapHandlerAddress = (U32)(*BiosLowMemorySize) << 10; + DriveMapHandlerAddress = (ULONG)(*BiosLowMemorySize) << 10; // Convert to segment:offset style address DriveMapHandlerSegOff = (DriveMapHandlerAddress << 12) & 0xffff0000; @@ -199,7 +199,7 @@ VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap) DriveMapOldInt13HandlerAddress = OldInt13HandlerAddress; // Copy the code to our reserved area - RtlCopyMemory((PVOID)DriveMapHandlerAddress, &DriveMapInt13HandlerStart, ((U32)&DriveMapInt13HandlerEnd - (U32)&DriveMapInt13HandlerStart)); + RtlCopyMemory((PVOID)DriveMapHandlerAddress, &DriveMapInt13HandlerStart, ((ULONG)&DriveMapInt13HandlerEnd - (ULONG)&DriveMapInt13HandlerStart)); // Update the IVT RealModeIVT[0x13] = DriveMapHandlerSegOff; @@ -210,8 +210,8 @@ VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap) VOID DriveMapRemoveInt13Handler(VOID) { - U32* RealModeIVT = (U32*)0x00000000; - U16* BiosLowMemorySize = (U16*)0x00000413; + ULONG* RealModeIVT = (ULONG*)0x00000000; + USHORT* BiosLowMemorySize = (USHORT*)0x00000413; if (DriveMapInstalled) { diff --git a/reactos/boot/freeldr/freeldr/freeldr.xml b/reactos/boot/freeldr/freeldr/freeldr.xml index 563d99db7f0..eaa46f3de70 100644 --- a/reactos/boot/freeldr/freeldr/freeldr.xml +++ b/reactos/boot/freeldr/freeldr/freeldr.xml @@ -3,4 +3,5 @@ freeldr_base64k freeldr_base freeldr_main + rossym diff --git a/reactos/boot/freeldr/freeldr/freeldr_base.xml b/reactos/boot/freeldr/freeldr/freeldr_base.xml index 3024356e7ac..f08569ed98c 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_base.xml +++ b/reactos/boot/freeldr/freeldr/freeldr_base.xml @@ -1,8 +1,9 @@ include cache + include + -nostdlib - -nostdinc -ffreestanding -fno-builtin -fno-inline diff --git a/reactos/boot/freeldr/freeldr/freeldr_base64k.xml b/reactos/boot/freeldr/freeldr/freeldr_base64k.xml index d783e49a05a..a170dd67209 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_base64k.xml +++ b/reactos/boot/freeldr/freeldr/freeldr_base64k.xml @@ -1,7 +1,8 @@ include + include + -nostdlib - -nostdinc -ffreestanding -fno-builtin -fno-inline diff --git a/reactos/boot/freeldr/freeldr/freeldr_main.xml b/reactos/boot/freeldr/freeldr/freeldr_main.xml index 9c8dd4cc129..820e4a6e44d 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_main.xml +++ b/reactos/boot/freeldr/freeldr/freeldr_main.xml @@ -1,7 +1,8 @@ include + include + -nostdlib - -nostdinc -ffreestanding -fno-builtin -fno-inline diff --git a/reactos/boot/freeldr/freeldr/freeldr_startup.xml b/reactos/boot/freeldr/freeldr/freeldr_startup.xml index 238d487f537..d69984cf13e 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_startup.xml +++ b/reactos/boot/freeldr/freeldr/freeldr_startup.xml @@ -1,7 +1,8 @@ include + include + -nostdlib - -nostdinc -ffreestanding -fno-builtin -fno-inline diff --git a/reactos/boot/freeldr/freeldr/fs/ext2.c b/reactos/boot/freeldr/freeldr/fs/ext2.c index 0710196df09..8825c87f471 100644 --- a/reactos/boot/freeldr/freeldr/fs/ext2.c +++ b/reactos/boot/freeldr/freeldr/fs/ext2.c @@ -35,17 +35,17 @@ GEOMETRY Ext2DiskGeometry; // Ext2 file system disk geometry PEXT2_SUPER_BLOCK Ext2SuperBlock = NULL; // Ext2 file system super block PEXT2_GROUP_DESC Ext2GroupDescriptors = NULL; // Ext2 file system group descriptors -U8 Ext2DriveNumber = 0; // Ext2 file system drive number -U64 Ext2VolumeStartSector = 0; // Ext2 file system starting sector -U32 Ext2BlockSizeInBytes = 0; // Block size in bytes -U32 Ext2BlockSizeInSectors = 0; // Block size in sectors -U32 Ext2FragmentSizeInBytes = 0; // Fragment size in bytes -U32 Ext2FragmentSizeInSectors = 0; // Fragment size in sectors -U32 Ext2GroupCount = 0; // Number of groups in this file system -U32 Ext2InodesPerBlock = 0; // Number of inodes in one block -U32 Ext2GroupDescPerBlock = 0; // Number of group descriptors in one block +UCHAR Ext2DriveNumber = 0; // Ext2 file system drive number +ULONGLONG Ext2VolumeStartSector = 0; // Ext2 file system starting sector +ULONG Ext2BlockSizeInBytes = 0; // Block size in bytes +ULONG Ext2BlockSizeInSectors = 0; // Block size in sectors +ULONG Ext2FragmentSizeInBytes = 0; // Fragment size in bytes +ULONG Ext2FragmentSizeInSectors = 0; // Fragment size in sectors +ULONG Ext2GroupCount = 0; // Number of groups in this file system +ULONG Ext2InodesPerBlock = 0; // Number of inodes in one block +ULONG Ext2GroupDescPerBlock = 0; // Number of group descriptors in one block -BOOL Ext2OpenVolume(U8 DriveNumber, U64 VolumeStartSector) +BOOL Ext2OpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector) { DbgPrint((DPRINT_FILESYSTEM, "Ext2OpenVolume() DriveNumber = 0x%x VolumeStartSector = %d\n", DriveNumber, VolumeStartSector)); @@ -93,7 +93,7 @@ FILE* Ext2OpenFile(PUCHAR FileName) PEXT2_FILE_INFO FileHandle; UCHAR SymLinkPath[EXT3_NAME_LEN]; UCHAR FullPath[EXT3_NAME_LEN * 2]; - U32 Index; + ULONG Index; DbgPrint((DPRINT_FILESYSTEM, "Ext2OpenFile() FileName = %s\n", FileName)); @@ -193,10 +193,10 @@ FILE* Ext2OpenFile(PUCHAR FileName) BOOL Ext2LookupFile(PUCHAR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer) { int i; - U32 NumberOfPathParts; + ULONG NumberOfPathParts; UCHAR PathPart[261]; PVOID DirectoryBuffer; - U32 DirectoryInode = EXT3_ROOT_INO; + ULONG DirectoryInode = EXT3_ROOT_INO; EXT2_INODE InodeData; EXT2_DIR_ENTRY DirectoryEntry; @@ -238,7 +238,7 @@ BOOL Ext2LookupFile(PUCHAR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer) // // Search for file name in directory // - if (!Ext2SearchDirectoryBufferForFile(DirectoryBuffer, (U32)Ext2GetInodeFileSize(&InodeData), PathPart, &DirectoryEntry)) + if (!Ext2SearchDirectoryBufferForFile(DirectoryBuffer, (ULONG)Ext2GetInodeFileSize(&InodeData), PathPart, &DirectoryEntry)) { MmFreeMemory(DirectoryBuffer); return FALSE; @@ -289,9 +289,9 @@ BOOL Ext2LookupFile(PUCHAR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer) return TRUE; } -BOOL Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, PUCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry) +BOOL Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PUCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry) { - U32 CurrentOffset; + ULONG CurrentOffset; PEXT2_DIR_ENTRY CurrentDirectoryEntry; DbgPrint((DPRINT_FILESYSTEM, "Ext2SearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = %s\n", DirectoryBuffer, DirectorySize, FileName)); @@ -345,16 +345,16 @@ BOOL Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, * Reads BytesToRead from open file and * returns the number of bytes read in BytesRead */ -BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffer) +BOOL Ext2ReadFile(FILE *FileHandle, ULONGLONG BytesToRead, ULONGLONG* BytesRead, PVOID Buffer) { PEXT2_FILE_INFO Ext2FileInfo = (PEXT2_FILE_INFO)FileHandle; - U32 BlockNumber; - U32 BlockNumberIndex; - U32 OffsetInBlock; - U32 LengthInBlock; - U32 NumberOfBlocks; + ULONG BlockNumber; + ULONG BlockNumberIndex; + ULONG OffsetInBlock; + ULONG LengthInBlock; + ULONG NumberOfBlocks; - DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadFile() BytesToRead = %d Buffer = 0x%x\n", (U32)BytesToRead, Buffer)); + DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadFile() BytesToRead = %d Buffer = 0x%x\n", (ULONG)BytesToRead, Buffer)); if (BytesRead != NULL) { @@ -529,7 +529,7 @@ BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffe return TRUE; } -U64 Ext2GetFileSize(FILE *FileHandle) +ULONGLONG Ext2GetFileSize(FILE *FileHandle) { PEXT2_FILE_INFO Ext2FileHandle = (PEXT2_FILE_INFO)FileHandle; @@ -538,7 +538,7 @@ U64 Ext2GetFileSize(FILE *FileHandle) return Ext2FileHandle->FileSize; } -VOID Ext2SetFilePointer(FILE *FileHandle, U64 NewFilePointer) +VOID Ext2SetFilePointer(FILE *FileHandle, ULONGLONG NewFilePointer) { PEXT2_FILE_INFO Ext2FileHandle = (PEXT2_FILE_INFO)FileHandle; @@ -547,7 +547,7 @@ VOID Ext2SetFilePointer(FILE *FileHandle, U64 NewFilePointer) Ext2FileHandle->FilePointer = NewFilePointer; } -U64 Ext2GetFilePointer(FILE *FileHandle) +ULONGLONG Ext2GetFilePointer(FILE *FileHandle) { PEXT2_FILE_INFO Ext2FileHandle = (PEXT2_FILE_INFO)FileHandle; @@ -556,7 +556,7 @@ U64 Ext2GetFilePointer(FILE *FileHandle) return Ext2FileHandle->FilePointer; } -BOOL Ext2ReadVolumeSectors(U8 DriveNumber, U64 SectorNumber, U64 SectorCount, PVOID Buffer) +BOOL Ext2ReadVolumeSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONGLONG SectorCount, PVOID Buffer) { //GEOMETRY DiskGeometry; //BOOL ReturnValue; @@ -734,8 +734,8 @@ BOOL Ext2ReadSuperBlock(VOID) BOOL Ext2ReadGroupDescriptors(VOID) { - U32 GroupDescBlockCount; - U32 CurrentGroupDescBlock; + ULONG GroupDescBlockCount; + ULONG CurrentGroupDescBlock; DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadGroupDescriptors()\n")); @@ -778,7 +778,7 @@ BOOL Ext2ReadGroupDescriptors(VOID) return TRUE; } -BOOL Ext2ReadDirectory(U32 Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer) +BOOL Ext2ReadDirectory(ULONG Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer) { EXT2_FILE_INFO DirectoryFileInfo; @@ -837,7 +837,7 @@ BOOL Ext2ReadDirectory(U32 Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePoint return TRUE; } -BOOL Ext2ReadBlock(U32 BlockNumber, PVOID Buffer) +BOOL Ext2ReadBlock(ULONG BlockNumber, PVOID Buffer) { UCHAR ErrorString[80]; @@ -861,14 +861,14 @@ BOOL Ext2ReadBlock(U32 BlockNumber, PVOID Buffer) return TRUE; } - return Ext2ReadVolumeSectors(Ext2DriveNumber, (U64)BlockNumber * Ext2BlockSizeInSectors, Ext2BlockSizeInSectors, Buffer); + return Ext2ReadVolumeSectors(Ext2DriveNumber, (ULONGLONG)BlockNumber * Ext2BlockSizeInSectors, Ext2BlockSizeInSectors, Buffer); } /* * Ext2ReadPartialBlock() * Reads part of a block into memory */ -BOOL Ext2ReadPartialBlock(U32 BlockNumber, U32 StartingOffset, U32 Length, PVOID Buffer) +BOOL Ext2ReadPartialBlock(ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer) { DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadPartialBlock() BlockNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", BlockNumber, StartingOffset, Length, Buffer)); @@ -883,36 +883,36 @@ BOOL Ext2ReadPartialBlock(U32 BlockNumber, U32 StartingOffset, U32 Length, PVOID return TRUE; } -U32 Ext2GetGroupDescBlockNumber(U32 Group) +ULONG Ext2GetGroupDescBlockNumber(ULONG Group) { return (((Group * sizeof(EXT2_GROUP_DESC)) / Ext2GroupDescPerBlock) + Ext2SuperBlock->s_first_data_block + 1); } -U32 Ext2GetGroupDescOffsetInBlock(U32 Group) +ULONG Ext2GetGroupDescOffsetInBlock(ULONG Group) { return ((Group * sizeof(EXT2_GROUP_DESC)) % Ext2GroupDescPerBlock); } -U32 Ext2GetInodeGroupNumber(U32 Inode) +ULONG Ext2GetInodeGroupNumber(ULONG Inode) { return ((Inode - 1) / Ext2SuperBlock->s_inodes_per_group); } -U32 Ext2GetInodeBlockNumber(U32 Inode) +ULONG Ext2GetInodeBlockNumber(ULONG Inode) { return (((Inode - 1) % Ext2SuperBlock->s_inodes_per_group) / Ext2InodesPerBlock); } -U32 Ext2GetInodeOffsetInBlock(U32 Inode) +ULONG Ext2GetInodeOffsetInBlock(ULONG Inode) { return (((Inode - 1) % Ext2SuperBlock->s_inodes_per_group) % Ext2InodesPerBlock); } -BOOL Ext2ReadInode(U32 Inode, PEXT2_INODE InodeBuffer) +BOOL Ext2ReadInode(ULONG Inode, PEXT2_INODE InodeBuffer) { - U32 InodeGroupNumber; - U32 InodeBlockNumber; - U32 InodeOffsetInBlock; + ULONG InodeGroupNumber; + ULONG InodeBlockNumber; + ULONG InodeOffsetInBlock; UCHAR ErrorString[80]; EXT2_GROUP_DESC GroupDescriptor; @@ -978,7 +978,7 @@ BOOL Ext2ReadInode(U32 Inode, PEXT2_INODE InodeBuffer) return TRUE; } -BOOL Ext2ReadGroupDescriptor(U32 Group, PEXT2_GROUP_DESC GroupBuffer) +BOOL Ext2ReadGroupDescriptor(ULONG Group, PEXT2_GROUP_DESC GroupBuffer) { DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadGroupDescriptor()\n")); @@ -1002,13 +1002,13 @@ BOOL Ext2ReadGroupDescriptor(U32 Group, PEXT2_GROUP_DESC GroupBuffer) return TRUE; } -U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode) +ULONG* Ext2ReadBlockPointerList(PEXT2_INODE Inode) { - U64 FileSize; - U32 BlockCount; - U32* BlockList; - U32 CurrentBlockInList; - U32 CurrentBlock; + ULONGLONG FileSize; + ULONG BlockCount; + ULONG* BlockList; + ULONG CurrentBlockInList; + ULONG CurrentBlock; DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadBlockPointerList()\n")); @@ -1023,13 +1023,13 @@ U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode) BlockCount = (FileSize / Ext2BlockSizeInBytes); // Allocate the memory for the block list - BlockList = MmAllocateMemory(BlockCount * sizeof(U32)); + BlockList = MmAllocateMemory(BlockCount * sizeof(ULONG)); if (BlockList == NULL) { return NULL; } - RtlZeroMemory(BlockList, BlockCount * sizeof(U32)); + RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG)); CurrentBlockInList = 0; // Copy the direct block pointers @@ -1072,27 +1072,27 @@ U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode) return BlockList; } -U64 Ext2GetInodeFileSize(PEXT2_INODE Inode) +ULONGLONG Ext2GetInodeFileSize(PEXT2_INODE Inode) { if ((Inode->i_mode & EXT2_S_IFMT) == EXT2_S_IFDIR) { - return (U64)(Inode->i_size); + return (ULONGLONG)(Inode->i_size); } else { - return ((U64)(Inode->i_size) | ((U64)(Inode->i_dir_acl) << 32)); + return ((ULONGLONG)(Inode->i_size) | ((ULONGLONG)(Inode->i_dir_acl) << 32)); } } -BOOL Ext2CopyIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 IndirectBlock) +BOOL Ext2CopyIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock) { - U32* BlockBuffer = (U32*)FILESYSBUFFER; - U32 CurrentBlock; - U32 BlockPointersPerBlock; + ULONG* BlockBuffer = (ULONG*)FILESYSBUFFER; + ULONG CurrentBlock; + ULONG BlockPointersPerBlock; DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyIndirectBlockPointers() BlockCount = %d\n", BlockCount)); - BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32); + BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG); if (!Ext2ReadBlock(IndirectBlock, BlockBuffer)) { @@ -1108,17 +1108,17 @@ BOOL Ext2CopyIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 return TRUE; } -BOOL Ext2CopyDoubleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 DoubleIndirectBlock) +BOOL Ext2CopyDoubleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock) { - U32* BlockBuffer; - U32 CurrentBlock; - U32 BlockPointersPerBlock; + ULONG* BlockBuffer; + ULONG CurrentBlock; + ULONG BlockPointersPerBlock; DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount)); - BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32); + BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG); - BlockBuffer = (U32*)MmAllocateMemory(Ext2BlockSizeInBytes); + BlockBuffer = (ULONG*)MmAllocateMemory(Ext2BlockSizeInBytes); if (BlockBuffer == NULL) { return FALSE; @@ -1143,17 +1143,17 @@ BOOL Ext2CopyDoubleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList return TRUE; } -BOOL Ext2CopyTripleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 TripleIndirectBlock) +BOOL Ext2CopyTripleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock) { - U32* BlockBuffer; - U32 CurrentBlock; - U32 BlockPointersPerBlock; + ULONG* BlockBuffer; + ULONG CurrentBlock; + ULONG BlockPointersPerBlock; DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount)); - BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32); + BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG); - BlockBuffer = (U32*)MmAllocateMemory(Ext2BlockSizeInBytes); + BlockBuffer = (ULONG*)MmAllocateMemory(Ext2BlockSizeInBytes); if (BlockBuffer == NULL) { return FALSE; diff --git a/reactos/boot/freeldr/freeldr/fs/ext2.h b/reactos/boot/freeldr/freeldr/fs/ext2.h index 8204f1eac3e..5f3f02d6eed 100644 --- a/reactos/boot/freeldr/freeldr/fs/ext2.h +++ b/reactos/boot/freeldr/freeldr/fs/ext2.h @@ -113,7 +113,7 @@ # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size) #endif #define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry)) -#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32)) +#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (ULONG)) #ifdef __KERNEL__ # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) #else @@ -151,20 +151,20 @@ */ struct ext3_acl_header /* Header of Access Control Lists */ { - __u32 aclh_size; - __u32 aclh_file_count; - __u32 aclh_acle_count; - __u32 aclh_first_acle; + ULONG aclh_size; + ULONG aclh_file_count; + ULONG aclh_acle_count; + ULONG aclh_first_acle; }; struct ext3_acl_entry /* Access Control List Entry */ { - __u32 acle_size; - __u16 acle_perms; /* Access permissions */ - __u16 acle_type; /* Type of entry */ - __u16 acle_tag; /* User or group identity */ - __u16 acle_pad1; - __u32 acle_next; /* Pointer on next entry for the */ + ULONG acle_size; + USHORT acle_perms; /* Access permissions */ + USHORT acle_type; /* Type of entry */ + USHORT acle_tag; /* User or group identity */ + USHORT acle_pad1; + ULONG acle_next; /* Pointer on next entry for the */ /* same inode or on next free entry */ }; @@ -173,14 +173,14 @@ struct ext3_acl_entry /* Access Control List Entry */ */ struct ext3_group_desc { - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_pad; - __u32 bg_reserved[3]; + ULONG bg_block_bitmap; /* Blocks bitmap block */ + ULONG bg_inode_bitmap; /* Inodes bitmap block */ + ULONG bg_inode_table; /* Inodes table block */ + USHORT bg_free_blocks_count; /* Free blocks count */ + USHORT bg_free_inodes_count; /* Free inodes count */ + USHORT bg_used_dirs_count; /* Directories count */ + USHORT bg_pad; + ULONG bg_reserved[3]; }; /* @@ -254,55 +254,55 @@ struct ext3_group_desc * Structure of an inode on the disk */ struct ext3_inode { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Low 16 bits of Owner Uid */ - __u32 i_size; /* Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u16 i_gid; /* Low 16 bits of Group Id */ - __u16 i_links_count; /* Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* File flags */ + USHORT i_mode; /* File mode */ + USHORT i_uid; /* Low 16 bits of Owner Uid */ + ULONG i_size; /* Size in bytes */ + ULONG i_atime; /* Access time */ + ULONG i_ctime; /* Creation time */ + ULONG i_mtime; /* Modification time */ + ULONG i_dtime; /* Deletion Time */ + USHORT i_gid; /* Low 16 bits of Group Id */ + USHORT i_links_count; /* Links count */ + ULONG i_blocks; /* Blocks count */ + ULONG i_flags; /* File flags */ union { struct { - __u32 l_i_reserved1; + ULONG l_i_reserved1; } linux1; struct { - __u32 h_i_translator; + ULONG h_i_translator; } hurd1; struct { - __u32 m_i_reserved1; + ULONG m_i_reserved1; } masix1; } osd1; /* OS dependent 1 */ - __u32 i_block[EXT3_N_BLOCKS];/* Pointers to blocks */ - __u32 i_generation; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ + ULONG i_block[EXT3_N_BLOCKS];/* Pointers to blocks */ + ULONG i_generation; /* File version (for NFS) */ + ULONG i_file_acl; /* File ACL */ + ULONG i_dir_acl; /* Directory ACL */ + ULONG i_faddr; /* Fragment address */ union { struct { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; - __u16 l_i_uid_high; /* these 2 fields */ - __u16 l_i_gid_high; /* were reserved2[0] */ - __u32 l_i_reserved2; + UCHAR l_i_frag; /* Fragment number */ + UCHAR l_i_fsize; /* Fragment size */ + USHORT i_pad1; + USHORT l_i_uid_high; /* these 2 fields */ + USHORT l_i_gid_high; /* were reserved2[0] */ + ULONG l_i_reserved2; } linux2; struct { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; + UCHAR h_i_frag; /* Fragment number */ + UCHAR h_i_fsize; /* Fragment size */ + USHORT h_i_mode_high; + USHORT h_i_uid_high; + USHORT h_i_gid_high; + ULONG h_i_author; } hurd2; struct { - __u8 m_i_frag; /* Fragment number */ - __u8 m_i_fsize; /* Fragment size */ - __u16 m_pad1; - __u32 m_i_reserved2[2]; + UCHAR m_i_frag; /* Fragment number */ + UCHAR m_i_fsize; /* Fragment size */ + USHORT m_pad1; + ULONG m_i_reserved2[2]; } masix2; } osd2; /* OS dependent 2 */ }; @@ -398,31 +398,31 @@ struct ext3_inode { * Structure of the super block */ struct ext3_super_block { -/*00*/ __u32 s_inodes_count; /* Inodes count */ - __u32 s_blocks_count; /* Blocks count */ - __u32 s_r_blocks_count; /* Reserved blocks count */ - __u32 s_free_blocks_count; /* Free blocks count */ -/*10*/ __u32 s_free_inodes_count; /* Free inodes count */ - __u32 s_first_data_block; /* First Data Block */ - __u32 s_log_block_size; /* Block size */ - __s32 s_log_frag_size; /* Fragment size */ -/*20*/ __u32 s_blocks_per_group; /* # Blocks per group */ - __u32 s_frags_per_group; /* # Fragments per group */ - __u32 s_inodes_per_group; /* # Inodes per group */ - __u32 s_mtime; /* Mount time */ -/*30*/ __u32 s_wtime; /* Write time */ - __u16 s_mnt_count; /* Mount count */ - __s16 s_max_mnt_count; /* Maximal mount count */ - __u16 s_magic; /* Magic signature */ - __u16 s_state; /* File system state */ - __u16 s_errors; /* Behaviour when detecting errors */ - __u16 s_minor_rev_level; /* minor revision level */ -/*40*/ __u32 s_lastcheck; /* time of last check */ - __u32 s_checkinterval; /* max. time between checks */ - __u32 s_creator_os; /* OS */ - __u32 s_rev_level; /* Revision level */ -/*50*/ __u16 s_def_resuid; /* Default uid for reserved blocks */ - __u16 s_def_resgid; /* Default gid for reserved blocks */ +/*00*/ ULONG s_inodes_count; /* Inodes count */ + ULONG s_blocks_count; /* Blocks count */ + ULONG s_r_blocks_count; /* Reserved blocks count */ + ULONG s_free_blocks_count; /* Free blocks count */ +/*10*/ ULONG s_free_inodes_count; /* Free inodes count */ + ULONG s_first_data_block; /* First Data Block */ + ULONG s_log_block_size; /* Block size */ + LONG s_log_frag_size; /* Fragment size */ +/*20*/ ULONG s_blocks_per_group; /* # Blocks per group */ + ULONG s_frags_per_group; /* # Fragments per group */ + ULONG s_inodes_per_group; /* # Inodes per group */ + ULONG s_mtime; /* Mount time */ +/*30*/ ULONG s_wtime; /* Write time */ + USHORT s_mnt_count; /* Mount count */ + SHORT s_max_mnt_count; /* Maximal mount count */ + USHORT s_magic; /* Magic signature */ + USHORT s_state; /* File system state */ + USHORT s_errors; /* Behaviour when detecting errors */ + USHORT s_minor_rev_level; /* minor revision level */ +/*40*/ ULONG s_lastcheck; /* time of last check */ + ULONG s_checkinterval; /* max. time between checks */ + ULONG s_creator_os; /* OS */ + ULONG s_rev_level; /* Revision level */ +/*50*/ USHORT s_def_resuid; /* Default uid for reserved blocks */ + USHORT s_def_resgid; /* Default gid for reserved blocks */ /* * These fields are for EXT3_DYNAMIC_REV superblocks only. * @@ -436,32 +436,32 @@ struct ext3_super_block { * feature set, it must abort and not try to meddle with * things it doesn't understand... */ - __u32 s_first_ino; /* First non-reserved inode */ - __u16 s_inode_size; /* size of inode structure */ - __u16 s_block_group_nr; /* block group # of this superblock */ - __u32 s_feature_compat; /* compatible feature set */ -/*60*/ __u32 s_feature_incompat; /* incompatible feature set */ - __u32 s_feature_ro_compat; /* readonly-compatible feature set */ -/*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */ + ULONG s_first_ino; /* First non-reserved inode */ + USHORT s_inode_size; /* size of inode structure */ + USHORT s_block_group_nr; /* block group # of this superblock */ + ULONG s_feature_compat; /* compatible feature set */ +/*60*/ ULONG s_feature_incompat; /* incompatible feature set */ + ULONG s_feature_ro_compat; /* readonly-compatible feature set */ +/*68*/ UCHAR s_uuid[16]; /* 128-bit uuid for volume */ /*78*/ char s_volume_name[16]; /* volume name */ /*88*/ char s_last_mounted[64]; /* directory where last mounted */ -/*C8*/ __u32 s_algorithm_usage_bitmap; /* For compression */ +/*C8*/ ULONG s_algorithm_usage_bitmap; /* For compression */ /* * Performance hints. Directory preallocation should only * happen if the EXT3_FEATURE_COMPAT_DIR_PREALLOC flag is on. */ - __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ - __u16 s_padding1; + UCHAR s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + UCHAR s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + USHORT s_padding1; /* * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set. */ -/*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */ -/*E0*/ __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ +/*D0*/ UCHAR s_journal_uuid[16]; /* uuid of journal superblock */ +/*E0*/ ULONG s_journal_inum; /* inode number of journal file */ + ULONG s_journal_dev; /* device number of journal file */ + ULONG s_last_orphan; /* start of list of inodes to delete */ -/*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */ +/*EC*/ ULONG s_reserved[197]; /* Padding to the end of the block */ }; #ifdef __KERNEL__ @@ -555,9 +555,9 @@ struct ext3_super_block { #define EXT3_NAME_LEN 255 struct ext3_dir_entry { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u16 name_len; /* Name length */ + ULONG inode; /* Inode number */ + USHORT rec_len; /* Directory entry length */ + USHORT name_len; /* Name length */ char name[EXT3_NAME_LEN]; /* File name */ }; @@ -568,10 +568,10 @@ struct ext3_dir_entry { * file_type field. */ struct ext3_dir_entry_2 { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u8 name_len; /* Name length */ - __u8 file_type; + ULONG inode; /* Inode number */ + USHORT rec_len; /* Directory entry length */ + UCHAR name_len; /* Name length */ + UCHAR file_type; char name[EXT3_NAME_LEN]; /* File name */ }; @@ -653,45 +653,45 @@ typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY; #define EXT2_S_IFLNK 0xA000 // Symbolic link #define EXT2_S_IFSOCK 0xC000 // Socket -#define FAST_SYMLINK_MAX_NAME_SIZE (EXT3_N_BLOCKS * sizeof(U32)) /* 60 bytes */ +#define FAST_SYMLINK_MAX_NAME_SIZE (EXT3_N_BLOCKS * sizeof(ULONG)) /* 60 bytes */ typedef struct { - U64 FileSize; // File size - U64 FilePointer; // File pointer - U32* FileBlockList; // File block list - U8 DriveNumber; // Drive number of open file + ULONGLONG FileSize; // File size + ULONGLONG FilePointer; // File pointer + ULONG* FileBlockList; // File block list + UCHAR DriveNumber; // Drive number of open file EXT2_INODE Inode; // File's inode } EXT2_FILE_INFO, * PEXT2_FILE_INFO; -BOOL Ext2OpenVolume(U8 DriveNumber, U64 VolumeStartSector); +BOOL Ext2OpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector); FILE* Ext2OpenFile(PUCHAR FileName); BOOL Ext2LookupFile(PUCHAR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer); -BOOL Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, PUCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry); -BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffer); -U64 Ext2GetFileSize(FILE *FileHandle); -VOID Ext2SetFilePointer(FILE *FileHandle, U64 NewFilePointer); -U64 Ext2GetFilePointer(FILE *FileHandle); -BOOL Ext2ReadVolumeSectors(U8 DriveNumber, U64 SectorNumber, U64 SectorCount, PVOID Buffer); +BOOL Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PUCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry); +BOOL Ext2ReadFile(FILE *FileHandle, ULONGLONG BytesToRead, ULONGLONG* BytesRead, PVOID Buffer); +ULONGLONG Ext2GetFileSize(FILE *FileHandle); +VOID Ext2SetFilePointer(FILE *FileHandle, ULONGLONG NewFilePointer); +ULONGLONG Ext2GetFilePointer(FILE *FileHandle); +BOOL Ext2ReadVolumeSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONGLONG SectorCount, PVOID Buffer); BOOL Ext2ReadSuperBlock(VOID); BOOL Ext2ReadGroupDescriptors(VOID); -BOOL Ext2ReadDirectory(U32 Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer); -BOOL Ext2ReadBlock(U32 BlockNumber, PVOID Buffer); -BOOL Ext2ReadPartialBlock(U32 BlockNumber, U32 StartingOffset, U32 Length, PVOID Buffer); -U32 Ext2GetGroupDescBlockNumber(U32 Group); -U32 Ext2GetGroupDescOffsetInBlock(U32 Group); -U32 Ext2GetInodeGroupNumber(U32 Inode); -U32 Ext2GetInodeBlockNumber(U32 Inode); -U32 Ext2GetInodeOffsetInBlock(U32 Inode); -BOOL Ext2ReadInode(U32 Inode, PEXT2_INODE InodeBuffer); -BOOL Ext2ReadGroupDescriptor(U32 Group, PEXT2_GROUP_DESC GroupBuffer); -U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode); -U64 Ext2GetInodeFileSize(PEXT2_INODE Inode); -BOOL Ext2CopyIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 IndirectBlock); -BOOL Ext2CopyDoubleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 DoubleIndirectBlock); -BOOL Ext2CopyTripleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 TripleIndirectBlock); +BOOL Ext2ReadDirectory(ULONG Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer); +BOOL Ext2ReadBlock(ULONG BlockNumber, PVOID Buffer); +BOOL Ext2ReadPartialBlock(ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer); +ULONG Ext2GetGroupDescBlockNumber(ULONG Group); +ULONG Ext2GetGroupDescOffsetInBlock(ULONG Group); +ULONG Ext2GetInodeGroupNumber(ULONG Inode); +ULONG Ext2GetInodeBlockNumber(ULONG Inode); +ULONG Ext2GetInodeOffsetInBlock(ULONG Inode); +BOOL Ext2ReadInode(ULONG Inode, PEXT2_INODE InodeBuffer); +BOOL Ext2ReadGroupDescriptor(ULONG Group, PEXT2_GROUP_DESC GroupBuffer); +ULONG* Ext2ReadBlockPointerList(PEXT2_INODE Inode); +ULONGLONG Ext2GetInodeFileSize(PEXT2_INODE Inode); +BOOL Ext2CopyIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock); +BOOL Ext2CopyDoubleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock); +BOOL Ext2CopyTripleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock); #endif // #defined __EXT2_H diff --git a/reactos/boot/freeldr/freeldr/fs/fat.c b/reactos/boot/freeldr/freeldr/fs/fat.c index 65f8a95a043..973cf55383c 100644 --- a/reactos/boot/freeldr/freeldr/fs/fat.c +++ b/reactos/boot/freeldr/freeldr/fs/fat.c @@ -29,25 +29,25 @@ #include #include -U32 BytesPerSector; /* Number of bytes per sector */ -U32 SectorsPerCluster; /* Number of sectors per cluster */ -U32 FatVolumeStartSector; /* Absolute starting sector of the partition */ -U32 FatSectorStart; /* Starting sector of 1st FAT table */ -U32 ActiveFatSectorStart; /* Starting sector of active FAT table */ -U32 NumberOfFats; /* Number of FAT tables */ -U32 SectorsPerFat; /* Sectors per FAT table */ -U32 RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */ -U32 RootDirSectors; /* Number of sectors of the root directory (non-fat32) */ -U32 RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */ -U32 DataSectorStart; /* Starting sector of the data area */ +ULONG BytesPerSector; /* Number of bytes per sector */ +ULONG SectorsPerCluster; /* Number of sectors per cluster */ +ULONG FatVolumeStartSector; /* Absolute starting sector of the partition */ +ULONG FatSectorStart; /* Starting sector of 1st FAT table */ +ULONG ActiveFatSectorStart; /* Starting sector of active FAT table */ +ULONG NumberOfFats; /* Number of FAT tables */ +ULONG SectorsPerFat; /* Sectors per FAT table */ +ULONG RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */ +ULONG RootDirSectors; /* Number of sectors of the root directory (non-fat32) */ +ULONG RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */ +ULONG DataSectorStart; /* Starting sector of the data area */ -U32 FatType = 0; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */ -U32 FatDriveNumber = 0; +ULONG FatType = 0; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */ +ULONG FatDriveNumber = 0; -BOOL FatOpenVolume(U32 DriveNumber, U32 VolumeStartSector, U32 PartitionSectorCount) +BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG PartitionSectorCount) { char ErrMsg[80]; - U32 FatSize; + ULONG FatSize; PFAT_BOOTSECTOR FatVolumeBootSector; PFAT32_BOOTSECTOR Fat32VolumeBootSector; PFATX_BOOTSECTOR FatXVolumeBootSector; @@ -288,13 +288,13 @@ BOOL FatOpenVolume(U32 DriveNumber, U32 VolumeStartSector, U32 PartitionSectorCo return TRUE; } -U32 FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, U32 PartitionSectorCount) +ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCount) { - U32 RootDirSectors; - U32 DataSectorCount; - U32 SectorsPerFat; - U32 TotalSectors; - U32 CountOfClusters; + ULONG RootDirSectors; + ULONG DataSectorCount; + ULONG SectorsPerFat; + ULONG TotalSectors; + ULONG CountOfClusters; PFAT32_BOOTSECTOR Fat32BootSector = (PFAT32_BOOTSECTOR)FatBootSector; PFATX_BOOTSECTOR FatXBootSector = (PFATX_BOOTSECTOR)FatBootSector; @@ -343,7 +343,7 @@ U32 FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, U32 PartitionSectorCount) } } -PVOID FatBufferDirectory(U32 DirectoryStartCluster, U32 *DirectorySize, BOOL RootDirectory) +PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL RootDirectory) { PVOID DirectoryBuffer; @@ -405,15 +405,15 @@ PVOID FatBufferDirectory(U32 DirectoryStartCluster, U32 *DirectorySize, BOOL Roo return DirectoryBuffer; } -BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) +BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) { - U32 EntryCount; - U32 CurrentEntry; + ULONG EntryCount; + ULONG CurrentEntry; PDIRENTRY DirEntry; PLFN_DIRENTRY LfnDirEntry; UCHAR LfnNameBuffer[265]; UCHAR ShortNameBuffer[20]; - U32 StartCluster; + ULONG StartCluster; EntryCount = DirectorySize / sizeof(DIRENTRY); @@ -590,7 +590,7 @@ BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, P // // Get the cluster chain // - StartCluster = ((U32)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow; + StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow; DbgPrint((DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", StartCluster)); FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(StartCluster); @@ -616,12 +616,12 @@ BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, P return FALSE; } -BOOL FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) +BOOL FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) { - U32 EntryCount; - U32 CurrentEntry; + ULONG EntryCount; + ULONG CurrentEntry; PFATX_DIRENTRY DirEntry; - U32 FileNameLen; + ULONG FileNameLen; EntryCount = DirectorySize / sizeof(FATX_DIRENTRY); @@ -690,11 +690,11 @@ BOOL FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectorySize, BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) { int i; - U32 NumberOfPathParts; + ULONG NumberOfPathParts; UCHAR PathPart[261]; PVOID DirectoryBuffer; - U32 DirectoryStartCluster = 0; - U32 DirectorySize; + ULONG DirectoryStartCluster = 0; + ULONG DirectorySize; FAT_FILE_INFO FatFileInfo; DbgPrint((DPRINT_FILESYSTEM, "FatLookupFile() FileName = %s\n", FileName)); @@ -779,7 +779,7 @@ BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) */ void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry) { - U32 Idx; + ULONG Idx; Idx = 0; RtlZeroMemory(Buffer, 13); @@ -824,9 +824,9 @@ void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry) * FatGetFatEntry() * returns the Fat entry for a given cluster number */ -BOOL FatGetFatEntry(U32 Cluster, U32* ClusterPointer) +BOOL FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer) { - U32 fat = 0; + ULONG fat = 0; int FatOffset; int ThisFatSecNum; int ThisFatEntOffset; @@ -860,7 +860,7 @@ BOOL FatGetFatEntry(U32 Cluster, U32* ClusterPointer) } } - fat = *((U16 *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset)); + fat = *((USHORT *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset)); if (Cluster & 0x0001) fat = fat >> 4; /* Cluster number is ODD */ else @@ -880,7 +880,7 @@ BOOL FatGetFatEntry(U32 Cluster, U32* ClusterPointer) return FALSE; } - fat = *((U16 *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset)); + fat = *((USHORT *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset)); break; @@ -897,7 +897,7 @@ BOOL FatGetFatEntry(U32 Cluster, U32* ClusterPointer) } // Get the fat entry - fat = (*((U32 *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF; + fat = (*((ULONG *) ((PVOID)FILESYSBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF; break; @@ -939,9 +939,9 @@ FILE* FatOpenFile(PUCHAR FileName) return (FILE*)FileHandle; } -U32 FatCountClustersInChain(U32 StartCluster) +ULONG FatCountClustersInChain(ULONG StartCluster) { - U32 ClusterCount = 0; + ULONG ClusterCount = 0; DbgPrint((DPRINT_FILESYSTEM, "FatCountClustersInChain() StartCluster = %d\n", StartCluster)); @@ -976,17 +976,17 @@ U32 FatCountClustersInChain(U32 StartCluster) return ClusterCount; } -U32* FatGetClusterChainArray(U32 StartCluster) +ULONG* FatGetClusterChainArray(ULONG StartCluster) { - U32 ClusterCount; - U32 ArraySize; - U32* ArrayPointer; - U32 Idx; + ULONG ClusterCount; + ULONG ArraySize; + ULONG* ArrayPointer; + ULONG Idx; DbgPrint((DPRINT_FILESYSTEM, "FatGetClusterChainArray() StartCluster = %d\n", StartCluster)); ClusterCount = FatCountClustersInChain(StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array - ArraySize = ClusterCount * sizeof(U32); + ArraySize = ClusterCount * sizeof(ULONG); // // Allocate array memory @@ -1036,9 +1036,9 @@ U32* FatGetClusterChainArray(U32 StartCluster) * FatReadCluster() * Reads the specified cluster into memory */ -BOOL FatReadCluster(U32 ClusterNumber, PVOID Buffer) +BOOL FatReadCluster(ULONG ClusterNumber, PVOID Buffer) { - U32 ClusterStartSector; + ULONG ClusterStartSector; ClusterStartSector = ((ClusterNumber - 2) * SectorsPerCluster) + DataSectorStart; @@ -1058,9 +1058,9 @@ BOOL FatReadCluster(U32 ClusterNumber, PVOID Buffer) * FatReadClusterChain() * Reads the specified clusters into memory */ -BOOL FatReadClusterChain(U32 StartClusterNumber, U32 NumberOfClusters, PVOID Buffer) +BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer) { - U32 ClusterStartSector; + ULONG ClusterStartSector; DbgPrint((DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer)); @@ -1119,9 +1119,9 @@ BOOL FatReadClusterChain(U32 StartClusterNumber, U32 NumberOfClusters, PVOID Buf * FatReadPartialCluster() * Reads part of a cluster into memory */ -BOOL FatReadPartialCluster(U32 ClusterNumber, U32 StartingOffset, U32 Length, PVOID Buffer) +BOOL FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer) { - U32 ClusterStartSector; + ULONG ClusterStartSector; DbgPrint((DPRINT_FILESYSTEM, "FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer)); @@ -1142,14 +1142,14 @@ BOOL FatReadPartialCluster(U32 ClusterNumber, U32 StartingOffset, U32 Length, PV * Reads BytesToRead from open file and * returns the number of bytes read in BytesRead */ -BOOL FatReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) +BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) { PFAT_FILE_INFO FatFileInfo = (PFAT_FILE_INFO)FileHandle; - U32 ClusterNumber; - U32 OffsetInCluster; - U32 LengthInCluster; - U32 NumberOfClusters; - U32 BytesPerCluster; + ULONG ClusterNumber; + ULONG OffsetInCluster; + ULONG LengthInCluster; + ULONG NumberOfClusters; + ULONG BytesPerCluster; DbgPrint((DPRINT_FILESYSTEM, "FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer)); @@ -1296,7 +1296,7 @@ BOOL FatReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer return TRUE; } -U32 FatGetFileSize(FILE *FileHandle) +ULONG FatGetFileSize(FILE *FileHandle) { PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle; @@ -1305,7 +1305,7 @@ U32 FatGetFileSize(FILE *FileHandle) return FatFileHandle->FileSize; } -VOID FatSetFilePointer(FILE *FileHandle, U32 NewFilePointer) +VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer) { PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle; @@ -1314,7 +1314,7 @@ VOID FatSetFilePointer(FILE *FileHandle, U32 NewFilePointer) FatFileHandle->FilePointer = NewFilePointer; } -U32 FatGetFilePointer(FILE *FileHandle) +ULONG FatGetFilePointer(FILE *FileHandle) { PFAT_FILE_INFO FatFileHandle = (PFAT_FILE_INFO)FileHandle; @@ -1323,7 +1323,7 @@ U32 FatGetFilePointer(FILE *FileHandle) return FatFileHandle->FilePointer; } -BOOL FatReadVolumeSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer) +BOOL FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer) { return CacheReadDiskSectors(DriveNumber, SectorNumber + FatVolumeStartSector, SectorCount, Buffer); } diff --git a/reactos/boot/freeldr/freeldr/fs/fat.h b/reactos/boot/freeldr/freeldr/fs/fat.h index db21e0f315f..d697e4840f7 100644 --- a/reactos/boot/freeldr/freeldr/fs/fat.h +++ b/reactos/boot/freeldr/freeldr/fs/fat.h @@ -22,77 +22,77 @@ typedef struct _FAT_BOOTSECTOR { - U8 JumpBoot[3]; // Jump instruction to boot code - U8 OemName[8]; // "MSWIN4.1" for MS formatted volumes - U16 BytesPerSector; // Bytes per sector - U8 SectorsPerCluster; // Number of sectors in a cluster - U16 ReservedSectors; // Reserved sectors, usually 1 (the bootsector) - U8 NumberOfFats; // Number of FAT tables - U16 RootDirEntries; // Number of root directory entries (fat12/16) - U16 TotalSectors; // Number of total sectors on the drive, 16-bit - U8 MediaDescriptor; // Media descriptor byte - U16 SectorsPerFat; // Sectors per FAT table (fat12/16) - U16 SectorsPerTrack; // Number of sectors in a track - U16 NumberOfHeads; // Number of heads on the disk - U32 HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) - U32 TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume - U8 DriveNumber; // Int 0x13 drive number (e.g. 0x80) - U8 Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. - U8 BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. - U32 VolumeSerialNumber; // Volume serial number - U8 VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory - U8 FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " + UCHAR JumpBoot[3]; // Jump instruction to boot code + UCHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + UCHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + UCHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " - U8 BootCodeAndData[448]; // The remainder of the boot sector + UCHAR BootCodeAndData[448]; // The remainder of the boot sector - U16 BootSectorMagic; // 0xAA55 + USHORT BootSectorMagic; // 0xAA55 } PACKED FAT_BOOTSECTOR, *PFAT_BOOTSECTOR; typedef struct _FAT32_BOOTSECTOR { - U8 JumpBoot[3]; // Jump instruction to boot code - U8 OemName[8]; // "MSWIN4.1" for MS formatted volumes - U16 BytesPerSector; // Bytes per sector - U8 SectorsPerCluster; // Number of sectors in a cluster - U16 ReservedSectors; // Reserved sectors, usually 1 (the bootsector) - U8 NumberOfFats; // Number of FAT tables - U16 RootDirEntries; // Number of root directory entries (fat12/16) - U16 TotalSectors; // Number of total sectors on the drive, 16-bit - U8 MediaDescriptor; // Media descriptor byte - U16 SectorsPerFat; // Sectors per FAT table (fat12/16) - U16 SectorsPerTrack; // Number of sectors in a track - U16 NumberOfHeads; // Number of heads on the disk - U32 HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) - U32 TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume - U32 SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 - U16 ExtendedFlags; // Extended flags (fat32) - U16 FileSystemVersion; // File system version (fat32) - U32 RootDirStartCluster; // Starting cluster of the root directory (fat32) - U16 FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. - U16 BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. - U8 Reserved[12]; // Reserved for future expansion - U8 DriveNumber; // Int 0x13 drive number (e.g. 0x80) - U8 Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. - U8 BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. - U32 VolumeSerialNumber; // Volume serial number - U8 VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory - U8 FileSystemType[8]; // Always set to the string "FAT32 " + UCHAR JumpBoot[3]; // Jump instruction to boot code + UCHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 + USHORT ExtendedFlags; // Extended flags (fat32) + USHORT FileSystemVersion; // File system version (fat32) + ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) + USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. + USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. + UCHAR Reserved[12]; // Reserved for future expansion + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + UCHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + UCHAR FileSystemType[8]; // Always set to the string "FAT32 " - U8 BootCodeAndData[420]; // The remainder of the boot sector + UCHAR BootCodeAndData[420]; // The remainder of the boot sector - U16 BootSectorMagic; // 0xAA55 + USHORT BootSectorMagic; // 0xAA55 } PACKED FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR; typedef struct _FATX_BOOTSECTOR { - U8 FileSystemType[4]; /* String "FATX" */ - U32 VolumeSerialNumber; /* Volume serial number */ - U32 SectorsPerCluster; /* Number of sectors in a cluster */ - U16 NumberOfFats; /* Number of FAT tables */ - U32 Unknown; /* Always 0? */ - U8 Unused[494]; /* Actually size should be 4078 (boot block is 4096 bytes) */ + UCHAR FileSystemType[4]; /* String "FATX" */ + ULONG VolumeSerialNumber; /* Volume serial number */ + ULONG SectorsPerCluster; /* Number of sectors in a cluster */ + USHORT NumberOfFats; /* Number of FAT tables */ + ULONG Unknown; /* Always 0? */ + UCHAR Unused[494]; /* Actually size should be 4078 (boot block is 4096 bytes) */ } PACKED FATX_BOOTSECTOR, *PFATX_BOOTSECTOR; @@ -102,74 +102,74 @@ typedef struct _FATX_BOOTSECTOR typedef struct //_DIRENTRY { UCHAR FileName[11]; /* Filename + extension */ - U8 Attr; /* File attributes */ - U8 ReservedNT; /* Reserved for use by Windows NT */ - U8 TimeInTenths; /* Millisecond stamp at file creation */ - U16 CreateTime; /* Time file was created */ - U16 CreateDate; /* Date file was created */ - U16 LastAccessDate; /* Date file was last accessed */ - U16 ClusterHigh; /* High word of this entry's start cluster */ - U16 Time; /* Time last modified */ - U16 Date; /* Date last modified */ - U16 ClusterLow; /* First cluster number low word */ - U32 Size; /* File size */ + UCHAR Attr; /* File attributes */ + UCHAR ReservedNT; /* Reserved for use by Windows NT */ + UCHAR TimeInTenths; /* Millisecond stamp at file creation */ + USHORT CreateTime; /* Time file was created */ + USHORT CreateDate; /* Date file was created */ + USHORT LastAccessDate; /* Date file was last accessed */ + USHORT ClusterHigh; /* High word of this entry's start cluster */ + USHORT Time; /* Time last modified */ + USHORT Date; /* Date last modified */ + USHORT ClusterLow; /* First cluster number low word */ + ULONG Size; /* File size */ } PACKED DIRENTRY, * PDIRENTRY; typedef struct { - U8 SequenceNumber; /* Sequence number for slot */ + UCHAR SequenceNumber; /* Sequence number for slot */ WCHAR Name0_4[5]; /* First 5 characters in name */ - U8 EntryAttributes; /* Attribute byte */ - U8 Reserved; /* Always 0 */ - U8 AliasChecksum; /* Checksum for 8.3 alias */ + UCHAR EntryAttributes; /* Attribute byte */ + UCHAR Reserved; /* Always 0 */ + UCHAR AliasChecksum; /* Checksum for 8.3 alias */ WCHAR Name5_10[6]; /* 6 more characters in name */ - U16 StartCluster; /* Starting cluster number */ + USHORT StartCluster; /* Starting cluster number */ WCHAR Name11_12[2]; /* Last 2 characters in name */ } PACKED LFN_DIRENTRY, * PLFN_DIRENTRY; typedef struct { - U8 FileNameSize; /* Size of filename (max 42) */ - U8 Attr; /* File attributes */ + UCHAR FileNameSize; /* Size of filename (max 42) */ + UCHAR Attr; /* File attributes */ UCHAR FileName[42]; /* Filename in ASCII, padded with 0xff (not zero-terminated) */ - U32 StartCluster; /* Starting cluster number */ - U32 Size; /* File size */ - U16 Time; /* Time last modified */ - U16 Date; /* Date last modified */ - U16 CreateTime; /* Time file was created */ - U16 CreateDate; /* Date file was created */ - U16 LastAccessTime; /* Time file was last accessed */ - U16 LastAccessDate; /* Date file was last accessed */ + ULONG StartCluster; /* Starting cluster number */ + ULONG Size; /* File size */ + USHORT Time; /* Time last modified */ + USHORT Date; /* Date last modified */ + USHORT CreateTime; /* Time file was created */ + USHORT CreateDate; /* Date file was created */ + USHORT LastAccessTime; /* Time file was last accessed */ + USHORT LastAccessDate; /* Date file was last accessed */ } PACKED FATX_DIRENTRY, * PFATX_DIRENTRY; typedef struct { - U32 FileSize; /* File size */ - U32 FilePointer; /* File pointer */ - U32* FileFatChain; /* File fat chain array */ - U32 DriveNumber; + ULONG FileSize; /* File size */ + ULONG FilePointer; /* File pointer */ + ULONG* FileFatChain; /* File fat chain array */ + ULONG DriveNumber; } FAT_FILE_INFO, * PFAT_FILE_INFO; -BOOL FatOpenVolume(U32 DriveNumber, U32 VolumeStartSector, U32 PartitionSectorCount); -U32 FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, U32 PartitionSectorCount); -PVOID FatBufferDirectory(U32 DirectoryStartCluster, U32* EntryCountPointer, BOOL RootDirectory); -BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 EntryCount, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer); +BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG PartitionSectorCount); +ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCount); +PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG* EntryCountPointer, BOOL RootDirectory); +BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG EntryCount, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer); BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer); void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry); -BOOL FatGetFatEntry(U32 Cluster, U32* ClusterPointer); +BOOL FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer); FILE* FatOpenFile(PUCHAR FileName); -U32 FatCountClustersInChain(U32 StartCluster); -U32* FatGetClusterChainArray(U32 StartCluster); -BOOL FatReadCluster(U32 ClusterNumber, PVOID Buffer); -BOOL FatReadClusterChain(U32 StartClusterNumber, U32 NumberOfClusters, PVOID Buffer); -BOOL FatReadPartialCluster(U32 ClusterNumber, U32 StartingOffset, U32 Length, PVOID Buffer); -BOOL FatReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); -U32 FatGetFileSize(FILE *FileHandle); -VOID FatSetFilePointer(FILE *FileHandle, U32 NewFilePointer); -U32 FatGetFilePointer(FILE *FileHandle); -BOOL FatReadVolumeSectors(U32 DriveNumber, U32 SectorNumber, U32 SectorCount, PVOID Buffer); +ULONG FatCountClustersInChain(ULONG StartCluster); +ULONG* FatGetClusterChainArray(ULONG StartCluster); +BOOL FatReadCluster(ULONG ClusterNumber, PVOID Buffer); +BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer); +BOOL FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer); +BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer); +ULONG FatGetFileSize(FILE *FileHandle); +VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer); +ULONG FatGetFilePointer(FILE *FileHandle); +BOOL FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer); #define ATTR_NORMAL 0x00 diff --git a/reactos/boot/freeldr/freeldr/fs/fs.c b/reactos/boot/freeldr/freeldr/fs/fs.c index 22aa1e6b2b2..c91813f95d6 100644 --- a/reactos/boot/freeldr/freeldr/fs/fs.c +++ b/reactos/boot/freeldr/freeldr/fs/fs.c @@ -36,7 +36,7 @@ // DATA ///////////////////////////////////////////////////////////////////////////////////////////// -U32 FileSystemType = 0; // Type of filesystem on boot device, set by FsOpenVolume() +ULONG FsType = 0; // Type of filesystem on boot device, set by FsOpenVolume() ///////////////////////////////////////////////////////////////////////////////////////////// // FUNCTIONS @@ -51,7 +51,7 @@ VOID FileSystemError(PUCHAR ErrorString) /* * - * BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber); + * BOOL FsOpenVolume(ULONG DriveNumber, ULONG PartitionNumber); * * This function is called to open a disk volume for file access. * It must be called before any of the file functions will work. @@ -64,11 +64,11 @@ VOID FileSystemError(PUCHAR ErrorString) * If it is zero then it opens the active (bootable) partition * */ -BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber) +BOOL FsOpenVolume(ULONG DriveNumber, ULONG PartitionNumber) { PARTITION_TABLE_ENTRY PartitionTableEntry; UCHAR ErrorText[80]; - U8 VolumeType; + UCHAR VolumeType; DbgPrint((DPRINT_FILESYSTEM, "FsOpenVolume() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber)); @@ -78,7 +78,7 @@ BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber) { DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n")); - FileSystemType = FS_FAT; + FsType = FS_FAT; return FatOpenVolume(DriveNumber, 0, 0); } @@ -87,7 +87,7 @@ BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber) { DbgPrint((DPRINT_FILESYSTEM, "Drive is a cdrom drive. Assuming ISO-9660 file system.\n")); - FileSystemType = FS_ISO9660; + FsType = FS_ISO9660; return IsoOpenVolume(DriveNumber); } @@ -137,16 +137,16 @@ BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber) case PARTITION_XINT13: case PARTITION_FAT32: case PARTITION_FAT32_XINT13: - FileSystemType = FS_FAT; + FsType = FS_FAT; return FatOpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, PartitionTableEntry.PartitionSectorCount); case PARTITION_EXT2: - FileSystemType = FS_EXT2; + FsType = FS_EXT2; return Ext2OpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition); case PARTITION_NTFS: - FileSystemType = FS_NTFS; + FsType = FS_NTFS; return NtfsOpenVolume(DriveNumber, PartitionTableEntry.SectorCountBeforePartition); default: - FileSystemType = 0; + FsType = 0; sprintf(ErrorText, "Unsupported file system. Type: 0x%x", VolumeType); FileSystemError(ErrorText); return FALSE; @@ -175,7 +175,7 @@ PFILE FsOpenFile(PUCHAR FileName) // // Check file system type and pass off to appropriate handler // - switch (FileSystemType) + switch (FsType) { case FS_FAT: FileHandle = FatOpenFile(FileName); @@ -219,9 +219,9 @@ VOID FsCloseFile(PFILE FileHandle) * ReadFile() * returns number of bytes read or EOF */ -BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) +BOOL FsReadFile(PFILE FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) { - U64 BytesReadBig; + ULONGLONG BytesReadBig; BOOL Success; // @@ -232,7 +232,7 @@ BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) *BytesRead = 0; } - switch (FileSystemType) + switch (FsType) { case FS_FAT: @@ -246,7 +246,7 @@ BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) //return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer); Success = Ext2ReadFile(FileHandle, BytesToRead, &BytesReadBig, Buffer); - *BytesRead = (U32)BytesReadBig; + *BytesRead = (ULONG)BytesReadBig; return Success; case FS_NTFS: @@ -262,9 +262,9 @@ BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) return FALSE; } -U32 FsGetFileSize(PFILE FileHandle) +ULONG FsGetFileSize(PFILE FileHandle) { - switch (FileSystemType) + switch (FsType) { case FS_FAT: @@ -290,9 +290,9 @@ U32 FsGetFileSize(PFILE FileHandle) return 0; } -VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer) +VOID FsSetFilePointer(PFILE FileHandle, ULONG NewFilePointer) { - switch (FileSystemType) + switch (FsType) { case FS_FAT: @@ -320,9 +320,9 @@ VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer) } } -U32 FsGetFilePointer(PFILE FileHandle) +ULONG FsGetFilePointer(PFILE FileHandle) { - switch (FileSystemType) + switch (FsType) { case FS_FAT: @@ -369,10 +369,10 @@ BOOL FsIsEndOfFile(PFILE FileHandle) * This function parses a path in the form of dir1\dir2\file1.ext * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext) */ -U32 FsGetNumPathParts(PUCHAR Path) +ULONG FsGetNumPathParts(PUCHAR Path) { - U32 i; - U32 num; + ULONG i; + ULONG num; for (i=0,num=0; i<(int)strlen(Path); i++) { @@ -396,7 +396,7 @@ U32 FsGetNumPathParts(PUCHAR Path) */ VOID FsGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path) { - U32 i; + ULONG i; // Copy all the characters up to the end of the // string or until we hit a '\' character diff --git a/reactos/boot/freeldr/freeldr/fs/fsrec.c b/reactos/boot/freeldr/freeldr/fs/fsrec.c index b3c84062f9b..8c0a2e69e3c 100644 --- a/reactos/boot/freeldr/freeldr/fs/fsrec.c +++ b/reactos/boot/freeldr/freeldr/fs/fsrec.c @@ -39,10 +39,10 @@ /* * - * BOOL FsRecognizeVolume(U32 DriveNumber, U32 VolumeStartSector, U8* VolumeType); + * BOOL FsRecognizeVolume(ULONG DriveNumber, ULONG VolumeStartSector, UCHAR* VolumeType); * */ -BOOL FsRecognizeVolume(U32 DriveNumber, U32 VolumeStartSector, U8* VolumeType) +BOOL FsRecognizeVolume(ULONG DriveNumber, ULONG VolumeStartSector, UCHAR* VolumeType) { DbgPrint((DPRINT_FILESYSTEM, "FsRecognizeVolume() DriveNumber: 0x%x VolumeStartSector: %d\n", DriveNumber, VolumeStartSector)); @@ -66,7 +66,7 @@ BOOL FsRecognizeVolume(U32 DriveNumber, U32 VolumeStartSector, U8* VolumeType) return FALSE; } -BOOL FsRecIsIso9660(U32 DriveNumber) +BOOL FsRecIsIso9660(ULONG DriveNumber) { PUCHAR Sector = (PUCHAR)DISKREADBUFFER; @@ -84,7 +84,7 @@ BOOL FsRecIsIso9660(U32 DriveNumber) Sector[5] == '1'); } -BOOL FsRecIsExt2(U32 DriveNumber, U32 VolumeStartSector) +BOOL FsRecIsExt2(ULONG DriveNumber, ULONG VolumeStartSector) { PEXT2_SUPER_BLOCK SuperBlock = (PEXT2_SUPER_BLOCK)DISKREADBUFFER; @@ -102,7 +102,7 @@ BOOL FsRecIsExt2(U32 DriveNumber, U32 VolumeStartSector) return FALSE; } -BOOL FsRecIsFat(U32 DriveNumber, U32 VolumeStartSector) +BOOL FsRecIsFat(ULONG DriveNumber, ULONG VolumeStartSector) { PFAT_BOOTSECTOR BootSector = (PFAT_BOOTSECTOR)DISKREADBUFFER; PFAT32_BOOTSECTOR BootSector32 = (PFAT32_BOOTSECTOR)DISKREADBUFFER; @@ -124,7 +124,7 @@ BOOL FsRecIsFat(U32 DriveNumber, U32 VolumeStartSector) return FALSE; } -BOOL FsRecIsNtfs(U32 DriveNumber, U32 VolumeStartSector) +BOOL FsRecIsNtfs(ULONG DriveNumber, ULONG VolumeStartSector) { PNTFS_BOOTSECTOR BootSector = (PNTFS_BOOTSECTOR)DISKREADBUFFER; if (!MachDiskReadLogicalSectors(DriveNumber, VolumeStartSector, 1, BootSector)) diff --git a/reactos/boot/freeldr/freeldr/fs/fsrec.h b/reactos/boot/freeldr/freeldr/fs/fsrec.h index 210a4acebcf..2f8dd0bb5a5 100644 --- a/reactos/boot/freeldr/freeldr/fs/fsrec.h +++ b/reactos/boot/freeldr/freeldr/fs/fsrec.h @@ -20,10 +20,10 @@ #ifndef __FSREC_H #define __FSREC_H -BOOL FsRecognizeVolume(U32 DriveNumber, U32 VolumeStartSector, U8* VolumeType); -BOOL FsRecIsIso9660(U32 DriveNumber); -BOOL FsRecIsExt2(U32 DriveNumber, U32 VolumeStartSector); -BOOL FsRecIsFat(U32 DriveNumber, U32 VolumeStartSector); -BOOL FsRecIsNtfs(U32 DriveNumber, U32 VolumeStartSector); +BOOL FsRecognizeVolume(ULONG DriveNumber, ULONG VolumeStartSector, UCHAR* VolumeType); +BOOL FsRecIsIso9660(ULONG DriveNumber); +BOOL FsRecIsExt2(ULONG DriveNumber, ULONG VolumeStartSector); +BOOL FsRecIsFat(ULONG DriveNumber, ULONG VolumeStartSector); +BOOL FsRecIsNtfs(ULONG DriveNumber, ULONG VolumeStartSector); #endif // #defined __FSREC_H diff --git a/reactos/boot/freeldr/freeldr/fs/iso.c b/reactos/boot/freeldr/freeldr/fs/iso.c index 54e7aa38c88..58e881bff74 100644 --- a/reactos/boot/freeldr/freeldr/fs/iso.c +++ b/reactos/boot/freeldr/freeldr/fs/iso.c @@ -32,13 +32,13 @@ #define SECTORSIZE 2048 -static U32 IsoRootSector; // Starting sector of the root directory -static U32 IsoRootLength; // Length of the root directory +static ULONG IsoRootSector; // Starting sector of the root directory +static ULONG IsoRootLength; // Length of the root directory -U32 IsoDriveNumber = 0; +ULONG IsoDriveNumber = 0; -BOOL IsoOpenVolume(U32 DriveNumber) +BOOL IsoOpenVolume(ULONG DriveNumber) { PPVD Pvd = (PPVD)DISKREADBUFFER; @@ -65,11 +65,11 @@ BOOL IsoOpenVolume(U32 DriveNumber) } -static BOOL IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 DirectoryLength, PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer) +static BOOL IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectoryLength, PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer) { PDIR_RECORD Record; - U32 Offset; - U32 i; + ULONG Offset; + ULONG i; UCHAR Name[32]; DbgPrint((DPRINT_FILESYSTEM, "IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer, DirectoryLength, FileName)); @@ -133,12 +133,12 @@ static BOOL IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer, U32 Directory * if allocation or read fails. The directory is specified by its * starting sector and length. */ -static PVOID IsoBufferDirectory(U32 DirectoryStartSector, U32 DirectoryLength) +static PVOID IsoBufferDirectory(ULONG DirectoryStartSector, ULONG DirectoryLength) { PVOID DirectoryBuffer; PVOID Ptr; - U32 SectorCount; - U32 i; + ULONG SectorCount; + ULONG i; DbgPrint((DPRINT_FILESYSTEM, "IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector, DirectoryLength)); @@ -183,11 +183,11 @@ static PVOID IsoBufferDirectory(U32 DirectoryStartSector, U32 DirectoryLength) static BOOL IsoLookupFile(PUCHAR FileName, PISO_FILE_INFO IsoFileInfoPointer) { int i; - U32 NumberOfPathParts; + ULONG NumberOfPathParts; UCHAR PathPart[261]; PVOID DirectoryBuffer; - U32 DirectorySector; - U32 DirectoryLength; + ULONG DirectorySector; + ULONG DirectoryLength; ISO_FILE_INFO IsoFileInfo; DbgPrint((DPRINT_FILESYSTEM, "IsoLookupFile() FileName = %s\n", FileName)); @@ -293,14 +293,14 @@ FILE* IsoOpenFile(PUCHAR FileName) * Reads BytesToRead from open file and * returns the number of bytes read in BytesRead */ -BOOL IsoReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer) +BOOL IsoReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) { PISO_FILE_INFO IsoFileInfo = (PISO_FILE_INFO)FileHandle; - U32 SectorNumber; - U32 OffsetInSector; - U32 LengthInSector; - U32 NumberOfSectors; - U32 i; + ULONG SectorNumber; + ULONG OffsetInSector; + ULONG LengthInSector; + ULONG NumberOfSectors; + ULONG i; DbgPrint((DPRINT_FILESYSTEM, "IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer)); @@ -451,7 +451,7 @@ BOOL IsoReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer } -U32 IsoGetFileSize(FILE *FileHandle) +ULONG IsoGetFileSize(FILE *FileHandle) { PISO_FILE_INFO IsoFileHandle = (PISO_FILE_INFO)FileHandle; @@ -460,7 +460,7 @@ U32 IsoGetFileSize(FILE *FileHandle) return IsoFileHandle->FileSize; } -VOID IsoSetFilePointer(FILE *FileHandle, U32 NewFilePointer) +VOID IsoSetFilePointer(FILE *FileHandle, ULONG NewFilePointer) { PISO_FILE_INFO IsoFileHandle = (PISO_FILE_INFO)FileHandle; @@ -469,7 +469,7 @@ VOID IsoSetFilePointer(FILE *FileHandle, U32 NewFilePointer) IsoFileHandle->FilePointer = NewFilePointer; } -U32 IsoGetFilePointer(FILE *FileHandle) +ULONG IsoGetFilePointer(FILE *FileHandle) { PISO_FILE_INFO IsoFileHandle = (PISO_FILE_INFO)FileHandle; diff --git a/reactos/boot/freeldr/freeldr/fs/iso.h b/reactos/boot/freeldr/freeldr/fs/iso.h index feaa1b57896..db549a40b37 100644 --- a/reactos/boot/freeldr/freeldr/fs/iso.h +++ b/reactos/boot/freeldr/freeldr/fs/iso.h @@ -25,10 +25,10 @@ struct _DIR_RECORD { UCHAR RecordLength; // 1 UCHAR ExtAttrRecordLength; // 2 - U32 ExtentLocationL; // 3-6 - U32 ExtentLocationM; // 7-10 - U32 DataLengthL; // 11-14 - U32 DataLengthM; // 15-18 + ULONG ExtentLocationL; // 3-6 + ULONG ExtentLocationM; // 7-10 + ULONG DataLengthL; // 11-14 + ULONG DataLengthM; // 15-18 UCHAR Year; // 19 UCHAR Month; // 20 UCHAR Day; // 21 @@ -39,7 +39,7 @@ struct _DIR_RECORD UCHAR FileFlags; // 26 UCHAR FileUnitSize; // 27 UCHAR InterleaveGapSize; // 28 - U32 VolumeSequenceNumber; // 29-32 + ULONG VolumeSequenceNumber; // 29-32 UCHAR FileIdLength; // 33 UCHAR FileId[1]; // 34 } __attribute__((packed)); @@ -71,18 +71,18 @@ struct _PVD UCHAR SystemId[32]; // 9-40 UCHAR VolumeId[32]; // 41-72 UCHAR unused1[8]; // 73-80 - U32 VolumeSpaceSizeL; // 81-84 - U32 VolumeSpaceSizeM; // 85-88 + ULONG VolumeSpaceSizeL; // 81-84 + ULONG VolumeSpaceSizeM; // 85-88 UCHAR unused2[32]; // 89-120 - U32 VolumeSetSize; // 121-124 - U32 VolumeSequenceNumber; // 125-128 - U32 LogicalBlockSize; // 129-132 - U32 PathTableSizeL; // 133-136 - U32 PathTableSizeM; // 137-140 - U32 LPathTablePos; // 141-144 - U32 LOptPathTablePos; // 145-148 - U32 MPathTablePos; // 149-152 - U32 MOptPathTablePos; // 153-156 + ULONG VolumeSetSize; // 121-124 + ULONG VolumeSequenceNumber; // 125-128 + ULONG LogicalBlockSize; // 129-132 + ULONG PathTableSizeL; // 133-136 + ULONG PathTableSizeM; // 137-140 + ULONG LPathTablePos; // 141-144 + ULONG LOptPathTablePos; // 145-148 + ULONG MPathTablePos; // 149-152 + ULONG MOptPathTablePos; // 153-156 DIR_RECORD RootDirRecord; // 157-190 UCHAR VolumeSetIdentifier[128]; // 191-318 UCHAR PublisherIdentifier[128]; // 319-446 @@ -97,19 +97,19 @@ typedef struct _PVD PVD, *PPVD; typedef struct { - U32 FileStart; // File start sector - U32 FileSize; // File size - U32 FilePointer; // File pointer + ULONG FileStart; // File start sector + ULONG FileSize; // File size + ULONG FilePointer; // File pointer BOOL Directory; - U32 DriveNumber; + ULONG DriveNumber; } ISO_FILE_INFO, * PISO_FILE_INFO; -BOOL IsoOpenVolume(U32 DriveNumber); +BOOL IsoOpenVolume(ULONG DriveNumber); FILE* IsoOpenFile(PUCHAR FileName); -BOOL IsoReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); -U32 IsoGetFileSize(FILE *FileHandle); -VOID IsoSetFilePointer(FILE *FileHandle, U32 NewFilePointer); -U32 IsoGetFilePointer(FILE *FileHandle); +BOOL IsoReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer); +ULONG IsoGetFileSize(FILE *FileHandle); +VOID IsoSetFilePointer(FILE *FileHandle, ULONG NewFilePointer); +ULONG IsoGetFilePointer(FILE *FileHandle); #endif // #defined __FAT_H diff --git a/reactos/boot/freeldr/freeldr/fs/ntfs.c b/reactos/boot/freeldr/freeldr/fs/ntfs.c index 6f6aebf86c9..625020a549f 100644 --- a/reactos/boot/freeldr/freeldr/fs/ntfs.c +++ b/reactos/boot/freeldr/freeldr/fs/ntfs.c @@ -37,19 +37,19 @@ #include "ntfs.h" PNTFS_BOOTSECTOR NtfsBootSector; -U32 NtfsClusterSize; -U32 NtfsMftRecordSize; -U32 NtfsIndexRecordSize; -U32 NtfsDriveNumber; -U32 NtfsSectorOfClusterZero; +ULONG NtfsClusterSize; +ULONG NtfsMftRecordSize; +ULONG NtfsIndexRecordSize; +ULONG NtfsDriveNumber; +ULONG NtfsSectorOfClusterZero; PNTFS_MFT_RECORD NtfsMasterFileTable; NTFS_ATTR_CONTEXT NtfsMFTContext; -PUCHAR NtfsDecodeRun(PUCHAR DataRun, S64 *DataRunOffset, U64 *DataRunLength) +PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength) { - U8 DataRunOffsetSize; - U8 DataRunLengthSize; - S8 i; + UCHAR DataRunOffsetSize; + UCHAR DataRunLengthSize; + CHAR i; DataRunOffsetSize = (*DataRun >> 4) & 0xF; DataRunLengthSize = *DataRun & 0xF; @@ -75,7 +75,7 @@ PUCHAR NtfsDecodeRun(PUCHAR DataRun, S64 *DataRunOffset, U64 *DataRunLength) DataRun++; } /* The last byte contains sign so we must process it different way. */ - *DataRunOffset = ((S8)(*(DataRun++)) << (i << 3)) + *DataRunOffset; + *DataRunOffset = ((CHAR)(*(DataRun++)) << (i << 3)) + *DataRunOffset; } DbgPrint((DPRINT_FILESYSTEM, "DataRunOffsetSize: %x\n", DataRunOffsetSize)); @@ -87,11 +87,11 @@ PUCHAR NtfsDecodeRun(PUCHAR DataRun, S64 *DataRunOffset, U64 *DataRunLength) } /* FIXME: Add support for attribute lists! */ -BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, U32 Type, PWCHAR Name) +BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, ULONG Type, PWCHAR Name) { PNTFS_ATTR_RECORD AttrRecord; PNTFS_ATTR_RECORD AttrRecordEnd; - U32 NameLength; + ULONG NameLength; PWCHAR AttrName; AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset); @@ -115,8 +115,8 @@ BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, U Context->Record = AttrRecord; if (AttrRecord->IsNonResident) { - S64 DataRunOffset; - U64 DataRunLength; + LONGLONG DataRunOffset; + ULONGLONG DataRunLength; Context->CacheRun = (PUCHAR)Context->Record + Context->Record->NonResident.MappingPairsOffset; Context->CacheRunOffset = 0; @@ -148,9 +148,9 @@ BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, U } /* FIXME: Optimize for multisector reads. */ -BOOL NtfsDiskRead(U64 Offset, U64 Length, PCHAR Buffer) +BOOL NtfsDiskRead(ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer) { - U16 ReadLength; + USHORT ReadLength; DbgPrint((DPRINT_FILESYSTEM, "NtfsDiskRead - Offset: %I64d Length: %I64d\n", Offset, Length)); RtlZeroMemory((PCHAR)DISKREADBUFFER, 0x1000); @@ -190,16 +190,16 @@ BOOL NtfsDiskRead(U64 Offset, U64 Length, PCHAR Buffer) return TRUE; } -U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64 Length) +ULONGLONG NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONGLONG Length) { - U64 LastLCN; + ULONGLONG LastLCN; PUCHAR DataRun; - S64 DataRunOffset; - U64 DataRunLength; - S64 DataRunStartLCN; - U64 CurrentOffset; - U64 ReadLength; - U64 AlreadyRead; + LONGLONG DataRunOffset; + ULONGLONG DataRunLength; + LONGLONG DataRunStartLCN; + ULONGLONG CurrentOffset; + ULONGLONG ReadLength; + ULONGLONG AlreadyRead; if (!Context->Record->IsNonResident) { @@ -316,31 +316,31 @@ U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64 BOOL NtfsFixupRecord(PNTFS_RECORD Record) { - U16 *USA; - U16 USANumber; - U16 USACount; - U16 *Block; + USHORT *USA; + USHORT USANumber; + USHORT USACount; + USHORT *Block; - USA = (U16*)((PCHAR)Record + Record->USAOffset); + USA = (USHORT*)((PCHAR)Record + Record->USAOffset); USANumber = *(USA++); USACount = Record->USACount - 1; /* Exclude the USA Number. */ - Block = (U16*)((PCHAR)Record + NtfsBootSector->BytesPerSector - 2); + Block = (USHORT*)((PCHAR)Record + NtfsBootSector->BytesPerSector - 2); while (USACount) { if (*Block != USANumber) return FALSE; *Block = *(USA++); - Block = (U16*)((PCHAR)Block + NtfsBootSector->BytesPerSector); + Block = (USHORT*)((PCHAR)Block + NtfsBootSector->BytesPerSector); USACount--; } return TRUE; } -BOOL NtfsReadMftRecord(U32 MFTIndex, PNTFS_MFT_RECORD Buffer) +BOOL NtfsReadMftRecord(ULONG MFTIndex, PNTFS_MFT_RECORD Buffer) { - U64 BytesRead; + ULONGLONG BytesRead; BytesRead = NtfsReadAttribute(&NtfsMFTContext, MFTIndex * NtfsMftRecordSize, (PCHAR)Buffer, NtfsMftRecordSize); if (BytesRead != NtfsMftRecordSize) @@ -354,9 +354,9 @@ BOOL NtfsReadMftRecord(U32 MFTIndex, PNTFS_MFT_RECORD Buffer) VOID NtfsPrintFile(PNTFS_INDEX_ENTRY IndexEntry) { PWCHAR FileName; - U8 FileNameLength; + UCHAR FileNameLength; CHAR AnsiFileName[256]; - U8 i; + UCHAR i; FileName = IndexEntry->FileName.FileName; FileNameLength = IndexEntry->FileName.FileNameLength; @@ -372,8 +372,8 @@ VOID NtfsPrintFile(PNTFS_INDEX_ENTRY IndexEntry) BOOL NtfsCompareFileName(PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry) { PWCHAR EntryFileName; - U8 EntryFileNameLength; - U8 i; + UCHAR EntryFileNameLength; + UCHAR i; EntryFileName = IndexEntry->FileName.FileName; EntryFileNameLength = IndexEntry->FileName.FileNameLength; @@ -402,21 +402,21 @@ BOOL NtfsCompareFileName(PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry) return TRUE; } -BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex) +BOOL NtfsFindMftRecord(ULONG MFTIndex, PCHAR FileName, ULONG *OutMFTIndex) { PNTFS_MFT_RECORD MftRecord; - U32 Magic; + ULONG Magic; NTFS_ATTR_CONTEXT IndexRootCtx; NTFS_ATTR_CONTEXT IndexBitmapCtx; NTFS_ATTR_CONTEXT IndexAllocationCtx; PNTFS_INDEX_ROOT IndexRoot; - U64 BitmapDataSize; - U64 IndexAllocationSize; + ULONGLONG BitmapDataSize; + ULONGLONG IndexAllocationSize; PCHAR BitmapData; PCHAR IndexRecord; PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd; - U32 RecordOffset; - U32 IndexBlockSize; + ULONG RecordOffset; + ULONG IndexBlockSize; MftRecord = MmAllocateMemory(NtfsMftRecordSize); if (MftRecord == NULL) @@ -508,8 +508,8 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex) DbgPrint((DPRINT_FILESYSTEM, "RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize)); for (; RecordOffset < IndexAllocationSize;) { - U8 Bit = 1 << ((RecordOffset / IndexBlockSize) & 7); - U32 Byte = (RecordOffset / IndexBlockSize) >> 3; + UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7); + ULONG Byte = (RecordOffset / IndexBlockSize) >> 3; if ((BitmapData[Byte] & Bit)) break; RecordOffset += IndexBlockSize; @@ -528,7 +528,7 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex) } /* FIXME */ - IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(U16 *)(IndexRecord + 0x18)); + IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18)); IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize); while (IndexEntry < IndexEntryEnd && @@ -565,10 +565,10 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex) BOOL NtfsLookupFile(PUCHAR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT DataContext) { - U32 NumberOfPathParts; + ULONG NumberOfPathParts; UCHAR PathPart[261]; - U32 CurrentMFTIndex; - U8 i; + ULONG CurrentMFTIndex; + UCHAR i; DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile() FileName = %s\n", FileName)); @@ -606,7 +606,7 @@ BOOL NtfsLookupFile(PUCHAR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONT return TRUE; } -BOOL NtfsOpenVolume(U32 DriveNumber, U32 VolumeStartSector) +BOOL NtfsOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector) { NtfsBootSector = (PNTFS_BOOTSECTOR)DISKREADBUFFER; @@ -703,36 +703,36 @@ FILE* NtfsOpenFile(PUCHAR FileName) return (FILE*)FileHandle; } -BOOL NtfsReadFile(FILE *File, U32 BytesToRead, U32* BytesRead, PVOID Buffer) +BOOL NtfsReadFile(FILE *File, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) { PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File; - U64 BytesRead64; + ULONGLONG BytesRead64; BytesRead64 = NtfsReadAttribute(&FileHandle->DataContext, FileHandle->Offset, Buffer, BytesToRead); if (BytesRead64) { - *BytesRead = (U32)BytesRead64; + *BytesRead = (ULONG)BytesRead64; FileHandle->Offset += BytesRead64; return TRUE; } return FALSE; } -U32 NtfsGetFileSize(FILE *File) +ULONG NtfsGetFileSize(FILE *File) { PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File; if (FileHandle->DataContext.Record->IsNonResident) - return (U32)FileHandle->DataContext.Record->NonResident.DataSize; + return (ULONG)FileHandle->DataContext.Record->NonResident.DataSize; else - return (U32)FileHandle->DataContext.Record->Resident.ValueLength; + return (ULONG)FileHandle->DataContext.Record->Resident.ValueLength; } -VOID NtfsSetFilePointer(FILE *File, U32 NewFilePointer) +VOID NtfsSetFilePointer(FILE *File, ULONG NewFilePointer) { PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File; FileHandle->Offset = NewFilePointer; } -U32 NtfsGetFilePointer(FILE *File) +ULONG NtfsGetFilePointer(FILE *File) { PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File; return FileHandle->Offset; diff --git a/reactos/boot/freeldr/freeldr/fs/ntfs.h b/reactos/boot/freeldr/freeldr/fs/ntfs.h index af51534d365..5c99fb9c638 100644 --- a/reactos/boot/freeldr/freeldr/fs/ntfs.h +++ b/reactos/boot/freeldr/freeldr/fs/ntfs.h @@ -61,122 +61,122 @@ typedef struct { - U8 JumpBoot[3]; // Jump to the boot loader routine - U8 SystemId[8]; // System Id ("NTFS ") - U16 BytesPerSector; // Bytes per sector - U8 SectorsPerCluster; // Number of sectors in a cluster - U8 Unused1[7]; - U8 MediaDescriptor; // Media descriptor byte - U8 Unused2[2]; - U16 SectorsPerTrack; // Number of sectors in a track - U16 NumberOfHeads; // Number of heads on the disk - U8 Unused3[8]; - U8 DriveNumber; // Int 0x13 drive number (e.g. 0x80) - U8 CurrentHead; - U8 BootSignature; // Extended boot signature (0x80) - U8 Unused4; - U64 VolumeSectorCount; // Number of sectors in the volume - U64 MftLocation; - U64 MftMirrorLocation; - S8 ClustersPerMftRecord; // Clusters per MFT Record - U8 Unused5[3]; - S8 ClustersPerIndexRecord; // Clusters per Index Record - U8 Unused6[3]; - U64 VolumeSerialNumber; // Volume serial number - U8 BootCodeAndData[430]; // The remainder of the boot sector - U16 BootSectorMagic; // 0xAA55 + UCHAR JumpBoot[3]; // Jump to the boot loader routine + UCHAR SystemId[8]; // System Id ("NTFS ") + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + UCHAR Unused1[7]; + UCHAR MediaDescriptor; // Media descriptor byte + UCHAR Unused2[2]; + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + UCHAR Unused3[8]; + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR CurrentHead; + UCHAR BootSignature; // Extended boot signature (0x80) + UCHAR Unused4; + ULONGLONG VolumeSectorCount; // Number of sectors in the volume + ULONGLONG MftLocation; + ULONGLONG MftMirrorLocation; + CHAR ClustersPerMftRecord; // Clusters per MFT Record + UCHAR Unused5[3]; + CHAR ClustersPerIndexRecord; // Clusters per Index Record + UCHAR Unused6[3]; + ULONGLONG VolumeSerialNumber; // Volume serial number + UCHAR BootCodeAndData[430]; // The remainder of the boot sector + USHORT BootSectorMagic; // 0xAA55 } PACKED NTFS_BOOTSECTOR, *PNTFS_BOOTSECTOR; typedef struct { - U32 Magic; - U16 USAOffset; // Offset to the Update Sequence Array from the start of the ntfs record - U16 USACount; + ULONG Magic; + USHORT USAOffset; // Offset to the Update Sequence Array from the start of the ntfs record + USHORT USACount; } PACKED NTFS_RECORD, *PNTFS_RECORD; typedef struct { - U32 Magic; - U16 USAOffset; // Offset to the Update Sequence Array from the start of the ntfs record - U16 USACount; - U64 LogSequenceNumber; - U16 SequenceNumber; - U16 LinkCount; - U16 AttributesOffset; - U16 Flags; - U32 BytesInUse; // Number of bytes used in this mft record. - U32 BytesAllocated; - U64 BaseMFTRecord; - U16 NextAttributeInstance; + ULONG Magic; + USHORT USAOffset; // Offset to the Update Sequence Array from the start of the ntfs record + USHORT USACount; + ULONGLONG LogSequenceNumber; + USHORT SequenceNumber; + USHORT LinkCount; + USHORT AttributesOffset; + USHORT Flags; + ULONG BytesInUse; // Number of bytes used in this mft record. + ULONG BytesAllocated; + ULONGLONG BaseMFTRecord; + USHORT NextAttributeInstance; } PACKED NTFS_MFT_RECORD, *PNTFS_MFT_RECORD; typedef struct { - U32 Type; - U32 Length; - U8 IsNonResident; - U8 NameLength; - U16 NameOffset; - U16 Flags; - U16 Instance; + ULONG Type; + ULONG Length; + UCHAR IsNonResident; + UCHAR NameLength; + USHORT NameOffset; + USHORT Flags; + USHORT Instance; union { // Resident attributes struct { - U32 ValueLength; - U16 ValueOffset; - U16 Flags; + ULONG ValueLength; + USHORT ValueOffset; + USHORT Flags; } PACKED Resident; // Non-resident attributes struct { - U64 LowestVCN; - U64 HighestVCN; - U16 MappingPairsOffset; - U8 CompressionUnit; - U8 Reserved[5]; - S64 AllocatedSize; - S64 DataSize; - S64 InitializedSize; - S64 CompressedSize; + ULONGLONG LowestVCN; + ULONGLONG HighestVCN; + USHORT MappingPairsOffset; + UCHAR CompressionUnit; + UCHAR Reserved[5]; + LONGLONG AllocatedSize; + LONGLONG DataSize; + LONGLONG InitializedSize; + LONGLONG CompressedSize; } PACKED NonResident; } PACKED; } PACKED NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD; typedef struct { - U32 EntriesOffset; - U32 IndexLength; - U32 AllocatedSize; - U8 Flags; - U8 Reserved[3]; + ULONG EntriesOffset; + ULONG IndexLength; + ULONG AllocatedSize; + UCHAR Flags; + UCHAR Reserved[3]; } PACKED NTFS_INDEX_HEADER, *PNTFS_INDEX_HEADER; typedef struct { - U32 Type; - U32 CollationRule; - U32 IndexBlockSize; - U8 ClustersPerIndexBlock; - U8 Reserved[3]; + ULONG Type; + ULONG CollationRule; + ULONG IndexBlockSize; + UCHAR ClustersPerIndexBlock; + UCHAR Reserved[3]; NTFS_INDEX_HEADER IndexHeader; } PACKED NTFS_INDEX_ROOT, *PNTFS_INDEX_ROOT; typedef struct { - U64 ParentDirectory; - S64 CreationTime; - S64 LastDataChangeTime; - S64 LastMftChangeTime; - S64 LastAccessTime; - S64 AllocatedSize; - S64 DataSize; - U32 FileAttributes; - U16 PackedExtendedAttributeSize; - U16 Reserved; - U8 FileNameLength; - U8 FileNameType; + ULONGLONG ParentDirectory; + LONGLONG CreationTime; + LONGLONG LastDataChangeTime; + LONGLONG LastMftChangeTime; + LONGLONG LastAccessTime; + LONGLONG AllocatedSize; + LONGLONG DataSize; + ULONG FileAttributes; + USHORT PackedExtendedAttributeSize; + USHORT Reserved; + UCHAR FileNameLength; + UCHAR FileNameType; WCHAR FileName[0]; } PACKED NTFS_FILE_NAME_ATTR, *PNTFS_FILE_NAME_ATTR; @@ -185,19 +185,19 @@ typedef struct { { struct { - U64 IndexedFile; + ULONGLONG IndexedFile; } PACKED Directory; struct { - U16 DataOffset; - U16 DataLength; - U32 Reserved; + USHORT DataOffset; + USHORT DataLength; + ULONG Reserved; } PACKED ViewIndex; } PACKED Data; - U16 Length; - U16 KeyLength; - U16 Flags; - U16 Reserved; + USHORT Length; + USHORT KeyLength; + USHORT Flags; + USHORT Reserved; NTFS_FILE_NAME_ATTR FileName; } PACKED NTFS_INDEX_ENTRY, *PNTFS_INDEX_ENTRY; @@ -205,24 +205,24 @@ typedef struct { PNTFS_ATTR_RECORD Record; PUCHAR CacheRun; - U64 CacheRunOffset; - S64 CacheRunStartLCN; - U64 CacheRunLength; - S64 CacheRunLastLCN; - U64 CacheRunCurrentOffset; + ULONGLONG CacheRunOffset; + LONGLONG CacheRunStartLCN; + ULONGLONG CacheRunLength; + LONGLONG CacheRunLastLCN; + ULONGLONG CacheRunCurrentOffset; } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT; typedef struct { NTFS_ATTR_CONTEXT DataContext; - U64 Offset; + ULONGLONG Offset; } PACKED NTFS_FILE_HANDLE, *PNTFS_FILE_HANDLE; -BOOL NtfsOpenVolume(U32 DriveNumber, U32 VolumeStartSector); +BOOL NtfsOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector); FILE* NtfsOpenFile(PUCHAR FileName); -BOOL NtfsReadFile(FILE *FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); -U32 NtfsGetFileSize(FILE *FileHandle); -VOID NtfsSetFilePointer(FILE *FileHandle, U32 NewFilePointer); -U32 NtfsGetFilePointer(FILE *FileHandle); +BOOL NtfsReadFile(FILE *FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer); +ULONG NtfsGetFileSize(FILE *FileHandle); +VOID NtfsSetFilePointer(FILE *FileHandle, ULONG NewFilePointer); +ULONG NtfsGetFilePointer(FILE *FileHandle); #endif // #defined __NTFS_H diff --git a/reactos/boot/freeldr/freeldr/include/bootmgr.h b/reactos/boot/freeldr/freeldr/include/bootmgr.h index 330010d2523..9d61a176eeb 100644 --- a/reactos/boot/freeldr/freeldr/include/bootmgr.h +++ b/reactos/boot/freeldr/freeldr/include/bootmgr.h @@ -21,9 +21,9 @@ #define __BOOTMGR_H -U32 GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], U32 OperatingSystemCount); -S32 GetTimeOut(VOID); -BOOL MainBootMenuKeyPressFilter(U32 KeyPress); +ULONG GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount); +LONG GetTimeOut(VOID); +BOOL MainBootMenuKeyPressFilter(ULONG KeyPress); #endif // #defined __BOOTMGR_H diff --git a/reactos/boot/freeldr/freeldr/include/cache.h b/reactos/boot/freeldr/freeldr/include/cache.h index c9b07c759f9..f1f7529f2e7 100644 --- a/reactos/boot/freeldr/freeldr/include/cache.h +++ b/reactos/boot/freeldr/freeldr/include/cache.h @@ -21,10 +21,10 @@ #ifndef __CACHE_H #define __CACHE_H -BOOL CacheInitializeDrive(U32 DriveNumber); +BOOL CacheInitializeDrive(ULONG DriveNumber); VOID CacheInvalidateCacheData(VOID); -BOOL CacheReadDiskSectors(U32 DiskNumber, U32 StartSector, U32 SectorCount, PVOID Buffer); -BOOL CacheForceDiskSectorsIntoCache(U32 DiskNumber, U32 StartSector, U32 SectorCount); -BOOL CacheReleaseMemory(U32 MinimumAmountToRelease); +BOOL CacheReadDiskSectors(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount, PVOID Buffer); +BOOL CacheForceDiskSectorsIntoCache(ULONG DiskNumber, ULONG StartSector, ULONG SectorCount); +BOOL CacheReleaseMemory(ULONG MinimumAmountToRelease); #endif // defined __CACHE_H diff --git a/reactos/boot/freeldr/freeldr/include/cmdline.h b/reactos/boot/freeldr/freeldr/include/cmdline.h index ddb11fccae4..5bfc3ff84bf 100644 --- a/reactos/boot/freeldr/freeldr/include/cmdline.h +++ b/reactos/boot/freeldr/freeldr/include/cmdline.h @@ -24,13 +24,13 @@ typedef struct tagCMDLINEINFO { char *DefaultOperatingSystem; - S32 TimeOut; + LONG TimeOut; } CMDLINEINFO, *PCMDLINEINFO; extern void CmdLineParse(char *CmdLine); extern char *CmdLineGetDefaultOS(void); -extern S32 CmdLineGetTimeOut(void); +extern LONG CmdLineGetTimeOut(void); #endif /* __CMDLINE_H__ */ diff --git a/reactos/boot/freeldr/freeldr/include/comm.h b/reactos/boot/freeldr/freeldr/include/comm.h index 84fa9a6b98a..bef0d583ab8 100644 --- a/reactos/boot/freeldr/freeldr/include/comm.h +++ b/reactos/boot/freeldr/freeldr/include/comm.h @@ -22,7 +22,7 @@ #ifndef __RS232_H #define __RS232_H -BOOL Rs232PortInitialize(U32 ComPort, U32 BaudRate); +BOOL Rs232PortInitialize(ULONG ComPort, ULONG BaudRate); BOOL Rs232PortGetByte(PUCHAR ByteRecieved); BOOL Rs232PortPollByte(PUCHAR ByteRecieved); VOID Rs232PortPutByte(UCHAR ByteToSend); diff --git a/reactos/boot/freeldr/freeldr/include/debug.h b/reactos/boot/freeldr/freeldr/include/debug.h index 9098dbd7857..d489199d964 100644 --- a/reactos/boot/freeldr/freeldr/include/debug.h +++ b/reactos/boot/freeldr/freeldr/include/debug.h @@ -37,9 +37,9 @@ #define DPRINT_HWDETECT 0x00000400 // OR this with DebugPrintMask to enable hardware detection messages VOID DebugInit(VOID); - VOID DebugPrint(U32 Mask, char *format, ...); + VOID DebugPrint(ULONG Mask, char *format, ...); VOID DebugPrint1(char *format, ...); - VOID DebugDumpBuffer(U32 Mask, PVOID Buffer, U32 Length); + VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length); #define DbgPrint(_x_) DebugPrint _x_ ; #define DPRINT1 DebugPrint1 diff --git a/reactos/boot/freeldr/freeldr/include/disk.h b/reactos/boot/freeldr/freeldr/include/disk.h index bc4451b29c0..dc5abcb4f73 100644 --- a/reactos/boot/freeldr/freeldr/include/disk.h +++ b/reactos/boot/freeldr/freeldr/include/disk.h @@ -23,10 +23,10 @@ typedef struct _GEOMETRY { - U32 Cylinders; // Number of cylinders on the disk - U32 Heads; // Number of heads on the disk - U32 Sectors; // Number of sectors per track - U32 BytesPerSector; // Number of bytes per sector + ULONG Cylinders; // Number of cylinders on the disk + ULONG Heads; // Number of heads on the disk + ULONG Sectors; // Number of sectors per track + ULONG BytesPerSector; // Number of bytes per sector } GEOMETRY, *PGEOMETRY; @@ -35,14 +35,14 @@ typedef struct _GEOMETRY // typedef struct _EXTENDED_GEOMETRY { - U16 Size; - U16 Flags; - U32 Cylinders; - U32 Heads; - U32 SectorsPerTrack; - U64 Sectors; - U16 BytesPerSector; - U32 PDPTE; + USHORT Size; + USHORT Flags; + ULONG Cylinders; + ULONG Heads; + ULONG SectorsPerTrack; + ULONGLONG Sectors; + USHORT BytesPerSector; + ULONG PDPTE; } __attribute__((packed)) EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY; // @@ -50,16 +50,16 @@ typedef struct _EXTENDED_GEOMETRY // typedef struct _PARTITION_TABLE_ENTRY { - U8 BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only) - U8 StartHead; // Beginning head number - U8 StartSector; // Beginning sector (2 high bits of cylinder #) - U8 StartCylinder; // Beginning cylinder# (low order bits of cylinder #) - U8 SystemIndicator; // System indicator - U8 EndHead; // Ending head number - U8 EndSector; // Ending sector (2 high bits of cylinder #) - U8 EndCylinder; // Ending cylinder# (low order bits of cylinder #) - U32 SectorCountBeforePartition; // Number of sectors preceding the partition - U32 PartitionSectorCount; // Number of sectors in the partition + UCHAR BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only) + UCHAR StartHead; // Beginning head number + UCHAR StartSector; // Beginning sector (2 high bits of cylinder #) + UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #) + UCHAR SystemIndicator; // System indicator + UCHAR EndHead; // Ending head number + UCHAR EndSector; // Ending sector (2 high bits of cylinder #) + UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #) + ULONG SectorCountBeforePartition; // Number of sectors preceding the partition + ULONG PartitionSectorCount; // Number of sectors in the partition } PACKED PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY; @@ -68,11 +68,11 @@ typedef struct _PARTITION_TABLE_ENTRY // typedef struct _MASTER_BOOT_RECORD { - U8 MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */ - U32 Signature; /* 0x1B8 */ - U16 Reserved; /* 0x1BC */ + UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */ + ULONG Signature; /* 0x1B8 */ + USHORT Reserved; /* 0x1BC */ PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */ - U16 MasterBootRecordMagic; /* 0x1FE */ + USHORT MasterBootRecordMagic; /* 0x1FE */ } PACKED MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD; @@ -106,10 +106,10 @@ typedef struct _MASTER_BOOT_RECORD /////////////////////////////////////////////////////////////////////////////////////// #ifdef __i386__ -BOOL DiskResetController(U32 DriveNumber); -BOOL DiskInt13ExtensionsSupported(U32 DriveNumber); +BOOL DiskResetController(ULONG DriveNumber); +BOOL DiskInt13ExtensionsSupported(ULONG DriveNumber); //VOID DiskStopFloppyMotor(VOID); -BOOL DiskGetExtendedDriveParameters(U32 DriveNumber, PVOID Buffer, U16 BufferSize); +BOOL DiskGetExtendedDriveParameters(ULONG DriveNumber, PVOID Buffer, USHORT BufferSize); #endif // defined __i386__ @@ -119,10 +119,10 @@ BOOL DiskGetExtendedDriveParameters(U32 DriveNumber, PVOID Buffer, U16 BufferSiz // /////////////////////////////////////////////////////////////////////////////////////// VOID DiskReportError (BOOL bError); -VOID DiskError(PUCHAR ErrorString, U32 ErrorCode); -PUCHAR DiskGetErrorCodeString(U32 ErrorCode); -BOOL DiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); // Implemented in i386disk.c -BOOL DiskIsDriveRemovable(U32 DriveNumber); +VOID DiskError(PUCHAR ErrorString, ULONG ErrorCode); +PUCHAR DiskGetErrorCodeString(ULONG ErrorCode); +BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); // Implemented in i386disk.c +BOOL DiskIsDriveRemovable(ULONG DriveNumber); VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c /////////////////////////////////////////////////////////////////////////////////////// @@ -130,10 +130,10 @@ VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c // Fixed Disk Partition Management Functions // /////////////////////////////////////////////////////////////////////////////////////// -BOOL DiskGetActivePartitionEntry(U32 DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); -BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); +BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); +BOOL DiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOL DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOL DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); -BOOL DiskReadBootRecord(U32 DriveNumber, U64 LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); +BOOL DiskReadBootRecord(ULONG DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); #endif // defined __DISK_H diff --git a/reactos/boot/freeldr/freeldr/include/drivemap.h b/reactos/boot/freeldr/freeldr/include/drivemap.h index af4b1c91c87..2aeaf662089 100644 --- a/reactos/boot/freeldr/freeldr/include/drivemap.h +++ b/reactos/boot/freeldr/freeldr/include/drivemap.h @@ -23,21 +23,21 @@ typedef struct { - U8 DriveMapCount; // Count of drives currently mapped + UCHAR DriveMapCount; // Count of drives currently mapped - U8 DriveMap[8]; // Map of BIOS drives + UCHAR DriveMap[8]; // Map of BIOS drives } PACKED DRIVE_MAP_LIST, *PDRIVE_MAP_LIST; VOID DriveMapMapDrivesInSection(PUCHAR SectionName); BOOL DriveMapIsValidDriveString(PUCHAR DriveString); // Checks the drive string ("hd0") for validity -U32 DriveMapGetBiosDriveNumber(PUCHAR DeviceName); // Returns a BIOS drive number for any given device name (e.g. 0x80 for 'hd0') +ULONG DriveMapGetBiosDriveNumber(PUCHAR DeviceName); // Returns a BIOS drive number for any given device name (e.g. 0x80 for 'hd0') VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap); // Installs the int 13h handler for the drive mapper VOID DriveMapRemoveInt13Handler(VOID); // Removes a previously installed int 13h drive map handler extern PVOID DriveMapInt13HandlerStart; extern PVOID DriveMapInt13HandlerEnd; -extern U32 DriveMapOldInt13HandlerAddress; +extern ULONG DriveMapOldInt13HandlerAddress; extern DRIVE_MAP_LIST DriveMapInt13HandlerMapList; #endif // #defined __DRIVEMAP_H diff --git a/reactos/boot/freeldr/freeldr/include/freeldr.h b/reactos/boot/freeldr/freeldr/include/freeldr.h index 3f3ca67235d..3b41ac30190 100644 --- a/reactos/boot/freeldr/freeldr/include/freeldr.h +++ b/reactos/boot/freeldr/freeldr/include/freeldr.h @@ -20,62 +20,29 @@ #ifndef __FREELDR_H #define __FREELDR_H -#define NULL 0 -#define TRUE 1 -#define FALSE 0 - -#define BOOL int -#define BOOLEAN int -typedef BOOLEAN *PBOOLEAN; - -#define CHAR char -#define PCHAR char * -#define UCHAR unsigned char -#define PUCHAR unsigned char * -#define WCHAR unsigned short -#define PWCHAR unsigned short * - -#define VOID void -#define PVOID VOID* - -#ifdef __i386__ - -#define size_t unsigned int - -typedef unsigned char U8; -typedef char S8; -typedef unsigned short U16; -typedef short S16; -typedef unsigned long U32; -typedef long S32; -typedef unsigned long long U64; -typedef long long S64; - -typedef U8 __u8; -typedef S8 __s8; -typedef U16 __u16; -typedef S16 __s16; -typedef U32 __u32; -typedef S32 __s32; -typedef U64 __u64; -typedef S64 __s64; - -#endif // __i386__ - -typedef U8 *PU8; -typedef U16 *PU16; -typedef U32 *PU32; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define ROUND_UP(N, S) (((N) + (S) - 1) & ~((S) - 1)) #define ROUND_DOWN(N, S) ((N) & ~((S) - 1)) +#define Ke386EraseFlags(x) __asm__ __volatile__("pushl $0 ; popfl\n") + +extern ULONG BootDrive; /* BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc. */ +extern ULONG BootPartition; /* Boot Partition, 1-4 */ +extern BOOL UserInterfaceUp; /* Tells us if the user interface is displayed */ -#define PACKED __attribute__((packed)) - -extern U32 BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc. -extern U32 BootPartition; // Boot Partition, 1-4 -extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed - -void BootMain(char *CmdLine); -VOID RunLoader(VOID); +VOID BootMain(LPSTR CmdLine); +VOID RunLoader(VOID); #endif // defined __FREELDR_H diff --git a/reactos/boot/freeldr/freeldr/include/fs.h b/reactos/boot/freeldr/freeldr/include/fs.h index 35ab38f4c09..6b2d57d774a 100644 --- a/reactos/boot/freeldr/freeldr/include/fs.h +++ b/reactos/boot/freeldr/freeldr/include/fs.h @@ -33,15 +33,15 @@ #define PFILE FILE * VOID FileSystemError(PUCHAR ErrorString); -BOOL FsOpenVolume(U32 DriveNumber, U32 PartitionNumber); +BOOL FsOpenVolume(ULONG DriveNumber, ULONG PartitionNumber); PFILE FsOpenFile(PUCHAR FileName); VOID FsCloseFile(PFILE FileHandle); -BOOL FsReadFile(PFILE FileHandle, U32 BytesToRead, U32* BytesRead, PVOID Buffer); -U32 FsGetFileSize(PFILE FileHandle); -VOID FsSetFilePointer(PFILE FileHandle, U32 NewFilePointer); -U32 FsGetFilePointer(PFILE FileHandle); +BOOL FsReadFile(PFILE FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer); +ULONG FsGetFileSize(PFILE FileHandle); +VOID FsSetFilePointer(PFILE FileHandle, ULONG NewFilePointer); +ULONG FsGetFilePointer(PFILE FileHandle); BOOL FsIsEndOfFile(PFILE FileHandle); -U32 FsGetNumPathParts(PUCHAR Path); +ULONG FsGetNumPathParts(PUCHAR Path); VOID FsGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path); #endif // #defined __FS_H diff --git a/reactos/boot/freeldr/freeldr/include/inffile.h b/reactos/boot/freeldr/freeldr/include/inffile.h index e386324aee3..5848be34f50 100644 --- a/reactos/boot/freeldr/freeldr/include/inffile.h +++ b/reactos/boot/freeldr/freeldr/include/inffile.h @@ -36,7 +36,7 @@ #define MAX_INF_STRING_LENGTH 512 -typedef PU32 HINF, *PHINF; +typedef PULONG HINF, *PHINF; typedef struct _INFCONTEXT { @@ -52,7 +52,7 @@ typedef struct _INFCONTEXT BOOLEAN InfOpenFile (PHINF InfHandle, PCHAR FileName, - PU32 ErrorLine); + PULONG ErrorLine); VOID InfCloseFile (HINF InfHandle); @@ -79,39 +79,39 @@ InfFindNextMatchLine (PINFCONTEXT ContextIn, PINFCONTEXT ContextOut); -S32 +LONG InfGetLineCount (HINF InfHandle, PCHAR Section); -S32 +LONG InfGetFieldCount (PINFCONTEXT Context); BOOLEAN InfGetBinaryField (PINFCONTEXT Context, - U32 FieldIndex, - PU8 ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize); + ULONG FieldIndex, + PUCHAR ReturnBuffer, + ULONG ReturnBufferSize, + PULONG RequiredSize); BOOLEAN InfGetIntField (PINFCONTEXT Context, - U32 FieldIndex, - S32 *IntegerValue); + ULONG FieldIndex, + LONG *IntegerValue); BOOLEAN InfGetMultiSzField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize); + ULONG ReturnBufferSize, + PULONG RequiredSize); BOOLEAN InfGetStringField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize); + ULONG ReturnBufferSize, + PULONG RequiredSize); @@ -122,7 +122,7 @@ InfGetData (PINFCONTEXT Context, BOOLEAN InfGetDataField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR *Data); #endif /* __INFCACHE_H__ */ diff --git a/reactos/boot/freeldr/freeldr/include/inifile.h b/reactos/boot/freeldr/freeldr/include/inifile.h index 646d5319a3f..4b218363eb2 100644 --- a/reactos/boot/freeldr/freeldr/include/inifile.h +++ b/reactos/boot/freeldr/freeldr/include/inifile.h @@ -22,14 +22,14 @@ BOOL IniFileInitialize(VOID); -BOOL IniOpenSection(PUCHAR SectionName, U32* SectionId); -U32 IniGetNumSectionItems(U32 SectionId); -U32 IniGetSectionSettingNameSize(U32 SectionId, U32 SettingIndex); -U32 IniGetSectionSettingValueSize(U32 SectionId, U32 SettingIndex); -BOOL IniReadSettingByNumber(U32 SectionId, U32 SettingNumber, PUCHAR SettingName, U32 NameSize, PUCHAR SettingValue, U32 ValueSize); -BOOL IniReadSettingByName(U32 SectionId, PUCHAR SettingName, PUCHAR Buffer, U32 BufferSize); -BOOL IniAddSection(PUCHAR SectionName, U32* SectionId); -BOOL IniAddSettingValueToSection(U32 SectionId, PUCHAR SettingName, PUCHAR SettingValue); +BOOL IniOpenSection(PUCHAR SectionName, ULONG* SectionId); +ULONG IniGetNumSectionItems(ULONG SectionId); +ULONG IniGetSectionSettingNameSize(ULONG SectionId, ULONG SettingIndex); +ULONG IniGetSectionSettingValueSize(ULONG SectionId, ULONG SettingIndex); +BOOL IniReadSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize); +BOOL IniReadSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize); +BOOL IniAddSection(PUCHAR SectionName, ULONG* SectionId); +BOOL IniAddSettingValueToSection(ULONG SectionId, PUCHAR SettingName, PUCHAR SettingValue); #endif // defined __PARSEINI_H diff --git a/reactos/boot/freeldr/freeldr/include/linux.h b/reactos/boot/freeldr/freeldr/include/linux.h index 280cbf762ad..dc19f971b76 100644 --- a/reactos/boot/freeldr/freeldr/include/linux.h +++ b/reactos/boot/freeldr/freeldr/include/linux.h @@ -45,34 +45,34 @@ typedef struct { - U8 BootCode1[0x20]; + UCHAR BootCode1[0x20]; - U16 CommandLineMagic; - U16 CommandLineOffset; + USHORT CommandLineMagic; + USHORT CommandLineOffset; - U8 BootCode2[0x1CD]; + UCHAR BootCode2[0x1CD]; - U8 SetupSectors; - U16 RootFlags; - U16 SystemSize; - U16 SwapDevice; - U16 RamSize; - U16 VideoMode; - U16 RootDevice; - U16 BootFlag; // 0xAA55 + UCHAR SetupSectors; + USHORT RootFlags; + USHORT SystemSize; + USHORT SwapDevice; + USHORT RamSize; + USHORT VideoMode; + USHORT RootDevice; + USHORT BootFlag; // 0xAA55 } PACKED LINUX_BOOTSECTOR, *PLINUX_BOOTSECTOR; typedef struct { - U8 JumpInstruction[2]; - U32 SetupHeaderSignature; // Signature for SETUP-header - U16 Version; // Version number of header format - U16 RealModeSwitch; // Default switch - U16 SetupSeg; // SETUPSEG - U16 StartSystemSeg; - U16 KernelVersion; // Offset to kernel version string - U8 TypeOfLoader; // Loader ID + UCHAR JumpInstruction[2]; + ULONG SetupHeaderSignature; // Signature for SETUP-header + USHORT Version; // Version number of header format + USHORT RealModeSwitch; // Default switch + USHORT SetupSeg; // SETUPSEG + USHORT StartSystemSeg; + USHORT KernelVersion; // Offset to kernel version string + UCHAR TypeOfLoader; // Loader ID // =0, old one (LILO, Loadlin, // Bootlin, SYSLX, bootsect...) // else it is set by the loader: @@ -83,7 +83,7 @@ typedef struct // T=4 for ETHERBOOT // V = version - U8 LoadFlags; // flags, unused bits must be zero (RFU) + UCHAR LoadFlags; // flags, unused bits must be zero (RFU) // LOADED_HIGH = 1 // bit within loadflags, // if set, then the kernel is loaded high @@ -93,39 +93,39 @@ typedef struct // can be used for heap purposes. // Only the loader knows what is free! - U16 SetupMoveSize; // size to move, when we (setup) are not + USHORT SetupMoveSize; // size to move, when we (setup) are not // loaded at 0x90000. We will move ourselves // to 0x90000 then just before jumping into // the kernel. However, only the loader // know how much of data behind us also needs // to be loaded. - U32 Code32Start; // here loaders can put a different + ULONG Code32Start; // here loaders can put a different // start address for 32-bit code. // // 0x1000 = default for zImage // // 0x100000 = default for big kernel - U32 RamdiskAddress; // address of loaded ramdisk image + ULONG RamdiskAddress; // address of loaded ramdisk image // Here the loader (or kernel generator) puts // the 32-bit address were it loaded the image. - U32 RamdiskSize; // its size in bytes + ULONG RamdiskSize; // its size in bytes - U16 BootSectKludgeOffset; - U16 BootSectKludgeSegment; - U16 HeapEnd; // space from here (exclusive) down to + USHORT BootSectKludgeOffset; + USHORT BootSectKludgeSegment; + USHORT HeapEnd; // space from here (exclusive) down to // end of setup code can be used by setup // for local heap purposes. - U16 Pad1; - U32 CommandLinePointer; // 32-bit pointer to the kernel command line - U32 InitrdAddressMax; // Highest legal initrd address + USHORT Pad1; + ULONG CommandLinePointer; // 32-bit pointer to the kernel command line + ULONG InitrdAddressMax; // Highest legal initrd address } PACKED LINUX_SETUPSECTOR, *PLINUX_SETUPSECTOR; VOID BootNewLinuxKernel(VOID); // Implemented in linux.S -VOID BootOldLinuxKernel(U32 KernelSize); // Implemented in linux.S +VOID BootOldLinuxKernel(ULONG KernelSize); // Implemented in linux.S VOID LoadAndBootLinux(PUCHAR OperatingSystemName, PUCHAR Description); diff --git a/reactos/boot/freeldr/freeldr/include/machine.h b/reactos/boot/freeldr/freeldr/include/machine.h index 3da9b3b4d9d..2642ed57f8e 100644 --- a/reactos/boot/freeldr/freeldr/include/machine.h +++ b/reactos/boot/freeldr/freeldr/include/machine.h @@ -40,28 +40,28 @@ typedef struct tagMACHVTBL BOOL (*ConsKbHit)(VOID); int (*ConsGetCh)(VOID); - VOID (*VideoClearScreen)(U8 Attr); + VOID (*VideoClearScreen)(UCHAR Attr); VIDEODISPLAYMODE (*VideoSetDisplayMode)(char *DisplayMode, BOOL Init); - VOID (*VideoGetDisplaySize)(PU32 Width, PU32 Height, PU32 Depth); - U32 (*VideoGetBufferSize)(VOID); - VOID (*VideoSetTextCursorPosition)(U32 X, U32 Y); + VOID (*VideoGetDisplaySize)(PULONG Width, PULONG Height, PULONG Depth); + ULONG (*VideoGetBufferSize)(VOID); + VOID (*VideoSetTextCursorPosition)(ULONG X, ULONG Y); VOID (*VideoHideShowTextCursor)(BOOL Show); - VOID (*VideoPutChar)(int Ch, U8 Attr, unsigned X, unsigned Y); + VOID (*VideoPutChar)(int Ch, UCHAR Attr, unsigned X, unsigned Y); VOID (*VideoCopyOffScreenBufferToVRAM)(PVOID Buffer); BOOL (*VideoIsPaletteFixed)(VOID); - VOID (*VideoSetPaletteColor)(U8 Color, U8 Red, U8 Green, U8 Blue); - VOID (*VideoGetPaletteColor)(U8 Color, U8* Red, U8* Green, U8* Blue); + VOID (*VideoSetPaletteColor)(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue); + VOID (*VideoGetPaletteColor)(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue); VOID (*VideoSync)(VOID); VOID (*VideoPrepareForReactOS)(VOID); - U32 (*GetMemoryMap)(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize); + ULONG (*GetMemoryMap)(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize); - BOOL (*DiskReadLogicalSectors)(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer); - BOOL (*DiskGetPartitionEntry)(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); - BOOL (*DiskGetDriveGeometry)(U32 DriveNumber, PGEOMETRY DriveGeometry); - U32 (*DiskGetCacheableBlockCount)(U32 DriveNumber); + BOOL (*DiskReadLogicalSectors)(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); + BOOL (*DiskGetPartitionEntry)(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); + BOOL (*DiskGetDriveGeometry)(ULONG DriveNumber, PGEOMETRY DriveGeometry); + ULONG (*DiskGetCacheableBlockCount)(ULONG DriveNumber); - VOID (*RTCGetCurrentDateTime)(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second); + VOID (*RTCGetCurrentDateTime)(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second); VOID (*HwDetect)(VOID); } MACHVTBL, *PMACHVTBL; diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index 96c87de24a9..ccd6aaaa933 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -29,23 +29,23 @@ typedef struct { - U64 BaseAddress; - U64 Length; - U32 Type; - U32 Reserved; + ULONGLONG BaseAddress; + ULONGLONG Length; + ULONG Type; + ULONG Reserved; } PACKED BIOS_MEMORY_MAP, *PBIOS_MEMORY_MAP; -U32 GetSystemMemorySize(VOID); // Returns the amount of total memory in the system +ULONG GetSystemMemorySize(VOID); // Returns the amount of total memory in the system -//BOOL MmInitializeMemoryManager(U32 LowMemoryStart, U32 LowMemoryLength); +//BOOL MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength); BOOL MmInitializeMemoryManager(VOID); -PVOID MmAllocateMemory(U32 MemorySize); +PVOID MmAllocateMemory(ULONG MemorySize); VOID MmFreeMemory(PVOID MemoryPointer); -//PVOID MmAllocateLowMemory(U32 MemorySize); +//PVOID MmAllocateLowMemory(ULONG MemorySize); //VOID MmFreeLowMemory(PVOID MemoryPointer); -PVOID MmAllocateMemoryAtAddress(U32 MemorySize, PVOID DesiredAddress); -PVOID MmAllocateHighestMemoryBelowAddress(U32 MemorySize, PVOID DesiredAddress); +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress); +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress); #endif // defined __MEMORY_H diff --git a/reactos/boot/freeldr/freeldr/include/multiboot.h b/reactos/boot/freeldr/freeldr/include/multiboot.h index 755a7c829b2..f4e2cb42cf7 100644 --- a/reactos/boot/freeldr/freeldr/include/multiboot.h +++ b/reactos/boot/freeldr/freeldr/include/multiboot.h @@ -89,38 +89,34 @@ typedef struct elf_section_header_table unsigned long shndx; } elf_section_header_table_t; -/* The Multiboot information. */ -typedef struct multiboot_info +typedef struct _LOADER_PARAMETER_BLOCK { - unsigned long flags; - unsigned long mem_lower; - unsigned long mem_upper; - unsigned long boot_device; - unsigned long cmdline; - unsigned long mods_count; - unsigned long mods_addr; -#if 0 - /* reactos and loadros define this entry with a size of 12 byte but the union is 16 byte */ - union - { - aout_symbol_table_t aout_sym; - elf_section_header_table_t elf_sec; - } u; -#else - char syms[12]; -#endif - unsigned long mmap_length; - unsigned long mmap_addr; -} multiboot_info_t; + ULONG Flags; + ULONG MemLower; + ULONG MemHigher; + ULONG BootDevice; + ULONG CommandLine; + ULONG ModsCount; + ULONG ModsAddr; + UCHAR Syms[12]; + ULONG MmapLength; + ULONG MmapAddr; + ULONG DrivesCount; + ULONG DrivesAddr; + ULONG ConfigTable; + ULONG BootLoaderName; + ULONG PageDirectoryStart; + ULONG PageDirectoryEnd; + ULONG KernelBase; +} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK; /* The module structure. */ -typedef struct module -{ - unsigned long mod_start; - unsigned long mod_end; - unsigned long string; - unsigned long reserved; -} module_t; +typedef struct _FRLDR_MODULE { + ULONG_PTR ModuleStart; + ULONG_PTR ModuleEnd; + LPSTR ModuleName; + ULONG Reserved; +} FRLDR_MODULE, *PFRLDR_MODULE; /* The memory map. Be careful that the offset 0 is base_addr_low but no size. */ @@ -136,27 +132,92 @@ typedef struct memory_map } memory_map_t; -multiboot_header_t mb_header; // Multiboot header structure defined in kernel image file -multiboot_info_t mb_info; // Multiboot info structure passed to kernel -char multiboot_kernel_cmdline[255]; // Command line passed to kernel -module_t multiboot_modules[64]; // Array to hold boot module info loaded for the kernel +LOADER_PARAMETER_BLOCK LoaderBlock; /* Multiboot info structure passed to kernel */ +char multiboot_kernel_cmdline[255]; // Command line passed to kernel +FRLDR_MODULE multiboot_modules[64]; // Array to hold boot module info loaded for the kernel char multiboot_module_strings[64][256]; // Array to hold module names unsigned long multiboot_memory_map_descriptor_size; -memory_map_t multiboot_memory_map[32]; // Memory map +memory_map_t multiboot_memory_map[32]; // Memory map void boot_reactos(void); #include "fs.h" // Included FILE structure definition -BOOL MultiBootLoadKernel(FILE *KernelImage); -//BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName); -PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize); +BOOL +STDCALL +FrLdrBootReactOs(VOID); + +BOOL +STDCALL +FrLdrMapKernel(FILE *KernelImage); + +ULONG_PTR +STDCALL +FrLdrCreateModule(LPSTR ModuleName); + +ULONG_PTR +STDCALL +FrLdrLoadModule(FILE *ModuleImage, + LPSTR ModuleName, + PULONG ModuleSize); + +BOOL +STDCALL +FrLdrLoadKernel(PCHAR szFileName, + INT nPos); + +BOOL +FrLdrLoadNlsFile(PCHAR szSystemRoot, + PCHAR szErrorOut); + +BOOL +FrLdrLoadDriver(PCHAR szFileName, + INT nPos); +BOOL +LoadSymbolFile(PCHAR szSystemRoot, + PCHAR ModuleName, + INT nPos); + +VOID +FrLdrLoadBootDrivers(PCHAR szSystemRoot, + INT nPos); + +BOOL +STDCALL +FrLdrCloseModule(ULONG_PTR ModuleBase, + ULONG dwModuleSize); + +VOID +STDCALL +FrLdrStartup(ULONG Magic); + +VOID +FASTCALL +FrLdrGetKernelBase(VOID); + +VOID +FASTCALL +FrLdrSetupPae(ULONG Magic); + +VOID +FASTCALL +FrLdrGetPaeMode(VOID); + +VOID +FASTCALL +FrLdrSetupPageDirectory(VOID); + +VOID +LoadAndBootReactOS(PUCHAR OperatingSystemName); + +VOID FASTCALL AsmCode(VOID); +typedef VOID (FASTCALL *ASMCODE)(ULONG Magic, + PLOADER_PARAMETER_BLOCK LoaderBlock); int GetBootPartition(char *OperatingSystemName); -PVOID MultiBootCreateModule(char *ModuleName); -BOOL MultiBootCloseModule(PVOID ModuleBase, U32 dwModuleSize); + #endif /* ! ASM */ diff --git a/reactos/boot/freeldr/freeldr/include/oslist.h b/reactos/boot/freeldr/freeldr/include/oslist.h index 5f874066bd6..3376df9e74d 100644 --- a/reactos/boot/freeldr/freeldr/include/oslist.h +++ b/reactos/boot/freeldr/freeldr/include/oslist.h @@ -20,9 +20,9 @@ #ifndef __OSLIST_H #define __OSLIST_H -BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, U32* OperatingSystemCountPointer); -U32 CountOperatingSystems(U32 SectionId); -BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, U32 OperatingSystemCount); +BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG* OperatingSystemCountPointer); +ULONG CountOperatingSystems(ULONG SectionId); +BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount); BOOL RemoveQuotes(PUCHAR QuotedString); #endif // #defined __OSLIST_H diff --git a/reactos/boot/freeldr/freeldr/include/portio.h b/reactos/boot/freeldr/freeldr/include/portio.h index f7aba205aa0..f4550bf2f50 100644 --- a/reactos/boot/freeldr/freeldr/include/portio.h +++ b/reactos/boot/freeldr/freeldr/include/portio.h @@ -27,52 +27,52 @@ */ VOID -/*STDCALL*/ -READ_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Value, U32 Count); +STDCALL +READ_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Value, ULONG Count); VOID -/*STDCALL*/ -READ_PORT_BUFFER_ULONG (U32* Port, U32* Value, U32 Count); +STDCALL +READ_PORT_BUFFER_ULONG (ULONG* Port, ULONG* Value, ULONG Count); VOID -/*STDCALL*/ -READ_PORT_BUFFER_USHORT (U16* Port, U16* Value, U32 Count); +STDCALL +READ_PORT_BUFFER_USHORT (USHORT* Port, USHORT* Value, ULONG Count); UCHAR -/*STDCALL*/ +STDCALL READ_PORT_UCHAR (PUCHAR Port); -U32 -/*STDCALL*/ -READ_PORT_ULONG (U32* Port); +ULONG +STDCALL +READ_PORT_ULONG (ULONG* Port); -U16 -/*STDCALL*/ -READ_PORT_USHORT (U16* Port); +USHORT +STDCALL +READ_PORT_USHORT (USHORT* Port); VOID -/*STDCALL*/ -WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Value, U32 Count); +STDCALL +WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, PUCHAR Value, ULONG Count); VOID -/*STDCALL*/ -WRITE_PORT_BUFFER_ULONG (U32* Port, U32* Value, U32 Count); +STDCALL +WRITE_PORT_BUFFER_ULONG (ULONG* Port, ULONG* Value, ULONG Count); VOID -/*STDCALL*/ -WRITE_PORT_BUFFER_USHORT (U16* Port, U16* Value, U32 Count); +STDCALL +WRITE_PORT_BUFFER_USHORT (USHORT* Port, USHORT* Value, ULONG Count); VOID -/*STDCALL*/ +STDCALL WRITE_PORT_UCHAR (PUCHAR Port, UCHAR Value); VOID -/*STDCALL*/ -WRITE_PORT_ULONG (U32* Port, U32 Value); +STDCALL +WRITE_PORT_ULONG (ULONG* Port, ULONG Value); VOID -/*STDCALL*/ -WRITE_PORT_USHORT (U16* Port, U16 Value); +STDCALL +WRITE_PORT_USHORT (USHORT* Port, USHORT Value); #endif // defined __PORTIO_H diff --git a/reactos/boot/freeldr/freeldr/include/reactos.h b/reactos/boot/freeldr/freeldr/include/reactos.h index 780bb139afc..c553754b2e6 100644 --- a/reactos/boot/freeldr/freeldr/include/reactos.h +++ b/reactos/boot/freeldr/freeldr/include/reactos.h @@ -26,23 +26,23 @@ // ReactOS Loading Functions // /////////////////////////////////////////////////////////////////////////////////////// -void LoadAndBootReactOS(PUCHAR OperatingSystemName); +VOID LoadAndBootReactOS(PUCHAR OperatingSystemName); /////////////////////////////////////////////////////////////////////////////////////// // // ReactOS Setup Loader Functions // /////////////////////////////////////////////////////////////////////////////////////// -VOID ReactOSRunSetupLoader(VOID); +VOID ReactOSRunSetupLoader(VOID); /////////////////////////////////////////////////////////////////////////////////////// // // ARC Path Functions // /////////////////////////////////////////////////////////////////////////////////////// -BOOL DissectArcPath(char *ArcPath, char *BootPath, U32* BootDrive, U32* BootPartition); -void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, U32 Disk, U32 Partition); -U32 ConvertArcNameToBiosDriveNumber(PUCHAR ArcPath); +BOOL DissectArcPath(LPSTR ArcPath, LPSTR BootPath, PULONG BootDrive, PULONG BootPartition); +VOID ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, ULONG Disk, ULONG Partition); +ULONG ConvertArcNameToBiosDriveNumber(PUCHAR ArcPath); #endif // defined __REACTOS_H diff --git a/reactos/boot/freeldr/freeldr/include/rtl.h b/reactos/boot/freeldr/freeldr/include/rtl.h index 8fd5384b5af..bcf796de590 100644 --- a/reactos/boot/freeldr/freeldr/include/rtl.h +++ b/reactos/boot/freeldr/freeldr/include/rtl.h @@ -22,23 +22,6 @@ #include -/////////////////////////////////////////////////////////////////////////////////////// -// -// String Functions -// -/////////////////////////////////////////////////////////////////////////////////////// -int strlen(char *str); -char * strcpy(char *dest, char *src); -char * strncpy(char *dest, char *src, size_t count); -char * strcat(char *dest, char *src); -char * strncat(char *dst, const char *src, size_t n); -char * strchr(const char *s, int c); -char * strrchr(const char *s, int c); -int strcmp(const char *string1, const char *string2); -int stricmp(const char *string1, const char *string2); -int strncmp(const char *string1, const char *string2, size_t length); -int strnicmp(const char *string1, const char *string2, size_t length); - /////////////////////////////////////////////////////////////////////////////////////// // // Memory Functions @@ -52,7 +35,6 @@ void * memset(void *src, int val, size_t count); #define RtlCompareMemory(Source1, Source2, Length) memcmp(Source1, Source2, Length) #define RtlCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) #define RtlFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) -#define RtlMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) #define RtlZeroMemory(Destination, Length) memset(Destination, 0, Length) /////////////////////////////////////////////////////////////////////////////////////// @@ -117,7 +99,7 @@ PLIST_ITEM RtlListRemoveTail(PLIST_ITEM ListHead); // Removes the entry a PLIST_ITEM RtlListGetHead(PLIST_ITEM ListHead); // Returns the entry at the head of the list PLIST_ITEM RtlListGetTail(PLIST_ITEM ListHead); // Returns the entry at the tail of the list BOOL RtlListIsEmpty(PLIST_ITEM ListHead); // Indicates whether a doubly linked list is empty -U32 RtlListCountEntries(PLIST_ITEM ListHead); // Counts the entries in a doubly linked list +ULONG RtlListCountEntries(PLIST_ITEM ListHead); // Counts the entries in a doubly linked list PLIST_ITEM RtlListGetPrevious(PLIST_ITEM ListEntry); // Returns the previous item in the list PLIST_ITEM RtlListGetNext(PLIST_ITEM ListEntry); // Returns the next item in the list PLIST_ITEM RtlListRemoveEntry(PLIST_ITEM ListEntry); // Removes the entry from the list diff --git a/reactos/boot/freeldr/freeldr/include/ui.h b/reactos/boot/freeldr/freeldr/include/ui.h index 34c7016c878..997b1e6e824 100644 --- a/reactos/boot/freeldr/freeldr/include/ui.h +++ b/reactos/boot/freeldr/freeldr/include/ui.h @@ -21,8 +21,8 @@ #define __UI_H -extern U32 UiScreenWidth; // Screen Width -extern U32 UiScreenHeight; // Screen Height +extern ULONG UiScreenWidth; // Screen Width +extern ULONG UiScreenHeight; // Screen Height extern UCHAR UiStatusBarFgColor; // Status bar foreground color extern UCHAR UiStatusBarBgColor; // Status bar background color @@ -57,26 +57,26 @@ extern UCHAR UiMonthNames[12][15]; BOOL UiInitialize(BOOLEAN ShowGui); // Initialize User-Interface VOID UiUnInitialize(PUCHAR BootText); // Un-initialize User-Interface VOID UiDrawBackdrop(VOID); // Fills the entire screen with a backdrop -VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr -VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom); // Draws a shadow on the bottom and right sides of the area specified -VOID UiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr); // Draws a box around the area specified -VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified -VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges +VOID UiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr +VOID UiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); // Draws a shadow on the bottom and right sides of the area specified +VOID UiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr); // Draws a box around the area specified +VOID UiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified +VOID UiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PUCHAR TextString, UCHAR Attr); // Draws centered text at the coordinates specified and clips the edges VOID UiDrawStatusText(PUCHAR StatusText); // Draws text at the very bottom line on the screen VOID UiUpdateDateTime(VOID); // Updates the date and time VOID UiInfoBox(PUCHAR MessageText); // Displays a info box on the screen VOID UiMessageBox(PUCHAR MessageText); // Displays a message box on the screen with an ok button VOID UiMessageBoxCritical(PUCHAR MessageText); // Displays a message box on the screen with an ok button using no system resources -VOID UiDrawProgressBarCenter(U32 Position, U32 Range, PUCHAR ProgressText); // Draws the progress bar showing nPos percent filled -VOID UiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position, U32 Range, PUCHAR ProgressText); // Draws the progress bar showing nPos percent filled +VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PUCHAR ProgressText); // Draws the progress bar showing nPos percent filled +VOID UiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PUCHAR ProgressText); // Draws the progress bar showing nPos percent filled VOID UiShowMessageBoxesInSection(PUCHAR SectionName); // Displays all the message boxes in a given section VOID UiEscapeString(PUCHAR String); // Processes a string and changes all occurances of "\n" to '\n' -BOOL UiEditBox(PUCHAR MessageText, PUCHAR EditTextBuffer, U32 Length); +BOOL UiEditBox(PUCHAR MessageText, PUCHAR EditTextBuffer, ULONG Length); UCHAR UiTextToColor(PUCHAR ColorText); // Converts the text color into it's equivalent color value UCHAR UiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill into it's equivalent fill value -VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars); // Truncates a string to MaxChars by adding an ellipsis on the end '...' +VOID UiTruncateStringEllipsis(PUCHAR StringText, ULONG MaxChars); // Truncates a string to MaxChars by adding an ellipsis on the end '...' VOID UiFadeInBackdrop(VOID); // Draws the backdrop and fades the screen in VOID UiFadeOut(VOID); // Fades the screen out @@ -86,9 +86,9 @@ VOID UiFadeOut(VOID); // Fades the screen out // Menu Functions // /////////////////////////////////////////////////////////////////////////////////////// -typedef BOOL (*UiMenuKeyPressFilterCallback)(U32 KeyPress); +typedef BOOL (*UiMenuKeyPressFilterCallback)(ULONG KeyPress); -BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter); +BOOL UiDisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, ULONG* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter); diff --git a/reactos/boot/freeldr/freeldr/include/version.h b/reactos/boot/freeldr/freeldr/include/version.h index 0ca8cfc9034..b51df4ada21 100644 --- a/reactos/boot/freeldr/freeldr/include/version.h +++ b/reactos/boot/freeldr/freeldr/include/version.h @@ -22,7 +22,7 @@ /* just some stuff */ -#define VERSION "FreeLoader v1.9" +#define VERSION "FreeLoader v2.0" #define COPYRIGHT "Copyright (C) 1998-2003 Brian Palmer " #define AUTHOR_EMAIL "" #define BY_AUTHOR "by Brian Palmer" @@ -34,8 +34,8 @@ // If you add features then you increment the minor version and zero the patch version // If you add major functionality then you increment the major version and zero the minor & patch versions // -#define FREELOADER_MAJOR_VERSION 1 -#define FREELOADER_MINOR_VERSION 9 +#define FREELOADER_MAJOR_VERSION 2 +#define FREELOADER_MINOR_VERSION 0 #define FREELOADER_PATCH_VERSION 0 diff --git a/reactos/boot/freeldr/freeldr/include/video.h b/reactos/boot/freeldr/freeldr/include/video.h index f269c2530db..ba66d7771c4 100644 --- a/reactos/boot/freeldr/freeldr/include/video.h +++ b/reactos/boot/freeldr/freeldr/include/video.h @@ -22,42 +22,25 @@ typedef struct { - U8 Red; - U8 Green; - U8 Blue; + UCHAR Red; + UCHAR Green; + UCHAR Blue; } PACKED PALETTE_ENTRY, *PPALETTE_ENTRY; extern PVOID VideoOffScreenBuffer; -U16 BiosIsVesaSupported(VOID); // Implemented in i386vid.S, returns the VESA version +USHORT BiosIsVesaSupported(VOID); // Implemented in i386vid.S, returns the VESA version PVOID VideoAllocateOffScreenBuffer(VOID); // Returns a pointer to an off-screen buffer sufficient for the current video mode -#if 0 /* Not used */ -U32 VideoGetMemoryBankForPixel(U32 X, U32 Y); -U32 VideoGetMemoryBankForPixel16(U32 X, U32 Y); -U32 VideoGetBankOffsetForPixel(U32 X, U32 Y); -U32 VideoGetBankOffsetForPixel16(U32 X, U32 Y); -VOID VideoSetMemoryBank(U16 BankNumber); -U32 VideoGetOffScreenMemoryOffsetForPixel(U32 X, U32 Y); -#endif VOID VideoCopyOffScreenBufferToVRAM(VOID); -VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount); -VOID VideoRestorePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount); +VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, ULONG ColorCount); +VOID VideoRestorePaletteState(PPALETTE_ENTRY Palette, ULONG ColorCount); -#if 0 /* Not used */ -VOID VideoSetPixel16(U32 X, U32 Y, U8 Color); -VOID VideoSetPixel256(U32 X, U32 Y, U8 Color); -VOID VideoSetPixelRGB(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue); -VOID VideoSetPixel16_OffScreen(U32 X, U32 Y, U8 Color); -VOID VideoSetPixel256_OffScreen(U32 X, U32 Y, U8 Color); -VOID VideoSetPixelRGB_OffScreen(U32 X, U32 Y, U8 Red, U8 Green, U8 Blue); -#endif - -VOID VideoSetAllColorsToBlack(U32 ColorCount); -VOID VideoFadeIn(PPALETTE_ENTRY Palette, U32 ColorCount); -VOID VideoFadeOut(U32 ColorCount); +VOID VideoSetAllColorsToBlack(ULONG ColorCount); +VOID VideoFadeIn(PPALETTE_ENTRY Palette, ULONG ColorCount); +VOID VideoFadeOut(ULONG ColorCount); #endif // defined __VIDEO_H diff --git a/reactos/boot/freeldr/freeldr/inffile/inffile.c b/reactos/boot/freeldr/freeldr/inffile/inffile.c index 0f4cb50642e..255e0c0f6de 100644 --- a/reactos/boot/freeldr/freeldr/inffile/inffile.c +++ b/reactos/boot/freeldr/freeldr/inffile/inffile.c @@ -56,7 +56,7 @@ typedef struct _INFCACHELINE struct _INFCACHELINE *Next; struct _INFCACHELINE *Prev; - S32 FieldCount; + LONG FieldCount; PCHAR Key; @@ -74,7 +74,7 @@ typedef struct _INFCACHESECTION PINFCACHELINE FirstLine; PINFCACHELINE LastLine; - S32 LineCount; + LONG LineCount; CHAR Name[1]; } INFCACHESECTION, *PINFCACHESECTION; @@ -241,7 +241,7 @@ InfpCacheAddSection (PINFCACHE Cache, PCHAR Name) { PINFCACHESECTION Section = NULL; - U32 Size; + ULONG Size; if (Cache == NULL || Name == NULL) { @@ -341,7 +341,7 @@ InfpAddFieldToLine (PINFCACHELINE Line, PCHAR Data) { PINFCACHEFIELD Field; - U32 Size; + ULONG Size; Size = sizeof(INFCACHEFIELD) + strlen(Data); Field = (PINFCACHEFIELD)MmAllocateMemory (Size); @@ -839,7 +839,7 @@ static BOOLEAN InfpParseBuffer (PINFCACHE file, const CHAR *buffer, const CHAR *end, - PU32 error_line) + PULONG error_line) { struct parser parser; const CHAR *pos = buffer; @@ -877,17 +877,17 @@ InfpParseBuffer (PINFCACHE file, BOOLEAN InfOpenFile(PHINF InfHandle, PCHAR FileName, - PU32 ErrorLine) + PULONG ErrorLine) { PFILE FileHandle; PCHAR FileBuffer; - U32 FileSize; + ULONG FileSize; PINFCACHE Cache; BOOLEAN Success; *InfHandle = NULL; - *ErrorLine = (U32)-1; + *ErrorLine = (ULONG)-1; /* Open the inf file */ @@ -1144,7 +1144,7 @@ InfFindNextMatchLine (PINFCONTEXT ContextIn, } -S32 +LONG InfGetLineCount(HINF InfHandle, PCHAR Section) { @@ -1184,7 +1184,7 @@ InfGetLineCount(HINF InfHandle, /* InfGetLineText */ -S32 +LONG InfGetFieldCount(PINFCONTEXT Context) { if (Context == NULL || Context->Line == NULL) @@ -1196,16 +1196,16 @@ InfGetFieldCount(PINFCONTEXT Context) BOOLEAN InfGetBinaryField (PINFCONTEXT Context, - U32 FieldIndex, - PU8 ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize) + ULONG FieldIndex, + PUCHAR ReturnBuffer, + ULONG ReturnBufferSize, + PULONG RequiredSize) { PINFCACHELINE CacheLine; PINFCACHEFIELD CacheField; - U32 Index; - U32 Size; - PU8 Ptr; + ULONG Index; + ULONG Size; + PUCHAR Ptr; if (Context == NULL || Context->Line == NULL || FieldIndex == 0) { @@ -1252,12 +1252,12 @@ InfGetBinaryField (PINFCONTEXT Context, BOOLEAN InfGetIntField (PINFCONTEXT Context, - U32 FieldIndex, - S32 *IntegerValue) + ULONG FieldIndex, + LONG *IntegerValue) { PINFCACHELINE CacheLine; PINFCACHEFIELD CacheField; - U32 Index; + ULONG Index; PCHAR Ptr; if (Context == NULL || Context->Line == NULL || IntegerValue == NULL) @@ -1295,16 +1295,16 @@ InfGetIntField (PINFCONTEXT Context, BOOLEAN InfGetMultiSzField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize) + ULONG ReturnBufferSize, + PULONG RequiredSize) { PINFCACHELINE CacheLine; PINFCACHEFIELD CacheField; PINFCACHEFIELD FieldPtr; - U32 Index; - U32 Size; + ULONG Index; + ULONG Size; PCHAR Ptr; if (Context == NULL || Context->Line == NULL || FieldIndex == 0) @@ -1364,16 +1364,16 @@ InfGetMultiSzField (PINFCONTEXT Context, BOOLEAN InfGetStringField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR ReturnBuffer, - U32 ReturnBufferSize, - PU32 RequiredSize) + ULONG ReturnBufferSize, + PULONG RequiredSize) { PINFCACHELINE CacheLine; PINFCACHEFIELD CacheField; - U32 Index; + ULONG Index; PCHAR Ptr; - U32 Size; + ULONG Size; if (Context == NULL || Context->Line == NULL || FieldIndex == 0) { @@ -1456,12 +1456,12 @@ InfGetData (PINFCONTEXT Context, BOOLEAN InfGetDataField (PINFCONTEXT Context, - U32 FieldIndex, + ULONG FieldIndex, PCHAR *Data) { PINFCACHELINE CacheLine; PINFCACHEFIELD CacheField; - U32 Index; + ULONG Index; if (Context == NULL || Context->Line == NULL || Data == NULL) { diff --git a/reactos/boot/freeldr/freeldr/inifile/ini.h b/reactos/boot/freeldr/freeldr/inifile/ini.h index b24c1f0cab2..98a74967d33 100644 --- a/reactos/boot/freeldr/freeldr/inifile/ini.h +++ b/reactos/boot/freeldr/freeldr/inifile/ini.h @@ -48,29 +48,29 @@ typedef struct { LIST_ITEM ListEntry; PUCHAR SectionName; - U32 SectionItemCount; + ULONG SectionItemCount; PINI_SECTION_ITEM SectionItemList; } INI_SECTION, *PINI_SECTION; extern PINI_SECTION IniFileSectionListHead; -extern U32 IniFileSectionCount; -extern U32 IniFileSettingCount; +extern ULONG IniFileSectionCount; +extern ULONG IniFileSettingCount; -PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber); +PFILE IniOpenIniFile(UCHAR BootDriveNumber, UCHAR BootPartitionNumber); -BOOL IniParseFile(PUCHAR IniFileData, U32 IniFileSize); -U32 IniGetNextLineSize(PUCHAR IniFileData, U32 IniFileSize, U32 CurrentOffset); -U32 IniGetNextLine(PUCHAR IniFileData, U32 IniFileSize, PUCHAR Buffer, U32 BufferSize, U32 CurrentOffset); -BOOL IniIsLineEmpty(PUCHAR LineOfText, U32 TextLength); -BOOL IniIsCommentLine(PUCHAR LineOfText, U32 TextLength); -BOOL IniIsSectionName(PUCHAR LineOfText, U32 TextLength); -U32 IniGetSectionNameSize(PUCHAR SectionNameLine, U32 LineLength); -VOID IniExtractSectionName(PUCHAR SectionName, PUCHAR SectionNameLine, U32 LineLength); -BOOL IniIsSetting(PUCHAR LineOfText, U32 TextLength); -U32 IniGetSettingNameSize(PUCHAR SettingNameLine, U32 LineLength); -U32 IniGetSettingValueSize(PUCHAR SettingValueLine, U32 LineLength); -VOID IniExtractSettingName(PUCHAR SettingName, PUCHAR SettingNameLine, U32 LineLength); -VOID IniExtractSettingValue(PUCHAR SettingValue, PUCHAR SettingValueLine, U32 LineLength); +BOOL IniParseFile(PUCHAR IniFileData, ULONG IniFileSize); +ULONG IniGetNextLineSize(PUCHAR IniFileData, ULONG IniFileSize, ULONG CurrentOffset); +ULONG IniGetNextLine(PUCHAR IniFileData, ULONG IniFileSize, PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset); +BOOL IniIsLineEmpty(PUCHAR LineOfText, ULONG TextLength); +BOOL IniIsCommentLine(PUCHAR LineOfText, ULONG TextLength); +BOOL IniIsSectionName(PUCHAR LineOfText, ULONG TextLength); +ULONG IniGetSectionNameSize(PUCHAR SectionNameLine, ULONG LineLength); +VOID IniExtractSectionName(PUCHAR SectionName, PUCHAR SectionNameLine, ULONG LineLength); +BOOL IniIsSetting(PUCHAR LineOfText, ULONG TextLength); +ULONG IniGetSettingNameSize(PUCHAR SettingNameLine, ULONG LineLength); +ULONG IniGetSettingValueSize(PUCHAR SettingValueLine, ULONG LineLength); +VOID IniExtractSettingName(PUCHAR SettingName, PUCHAR SettingNameLine, ULONG LineLength); +VOID IniExtractSettingValue(PUCHAR SettingValue, PUCHAR SettingValueLine, ULONG LineLength); #endif // defined __INI_H diff --git a/reactos/boot/freeldr/freeldr/inifile/ini_init.c b/reactos/boot/freeldr/freeldr/inifile/ini_init.c index d47cdc11ad6..046133e4c1b 100644 --- a/reactos/boot/freeldr/freeldr/inifile/ini_init.c +++ b/reactos/boot/freeldr/freeldr/inifile/ini_init.c @@ -29,7 +29,7 @@ BOOL IniFileInitialize(VOID) { PFILE Freeldr_Ini; // File handle for freeldr.ini PUCHAR FreeLoaderIniFileData; - U32 FreeLoaderIniFileSize; + ULONG FreeLoaderIniFileSize; BOOL Success; // Open freeldr.ini @@ -87,7 +87,7 @@ BOOL IniFileInitialize(VOID) return Success; } -PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber) +PFILE IniOpenIniFile(UCHAR BootDriveNumber, UCHAR BootPartitionNumber) { PFILE IniFileHandle; // File handle for freeldr.ini diff --git a/reactos/boot/freeldr/freeldr/inifile/inifile.c b/reactos/boot/freeldr/freeldr/inifile/inifile.c index 4456df98834..9f8c19b8e5b 100644 --- a/reactos/boot/freeldr/freeldr/inifile/inifile.c +++ b/reactos/boot/freeldr/freeldr/inifile/inifile.c @@ -24,7 +24,7 @@ #include #include -BOOL IniOpenSection(PUCHAR SectionName, U32* SectionId) +BOOL IniOpenSection(PUCHAR SectionName, ULONG* SectionId) { PINI_SECTION Section; @@ -41,7 +41,7 @@ BOOL IniOpenSection(PUCHAR SectionName, U32* SectionId) if (stricmp(SectionName, Section->SectionName) == 0) { // We found it - *SectionId = (U32)Section; + *SectionId = (ULONG)Section; DbgPrint((DPRINT_INIFILE, "IniOpenSection() Found it! SectionId = 0x%x\n", SectionId)); return TRUE; } @@ -55,7 +55,7 @@ BOOL IniOpenSection(PUCHAR SectionName, U32* SectionId) return FALSE; } -U32 IniGetNumSectionItems(U32 SectionId) +ULONG IniGetNumSectionItems(ULONG SectionId) { PINI_SECTION Section = (PINI_SECTION)SectionId; @@ -65,7 +65,7 @@ U32 IniGetNumSectionItems(U32 SectionId) return Section->SectionItemCount; } -U32 IniGetSectionSettingNameSize(U32 SectionId, U32 SettingIndex) +ULONG IniGetSectionSettingNameSize(ULONG SectionId, ULONG SettingIndex) { PINI_SECTION Section = (PINI_SECTION)SectionId; @@ -73,7 +73,7 @@ U32 IniGetSectionSettingNameSize(U32 SectionId, U32 SettingIndex) return (strlen(Section->SectionItemList[SettingIndex].ItemName) + 1); } -U32 IniGetSectionSettingValueSize(U32 SectionId, U32 SettingIndex) +ULONG IniGetSectionSettingValueSize(ULONG SectionId, ULONG SettingIndex) { PINI_SECTION Section = (PINI_SECTION)SectionId; @@ -81,12 +81,12 @@ U32 IniGetSectionSettingValueSize(U32 SectionId, U32 SettingIndex) return (strlen(Section->SectionItemList[SettingIndex].ItemValue) + 1); } -BOOL IniReadSettingByNumber(U32 SectionId, U32 SettingNumber, PUCHAR SettingName, U32 NameSize, PUCHAR SettingValue, U32 ValueSize) +BOOL IniReadSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize) { PINI_SECTION Section = (PINI_SECTION)SectionId; PINI_SECTION_ITEM SectionItem; #ifdef DEBUG - U32 RealSettingNumber = SettingNumber; + ULONG RealSettingNumber = SettingNumber; #endif DbgPrint((DPRINT_INIFILE, ".001 NameSize = %d ValueSize = %d\n", NameSize, ValueSize)); @@ -131,7 +131,7 @@ BOOL IniReadSettingByNumber(U32 SectionId, U32 SettingNumber, PUCHAR SettingName return FALSE; } -BOOL IniReadSettingByName(U32 SectionId, PUCHAR SettingName, PUCHAR Buffer, U32 BufferSize) +BOOL IniReadSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize) { PINI_SECTION Section = (PINI_SECTION)SectionId; PINI_SECTION_ITEM SectionItem; @@ -163,7 +163,7 @@ BOOL IniReadSettingByName(U32 SectionId, PUCHAR SettingName, PUCHAR Buffer, U32 return FALSE; } -BOOL IniAddSection(PUCHAR SectionName, U32* SectionId) +BOOL IniAddSection(PUCHAR SectionName, ULONG* SectionId) { PINI_SECTION Section; @@ -198,12 +198,12 @@ BOOL IniAddSection(PUCHAR SectionName, U32* SectionId) RtlListInsertTail((PLIST_ITEM)IniFileSectionListHead, (PLIST_ITEM)Section); } - *SectionId = (U32)Section; + *SectionId = (ULONG)Section; return TRUE; } -BOOL IniAddSettingValueToSection(U32 SectionId, PUCHAR SettingName, PUCHAR SettingValue) +BOOL IniAddSettingValueToSection(ULONG SectionId, PUCHAR SettingName, PUCHAR SettingValue) { PINI_SECTION Section = (PINI_SECTION)SectionId; PINI_SECTION_ITEM SectionItem; diff --git a/reactos/boot/freeldr/freeldr/inifile/parse.c b/reactos/boot/freeldr/freeldr/inifile/parse.c index f490b1d733c..87f6bbd1035 100644 --- a/reactos/boot/freeldr/freeldr/inifile/parse.c +++ b/reactos/boot/freeldr/freeldr/inifile/parse.c @@ -26,17 +26,17 @@ PINI_SECTION IniFileSectionListHead = NULL; -U32 IniFileSectionCount = 0; -U32 IniFileSettingCount = 0; +ULONG IniFileSectionCount = 0; +ULONG IniFileSettingCount = 0; -BOOL IniParseFile(PUCHAR IniFileData, U32 IniFileSize) +BOOL IniParseFile(PUCHAR IniFileData, ULONG IniFileSize) { - U32 CurrentOffset; - U32 CurrentLineNumber; + ULONG CurrentOffset; + ULONG CurrentLineNumber; PUCHAR IniFileLine; - U32 IniFileLineSize; - U32 LineLength; + ULONG IniFileLineSize; + ULONG LineLength; PINI_SECTION CurrentSection = NULL; PINI_SECTION_ITEM CurrentItem = NULL; @@ -189,10 +189,10 @@ BOOL IniParseFile(PUCHAR IniFileData, U32 IniFileSize) return TRUE; } -U32 IniGetNextLineSize(PUCHAR IniFileData, U32 IniFileSize, U32 CurrentOffset) +ULONG IniGetNextLineSize(PUCHAR IniFileData, ULONG IniFileSize, ULONG CurrentOffset) { - U32 Idx; - U32 LineCharCount = 0; + ULONG Idx; + ULONG LineCharCount = 0; // Loop through counting chars until we hit the end of the // file or we encounter a new line char @@ -216,9 +216,9 @@ U32 IniGetNextLineSize(PUCHAR IniFileData, U32 IniFileSize, U32 CurrentOffset) return LineCharCount; } -U32 IniGetNextLine(PUCHAR IniFileData, U32 IniFileSize, PUCHAR Buffer, U32 BufferSize, U32 CurrentOffset) +ULONG IniGetNextLine(PUCHAR IniFileData, ULONG IniFileSize, PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset) { - U32 Idx; + ULONG Idx; // Loop through grabbing chars until we hit the end of the // file or we encounter a new line char @@ -252,9 +252,9 @@ U32 IniGetNextLine(PUCHAR IniFileData, U32 IniFileSize, PUCHAR Buffer, U32 Buffe return CurrentOffset; } -BOOL IniIsLineEmpty(PUCHAR LineOfText, U32 TextLength) +BOOL IniIsLineEmpty(PUCHAR LineOfText, ULONG TextLength) { - U32 Idx; + ULONG Idx; // Check for text (skipping whitespace) for (Idx=0; IdxRamdiskAddress = (U32)LinuxInitrdLoadAddress; + LinuxSetupSector->RamdiskAddress = (ULONG)LinuxInitrdLoadAddress; LinuxSetupSector->RamdiskSize = LinuxInitrdSize; DbgPrint((DPRINT_LINUX, "RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress)); diff --git a/reactos/boot/freeldr/freeldr/machine.c b/reactos/boot/freeldr/freeldr/machine.c index 993a9a43591..520769e3b06 100644 --- a/reactos/boot/freeldr/freeldr/machine.c +++ b/reactos/boot/freeldr/freeldr/machine.c @@ -65,7 +65,7 @@ MachConsGetCh() } VOID -MachVideoClearScreen(U8 Attr) +MachVideoClearScreen(UCHAR Attr) { MachVtbl.VideoClearScreen(Attr); } @@ -77,19 +77,19 @@ MachVideoSetDisplayMode(char *DisplayMode, BOOL Init) } VOID -MachVideoGetDisplaySize(PU32 Width, PU32 Height, PU32 Depth) +MachVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) { return MachVtbl.VideoGetDisplaySize(Width, Height, Depth); } -U32 +ULONG MachVideoGetBufferSize(VOID) { return MachVtbl.VideoGetBufferSize(); } VOID -MachVideoSetTextCursorPosition(U32 X, U32 Y) +MachVideoSetTextCursorPosition(ULONG X, ULONG Y) { return MachVtbl.VideoSetTextCursorPosition(X, Y); } @@ -101,7 +101,7 @@ MachVideoHideShowTextCursor(BOOL Show) } VOID -MachVideoPutChar(int Ch, U8 Attr, unsigned X, unsigned Y) +MachVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) { MachVtbl.VideoPutChar(Ch, Attr, X, Y); } @@ -119,13 +119,13 @@ MachVideoIsPaletteFixed(VOID) } VOID -MachVideoSetPaletteColor(U8 Color, U8 Red, U8 Green, U8 Blue) +MachVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue) { return MachVtbl.VideoSetPaletteColor(Color, Red, Green, Blue); } VOID -MachVideoGetPaletteColor(U8 Color, U8 *Red, U8 *Green, U8 *Blue) +MachVideoGetPaletteColor(UCHAR Color, UCHAR *Red, UCHAR *Green, UCHAR *Blue) { return MachVtbl.VideoGetPaletteColor(Color, Red, Green, Blue); } @@ -142,38 +142,38 @@ MachVideoPrepareForReactOS(VOID) MachVtbl.VideoPrepareForReactOS(); } -U32 -MachGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MaxMemoryMapSize) +ULONG +MachGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) { return MachVtbl.GetMemoryMap(BiosMemoryMap, MaxMemoryMapSize); } BOOL -MachDiskReadLogicalSectors(U32 DriveNumber, U64 SectorNumber, U32 SectorCount, PVOID Buffer) +MachDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) { return MachVtbl.DiskReadLogicalSectors(DriveNumber, SectorNumber, SectorCount, Buffer); } BOOL -MachDiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) +MachDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) { return MachVtbl.DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); } BOOL -MachDiskGetDriveGeometry(U32 DriveNumber, PGEOMETRY DriveGeometry) +MachDiskGetDriveGeometry(ULONG DriveNumber, PGEOMETRY DriveGeometry) { return MachVtbl.DiskGetDriveGeometry(DriveNumber, DriveGeometry); } -U32 -MachDiskGetCacheableBlockCount(U32 DriveNumber) +ULONG +MachDiskGetCacheableBlockCount(ULONG DriveNumber) { return MachVtbl.DiskGetCacheableBlockCount(DriveNumber); } VOID -MachRTCGetCurrentDateTime(PU32 Year, PU32 Month, PU32 Day, PU32 Hour, PU32 Minute, PU32 Second) +MachRTCGetCurrentDateTime(PULONG Year, PULONG Month, PULONG Day, PULONG Hour, PULONG Minute, PULONG Second) { MachVtbl.RTCGetCurrentDateTime(Year, Month, Day, Hour, Minute, Second); } diff --git a/reactos/boot/freeldr/freeldr/miscboot.c b/reactos/boot/freeldr/freeldr/miscboot.c index 5b4828cfbc8..3531fe254f0 100644 --- a/reactos/boot/freeldr/freeldr/miscboot.c +++ b/reactos/boot/freeldr/freeldr/miscboot.c @@ -34,9 +34,9 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) PFILE FilePointer; UCHAR SettingName[80]; UCHAR SettingValue[80]; - U32 SectionId; + ULONG SectionId; UCHAR FileName[260]; - U32 BytesRead; + ULONG BytesRead; // Find all the message box settings and run them UiShowMessageBoxesInSection(OperatingSystemName); @@ -90,7 +90,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName) } // Check for validity - if (*((U16*)(0x7c00 + 0x1fe)) != 0xaa55) + if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; @@ -113,7 +113,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName) { UCHAR SettingName[80]; UCHAR SettingValue[80]; - U32 SectionId; + ULONG SectionId; PARTITION_TABLE_ENTRY PartitionTableEntry; // Find all the message box settings and run them @@ -159,7 +159,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName) } // Check for validity - if (*((U16*)(0x7c00 + 0x1fe)) != 0xaa55) + if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; @@ -182,7 +182,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName) { UCHAR SettingName[80]; UCHAR SettingValue[80]; - U32 SectionId; + ULONG SectionId; // Find all the message box settings and run them UiShowMessageBoxesInSection(OperatingSystemName); @@ -211,7 +211,7 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName) } // Check for validity - if (*((U16*)(0x7c00 + 0x1fe)) != 0xaa55) + if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55) { UiMessageBox("Invalid boot sector magic (0xaa55)"); return; diff --git a/reactos/boot/freeldr/freeldr/mm/mem.h b/reactos/boot/freeldr/freeldr/mm/mem.h index 7d24552d6f0..168f3f4027e 100644 --- a/reactos/boot/freeldr/freeldr/mm/mem.h +++ b/reactos/boot/freeldr/freeldr/mm/mem.h @@ -30,8 +30,8 @@ typedef struct { - U32 PageAllocated; // Zero = free, non-zero = allocated - U32 PageAllocationLength; // Number of pages allocated (or zero if this isn't the first page in the chain) + ULONG PageAllocated; // Zero = free, non-zero = allocated + ULONG PageAllocationLength; // Number of pages allocated (or zero if this isn't the first page in the chain) } PACKED PAGE_LOOKUP_TABLE_ITEM, *PPAGE_LOOKUP_TABLE_ITEM; // @@ -44,27 +44,27 @@ typedef struct extern PVOID PageLookupTableAddress; -extern U32 TotalPagesInLookupTable; -extern U32 FreePagesInLookupTable; -extern U32 LastFreePageHint; +extern ULONG TotalPagesInLookupTable; +extern ULONG FreePagesInLookupTable; +extern ULONG LastFreePageHint; #ifdef DEBUG -PUCHAR MmGetSystemMemoryMapTypeString(U32 Type); +PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type); #endif -U32 MmGetPageNumberFromAddress(PVOID Address); // Returns the page number that contains a linear address -PVOID MmGetEndAddressOfAnyMemory(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount); // Returns the last address of memory from the memory map -U32 MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount); // Returns the count of addressable pages from address zero including any memory holes and reserved memory regions -PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount); // Returns the address for a memory chunk big enough to hold the page lookup table (starts search from end of memory) -VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount); // Sorts the BIOS_MEMORY_MAP array so the first element corresponds to the first address in memory -VOID MmInitPageLookupTable(PVOID PageLookupTable, U32 TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount); // Inits the page lookup table according to the memory types in the memory map -VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, U32 StartPage, U32 PageCount, U32 PageAllocated); // Marks the specified pages as allocated or free in the lookup table -VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, U32 StartPage, U32 PageCount); // Allocates the specified pages in the lookup table -U32 MmCountFreePagesInLookupTable(PVOID PageLookupTable, U32 TotalPageCount); // Returns the number of free pages in the lookup table -U32 MmFindAvailablePagesFromEnd(PVOID PageLookupTable, U32 TotalPageCount, U32 PagesNeeded); // Returns the page number of the first available page range from the end of memory -U32 MmFindAvailablePagesBeforePage(PVOID PageLookupTable, U32 TotalPageCount, U32 PagesNeeded, U32 LastPage); // Returns the page number of the first available page range before the specified page -VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32* MapCount); // Removes entries in the memory map that describe memory above 4G -VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, U32 TotalPageCount); // Sets the LastFreePageHint to the last usable page of memory -BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, U32 TotalPageCount, PVOID PageAddress, U32 PageCount); // Returns TRUE if the specified pages of memory are available, otherwise FALSE +ULONG MmGetPageNumberFromAddress(PVOID Address); // Returns the page number that contains a linear address +PVOID MmGetEndAddressOfAnyMemory(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the last address of memory from the memory map +ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the count of addressable pages from address zero including any memory holes and reserved memory regions +PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the address for a memory chunk big enough to hold the page lookup table (starts search from end of memory) +VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Sorts the BIOS_MEMORY_MAP array so the first element corresponds to the first address in memory +VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Inits the page lookup table according to the memory types in the memory map +VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, ULONG PageAllocated); // Marks the specified pages as allocated or free in the lookup table +VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount); // Allocates the specified pages in the lookup table +ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Returns the number of free pages in the lookup table +ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded); // Returns the page number of the first available page range from the end of memory +ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage); // Returns the page number of the first available page range before the specified page +VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount); // Removes entries in the memory map that describe memory above 4G +VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount); // Sets the LastFreePageHint to the last usable page of memory +BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount); // Returns TRUE if the specified pages of memory are available, otherwise FALSE #endif // defined __MEM_H diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 408e4ff6490..1d93653f4ca 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/boot/freeldr/freeldr/mm/meminit.c @@ -30,11 +30,11 @@ #ifdef DEBUG typedef struct { - U32 Type; + ULONG Type; UCHAR TypeString[20]; } MEMORY_TYPE, *PMEMORY_TYPE; -U32 MemoryTypeCount = 5; +ULONG MemoryTypeCount = 5; MEMORY_TYPE MemoryTypeArray[] = { { 0, "Unknown Memory" }, @@ -46,16 +46,16 @@ MEMORY_TYPE MemoryTypeArray[] = #endif PVOID PageLookupTableAddress = NULL; -U32 TotalPagesInLookupTable = 0; -U32 FreePagesInLookupTable = 0; -U32 LastFreePageHint = 0; +ULONG TotalPagesInLookupTable = 0; +ULONG FreePagesInLookupTable = 0; +ULONG LastFreePageHint = 0; BOOL MmInitializeMemoryManager(VOID) { BIOS_MEMORY_MAP BiosMemoryMap[32]; - U32 BiosMemoryMapEntryCount; + ULONG BiosMemoryMapEntryCount; #ifdef DEBUG - U32 Index; + ULONG Index; #endif DbgPrint((DPRINT_MEMORY, "Initializing Memory Manager.\n")); @@ -105,9 +105,9 @@ BOOL MmInitializeMemoryManager(VOID) } #ifdef DEBUG -PUCHAR MmGetSystemMemoryMapTypeString(U32 Type) +PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type) { - U32 Index; + ULONG Index; for (Index=1; Index= PageLookupTableSize) { - PageLookupTableMemAddress = (PVOID)(U32)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); + PageLookupTableMemAddress = (PVOID)(ULONG)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); break; } } @@ -209,10 +209,10 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCo return PageLookupTableMemAddress; } -VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount) +VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) { - U32 Index; - U32 LoopCount; + ULONG Index; + ULONG LoopCount; BIOS_MEMORY_MAP TempMapItem; // Loop once for each entry in the memory map minus one @@ -231,15 +231,15 @@ VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount) } } -VOID MmInitPageLookupTable(PVOID PageLookupTable, U32 TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, U32 MapCount) +VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) { - U32 MemoryMapStartPage; - U32 MemoryMapEndPage; - U32 MemoryMapPageCount; - U32 MemoryMapPageAllocated; - U32 PageLookupTableStartPage; - U32 PageLookupTablePageCount; - U32 Index; + ULONG MemoryMapStartPage; + ULONG MemoryMapEndPage; + ULONG MemoryMapPageCount; + ULONG MemoryMapPageAllocated; + ULONG PageLookupTableStartPage; + ULONG PageLookupTablePageCount; + ULONG Index; DbgPrint((DPRINT_MEMORY, "MmInitPageLookupTable()\n")); @@ -250,8 +250,8 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, U32 TotalPageCount, PBIOS_MEMO for (Index=0; Index TotalPageCount) { @@ -349,11 +349,11 @@ U32 MmFindAvailablePagesFromEnd(PVOID PageLookupTable, U32 TotalPageCount, U32 P return 0; } -U32 MmFindAvailablePagesBeforePage(PVOID PageLookupTable, U32 TotalPageCount, U32 PagesNeeded, U32 LastPage) +ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; - U32 AvailablePagesSoFar; - U32 Index; + ULONG AvailablePagesSoFar; + ULONG Index; if (LastPage > TotalPageCount) { @@ -382,7 +382,7 @@ U32 MmFindAvailablePagesBeforePage(PVOID PageLookupTable, U32 TotalPageCount, U3 return 0; } -VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32* MapCount) +VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount) { int Index; int Index2; @@ -406,10 +406,10 @@ VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, U32* MapCount) } } -VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, U32 TotalPageCount) +VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; - U32 Index; + ULONG Index; for (Index=TotalPageCount-1; Index>0; Index--) { @@ -421,11 +421,11 @@ VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, U32 TotalPageCount) } } -BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, U32 TotalPageCount, PVOID PageAddress, U32 PageCount) +BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; - U32 StartPage; - U32 Index; + ULONG StartPage; + ULONG Index; StartPage = MmGetPageNumberFromAddress(PageAddress); diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index 1eb5bfdd971..402069a634e 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -27,7 +27,7 @@ #ifdef DEBUG -U32 AllocationCount = 0; +ULONG AllocationCount = 0; VOID VerifyHeap(VOID); VOID DumpMemoryAllocMap(VOID); @@ -36,10 +36,10 @@ VOID DecrementAllocationCount(VOID); VOID MemAllocTest(VOID); #endif // DEBUG -PVOID MmAllocateMemory(U32 MemorySize) +PVOID MmAllocateMemory(ULONG MemorySize) { - U32 PagesNeeded; - U32 FirstFreePageFromEnd; + ULONG PagesNeeded; + ULONG FirstFreePageFromEnd; PVOID MemPointer; if (MemorySize == 0) @@ -87,10 +87,10 @@ PVOID MmAllocateMemory(U32 MemorySize) return MemPointer; } -PVOID MmAllocateMemoryAtAddress(U32 MemorySize, PVOID DesiredAddress) +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) { - U32 PagesNeeded; - U32 StartPageNumber; + ULONG PagesNeeded; + ULONG StartPageNumber; PVOID MemPointer; if (MemorySize == 0) @@ -139,11 +139,11 @@ PVOID MmAllocateMemoryAtAddress(U32 MemorySize, PVOID DesiredAddress) return MemPointer; } -PVOID MmAllocateHighestMemoryBelowAddress(U32 MemorySize, PVOID DesiredAddress) +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress) { - U32 PagesNeeded; - U32 FirstFreePageFromEnd; - U32 DesiredAddressPageNumber; + ULONG PagesNeeded; + ULONG FirstFreePageFromEnd; + ULONG DesiredAddressPageNumber; PVOID MemPointer; if (MemorySize == 0) @@ -158,7 +158,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(U32 MemorySize, PVOID DesiredAddress) PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE; // Get the page number for their desired address - DesiredAddressPageNumber = (U32)DesiredAddress / MM_PAGE_SIZE; + DesiredAddressPageNumber = (ULONG)DesiredAddress / MM_PAGE_SIZE; // If we don't have enough available mem // then return NULL @@ -196,9 +196,9 @@ PVOID MmAllocateHighestMemoryBelowAddress(U32 MemorySize, PVOID DesiredAddress) VOID MmFreeMemory(PVOID MemoryPointer) { - U32 PageNumber; - U32 PageCount; - U32 Idx; + ULONG PageNumber; + ULONG PageCount; + ULONG Idx; PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress; #ifdef DEBUG @@ -255,9 +255,9 @@ VOID MmFreeMemory(PVOID MemoryPointer) #ifdef DEBUG VOID VerifyHeap(VOID) { - U32 Idx; - U32 Idx2; - U32 Count; + ULONG Idx; + ULONG Idx2; + ULONG Count; PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress; if (DUMP_MEM_MAP_ON_VERIFY) @@ -315,7 +315,7 @@ VOID VerifyHeap(VOID) VOID DumpMemoryAllocMap(VOID) { - U32 Idx; + ULONG Idx; PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress; DbgPrint((DPRINT_MEMORY, "----------- Memory Allocation Bitmap -----------\n")); @@ -400,7 +400,7 @@ VOID MemAllocTest(VOID) } #endif // DEBUG -U32 GetSystemMemorySize(VOID) +ULONG GetSystemMemorySize(VOID) { return (TotalPagesInLookupTable * MM_PAGE_SIZE); } diff --git a/reactos/boot/freeldr/freeldr/multiboot.c b/reactos/boot/freeldr/freeldr/multiboot.c index 5db72524353..97b7191e8f3 100644 --- a/reactos/boot/freeldr/freeldr/multiboot.c +++ b/reactos/boot/freeldr/freeldr/multiboot.c @@ -1,271 +1,728 @@ /* - * FreeLoader - * Copyright (C) 1998-2003 Brian Palmer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Freeloader + * FILE: boot/freeldr/freeldr/multiboot.c + * PURPOSE: ReactOS Loader + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Hartmutt Birr - SMP/PAE Code */ - #include -#include -#include -#include -#include -#include -#include -#include +#include -unsigned long next_module_load_base = 0; -module_t* pOpenModule = NULL; +#define NDEBUG +#include + +/* Base Addres of Kernel in Physical Memory */ +#define KERNEL_BASE_PHYS 0x200000 + +/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */ +#define PFN_SHIFT 12 + +/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */ +#define PDE_SHIFT 20 +#define PDE_SHIFT_PAE 18 + + +/* Converts a Relative Address read from the Kernel into a Physical Address */ +#define RaToPa(p) \ + (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS) + +/* Converts a Phsyical Address Pointer into a Page Frame Number */ +#define PaPtrToPfn(p) \ + (((ULONG_PTR)&p) >> PFN_SHIFT) + +/* Converts a Phsyical Address into a Page Frame Number */ +#define PaToPfn(p) \ + ((p) >> PFN_SHIFT) + +#define STARTUP_BASE 0xF0000000 +#define HYPERSPACE_BASE 0xF0800000 +#define APIC_BASE 0xFEC00000 +#define KPCR_BASE 0xFF000000 + +#define LowMemPageTableIndex 0 +#define StartupPageTableIndex (STARTUP_BASE >> 20) / sizeof(HARDWARE_PTE_X86) +#define HyperspacePageTableIndex (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86) +#define KpcrPageTableIndex (KPCR_BASE >> 20) / sizeof(HARDWARE_PTE_X86) +#define ApicPageTableIndex (APIC_BASE >> 20) / sizeof(HARDWARE_PTE_X86) + +#define LowMemPageTableIndexPae 0 +#define StartupPageTableIndexPae (STARTUP_BASE >> 21) +#define HyperspacePageTableIndexPae (HYPERSPACE_BASE >> 21) +#define KpcrPageTableIndexPae (KPCR_BASE >> 21) +#define ApicPageTableIndexPae (APIC_BASE >> 21) -BOOL MultiBootLoadKernel(FILE *KernelImage) -{ - U32* ImageHeaders; - int Idx; - U32 dwHeaderChecksum; - U32 dwFileLoadOffset; - U32 dwDataSize; - U32 dwBssSize; +#define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase - // Allocate 8192 bytes for multiboot header - ImageHeaders = (U32*)MmAllocateMemory(8192); - if (ImageHeaders == NULL) - { - return FALSE; - } +/* Load Address of Next Module */ +ULONG_PTR NextModuleBase = 0; - /* - * Load the first 8192 bytes of the kernel image - * so we can search for the multiboot header - */ - if (!FsReadFile(KernelImage, 8192, NULL, ImageHeaders)) - { - MmFreeMemory(ImageHeaders); - return FALSE; - } +/* Currently Opened Module */ +PFRLDR_MODULE CurrentModule = NULL; - /* - * Now find the multiboot header and copy it - */ - for (Idx=0; Idx<2048; Idx++) - { - // Did we find it? - if (ImageHeaders[Idx] == MULTIBOOT_HEADER_MAGIC) - { - // Yes, copy it and break out of this loop - memcpy(&mb_header, &ImageHeaders[Idx], sizeof(multiboot_header_t)); +/* Unrelocated Kernel Base in Virtual Memory */ +ULONG_PTR KernelBase; - break; - } - } +/* Wether PAE is to be used or not */ +BOOLEAN PaeModeEnabled; - MmFreeMemory(ImageHeaders); +/* Kernel Entrypoint in Physical Memory */ +ULONG_PTR KernelEntry; - /* - * If we reached the end of the 8192 bytes without - * finding the multiboot header then return error - */ - if (Idx == 2048) - { - UiMessageBox("No multiboot header found!"); - return FALSE; - } +/* Page Directory and Tables for non-PAE Systems */ +extern ULONG_PTR startup_pagedirectory; +extern ULONG_PTR lowmem_pagetable; +extern ULONG_PTR kernel_pagetable; +extern ULONG_PTR hyperspace_pagetable; +extern ULONG_PTR _pae_pagedirtable; +extern ULONG_PTR apic_pagetable; +extern ULONG_PTR kpcr_pagetable; - /*printf("multiboot header:\n"); - printf("0x%x\n", mb_header.magic); - printf("0x%x\n", mb_header.flags); - printf("0x%x\n", mb_header.checksum); - printf("0x%x\n", mb_header.header_addr); - printf("0x%x\n", mb_header.load_addr); - printf("0x%x\n", mb_header.load_end_addr); - printf("0x%x\n", mb_header.bss_end_addr); - printf("0x%x\n", mb_header.entry_addr); - getch();*/ +/* Page Directory and Tables for PAE Systems */ +extern ULONG_PTR startup_pagedirectorytable_pae; +extern ULONG_PTR startup_pagedirectory_pae; +extern ULONG_PTR lowmem_pagetable_pae; +extern ULONG_PTR kernel_pagetable_pae; +extern ULONG_PTR hyperspace_pagetable_pae; +extern ULONG_PTR pagedirtable_pae; +extern ULONG_PTR apic_pagetable_pae; +extern ULONG_PTR kpcr_pagetable_pae; - /* - * Calculate the checksum and make sure it matches - */ - dwHeaderChecksum = mb_header.magic; - dwHeaderChecksum += mb_header.flags; - dwHeaderChecksum += mb_header.checksum; - if (dwHeaderChecksum != 0) - { - UiMessageBox("Multiboot header checksum invalid!"); - return FALSE; - } - - /* - * Get the file offset, this should be 0, and move the file pointer - */ - dwFileLoadOffset = (Idx * sizeof(U32)) - (mb_header.header_addr - mb_header.load_addr); - FsSetFilePointer(KernelImage, dwFileLoadOffset); - - /* - * Load the file image - */ - dwDataSize = (mb_header.load_end_addr - mb_header.load_addr); - FsReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr); +typedef struct _HARDWARE_PTE_X86 { + ULONG Valid : 1; + ULONG Write : 1; + ULONG Owner : 1; + ULONG WriteThrough : 1; + ULONG CacheDisable : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG LargePage : 1; + ULONG Global : 1; + ULONG CopyOnWrite : 1; + ULONG Prototype : 1; + ULONG reserved : 1; + ULONG PageFrameNumber : 20; +} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86; - /* - * Initialize bss area - */ - dwBssSize = (mb_header.bss_end_addr - mb_header.load_end_addr); - memset((void*)mb_header.load_end_addr, 0, dwBssSize); +typedef struct _HARDWARE_PTE_X64 { + ULONG Valid : 1; + ULONG Write : 1; + ULONG Owner : 1; + ULONG WriteThrough : 1; + ULONG CacheDisable : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG LargePage : 1; + ULONG Global : 1; + ULONG CopyOnWrite : 1; + ULONG Prototype : 1; + ULONG reserved : 1; + ULONG PageFrameNumber : 20; + ULONG reserved2 : 31; + ULONG NoExecute : 1; +} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64; - next_module_load_base = ROUND_UP(mb_header.bss_end_addr, /*PAGE_SIZE*/4096); +typedef struct _PAGE_DIRECTORY_X86 { + HARDWARE_PTE_X86 Pde[1024]; +} PAGE_DIRECTORY_x86, *PPAGE_DIRECTORY_X86; - return TRUE; +typedef struct _PAGE_DIRECTORY_X64 { + HARDWARE_PTE_X64 Pde[2048]; +} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64; + +typedef struct _PAGE_DIRECTORY_TABLE_X64 { + HARDWARE_PTE_X64 Pde[4]; +} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64; + +/* FUNCTIONS *****************************************************************/ + +/*++ + * FrLdrStartup + * INTERNAL + * + * Prepares the system for loading the Kernel. + * + * Params: + * Magic - Multiboot Magic + * + * Returns: + * None. + * + * Remarks: + * None. + * + *--*/ +VOID +STDCALL +FrLdrStartup(ULONG Magic) +{ + /* Disable Interrupts */ + Ke386DisableInterrupts(); + + /* Re-initalize EFLAGS */ + Ke386EraseFlags(); + + /* Get Kernel Base and Set MmSystemRangeStart */ + FrLdrGetKernelBase(); + + FrLdrGetPaeMode(); + + /* Initialize the page directory */ + FrLdrSetupPageDirectory(); + + /* Initialize Paging, Write-Protection and Load NTOSKRNL */ + FrLdrSetupPae(Magic); } -#if 0 -BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName) +/*++ + * FrLdrSetupPae + * INTERNAL + * + * Configures PAE on a MP System, and sets the PDBR if it's supported, or if + * the system is UP. + * + * Params: + * Magic - Multiboot Magic + * + * Returns: + * None. + * + * Remarks: + * None. + * + *--*/ +VOID +FASTCALL +FrLdrSetupPae(ULONG Magic) { - U32 dwModuleSize; - module_t* pModule; - char* ModuleNameString; - char * TempName; - - /* - * Get current module data structure and module name string array - */ - pModule = &multiboot_modules[mb_info.mods_count]; - do { - TempName = strchr( ModuleName, '\\' ); - if( TempName ) - ModuleName = TempName + 1; - } while( TempName ); + ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory; + ASMCODE PagedJump; - ModuleNameString = multiboot_module_strings[mb_info.mods_count]; - - dwModuleSize = FsGetFileSize(ModuleImage); - pModule->mod_start = next_module_load_base; - pModule->mod_end = next_module_load_base + dwModuleSize; - strcpy(ModuleNameString, ModuleName); - pModule->string = (unsigned long)ModuleNameString; - - /* - * Load the file image - */ - FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); + if (PaeModeEnabled) + { + PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectorytable_pae; + + /* Enable PAE */ + Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE); + } + + /* Set the PDBR */ + Ke386SetPageTableDirectory(PageDirectoryBaseAddress); + + /* Enable Paging and Write Protect*/ + Ke386SetCr0(Ke386GetCr0() | X86_CR0_PG | X86_CR0_WP); + + /* Jump to Kernel */ + PagedJump = (ASMCODE)KernelEntryPoint; + PagedJump(Magic, &LoaderBlock); + } - next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096); - mb_info.mods_count++; - - return TRUE; -} -#endif - -PVOID MultiBootLoadModule(FILE *ModuleImage, char *ModuleName, U32* ModuleSize) +/*++ + * FrLdrGetKernelBase + * INTERNAL + * + * Gets the Kernel Base to use. + * + * Params: + * + * Returns: + * None. + * + * Remarks: + * Sets both the FreeLdr internal variable as well as the one which + * will be used by the Kernel. + * + *--*/ +VOID +FASTCALL +FrLdrGetKernelBase(VOID) { - U32 dwModuleSize; - module_t* pModule; - char* ModuleNameString; - char * TempName; - - /* - * Get current module data structure and module name string array - */ - pModule = &multiboot_modules[mb_info.mods_count]; - do { - TempName = strchr( ModuleName, '\\' ); - if( TempName ) - ModuleName = TempName + 1; - } while( TempName ); - - ModuleNameString = multiboot_module_strings[mb_info.mods_count]; - - dwModuleSize = FsGetFileSize(ModuleImage); - pModule->mod_start = next_module_load_base; - pModule->mod_end = next_module_load_base + dwModuleSize; - strcpy(ModuleNameString, ModuleName); - pModule->string = (unsigned long)ModuleNameString; - - /* - * Load the file image - */ - FsReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base); - - next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096); - mb_info.mods_count++; - - if (ModuleSize != NULL) - *ModuleSize = dwModuleSize; - - return((PVOID)pModule->mod_start); + PCHAR p1; + PCHAR p2; + + /* Read Command Line */ + for(p1 = (PCHAR)&LoaderBlock.CommandLine; *p1 && (p2 = strchr(p1, '/')); p2++) { + + /* Find "/3GB" */ + if (!strnicmp(p2, "3GB", 3)) { + + /* Make sure there's nothing following it */ + if (p2[3] == ' ' || p2[3] == 0) { + + /* Use 3GB */ + KernelBase = 0xC0000000; + + } else { + + /* Use 2GB */ + KernelBase = 0x80000000; + } + } + } + + /* Set KernelBase */ + LoaderBlock.KernelBase = KernelBase; } -#if 0 -int GetBootPartition(char *OperatingSystemName) +/*++ + * FrLdrGetPaeMode + * INTERNAL + * + * Determines whether PAE mode shoudl be enabled or not. + * + * Params: + * None. + * + * Returns: + * None. + * + * Remarks: + * None. + * + *--*/ +VOID +FASTCALL +FrLdrGetPaeMode(VOID) { - int BootPartitionNumber = -1; - char value[1024]; - U32 SectionId; + /* FIXME: Read command line */ + PaeModeEnabled = FALSE; - if (IniOpenSection(OperatingSystemName, &SectionId)) - { - if (IniReadSettingByName(SectionId, "BootPartition", value, 1024)) - { - BootPartitionNumber = atoi(value); - } - } - - return BootPartitionNumber; -} -#endif - -PVOID MultiBootCreateModule(char *ModuleName) -{ - module_t* pModule; - char* ModuleNameString; - - /* - * Get current module data structure and module name string array - */ - pModule = &multiboot_modules[mb_info.mods_count]; - - ModuleNameString = multiboot_module_strings[mb_info.mods_count]; - - pModule->mod_start = next_module_load_base; - pModule->mod_end = -1; - strcpy(ModuleNameString, ModuleName); - pModule->string = (unsigned long)ModuleNameString; - - pOpenModule = pModule; - - return((PVOID)pModule->mod_start); + if (PaeModeEnabled) + { + } } - -BOOL MultiBootCloseModule(PVOID ModuleBase, U32 dwModuleSize) +/*++ + * FrLdrSetupPageDirectory + * INTERNAL + * + * Sets up the ReactOS Startup Page Directory. + * + * Params: + * None. + * + * Returns: + * None. + * + * Remarks: + * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure. + * As such, please note that PageFrameNumber == PageEntryNumber. + * + *--*/ +VOID +FASTCALL +FrLdrSetupPageDirectory(VOID) { - module_t* pModule; + PPAGE_DIRECTORY_X86 PageDir; + PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae; + PPAGE_DIRECTORY_X64 PageDirPae; + ULONG KernelPageTableIndex; + ULONG i; - if ((pOpenModule != NULL) && - ((module_t*)ModuleBase == (module_t*)pOpenModule->mod_start) && - (pOpenModule->mod_end == -1)) - { - pModule = pOpenModule; - pModule->mod_end = pModule->mod_start + dwModuleSize; + if (PaeModeEnabled) { + + /* Get the Kernel Table Index */ + KernelPageTableIndex = (KernelBase >> 21); - next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096); - mb_info.mods_count++; - pOpenModule = NULL; + /* Get the Startup Page Directory Table */ + PageDirTablePae = (PPAGE_DIRECTORY_TABLE_X64)&startup_pagedirectorytable_pae; - return(TRUE); - } + /* Get the Startup Page Directory */ + PageDirPae = (PPAGE_DIRECTORY_X64)&startup_pagedirectory_pae; - return(FALSE); + /* Set the Startup page directory table */ + for (i = 0; i < 4; i++) + { + PageDirTablePae->Pde[i].Valid = 1; + PageDirTablePae->Pde[i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i; + } + + /* Set up the Low Memory PDE */ + for (i = 0; i < 2; i++) + { + PageDirPae->Pde[LowMemPageTableIndexPae + i].Valid = 1; + PageDirPae->Pde[LowMemPageTableIndexPae + i].Write = 1; + PageDirPae->Pde[LowMemPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(lowmem_pagetable_pae) + i; + } + + /* Set up the Kernel PDEs */ + for (i = 0; i < 3; i++) + { + PageDirPae->Pde[KernelPageTableIndex + i].Valid = 1; + PageDirPae->Pde[KernelPageTableIndex + i].Write = 1; + PageDirPae->Pde[KernelPageTableIndex + i].PageFrameNumber = PaPtrToPfn(kernel_pagetable_pae) + i; + } + + /* Set up the Startup PDE */ + for (i = 0; i < 4; i++) + { + PageDirPae->Pde[StartupPageTableIndexPae + i].Valid = 1; + PageDirPae->Pde[StartupPageTableIndexPae + i].Write = 1; + PageDirPae->Pde[StartupPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i; + } + + /* Set up the Hyperspace PDE */ + for (i = 0; i < 2; i++) + { + PageDirPae->Pde[HyperspacePageTableIndexPae + i].Valid = 1; + PageDirPae->Pde[HyperspacePageTableIndexPae + i].Write = 1; + PageDirPae->Pde[HyperspacePageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable_pae) + i; + } + + /* Set up the Apic PDE */ + for (i = 0; i < 2; i++) + { + PageDirPae->Pde[ApicPageTableIndexPae + i].Valid = 1; + PageDirPae->Pde[ApicPageTableIndexPae + i].Write = 1; + PageDirPae->Pde[ApicPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(apic_pagetable_pae) + i; + } + + /* Set up the KPCR PDE */ + PageDirPae->Pde[KpcrPageTableIndexPae].Valid = 1; + PageDirPae->Pde[KpcrPageTableIndexPae].Write = 1; + PageDirPae->Pde[KpcrPageTableIndexPae].PageFrameNumber = PaPtrToPfn(kpcr_pagetable_pae); + + /* Set up Low Memory PTEs */ + PageDirPae = (PPAGE_DIRECTORY_X64)&lowmem_pagetable_pae; + for (i=0; i<1024; i++) { + + PageDirPae->Pde[i].Valid = 1; + PageDirPae->Pde[i].Write = 1; + PageDirPae->Pde[i].Owner = 1; + PageDirPae->Pde[i].PageFrameNumber = i; + } + + /* Set up Kernel PTEs */ + PageDirPae = (PPAGE_DIRECTORY_X64)&kernel_pagetable_pae; + for (i=0; i<1536; i++) { + + PageDirPae->Pde[i].Valid = 1; + PageDirPae->Pde[i].Write = 1; + PageDirPae->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS) + i; + } + + /* Set up APIC PTEs */ + PageDirPae = (PPAGE_DIRECTORY_X64)&apic_pagetable_pae; + PageDirPae->Pde[0].Valid = 1; + PageDirPae->Pde[0].Write = 1; + PageDirPae->Pde[0].CacheDisable = 1; + PageDirPae->Pde[0].WriteThrough = 1; + PageDirPae->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE); + PageDirPae->Pde[0x200].Valid = 1; + PageDirPae->Pde[0x200].Write = 1; + PageDirPae->Pde[0x200].CacheDisable = 1; + PageDirPae->Pde[0x200].WriteThrough = 1; + PageDirPae->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS); + + /* Set up KPCR PTEs */ + PageDirPae = (PPAGE_DIRECTORY_X64)&kpcr_pagetable_pae; + PageDirPae->Pde[0].Valid = 1; + PageDirPae->Pde[0].Write = 1; + PageDirPae->Pde[0].PageFrameNumber = 1; + + } else { + + /* Get the Kernel Table Index */ + KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86); + + /* Get the Startup Page Directory */ + PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory; + + /* Set up the Low Memory PDE */ + PageDir->Pde[LowMemPageTableIndex].Valid = 1; + PageDir->Pde[LowMemPageTableIndex].Write = 1; + PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable); + + /* Set up the Kernel PDEs */ + PageDir->Pde[KernelPageTableIndex].Valid = 1; + PageDir->Pde[KernelPageTableIndex].Write = 1; + PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable); + PageDir->Pde[KernelPageTableIndex + 1].Valid = 1; + PageDir->Pde[KernelPageTableIndex + 1].Write = 1; + PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096); + + /* Set up the Startup PDE */ + PageDir->Pde[StartupPageTableIndex].Valid = 1; + PageDir->Pde[StartupPageTableIndex].Write = 1; + PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory); + + /* Set up the Hyperspace PDE */ + PageDir->Pde[HyperspacePageTableIndex].Valid = 1; + PageDir->Pde[HyperspacePageTableIndex].Write = 1; + PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable); + + /* Set up the Apic PDE */ + PageDir->Pde[ApicPageTableIndex].Valid = 1; + PageDir->Pde[ApicPageTableIndex].Write = 1; + PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable); + + /* Set up the KPCR PDE */ + PageDir->Pde[KpcrPageTableIndex].Valid = 1; + PageDir->Pde[KpcrPageTableIndex].Write = 1; + PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable); + + /* Set up Low Memory PTEs */ + PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable; + for (i=0; i<1024; i++) { + + PageDir->Pde[i].Valid = 1; + PageDir->Pde[i].Write = 1; + PageDir->Pde[i].Owner = 1; + PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE); + } + + /* Set up Kernel PTEs */ + PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable; + for (i=0; i<1536; i++) { + + PageDir->Pde[i].Valid = 1; + PageDir->Pde[i].Write = 1; + PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE); + } + + /* Set up APIC PTEs */ + PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable; + PageDir->Pde[0].Valid = 1; + PageDir->Pde[0].Write = 1; + PageDir->Pde[0].CacheDisable = 1; + PageDir->Pde[0].WriteThrough = 1; + PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE); + PageDir->Pde[0x200].Valid = 1; + PageDir->Pde[0x200].Write = 1; + PageDir->Pde[0x200].CacheDisable = 1; + PageDir->Pde[0x200].WriteThrough = 1; + PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS); + + /* Set up KPCR PTEs */ + PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable; + PageDir->Pde[0].Valid = 1; + PageDir->Pde[0].Write = 1; + PageDir->Pde[0].PageFrameNumber = 1; + } + return; +} + +/*++ + * FrLdrMapKernel + * INTERNAL + * + * Maps the Kernel into memory, does PE Section Mapping, initalizes the + * uninitialized data sections, and relocates the image. + * + * Params: + * KernelImage - FILE Structure representing the ntoskrnl image file. + * + * Returns: + * TRUE if the Kernel was mapped. + * + * Remarks: + * None. + * + *--*/ +BOOL +STDCALL +FrLdrMapKernel(FILE *KernelImage) +{ + PIMAGE_DOS_HEADER ImageHeader; + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_SECTION_HEADER Section; + ULONG SectionCount; + ULONG ImageSize; + ULONG_PTR SourceSection; + ULONG_PTR TargetSection; + ULONG SectionSize; + LONG i; + + /* Allocate 1024 bytes for PE Header */ + ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024); + + /* Make sure it was succesful */ + if (ImageHeader == NULL) { + + return FALSE; + } + + /* Load the first 1024 bytes of the kernel image so we can read the PE header */ + if (!FsReadFile(KernelImage, 1024, NULL, ImageHeader)) { + + /* Fail if we couldn't read */ + MmFreeMemory(ImageHeader); + return FALSE; + } + + /* Now read the MZ header to get the offset to the PE Header */ + NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew); + + /* Save the Image Base */ + KernelBase = NtHeader->OptionalHeader.ImageBase; + + /* Save Entrypoint */ + KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint); + + /* Save the Image Size */ + ImageSize = NtHeader->OptionalHeader.SizeOfImage; + + /* Free the Header */ + MmFreeMemory(ImageHeader); + + /* Set the file pointer to zero */ + FsSetFilePointer(KernelImage, 0); + + /* Load the file image */ + FsReadFile(KernelImage, ImageSize, NULL, (PVOID)KERNEL_BASE_PHYS); + + /* Reload the NT Header */ + NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KERNEL_BASE_PHYS + ImageHeader->e_lfanew); + + /* Load the first section */ + Section = IMAGE_FIRST_SECTION(NtHeader); + SectionCount = NtHeader->FileHeader.NumberOfSections - 1; + + /* Now go to the last section */ + Section += SectionCount; + + /* Walk each section backwards */ + for (i=SectionCount; i >= 0; i--, Section--) { + + /* Get the disk location and the memory location, and the size */ + SourceSection = RaToPa(Section->PointerToRawData); + TargetSection = RaToPa(Section->VirtualAddress); + SectionSize = Section->SizeOfRawData; + + /* If the section is already mapped correctly, go to the next */ + if (SourceSection == TargetSection) continue; + + /* Load it into memory */ + memmove((PVOID)TargetSection, (PVOID)SourceSection, SectionSize); + + /* Check for unitilizated data */ + if (Section->SizeOfRawData < Section->Misc.VirtualSize) { + + /* Zero it out */ + memset((PVOID)RaToPa(Section->VirtualAddress + Section->SizeOfRawData), + 0, + Section->Misc.VirtualSize - Section->SizeOfRawData); + } + } + + /* Now relocate the file */ + /* FIXME: ADD RELOC CODE */ + + /* Increase the next Load Base */ + NextModuleBase = ROUND_UP(KERNEL_BASE_PHYS + ImageSize, PAGE_SIZE); + + /* Return Success */ + return TRUE; +} + +ULONG_PTR +STDCALL +FrLdrLoadModule(FILE *ModuleImage, + LPSTR ModuleName, + PULONG ModuleSize) +{ + ULONG LocalModuleSize; + PFRLDR_MODULE ModuleData; + LPSTR NameBuffer; + LPSTR TempName; + + /* Get current module data structure and module name string array */ + ModuleData = &multiboot_modules[LoaderBlock.ModsCount]; + + /* Get only the Module Name */ + do { + + TempName = strchr(ModuleName, '\\'); + + if(TempName) { + ModuleName = TempName + 1; + } + + } while(TempName); + NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount]; + + /* Get Module Size */ + LocalModuleSize = FsGetFileSize(ModuleImage); + + /* Fill out Module Data Structure */ + ModuleData->ModuleStart = NextModuleBase; + ModuleData->ModuleEnd = NextModuleBase + LocalModuleSize; + + /* Save name */ + strcpy(NameBuffer, ModuleName); + ModuleData->ModuleName = NameBuffer; + + /* Load the file image */ + FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase); + + /* Move to next memory block and increase Module Count */ + NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE); + LoaderBlock.ModsCount++; + + /* Return Module Size if required */ + if (ModuleSize != NULL) { + *ModuleSize = LocalModuleSize; + } + + return(ModuleData->ModuleStart); +} + +ULONG_PTR +STDCALL +FrLdrCreateModule(LPSTR ModuleName) +{ + PFRLDR_MODULE ModuleData; + LPSTR NameBuffer; + + /* Get current module data structure and module name string array */ + ModuleData = &multiboot_modules[LoaderBlock.ModsCount]; + NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount]; + + /* Set up the structure */ + ModuleData->ModuleStart = NextModuleBase; + ModuleData->ModuleEnd = -1; + + /* Copy the name */ + strcpy(NameBuffer, ModuleName); + ModuleData->ModuleName = NameBuffer; + + /* Set the current Module */ + CurrentModule = ModuleData; + + /* Return Module Base Address */ + return(ModuleData->ModuleStart); +} + +BOOL +STDCALL +FrLdrCloseModule(ULONG_PTR ModuleBase, + ULONG ModuleSize) +{ + PFRLDR_MODULE ModuleData = CurrentModule; + + /* Make sure a module is opened */ + if (ModuleData) { + + /* Make sure this is the right module and that it hasn't been closed */ + if ((ModuleBase == ModuleData->ModuleStart) && (ModuleData->ModuleEnd == -1)) { + + /* Close the Module */ + ModuleData->ModuleEnd = ModuleData->ModuleStart + ModuleSize; + + /* Set the next Module Base and increase the number of modules */ + NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE); + LoaderBlock.ModsCount++; + + /* Close the currently opened module */ + CurrentModule = NULL; + + /* Success */ + return(TRUE); + } + } + + /* Failure path */ + return(FALSE); } diff --git a/reactos/boot/freeldr/freeldr/options.c b/reactos/boot/freeldr/freeldr/options.c index e56480c4703..4260283905f 100644 --- a/reactos/boot/freeldr/freeldr/options.c +++ b/reactos/boot/freeldr/freeldr/options.c @@ -67,11 +67,11 @@ enum OptionMenuItems REBOOT = 11, }; -U32 OptionsMenuItemCount = sizeof(OptionsMenuList) / sizeof(OptionsMenuList[0]); +ULONG OptionsMenuItemCount = sizeof(OptionsMenuList) / sizeof(OptionsMenuList[0]); VOID DoOptionsMenu(VOID) { - U32 SelectedMenuItem; + ULONG SelectedMenuItem; if (!UiDisplayMenu(OptionsMenuList, OptionsMenuItemCount, 0, -1, &SelectedMenuItem, TRUE, NULL)) { diff --git a/reactos/boot/freeldr/freeldr/oslist.c b/reactos/boot/freeldr/freeldr/oslist.c index 8c2c5b5eb45..4dbe7ed13f8 100644 --- a/reactos/boot/freeldr/freeldr/oslist.c +++ b/reactos/boot/freeldr/freeldr/oslist.c @@ -24,16 +24,16 @@ #include #include -BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, U32* OperatingSystemCountPointer) +BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG* OperatingSystemCountPointer) { - U32 Idx; - U32 CurrentOperatingSystemIndex; + ULONG Idx; + ULONG CurrentOperatingSystemIndex; UCHAR SettingName[260]; UCHAR SettingValue[260]; - U32 OperatingSystemCount; - U32 SectionId; - U32 OperatingSystemSectionId; - U32 SectionSettingCount; + ULONG OperatingSystemCount; + ULONG SectionId; + ULONG OperatingSystemSectionId; + ULONG SectionSettingCount; PUCHAR *OperatingSystemSectionNames; PUCHAR *OperatingSystemDisplayNames; @@ -85,13 +85,13 @@ BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNames return TRUE; } -U32 CountOperatingSystems(U32 SectionId) +ULONG CountOperatingSystems(ULONG SectionId) { - U32 Idx; + ULONG Idx; UCHAR SettingName[260]; UCHAR SettingValue[260]; - U32 OperatingSystemCount = 0; - U32 SectionSettingCount; + ULONG OperatingSystemCount = 0; + ULONG SectionSettingCount; // // Loop through and count the operating systems @@ -115,9 +115,9 @@ U32 CountOperatingSystems(U32 SectionId) return OperatingSystemCount; } -BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, U32 OperatingSystemCount) +BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount) { - U32 Idx; + ULONG Idx; PUCHAR *OperatingSystemSectionNames = NULL; PUCHAR *OperatingSystemDisplayNames = NULL; diff --git a/reactos/boot/freeldr/freeldr/reactos/arcname.c b/reactos/boot/freeldr/freeldr/reactos/arcname.c index 94304459cab..9b1f1487cca 100644 --- a/reactos/boot/freeldr/freeldr/reactos/arcname.c +++ b/reactos/boot/freeldr/freeldr/reactos/arcname.c @@ -23,7 +23,7 @@ #include -BOOL DissectArcPath(char *ArcPath, char *BootPath, U32* BootDrive, U32* BootPartition) +BOOL DissectArcPath(char *ArcPath, char *BootPath, ULONG* BootDrive, ULONG* BootPartition) { char *p; @@ -73,7 +73,7 @@ BOOL DissectArcPath(char *ArcPath, char *BootPath, U32* BootDrive, U32* BootPart return TRUE; } -void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, U32 Disk, U32 Partition) +void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, ULONG Disk, ULONG Partition) { char tmp[50]; @@ -109,10 +109,10 @@ void ConstructArcPath(PUCHAR ArcPath, PUCHAR SystemFolder, U32 Disk, U32 Partiti } } -U32 ConvertArcNameToBiosDriveNumber(PUCHAR ArcPath) +ULONG ConvertArcNameToBiosDriveNumber(PUCHAR ArcPath) { char * p; - U32 DriveNumber = 0; + ULONG DriveNumber = 0; if (strnicmp(ArcPath, "multi(0)disk(0)", 15) != 0) return 0; diff --git a/reactos/boot/freeldr/freeldr/reactos/binhive.c b/reactos/boot/freeldr/freeldr/reactos/binhive.c index 60f7329253c..8a94e812a8e 100644 --- a/reactos/boot/freeldr/freeldr/reactos/binhive.c +++ b/reactos/boot/freeldr/freeldr/reactos/binhive.c @@ -45,119 +45,119 @@ /* BLOCK_OFFSET = offset in file after header block */ -typedef U32 BLOCK_OFFSET, *PBLOCK_OFFSET; +typedef ULONG BLOCK_OFFSET, *PBLOCK_OFFSET; /* header for registry hive file : */ typedef struct _HIVE_HEADER { /* Hive identifier "regf" (0x66676572) */ - U32 BlockId; + ULONG BlockId; /* Update counter */ - U32 UpdateCounter1; + ULONG UpdateCounter1; /* Update counter */ - U32 UpdateCounter2; + ULONG UpdateCounter2; /* When this hive file was last modified */ - U64 DateModified; /* FILETIME */ + ULONGLONG DateModified; /* FILETIME */ /* Registry format version ? (1?) */ - U32 Unused3; + ULONG Unused3; /* Registry format version ? (3?) */ - U32 Unused4; + ULONG Unused4; /* Registry format version ? (0?) */ - U32 Unused5; + ULONG Unused5; /* Registry format version ? (1?) */ - U32 Unused6; + ULONG Unused6; /* Offset into file from the byte after the end of the base block. If the hive is volatile, this is the actual pointer to the KEY_CELL */ BLOCK_OFFSET RootKeyOffset; /* Size of each hive block ? */ - U32 BlockSize; + ULONG BlockSize; /* (1?) */ - U32 Unused7; + ULONG Unused7; /* Name of hive file */ WCHAR FileName[64]; /* ? */ - U32 Unused8[83]; + ULONG Unused8[83]; /* Checksum of first 0x200 bytes */ - U32 Checksum; + ULONG Checksum; } __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER; typedef struct _BIN_HEADER { /* Bin identifier "hbin" (0x6E696268) */ - U32 HeaderId; + ULONG HeaderId; /* Bin offset */ BLOCK_OFFSET BinOffset; /* Size in bytes, multiple of the block size (4KB) */ - U32 BinSize; + ULONG BinSize; /* ? */ - U32 Unused1; + ULONG Unused1; /* When this bin was last modified */ - U64 DateModified; /* FILETIME */ + ULONGLONG DateModified; /* FILETIME */ /* ? */ - U32 Unused2; + ULONG Unused2; } __attribute__((packed)) HBIN, *PHBIN; typedef struct _CELL_HEADER { /* <0 if used, >0 if free */ - S32 CellSize; + LONG CellSize; } __attribute__((packed)) CELL_HEADER, *PCELL_HEADER; typedef struct _KEY_CELL { /* Size of this cell */ - S32 CellSize; + LONG CellSize; /* Key cell identifier "kn" (0x6b6e) */ - U16 Id; + USHORT Id; /* ? */ - U16 Type; + USHORT Type; /* Time of last flush */ - U64 LastWriteTime; /* FILETIME */ + ULONGLONG LastWriteTime; /* FILETIME */ /* ? */ - U32 UnUsed1; + ULONG UnUsed1; /* Block offset of parent key cell */ BLOCK_OFFSET ParentKeyOffset; /* Count of sub keys for the key in this key cell */ - U32 NumberOfSubKeys; + ULONG NumberOfSubKeys; /* ? */ - U32 UnUsed2; + ULONG UnUsed2; /* Block offset of has table for FIXME: subkeys/values? */ BLOCK_OFFSET HashTableOffset; /* ? */ - U32 UnUsed3; + ULONG UnUsed3; /* Count of values contained in this key cell */ - U32 NumberOfValues; + ULONG NumberOfValues; /* Block offset of VALUE_LIST_CELL */ BLOCK_OFFSET ValueListOffset; @@ -169,16 +169,16 @@ typedef struct _KEY_CELL BLOCK_OFFSET ClassNameOffset; /* ? */ - U32 Unused4[5]; + ULONG Unused4[5]; /* Size in bytes of key name */ - U16 NameSize; + USHORT NameSize; /* Size of class name in bytes */ - U16 ClassSize; + USHORT ClassSize; /* Name of key (not zero terminated) */ - U8 Name[0]; + UCHAR Name[0]; } __attribute__((packed)) KEY_CELL, *PKEY_CELL; @@ -193,36 +193,36 @@ typedef struct _KEY_CELL typedef struct _HASH_RECORD { BLOCK_OFFSET KeyOffset; - U32 HashValue; + ULONG HashValue; } __attribute__((packed)) HASH_RECORD, *PHASH_RECORD; typedef struct _HASH_TABLE_CELL { - S32 CellSize; - U16 Id; - U16 HashTableSize; + LONG CellSize; + USHORT Id; + USHORT HashTableSize; HASH_RECORD Table[0]; } __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL; typedef struct _VALUE_LIST_CELL { - S32 CellSize; + LONG CellSize; BLOCK_OFFSET ValueOffset[0]; } __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL; typedef struct _VALUE_CELL { - S32 CellSize; - U16 Id; // "kv" - U16 NameSize; // length of Name - U32 DataSize; // length of datas in the cell pointed by DataOffset + LONG CellSize; + USHORT Id; // "kv" + USHORT NameSize; // length of Name + ULONG DataSize; // length of datas in the cell pointed by DataOffset BLOCK_OFFSET DataOffset;// datas are here if high bit of DataSize is set - U32 DataType; - U16 Flags; - U16 Unused1; + ULONG DataType; + USHORT Flags; + USHORT Unused1; UCHAR Name[0]; /* warning : not zero terminated */ } __attribute__((packed)) VALUE_CELL, *PVALUE_CELL; @@ -236,26 +236,26 @@ typedef struct _VALUE_CELL typedef struct _DATA_CELL { - S32 CellSize; + LONG CellSize; UCHAR Data[0]; } __attribute__((packed)) DATA_CELL, *PDATA_CELL; typedef struct _REGISTRY_HIVE { - U32 FileSize; + ULONG FileSize; PHIVE_HEADER HiveHeader; - U32 BlockListSize; + ULONG BlockListSize; PHBIN *BlockList; - U32 FreeListSize; - U32 FreeListMax; + ULONG FreeListSize; + ULONG FreeListMax; PCELL_HEADER *FreeList; BLOCK_OFFSET *FreeListOffset; } REGISTRY_HIVE, *PREGISTRY_HIVE; static PVOID MbBase = NULL; -static U32 MbSize = 0; +static ULONG MbSize = 0; /* FUNCTIONS ****************************************************************/ @@ -268,13 +268,13 @@ InitMbMemory (PVOID ChunkBase) static PVOID -AllocateMbMemory (U32 MemSize) +AllocateMbMemory (ULONG MemSize) { PVOID CurBase; CurBase = MbBase; - MbBase = (PVOID)((U32)MbBase + MemSize); + MbBase = (PVOID)((ULONG)MbBase + MemSize); MbSize += MemSize; return CurBase; @@ -286,7 +286,7 @@ FreeMbMemory (VOID) MbSize = 0; } -static U32 +static ULONG GetMbAllocatedSize (VOID) { return MbSize; @@ -329,8 +329,8 @@ static VOID CmiCreateDefaultRootKeyCell (PKEY_CELL RootKeyCell, PCHAR KeyName) { PCHAR BaseKeyName; - U32 NameSize; - U32 CellSize; + ULONG NameSize; + ULONG CellSize; assert (RootKeyCell); @@ -428,12 +428,12 @@ CmiCreateHive (PCHAR KeyName) BinCell->BinOffset = 0; /* Init root key cell */ - RootKeyCell = (PKEY_CELL)((U32)BinCell + REG_HBIN_DATA_OFFSET); + RootKeyCell = (PKEY_CELL)((ULONG)BinCell + REG_HBIN_DATA_OFFSET); CmiCreateDefaultRootKeyCell(RootKeyCell, KeyName); Hive->HiveHeader->RootKeyOffset = REG_HBIN_DATA_OFFSET; /* Init free cell */ - FreeCell = (PCELL_HEADER)((U32)RootKeyCell - RootKeyCell->CellSize); + FreeCell = (PCELL_HEADER)((ULONG)RootKeyCell - RootKeyCell->CellSize); FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET - RootKeyCell->CellSize); Hive->FreeList[0] = FreeCell; @@ -463,9 +463,9 @@ static PHBIN CmiGetBin (PREGISTRY_HIVE Hive, BLOCK_OFFSET BlockOffset) { - U32 BlockIndex; + ULONG BlockIndex; - if (BlockOffset == (U32) -1) + if (BlockOffset == (ULONG) -1) return NULL; BlockIndex = BlockOffset / REG_BLOCK_SIZE; @@ -483,10 +483,10 @@ CmiMergeFree(PREGISTRY_HIVE RegistryHive, { BLOCK_OFFSET BlockOffset; BLOCK_OFFSET BinOffset; - U32 BlockSize; - U32 BinSize; + ULONG BlockSize; + ULONG BinSize; PHBIN Bin; - U32 i; + ULONG i; DbgPrint((DPRINT_REGISTRY, "CmiMergeFree(Block %lx Offset %lx Size %lx) called\n", FreeBlock, FreeOffset, FreeBlock->CellSize)); @@ -574,9 +574,9 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive, { PCELL_HEADER *tmpList; BLOCK_OFFSET *tmpListOffset; - S32 minInd; - S32 maxInd; - S32 medInd; + LONG minInd; + LONG maxInd; + LONG medInd; assert(RegistryHive); assert(FreeBlock); @@ -675,15 +675,15 @@ CmiAddFree(PREGISTRY_HIVE RegistryHive, static BOOL CmiAddBin(PREGISTRY_HIVE RegistryHive, - U32 BlockCount, + ULONG BlockCount, PVOID *NewBlock, PBLOCK_OFFSET NewBlockOffset) { PCELL_HEADER tmpBlock; PHBIN *BlockList; PHBIN tmpBin; - U32 BinSize; - U32 i; + ULONG BinSize; + ULONG i; BinSize = BlockCount * REG_BLOCK_SIZE; tmpBin = AllocateMbMemory (BinSize); @@ -722,7 +722,7 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive, RegistryHive->BlockListSize += BlockCount; /* Initialize a free block in this heap : */ - tmpBlock = (PCELL_HEADER)((U32) tmpBin + REG_HBIN_DATA_OFFSET); + tmpBlock = (PCELL_HEADER)((ULONG) tmpBin + REG_HBIN_DATA_OFFSET); tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET); *NewBlock = (PVOID) tmpBlock; @@ -736,12 +736,12 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive, static BOOL CmiAllocateCell (PREGISTRY_HIVE RegistryHive, - S32 CellSize, + LONG CellSize, PVOID *Block, PBLOCK_OFFSET pBlockOffset) { PCELL_HEADER NewBlock; - U32 i; + ULONG i; *Block = NULL; @@ -790,7 +790,7 @@ CmiAllocateCell (PREGISTRY_HIVE RegistryHive, /* Split the block in two parts */ if (NewBlock->CellSize > CellSize) { - NewBlock = (PCELL_HEADER) ((U32)NewBlock + CellSize); + NewBlock = (PCELL_HEADER) ((ULONG)NewBlock + CellSize); NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - CellSize; CmiAddFree (RegistryHive, NewBlock, @@ -814,9 +814,9 @@ CmiGetCell (PREGISTRY_HIVE Hive, BLOCK_OFFSET BlockOffset) { PHBIN Bin; - U32 BlockIndex; + ULONG BlockIndex; - if (BlockOffset == (U32) -1) + if (BlockOffset == (ULONG) -1) return NULL; BlockIndex = BlockOffset / REG_BLOCK_SIZE; @@ -827,17 +827,17 @@ CmiGetCell (PREGISTRY_HIVE Hive, if (Bin == NULL) return NULL; - return (PVOID)((U32)Bin + (BlockOffset - Bin->BinOffset)); + return (PVOID)((ULONG)Bin + (BlockOffset - Bin->BinOffset)); } static BOOL CmiAllocateHashTableCell (PREGISTRY_HIVE Hive, PBLOCK_OFFSET HBOffset, - U32 SubKeyCount) + ULONG SubKeyCount) { PHASH_TABLE_CELL HashCell; - U32 NewHashSize; + ULONG NewHashSize; BOOL Status; NewHashSize = sizeof(HASH_TABLE_CELL) + @@ -866,7 +866,7 @@ CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive, { PHASH_TABLE_CELL HashBlock; PKEY_CELL ParentKeyCell; - U32 i; + ULONG i; ParentKeyCell = CmiGetCell (Hive, ParentKeyOffset); if (ParentKeyCell == NULL) @@ -902,10 +902,10 @@ CmiAddKeyToParentHashTable (PREGISTRY_HIVE Hive, static BOOL CmiAllocateValueListCell (PREGISTRY_HIVE Hive, PBLOCK_OFFSET ValueListOffset, - U32 ValueCount) + ULONG ValueCount) { PVALUE_LIST_CELL ValueListCell; - U32 ValueListSize; + ULONG ValueListSize; BOOL Status; ValueListSize = sizeof(VALUE_LIST_CELL) + @@ -931,7 +931,7 @@ CmiAllocateValueCell(PREGISTRY_HIVE Hive, PCHAR ValueName) { PVALUE_CELL NewValueCell; - U32 NameSize; + ULONG NameSize; BOOL Status; NameSize = (ValueName == NULL) ? 0 : strlen (ValueName); @@ -996,9 +996,9 @@ CmiAddValueToKeyValueList(PREGISTRY_HIVE Hive, static VOID memexpand (PWCHAR Dst, PCHAR Src, - U32 Length) + ULONG Length) { - U32 i; + ULONG i; for (i = 0; i < Length; i++) Dst[i] = (WCHAR)Src[i]; @@ -1008,16 +1008,16 @@ memexpand (PWCHAR Dst, static BOOL CmiExportValue (PREGISTRY_HIVE Hive, BLOCK_OFFSET KeyCellOffset, - HKEY Key, + FRLDRHKEY Key, PVALUE Value) { BLOCK_OFFSET ValueCellOffset; BLOCK_OFFSET DataCellOffset; PVALUE_CELL ValueCell; PDATA_CELL DataCell; - U32 SrcDataSize; - U32 DstDataSize; - U32 DataType; + ULONG SrcDataSize; + ULONG DstDataSize; + ULONG DataType; PUCHAR Data; BOOL Expand = FALSE; @@ -1121,16 +1121,16 @@ CmiExportValue (PREGISTRY_HIVE Hive, static BOOL CmiExportSubKey (PREGISTRY_HIVE Hive, BLOCK_OFFSET ParentKeyOffset, - HKEY ParentKey, - HKEY Key) + FRLDRHKEY ParentKey, + FRLDRHKEY Key) { BLOCK_OFFSET NKBOffset; PKEY_CELL NewKeyCell; - U32 KeyCellSize; - U32 SubKeyCount; - U32 ValueCount; + ULONG KeyCellSize; + ULONG SubKeyCount; + ULONG ValueCount; PLIST_ENTRY Entry; - HKEY SubKey; + FRLDRHKEY SubKey; PVALUE Value; DbgPrint((DPRINT_REGISTRY, "CmiExportSubKey('%s') called\n", Key->Name)); @@ -1243,11 +1243,11 @@ CmiExportSubKey (PREGISTRY_HIVE Hive, static VOID CmiCalcHiveChecksum (PREGISTRY_HIVE Hive) { - U32 *Buffer; - U32 Sum; - U32 i; + ULONG *Buffer; + ULONG Sum; + ULONG i; - Buffer = (U32*)Hive->HiveHeader; + Buffer = (ULONG*)Hive->HiveHeader; Sum = 0; for (i = 0; i < 127; i++) Sum += Buffer[i]; @@ -1261,11 +1261,11 @@ CmiExportHive (PREGISTRY_HIVE Hive, PCHAR KeyName) { PKEY_CELL KeyCell; - HKEY Key; - U32 SubKeyCount; - U32 ValueCount; + FRLDRHKEY Key; + ULONG SubKeyCount; + ULONG ValueCount; PLIST_ENTRY Entry; - HKEY SubKey; + FRLDRHKEY SubKey; PVALUE Value; DbgPrint((DPRINT_REGISTRY, "CmiExportHive(%x, '%s') called\n", Hive, KeyName)); @@ -1354,16 +1354,16 @@ CmiExportHive (PREGISTRY_HIVE Hive, static BOOL RegImportValue (PHBIN RootBin, PVALUE_CELL ValueCell, - HKEY Key) + FRLDRHKEY Key) { PDATA_CELL DataCell; PWCHAR wName; PCHAR cName; - S32 Error; - S32 DataSize; + LONG Error; + LONG DataSize; PCHAR cBuffer; PWCHAR wBuffer; - S32 i; + LONG i; if (ValueCell->CellSize >= 0 || ValueCell->Id != REG_VALUE_CELL_ID) { @@ -1461,16 +1461,16 @@ RegImportValue (PHBIN RootBin, static BOOL RegImportSubKey(PHBIN RootBin, PKEY_CELL KeyCell, - HKEY ParentKey) + FRLDRHKEY ParentKey) { PHASH_TABLE_CELL HashCell; PKEY_CELL SubKeyCell; PVALUE_LIST_CELL ValueListCell; PVALUE_CELL ValueCell = NULL; PCHAR cName; - HKEY SubKey; - S32 Error; - U32 i; + FRLDRHKEY SubKey; + LONG Error; + ULONG i; DbgPrint((DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell)); @@ -1548,16 +1548,16 @@ RegImportSubKey(PHBIN RootBin, BOOL RegImportBinaryHive(PCHAR ChunkBase, - U32 ChunkSize) + ULONG ChunkSize) { PHIVE_HEADER HiveHeader; PHBIN RootBin; PKEY_CELL KeyCell; PHASH_TABLE_CELL HashCell; PKEY_CELL SubKeyCell; - HKEY SystemKey; - U32 i; - S32 Error; + FRLDRHKEY SystemKey; + ULONG i; + LONG Error; DbgPrint((DPRINT_REGISTRY, "RegImportBinaryHive(%x, %u) called\n",ChunkBase,ChunkSize)); @@ -1569,7 +1569,7 @@ RegImportBinaryHive(PCHAR ChunkBase, return FALSE; } - RootBin = (PHBIN)((U32)HiveHeader + REG_BLOCK_SIZE); + RootBin = (PHBIN)((ULONG)HiveHeader + REG_BLOCK_SIZE); DbgPrint((DPRINT_REGISTRY, "RootBin: %x\n", RootBin)); if (RootBin->HeaderId != REG_BIN_ID || RootBin->BinSize == 0) { @@ -1577,7 +1577,7 @@ RegImportBinaryHive(PCHAR ChunkBase, return FALSE; } - KeyCell = (PKEY_CELL)((U32)RootBin + REG_HBIN_DATA_OFFSET); + KeyCell = (PKEY_CELL)((ULONG)RootBin + REG_HBIN_DATA_OFFSET); DbgPrint((DPRINT_REGISTRY, "KeyCell: %x\n", KeyCell)); DbgPrint((DPRINT_REGISTRY, "KeyCell->CellSize: %x\n", KeyCell->CellSize)); DbgPrint((DPRINT_REGISTRY, "KeyCell->Id: %x\n", KeyCell->Id)); @@ -1603,14 +1603,14 @@ RegImportBinaryHive(PCHAR ChunkBase, /* Enumerate and add subkeys */ if (KeyCell->NumberOfSubKeys > 0) { - HashCell = (PHASH_TABLE_CELL)((U32)RootBin + KeyCell->HashTableOffset); + HashCell = (PHASH_TABLE_CELL)((ULONG)RootBin + KeyCell->HashTableOffset); DbgPrint((DPRINT_REGISTRY, "HashCell: %x\n", HashCell)); for (i = 0; i < KeyCell->NumberOfSubKeys; i++) { DbgPrint((DPRINT_REGISTRY, "KeyOffset[%d]: %x\n", i, HashCell->Table[i].KeyOffset)); - SubKeyCell = (PKEY_CELL)((U32)RootBin + HashCell->Table[i].KeyOffset); + SubKeyCell = (PKEY_CELL)((ULONG)RootBin + HashCell->Table[i].KeyOffset); DbgPrint((DPRINT_REGISTRY, "SubKeyCell[%d]: %x\n", i, SubKeyCell)); @@ -1626,7 +1626,7 @@ RegImportBinaryHive(PCHAR ChunkBase, BOOL RegExportBinaryHive(PCHAR KeyName, PCHAR ChunkBase, - U32* ChunkSize) + ULONG* ChunkSize) { PREGISTRY_HIVE Hive; diff --git a/reactos/boot/freeldr/freeldr/reactos/reactos.c b/reactos/boot/freeldr/freeldr/reactos/reactos.c index fda39008d78..427f34e6c23 100644 --- a/reactos/boot/freeldr/freeldr/reactos/reactos.c +++ b/reactos/boot/freeldr/freeldr/reactos/reactos.c @@ -1,40 +1,19 @@ /* - * FreeLoader - * - * Copyright (C) 1998-2003 Brian Palmer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Freeloader + * FILE: boot/freeldr/freeldr/reactos/rosboot.c + * PURPOSE: ReactOS Loader + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include "registry.h" - #define NDEBUG +#include #define IsRecognizedPartition(P) \ ((P) == PARTITION_FAT_12 || \ @@ -46,549 +25,561 @@ (P) == PARTITION_FAT32_XINT13 || \ (P) == PARTITION_XINT13) -static BOOL -LoadKernel(PCHAR szFileName, int nPos) +BOOL +STDCALL +FrLdrLoadKernel(PCHAR szFileName, + INT nPos) { - PFILE FilePointer; - PCHAR szShortName; - char szBuffer[256]; + PFILE FilePointer; + PCHAR szShortName; + CHAR szBuffer[256]; - szShortName = strrchr(szFileName, '\\'); - if (szShortName == NULL) - szShortName = szFileName; - else - szShortName = szShortName + 1; - - FilePointer = FsOpenFile(szFileName); - if (FilePointer == NULL) - { - strcpy(szBuffer, szShortName); - strcat(szBuffer, " not found."); - UiMessageBox(szBuffer); - return(FALSE); + /* Extract Kernel filename without path */ + szShortName = strrchr(szFileName, '\\'); + if (szShortName == NULL) { + + /* No path, leave it alone */ + szShortName = szFileName; + + } else { + + /* Skip the path */ + szShortName = szShortName + 1; } - /* - * Update the status bar with the current file - */ - strcpy(szBuffer, "Reading "); - strcat(szBuffer, szShortName); - UiDrawStatusText(szBuffer); - - /* - * Load the kernel - */ - MultiBootLoadKernel(FilePointer); - - UiDrawProgressBarCenter(nPos, 100, "Loading ReactOS..."); - - return(TRUE); -} - -static BOOL -LoadSymbolFile(PCHAR szSystemRoot, - PCHAR ModuleName, - int nPos) -{ - CHAR SymbolFileName[1024]; - PFILE FilePointer; - U32 Length; - PCHAR Start; - PCHAR Ext; - char value[256]; - char *p; - - /* Get the path to the symbol store */ - strcpy(SymbolFileName, szSystemRoot); - strcat(SymbolFileName, "symbols\\"); - - /* Get the symbol filename from the module name */ - Start = strrchr(ModuleName, '\\'); - if (Start == NULL) - Start = ModuleName; - else - Start++; - - Ext = strrchr(ModuleName, '.'); - if (Ext != NULL) - Length = Ext - Start; - else - Length = strlen(Start); - - strncat(SymbolFileName, Start, Length); - strcat(SymbolFileName, ".sym"); - - FilePointer = FsOpenFile((PCHAR)&SymbolFileName[0]); - if (FilePointer == NULL) - { - DbgPrint((DPRINT_REACTOS, "Symbol file %s not loaded.\n", SymbolFileName)); - /* This is not critical */ - return FALSE; + /* Open the Kernel */ + FilePointer = FsOpenFile(szFileName); + + /* Make sure it worked */ + if (FilePointer == NULL) { + + /* Return failure on the short name */ + strcpy(szBuffer, szShortName); + strcat(szBuffer, " not found."); + UiMessageBox(szBuffer); + return(FALSE); } - DbgPrint((DPRINT_REACTOS, "Symbol file %s is loaded.\n", SymbolFileName)); + /* Update the status bar with the current file */ + strcpy(szBuffer, "Reading "); + strcat(szBuffer, szShortName); + UiDrawStatusText(szBuffer); - /* - * Update the status bar with the current file - */ - strcpy(value, "Reading "); - p = strrchr(SymbolFileName, '\\'); - if (p == NULL) - strcat(value, SymbolFileName); - else - strcat(value, p + 1); - UiDrawStatusText(value); + /* Do the actual loading */ + FrLdrMapKernel(FilePointer); - /* - * Load the symbol file - */ - MultiBootLoadModule(FilePointer, SymbolFileName, NULL); - - UiDrawProgressBarCenter(nPos, 100, "Loading ReactOS..."); - - return (TRUE); + /* Update Processbar and return success */ + UiDrawProgressBarCenter(nPos, 100, "Loading ReactOS..."); + return(TRUE); } - -static BOOL -LoadDriver(PCHAR szFileName, int nPos) -{ - PFILE FilePointer; - char value[256]; - char *p; - - FilePointer = FsOpenFile(szFileName); - if (FilePointer == NULL) - { - strcpy(value, szFileName); - strcat(value, " not found."); - UiMessageBox(value); - return(FALSE); - } - - /* - * Update the status bar with the current file - */ - strcpy(value, "Reading "); - p = strrchr(szFileName, '\\'); - if (p == NULL) - strcat(value, szFileName); - else - strcat(value, p + 1); - UiDrawStatusText(value); - - /* - * Load the driver - */ - MultiBootLoadModule(FilePointer, szFileName, NULL); - - UiDrawProgressBarCenter(nPos, 100, "Loading ReactOS..."); - - return(TRUE); -} - - -static BOOL -LoadNlsFile(PCHAR szFileName, PCHAR szModuleName) -{ - PFILE FilePointer; - char value[256]; - char *p; - - FilePointer = FsOpenFile(szFileName); - if (FilePointer == NULL) - { - strcpy(value, szFileName); - strcat(value, " not found."); - UiMessageBox(value); - return(FALSE); - } - - /* - * Update the status bar with the current file - */ - strcpy(value, "Reading "); - p = strrchr(szFileName, '\\'); - if (p == NULL) - strcat(value, szFileName); - else - strcat(value, p + 1); - UiDrawStatusText(value); - - /* - * Load the driver - */ - MultiBootLoadModule(FilePointer, szModuleName, NULL); - - return(TRUE); -} - - static VOID -LoadBootDrivers(PCHAR szSystemRoot, int nPos) +FreeldrFreeMem(PVOID Area) { - S32 rc = 0; - HKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey; - char GroupNameBuffer[512]; - char ServiceName[256]; - U32 OrderList[128]; - U32 BufferSize; - U32 Index; - U32 TagIndex; - char *GroupName; - - U32 ValueSize; - U32 ValueType; - U32 StartValue; - U32 TagValue; - UCHAR DriverGroup[256]; - U32 DriverGroupSize; - - UCHAR ImagePath[256]; - UCHAR TempImagePath[256]; - - /* get 'service group order' key */ - rc = RegOpenKey(NULL, - "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder", - &hGroupKey); - if (rc != ERROR_SUCCESS) - { - DbgPrint((DPRINT_REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc)); - return; - } - - /* get 'group order list' key */ - rc = RegOpenKey(NULL, - "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList", - &hOrderKey); - if (rc != ERROR_SUCCESS) - { - DbgPrint((DPRINT_REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc)); - return; - } - - /* enumerate drivers */ - rc = RegOpenKey(NULL, - "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services", - &hServiceKey); - if (rc != ERROR_SUCCESS) - { - DbgPrint((DPRINT_REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc)); - return; - } - - BufferSize = sizeof(GroupNameBuffer); - rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize); - DbgPrint((DPRINT_REACTOS, "RegQueryValue(): rc %d\n", (int)rc)); - if (rc != ERROR_SUCCESS) - return; - - DbgPrint((DPRINT_REACTOS, "BufferSize: %d \n", (int)BufferSize)); - - DbgPrint((DPRINT_REACTOS, "GroupNameBuffer: '%s' \n", GroupNameBuffer)); - - GroupName = GroupNameBuffer; - while (*GroupName) - { - DbgPrint((DPRINT_REACTOS, "Driver group: '%s'\n", GroupName)); - - BufferSize = sizeof(OrderList); - rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize); - if (rc != ERROR_SUCCESS) - { - OrderList[0] = 0; - } - - for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) - { - /* enumerate all drivers */ - Index = 0; - while (TRUE) - { - ValueSize = sizeof(ServiceName); - rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); - DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc)); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - return; - DbgPrint((DPRINT_REACTOS, "Service %d: '%s'\n", (int)Index, ServiceName)); - - /* open driver Key */ - rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); - - ValueSize = sizeof(U32); - rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); - DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue)); - - ValueSize = sizeof(U32); - rc = RegQueryValue(hDriverKey, "Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); - if (rc != ERROR_SUCCESS) - { - TagValue = (U32)-1; - } - DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue)); - - - DriverGroupSize = 256; - rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); - DbgPrint((DPRINT_REACTOS, " Group: '%s' \n", DriverGroup)); - - if ((StartValue == 0) && (TagValue == OrderList[TagIndex]) &&(stricmp(DriverGroup, GroupName) == 0)) - { - ValueSize = 256; - rc = RegQueryValue(hDriverKey, - "ImagePath", - NULL, - (PUCHAR)TempImagePath, - &ValueSize); - if (rc != ERROR_SUCCESS) - { - DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n")); - strcpy(ImagePath, szSystemRoot); - strcat(ImagePath, "system32\\drivers\\"); - strcat(ImagePath, ServiceName); - strcat(ImagePath, ".sys"); - } - else if (TempImagePath[0] != '\\') - { - strcpy(ImagePath, szSystemRoot); - strcat(ImagePath, TempImagePath); - } - else - { - strcpy(ImagePath, TempImagePath); - DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath)); - } - DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath)); - - if (nPos < 100) - nPos += 5; - - LoadDriver(ImagePath, nPos); - LoadSymbolFile(szSystemRoot, ImagePath, nPos); - } - else - { - DbgPrint((DPRINT_REACTOS, " Skipping driver '%s' with Start %d, Tag %d and Group '%s' (Current Tag %d, current group '%s')\n", - ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName)); - } - Index++; - } - } - - Index = 0; - while (TRUE) - { - ValueSize = sizeof(ServiceName); - rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); - DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc)); - if (rc == ERROR_NO_MORE_ITEMS) - break; - if (rc != ERROR_SUCCESS) - return; - DbgPrint((DPRINT_REACTOS, "Service %d: '%s'\n", (int)Index, ServiceName)); - - /* open driver Key */ - rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); - - ValueSize = sizeof(U32); - rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); - DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue)); - - ValueSize = sizeof(U32); - rc = RegQueryValue(hDriverKey, "Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); - if (rc != ERROR_SUCCESS) - { - TagValue = (U32)-1; - } - DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue)); - - DriverGroupSize = 256; - rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); - DbgPrint((DPRINT_REACTOS, " Group: '%s' \n", DriverGroup)); - - for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) - { - if (TagValue == OrderList[TagIndex]) - break; - } - - if ((StartValue == 0) && (TagIndex > OrderList[0]) && (stricmp(DriverGroup, GroupName) == 0)) - { - ValueSize = 256; - rc = RegQueryValue(hDriverKey, - "ImagePath", - NULL, - (PUCHAR)TempImagePath, - &ValueSize); - if (rc != ERROR_SUCCESS) - { - DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n")); - strcpy(ImagePath, szSystemRoot); - strcat(ImagePath, "system32\\drivers\\"); - strcat(ImagePath, ServiceName); - strcat(ImagePath, ".sys"); - } - else if (TempImagePath[0] != '\\') - { - strcpy(ImagePath, szSystemRoot); - strcat(ImagePath, TempImagePath); - } - else - { - strcpy(ImagePath, TempImagePath); - DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath)); - } - DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath)); - - if (nPos < 100) - nPos += 5; - - LoadDriver(ImagePath, nPos); - LoadSymbolFile(szSystemRoot, ImagePath, nPos); - } - else - { - DbgPrint((DPRINT_REACTOS, " Skipping driver '%s' with Start %d, Tag %d and Group '%s' (Current group '%s')\n", - ServiceName, StartValue, TagValue, DriverGroup, GroupName)); - } - Index++; - } - - GroupName = GroupName + strlen(GroupName) + 1; - } + MmFreeMemory(Area); } +static PVOID +FreeldrAllocMem(ULONG_PTR Size) +{ + return MmAllocateMemory((ULONG) Size); +} + +static BOOLEAN +FreeldrReadFile(PVOID FileContext, PVOID Buffer, ULONG Size) +{ + ULONG BytesRead; + + return FsReadFile((PFILE) FileContext, (ULONG) Size, &BytesRead, Buffer) + && Size == BytesRead; +} + +static BOOLEAN +FreeldrSeekFile(PVOID FileContext, ULONG_PTR Position) +{ + FsSetFilePointer((PFILE) FileContext, (ULONG) Position); + return TRUE; +} static BOOL -LoadNlsFiles(PCHAR szSystemRoot, PCHAR szErrorOut) +LoadKernelSymbols(PCHAR szKernelName, int nPos) { - S32 rc = ERROR_SUCCESS; - HKEY hKey; - char szIdBuffer[80]; - char szNameBuffer[80]; - char szFileName[256]; - U32 BufferSize; + static ROSSYM_CALLBACKS FreeldrCallbacks = + { + FreeldrAllocMem, + FreeldrFreeMem, + FreeldrReadFile, + FreeldrSeekFile + }; + PFILE FilePointer; + PROSSYM_INFO RosSymInfo; + ULONG Size; + ULONG_PTR Base; - /* open the codepage key */ - rc = RegOpenKey(NULL, - "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage", - &hKey); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "Couldn't open CodePage registry key"); - return(FALSE); - } + RosSymInit(&FreeldrCallbacks); + FilePointer = FsOpenFile(szKernelName); + if (FilePointer == NULL) + { + return FALSE; + } + if (! RosSymCreateFromFile(FilePointer, &RosSymInfo)) + { + return FALSE; + } + Base = FrLdrCreateModule("NTOSKRNL.SYM"); + Size = RosSymGetRawDataLength(RosSymInfo); + RosSymGetRawData(RosSymInfo, (PVOID)Base); + FrLdrCloseModule(Base, Size); + RosSymDelete(RosSymInfo); + return TRUE; +} + +BOOL +FrLdrLoadNlsFile(PCHAR szFileName, + PCHAR szModuleName) +{ + PFILE FilePointer; + CHAR value[256]; + LPSTR p; - /* get ANSI codepage */ - BufferSize = 80; - rc = RegQueryValue(hKey, "ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "Couldn't get ACP NLS setting"); - return(FALSE); - } + /* Open the Driver */ + FilePointer = FsOpenFile(szFileName); + + /* Make sure we did */ + if (FilePointer == NULL) { + + /* Fail if file wasn't opened */ + strcpy(value, szFileName); + strcat(value, " not found."); + UiMessageBox(value); + return(FALSE); + } - BufferSize = 80; - rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable"); - return(FALSE); - } + /* Update the status bar with the current file */ + strcpy(value, "Reading "); + p = strrchr(szFileName, '\\'); + if (p == NULL) { + + strcat(value, szFileName); + + } else { + + strcat(value, p + 1); + } + UiDrawStatusText(value); - /* load ANSI codepage table */ - strcpy(szFileName, szSystemRoot); - strcat(szFileName, "system32\\"); - strcat(szFileName, szNameBuffer); - DbgPrint((DPRINT_REACTOS, "ANSI file: %s\n", szFileName)); - if (!LoadNlsFile(szFileName, "ansi.nls")) { - strcpy(szErrorOut, "Couldn't load ansi.nls"); - return(FALSE); - } - - /* get OEM codepage */ - BufferSize = 80; - rc = RegQueryValue(hKey, "OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "Couldn't get OEMCP NLS setting"); - return(FALSE); - } - - BufferSize = 80; - rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable"); - return(FALSE); - } - - /* load OEM codepage table */ - strcpy(szFileName, szSystemRoot); - strcat(szFileName, "system32\\"); - strcat(szFileName, szNameBuffer); - DbgPrint((DPRINT_REACTOS, "Oem file: %s\n", szFileName)); - if (!LoadNlsFile(szFileName, "oem.nls")) { - strcpy(szErrorOut, "Couldn't load oem.nls"); - return(FALSE); - } - - /* open the language key */ - rc = RegOpenKey(NULL, - "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", - &hKey); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "Couldn't open Language registry key"); - return(FALSE); - } - - /* get the Unicode case table */ - BufferSize = 80; - rc = RegQueryValue(hKey, "Default", NULL, (PUCHAR)szIdBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, "Couldn't get Language Default setting"); - return(FALSE); - } - - BufferSize = 80; - rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); - if (rc != ERROR_SUCCESS) { - strcpy(szErrorOut, - "Language Default setting exists, but isn't readable"); - return(FALSE); - } - - /* load Unicode case table */ - strcpy(szFileName, szSystemRoot); - strcat(szFileName, "system32\\"); - strcat(szFileName, szNameBuffer); - DbgPrint((DPRINT_REACTOS, "Casemap file: %s\n", szFileName)); - if (!LoadNlsFile(szFileName, "casemap.nls")) { - strcpy(szErrorOut, "casemap.nls"); - return(FALSE); - } - - return(TRUE); + /* Load the driver */ + FrLdrLoadModule(FilePointer, szModuleName, NULL); + return(TRUE); } +BOOL +FrLdrLoadNlsFiles(PCHAR szSystemRoot, + PCHAR szErrorOut) +{ + LONG rc = ERROR_SUCCESS; + FRLDRHKEY hKey; + CHAR szIdBuffer[80]; + CHAR szNameBuffer[80]; + CHAR szFileName[256]; + ULONG BufferSize; -void + /* open the codepage key */ + rc = RegOpenKey(NULL, + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage", + &hKey); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Couldn't open CodePage registry key"); + return(FALSE); + } + + /* get ANSI codepage */ + BufferSize = 80; + rc = RegQueryValue(hKey, "ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Couldn't get ACP NLS setting"); + return(FALSE); + } + + BufferSize = 80; + rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable"); + return(FALSE); + } + + /* load ANSI codepage table */ + strcpy(szFileName, szSystemRoot); + strcat(szFileName, "system32\\"); + strcat(szFileName, szNameBuffer); + DbgPrint((DPRINT_REACTOS, "ANSI file: %s\n", szFileName)); + if (!FrLdrLoadNlsFile(szFileName, "ansi.nls")) { + + strcpy(szErrorOut, "Couldn't load ansi.nls"); + return(FALSE); + } + + /* get OEM codepage */ + BufferSize = 80; + rc = RegQueryValue(hKey, "OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Couldn't get OEMCP NLS setting"); + return(FALSE); + } + + BufferSize = 80; + rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable"); + return(FALSE); + } + + /* load OEM codepage table */ + strcpy(szFileName, szSystemRoot); + strcat(szFileName, "system32\\"); + strcat(szFileName, szNameBuffer); + DbgPrint((DPRINT_REACTOS, "Oem file: %s\n", szFileName)); + if (!FrLdrLoadNlsFile(szFileName, "oem.nls")) { + + strcpy(szErrorOut, "Couldn't load oem.nls"); + return(FALSE); + } + + /* open the language key */ + rc = RegOpenKey(NULL, + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language", + &hKey); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Couldn't open Language registry key"); + return(FALSE); + } + + /* get the Unicode case table */ + BufferSize = 80; + rc = RegQueryValue(hKey, "Default", NULL, (PUCHAR)szIdBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Couldn't get Language Default setting"); + return(FALSE); + } + + BufferSize = 80; + rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize); + if (rc != ERROR_SUCCESS) { + + strcpy(szErrorOut, "Language Default setting exists, but isn't readable"); + return(FALSE); + } + + /* load Unicode case table */ + strcpy(szFileName, szSystemRoot); + strcat(szFileName, "system32\\"); + strcat(szFileName, szNameBuffer); + DbgPrint((DPRINT_REACTOS, "Casemap file: %s\n", szFileName)); + if (!FrLdrLoadNlsFile(szFileName, "casemap.nls")) { + + strcpy(szErrorOut, "casemap.nls"); + return(FALSE); + } + + return(TRUE); +} + +BOOL +FrLdrLoadDriver(PCHAR szFileName, + INT nPos) +{ + PFILE FilePointer; + CHAR value[256]; + LPSTR p; + + /* Open the Driver */ + FilePointer = FsOpenFile(szFileName); + + /* Make sure we did */ + if (FilePointer == NULL) { + + /* Fail if file wasn't opened */ + strcpy(value, szFileName); + strcat(value, " not found."); + UiMessageBox(value); + return(FALSE); + } + + /* Update the status bar with the current file */ + strcpy(value, "Reading "); + p = strrchr(szFileName, '\\'); + if (p == NULL) { + + strcat(value, szFileName); + + } else { + + strcat(value, p + 1); + + } + UiDrawStatusText(value); + + /* Load the driver */ + FrLdrLoadModule(FilePointer, szFileName, NULL); + + /* Update status and return */ + UiDrawProgressBarCenter(nPos, 100, "Loading ReactOS..."); + return(TRUE); +} + +VOID +FrLdrLoadBootDrivers(PCHAR szSystemRoot, + INT nPos) +{ + LONG rc = 0; + FRLDRHKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey; + CHAR GroupNameBuffer[512]; + CHAR ServiceName[256]; + ULONG OrderList[128]; + ULONG BufferSize; + ULONG Index; + ULONG TagIndex; + LPSTR GroupName; + + ULONG ValueSize; + ULONG ValueType; + ULONG StartValue; + ULONG TagValue; + UCHAR DriverGroup[256]; + ULONG DriverGroupSize; + + UCHAR ImagePath[256]; + UCHAR TempImagePath[256]; + + /* get 'service group order' key */ + rc = RegOpenKey(NULL, + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder", + &hGroupKey); + if (rc != ERROR_SUCCESS) { + + DbgPrint((DPRINT_REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc)); + return; + } + + /* get 'group order list' key */ + rc = RegOpenKey(NULL, + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList", + &hOrderKey); + if (rc != ERROR_SUCCESS) { + + DbgPrint((DPRINT_REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc)); + return; + } + + /* enumerate drivers */ + rc = RegOpenKey(NULL, + "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services", + &hServiceKey); + if (rc != ERROR_SUCCESS) { + + DbgPrint((DPRINT_REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc)); + return; + } + + /* Get the Name Group */ + BufferSize = sizeof(GroupNameBuffer); + rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize); + DbgPrint((DPRINT_REACTOS, "RegQueryValue(): rc %d\n", (int)rc)); + if (rc != ERROR_SUCCESS) return; + DbgPrint((DPRINT_REACTOS, "BufferSize: %d \n", (int)BufferSize)); + DbgPrint((DPRINT_REACTOS, "GroupNameBuffer: '%s' \n", GroupNameBuffer)); + + /* Loop through each group */ + GroupName = GroupNameBuffer; + while (*GroupName) { + DbgPrint((DPRINT_REACTOS, "Driver group: '%s'\n", GroupName)); + + /* Query the Order */ + BufferSize = sizeof(OrderList); + rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize); + if (rc != ERROR_SUCCESS) OrderList[0] = 0; + + /* enumerate all drivers */ + for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) { + + Index = 0; + + while (TRUE) { + + /* Get the Driver's Name */ + ValueSize = sizeof(ServiceName); + rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); + DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc)); + + /* Makre sure it's valid, and check if we're done */ + if (rc == ERROR_NO_MORE_ITEMS) break; + if (rc != ERROR_SUCCESS) return; + DbgPrint((DPRINT_REACTOS, "Service %d: '%s'\n", (int)Index, ServiceName)); + + /* open driver Key */ + rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); + + /* Read the Start Value */ + ValueSize = sizeof(ULONG); + rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); + DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue)); + + /* Read the Tag */ + ValueSize = sizeof(ULONG); + rc = RegQueryValue(hDriverKey, "Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); + if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; + DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue)); + + /* Read the driver's group */ + DriverGroupSize = 256; + rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); + DbgPrint((DPRINT_REACTOS, " Group: '%s' \n", DriverGroup)); + + /* Make sure it should be started */ + if ((StartValue == 0) && + (TagValue == OrderList[TagIndex]) && + (stricmp(DriverGroup, GroupName) == 0)) { + + /* Get the Driver's Location */ + ValueSize = 256; + rc = RegQueryValue(hDriverKey, "ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); + + /* Write the whole path if it suceeded, else prepare to fail */ + if (rc != ERROR_SUCCESS) { + DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n")); + strcpy(ImagePath, szSystemRoot); + strcat(ImagePath, "system32\\drivers\\"); + strcat(ImagePath, ServiceName); + strcat(ImagePath, ".sys"); + } else if (TempImagePath[0] != '\\') { + strcpy(ImagePath, szSystemRoot); + strcat(ImagePath, TempImagePath); + } else { + strcpy(ImagePath, TempImagePath); + DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath)); + } + + DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath)); + + /* Update the position if needed */ + if (nPos < 100) nPos += 5; + + FrLdrLoadDriver(ImagePath, nPos); + + } else { + + DbgPrint((DPRINT_REACTOS, " Skipping driver '%s' with Start %d, Tag %d and Group '%s' (Current Tag %d, current group '%s')\n", + ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName)); + } + + Index++; + } + } + + Index = 0; + while (TRUE) { + + /* Get the Driver's Name */ + ValueSize = sizeof(ServiceName); + rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); + + DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc)); + if (rc == ERROR_NO_MORE_ITEMS) break; + if (rc != ERROR_SUCCESS) return; + DbgPrint((DPRINT_REACTOS, "Service %d: '%s'\n", (int)Index, ServiceName)); + + /* open driver Key */ + rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); + + /* Read the Start Value */ + ValueSize = sizeof(ULONG); + rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); + DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue)); + + /* Read the Tag */ + ValueSize = sizeof(ULONG); + rc = RegQueryValue(hDriverKey, "Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); + if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; + DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue)); + + /* Read the driver's group */ + DriverGroupSize = 256; + rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); + DbgPrint((DPRINT_REACTOS, " Group: '%s' \n", DriverGroup)); + + for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) { + if (TagValue == OrderList[TagIndex]) break; + } + + if ((StartValue == 0) && + (TagIndex > OrderList[0]) && + (stricmp(DriverGroup, GroupName) == 0)) { + + ValueSize = 256; + rc = RegQueryValue(hDriverKey, "ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); + if (rc != ERROR_SUCCESS) { + DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n")); + strcpy(ImagePath, szSystemRoot); + strcat(ImagePath, "system32\\drivers\\"); + strcat(ImagePath, ServiceName); + strcat(ImagePath, ".sys"); + } else if (TempImagePath[0] != '\\') { + strcpy(ImagePath, szSystemRoot); + strcat(ImagePath, TempImagePath); + } else { + strcpy(ImagePath, TempImagePath); + DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath)); + } + DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath)); + + if (nPos < 100) nPos += 5; + + FrLdrLoadDriver(ImagePath, nPos); + + } else { + + DbgPrint((DPRINT_REACTOS, " Skipping driver '%s' with Start %d, Tag %d and Group '%s' (Current group '%s')\n", + ServiceName, StartValue, TagValue, DriverGroup, GroupName)); + } + + Index++; + } + + /* Move to the next group name */ + GroupName = GroupName + strlen(GroupName) + 1; + } +} + +VOID LoadAndBootReactOS(PUCHAR OperatingSystemName) { PFILE FilePointer; - char name[1024]; - char value[1024]; - char szKernelName[1024]; - char szHalName[1024]; - char szFileName[1024]; - char szBootPath[256]; - int i; - char MsgBuffer[256]; - U32 SectionId; + CHAR name[1024]; + CHAR value[1024]; + CHAR szKernelName[1024]; + CHAR szHalName[1024]; + CHAR szFileName[1024]; + CHAR szBootPath[256]; + INT i; + CHAR MsgBuffer[256]; + ULONG SectionId; - char* Base; - U32 Size; + ULONG_PTR Base; + ULONG Size; PARTITION_TABLE_ENTRY PartitionTableEntry; - U32 rosPartition; + ULONG rosPartition; + + extern ULONG PageDirectoryStart; + extern ULONG PageDirectoryEnd; // // Open the operating system section @@ -604,35 +595,37 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) /* * Setup multiboot information structure */ - mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES; - mb_info.boot_device = 0xffffffff; - mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline; - mb_info.mods_count = 0; - mb_info.mods_addr = (unsigned long)multiboot_modules; - mb_info.mmap_length = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&multiboot_memory_map, 32) * sizeof(memory_map_t); - if (mb_info.mmap_length) + LoaderBlock.Flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES; + LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart; + LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd; + LoaderBlock.BootDevice = 0xffffffff; + LoaderBlock.CommandLine = (unsigned long)multiboot_kernel_cmdline; + LoaderBlock.ModsCount = 0; + LoaderBlock.ModsAddr = (unsigned long)multiboot_modules; + LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&multiboot_memory_map, 32) * sizeof(memory_map_t); + if (LoaderBlock.MmapLength) { - mb_info.mmap_addr = (unsigned long)&multiboot_memory_map; - mb_info.flags |= MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_MEMORY_MAP; + LoaderBlock.MmapAddr = (unsigned long)&multiboot_memory_map; + LoaderBlock.Flags |= MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_MEMORY_MAP; multiboot_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24 - DbgPrint((DPRINT_REACTOS, "memory map length: %d\n", mb_info.mmap_length)); + DbgPrint((DPRINT_REACTOS, "memory map length: %d\n", LoaderBlock.MmapLength)); DbgPrint((DPRINT_REACTOS, "dumping memory map:\n")); - for (i=0; i<(mb_info.mmap_length/sizeof(memory_map_t)); i++) + for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++) { if (MEMTYPE_USABLE == multiboot_memory_map[i].type && 0 == multiboot_memory_map[i].base_addr_low) { - mb_info.mem_lower = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024; - if (640 < mb_info.mem_lower) + LoaderBlock.MemLower = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024; + if (640 < LoaderBlock.MemLower) { - mb_info.mem_lower = 640; + LoaderBlock.MemLower = 640; } } if (MEMTYPE_USABLE == multiboot_memory_map[i].type && multiboot_memory_map[i].base_addr_low <= 1024 * 1024 && 1024 * 1024 <= multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) { - mb_info.mem_upper = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024 - 1024; + LoaderBlock.MemHigher = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024 - 1024; } DbgPrint((DPRINT_REACTOS, "start: %x\t size: %x\t type %d\n", multiboot_memory_map[i].base_addr_low, @@ -640,8 +633,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) multiboot_memory_map[i].type)); } } - DbgPrint((DPRINT_REACTOS, "low_mem = %d\n", mb_info.mem_lower)); - DbgPrint((DPRINT_REACTOS, "high_mem = %d\n", mb_info.mem_upper)); + DbgPrint((DPRINT_REACTOS, "low_mem = %d\n", LoaderBlock.MemLower)); + DbgPrint((DPRINT_REACTOS, "high_mem = %d\n", LoaderBlock.MemHigher)); /* * Initialize the registry @@ -713,8 +706,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) } /* Set boot drive and partition */ - ((char *)(&mb_info.boot_device))[0] = (char)BootDrive; - ((char *)(&mb_info.boot_device))[1] = (char)BootPartition; + ((LPSTR )(&LoaderBlock.BootDevice))[0] = (CHAR)BootDrive; + ((LPSTR )(&LoaderBlock.BootDevice))[1] = (CHAR)BootPartition; /* * Read the optional kernel parameters (if any) @@ -782,9 +775,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) strcat(szKernelName, value); } - if (!LoadKernel(szKernelName, 5)) - return; - + if (!FrLdrLoadKernel(szKernelName, 5)) return; + /* * Find the HAL image name * and try to load the kernel off the disk @@ -813,7 +805,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) strcat(szHalName, value); } - if (!LoadDriver(szHalName, 10)) + if (!FrLdrLoadDriver(szHalName, 10)) return; /* @@ -843,8 +835,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) /* * Load the System hive */ - Base = MultiBootLoadModule(FilePointer, szFileName, &Size); - if (Base == NULL || Size == 0) + Base = FrLdrLoadModule(FilePointer, szFileName, &Size); + if (Base == 0 || Size == 0) { UiMessageBox("Could not load the System hive!\n"); return; @@ -854,7 +846,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) /* * Import the loaded system hive */ - RegImportBinaryHive(Base, Size); + RegImportBinaryHive((PCHAR)Base, Size); /* * Initialize the 'CurrentControlSet' link @@ -866,59 +858,48 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName) /* * Export the hardware hive */ - Base = MultiBootCreateModule ("HARDWARE"); - RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", Base, &Size); - MultiBootCloseModule (Base, Size); + Base = FrLdrCreateModule ("HARDWARE"); + RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", (PCHAR)Base, &Size); + FrLdrCloseModule (Base, Size); UiDrawProgressBarCenter(20, 100, "Loading ReactOS..."); /* * Load NLS files */ - if (!LoadNlsFiles(szBootPath, MsgBuffer)) + if (!FrLdrLoadNlsFiles(szBootPath, MsgBuffer)) { UiMessageBox(MsgBuffer); return; } - UiDrawProgressBarCenter(25, 100, "Loading ReactOS..."); + UiDrawProgressBarCenter(30, 100, "Loading ReactOS..."); /* - * Load symbol files + * Load kernel symbols */ - LoadSymbolFile(szBootPath, szKernelName, 30); - LoadSymbolFile(szBootPath, szHalName, 30); - - UiDrawProgressBarCenter(30, 100, "Loading ReactOS..."); + LoadKernelSymbols(szKernelName, 30); + UiDrawProgressBarCenter(40, 100, "Loading ReactOS..."); /* * Load boot drivers */ - LoadBootDrivers(szBootPath, 30); - - -#if 0 - /* - * Clear the screen and redraw the backdrop and status bar - */ - UiDrawBackdrop(); - UiDrawStatusText("Press any key to boot"); - - /* - * Wait for user - */ - strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot "); - strcat(name, OperatingSystemName); - strcat(name, "."); - MessageBox(name); -#endif - + FrLdrLoadBootDrivers(szBootPath, 40); UiUnInitialize("Booting ReactOS..."); /* * Now boot the kernel */ DiskStopFloppyMotor(); - boot_reactos(); + MachVideoPrepareForReactOS(); + FrLdrStartup(0x2badb002); +} + +#undef DbgPrint +ULONG +DbgPrint(char *Fmt, ...) +{ + UiMessageBox(Fmt); + return 0; } /* EOF */ diff --git a/reactos/boot/freeldr/freeldr/reactos/registry.c b/reactos/boot/freeldr/freeldr/reactos/registry.c index 938ec3f116a..ffc0f1a56a1 100644 --- a/reactos/boot/freeldr/freeldr/reactos/registry.c +++ b/reactos/boot/freeldr/freeldr/reactos/registry.c @@ -26,18 +26,18 @@ #include -static HKEY RootKey; +static FRLDRHKEY RootKey; VOID RegInitializeRegistry (VOID) { #if 0 - HKEY TestKey; + FRLDRHKEY TestKey; #endif /* Create root key */ - RootKey = (HKEY) MmAllocateMemory (sizeof(KEY)); + RootKey = (FRLDRHKEY) MmAllocateMemory (sizeof(KEY)); InitializeListHead (&RootKey->SubKeyList); InitializeListHead (&RootKey->ValueList); @@ -94,19 +94,19 @@ RegInitializeRegistry (VOID) } -S32 +LONG RegInitCurrentControlSet(BOOL LastKnownGood) { CHAR ControlSetKeyName[80]; - HKEY SelectKey; - HKEY SystemKey; - HKEY ControlSetKey; - HKEY LinkKey; - U32 CurrentSet = 0; - U32 DefaultSet = 0; - U32 LastKnownGoodSet = 0; - U32 DataSize; - S32 Error; + FRLDRHKEY SelectKey; + FRLDRHKEY SystemKey; + FRLDRHKEY ControlSetKey; + FRLDRHKEY LinkKey; + ULONG CurrentSet = 0; + ULONG DefaultSet = 0; + ULONG LastKnownGoodSet = 0; + ULONG DataSize; + LONG Error; Error = RegOpenKey(NULL, "\\Registry\\Machine\\SYSTEM\\Select", @@ -117,7 +117,7 @@ RegInitCurrentControlSet(BOOL LastKnownGood) return(Error); } - DataSize = sizeof(U32); + DataSize = sizeof(ULONG); Error = RegQueryValue(SelectKey, "Default", NULL, @@ -129,7 +129,7 @@ RegInitCurrentControlSet(BOOL LastKnownGood) return(Error); } - DataSize = sizeof(U32); + DataSize = sizeof(ULONG); Error = RegQueryValue(SelectKey, "LastKnownGood", NULL, @@ -204,15 +204,15 @@ RegInitCurrentControlSet(BOOL LastKnownGood) } -S32 -RegCreateKey(HKEY ParentKey, +LONG +RegCreateKey(FRLDRHKEY ParentKey, PCHAR KeyName, - PHKEY Key) + PFRLDRHKEY Key) { PLIST_ENTRY Ptr; - HKEY SearchKey = INVALID_HANDLE_VALUE; - HKEY CurrentKey; - HKEY NewKey; + FRLDRHKEY SearchKey = INVALID_HANDLE_VALUE; + FRLDRHKEY CurrentKey; + FRLDRHKEY NewKey; PCHAR p; PCHAR name; int subkeyLength; @@ -237,7 +237,7 @@ RegCreateKey(HKEY ParentKey, /* Check whether current key is a link */ if (CurrentKey->DataType == REG_LINK) { - CurrentKey = (HKEY)CurrentKey->Data; + CurrentKey = (FRLDRHKEY)CurrentKey->Data; } while (*KeyName != 0) @@ -279,7 +279,7 @@ RegCreateKey(HKEY ParentKey, if (Ptr == &CurrentKey->SubKeyList) { /* no key found -> create new subkey */ - NewKey = (HKEY)MmAllocateMemory(sizeof(KEY)); + NewKey = (FRLDRHKEY)MmAllocateMemory(sizeof(KEY)); if (NewKey == NULL) return(ERROR_OUTOFMEMORY); @@ -315,7 +315,7 @@ RegCreateKey(HKEY ParentKey, /* Check whether current key is a link */ if (CurrentKey->DataType == REG_LINK) { - CurrentKey = (HKEY)CurrentKey->Data; + CurrentKey = (FRLDRHKEY)CurrentKey->Data; } } @@ -329,8 +329,8 @@ RegCreateKey(HKEY ParentKey, } -S32 -RegDeleteKey(HKEY Key, +LONG +RegDeleteKey(FRLDRHKEY Key, PCHAR Name) { @@ -344,16 +344,16 @@ RegDeleteKey(HKEY Key, } -S32 -RegEnumKey(HKEY Key, - U32 Index, +LONG +RegEnumKey(FRLDRHKEY Key, + ULONG Index, PCHAR Name, - U32* NameSize) + ULONG* NameSize) { PLIST_ENTRY Ptr; - HKEY SearchKey; - U32 Count = 0; - U32 Size; + FRLDRHKEY SearchKey; + ULONG Count = 0; + ULONG Size; Ptr = Key->SubKeyList.Flink; while (Ptr != &Key->SubKeyList) @@ -382,14 +382,14 @@ RegEnumKey(HKEY Key, } -S32 -RegOpenKey(HKEY ParentKey, +LONG +RegOpenKey(FRLDRHKEY ParentKey, PCHAR KeyName, - PHKEY Key) + PFRLDRHKEY Key) { PLIST_ENTRY Ptr; - HKEY SearchKey = INVALID_HANDLE_VALUE; - HKEY CurrentKey; + FRLDRHKEY SearchKey = INVALID_HANDLE_VALUE; + FRLDRHKEY CurrentKey; PCHAR p; PCHAR name; int subkeyLength; @@ -416,7 +416,7 @@ RegOpenKey(HKEY ParentKey, /* Check whether current key is a link */ if (CurrentKey->DataType == REG_LINK) { - CurrentKey = (HKEY)CurrentKey->Data; + CurrentKey = (FRLDRHKEY)CurrentKey->Data; } while (*KeyName != 0) @@ -468,7 +468,7 @@ RegOpenKey(HKEY ParentKey, /* Check whether current key is a link */ if (CurrentKey->DataType == REG_LINK) { - CurrentKey = (HKEY)CurrentKey->Data; + CurrentKey = (FRLDRHKEY)CurrentKey->Data; } } @@ -482,12 +482,12 @@ RegOpenKey(HKEY ParentKey, } -S32 -RegSetValue(HKEY Key, +LONG +RegSetValue(FRLDRHKEY Key, PCHAR ValueName, - U32 Type, + ULONG Type, PUCHAR Data, - U32 DataSize) + ULONG DataSize) { PLIST_ENTRY Ptr; PVALUE Value = NULL; @@ -583,14 +583,14 @@ RegSetValue(HKEY Key, } -S32 -RegQueryValue(HKEY Key, +LONG +RegQueryValue(FRLDRHKEY Key, PCHAR ValueName, - U32* Type, + ULONG* Type, PUCHAR Data, - U32* DataSize) + ULONG* DataSize) { - U32 Size; + ULONG Size; PLIST_ENTRY Ptr; PVALUE Value = NULL; @@ -670,8 +670,8 @@ RegQueryValue(HKEY Key, } -S32 -RegDeleteValue(HKEY Key, +LONG +RegDeleteValue(FRLDRHKEY Key, PCHAR ValueName) { PLIST_ENTRY Ptr; @@ -727,18 +727,18 @@ RegDeleteValue(HKEY Key, } -S32 -RegEnumValue(HKEY Key, - U32 Index, +LONG +RegEnumValue(FRLDRHKEY Key, + ULONG Index, PCHAR ValueName, - U32* NameSize, - U32* Type, + ULONG* NameSize, + ULONG* Type, PUCHAR Data, - U32* DataSize) + ULONG* DataSize) { PLIST_ENTRY Ptr; PVALUE Value; - U32 Count = 0; + ULONG Count = 0; if (Key->Data != NULL) { @@ -813,15 +813,15 @@ RegEnumValue(HKEY Key, } -U32 -RegGetSubKeyCount (HKEY Key) +ULONG +RegGetSubKeyCount (FRLDRHKEY Key) { return Key->SubKeyCount; } -U32 -RegGetValueCount (HKEY Key) +ULONG +RegGetValueCount (FRLDRHKEY Key) { if (Key->DataSize != 0) return Key->ValueCount + 1; diff --git a/reactos/boot/freeldr/freeldr/reactos/registry.h b/reactos/boot/freeldr/freeldr/reactos/registry.h index 4cfdb0fdc4a..6876301f78d 100644 --- a/reactos/boot/freeldr/freeldr/reactos/registry.h +++ b/reactos/boot/freeldr/freeldr/reactos/registry.h @@ -24,30 +24,23 @@ #define INVALID_HANDLE_VALUE NULL -typedef struct _LIST_ENTRY -{ - struct _LIST_ENTRY *Flink; - struct _LIST_ENTRY *Blink; -} LIST_ENTRY, *PLIST_ENTRY; - - typedef struct _REG_KEY { LIST_ENTRY KeyList; LIST_ENTRY SubKeyList; LIST_ENTRY ValueList; - U32 SubKeyCount; - U32 ValueCount; + ULONG SubKeyCount; + ULONG ValueCount; - U32 NameSize; + ULONG NameSize; PUCHAR Name; /* default data */ - U32 DataType; - U32 DataSize; + ULONG DataType; + ULONG DataSize; PUCHAR Data; -} KEY, *HKEY, **PHKEY; +} KEY, *FRLDRHKEY, **PFRLDRHKEY; typedef struct _REG_VALUE @@ -55,18 +48,17 @@ typedef struct _REG_VALUE LIST_ENTRY ValueList; /* value name */ - U32 NameSize; + ULONG NameSize; PUCHAR Name; /* value data */ - U32 DataType; - U32 DataSize; + ULONG DataType; + ULONG DataSize; PUCHAR Data; } VALUE, *PVALUE; #define ERROR_SUCCESS 0L -#define ERROR_PATH_NOT_FOUND 2L #define ERROR_OUTOFMEMORY 14L #define ERROR_INVALID_PARAMETER 87L #define ERROR_MORE_DATA 234L @@ -149,22 +141,6 @@ typedef struct _REG_VALUE assert((ListEntry)->Flink->Blink == (ListEntry)); \ } -/* - * BOOLEAN - * IsListEmpty ( - * PLIST_ENTRY ListHead - * ); - * - * FUNCTION: - * Checks if a double linked list is empty - * - * ARGUMENTS: - * ListHead = Head of the list -*/ -#define IsListEmpty(ListHead) \ - ((ListHead)->Flink == (ListHead)) - - /* *VOID *RemoveEntryList ( @@ -194,23 +170,6 @@ typedef struct _REG_VALUE (ListEntry)->Blink = NULL; \ } -/* - * PURPOSE: Returns the byte offset of a field within a structure - */ -#define FIELD_OFFSET(Type,Field) (S32)(&(((Type *)(0))->Field)) - -/* - * PURPOSE: Returns the base address structure if the caller knows the - * address of a field within the structure - * ARGUMENTS: - * Address = address of the field - * Type = Type of the whole structure - * Field = Name of the field whose address is none - */ -#define CONTAINING_RECORD(Address,Type,Field) \ - (Type *)(((S32)Address) - FIELD_OFFSET(Type,Field)) - - #define REG_NONE 0 #define REG_SZ 1 #define REG_EXPAND_SZ 2 @@ -229,73 +188,73 @@ typedef struct _REG_VALUE VOID RegInitializeRegistry(VOID); -S32 +LONG RegInitCurrentControlSet(BOOL LastKnownGood); -S32 -RegCreateKey(HKEY ParentKey, +LONG +RegCreateKey(FRLDRHKEY ParentKey, PCHAR KeyName, - PHKEY Key); + PFRLDRHKEY Key); -S32 -RegDeleteKey(HKEY Key, +LONG +RegDeleteKey(FRLDRHKEY Key, PCHAR Name); -S32 -RegEnumKey(HKEY Key, - U32 Index, +LONG +RegEnumKey(FRLDRHKEY Key, + ULONG Index, PCHAR Name, - U32* NameSize); + ULONG* NameSize); -S32 -RegOpenKey(HKEY ParentKey, +LONG +RegOpenKey(FRLDRHKEY ParentKey, PCHAR KeyName, - PHKEY Key); + PFRLDRHKEY Key); -S32 -RegSetValue(HKEY Key, +LONG +RegSetValue(FRLDRHKEY Key, PCHAR ValueName, - U32 Type, + ULONG Type, PUCHAR Data, - U32 DataSize); + ULONG DataSize); -S32 -RegQueryValue(HKEY Key, +LONG +RegQueryValue(FRLDRHKEY Key, PCHAR ValueName, - U32* Type, + ULONG* Type, PUCHAR Data, - U32* DataSize); + ULONG* DataSize); -S32 -RegDeleteValue(HKEY Key, +LONG +RegDeleteValue(FRLDRHKEY Key, PCHAR ValueName); -S32 -RegEnumValue(HKEY Key, - U32 Index, +LONG +RegEnumValue(FRLDRHKEY Key, + ULONG Index, PCHAR ValueName, - U32* NameSize, - U32* Type, + ULONG* NameSize, + ULONG* Type, PUCHAR Data, - U32* DataSize); + ULONG* DataSize); -U32 -RegGetSubKeyCount (HKEY Key); +ULONG +RegGetSubKeyCount (FRLDRHKEY Key); -U32 -RegGetValueCount (HKEY Key); +ULONG +RegGetValueCount (FRLDRHKEY Key); BOOL RegImportBinaryHive (PCHAR ChunkBase, - U32 ChunkSize); + ULONG ChunkSize); BOOL RegExportBinaryHive (PCHAR KeyName, PCHAR ChunkBase, - U32* ChunkSize); + ULONG* ChunkSize); #endif /* __REGISTRY_H */ diff --git a/reactos/boot/freeldr/freeldr/reactos/setupldr.c b/reactos/boot/freeldr/freeldr/reactos/setupldr.c index 23db7fd56ea..bc2fe82e964 100644 --- a/reactos/boot/freeldr/freeldr/reactos/setupldr.c +++ b/reactos/boot/freeldr/freeldr/reactos/setupldr.c @@ -97,7 +97,7 @@ LoadKernel(PCHAR szSourcePath, PCHAR szFileName) /* * Load the kernel */ - MultiBootLoadKernel(FilePointer); + FrLdrMapKernel(FilePointer); return(TRUE); } @@ -162,7 +162,7 @@ LoadDriver(PCHAR szSourcePath, PCHAR szFileName) #endif /* Load the driver */ - MultiBootLoadModule(FilePointer, szFileName, NULL); + FrLdrLoadModule(FilePointer, szFileName, NULL); return(TRUE); } @@ -227,7 +227,7 @@ LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName) #endif /* Load the driver */ - MultiBootLoadModule(FilePointer, szModuleName, NULL); + FrLdrLoadModule(FilePointer, szModuleName, NULL); return(TRUE); } @@ -235,44 +235,49 @@ LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName) VOID RunLoader(VOID) { - PVOID Base; - U32 Size; + ULONG_PTR Base; + ULONG Size; char *SourcePath; char *LoadOptions; int i; HINF InfHandle; - U32 ErrorLine; + ULONG ErrorLine; INFCONTEXT InfContext; + + extern ULONG PageDirectoryStart; + extern ULONG PageDirectoryEnd; /* Setup multiboot information structure */ - mb_info.flags = MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES; - mb_info.boot_device = 0xffffffff; - mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline; - mb_info.mods_count = 0; - mb_info.mods_addr = (unsigned long)multiboot_modules; - mb_info.mmap_length = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&multiboot_memory_map, 32) * sizeof(memory_map_t); - if (mb_info.mmap_length) + LoaderBlock.Flags = MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES; + LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart; + LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd; + LoaderBlock.BootDevice = 0xffffffff; + LoaderBlock.CommandLine = (unsigned long)multiboot_kernel_cmdline; + LoaderBlock.ModsCount = 0; + LoaderBlock.ModsAddr = (unsigned long)multiboot_modules; + LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&multiboot_memory_map, 32) * sizeof(memory_map_t); + if (LoaderBlock.MmapLength) { - mb_info.mmap_addr = (unsigned long)&multiboot_memory_map; - mb_info.flags |= MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_MEMORY_MAP; + LoaderBlock.MmapAddr = (unsigned long)&multiboot_memory_map; + LoaderBlock.Flags |= MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_MEMORY_MAP; multiboot_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24 - for (i = 0; i < (mb_info.mmap_length / sizeof(memory_map_t)); i++) + for (i = 0; i < (LoaderBlock.MmapLength / sizeof(memory_map_t)); i++) { if (MEMTYPE_USABLE == multiboot_memory_map[i].type && 0 == multiboot_memory_map[i].base_addr_low) { - mb_info.mem_lower = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024; - if (640 < mb_info.mem_lower) + LoaderBlock.MemLower = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024; + if (640 < LoaderBlock.MemLower) { - mb_info.mem_lower = 640; + LoaderBlock.MemLower = 640; } } if (MEMTYPE_USABLE == multiboot_memory_map[i].type && multiboot_memory_map[i].base_addr_low <= 1024 * 1024 && 1024 * 1024 <= multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) { - mb_info.mem_upper = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024 - 1024; + LoaderBlock.MemHigher = (multiboot_memory_map[i].base_addr_low + multiboot_memory_map[i].length_low) / 1024 - 1024; } #if 0 printf("start: %x\t size: %x\t type %d\n", @@ -283,8 +288,8 @@ VOID RunLoader(VOID) } } #if 0 - printf("low_mem = %d\n", mb_info.mem_lower); - printf("high_mem = %d\n", mb_info.mem_upper); + printf("low_mem = %d\n", LoaderBlock.MemLower); + printf("high_mem = %d\n", LoaderBlock.MemHigher); MachConsGetCh(); #endif @@ -308,8 +313,8 @@ VOID RunLoader(VOID) #endif /* set boot drive and partition */ - ((char *)(&mb_info.boot_device))[0] = (char)BootDrive; - ((char *)(&mb_info.boot_device))[1] = (char)BootPartition; + ((char *)(&LoaderBlock.BootDevice))[0] = (char)BootDrive; + ((char *)(&LoaderBlock.BootDevice))[1] = (char)BootPartition; /* Open boot drive */ @@ -383,9 +388,9 @@ VOID RunLoader(VOID) /* Export the hardware hive */ - Base = MultiBootCreateModule ("HARDWARE"); - RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", Base, &Size); - MultiBootCloseModule (Base, Size); + Base = FrLdrCreateModule ("HARDWARE"); + RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", (PVOID)Base, &Size); + FrLdrCloseModule (Base, Size); #if 0 printf("Base: %x\n", Base); @@ -571,7 +576,8 @@ for(;;); /* Now boot the kernel */ DiskStopFloppyMotor(); - boot_reactos(); + MachVideoPrepareForReactOS(); + FrLdrStartup(0x2badb002); } /* EOF */ diff --git a/reactos/boot/freeldr/freeldr/rtl/list.c b/reactos/boot/freeldr/freeldr/rtl/list.c index 962289b451f..30a2d6ea33c 100644 --- a/reactos/boot/freeldr/freeldr/rtl/list.c +++ b/reactos/boot/freeldr/freeldr/rtl/list.c @@ -92,9 +92,9 @@ BOOL RtlListIsEmpty(PLIST_ITEM ListHead) return (ListHead->ListNext == NULL); } -U32 RtlListCountEntries(PLIST_ITEM ListHead) +ULONG RtlListCountEntries(PLIST_ITEM ListHead) { - U32 Count = 0; + ULONG Count = 0; while (ListHead != NULL) { diff --git a/reactos/boot/freeldr/freeldr/rtl/string.c b/reactos/boot/freeldr/freeldr/rtl/string.c index 369ae54e6ac..7f5c76e639c 100644 --- a/reactos/boot/freeldr/freeldr/rtl/string.c +++ b/reactos/boot/freeldr/freeldr/rtl/string.c @@ -19,7 +19,7 @@ #include -int strlen(char *str) +size_t strlen(const char *str) { int len; @@ -28,7 +28,7 @@ int strlen(char *str) return len; } -char *strcpy(char *dest, char *src) +char *strcpy(char *dest, const char *src) { char *ret = dest; @@ -39,7 +39,7 @@ char *strcpy(char *dest, char *src) return ret; } -char *strncpy(char *dest, char *src, size_t count) +char *strncpy(char *dest, const char *src, size_t count) { char *ret = dest; @@ -52,7 +52,7 @@ char *strncpy(char *dest, char *src, size_t count) return ret; } -char *strcat(char *dest, char *src) +char *strcat(char *dest, const char *src) { char *ret = dest; diff --git a/reactos/boot/freeldr/freeldr/ui/gui.c b/reactos/boot/freeldr/freeldr/ui/gui.c index 0cdb3ae8ab6..f6bebf98506 100644 --- a/reactos/boot/freeldr/freeldr/ui/gui.c +++ b/reactos/boot/freeldr/freeldr/ui/gui.c @@ -30,19 +30,19 @@ VOID GuiDrawBackdrop(VOID) { } -VOID GuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) +VOID GuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) { } -VOID GuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) +VOID GuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom) { } -VOID GuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) +VOID GuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) { } -VOID GuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) +VOID GuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr) { } @@ -70,7 +70,7 @@ VOID GuiMessageBoxCritical(PUCHAR MessageText) { } -VOID GuiDrawProgressBar(U32 Position, U32 Range) +VOID GuiDrawProgressBar(ULONG Position, ULONG Range) { } diff --git a/reactos/boot/freeldr/freeldr/ui/gui.h b/reactos/boot/freeldr/freeldr/ui/gui.h index 4084b043cf7..ad1e031440f 100644 --- a/reactos/boot/freeldr/freeldr/ui/gui.h +++ b/reactos/boot/freeldr/freeldr/ui/gui.h @@ -29,17 +29,17 @@ // /////////////////////////////////////////////////////////////////////////////////////// VOID GuiDrawBackdrop(VOID); // Fills the entire screen with a backdrop -VOID GuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr -VOID GuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom); // Draws a shadow on the bottom and right sides of the area specified -VOID GuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr); // Draws a box around the area specified -VOID GuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified +VOID GuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */); // Fills the area specified with FillChar and Attr +VOID GuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom); // Draws a shadow on the bottom and right sides of the area specified +VOID GuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr); // Draws a box around the area specified +VOID GuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr); // Draws text at coordinates specified VOID GuiDrawStatusText(PUCHAR StatusText); // Draws text at the very bottom line on the screen VOID GuiUpdateDateTime(VOID); // Updates the date and time VOID GuiSaveScreen(PUCHAR Buffer); // Saves the screen so that it can be restored later VOID GuiRestoreScreen(PUCHAR Buffer); // Restores the screen from a previous save VOID GuiMessageBox(PUCHAR MessageText); // Displays a message box on the screen with an ok button VOID GuiMessageBoxCritical(PUCHAR MessageText); // Displays a message box on the screen with an ok button using no system resources -VOID GuiDrawProgressBar(U32 Position, U32 Range); // Draws the progress bar showing nPos percent filled +VOID GuiDrawProgressBar(ULONG Position, ULONG Range); // Draws the progress bar showing nPos percent filled UCHAR GuiTextToColor(PUCHAR ColorText); // Converts the text color into it's equivalent color value UCHAR GuiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill into it's equivalent fill value @@ -49,7 +49,7 @@ UCHAR GuiTextToFillStyle(PUCHAR FillStyleText); // Converts the text fill int // Menu Functions // /////////////////////////////////////////////////////////////////////////////////////// -BOOL GuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem); +BOOL GuiDisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, ULONG* SelectedMenuItem); diff --git a/reactos/boot/freeldr/freeldr/ui/tui.c b/reactos/boot/freeldr/freeldr/ui/tui.c index 68bae1c99c9..c88f6655ee4 100644 --- a/reactos/boot/freeldr/freeldr/ui/tui.c +++ b/reactos/boot/freeldr/freeldr/ui/tui.c @@ -136,10 +136,10 @@ VOID TuiDrawBackdrop(VOID) * FillArea() * This function assumes coordinates are zero-based */ -VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) +VOID TuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) { PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; - U32 i, j; + ULONG i, j; // Clip the area to the screen // FIXME: This code seems to have problems... Uncomment and view ;-) @@ -172,10 +172,10 @@ VOID TuiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR * DrawShadow() * This function assumes coordinates are zero-based */ -VOID TuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) +VOID TuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom) { PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; - U32 Idx; + ULONG Idx; // Shade the bottom of the area if (Bottom < (UiScreenHeight - 1)) @@ -232,7 +232,7 @@ VOID TuiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) * DrawBox() * This function assumes coordinates are zero-based */ -VOID TuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) +VOID TuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) { UCHAR ULCorner, URCorner, LLCorner, LRCorner; @@ -304,10 +304,10 @@ VOID TuiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR * DrawText() * This function assumes coordinates are zero-based */ -VOID TuiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) +VOID TuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr) { PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer; - U32 i, j; + ULONG i, j; // Draw the text for (i=X, j=0; Text[j] && i -BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter) +BOOL TuiDisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, ULONG* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter) { TUI_MENU_INFO MenuInformation; - U32 LastClockSecond; - U32 CurrentClockSecond; - U32 KeyPress; + ULONG LastClockSecond; + ULONG CurrentClockSecond; + ULONG KeyPress; // // The first thing we need to check is the timeout @@ -145,10 +145,10 @@ BOOL TuiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuIte VOID TuiCalcMenuBoxSize(PTUI_MENU_INFO MenuInfo) { - U32 Idx; - U32 Width; - U32 Height; - U32 Length; + ULONG Idx; + ULONG Width; + ULONG Height; + ULONG Length; // // Height is the menu item count plus 2 (top border & bottom border) @@ -186,7 +186,7 @@ VOID TuiCalcMenuBoxSize(PTUI_MENU_INFO MenuInfo) VOID TuiDrawMenu(PTUI_MENU_INFO MenuInfo) { - U32 Idx; + ULONG Idx; // // Draw the backdrop @@ -218,7 +218,7 @@ VOID TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo) { UCHAR MenuLineText[80]; UCHAR TempString[80]; - U32 Idx; + ULONG Idx; // // Draw the menu box @@ -262,13 +262,13 @@ VOID TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo) } } -VOID TuiDrawMenuItem(PTUI_MENU_INFO MenuInfo, U32 MenuItemNumber) +VOID TuiDrawMenuItem(PTUI_MENU_INFO MenuInfo, ULONG MenuItemNumber) { - U32 Idx; + ULONG Idx; UCHAR MenuLineText[80]; - U32 SpaceTotal; - U32 SpaceLeft; - U32 SpaceRight; + ULONG SpaceTotal; + ULONG SpaceLeft; + ULONG SpaceRight; UCHAR Attribute; // @@ -335,9 +335,9 @@ VOID TuiDrawMenuItem(PTUI_MENU_INFO MenuInfo, U32 MenuItemNumber) } } -U32 TuiProcessMenuKeyboardEvent(PTUI_MENU_INFO MenuInfo, UiMenuKeyPressFilterCallback KeyPressFilter) +ULONG TuiProcessMenuKeyboardEvent(PTUI_MENU_INFO MenuInfo, UiMenuKeyPressFilterCallback KeyPressFilter) { - U32 KeyEvent = 0; + ULONG KeyEvent = 0; // // Check for a keypress diff --git a/reactos/boot/freeldr/freeldr/ui/ui.c b/reactos/boot/freeldr/freeldr/ui/ui.c index b930e7f9174..0b11262e03d 100644 --- a/reactos/boot/freeldr/freeldr/ui/ui.c +++ b/reactos/boot/freeldr/freeldr/ui/ui.c @@ -28,8 +28,8 @@ #include #include -U32 UiScreenWidth = 80; // Screen Width -U32 UiScreenHeight = 25; // Screen Height +ULONG UiScreenWidth = 80; // Screen Width +ULONG UiScreenHeight = 25; // Screen Height UCHAR UiStatusBarFgColor = COLOR_BLACK; // Status bar foreground color UCHAR UiStatusBarBgColor = COLOR_CYAN; // Status bar background color @@ -61,10 +61,10 @@ UCHAR UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May BOOL UiInitialize(BOOLEAN ShowGui) { - U32 SectionId; + ULONG SectionId; UCHAR DisplayModeText[260]; UCHAR SettingText[260]; - U32 Depth; + ULONG Depth; if (!ShowGui) { if (!TuiInitialize()) @@ -233,7 +233,7 @@ VOID UiDrawBackdrop(VOID) } } -VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) +VOID UiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */) { if (VideoTextMode == UiDisplayMode) { @@ -246,7 +246,7 @@ VOID UiFillArea(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR FillChar, UCHAR } } -VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) +VOID UiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom) { if (VideoTextMode == UiDisplayMode) { @@ -259,7 +259,7 @@ VOID UiDrawShadow(U32 Left, U32 Top, U32 Right, U32 Bottom) } } -VOID UiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) +VOID UiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr) { if (VideoTextMode == UiDisplayMode) { @@ -272,7 +272,7 @@ VOID UiDrawBox(U32 Left, U32 Top, U32 Right, U32 Bottom, UCHAR VertStyle, UCHAR } } -VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) +VOID UiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr) { if (VideoTextMode == UiDisplayMode) { @@ -285,7 +285,7 @@ VOID UiDrawText(U32 X, U32 Y, PUCHAR Text, UCHAR Attr) } } -VOID UiDrawCenteredText(U32 Left, U32 Top, U32 Right, U32 Bottom, PUCHAR TextString, UCHAR Attr) +VOID UiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PUCHAR TextString, UCHAR Attr) { if (VideoTextMode == UiDisplayMode) { @@ -328,16 +328,16 @@ VOID UiUpdateDateTime(VOID) VOID UiInfoBox(PUCHAR MessageText) { - U32 TextLength; - U32 BoxWidth; - U32 BoxHeight; - U32 LineBreakCount; - U32 Index; - U32 LastIndex; - U32 Left; - U32 Top; - U32 Right; - U32 Bottom; + ULONG TextLength; + ULONG BoxWidth; + ULONG BoxHeight; + ULONG LineBreakCount; + ULONG Index; + ULONG LastIndex; + ULONG Left; + ULONG Top; + ULONG Right; + ULONG Bottom; TextLength = strlen(MessageText); @@ -465,7 +465,7 @@ UCHAR UiTextToFillStyle(PUCHAR FillStyleText) } } -VOID UiDrawProgressBarCenter(U32 Position, U32 Range, PUCHAR ProgressText) +VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PUCHAR ProgressText) { if (!UserInterfaceUp) return; @@ -480,7 +480,7 @@ VOID UiDrawProgressBarCenter(U32 Position, U32 Range, PUCHAR ProgressText) } } -VOID UiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position, U32 Range, PUCHAR ProgressText) +VOID UiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PUCHAR ProgressText) { if (VideoTextMode == UiDisplayMode) { @@ -495,12 +495,12 @@ VOID UiDrawProgressBar(U32 Left, U32 Top, U32 Right, U32 Bottom, U32 Position, U VOID UiShowMessageBoxesInSection(PUCHAR SectionName) { - U32 Idx; + ULONG Idx; UCHAR SettingName[80]; UCHAR SettingValue[80]; PUCHAR MessageBoxText; - U32 MessageBoxTextSize; - U32 SectionId; + ULONG MessageBoxTextSize; + ULONG SectionId; if (!IniOpenSection(SectionName, &SectionId)) { @@ -547,7 +547,7 @@ VOID UiShowMessageBoxesInSection(PUCHAR SectionName) VOID UiEscapeString(PUCHAR String) { - U32 Idx; + ULONG Idx; for (Idx=0; Idx MaxChars) { @@ -571,7 +571,7 @@ VOID UiTruncateStringEllipsis(PUCHAR StringText, U32 MaxChars) } } -BOOL UiDisplayMenu(PUCHAR MenuItemList[], U32 MenuItemCount, U32 DefaultMenuItem, S32 MenuTimeOut, U32* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter) +BOOL UiDisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, ULONG* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter) { if (VideoTextMode == UiDisplayMode) { @@ -611,7 +611,7 @@ VOID UiFadeOut(VOID) } } -BOOL UiEditBox(PUCHAR MessageText, PUCHAR EditTextBuffer, U32 Length) +BOOL UiEditBox(PUCHAR MessageText, PUCHAR EditTextBuffer, ULONG Length) { if (VideoTextMode == UiDisplayMode) { diff --git a/reactos/boot/freeldr/freeldr/video/fade.c b/reactos/boot/freeldr/freeldr/video/fade.c index db8ab3d98c6..c5d69b37ef8 100644 --- a/reactos/boot/freeldr/freeldr/video/fade.c +++ b/reactos/boot/freeldr/freeldr/video/fade.c @@ -25,9 +25,9 @@ #define RGB_MAX 64 #define RGB_MAX_PER_ITERATION 64 -VOID VideoSetAllColorsToBlack(U32 ColorCount) +VOID VideoSetAllColorsToBlack(ULONG ColorCount) { - U32 Color; + ULONG Color; MachVideoSync(); @@ -37,10 +37,10 @@ VOID VideoSetAllColorsToBlack(U32 ColorCount) } } -VOID VideoFadeIn(PPALETTE_ENTRY Palette, U32 ColorCount) +VOID VideoFadeIn(PPALETTE_ENTRY Palette, ULONG ColorCount) { - U32 Index; - U32 Color; + ULONG Index; + ULONG Color; PALETTE_ENTRY PaletteColors[ColorCount]; for (Index=0; Index #include -VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, U32 ColorCount) +VOID VideoSavePaletteState(PPALETTE_ENTRY Palette, ULONG ColorCount) { - U32 Color; + ULONG Color; for (Color=0; Color = ,, diff --git a/reactos/config b/reactos/config index 92565649585..5a8c1f69da9 100644 --- a/reactos/config +++ b/reactos/config @@ -8,7 +8,7 @@ ARCH := i386 # # Which cpu should reactos optimze for -# example : i486, i586, pentium, pentium2, pentum3, pentium4 +# example : i486, i586, pentium, pentium2, pentium3, pentium4 # athlon-xp, athlon-mp, k6-2, # # see gcc manual for more cpu name and which cpu it can @@ -25,7 +25,7 @@ KDBG := 0 # # Whether to compile for debugging # -DBG := 0 +DBG := 0 # # Whether to compile with optimizations @@ -35,7 +35,7 @@ OPTIMIZED := 0 # # Whether to compile a multiprocessor or single processor version # -MP := 0 +CONFIG_SMP := 0 # # Whether to compile for ACPI compliant systems @@ -45,7 +45,7 @@ ACPI := 0 # # whether to use a 3GB User, 1GB Kernel memory map # -3GB := 1 +3GB := 0 # # Which version of NDIS do we support up to? diff --git a/reactos/doc/README.WINE b/reactos/doc/README.WINE index 0d0aa38b2a4..e1009d7acb4 100644 --- a/reactos/doc/README.WINE +++ b/reactos/doc/README.WINE @@ -34,39 +34,39 @@ reactos/tools/wmc # Wine Message Compiler The following shared libraries are a 100% port from Winehq sources. -reactos/lib/cabinet # Synced to Wine-20041201 -reactos/lib/comctl32 # Synced to Wine-20041201 -reactos/lib/comdlg32 # Synced to Wine-20041201 -reactos/lib/dinput # Synced to Wine-20041201 -reactos/lib/dinput8 # Synced to Wine-20041201 -reactos/lib/icmp # Synced to Wine-20041201 +reactos/lib/cabinet # Synced to Wine-20050111 +reactos/lib/comctl32 # Synced to Wine-20050111 +reactos/lib/comdlg32 # Synced to Wine-20050111 +reactos/lib/dinput # Synced to Wine-20050111 +reactos/lib/dinput8 # Synced to Wine-20050111 +reactos/lib/icmp # Synced to Wine-20050111 reactos/lib/iphlpapi # Out of sync reactos/lib/imagehlp # Patches for BindImage need review and submission to winehq. reactos/lib/msvcrt20 # Out of sync -reactos/lib/mpr # Synced to Wine-20041201 +reactos/lib/mpr # Synced to Wine-20050111 reactos/lib/msacm # Out of sync -reactos/lib/msi # Synced to Wine-20041201 +reactos/lib/msi # Synced to Wine-20050111 reactos/lib/msvideo # Out of sync reactos/lib/netapi32 # Out of sync reactos/lib/odbc32 # In sync. Depends on port of Linux ODBC. -reactos/lib/ole32 # Synced to Wine-20041201 -reactos/lib/oleaut32 # Synced to Wine-20041201 -reactos/lib/oledlg # Synced to Wine-20041201 -reactos/lib/olepro32 # Synced to Wine-20041201 -reactos/lib/richedit # Synced to Wine-20041201 -reactos/lib/rpcrt4 # Synced to Wine-20041201 -reactos/lib/setupapi # Out of sync -reactos/lib/shell32 # Synced to Wine-20041201 -reactos/lib/shdocvw # Synced to Wine-20041201 -reactos/lib/shlwapi # Synced to Wine-20041201 +reactos/lib/ole32 # Synced to Wine-20050111 +reactos/lib/oleaut32 # Synced to Wine-20050111 +reactos/lib/oledlg # Synced to Wine-20050111 +reactos/lib/olepro32 # Synced to Wine-20050111 +reactos/lib/richedit # Synced to Wine-20050111 +reactos/lib/rpcrt4 # Synced to Wine-20050111 +reactos/lib/setupapi # Synced to Wine-20050125 # CVS +reactos/lib/shell32 # Synced to Wine-20050111 +reactos/lib/shdocvw # Synced to Wine-20050111 +reactos/lib/shlwapi # Synced to Wine-20050111 reactos/lib/twain # Out of sync -reactos/lib/unicode # Dependancy on this lib needs to be removed. Synced to Wine-20041201 -reactos/lib/urlmon # Synced to Wine-20041201 +reactos/lib/unicode # Dependancy on this lib needs to be removed. Synced to Wine-20050111 +reactos/lib/urlmon # Synced to Wine-20050111 reactos/lib/version # Out of sync reactos/lib/wininet # Out of sync -reactos/lib/winmm # Synced to Wine-20041201 -reactos/lib/winmm/midimap # Synced to Wine-20041201 -reactos/lib/winmm/wavemap # Synced to Wine-20041201 +reactos/lib/winmm # Synced to Wine-20050111 +reactos/lib/winmm/midimap # Synced to Wine-20050111 +reactos/lib/winmm/wavemap # Synced to Wine-20050111 ReactOS shares the following programs with Winehq. reactos/subsys/system/regedit # Out of sync @@ -100,5 +100,3 @@ User32 - reactos/lib/user32/misc/wsprintf.c # Out of sync reactos/lib/user32/windows/mdi.c # Out of sync - - ` \ No newline at end of file diff --git a/reactos/drivers/bus/acpi/ospm/osl.c b/reactos/drivers/bus/acpi/ospm/osl.c index fed55a17d54..741f0714c91 100644 --- a/reactos/drivers/bus/acpi/ospm/osl.c +++ b/reactos/drivers/bus/acpi/ospm/osl.c @@ -219,6 +219,11 @@ acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) &DIrql, &Affinity); + AcpiIrqNumber = irq; + AcpiIrqHandler = handler; + AcpiIrqContext = context; + AcpiInterruptHandlerRegistered = TRUE; + Status = IoConnectInterrupt( &AcpiInterrupt, OslIsrStub, @@ -236,11 +241,6 @@ acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) return AE_ERROR; } - AcpiIrqNumber = irq; - AcpiIrqHandler = handler; - AcpiIrqContext = context; - AcpiInterruptHandlerRegistered = TRUE; - return AE_OK; } diff --git a/reactos/drivers/dd/bootvid/bootvid.c b/reactos/drivers/dd/bootvid/bootvid.c index c1e468da2e4..20807f34d26 100644 --- a/reactos/drivers/dd/bootvid/bootvid.c +++ b/reactos/drivers/dd/bootvid/bootvid.c @@ -66,7 +66,6 @@ PUCHAR VideoMemory; /* Must be 4 bytes per entry */ long maskbit[640]; -static HANDLE BitmapThreadHandle; static CLIENT_ID BitmapThreadId; static PUCHAR BootimageBitmap; @@ -556,6 +555,7 @@ STATIC BOOLEAN STDCALL VidInitialize(VOID) { NTSTATUS Status; + HANDLE BitmapThreadHandle; InbvMapVideoMemory(); InbvInitVGAMode(); @@ -574,7 +574,7 @@ VidInitialize(VOID) return FALSE; } - NtClose(BitmapThreadHandle); + ZwClose(BitmapThreadHandle); return TRUE; } diff --git a/reactos/drivers/dd/bootvid/pixelsup_i386.S b/reactos/drivers/dd/bootvid/pixelsup_i386.S index 34244ec4ddb..3fd07c40375 100644 --- a/reactos/drivers/dd/bootvid/pixelsup_i386.S +++ b/reactos/drivers/dd/bootvid/pixelsup_i386.S @@ -28,6 +28,8 @@ _InbvPutPixels: pushl %ebp movl %esp, %ebp + pushl %esi + pushl %ebx /* Compute mask and put it in EBX mask = maskbit[x] */ @@ -66,7 +68,7 @@ _InbvPutPixels: (UCHAR) READ_REGISTER_UCHAR(VideoMemory + offset+0); */ movl (_VideoMemory), %esi addl %ebx, %esi - movb 0x0(%esi), %bl + movb 0x0(%esi), %bl /* Write color index for first pixel *((PUCHAR)(VideoMemory + offset+0)) = (c >> 0*8) & 0xff; */ movl 0x10(%ebp), %eax @@ -96,6 +98,8 @@ _InbvPutPixels: shrl $0x8, %eax movb %al, 0x3(%esi) + popl %ebx + popl %esi popl %ebp ret diff --git a/reactos/drivers/dd/ramdrv/ramdrv.c b/reactos/drivers/dd/ramdrv/ramdrv.c index 0f4772853ab..b3304be5bf9 100644 --- a/reactos/drivers/dd/ramdrv/ramdrv.c +++ b/reactos/drivers/dd/ramdrv/ramdrv.c @@ -139,7 +139,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, 0 ); allocsize.u.LowPart = allocsize.u.HighPart = 0; - Status = NtOpenFile( &file, + Status = ZwOpenFile( &file, GENERIC_READ, &objattr, &iosb, @@ -157,7 +157,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, 0, 0, 0 ); - Status = NtCreateEvent( &event, + Status = ZwCreateEvent( &event, 0, &objattr, NotificationEvent, @@ -168,7 +168,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, goto cleanfile; } - Status = NtQueryInformationFile( file, + Status = ZwQueryInformationFile( file, &iosb, &finfo, sizeof( finfo ), @@ -187,7 +187,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, goto cleanevent; } - Status = NtReadFile( file, + Status = ZwReadFile( file, event, 0, 0, @@ -202,7 +202,7 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, DPRINT( "Failed to read floppy\n" ); goto cleantbuff; } - Status = NtWaitForSingleObject( event, FALSE, 0 ); + Status = ZwWaitForSingleObject( event, FALSE, 0 ); if( Status != STATUS_WAIT_0 || !NT_SUCCESS( iosb.Status ) ) { DPRINT( "Failed to read floppy\n" ); @@ -221,16 +221,16 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, } else DbgPrint( "RAMDRV: Failed to decomparess image, error: %d\n", err ); ExFreePool( tbuff ); - NtClose( file ); - NtClose( event ); + ZwClose( file ); + ZwClose( event ); return STATUS_SUCCESS; cleantbuff: ExFreePool( tbuff ); cleanevent: - NtClose( event ); + ZwClose( event ); cleanfile: - NtClose( file ); + ZwClose( file ); cleanbuffer: ExFreePool( devext->Buffer ); diff --git a/reactos/drivers/fs/cdfs/common.c b/reactos/drivers/fs/cdfs/common.c index 940179adbf4..9e247805872 100644 --- a/reactos/drivers/fs/cdfs/common.c +++ b/reactos/drivers/fs/cdfs/common.c @@ -191,6 +191,19 @@ CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, *OutputBufferSize = IoStatus.Information; } + if (Status == STATUS_VERIFY_REQUIRED) + { + PDEVICE_OBJECT DeviceToVerify; + NTSTATUS NewStatus; + + DPRINT1("STATUS_VERIFY_REQUIRED\n"); + DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); + IoSetDeviceToVerify(PsGetCurrentThread(), NULL); + + NewStatus = IoVerifyVolume(DeviceToVerify, FALSE); + DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus); + } + DPRINT("Returning Status %x\n", Status); return Status; diff --git a/reactos/drivers/fs/cdfs/create.c b/reactos/drivers/fs/cdfs/create.c index 9ceaa6652b3..7bbef26a01c 100644 --- a/reactos/drivers/fs/cdfs/create.c +++ b/reactos/drivers/fs/cdfs/create.c @@ -44,7 +44,6 @@ CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject, PUNICODE_STRING AbsoluteFileName) { ULONG Length; -// PWSTR rcName; PFCB Fcb; NTSTATUS Status; @@ -65,42 +64,29 @@ CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject, sizeof(WCHAR) + RelativeFileName->Length + sizeof(WCHAR); -// ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 -// <= MAX_PATH); -// rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR)); -// if (!rcName) -// { -// return(STATUS_INSUFFICIENT_RESOURCES); -// } AbsoluteFileName->Length = 0; AbsoluteFileName->MaximumLength = Length; AbsoluteFileName->Buffer = ExAllocatePool(NonPagedPool, Length); if (AbsoluteFileName->Buffer == NULL) { -CHECKPOINT1; return STATUS_INSUFFICIENT_RESOURCES; } - -// wcscpy(rcName, Fcb->PathName); Status = RtlAppendUnicodeToString(AbsoluteFileName, Fcb->PathName); if (!NT_SUCCESS(Status)) { -CHECKPOINT1; RtlFreeUnicodeString(AbsoluteFileName); return Status; } if (!CdfsFCBIsRoot(Fcb)) { -// wcscat (rcName, L"\\"); Status = RtlAppendUnicodeToString(AbsoluteFileName, L"\\"); if (!NT_SUCCESS(Status)) { -CHECKPOINT1; RtlFreeUnicodeString(AbsoluteFileName); return Status; } @@ -110,14 +96,10 @@ CHECKPOINT1; RelativeFileName); if (!NT_SUCCESS(Status)) { -CHECKPOINT1; RtlFreeUnicodeString(AbsoluteFileName); return Status; } -// wcscat (rcName, pRelativeFileName); -// *pAbsoluteFilename = rcName; - return STATUS_SUCCESS; } @@ -150,10 +132,6 @@ CdfsOpenFile(PDEVICE_EXTENSION DeviceExt, } FileName = &AbsFileName; - - RtlFreeUnicodeString(&AbsFileName); - - return STATUS_UNSUCCESSFUL; } Status = CdfsDeviceIoControl (DeviceExt->StorageDevice, @@ -162,28 +140,9 @@ CdfsOpenFile(PDEVICE_EXTENSION DeviceExt, 0, NULL, 0, - TRUE); + FALSE); DPRINT ("Status %lx\n", Status); - if (Status == STATUS_VERIFY_REQUIRED) - { - PDEVICE_OBJECT DeviceToVerify; - - DPRINT1 ("Media change detected!\n"); - DPRINT1 ("Device %p\n", DeviceExt->VolumeDevice); - - DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ()); - IoSetDeviceToVerify (PsGetCurrentThread (), - NULL); - - Status = IoVerifyVolume (DeviceToVerify, - FALSE); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("Status %lx\n", Status); - return Status; - } - } - else if (!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { DPRINT1 ("Status %lx\n", Status); return Status; diff --git a/reactos/drivers/fs/cdfs/fcb.c b/reactos/drivers/fs/cdfs/fcb.c index a34a554c42e..afb602b133b 100644 --- a/reactos/drivers/fs/cdfs/fcb.c +++ b/reactos/drivers/fs/cdfs/fcb.c @@ -234,8 +234,6 @@ CdfsFCBInitializeCache(PVCB Vcb, RtlZeroMemory(newCCB, sizeof(CCB)); - FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; FileObject->FsContext = Fcb; FileObject->FsContext2 = newCCB; @@ -423,8 +421,6 @@ CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, } memset(newCCB, 0, sizeof(CCB)); - FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; FileObject->FsContext = Fcb; FileObject->FsContext2 = newCCB; diff --git a/reactos/drivers/fs/cdfs/fsctl.c b/reactos/drivers/fs/cdfs/fsctl.c index 15b25584c7c..85f67040781 100644 --- a/reactos/drivers/fs/cdfs/fsctl.c +++ b/reactos/drivers/fs/cdfs/fsctl.c @@ -345,6 +345,7 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject, goto ByeBye; NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; + NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME; DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION)); @@ -385,7 +386,6 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject, RtlZeroMemory(Ccb, sizeof(CCB)); - DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; DeviceExt->StreamFileObject->FsContext = Fcb; DeviceExt->StreamFileObject->FsContext2 = Ccb; DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; diff --git a/reactos/drivers/fs/np/create.c b/reactos/drivers/fs/np/create.c index cdbef4032ce..4c18f268e5f 100644 --- a/reactos/drivers/fs/np/create.c +++ b/reactos/drivers/fs/np/create.c @@ -192,14 +192,14 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE); /* - * Step 4. Add the client FCB to a list and connect it if necessary. + * Step 4. Add the client FCB to a list and connect it if possible. */ /* Add the client FCB to the pipe FCB list. */ InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry); - /* Connect pipes if they were created by the same thread */ - if (ServerFcb && ServerFcb->Thread == ClientFcb->Thread) + /* Connect to listening server side */ + if (ServerFcb) { ClientFcb->OtherSide = ServerFcb; ServerFcb->OtherSide = ClientFcb; @@ -320,11 +320,11 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, InitializeListHead(&Pipe->ClientFcbListHead); KeInitializeMutex(&Pipe->FcbListLock, 0); - Pipe->PipeType = Buffer->NamedPipeType ? FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE; - Pipe->PipeWriteMode = Buffer->NamedPipeType ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; - Pipe->PipeReadMode = Buffer->ReadMode ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; - Pipe->PipeBlockMode = Buffer->CompletionMode; - Pipe->PipeConfiguration = IoStack->Parameters.Create.Options & 0x3; + Pipe->PipeType = Buffer->NamedPipeType; + Pipe->WriteMode = Buffer->ReadMode; + Pipe->ReadMode = Buffer->ReadMode; + Pipe->CompletionMode = Buffer->CompletionMode; + Pipe->PipeConfiguration = IoStack->Parameters.CreatePipe.Options & 0x3; Pipe->MaximumInstances = Buffer->MaximumInstances; Pipe->CurrentInstances = 0; Pipe->TimeOut = Buffer->DefaultTimeout; diff --git a/reactos/drivers/fs/np/fsctrl.c b/reactos/drivers/fs/np/fsctrl.c index f0d9d5c4433..0e8e2633b54 100644 --- a/reactos/drivers/fs/np/fsctrl.c +++ b/reactos/drivers/fs/np/fsctrl.c @@ -217,64 +217,31 @@ static NTSTATUS NpfsGetState(PIRP Irp, PIO_STACK_LOCATION IrpSp) { - ULONG OutputBufferLength; PNPFS_GET_STATE Reply; - NTSTATUS Status; PNPFS_PIPE Pipe; PNPFS_FCB Fcb; - OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; - /* Validate parameters */ - if (OutputBufferLength >= sizeof(NPFS_GET_STATE)) + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(NPFS_GET_STATE)) { - Fcb = IrpSp->FileObject->FsContext; - Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer; - Pipe = Fcb->Pipe; - - if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE) - { - Reply->WriteModeMessage = TRUE; - } - else - { - Reply->WriteModeMessage = FALSE; + DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; } - if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE) - { - Reply->ReadModeMessage = TRUE; - } - else - { - Reply->ReadModeMessage = FALSE; - } + Fcb = IrpSp->FileObject->FsContext; + Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; - if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION) - { - Reply->NonBlocking = TRUE; - } - else - { - Reply->NonBlocking = FALSE; - } + Reply->WriteModeMessage = (Pipe->WriteMode == FILE_PIPE_MESSAGE_MODE); + Reply->ReadModeMessage = (Pipe->ReadMode == FILE_PIPE_MESSAGE_MODE); + Reply->NonBlocking = (Pipe->CompletionMode == FILE_PIPE_QUEUE_OPERATION); + Reply->InBufferSize = Pipe->InboundQuota; + Reply->OutBufferSize = Pipe->OutboundQuota; + Reply->Timeout = Pipe->TimeOut; - Reply->InBufferSize = Pipe->InboundQuota; + DPRINT("Status (0x%X).\n", STATUS_SUCCESS); - Reply->OutBufferSize = Pipe->OutboundQuota; - - Reply->Timeout = Pipe->TimeOut; - - Status = STATUS_SUCCESS; - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - - DPRINT("Status (0x%X).\n", Status); - - return Status; + return STATUS_SUCCESS; } @@ -290,64 +257,34 @@ static NTSTATUS NpfsSetState(PIRP Irp, PIO_STACK_LOCATION IrpSp) { - ULONG InputBufferLength; PNPFS_SET_STATE Request; PNPFS_PIPE Pipe; - NTSTATUS Status; PNPFS_FCB Fcb; - InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; - /* Validate parameters */ - if (InputBufferLength >= sizeof(NPFS_SET_STATE)) - { - Fcb = IrpSp->FileObject->FsContext; - Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer; - Pipe = Fcb->Pipe; - - if (Request->WriteModeMessage) + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(NPFS_SET_STATE)) { - Pipe->PipeWriteMode = FILE_PIPE_MESSAGE_MODE; - } - else - { - Pipe->PipeWriteMode = FILE_PIPE_BYTE_STREAM_MODE; + DPRINT("Status (0x%X).\n", STATUS_INVALID_PARAMETER); + return STATUS_INVALID_PARAMETER; } - if (Request->ReadModeMessage) - { - Pipe->PipeReadMode = FILE_PIPE_MESSAGE_MODE; - } - else - { - Pipe->PipeReadMode = FILE_PIPE_BYTE_STREAM_MODE; - } + Fcb = IrpSp->FileObject->FsContext; + Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; - if (Request->NonBlocking) - { - Pipe->PipeBlockMode = FILE_PIPE_QUEUE_OPERATION; - } - else - { - Pipe->PipeBlockMode = FILE_PIPE_COMPLETE_OPERATION; - } + Pipe->WriteMode = + Request->WriteModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; + Pipe->ReadMode = + Request->WriteModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; + Pipe->CompletionMode = + Request->NonBlocking ? FILE_PIPE_QUEUE_OPERATION : FILE_PIPE_COMPLETE_OPERATION; + Pipe->InboundQuota = Request->InBufferSize; + Pipe->OutboundQuota = Request->OutBufferSize; + Pipe->TimeOut = Request->Timeout; - Pipe->InboundQuota = Request->InBufferSize; + DPRINT("Status (0x%X).\n", STATUS_SUCCESS); - Pipe->OutboundQuota = Request->OutBufferSize; - - Pipe->TimeOut = Request->Timeout; - - Status = STATUS_SUCCESS; - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - - DPRINT("Status (0x%X).\n", Status); - - return Status; + return STATUS_SUCCESS; } diff --git a/reactos/drivers/fs/np/npfs.h b/reactos/drivers/fs/np/npfs.h index db552a55ec2..f7e70f463ca 100644 --- a/reactos/drivers/fs/np/npfs.h +++ b/reactos/drivers/fs/np/npfs.h @@ -26,9 +26,9 @@ typedef struct _NPFS_PIPE LIST_ENTRY ServerFcbListHead; LIST_ENTRY ClientFcbListHead; ULONG PipeType; - ULONG PipeReadMode; - ULONG PipeWriteMode; - ULONG PipeBlockMode; + ULONG ReadMode; + ULONG WriteMode; + ULONG CompletionMode; ULONG PipeConfiguration; ULONG MaximumInstances; ULONG CurrentInstances; diff --git a/reactos/drivers/fs/np/rw.c b/reactos/drivers/fs/np/rw.c index 7bbf3c35bd0..aab1872ff03 100644 --- a/reactos/drivers/fs/np/rw.c +++ b/reactos/drivers/fs/np/rw.c @@ -168,7 +168,7 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql); } - if (Pipe->PipeReadMode == FILE_PIPE_BYTE_STREAM_MODE) + if (Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE) { DPRINT("Byte stream mode\n"); /* Byte stream mode */ @@ -363,7 +363,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql); } - if (Pipe->PipeWriteMode == FILE_PIPE_BYTE_STREAM_MODE) + if (Pipe->WriteMode == FILE_PIPE_BYTE_STREAM_MODE) { DPRINT("Byte stream mode\n"); while (Length > 0 && Fcb->WriteQuotaAvailable > 0) diff --git a/reactos/drivers/fs/ntfs/fcb.c b/reactos/drivers/fs/ntfs/fcb.c index 77a4220b50b..31029adf4e7 100644 --- a/reactos/drivers/fs/ntfs/fcb.c +++ b/reactos/drivers/fs/ntfs/fcb.c @@ -235,8 +235,6 @@ NtfsFCBInitializeCache(PVCB Vcb, RtlZeroMemory(newCCB, sizeof(CCB)); - FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; FileObject->FsContext = Fcb; FileObject->FsContext2 = newCCB; @@ -406,8 +404,6 @@ NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, } memset(newCCB, 0, sizeof(CCB)); - FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; FileObject->FsContext = Fcb; FileObject->FsContext2 = newCCB; diff --git a/reactos/drivers/fs/ntfs/fsctl.c b/reactos/drivers/fs/ntfs/fsctl.c index 938fb1e5c95..41071faaf20 100644 --- a/reactos/drivers/fs/ntfs/fsctl.c +++ b/reactos/drivers/fs/ntfs/fsctl.c @@ -370,7 +370,6 @@ NtfsMountVolume(PDEVICE_OBJECT DeviceObject, RtlZeroMemory(Ccb, sizeof(CCB)); - DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; DeviceExt->StreamFileObject->FsContext = Fcb; DeviceExt->StreamFileObject->FsContext2 = Ccb; DeviceExt->StreamFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; diff --git a/reactos/drivers/fs/vfat/blockdev.c b/reactos/drivers/fs/vfat/blockdev.c index cf97ada1242..a653fe89567 100644 --- a/reactos/drivers/fs/vfat/blockdev.c +++ b/reactos/drivers/fs/vfat/blockdev.c @@ -10,11 +10,7 @@ /* INCLUDES *****************************************************************/ -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ***************************************************************/ @@ -71,7 +67,7 @@ VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject, KeInitializeEvent (&event, NotificationEvent, FALSE); - DPRINT ("VfatReadSectors(pDeviceObject %x, Offset %I64x, Length %d, Buffer %x)\n", + DPRINT ("VfatReadDisk(pDeviceObject %x, Offset %I64x, Length %d, Buffer %x)\n", pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); DPRINT ("Building synchronous FSD Request...\n"); @@ -108,7 +104,7 @@ VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject, if (!NT_SUCCESS (Status)) { - DPRINT ("IO failed!!! VfatReadSectors : Error code: %x\n", Status); + DPRINT ("IO failed!!! VfatReadDisk : Error code: %x\n", Status); DPRINT ("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n", pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); return (Status); @@ -134,7 +130,7 @@ VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, DPRINT ("Building asynchronous FSD Request...\n"); - Buffer = MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; + Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); if (Irp == NULL) @@ -212,7 +208,7 @@ VfatWriteDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext, DPRINT ("VfatWriteDiskPartial(IrpContext %x, WriteOffset %I64x, WriteLength %d, BufferOffset %x, Wait %d)\n", IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait); - Buffer = MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; + Buffer = (PCHAR)MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset; DPRINT ("Building asynchronous FSD Request...\n"); Irp = IoAllocateIrp(IrpContext->DeviceExt->StorageDevice->StackSize, TRUE); diff --git a/reactos/drivers/fs/vfat/cleanup.c b/reactos/drivers/fs/vfat/cleanup.c index d75c24cc16f..df24e8cbef0 100644 --- a/reactos/drivers/fs/vfat/cleanup.c +++ b/reactos/drivers/fs/vfat/cleanup.c @@ -10,11 +10,7 @@ /* INCLUDES *****************************************************************/ -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ @@ -50,12 +46,22 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext) VfatUpdateEntry (pFcb); } - /* Uninitialize file cache if initialized for this file object. */ - if (FileObject->PrivateCacheMap) + if (pFcb->Flags & FCB_DELETE_PENDING && + pFcb->OpenHandleCount == 1) { - CcRosReleaseFileCache (FileObject); +#if 0 + /* FIXME: + * CcPurgeCacheSection is unimplemented. + */ + CcPurgeCacheSection(FileObject->SectionObjectPointer, NULL, 0, FALSE); +#endif } - + /* Uninitialize file cache if. */ +#ifdef USE_ROS_CC_AND_FS + CcRosReleaseFileCache (FileObject); +#else + CcUninitializeCacheMap (FileObject, NULL, NULL); +#endif pFcb->OpenHandleCount--; IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess); } diff --git a/reactos/drivers/fs/vfat/close.c b/reactos/drivers/fs/vfat/close.c index b22206fc612..a3ae43f68c3 100644 --- a/reactos/drivers/fs/vfat/close.c +++ b/reactos/drivers/fs/vfat/close.c @@ -10,11 +10,7 @@ /* INCLUDES *****************************************************************/ -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ diff --git a/reactos/drivers/fs/vfat/create.c b/reactos/drivers/fs/vfat/create.c index 7e7b3835d8c..d11001574c1 100644 --- a/reactos/drivers/fs/vfat/create.c +++ b/reactos/drivers/fs/vfat/create.c @@ -27,13 +27,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS *****************************************************************/ @@ -41,7 +35,7 @@ void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU) { OEM_STRING StringA; - ULONG Length; + USHORT Length; CHAR cString[12]; RtlCopyMemory(cString, pEntry->Filename, 11); @@ -191,22 +185,32 @@ FindFile (PDEVICE_EXTENSION DeviceExt, * FUNCTION: Find a file */ { - WCHAR PathNameBuffer[MAX_PATH]; + PWCHAR PathNameBuffer; + ULONG PathNameBufferLength; NTSTATUS Status; PVOID Context = NULL; PVOID Page; PVFATFCB rcFcb; BOOLEAN Found; UNICODE_STRING PathNameU; + UNICODE_STRING FileToFindUpcase; BOOLEAN WildCard; DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n", Parent, FileToFindU, DirContext->DirIndex); DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU); + + PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR); + PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength + sizeof(WCHAR)); + if (!PathNameBuffer) + { + CHECKPOINT1; + return STATUS_INSUFFICIENT_RESOURCES; + } PathNameU.Buffer = PathNameBuffer; PathNameU.Length = 0; - PathNameU.MaximumLength = sizeof(PathNameBuffer); + PathNameU.MaximumLength = PathNameBufferLength; DirContext->LongNameU.Length = 0; DirContext->ShortNameU.Length = 0; @@ -227,7 +231,12 @@ FindFile (PDEVICE_EXTENSION DeviceExt, rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU); if (rcFcb) { - if(rcFcb->startIndex >= DirContext->DirIndex) + ULONG startIndex = rcFcb->startIndex; + if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent)) + { + startIndex += 2; + } + if(startIndex >= DirContext->DirIndex) { RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU); RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU); @@ -235,7 +244,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt, DirContext->StartIndex = rcFcb->startIndex; DirContext->DirIndex = rcFcb->dirIndex; DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n", - &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex); + &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex); Status = STATUS_SUCCESS; } else @@ -244,10 +253,21 @@ FindFile (PDEVICE_EXTENSION DeviceExt, Status = STATUS_UNSUCCESSFUL; } vfatReleaseFCB(DeviceExt, rcFcb); + ExFreePool(PathNameBuffer); return Status; } } + /* FsRtlIsNameInExpression need the searched string to be upcase, + * even if IgnoreCase is specified */ + Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFindU, TRUE); + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + ExFreePool(PathNameBuffer); + return Status; + } + while(TRUE) { Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First); @@ -263,14 +283,13 @@ FindFile (PDEVICE_EXTENSION DeviceExt, } if (WildCard) { - Found = FsRtlIsNameInExpression(FileToFindU, &DirContext->LongNameU, TRUE, NULL) || - FsRtlIsNameInExpression(FileToFindU, &DirContext->ShortNameU, TRUE, NULL); + Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) || + FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->ShortNameU, TRUE, NULL); } else { - /* FIXME: Use FsRtlAreNamesEqual */ - Found = RtlEqualUnicodeString(&DirContext->LongNameU, FileToFindU, TRUE) || - RtlEqualUnicodeString(&DirContext->ShortNameU, FileToFindU, TRUE); + Found = FsRtlAreNamesEqual(&DirContext->LongNameU, FileToFindU, TRUE, NULL) || + FsRtlAreNamesEqual(&DirContext->ShortNameU, FileToFindU, TRUE, NULL); } if (Found) @@ -300,6 +319,8 @@ FindFile (PDEVICE_EXTENSION DeviceExt, { CcUnpinData(Context); } + RtlFreeUnicodeString(&FileToFindUpcase); + ExFreePool(PathNameBuffer); return STATUS_SUCCESS; } DirContext->DirIndex++; @@ -310,6 +331,8 @@ FindFile (PDEVICE_EXTENSION DeviceExt, CcUnpinData(Context); } + RtlFreeUnicodeString(&FileToFindUpcase); + ExFreePool(PathNameBuffer); return Status; } @@ -410,55 +433,6 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PVFATFCB* Pa return Status; } -VOID STATIC -VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, - PVFATFCB Fcb) -{ - ULONG Cluster, NextCluster; - NTSTATUS Status; - - if (Fcb->Flags & FCB_IS_FATX_ENTRY) - { - Fcb->entry.FatX.FileSize = 0; - Cluster = Fcb->entry.FatX.FirstCluster; - Fcb->entry.FatX.FirstCluster = 0; - } - else - { - Fcb->entry.Fat.FileSize = 0; - if (DeviceExt->FatInfo.FatType == FAT32) - { - Cluster = Fcb->entry.Fat.FirstCluster + Fcb->entry.Fat.FirstClusterHigh * 65536; - } - else - { - Cluster = Fcb->entry.Fat.FirstCluster; - } - Fcb->entry.Fat.FirstCluster = 0; - Fcb->entry.Fat.FirstClusterHigh = 0; - } - Fcb->LastOffset = Fcb->LastCluster = 0; - VfatUpdateEntry (Fcb); - if (Fcb->RFCB.FileSize.QuadPart > 0) - { - Fcb->RFCB.AllocationSize.QuadPart = 0; - Fcb->RFCB.FileSize.QuadPart = 0; - Fcb->RFCB.ValidDataLength.QuadPart = 0; - /* Notify cache manager about the change in file size if caching is - initialized on the file stream */ - if (FileObject->SectionObjectPointer->SharedCacheMap != NULL) - { - CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize); - } - } - while (Cluster != 0xffffffff && Cluster > 1) - { - Status = GetNextCluster (DeviceExt, Cluster, &NextCluster); - WriteCluster (DeviceExt, Cluster, 0); - Cluster = NextCluster; - } -} - NTSTATUS VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) /* @@ -516,7 +490,6 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) return (STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory(pCcb, sizeof(VFATCCB)); - FileObject->Flags |= FO_FCB_IS_VALID; FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers; FileObject->FsContext = pFcb; FileObject->FsContext2 = pCcb; @@ -717,7 +690,9 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) /* Supersede the file */ if (RequestedDisposition == FILE_SUPERSEDE) { - VfatSupersedeFile(DeviceExt, FileObject, pFcb); + LARGE_INTEGER AllocationSize; + AllocationSize.QuadPart = 0LL; + VfatSetAllocationSizeInformation(FileObject, pFcb, DeviceExt, &AllocationSize); Irp->IoStatus.Information = FILE_SUPERSEDED; } else if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) diff --git a/reactos/drivers/fs/vfat/dir.c b/reactos/drivers/fs/vfat/dir.c index d10ab848dde..064ff79e373 100644 --- a/reactos/drivers/fs/vfat/dir.c +++ b/reactos/drivers/fs/vfat/dir.c @@ -10,21 +10,16 @@ */ -#include -#include - #define NDEBUG -#include - #include "vfat.h" // function like DosDateTimeToFileTime -BOOL -FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, WORD wDosDate, WORD wDosTime, PLARGE_INTEGER SystemTime) +BOOLEAN +FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, USHORT DosDate, USHORT DosTime, PLARGE_INTEGER SystemTime) { - PDOSTIME pdtime = (PDOSTIME) & wDosTime; - PDOSDATE pddate = (PDOSDATE) & wDosDate; + PDOSTIME pdtime = (PDOSTIME) &DosTime; + PDOSDATE pddate = (PDOSDATE) &DosDate; TIME_FIELDS TimeFields; LARGE_INTEGER LocalTime; @@ -47,11 +42,11 @@ FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, WORD wDosDate, WORD wDo } // function like FileTimeToDosDateTime -BOOL -FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, WORD * pwDosDate, WORD * pwDosTime) +BOOLEAN +FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, USHORT *pDosDate, USHORT *pDosTime) { - PDOSTIME pdtime = (PDOSTIME) pwDosTime; - PDOSDATE pddate = (PDOSDATE) pwDosDate; + PDOSTIME pdtime = (PDOSTIME) pDosTime; + PDOSDATE pddate = (PDOSDATE) pDosDate; TIME_FIELDS TimeFields; LARGE_INTEGER LocalTime; @@ -72,13 +67,13 @@ FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTi { pddate->Day = TimeFields.Day; pddate->Month = TimeFields.Month; - pddate->Year = TimeFields.Year - DeviceExt->BaseDateYear; + pddate->Year = (USHORT) (TimeFields.Year - DeviceExt->BaseDateYear); } return TRUE; } -#define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD))) +#define ULONG_ROUND_UP(x) ROUND_UP((x), (sizeof(ULONG))) NTSTATUS VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext, @@ -88,7 +83,7 @@ VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext, return STATUS_BUFFER_OVERFLOW; pInfo->FileNameLength = DirContext->LongNameU.Length; pInfo->NextEntryOffset = - DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); + ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length); return STATUS_SUCCESS; } @@ -103,7 +98,7 @@ VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext, return STATUS_BUFFER_OVERFLOW; pInfo->FileNameLength = DirContext->LongNameU.Length; pInfo->NextEntryOffset = - DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); + ULONG_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length); // pInfo->FileIndex=; if (DeviceExt->Flags & VCB_IS_FATX) @@ -166,14 +161,14 @@ VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext, NTSTATUS VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext, PDEVICE_EXTENSION DeviceExt, - PFILE_FULL_DIRECTORY_INFORMATION pInfo, + PFILE_FULL_DIR_INFORMATION pInfo, ULONG BufferLength) { - if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) + if ((sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) return STATUS_BUFFER_OVERFLOW; pInfo->FileNameLength = DirContext->LongNameU.Length; pInfo->NextEntryOffset = - DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); + ULONG_ROUND_UP (sizeof (FILE_FULL_DIR_INFORMATION) + DirContext->LongNameU.Length); RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length); // pInfo->FileIndex=; if (DeviceExt->Flags & VCB_IS_FATX) @@ -220,10 +215,10 @@ VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext, NTSTATUS VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext, PDEVICE_EXTENSION DeviceExt, - PFILE_BOTH_DIRECTORY_INFORMATION pInfo, + PFILE_BOTH_DIR_INFORMATION pInfo, ULONG BufferLength) { - if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) + if ((sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length) > BufferLength) return STATUS_BUFFER_OVERFLOW; if (DeviceExt->Flags & VCB_IS_FATX) @@ -231,7 +226,7 @@ VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext, pInfo->FileNameLength = DirContext->LongNameU.Length; RtlCopyMemory(pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length); pInfo->NextEntryOffset = - DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); + ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length); pInfo->ShortName[0] = 0; pInfo->ShortNameLength = 0; // pInfo->FileIndex=; @@ -264,7 +259,7 @@ VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext, { pInfo->FileNameLength = DirContext->LongNameU.Length; pInfo->NextEntryOffset = - DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length); + ULONG_ROUND_UP (sizeof (FILE_BOTH_DIR_INFORMATION) + DirContext->LongNameU.Length); RtlCopyMemory(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length); pInfo->ShortNameLength = DirContext->ShortNameU.Length; RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length); @@ -311,7 +306,7 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) BOOLEAN First = FALSE; BOOLEAN FirstCall; VFAT_DIRENTRY_CONTEXT DirContext; - WCHAR LongNameBuffer[MAX_PATH]; + WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1]; WCHAR ShortNameBuffer[13]; PIO_STACK_LOCATION Stack = IrpContext->Stack; @@ -344,7 +339,13 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) } /* Obtain the callers parameters */ +#ifdef _MSC_VER + /* HACKHACK: Bug in the MS ntifs.h header: + * FileName is really a PUNICODE_STRING, not a PSTRING */ + pSearchPattern = (PUNICODE_STRING)Stack->Parameters.QueryDirectory.FileName; +#else pSearchPattern = Stack->Parameters.QueryDirectory.FileName; +#endif FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass; FileIndex = Stack->Parameters.QueryDirectory.FileIndex; @@ -427,13 +428,13 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) case FileFullDirectoryInformation: RC = VfatGetFileFullDirectoryInformation (&DirContext, IrpContext->DeviceExt, - (PFILE_FULL_DIRECTORY_INFORMATION) Buffer, + (PFILE_FULL_DIR_INFORMATION) Buffer, BufferLength); break; case FileBothDirectoryInformation: RC = VfatGetFileBothInformation (&DirContext, IrpContext->DeviceExt, - (PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, + (PFILE_BOTH_DIR_INFORMATION) Buffer, BufferLength); break; default: diff --git a/reactos/drivers/fs/vfat/direntry.c b/reactos/drivers/fs/vfat/direntry.c index 273dd85de14..f3efe7f3ecf 100644 --- a/reactos/drivers/fs/vfat/direntry.c +++ b/reactos/drivers/fs/vfat/direntry.c @@ -13,13 +13,7 @@ /* ------------------------------------------------------- INCLUDES */ -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" ULONG @@ -45,7 +39,7 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, return cluster; } -BOOL FATIsDirectoryEmpty(PVFATFCB Fcb) +BOOLEAN FATIsDirectoryEmpty(PVFATFCB Fcb) { LARGE_INTEGER FileOffset; PVOID Context = NULL; @@ -98,7 +92,7 @@ BOOL FATIsDirectoryEmpty(PVFATFCB Fcb) return TRUE; } -BOOL FATXIsDirectoryEmpty(PVFATFCB Fcb) +BOOLEAN FATXIsDirectoryEmpty(PVFATFCB Fcb) { LARGE_INTEGER FileOffset; PVOID Context = NULL; @@ -144,7 +138,7 @@ BOOL FATXIsDirectoryEmpty(PVFATFCB Fcb) return TRUE; } -BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb) +BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb) { if (Fcb->Flags & FCB_IS_FATX_ENTRY) return FATXIsDirectoryEmpty(Fcb); @@ -181,7 +175,8 @@ NTSTATUS FATGetNextDirEntry(PVOID * pContext, { CcUnpinData(*pContext); } - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { *pContext = NULL; return STATUS_NO_MORE_ENTRIES; @@ -210,7 +205,8 @@ NTSTATUS FATGetNextDirEntry(PVOID * pContext, { CcUnpinData(*pContext); FileOffset.u.LowPart -= PAGE_SIZE; - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { CHECKPOINT; *pContext = NULL; @@ -234,7 +230,8 @@ NTSTATUS FATGetNextDirEntry(PVOID * pContext, { CcUnpinData(*pContext); FileOffset.u.LowPart += PAGE_SIZE; - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { CHECKPOINT; *pContext = NULL; @@ -331,7 +328,8 @@ NTSTATUS FATGetNextDirEntry(PVOID * pContext, { CcUnpinData(*pContext); FileOffset.u.LowPart += PAGE_SIZE; - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { CHECKPOINT; *pContext = NULL; @@ -367,7 +365,6 @@ NTSTATUS FATXGetNextDirEntry(PVOID * pContext, ULONG DirIndex = DirContext->DirIndex; FileOffset.u.HighPart = 0; - FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE); if (!vfatFCBIsRoot(pDirFcb)) { @@ -409,7 +406,9 @@ NTSTATUS FATXGetNextDirEntry(PVOID * pContext, { CcUnpinData(*pContext); } - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + FileOffset.u.LowPart = ROUND_DOWN(DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE); + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { *pContext = NULL; return STATUS_NO_MORE_ENTRIES; @@ -418,33 +417,35 @@ NTSTATUS FATXGetNextDirEntry(PVOID * pContext, fatxDirEntry = (PFATX_DIR_ENTRY)(*pPage) + DirIndex % FATX_ENTRIES_PER_PAGE; - DirContext->StartIndex = DirIndex; + DirContext->StartIndex = DirContext->DirIndex; while (TRUE) { - if (FATX_ENTRY_END(fatxDirEntry)) - { - CcUnpinData(*pContext); - *pContext = NULL; - return STATUS_NO_MORE_ENTRIES; - } + if (FATX_ENTRY_END(fatxDirEntry)) + { + CcUnpinData(*pContext); + *pContext = NULL; + return STATUS_NO_MORE_ENTRIES; + } - if (!FATX_ENTRY_DELETED(fatxDirEntry)) - { - RtlCopyMemory(&DirContext->DirEntry.FatX, fatxDirEntry, sizeof(FATX_DIR_ENTRY)); - break; + if (!FATX_ENTRY_DELETED(fatxDirEntry)) + { + RtlCopyMemory(&DirContext->DirEntry.FatX, fatxDirEntry, sizeof(FATX_DIR_ENTRY)); + break; } - DirContext->DirIndex++; - DirContext->StartIndex++; - if ((DirContext->DirIndex % FATX_ENTRIES_PER_PAGE) == 0) + DirContext->DirIndex++; + DirContext->StartIndex++; + DirIndex++; + if ((DirIndex % FATX_ENTRIES_PER_PAGE) == 0) { CcUnpinData(*pContext); FileOffset.u.LowPart += PAGE_SIZE; - if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) + if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || + !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { CHECKPOINT; - *pContext = NULL; - return STATUS_NO_MORE_ENTRIES; + *pContext = NULL; + return STATUS_NO_MORE_ENTRIES; } fatxDirEntry = (PFATX_DIR_ENTRY)*pPage; } diff --git a/reactos/drivers/fs/vfat/dirwr.c b/reactos/drivers/fs/vfat/dirwr.c index 649a9552201..b907f3bec91 100644 --- a/reactos/drivers/fs/vfat/dirwr.c +++ b/reactos/drivers/fs/vfat/dirwr.c @@ -9,14 +9,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" NTSTATUS @@ -47,9 +40,16 @@ VfatUpdateEntry (PVFATFCB pFcb) DPRINT ("updEntry dirIndex %d, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU); + if (vfatFCBIsRoot(pFcb) || (pFcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME))) + { + return STATUS_SUCCESS; + } + + ASSERT (pFcb->parrentFcb); + Offset.u.HighPart = 0; Offset.u.LowPart = dirIndex * SizeDirEntry; - if (CcMapData (pFcb->parentFcb->FileObject, &Offset, SizeDirEntry, + if (CcPinRead (pFcb->parentFcb->FileObject, &Offset, SizeDirEntry, TRUE, &Context, (PVOID*)&PinEntry)) { pFcb->Flags &= ~FCB_IS_DIRTY; @@ -99,7 +99,7 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, CcUnpinData(Context); } // FIXME: check return value - CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + CcPinRead (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, &Context, (PVOID*)&pFatEntry); FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster; } @@ -151,9 +151,9 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, return FALSE; } // clear the new dir cluster - FileOffset.u.LowPart = (DWORD)(pDirFcb->RFCB.FileSize.QuadPart - + FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart - DeviceExt->FatInfo.BytesPerCluster); - CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + CcPinRead (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, &Context, (PVOID*)&pFatEntry); if (DeviceExt->Flags & VCB_IS_FATX) memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster); @@ -164,7 +164,7 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, { // clear the entry after the last new entry FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry; - CcMapData (pDirFcb->FileObject, &FileOffset, SizeDirEntry, + CcPinRead (pDirFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&pFatEntry); if (DeviceExt->Flags & VCB_IS_FATX) memset(pFatEntry, 0xff, SizeDirEntry); @@ -195,7 +195,7 @@ FATAddEntry (PDEVICE_EXTENSION DeviceExt, PVOID Context = NULL; PFAT_DIR_ENTRY pFatEntry; slot *pSlots; - short nbSlots = 0, j, posCar; + USHORT nbSlots = 0, j, posCar; PUCHAR Buffer; BOOLEAN needTilde = FALSE, needLong = FALSE; BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt; @@ -211,7 +211,7 @@ FATAddEntry (PDEVICE_EXTENSION DeviceExt, BOOLEAN SpacesFound; VFAT_DIRENTRY_CONTEXT DirContext; - WCHAR LongNameBuffer[MAX_PATH]; + WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1]; WCHAR ShortNameBuffer[13]; DPRINT ("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU); @@ -402,11 +402,11 @@ FATAddEntry (PDEVICE_EXTENSION DeviceExt, pSlots[i].attr = 0xf; if (i) { - pSlots[i].id = nbSlots - i - 1; + pSlots[i].id = (unsigned char)(nbSlots - i - 1); } else { - pSlots[i].id = nbSlots - i - 1 + 0x40; + pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40); } pSlots[i].alias_checksum = pSlots[0].alias_checksum; RtlCopyMemory (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10); @@ -448,7 +448,7 @@ FATAddEntry (PDEVICE_EXTENSION DeviceExt, { /* one cluster */ CHECKPOINT; - CcMapData (ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY), + CcPinRead (ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY), TRUE, &Context, (PVOID*)&pFatEntry); if (nbSlots > 1) { @@ -463,13 +463,13 @@ FATAddEntry (PDEVICE_EXTENSION DeviceExt, size = DeviceExt->FatInfo.BytesPerCluster - (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster; i = size / sizeof(FAT_DIR_ENTRY); - CcMapData (ParentFcb->FileObject, &FileOffset, size, TRUE, + CcPinRead (ParentFcb->FileObject, &FileOffset, size, TRUE, &Context, (PVOID*)&pFatEntry); RtlCopyMemory(pFatEntry, Buffer, size); CcSetDirtyPinnedData(Context, NULL); CcUnpinData(Context); FileOffset.u.LowPart += size; - CcMapData (ParentFcb->FileObject, &FileOffset, + CcPinRead (ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY) - size, TRUE, &Context, (PVOID*)&pFatEntry); if (nbSlots - 1 > i) @@ -551,6 +551,7 @@ FATXAddEntry (PDEVICE_EXTENSION DeviceExt, if (!vfatFCBIsRoot(ParentFcb)) { DirContext.DirIndex += 2; + DirContext.StartIndex += 2; } DirContext.ShortNameU.Buffer = 0; @@ -566,7 +567,7 @@ FATXAddEntry (PDEVICE_EXTENSION DeviceExt, NameA.Length = 0; NameA.MaximumLength = 42; RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE); - DirContext.DirEntry.FatX.FilenameLength = NameA.Length; + DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length; /* set attributes */ DirContext.DirEntry.FatX.Attrib = ReqAttr; @@ -587,7 +588,7 @@ FATXAddEntry (PDEVICE_EXTENSION DeviceExt, /* add entry into parent directory */ FileOffset.u.HighPart = 0; FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATX_DIR_ENTRY); - CcMapData(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), + CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), TRUE, &Context, (PVOID*)&pFatXDirEntry); RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY)); CcSetDirtyPinnedData(Context, NULL); @@ -641,7 +642,7 @@ FATDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb) CcUnpinData(Context); } Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE; - CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE, + CcPinRead (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE, &Context, (PVOID*)&pDirEntry); } pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5; @@ -690,10 +691,10 @@ FATXDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb) DPRINT ("delete entry: %d\n", StartIndex); Offset.u.HighPart = 0; Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE; - if (!CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE, + if (!CcPinRead (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE, &Context, (PVOID*)&pDirEntry)) { - DPRINT1("CcMapData(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE); + DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE); return STATUS_UNSUCCESSFUL; } pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))]; diff --git a/reactos/drivers/fs/vfat/ea.c b/reactos/drivers/fs/vfat/ea.c index 93058681071..e597d4b27f4 100644 --- a/reactos/drivers/fs/vfat/ea.c +++ b/reactos/drivers/fs/vfat/ea.c @@ -27,13 +27,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS *****************************************************************/ diff --git a/reactos/drivers/fs/vfat/fastio.c b/reactos/drivers/fs/vfat/fastio.c new file mode 100644 index 00000000000..6d7b0010734 --- /dev/null +++ b/reactos/drivers/fs/vfat/fastio.c @@ -0,0 +1,399 @@ +/* $Id$ + * + * + * FILE: drivers/fs/vfat/fastio.c + * PURPOSE: Fast IO routines. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PROGRAMMER: Herve Poussineau (reactos@poussine.freesurf.fr) + * Hartmut Birr + */ + +#define NDEBUG +#include "vfat.h" + +BOOLEAN STDCALL +VfatFastIoCheckIfPossible(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Lenght, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN BOOLEAN CheckForReadOperation, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + /* Prevent all Fast I/O requests */ + DPRINT("VfatFastIoCheckIfPossible(): returning FALSE.\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoRead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoRead()\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoWrite()\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoQueryBasicInfo(IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_BASIC_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoQueryBasicInfo()\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoQueryStandardInfo(IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_STANDARD_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoQueryStandardInfo\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoLock(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + PEPROCESS ProcessId, + ULONG Key, + BOOLEAN FailImmediately, + BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoLock\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoUnlockSingle(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + PEPROCESS ProcessId, + ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoUnlockSingle\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoUnlockAll(IN PFILE_OBJECT FileObject, + PEPROCESS ProcessId, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoUnlockAll\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoUnlockAllByKey(IN PFILE_OBJECT FileObject, + PEPROCESS ProcessId, + ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoUnlockAllByKey\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoDeviceControl(IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength, + IN ULONG IoControlCode, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoDeviceControl\n"); + return FALSE; +} + +VOID STDCALL +VfatAcquireFileForNtCreateSection(IN PFILE_OBJECT FileObject) +{ + DPRINT("VfatAcquireFileForNtCreateSection\n"); +} + +VOID STDCALL +VfatReleaseFileForNtCreateSection(IN PFILE_OBJECT FileObject) +{ + DPRINT("VfatReleaseFileForNtCreateSection\n"); +} + +VOID STDCALL +VfatFastIoDetachDevice(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice) +{ + DPRINT("VfatFastIoDetachDevice\n"); +} + +BOOLEAN STDCALL +VfatFastIoQueryNetworkOpenInfo(IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoQueryNetworkOpenInfo\n"); + return FALSE; +} + +NTSTATUS STDCALL +VfatAcquireForModWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT PERESOURCE* ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatAcquireForModWrite\n"); + return STATUS_UNSUCCESSFUL; +} + +BOOLEAN STDCALL +VfatMdlRead(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL* MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatMdlRead\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatMdlReadComplete(IN PFILE_OBJECT FileObject, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatMdlReadComplete\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatPrepareMdlWrite(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL* MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatPrepareMdlWrite\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatMdlWriteComplete(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatMdlWriteComplete\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoReadCompressed(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PMDL* MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoReadCompressed\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoWriteCompressed(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PMDL* MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoWriteCompressed\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatMdlReadCompleteCompressed(IN PFILE_OBJECT FileObject, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatMdlReadCompleteCompressed\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatMdlWriteCompleteCompressed(IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatMdlWriteCompleteCompressed\n"); + return FALSE; +} + +BOOLEAN STDCALL +VfatFastIoQueryOpen(IN PIRP Irp, + OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatFastIoQueryOpen\n"); + return FALSE; +} + +NTSTATUS STDCALL +VfatReleaseForModWrite(IN PFILE_OBJECT FileObject, + IN PERESOURCE ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatReleaseForModWrite\n"); + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS STDCALL +VfatAcquireForCcFlush(IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatAcquireForCcFlush\n"); + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS STDCALL +VfatReleaseForCcFlush(IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject) +{ + DPRINT("VfatReleaseForCcFlush\n"); + return STATUS_UNSUCCESSFUL; +} + +BOOLEAN STDCALL +VfatAcquireForLazyWrite(IN PVOID Context, + IN BOOLEAN Wait) +{ + PVFATFCB Fcb = (PVFATFCB)Context; + ASSERT(Fcb); + DPRINT("VfatAcquireForLazyWrite(): Fcb %p\n", Fcb); + + if (!ExAcquireResourceExclusiveLite(&(Fcb->MainResource), Wait)) + { + DPRINT("VfatAcquireForLazyWrite(): ExReleaseResourceLite failed.\n"); + return FALSE; + } + return TRUE; +} + +VOID STDCALL +VfatReleaseFromLazyWrite(IN PVOID Context) +{ + PVFATFCB Fcb = (PVFATFCB)Context; + ASSERT(Fcb); + DPRINT("VfatReleaseFromLazyWrite(): Fcb %p\n", Fcb); + + ExReleaseResourceLite(&(Fcb->MainResource)); +} + +BOOLEAN STDCALL +VfatAcquireForReadAhead(IN PVOID Context, + IN BOOLEAN Wait) +{ + PVFATFCB Fcb = (PVFATFCB)Context; + ASSERT(Fcb); + DPRINT("VfatAcquireForReadAhead(): Fcb %p\n", Fcb); + + if (!ExAcquireResourceExclusiveLite(&(Fcb->MainResource), Wait)) + { + DPRINT("VfatAcquireForReadAhead(): ExReleaseResourceLite failed.\n"); + return FALSE; + } + return TRUE; +} + +VOID STDCALL +VfatReleaseFromReadAhead(IN PVOID Context) +{ + PVFATFCB Fcb = (PVFATFCB)Context; + ASSERT(Fcb); + DPRINT("VfatReleaseFromReadAhead(): Fcb %p\n", Fcb); + + ExReleaseResourceLite(&(Fcb->MainResource)); +} + +VOID +VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch) +{ + FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); + FastIoDispatch->FastIoCheckIfPossible = VfatFastIoCheckIfPossible; + FastIoDispatch->FastIoRead = VfatFastIoRead; + FastIoDispatch->FastIoWrite = VfatFastIoWrite; + FastIoDispatch->FastIoQueryBasicInfo = VfatFastIoQueryBasicInfo; + FastIoDispatch->FastIoQueryStandardInfo = VfatFastIoQueryStandardInfo; + FastIoDispatch->FastIoLock = VfatFastIoLock; + FastIoDispatch->FastIoUnlockSingle = VfatFastIoUnlockSingle; + FastIoDispatch->FastIoUnlockAll = VfatFastIoUnlockAll; + FastIoDispatch->FastIoUnlockAllByKey = VfatFastIoUnlockAllByKey; + FastIoDispatch->FastIoDeviceControl = VfatFastIoDeviceControl; + FastIoDispatch->AcquireFileForNtCreateSection = VfatAcquireFileForNtCreateSection; + FastIoDispatch->ReleaseFileForNtCreateSection = VfatReleaseFileForNtCreateSection; + FastIoDispatch->FastIoDetachDevice = VfatFastIoDetachDevice; + FastIoDispatch->FastIoQueryNetworkOpenInfo = VfatFastIoQueryNetworkOpenInfo; + FastIoDispatch->AcquireForModWrite = VfatAcquireForModWrite; + FastIoDispatch->MdlRead = VfatMdlRead; + FastIoDispatch->MdlReadComplete = VfatMdlReadComplete; + FastIoDispatch->PrepareMdlWrite = VfatPrepareMdlWrite; + FastIoDispatch->MdlWriteComplete = VfatMdlWriteComplete; + FastIoDispatch->FastIoReadCompressed = VfatFastIoReadCompressed; + FastIoDispatch->FastIoWriteCompressed = VfatFastIoWriteCompressed; + FastIoDispatch->MdlReadCompleteCompressed = VfatMdlReadCompleteCompressed; + FastIoDispatch->MdlWriteCompleteCompressed = VfatMdlWriteCompleteCompressed; + FastIoDispatch->FastIoQueryOpen = VfatFastIoQueryOpen; + FastIoDispatch->ReleaseForModWrite = VfatReleaseForModWrite; + FastIoDispatch->AcquireForCcFlush = VfatAcquireForCcFlush; + FastIoDispatch->ReleaseForCcFlush = VfatReleaseForCcFlush; +} + + diff --git a/reactos/drivers/fs/vfat/fat.c b/reactos/drivers/fs/vfat/fat.c index 433f21324b4..27ebe3f1d3a 100644 --- a/reactos/drivers/fs/vfat/fat.c +++ b/reactos/drivers/fs/vfat/fat.c @@ -12,13 +12,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* GLOBALS ******************************************************************/ @@ -157,7 +151,7 @@ FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, for (i = StartCluster; i < FatLength; ) { Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize); - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); return STATUS_UNSUCCESSFUL; @@ -209,7 +203,7 @@ FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster) *Cluster = 0; StartCluster = DeviceExt->LastAvailableCluster; Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector); return STATUS_UNSUCCESSFUL; @@ -274,7 +268,7 @@ FAT32FindAndMarkAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster) for (i = StartCluster; i < FatLength;) { Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize); - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); return STATUS_UNSUCCESSFUL; @@ -491,7 +485,7 @@ FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, LARGE_INTEGER Offset; Offset.QuadPart = 0; - if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } @@ -540,7 +534,7 @@ FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ChunkSize = CACHEPAGESIZE(DeviceExt); FATOffset = ClusterToWrite * 2; Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } @@ -574,7 +568,7 @@ FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, FATOffset = (ClusterToWrite * 4); Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); - if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) { return STATUS_UNSUCCESSFUL; } diff --git a/reactos/drivers/fs/vfat/fcb.c b/reactos/drivers/fs/vfat/fcb.c index a3687d48c9b..ecffdcbb68e 100644 --- a/reactos/drivers/fs/vfat/fcb.c +++ b/reactos/drivers/fs/vfat/fcb.c @@ -13,20 +13,13 @@ /* ------------------------------------------------------- INCLUDES */ -#include -#include -#include -#include -#include +#include /* towlower prototype */ #define NDEBUG -#include - #include "vfat.h" /* -------------------------------------------------------- DEFINES */ -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) #define TAG_FCB TAG('V', 'F', 'C', 'B') #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) @@ -55,7 +48,7 @@ VOID vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU) { PWCHAR pName; - ULONG Length = 0; + USHORT Length = 0; pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1; while (*pName != L'\\' && pName >= PathNameU->Buffer) { @@ -79,9 +72,24 @@ vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_ VOID vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU) { + ULONG PathNameBufferLength; + + if (NameU) + PathNameBufferLength = NameU->Length + sizeof(WCHAR); + else + PathNameBufferLength = 0; + + Fcb->PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength); + if (!Fcb->PathNameBuffer) + { + /* FIXME: what to do if no more memory? */ + DPRINT1("Unable to initialize FCB for filename '%wZ'\n", NameU); + KEBUGCHECKEX(0, (ULONG_PTR)Fcb, (ULONG_PTR)NameU, 0, 0); + } + Fcb->PathNameU.Length = 0; Fcb->PathNameU.Buffer = Fcb->PathNameBuffer; - Fcb->PathNameU.MaximumLength = sizeof(Fcb->PathNameBuffer); + Fcb->PathNameU.MaximumLength = PathNameBufferLength; Fcb->ShortNameU.Length = 0; Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer; Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer); @@ -129,6 +137,10 @@ vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU) ExInitializeResourceLite(&rcFCB->MainResource); FsRtlInitializeFileLock(&rcFCB->FileLock, NULL, NULL); ExInitializeFastMutex(&rcFCB->LastMutex); + rcFCB->RFCB.PagingIoResource = &rcFCB->PagingIoResource; + rcFCB->RFCB.Resource = &rcFCB->MainResource; + rcFCB->RFCB.IsFastIoPossible = FastIoIsNotPossible; + return rcFCB; } @@ -146,18 +158,19 @@ VOID vfatDestroyFCB(PVFATFCB pFCB) { FsRtlUninitializeFileLock(&pFCB->FileLock); + ExFreePool(pFCB->PathNameBuffer); ExDeleteResourceLite(&pFCB->PagingIoResource); ExDeleteResourceLite(&pFCB->MainResource); ExFreeToNPagedLookasideList(&VfatGlobalData->FcbLookasideList, pFCB); } -BOOL +BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB) { return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY; } -BOOL +BOOLEAN vfatFCBIsRoot(PVFATFCB FCB) { return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE; @@ -219,7 +232,11 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) /* Uninitialize file cache if initialized for this file object. */ if (pFCB->FileObject->SectionObjectPointer->SharedCacheMap) { +#ifdef USE_ROS_CC_AND_FS CcRosReleaseFileCache(pFCB->FileObject); +#else + CcUninitializeCacheMap(pFCB->FileObject, NULL, NULL); +#endif } vfatDestroyCCB(pFCB->FileObject->FsContext2); pFCB->FileObject->FsContext2 = NULL; @@ -316,9 +333,11 @@ vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU) NTSTATUS vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb) { +#ifdef USE_ROS_CC_AND_FS NTSTATUS status; - PFILE_OBJECT fileObject; ULONG fileCacheQuantum; +#endif + PFILE_OBJECT fileObject; PVFATCCB newCCB; fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice); @@ -330,13 +349,12 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb) } RtlZeroMemory(newCCB, sizeof (VFATCCB)); - fileObject->Flags |= FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; fileObject->SectionObjectPointer = &fcb->SectionObjectPointers; fileObject->FsContext = fcb; fileObject->FsContext2 = newCCB; fcb->FileObject = fileObject; - +#ifdef USE_ROS_CC_AND_FS fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGE_SIZE) ? vcb->FatInfo.BytesPerCluster : PAGE_SIZE; @@ -347,10 +365,22 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb) DbgPrint ("CcRosInitializeFileCache failed\n"); KEBUGCHECK (0); } +#else + /* FIXME: Guard by SEH. */ + CcInitializeCacheMap(fileObject, + (PCC_FILE_SIZES)(&fcb->RFCB.AllocationSize), + FALSE, + &VfatGlobalData->CacheMgrCallbacks, + fcb); +#endif fcb->Flags |= FCB_CACHE_INITIALIZED; +#ifdef USE_ROS_CC_AND_FS return status; +#else + return STATUS_SUCCESS; +#endif } PVFATFCB @@ -359,9 +389,7 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB) PVFATFCB FCB; ULONG FirstCluster, CurrentCluster, Size = 0; NTSTATUS Status = STATUS_SUCCESS; - UNICODE_STRING NameU; - - RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\"); + UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\"); FCB = vfatNewFCB(pVCB, &NameU); if (FCB->Flags & FCB_IS_FATX_ENTRY) @@ -401,6 +429,7 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB) FCB->RFCB.FileSize.QuadPart = Size; FCB->RFCB.ValidDataLength.QuadPart = Size; FCB->RFCB.AllocationSize.QuadPart = Size; + FCB->RFCB.IsFastIoPossible = FastIoIsNotPossible; vfatFCBInitializeCacheFromVolume(pVCB, FCB); vfatAddFCBToTable(pVCB, FCB); @@ -412,9 +441,7 @@ PVFATFCB vfatOpenRootFCB(PDEVICE_EXTENSION pVCB) { PVFATFCB FCB; - UNICODE_STRING NameU; - - RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\"); + UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\"); FCB = vfatGrabFCBFromTable (pVCB, &NameU); if (FCB == NULL) @@ -432,20 +459,31 @@ vfatMakeFCBFromDirEntry(PVCB vcb, PVFATFCB* fileFCB) { PVFATFCB rcFCB; - WCHAR pathName [MAX_PATH]; + PWCHAR PathNameBuffer; + ULONG PathNameLength; ULONG Size; ULONG hash; UNICODE_STRING NameU; - if (directoryFCB->PathNameU.Length + 2 * sizeof(WCHAR) + - + DirContext->LongNameU.Length > MAX_PATH * sizeof(WCHAR)) + PathNameLength = directoryFCB->PathNameU.Length + max(DirContext->LongNameU.Length, DirContext->ShortNameU.Length); + if (!vfatFCBIsRoot (directoryFCB)) + { + PathNameLength += sizeof(WCHAR); + } + + if (PathNameLength > LONGNAME_MAX_LENGTH * sizeof(WCHAR)) { return STATUS_OBJECT_NAME_INVALID; } - NameU.Buffer = pathName; + PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameLength + sizeof(WCHAR)); + if (!PathNameBuffer) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + NameU.Buffer = PathNameBuffer; NameU.Length = 0; - NameU.MaximumLength = sizeof(pathName); + NameU.MaximumLength = PathNameLength; RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU); if (!vfatFCBIsRoot (directoryFCB)) @@ -505,6 +543,12 @@ vfatMakeFCBFromDirEntry(PVCB vcb, } rcFCB->dirIndex = DirContext->DirIndex; rcFCB->startIndex = DirContext->StartIndex; + if ((rcFCB->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot (directoryFCB)) + { + ASSERT(DirContext->DirIndex >= 2 && DirContext->StartIndex >= 2); + rcFCB->dirIndex = DirContext->DirIndex-2; + rcFCB->startIndex = DirContext->StartIndex-2; + } rcFCB->RFCB.FileSize.QuadPart = Size; rcFCB->RFCB.ValidDataLength.QuadPart = Size; rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); @@ -517,6 +561,7 @@ vfatMakeFCBFromDirEntry(PVCB vcb, vfatAddFCBToTable (vcb, rcFCB); *fileFCB = rcFCB; + ExFreePool(PathNameBuffer); return STATUS_SUCCESS; } @@ -535,8 +580,6 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, } RtlZeroMemory (newCCB, sizeof (VFATCCB)); - fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID | - FO_DIRECT_CACHE_PAGING_READ; fileObject->SectionObjectPointer = &fcb->SectionObjectPointers; fileObject->FsContext = fcb; fileObject->FsContext2 = newCCB; @@ -556,7 +599,9 @@ vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt, PVOID Page = NULL; BOOLEAN First = TRUE; VFAT_DIRENTRY_CONTEXT DirContext; - WCHAR LongNameBuffer[MAX_PATH]; + /* This buffer must have a size of 260 characters, because + vfatMakeFCBFromDirEntry can copy 20 name entries with 13 characters. */ + WCHAR LongNameBuffer[260]; WCHAR ShortNameBuffer[13]; BOOLEAN FoundLong = FALSE; BOOLEAN FoundShort = FALSE; @@ -634,7 +679,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, PVFATFCB FCB = NULL; PVFATFCB parentFCB; UNICODE_STRING NameU; - UNICODE_STRING RootNameU; + UNICODE_STRING RootNameU = RTL_CONSTANT_STRING(L"\\"); PWCHAR curr, prev, last; ULONG Length; @@ -648,8 +693,6 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, if (parentFCB == NULL) { - RtlRosInitUnicodeStringFromLiteral(&RootNameU, L"\\"); - // Trivial case, open of the root directory on volume if (RtlEqualUnicodeString(pFileNameU, &RootNameU, FALSE)) { @@ -693,9 +736,9 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, vfatReleaseFCB (pVCB, FCB); return STATUS_OBJECT_NAME_INVALID; } - memmove(pFileNameU->Buffer + FCB->PathNameU.Length / sizeof(WCHAR), + RtlMoveMemory(pFileNameU->Buffer + FCB->PathNameU.Length / sizeof(WCHAR), curr, pFileNameU->Length - Length); - pFileNameU->Length += FCB->PathNameU.Length - Length; + pFileNameU->Length += (USHORT)(FCB->PathNameU.Length - Length); curr = pFileNameU->Buffer + FCB->PathNameU.Length / sizeof(WCHAR); last = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1; } @@ -754,9 +797,9 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, vfatReleaseFCB (pVCB, parentFCB); return STATUS_OBJECT_NAME_INVALID; } - memmove(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr, + RtlMoveMemory(prev + parentFCB->LongNameU.Length / sizeof(WCHAR), curr, pFileNameU->Length - (curr - pFileNameU->Buffer) * sizeof(WCHAR)); - pFileNameU->Length += parentFCB->LongNameU.Length - Length; + pFileNameU->Length += (USHORT)(parentFCB->LongNameU.Length - Length); curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR); last = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1; } diff --git a/reactos/drivers/fs/vfat/finfo.c b/reactos/drivers/fs/vfat/finfo.c index 3c4b2baa2f3..1f8015fe8c9 100644 --- a/reactos/drivers/fs/vfat/finfo.c +++ b/reactos/drivers/fs/vfat/finfo.c @@ -12,14 +12,57 @@ /* INCLUDES *****************************************************************/ -#include -#include - #define NDEBUG -#include - #include "vfat.h" +/* GLOBALS ******************************************************************/ + +const char* FileInformationClassNames[] = +{ + "??????", + "FileDirectoryInformation", + "FileFullDirectoryInformation", + "FileBothDirectoryInformation", + "FileBasicInformation", + "FileStandardInformation", + "FileInternalInformation", + "FileEaInformation", + "FileAccessInformation", + "FileNameInformation", + "FileRenameInformation", + "FileLinkInformation", + "FileNamesInformation", + "FileDispositionInformation", + "FilePositionInformation", + "FileFullEaInformation", + "FileModeInformation", + "FileAlignmentInformation", + "FileAllInformation", + "FileAllocationInformation", + "FileEndOfFileInformation", + "FileAlternateNameInformation", + "FileStreamInformation", + "FilePipeInformation", + "FilePipeLocalInformation", + "FilePipeRemoteInformation", + "FileMailslotQueryInformation", + "FileMailslotSetInformation", + "FileCompressionInformation", + "FileObjectIdInformation", + "FileCompletionInformation", + "FileMoveClusterInformation", + "FileQuotaInformation", + "FileReparsePointInformation", + "FileNetworkOpenInformation", + "FileAttributeTagInformation", + "FileTrackingInformation", + "FileIdBothDirectoryInformation", + "FileIdFullDirectoryInformation", + "FileValidDataLengthInformation", + "FileShortNameInformation", + "FileMaximumInformation" +}; + /* FUNCTIONS ****************************************************************/ static NTSTATUS @@ -226,8 +269,9 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject, PFILE_DISPOSITION_INFORMATION DispositionInfo) { NTSTATUS Status = STATUS_SUCCESS; - +#ifdef DBG PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; +#endif DPRINT ("FsdSetDispositionInformation()\n"); @@ -248,13 +292,13 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject, return STATUS_ACCESS_DENIED; } - if (DispositionInfo->DoDeleteFile) + if (DispositionInfo->DeleteFile) { if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete)) { - if (FCB->RefCount > 1) + if (FCB->OpenHandleCount > 1) { - DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer)); + DPRINT1("%d %x\n", FCB->OpenHandleCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer)); Status = STATUS_ACCESS_DENIED; } else @@ -479,7 +523,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster; ULONG NewSize = AllocationSize->u.LowPart; ULONG NCluster; - BOOL AllocSizeChanged = FALSE; + BOOLEAN AllocSizeChanged = FALSE; DPRINT("VfatSetAllocationSizeInformation()\n"); @@ -654,6 +698,10 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext) FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass; FCB = (PVFATFCB) IrpContext->FileObject->FsContext; + DPRINT("VfatQueryInformation is called for '%s'\n", + FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[FileInformationClass]); + + SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; BufferLength = IrpContext->Stack->Parameters.QueryFile.Length; @@ -746,7 +794,7 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext) PVFATFCB FCB = NULL; NTSTATUS RC = STATUS_SUCCESS; PVOID SystemBuffer; - BOOL CanWait = IrpContext->Flags & IRPCONTEXT_CANWAIT; + BOOLEAN CanWait = (IrpContext->Flags & IRPCONTEXT_CANWAIT) != 0; /* PRECONDITION */ ASSERT(IrpContext); @@ -758,6 +806,9 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext) IrpContext->Stack->Parameters.SetFile.FileInformationClass; FCB = (PVFATFCB) IrpContext->FileObject->FsContext; SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; + + DPRINT("VfatSetInformation is called for '%s'\n", + FileInformationClass >= FileMaximumInformation - 1 ? "????" : FileInformationClassNames[ FileInformationClass]); DPRINT("FileInformationClass %d\n", FileInformationClass); DPRINT("SystemBuffer %x\n", SystemBuffer); diff --git a/reactos/drivers/fs/vfat/flush.c b/reactos/drivers/fs/vfat/flush.c index f128dfdcf21..9326a224c6e 100644 --- a/reactos/drivers/fs/vfat/flush.c +++ b/reactos/drivers/fs/vfat/flush.c @@ -9,11 +9,8 @@ /* INCLUDES *****************************************************************/ -#include -#include "vfat.h" - #define NDEBUG -#include +#include "vfat.h" /* FUNCTIONS ****************************************************************/ diff --git a/reactos/drivers/fs/vfat/fsctl.c b/reactos/drivers/fs/vfat/fsctl.c index efdda7ca630..0a797c76075 100644 --- a/reactos/drivers/fs/vfat/fsctl.c +++ b/reactos/drivers/fs/vfat/fsctl.c @@ -26,14 +26,7 @@ /* INCLUDES *****************************************************************/ -#include -#include -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ @@ -56,7 +49,7 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, LARGE_INTEGER Offset; struct _BootSector* Boot; struct _BootSectorFatX* BootFatX; - BOOL PartitionInfoIsValid = FALSE; + BOOLEAN PartitionInfoIsValid = FALSE; DPRINT("VfatHasFileSystem\n"); @@ -123,153 +116,143 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, *RecognizedFS = TRUE; } } - /* - * Floppy disk driver can return Unknown as media type if it - * doesn't know yet what floppy in the drive really is. This is - * perfectly correct to do under Windows. - */ - if (DiskGeometry.MediaType == Unknown) + else if (DiskGeometry.MediaType == Unknown) { + /* + * Floppy disk driver can return Unknown as media type if it + * doesn't know yet what floppy in the drive really is. This is + * perfectly correct to do under Windows. + */ *RecognizedFS = TRUE; DiskGeometry.BytesPerSector = 512; } - if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType < RemovableMedia ) + else { *RecognizedFS = TRUE; - } - if (*RecognizedFS == FALSE) + } + if (*RecognizedFS) { - return STATUS_SUCCESS; - } - Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector); - if (Boot == NULL) - { - *RecognizedFS=FALSE; - return STATUS_INSUFFICIENT_RESOURCES; - } + Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector); + if (Boot == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } - Offset.QuadPart = 0; + Offset.QuadPart = 0; - /* Try to recognize FAT12/FAT16/FAT32 partitions */ - Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE); - if (NT_SUCCESS(Status)) - { - if (Boot->Signatur1 != 0xaa55) + /* Try to recognize FAT12/FAT16/FAT32 partitions */ + Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE); + if (NT_SUCCESS(Status)) { - BootFatX = (struct _BootSectorFatX *) Boot; - if (BootFatX->SysType[0] != 'F' || - BootFatX->SysType[1] != 'A' || - BootFatX->SysType[2] != 'T' || - BootFatX->SysType[3] != 'X') + if (Boot->Signatur1 != 0xaa55) { - DPRINT1("Signature %04x\n", Boot->Signatur1); - } - *RecognizedFS=FALSE; - } - if (*RecognizedFS && - Boot->BytesPerSector != 512 && - Boot->BytesPerSector != 1024 && - Boot->BytesPerSector != 2048 && - Boot->BytesPerSector != 4096) - { - DPRINT1("BytesPerSector %d\n", Boot->BytesPerSector); - *RecognizedFS=FALSE; - } - - if (*RecognizedFS && - Boot->FATCount != 1 && - Boot->FATCount != 2) - { - DPRINT1("FATCount %d\n", Boot->FATCount); - *RecognizedFS=FALSE; - } - - if (*RecognizedFS && - Boot->Media != 0xf0 && - Boot->Media != 0xf8 && - Boot->Media != 0xf9 && - Boot->Media != 0xfa && - Boot->Media != 0xfb && - Boot->Media != 0xfc && - Boot->Media != 0xfd && - Boot->Media != 0xfe && - Boot->Media != 0xff) - { - DPRINT1("Media %02x\n", Boot->Media); - *RecognizedFS=FALSE; - } - - if (*RecognizedFS && - Boot->SectorsPerCluster != 1 && - Boot->SectorsPerCluster != 2 && - Boot->SectorsPerCluster != 4 && - Boot->SectorsPerCluster != 8 && - Boot->SectorsPerCluster != 16 && - Boot->SectorsPerCluster != 32 && - Boot->SectorsPerCluster != 64 && - Boot->SectorsPerCluster != 128) - { - DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster); - *RecognizedFS=FALSE; - } - - if (*RecognizedFS && - Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024) - { - DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster); - *RecognizedFS=FALSE; - } - - if (*RecognizedFS) - { - FatInfo.VolumeID = Boot->VolumeID; - FatInfo.FATStart = Boot->ReservedSectors; - FatInfo.FATCount = Boot->FATCount; - FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32; - FatInfo.BytesPerSector = Boot->BytesPerSector; - FatInfo.SectorsPerCluster = Boot->SectorsPerCluster; - FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster; - FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector; - FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors; - FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors; - FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge; - Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors; - FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster; - if (FatInfo.NumberOfClusters < 4085) - { - DPRINT("FAT12\n"); - FatInfo.FatType = FAT12; - } - else if (FatInfo.NumberOfClusters >= 65525) - { - DPRINT("FAT32\n"); - FatInfo.FatType = FAT32; - FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster; - FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster); - FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID; - } - else - { - DPRINT("FAT16\n"); - FatInfo.FatType = FAT16; - } - if (PartitionInfoIsValid && - FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector) - { - CHECKPOINT1; *RecognizedFS = FALSE; } - - if (pFatInfo && *RecognizedFS) + if (*RecognizedFS && + Boot->BytesPerSector != 512 && + Boot->BytesPerSector != 1024 && + Boot->BytesPerSector != 2048 && + Boot->BytesPerSector != 4096) { - *pFatInfo = FatInfo; + DPRINT1("BytesPerSector %d\n", Boot->BytesPerSector); + *RecognizedFS = FALSE; + } + + if (*RecognizedFS && + Boot->FATCount != 1 && + Boot->FATCount != 2) + { + DPRINT1("FATCount %d\n", Boot->FATCount); + *RecognizedFS = FALSE; + } + + if (*RecognizedFS && + Boot->Media != 0xf0 && + Boot->Media != 0xf8 && + Boot->Media != 0xf9 && + Boot->Media != 0xfa && + Boot->Media != 0xfb && + Boot->Media != 0xfc && + Boot->Media != 0xfd && + Boot->Media != 0xfe && + Boot->Media != 0xff) + { + DPRINT1("Media %02x\n", Boot->Media); + *RecognizedFS = FALSE; + } + + if (*RecognizedFS && + Boot->SectorsPerCluster != 1 && + Boot->SectorsPerCluster != 2 && + Boot->SectorsPerCluster != 4 && + Boot->SectorsPerCluster != 8 && + Boot->SectorsPerCluster != 16 && + Boot->SectorsPerCluster != 32 && + Boot->SectorsPerCluster != 64 && + Boot->SectorsPerCluster != 128) + { + DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster); + *RecognizedFS = FALSE; + } + + if (*RecognizedFS && + Boot->BytesPerSector * Boot->SectorsPerCluster > 32 * 1024) + { + DPRINT1("ClusterSize %dx\n", Boot->BytesPerSector * Boot->SectorsPerCluster); + *RecognizedFS = FALSE; + } + + if (*RecognizedFS) + { + FatInfo.VolumeID = Boot->VolumeID; + FatInfo.FATStart = Boot->ReservedSectors; + FatInfo.FATCount = Boot->FATCount; + FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32; + FatInfo.BytesPerSector = Boot->BytesPerSector; + FatInfo.SectorsPerCluster = Boot->SectorsPerCluster; + FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster; + FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector; + FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors; + FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors; + FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge; + Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors; + FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster; + if (FatInfo.NumberOfClusters < 4085) + { + DPRINT("FAT12\n"); + FatInfo.FatType = FAT12; + } + else if (FatInfo.NumberOfClusters >= 65525) + { + DPRINT("FAT32\n"); + FatInfo.FatType = FAT32; + FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster; + FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster); + FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID; + } + else + { + DPRINT("FAT16\n"); + FatInfo.FatType = FAT16; + } + if (PartitionInfoIsValid && + FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector) + { + CHECKPOINT1; + *RecognizedFS = FALSE; + } + + if (pFatInfo && *RecognizedFS) + { + *pFatInfo = FatInfo; + } } } + + ExFreePool(Boot); } - ExFreePool(Boot); - if (!*RecognizedFS && PartitionInfoIsValid) { BootFatX = ExAllocatePool(NonPagedPool, sizeof(struct _BootSectorFatX)); @@ -315,8 +298,8 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster; FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster; FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector; - FatInfo.NumberOfClusters = PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerCluster; - if (FatInfo.NumberOfClusters < 65525) + FatInfo.Sectors = PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector; + if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525) { DPRINT("FATX16\n"); FatInfo.FatType = FATX16; @@ -329,13 +312,14 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, FatInfo.VolumeID = BootFatX->VolumeID; FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector; FatInfo.FATCount = BootFatX->FATCount; - FatInfo.FATSectors = - ROUND_UP(FatInfo.NumberOfClusters * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) / + FatInfo.FATSectors = + ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) / FatInfo.BytesPerSector; FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors; FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors; - FatInfo.Sectors = PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector; - if (pFatInfo && *RecognizedFS) + FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster; + + if (pFatInfo && *RecognizedFS) { *pFatInfo = FatInfo; } @@ -386,7 +370,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) PVFATFCB VolumeFcb = NULL; PVFATCCB Ccb = NULL; PDEVICE_OBJECT DeviceToMount; - UNICODE_STRING NameU; + UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$"); + UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$"); DPRINT("VfatMount(IrpContext %x)\n", IrpContext); @@ -496,7 +481,6 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) DPRINT("FsDeviceObject %lx\n", DeviceObject); DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); - RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$"); Fcb = vfatNewFCB(DeviceExt, &NameU); if (Fcb == NULL) { @@ -511,7 +495,6 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) } RtlZeroMemory(Ccb, sizeof (VFATCCB)); - DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; DeviceExt->FATFileObject->FsContext = Fcb; DeviceExt->FATFileObject->FsContext2 = Ccb; DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; @@ -525,6 +508,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize; Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; +#ifdef USE_ROS_CC_AND_FS if (DeviceExt->FatInfo.FatType != FAT12) { Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, CACHEPAGESIZE(DeviceExt)); @@ -538,14 +522,21 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) DPRINT1 ("CcRosInitializeFileCache failed\n"); goto ByeBye; } +#else + /* FIXME: Guard by SEH. */ + CcInitializeCacheMap(DeviceExt->FATFileObject, + (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), + FALSE, + &VfatGlobalData->CacheMgrCallbacks, + Fcb); +#endif DeviceExt->LastAvailableCluster = 2; ExInitializeResourceLite(&DeviceExt->DirResource); ExInitializeResourceLite(&DeviceExt->FatResource); InitializeListHead(&DeviceExt->FcbListHead); - RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$"); - VolumeFcb = vfatNewFCB(DeviceExt, &NameU); + VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU); if (VolumeFcb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -655,9 +646,9 @@ VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext) static NTSTATUS VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) { - PIO_STACK_LOCATION Stack; + PIO_STACK_LOCATION Stack; LARGE_INTEGER Vcn; - PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; PFILE_OBJECT FileObject; ULONG MaxExtentCount; PVFATFCB Fcb; @@ -678,7 +669,7 @@ VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) return STATUS_INVALID_PARAMETER; } if (IrpContext->Irp->UserBuffer == NULL || - Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR)) + Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER)) { return STATUS_BUFFER_TOO_SMALL; } @@ -690,7 +681,7 @@ VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) Vcn = *(PLARGE_INTEGER)Stack->Parameters.DeviceIoControl.Type3InputBuffer; RetrievalPointers = IrpContext->Irp->UserBuffer; - MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(GET_RETRIEVAL_DESCRIPTOR)) / sizeof(MAPPING_PAIR)); + MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0])); if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster) @@ -708,11 +699,12 @@ VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) goto ByeBye; } - RetrievalPointers->StartVcn = Vcn.QuadPart; - RetrievalPointers->NumberOfPairs = 0; - RetrievalPointers->Pair[0].Lcn = CurrentCluster - 2; + RetrievalPointers->StartingVcn = Vcn; + RetrievalPointers->ExtentCount = 0; + RetrievalPointers->Extents[0].Lcn.u.HighPart = 0; + RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2; LastCluster = 0; - while (CurrentCluster != 0xffffffff && RetrievalPointers->NumberOfPairs < MaxExtentCount) + while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount) { LastCluster = CurrentCluster; @@ -725,16 +717,17 @@ VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext) if (LastCluster + 1 != CurrentCluster) { - RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Vcn = Vcn.QuadPart; - RetrievalPointers->NumberOfPairs++; - if (RetrievalPointers->NumberOfPairs < MaxExtentCount) + RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn; + RetrievalPointers->ExtentCount++; + if (RetrievalPointers->ExtentCount < MaxExtentCount) { - RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Lcn = CurrentCluster - 2; + RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0; + RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2; } } } - IrpContext->Irp->IoStatus.Information = sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR) * RetrievalPointers->NumberOfPairs; + IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1)); Status = STATUS_SUCCESS; ByeBye: @@ -751,6 +744,7 @@ VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext) return STATUS_INVALID_DEVICE_REQUEST; } +#ifdef USE_ROS_CC_AND_FS static NTSTATUS VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext) { @@ -758,7 +752,7 @@ VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext) PROS_QUERY_LCN_MAPPING LcnQuery; PIO_STACK_LOCATION Stack; - DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext); + DPRINT("VfatRosQueryLcnMapping(IrpContext %x)\n", IrpContext); DeviceExt = IrpContext->DeviceExt; Stack = IrpContext->Stack; @@ -772,6 +766,7 @@ VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext) IrpContext->Irp->IoStatus.Information = sizeof(ROS_QUERY_LCN_MAPPING); return(STATUS_SUCCESS); } +#endif NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) /* @@ -803,9 +798,11 @@ NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) case FSCTL_MOVE_FILE: Status = VfatMoveFile(IrpContext); break; +#ifdef USE_ROS_CC_AND_FS case FSCTL_ROS_QUERY_LCN_MAPPING: Status = VfatRosQueryLcnMapping(IrpContext); break; +#endif default: Status = STATUS_INVALID_DEVICE_REQUEST; } diff --git a/reactos/drivers/fs/vfat/iface.c b/reactos/drivers/fs/vfat/iface.c index 0a3928bad9c..311d7b7076b 100644 --- a/reactos/drivers/fs/vfat/iface.c +++ b/reactos/drivers/fs/vfat/iface.c @@ -27,12 +27,7 @@ /* INCLUDES *****************************************************************/ -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* GLOBALS *****************************************************************/ @@ -45,7 +40,7 @@ NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) /* - * FUNCTION: Called by the system to initalize the driver + * FUNCTION: Called by the system to initialize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries @@ -53,7 +48,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, */ { PDEVICE_OBJECT DeviceObject; - UNICODE_STRING DeviceName = ROS_STRING_INITIALIZER(L"\\Fat"); + UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat"); NTSTATUS Status; Status = IoCreateDevice(DriverObject, @@ -65,7 +60,23 @@ DriverEntry(PDRIVER_OBJECT DriverObject, &DeviceObject); if (!NT_SUCCESS(Status)) { - return (Status); + if (Status == STATUS_OBJECT_NAME_EXISTS || + Status == STATUS_OBJECT_NAME_COLLISION) + { + /* Try an other name, if 'Fat' is already in use. 'Fat' is also used by fastfat.sys on W2K */ + RtlInitUnicodeString(&DeviceName, L"\\RosFat"); + Status = IoCreateDevice(DriverObject, + sizeof(VFAT_GLOBAL_DATA), + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + } } VfatGlobalData = DeviceObject->DeviceExtension; RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA)); @@ -91,7 +102,18 @@ DriverEntry(PDRIVER_OBJECT DriverObject, DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = VfatBuildRequest; DriverObject->DriverUnload = NULL; + + /* Cache manager */ + VfatGlobalData->CacheMgrCallbacks.AcquireForLazyWrite = VfatAcquireForLazyWrite; + VfatGlobalData->CacheMgrCallbacks.ReleaseFromLazyWrite = VfatReleaseFromLazyWrite; + VfatGlobalData->CacheMgrCallbacks.AcquireForReadAhead = VfatAcquireForReadAhead; + VfatGlobalData->CacheMgrCallbacks.ReleaseFromReadAhead = VfatReleaseFromReadAhead; + + /* Fast I/O */ + VfatInitFastIoRoutines(&VfatGlobalData->FastIoDispatch); + DriverObject->FastIoDispatch = &VfatGlobalData->FastIoDispatch; + /* Private lists */ ExInitializeNPagedLookasideList(&VfatGlobalData->FcbLookasideList, NULL, NULL, 0, sizeof(VFATFCB), TAG_FCB, 0); ExInitializeNPagedLookasideList(&VfatGlobalData->CcbLookasideList, diff --git a/reactos/drivers/fs/vfat/makefile b/reactos/drivers/fs/vfat/makefile index bedba47eaf4..7ae216e9e62 100644 --- a/reactos/drivers/fs/vfat/makefile +++ b/reactos/drivers/fs/vfat/makefile @@ -19,6 +19,7 @@ TARGET_OBJECTS = \ direntry.o \ dirwr.o \ fat.o \ + fastio.o \ fcb.o \ finfo.o \ iface.o \ @@ -38,9 +39,9 @@ TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym include $(PATH_TO_TOP)/config ifeq ($(DBG), 1) -TARGET_CFLAGS = -Wall -Werror -g +TARGET_CFLAGS = -D__USE_W32API -Wall -Werror -g else -TARGET_CFLAGS = -Wall -Werror -O3 -fno-strict-aliasing +TARGET_CFLAGS = -D__USE_W32API -Wall -Werror -O3 -fno-strict-aliasing endif include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/drivers/fs/vfat/misc.c b/reactos/drivers/fs/vfat/misc.c index 7d464465f95..c3cc379f510 100644 --- a/reactos/drivers/fs/vfat/misc.c +++ b/reactos/drivers/fs/vfat/misc.c @@ -10,14 +10,44 @@ /* INCLUDES *****************************************************************/ -#include -#include - #define NDEBUG -#include - #include "vfat.h" +/* GLOBALS ******************************************************************/ + +const char* MajorFunctionNames[] = +{ + "IRP_MJ_CREATE", + "IRP_MJ_CREATE_NAMED_PIPE", + "IRP_MJ_CLOSE", + "IRP_MJ_READ", + "IRP_MJ_WRITE", + "IRP_MJ_QUERY_INFORMATION", + "IRP_MJ_SET_INFORMATION", + "IRP_MJ_QUERY_EA", + "IRP_MJ_SET_EA", + "IRP_MJ_FLUSH_BUFFERS", + "IRP_MJ_QUERY_VOLUME_INFORMATION", + "IRP_MJ_SET_VOLUME_INFORMATION", + "IRP_MJ_DIRECTORY_CONTROL", + "IRP_MJ_FILE_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CONTROL", + "IRP_MJ_INTERNAL_DEVICE_CONTROL", + "IRP_MJ_SHUTDOWN", + "IRP_MJ_LOCK_CONTROL", + "IRP_MJ_CLEANUP", + "IRP_MJ_CREATE_MAILSLOT", + "IRP_MJ_QUERY_SECURITY", + "IRP_MJ_SET_SECURITY", + "IRP_MJ_POWER", + "IRP_MJ_SYSTEM_CONTROL", + "IRP_MJ_DEVICE_CHANGE", + "IRP_MJ_QUERY_QUOTA", + "IRP_MJ_SET_QUOTA", + "IRP_MJ_PNP", + "IRP_MJ_MAXIMUM_FUNCTION" +}; + /* FUNCTIONS ****************************************************************/ static LONG QueueCount = 0; @@ -62,10 +92,11 @@ Fail:; return Status; } -NTSTATUS VfatDispatchRequest ( - IN PVFAT_IRP_CONTEXT IrpContext) +NTSTATUS +VfatDispatchRequest (IN PVFAT_IRP_CONTEXT IrpContext) { - DPRINT ("VfatDispatchRequest (IrpContext %x), MajorFunction %x\n", IrpContext, IrpContext->MajorFunction); + DPRINT ("VfatDispatchRequest (IrpContext %x), is called for %s\n", IrpContext, + IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]); ASSERT(IrpContext); @@ -223,7 +254,9 @@ PVOID VfatGetUserBuffer(IN PIRP Irp) if (Irp->MdlAddress) { - return MmGetSystemAddressForMdl(Irp->MdlAddress); + /* This call may be in the paging path, so use maximum priority */ + /* FIXME: call with normal priority in the non-paging path */ + return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority); } else { diff --git a/reactos/drivers/fs/vfat/rw.c b/reactos/drivers/fs/vfat/rw.c index bb86e51f576..6851681dbde 100644 --- a/reactos/drivers/fs/vfat/rw.c +++ b/reactos/drivers/fs/vfat/rw.c @@ -13,7 +13,6 @@ /* INCLUDES *****************************************************************/ #include -#include #include #include @@ -375,7 +374,7 @@ VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, ASSERT(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart); ASSERT(WriteOffset.u.LowPart % BytesPerSector == 0); - ASSERT(Length % BytesPerSector == 0) + ASSERT(Length % BytesPerSector == 0); // Is this a write of the volume ? if (Fcb->Flags & FCB_IS_VOLUME) @@ -681,10 +680,19 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext) CHECKPOINT; if (IrpContext->FileObject->PrivateCacheMap == NULL) { - ULONG CacheSize; - CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster, - 8 * PAGE_SIZE); - CcRosInitializeFileCache(IrpContext->FileObject, CacheSize); +#ifdef USE_ROS_CC_AND_FS + ULONG CacheSize; + CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster, + 8 * PAGE_SIZE); + CcRosInitializeFileCache(IrpContext->FileObject, CacheSize); +#else + /* FIXME: Guard by SEH. */ + CcInitializeCacheMap(IrpContext->FileObject, + (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), + FALSE, + &(VfatGlobalData->CacheMgrCallbacks), + Fcb); +#endif } if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length, (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT), Buffer, @@ -705,7 +713,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext) CHECKPOINT; if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector)) { - Length = ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart; + Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart); } Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess); @@ -719,8 +727,8 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext) if (Status == STATUS_VERIFY_REQUIRED) { DPRINT("VfatReadFile returned STATUS_VERIFY_REQUIRED\n"); - DeviceToVerify = IoGetDeviceToVerify((struct _ETHREAD*)KeGetCurrentThread()); - IoSetDeviceToVerify((struct _ETHREAD*)KeGetCurrentThread(), NULL); + DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); + IoSetDeviceToVerify(PsGetCurrentThread(), NULL); Status = IoVerifyVolume (DeviceToVerify, FALSE); if (NT_SUCCESS(Status)) @@ -973,14 +981,23 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext) if (IrpContext->FileObject->PrivateCacheMap == NULL) { - ULONG CacheSize; - CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster, - 8 * PAGE_SIZE); - CcRosInitializeFileCache(IrpContext->FileObject, CacheSize); +#ifdef USE_ROS_CC_AND_FS + ULONG CacheSize; + CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster, + 8 * PAGE_SIZE); + CcRosInitializeFileCache(IrpContext->FileObject, CacheSize); +#else + /* FIXME: Guard by SEH. */ + CcInitializeCacheMap(IrpContext->FileObject, + (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize), + FALSE, + &VfatGlobalData->CacheMgrCallbacks, + Fcb); +#endif } if (ByteOffset.QuadPart > OldFileSize.QuadPart) { - CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE); + CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE); } if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length, 1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer)) diff --git a/reactos/drivers/fs/vfat/shutdown.c b/reactos/drivers/fs/vfat/shutdown.c index 28330e4547c..37e95be3da4 100644 --- a/reactos/drivers/fs/vfat/shutdown.c +++ b/reactos/drivers/fs/vfat/shutdown.c @@ -9,11 +9,7 @@ /* INCLUDES *****************************************************************/ -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ diff --git a/reactos/drivers/fs/vfat/string.c b/reactos/drivers/fs/vfat/string.c index 4df78172c9d..2d5e485c42c 100644 --- a/reactos/drivers/fs/vfat/string.c +++ b/reactos/drivers/fs/vfat/string.c @@ -11,12 +11,7 @@ /* INCLUDES *****************************************************************/ -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ diff --git a/reactos/drivers/fs/vfat/vfat.h b/reactos/drivers/fs/vfat/vfat.h index bfa0b22adf6..7f14a207daa 100644 --- a/reactos/drivers/fs/vfat/vfat.h +++ b/reactos/drivers/fs/vfat/vfat.h @@ -1,6 +1,29 @@ /* $Id$ */ #include +#include +#include +#include + +#define USE_ROS_CC_AND_FS + +/* FIXME */ +#ifdef __USE_W32API +NTSTATUS NTAPI RtlOemStringToUnicodeString(PUNICODE_STRING, CONST STRING *, BOOLEAN); +NTSTATUS NTAPI RtlDowncaseUnicodeString(PUNICODE_STRING, PCUNICODE_STRING, BOOLEAN); +NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING, PCUNICODE_STRING, BOOLEAN); +#undef DeleteFile /* FIXME */ +#endif + +#ifdef USE_ROS_CC_AND_FS +NTSTATUS STDCALL CcRosInitializeFileCache(PFILE_OBJECT, ULONG); +NTSTATUS STDCALL CcRosReleaseFileCache(PFILE_OBJECT); +#define FSCTL_ROS_QUERY_LCN_MAPPING CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 63, METHOD_BUFFERED, FILE_ANY_ACCESS) +typedef struct _ROS_QUERY_LCN_MAPPING { LARGE_INTEGER LcnDiskOffset; } ROS_QUERY_LCN_MAPPING, *PROS_QUERY_LCN_MAPPING; +#endif + +#define KEBUGCHECK(a) DbgPrint("KeBugCheck at %s:%i\n",__FILE__,__LINE__), KeBugCheck(a) +#define KEBUGCHECKEX(a,b,c,d,e) DbgPrint("KeBugCheckEx at %s:%i\n",__FILE__,__LINE__), KeBugCheckEx(a,b,c,d,e) #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) #define ROUND_DOWN(N, S) ((N) - ((N) % (S))) @@ -75,8 +98,10 @@ struct _FsInfoSector typedef struct _BootSector BootSector; -#define VFAT_CASE_LOWER_BASE 8 // base is lower case -#define VFAT_CASE_LOWER_EXT 16 // extension is lower case +#define VFAT_CASE_LOWER_BASE 8 // base is lower case +#define VFAT_CASE_LOWER_EXT 16 // extension is lower case + +#define LONGNAME_MAX_LENGTH 256 // max length for a long filename #define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat))) #define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat))) @@ -179,7 +204,7 @@ typedef struct ULONG NumberOfClusters; ULONG FatType; ULONG Sectors; - BOOL FixedMedia; + BOOLEAN FixedMedia; } FATINFO, *PFATINFO; struct _VFATFCB; @@ -244,6 +269,8 @@ typedef struct NPAGED_LOOKASIDE_LIST FcbLookasideList; NPAGED_LOOKASIDE_LIST CcbLookasideList; NPAGED_LOOKASIDE_LIST IrpContextLookasideList; + FAST_IO_DISPATCH FastIoDispatch; + CACHE_MANAGER_CALLBACKS CacheMgrCallbacks; } VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; extern PVFAT_GLOBAL_DATA VfatGlobalData; @@ -284,7 +311,7 @@ typedef struct _VFATFCB UNICODE_STRING PathNameU; /* buffer for PathNameU */ - WCHAR PathNameBuffer[MAX_PATH]; + PWCHAR PathNameBuffer; /* buffer for ShortNameU */ WCHAR ShortNameBuffer[13]; @@ -356,17 +383,17 @@ typedef struct _VFATCCB typedef struct __DOSTIME { - WORD Second:5; - WORD Minute:6; - WORD Hour:5; + USHORT Second:5; + USHORT Minute:6; + USHORT Hour:5; } DOSTIME, *PDOSTIME; typedef struct __DOSDATE { - WORD Day:5; - WORD Month:4; - WORD Year:5; + USHORT Day:5; + USHORT Month:4; + USHORT Year:5; } DOSDATE, *PDOSDATE; @@ -441,15 +468,15 @@ NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); -BOOL FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, - WORD wDosDate, - WORD wDosTime, - PLARGE_INTEGER SystemTime); +BOOLEAN FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, + USHORT DosDate, + USHORT DosTime, + PLARGE_INTEGER SystemTime); -BOOL FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, - PLARGE_INTEGER SystemTime, - WORD *pwDosDate, - WORD *pwDosTime); +BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER SystemTime, + USHORT *pDosDate, + USHORT *pDosTime); /* -------------------------------------------------------- create.c */ @@ -482,6 +509,25 @@ NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); +/* --------------------------------------------------------- fastio.c */ + +VOID +VfatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch); + +BOOLEAN NTAPI +VfatAcquireForLazyWrite(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromLazyWrite(IN PVOID Context); + +BOOLEAN NTAPI +VfatAcquireForReadAhead(IN PVOID Context, + IN BOOLEAN Wait); + +VOID NTAPI +VfatReleaseFromReadAhead(IN PVOID Context); + /* --------------------------------------------------------- fsctl.c */ NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); @@ -602,7 +648,7 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pDirEntry); -BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb); +BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb); NTSTATUS FATGetNextDirEntry(PVOID * pContext, PVOID * pPage, @@ -641,9 +687,9 @@ PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); -BOOL vfatFCBIsDirectory (PVFATFCB FCB); +BOOLEAN vfatFCBIsDirectory (PVFATFCB FCB); -BOOL vfatFCBIsRoot(PVFATFCB FCB); +BOOLEAN vfatFCBIsRoot(PVFATFCB FCB); NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, PVFATFCB fcb, diff --git a/reactos/drivers/fs/vfat/vfatfs.xml b/reactos/drivers/fs/vfat/vfatfs.xml index 7d7549e78f3..3d1ce7ce470 100644 --- a/reactos/drivers/fs/vfat/vfatfs.xml +++ b/reactos/drivers/fs/vfat/vfatfs.xml @@ -1,5 +1,6 @@ . + ntoskrnl hal blockdev.c @@ -11,6 +12,7 @@ dirwr.c ea.c fat.c + fastio.c fcb.c finfo.c flush.c diff --git a/reactos/drivers/fs/vfat/volume.c b/reactos/drivers/fs/vfat/volume.c index 5f0b422abc8..3ed1ad22c63 100644 --- a/reactos/drivers/fs/vfat/volume.c +++ b/reactos/drivers/fs/vfat/volume.c @@ -11,12 +11,7 @@ /* INCLUDES *****************************************************************/ -#include -#include - #define NDEBUG -#include - #include "vfat.h" /* FUNCTIONS ****************************************************************/ @@ -169,7 +164,7 @@ FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, PDIR_ENTRY Entry; PVFATFCB pRootFcb; LARGE_INTEGER FileOffset; - BOOL LabelFound = FALSE; + BOOLEAN LabelFound = FALSE; DIR_ENTRY VolumeLabelDirEntry; ULONG VolumeLabelDirIndex; ULONG LabelLen; @@ -233,7 +228,7 @@ FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, /* Search existing volume entry on disk */ FileOffset.QuadPart = 0; - if (CcMapData(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) + if (CcPinRead(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) { while (TRUE) { @@ -256,7 +251,7 @@ FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, { CcUnpinData(Context); FileOffset.u.LowPart += PAGE_SIZE; - if (!CcMapData(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) + if (!CcPinRead(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) { Context = NULL; break; @@ -277,7 +272,7 @@ FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, { FileOffset.u.HighPart = 0; FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry; - CcMapData(pRootFcb->FileObject, &FileOffset, SizeDirEntry, + CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry); RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry); CcSetDirtyPinnedData(Context, NULL); diff --git a/reactos/drivers/input/psaux/psaux.c b/reactos/drivers/input/psaux/psaux.c index 4cb6369d797..44a4c319525 100644 --- a/reactos/drivers/input/psaux/psaux.c +++ b/reactos/drivers/input/psaux/psaux.c @@ -177,7 +177,6 @@ AllocatePointerDevice(PDRIVER_OBJECT DriverObject) PDEVICE_OBJECT DeviceObject; UNICODE_STRING DeviceName; UNICODE_STRING SuffixString; - UNICODE_STRING SymlinkName; PDEVICE_EXTENSION DeviceExtension; ULONG Suffix; NTSTATUS Status; @@ -213,25 +212,16 @@ AllocatePointerDevice(PDRIVER_OBJECT DriverObject) } ExFreePool(DeviceName.Buffer); + ExFreePool(SuffixString.Buffer); /* Couldn't create device */ if (!NT_SUCCESS(Status)) { - ExFreePool(SuffixString.Buffer); return NULL; } DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; - /* Create symlink */ - RtlInitUnicodeString(&SymlinkName, NULL); - SymlinkName.MaximumLength = sizeof(L"\\??\\Mouse") + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL); - SymlinkName.Buffer = ExAllocatePool(PagedPool, SymlinkName.MaximumLength); - RtlAppendUnicodeToString(&SymlinkName, L"\\??\\Mouse"); - RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer); - IoCreateSymbolicLink(&SymlinkName, &DeviceName); - ExFreePool(SuffixString.Buffer); - DeviceExtension = DeviceObject->DeviceExtension; KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject); diff --git a/reactos/drivers/input/sermouse/sermouse.c b/reactos/drivers/input/sermouse/sermouse.c index 23ed60e7cf4..b2ad310a84d 100644 --- a/reactos/drivers/input/sermouse/sermouse.c +++ b/reactos/drivers/input/sermouse/sermouse.c @@ -26,8 +26,6 @@ #define SERMOUSE_COM1_SUPPORT /* Check for mouse on COM2? */ /* #define SERMOUSE_COM2_SUPPORT */ -/* Create \??\Mouse* symlink for device? */ -#define SERMOUSE_MOUSESYMLINK_SUPPORT /* * Definitions @@ -511,7 +509,6 @@ AllocatePointerDevice(PDRIVER_OBJECT DriverObject) PDEVICE_OBJECT DeviceObject; UNICODE_STRING DeviceName; UNICODE_STRING SuffixString; - UNICODE_STRING SymlinkName; PDEVICE_EXTENSION DeviceExtension; ULONG Suffix; NTSTATUS Status; @@ -541,28 +538,16 @@ AllocatePointerDevice(PDRIVER_OBJECT DriverObject) } ExFreePool(DeviceName.Buffer); + ExFreePool(SuffixString.Buffer); /* Couldn't create device */ if (!NT_SUCCESS(Status)) { - ExFreePool(SuffixString.Buffer); return NULL; } DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; -#ifdef SERMOUSE_MOUSESYMLINK_SUPPORT - /* Create symlink */ - /* FIXME: Why? FiN 20/08/2003 */ - RtlInitUnicodeString(&SymlinkName, NULL); - SymlinkName.MaximumLength = sizeof(L"\\??\\Mouse") + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL); - SymlinkName.Buffer = ExAllocatePool(PagedPool, SymlinkName.MaximumLength); - RtlAppendUnicodeToString(&SymlinkName, L"\\??\\Mouse"); - RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer); - IoCreateSymbolicLink(&SymlinkName, &DeviceName); -#endif - ExFreePool(SuffixString.Buffer); - DeviceExtension = DeviceObject->DeviceExtension; KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject); diff --git a/reactos/drivers/lib/ip/network/address.c b/reactos/drivers/lib/ip/network/address.c index 38194a34c0b..1631efdda81 100644 --- a/reactos/drivers/lib/ip/network/address.c +++ b/reactos/drivers/lib/ip/network/address.c @@ -86,6 +86,7 @@ UINT AddrCountPrefixBits( PIP_ADDRESS Netmask ) { VOID AddrWidenAddress( PIP_ADDRESS Network, PIP_ADDRESS Source, PIP_ADDRESS Netmask ) { if( Netmask->Type == IP_ADDRESS_V4 ) { + Network->Type = Netmask->Type; Network->Address.IPv4Address = Source->Address.IPv4Address & Netmask->Address.IPv4Address; } else { @@ -220,8 +221,10 @@ BOOLEAN AddrIsEqual( PIP_ADDRESS Address1, PIP_ADDRESS Address2) { - if (Address1->Type != Address2->Type) + if (Address1->Type != Address2->Type) { + DbgPrint("AddrIsEqual: Unequal Address Types\n"); return FALSE; + } switch (Address1->Type) { case IP_ADDRESS_V4: @@ -231,6 +234,10 @@ BOOLEAN AddrIsEqual( return (RtlCompareMemory(&Address1->Address, &Address2->Address, sizeof(IPv6_RAW_ADDRESS)) == sizeof(IPv6_RAW_ADDRESS)); break; + + default: + DbgPrint("AddrIsEqual: Bad address type\n"); + break; } return FALSE; diff --git a/reactos/drivers/lib/ip/network/interface.c b/reactos/drivers/lib/ip/network/interface.c index 664d86f0e4d..8094c43050f 100644 --- a/reactos/drivers/lib/ip/network/interface.c +++ b/reactos/drivers/lib/ip/network/interface.c @@ -24,9 +24,7 @@ NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface, break; case ADE_BROADCAST: - *Address = - Interface->Unicast.Address.IPv4Address | - ~Interface->Netmask.Address.IPv4Address; + *Address = Interface->Broadcast.Address.IPv4Address; break; case ADE_POINTOPOINT: diff --git a/reactos/drivers/lib/ip/network/ip.c b/reactos/drivers/lib/ip/network/ip.c index d2ccd11da3a..4b6871efc0c 100644 --- a/reactos/drivers/lib/ip/network/ip.c +++ b/reactos/drivers/lib/ip/network/ip.c @@ -152,6 +152,10 @@ VOID IPDispatchProtocol( /* Call the appropriate protocol handler */ (*ProtocolTable[Protocol])(Interface, IPPacket); + /* Special case for ICMP -- ICMP can be caught by a SOCK_RAW but also + * must be handled here. */ + if( Protocol == IPPROTO_ICMP ) + ICMPReceive( Interface, IPPacket ); } @@ -401,9 +405,6 @@ NTSTATUS IPStartup(PUNICODE_STRING RegistryPath) for (i = 0; i < IP_PROTOCOL_TABLE_SIZE; i++) IPRegisterProtocol(i, DefaultProtocolHandler); - /* Register network level protocol receive handlers */ - IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive); - /* Initialize NTE list and protecting lock */ InitializeListHead(&NetTableListHead); TcpipInitializeSpinLock(&NetTableListLock); diff --git a/reactos/drivers/lib/ip/network/loopback.c b/reactos/drivers/lib/ip/network/loopback.c index 6584cf9c2b9..e2be1fa4383 100644 --- a/reactos/drivers/lib/ip/network/loopback.c +++ b/reactos/drivers/lib/ip/network/loopback.c @@ -11,6 +11,107 @@ #include "precomp.h" PIP_INTERFACE Loopback = NULL; +typedef struct _LAN_WQ_ITEM { + LIST_ENTRY ListEntry; + PNDIS_PACKET Packet; + PLAN_ADAPTER Adapter; + UINT BytesTransferred; +} LAN_WQ_ITEM, *PLAN_WQ_ITEM; + +/* Work around being called back into afd at Dpc level */ +KSPIN_LOCK LoopWorkLock; +LIST_ENTRY LoopWorkList; +WORK_QUEUE_ITEM LoopWorkItem; +BOOLEAN LoopReceiveWorkerBusy = FALSE; + +VOID STDCALL LoopReceiveWorker( PVOID Context ) { + PLIST_ENTRY ListEntry; + PLAN_WQ_ITEM WorkItem; + PNDIS_PACKET Packet; + PLAN_ADAPTER Adapter; + UINT BytesTransferred; + PNDIS_BUFFER NdisBuffer; + IP_PACKET IPPacket; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + while( (ListEntry = + ExInterlockedRemoveHeadList( &LoopWorkList, &LoopWorkLock )) ) { + WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry); + + TI_DbgPrint(DEBUG_DATALINK, ("WorkItem: %x\n", WorkItem)); + + Packet = WorkItem->Packet; + Adapter = WorkItem->Adapter; + BytesTransferred = WorkItem->BytesTransferred; + + ExFreePool( WorkItem ); + + IPPacket.NdisPacket = Packet; + + TI_DbgPrint(DEBUG_DATALINK, ("Packet %x Adapter %x Trans %x\n", + Packet, Adapter, BytesTransferred)); + + NdisGetFirstBufferFromPacket(Packet, + &NdisBuffer, + &IPPacket.Header, + &IPPacket.ContigSize, + &IPPacket.TotalSize); + + IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred; + /* Determine which upper layer protocol that should receive + this packet and pass it to the correct receive handler */ + + TI_DbgPrint(MID_TRACE, + ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n", + IPPacket.ContigSize, IPPacket.TotalSize, + BytesTransferred)); + + IPPacket.Position = 0; + + IPReceive(Loopback, &IPPacket); + + FreeNdisPacket( Packet ); + } + TI_DbgPrint(DEBUG_DATALINK, ("Leaving\n")); + LoopReceiveWorkerBusy = FALSE; +} + +VOID LoopSubmitReceiveWork( + NDIS_HANDLE BindingContext, + PNDIS_PACKET Packet, + NDIS_STATUS Status, + UINT BytesTransferred) { + PLAN_WQ_ITEM WQItem; + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + KIRQL OldIrql; + + TcpipAcquireSpinLock( &LoopWorkLock, &OldIrql ); + + WQItem = ExAllocatePool( NonPagedPool, sizeof(LAN_WQ_ITEM) ); + if( !WQItem ) { + TcpipReleaseSpinLock( &LoopWorkLock, OldIrql ); + return; + } + + WQItem->Packet = Packet; + WQItem->Adapter = Adapter; + WQItem->BytesTransferred = BytesTransferred; + InsertTailList( &LoopWorkList, &WQItem->ListEntry ); + + TI_DbgPrint(DEBUG_DATALINK, ("Packet %x Adapter %x BytesTrans %x\n", + Packet, Adapter, BytesTransferred)); + + if( !LoopReceiveWorkerBusy ) { + LoopReceiveWorkerBusy = TRUE; + ExQueueWorkItem( &LoopWorkItem, CriticalWorkQueue ); + TI_DbgPrint(DEBUG_DATALINK, + ("Work item inserted %x %x\n", &LoopWorkItem, WQItem)); + } else { + DbgPrint("LOOP WORKER BUSY %x %x\n", &LoopWorkItem, WQItem); + } + TcpipReleaseSpinLock( &LoopWorkLock, OldIrql ); +} VOID LoopTransmit( PVOID Context, @@ -28,30 +129,31 @@ VOID LoopTransmit( * Type = LAN protocol type (unused) */ { - IP_PACKET IPPacket; + PCHAR PacketBuffer; + UINT PacketLength; + PNDIS_PACKET XmitPacket; + NDIS_STATUS NdisStatus; - ASSERT_KM_POINTER(NdisPacket); - ASSERT_KM_POINTER(PC(NdisPacket)); - ASSERT_KM_POINTER(PC(NdisPacket)->DLComplete); + ASSERT_KM_POINTER(NdisPacket); + ASSERT_KM_POINTER(PC(NdisPacket)); + ASSERT_KM_POINTER(PC(NdisPacket)->DLComplete); + + TI_DbgPrint(MAX_TRACE, ("Called (NdisPacket = %x)\n", NdisPacket)); - TI_DbgPrint(MAX_TRACE, ("Called (NdisPacket = %x)\n", NdisPacket)); + GetDataPtr( NdisPacket, MaxLLHeaderSize, &PacketBuffer, &PacketLength ); - IPPacket.NdisPacket = NdisPacket; - IPPacket.HeaderSize = 0; - GetDataPtr( NdisPacket, 0, (PCHAR *)&IPPacket.Header, &IPPacket.TotalSize ); - IPPacket.Header += Offset; - IPPacket.ContigSize = IPPacket.TotalSize; - IPPacket.Position = Offset; + NdisStatus = AllocatePacketWithBuffer + ( &XmitPacket, PacketBuffer, PacketLength ); - TI_DbgPrint(MAX_TRACE, - ("Doing receive (complete: %x, context %x, packet %x)\n", - PC(NdisPacket)->DLComplete, Context, NdisPacket)); - IPReceive(Context, &IPPacket); - TI_DbgPrint(MAX_TRACE, - ("Finished receive (complete: %x, context %x, packet %x)\n", - PC(NdisPacket)->DLComplete, Context, NdisPacket)); - PC(NdisPacket)->DLComplete(PC(NdisPacket)->Context, NdisPacket, NDIS_STATUS_SUCCESS); - TI_DbgPrint(MAX_TRACE, ("Done\n")); + if( NT_SUCCESS(NdisStatus) ) { + LoopSubmitReceiveWork + ( NULL, XmitPacket, STATUS_SUCCESS, PacketLength ); + } + + (PC(NdisPacket)->DLComplete) + ( PC(NdisPacket)->Context, NdisPacket, STATUS_SUCCESS ); + + TI_DbgPrint(MAX_TRACE, ("Done\n")); } NDIS_STATUS LoopRegisterAdapter( @@ -73,6 +175,9 @@ NDIS_STATUS LoopRegisterAdapter( TI_DbgPrint(MID_TRACE, ("Called.\n")); + InitializeListHead( &LoopWorkList ); + ExInitializeWorkItem( &LoopWorkItem, LoopReceiveWorker, NULL ); + /* Bind the adapter to network (IP) layer */ BindInfo.Context = NULL; BindInfo.HeaderSize = 0; diff --git a/reactos/drivers/lib/ip/network/neighbor.c b/reactos/drivers/lib/ip/network/neighbor.c index 49f650ff276..99e9bbf6e55 100644 --- a/reactos/drivers/lib/ip/network/neighbor.c +++ b/reactos/drivers/lib/ip/network/neighbor.c @@ -52,19 +52,19 @@ VOID NBSendPackets( PNEIGHBOR_CACHE_ENTRY NCE ) { } } +/* Must be called with table lock acquired */ VOID NBFlushPacketQueue( PNEIGHBOR_CACHE_ENTRY NCE, BOOL CallComplete, NTSTATUS ErrorCode ) { PLIST_ENTRY PacketEntry; PNEIGHBOR_PACKET Packet; - PacketEntry = ExInterlockedRemoveHeadList(&NCE->PacketQueue, - &NCE->Table->Lock); - while( PacketEntry != NULL ) { + while( !IsListEmpty(&NCE->PacketQueue) ) { + PacketEntry = RemoveHeadList(&NCE->PacketQueue); Packet = CONTAINING_RECORD ( PacketEntry, NEIGHBOR_PACKET, Next ); - ASSERT_KM_POINTER(Packet); + ASSERT_KM_POINTER(Packet); TI_DbgPrint (MID_TRACE, @@ -72,16 +72,14 @@ VOID NBFlushPacketQueue( PNEIGHBOR_CACHE_ENTRY NCE, PacketEntry, Packet->Packet)); if( CallComplete ) - { - ASSERT_KM_POINTER(Packet->Complete); + { + ASSERT_KM_POINTER(Packet->Complete); Packet->Complete( Packet->Context, Packet->Packet, NDIS_STATUS_REQUEST_ABORTED ); - } + } PoolFreeBuffer( Packet ); - PacketEntry = ExInterlockedRemoveHeadList(&NCE->PacketQueue, - &NCE->Table->Lock); } } @@ -407,10 +405,19 @@ PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( NCE = NBLocateNeighbor(Address); if (NCE == NULL) { - NCE = NBAddNeighbor(Interface, Address, NULL, - Interface->AddressLength, NUD_INCOMPLETE); - NCE->EventTimer = 1; - NCE->EventCount = 0; + TI_DbgPrint(MID_TRACE,("BCAST: %s\n", A2S(&Interface->Broadcast))); + if( AddrIsEqual(Address, &Interface->Broadcast) ) { + TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n")); + NCE = NBAddNeighbor(Interface, Address, NULL, + Interface->AddressLength, NUD_CONNECTED); + NCE->EventTimer = 0; + NCE->EventCount = 0; + } else { + NCE = NBAddNeighbor(Interface, Address, NULL, + Interface->AddressLength, NUD_INCOMPLETE); + NCE->EventTimer = 1; + NCE->EventCount = 0; + } } return NCE; diff --git a/reactos/drivers/lib/ip/network/ports.c b/reactos/drivers/lib/ip/network/ports.c index 6f0ab37468d..62be2ef11a3 100644 --- a/reactos/drivers/lib/ip/network/ports.c +++ b/reactos/drivers/lib/ip/network/ports.c @@ -20,6 +20,8 @@ VOID PortsStartup( PPORT_SET PortSet, RtlInitializeBitMap( &PortSet->ProtoBitmap, PortSet->ProtoBitBuffer, PortSet->PortsToOversee ); + RtlClearBits( &PortSet->ProtoBitmap, + PortSet->StartingPort, PortsToManage ); ExInitializeFastMutex( &PortSet->Mutex ); } diff --git a/reactos/drivers/lib/ip/transport/datagram/datagram.c b/reactos/drivers/lib/ip/transport/datagram/datagram.c index 9d50ab38a30..a10c20816ee 100644 --- a/reactos/drivers/lib/ip/transport/datagram/datagram.c +++ b/reactos/drivers/lib/ip/transport/datagram/datagram.c @@ -59,7 +59,7 @@ VOID DGDeliverData( if (!IsListEmpty(&AddrFile->ReceiveQueue)) { PLIST_ENTRY CurrentEntry; - PDATAGRAM_RECEIVE_REQUEST Current; + PDATAGRAM_RECEIVE_REQUEST Current = NULL; BOOLEAN Found; PTA_IP_ADDRESS RTAIPAddress; @@ -86,6 +86,10 @@ VOID DGDeliverData( if (Found) { TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n")); + + TI_DbgPrint(MAX_TRACE, + ("Target Buffer: %x, Source Buffer: %x, Size %d\n", + Current->Buffer, DataBuffer, DataSize)); /* Copy the data into buffer provided by the user */ RtlCopyMemory( Current->Buffer, diff --git a/reactos/drivers/lib/ip/transport/rawip/rawip.c b/reactos/drivers/lib/ip/transport/rawip/rawip.c index e75d78a8325..181cc04e550 100644 --- a/reactos/drivers/lib/ip/transport/rawip/rawip.c +++ b/reactos/drivers/lib/ip/transport/rawip/rawip.c @@ -2,7 +2,7 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS TCP/IP protocol driver * FILE: transport/rawip/rawip.c - * PURPOSE: Raw IP routines + * PURPOSE: User Datagram Protocol routines * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISIONS: * CSH 01/08-2000 Created @@ -10,71 +10,155 @@ #include "precomp.h" - -BOOLEAN RawIPInitialized = FALSE; - - -NTSTATUS BuildRawIPPacket( - PIP_PACKET Packet, - UINT DataLength, +NTSTATUS AddGenericHeaderIPv4( + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, PIP_ADDRESS LocalAddress, - USHORT LocalPort ) + USHORT LocalPort, + PIP_PACKET IPPacket, + UINT DataLength, + UINT Protocol, + UINT ExtraLength, + PVOID *NextHeader ) /* - * FUNCTION: Builds an UDP packet + * FUNCTION: Adds an IPv4 and RawIp header to an IP packet + * ARGUMENTS: + * SendRequest = Pointer to send request + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from + * IPPacket = Pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + PIPv4_HEADER IPHeader; + ULONG BufferSize; + + TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", + IPPacket, IPPacket->NdisPacket)); + + BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + ExtraLength; + + GetDataPtr( IPPacket->NdisPacket, + MaxLLHeaderSize, + (PCHAR *)&IPPacket->Header, + &IPPacket->ContigSize ); + + IPPacket->HeaderSize = 20; + + TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", + BufferSize, IPPacket->Header)); + TI_DbgPrint(MAX_TRACE, ("Packet total length %d\n", IPPacket->TotalSize)); + + /* Build IPv4 header */ + IPHeader = (PIPv4_HEADER)IPPacket->Header; + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of header and data */ + IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); + /* Identification */ + IPHeader->Id = 0; + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* User Datagram Protocol */ + IPHeader->Protocol = Protocol; + /* Checksum is 0 (for later calculation of this) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; + /* Destination address. FIXME: IPv4 only */ + IPHeader->DstAddr = RemoteAddress->Address.IPv4Address; + + /* Build RawIp header */ + *NextHeader = (((PCHAR)IPHeader) + sizeof(IPv4_HEADER)); + IPPacket->Data = ((PCHAR)*NextHeader) + ExtraLength; + + return STATUS_SUCCESS; +} + + +NTSTATUS BuildRawIpPacket( + PIP_PACKET Packet, + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PCHAR DataBuffer, + UINT DataLen ) +/* + * FUNCTION: Builds an RawIp packet * ARGUMENTS: * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) - * LocalAddress = Pointer to our local address (NULL) - * LocalPort = The port we send this datagram from (0) + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from * IPPacket = Address of pointer to IP packet * RETURNS: * Status of operation */ { - PVOID Header; - NDIS_STATUS NdisStatus; - PNDIS_BUFFER HeaderBuffer; - PNDIS_PACKET NdisPacket = Packet->NdisPacket; - /* Will be zeroed in packet by IPInitializePacket */ - + NTSTATUS Status; + PCHAR Payload; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Assumes IPv4 */ + IPInitializePacket(Packet, IP_ADDRESS_V4); + if (!Packet) + return STATUS_INSUFFICIENT_RESOURCES; + + Packet->TotalSize = sizeof(IPv4_HEADER) + DataLen; + /* Prepare packet */ - IPInitializePacket(Packet,IP_ADDRESS_V4); - Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */ - Packet->TotalSize = DataLength; - Packet->NdisPacket = NdisPacket; + Status = AllocatePacketWithBuffer( &Packet->NdisPacket, + NULL, + Packet->TotalSize + MaxLLHeaderSize ); + + if( !NT_SUCCESS(Status) ) return Status; - if (MaxLLHeaderSize != 0) { - Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize); - if (!Header) { - TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n")); - return STATUS_INSUFFICIENT_RESOURCES; - } + TI_DbgPrint(MID_TRACE, ("Allocated packet: %x\n", Packet->NdisPacket)); + TI_DbgPrint(MID_TRACE, ("Local Addr : %s\n", A2S(LocalAddress))); + TI_DbgPrint(MID_TRACE, ("Remote Addr: %s\n", A2S(RemoteAddress))); + + switch (RemoteAddress->Type) { + case IP_ADDRESS_V4: + Status = AddGenericHeaderIPv4 + (RemoteAddress, RemotePort, + LocalAddress, LocalPort, Packet, DataLen, + IPPROTO_ICMP, /* XXX Figure out a better way to do this */ + 0, (PVOID *)&Payload ); + break; + case IP_ADDRESS_V6: + /* FIXME: Support IPv6 */ + Status = STATUS_UNSUCCESSFUL; + TI_DbgPrint(MIN_TRACE, ("IPv6 RawIp datagrams are not supported.\n")); + break; - TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", - MaxLLHeaderSize, Header)); - - /* Allocate NDIS buffer for maximum link level header */ - NdisAllocateBuffer(&NdisStatus, - &HeaderBuffer, - GlobalBufferPool, - Header, - MaxLLHeaderSize); - - if (NdisStatus != NDIS_STATUS_SUCCESS) { - TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus)); - ExFreePool(Header); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Chain header at front of packet */ - NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer); + default: + Status = STATUS_UNSUCCESSFUL; + TI_DbgPrint(MIN_TRACE, ("Bad Address Type %d\n", RemoteAddress->Type)); + break; } - + + TI_DbgPrint(MID_TRACE, ("Copying data (hdr %x data %x (%d))\n", + Packet->Header, Packet->Data, + (PCHAR)Packet->Data - (PCHAR)Packet->Header)); + + RtlCopyMemory( Packet->Data, DataBuffer, DataLen ); + + TI_DbgPrint(MID_TRACE, ("Displaying packet\n")); + DISPLAY_IP_PACKET(Packet); - + + TI_DbgPrint(MID_TRACE, ("Leaving\n")); + return STATUS_SUCCESS; } -VOID RawIPSendComplete +VOID RawIpSendPacketComplete ( PVOID Context, PNDIS_PACKET Packet, NDIS_STATUS Status ) { FreeNdisPacket( Packet ); } @@ -83,10 +167,10 @@ NTSTATUS RawIPSendDatagram( PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, PCHAR BufferData, - ULONG BufferLen, - PULONG DataUsed ) + ULONG DataSize, + PULONG DataUsed ) /* - * FUNCTION: Sends a raw IP datagram to a remote address + * FUNCTION: Sends an RawIp datagram to a remote address * ARGUMENTS: * Request = Pointer to TDI request * ConnInfo = Pointer to connection information @@ -96,134 +180,258 @@ NTSTATUS RawIPSendDatagram( * Status of operation */ { - NDIS_STATUS Status; IP_PACKET Packet; - PNEIGHBOR_CACHE_ENTRY NCE; + PTA_IP_ADDRESS RemoteAddressTa = (PTA_IP_ADDRESS)ConnInfo->RemoteAddress; IP_ADDRESS RemoteAddress; + USHORT RemotePort; + NTSTATUS Status; + PNEIGHBOR_CACHE_ENTRY NCE; - Status = AllocatePacketWithBuffer( &Packet.NdisPacket, - BufferData, - BufferLen ); - - TI_DbgPrint(MID_TRACE,("Packet.NdisPacket %x\n", Packet.NdisPacket)); + TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n", + AddrFile, ConnInfo, BufferData, DataSize)); + TI_DbgPrint(MID_TRACE,("RemoteAddressTa: %x\n", RemoteAddressTa)); - *DataUsed = BufferLen; - - if( Status == NDIS_STATUS_SUCCESS ) - Status = BuildRawIPPacket( &Packet, - BufferLen, - &AddrFile->Address, - AddrFile->Port ); - - if( Status == NDIS_STATUS_SUCCESS ) { + switch( RemoteAddressTa->Address[0].AddressType ) { + case TDI_ADDRESS_TYPE_IP: RemoteAddress.Type = IP_ADDRESS_V4; - RtlCopyMemory( &RemoteAddress.Address.IPv4Address, - BufferData + FIELD_OFFSET(IPv4_HEADER, DstAddr), - sizeof(IPv4_RAW_ADDRESS) ); + RemoteAddress.Address.IPv4Address = + RemoteAddressTa->Address[0].Address[0].in_addr; + RemotePort = RemoteAddressTa->Address[0].Address[0].sin_port; + break; - if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) { - FreeNdisPacket( Packet.NdisPacket ); - return STATUS_NO_SUCH_DEVICE; - } - - IPSendDatagram( &Packet, NCE, RawIPSendComplete, NULL ); - } else - FreeNdisPacket( Packet.NdisPacket ); + default: + return STATUS_UNSUCCESSFUL; + } + + Status = BuildRawIpPacket( &Packet, + &RemoteAddress, + RemotePort, + &AddrFile->Address, + AddrFile->Port, + BufferData, + DataSize ); + + if( !NT_SUCCESS(Status) ) + return Status; + TI_DbgPrint(MID_TRACE,("About to get route to destination\n")); + + if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) + return STATUS_UNSUCCESSFUL; + + TI_DbgPrint(MID_TRACE,("About to send datagram\n")); + + IPSendDatagram( &Packet, NCE, RawIpSendPacketComplete, NULL ); + + TI_DbgPrint(MID_TRACE,("Leaving\n")); + + return STATUS_SUCCESS; +} + +VOID RawIpReceiveComplete(PVOID Context, NTSTATUS Status, ULONG Count) { + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest = + (PDATAGRAM_RECEIVE_REQUEST)Context; + TI_DbgPrint(MAX_TRACE,("Called\n")); + ReceiveRequest->UserComplete( ReceiveRequest->UserContext, Status, Count ); + exFreePool( ReceiveRequest ); + TI_DbgPrint(MAX_TRACE,("Done\n")); +} + +NTSTATUS RawIPReceiveDatagram( + PADDRESS_FILE AddrFile, + PTDI_CONNECTION_INFORMATION ConnInfo, + PCHAR BufferData, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived, + PDATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context) +/* + * FUNCTION: Attempts to receive an RawIp datagram from a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer chain to store received data + * ReceiveLength = Maximum size to use of buffer, 0 if all can be used + * ReceiveFlags = Receive flags (None, Normal, Peek) + * ReturnInfo = Pointer to structure for return information + * BytesReceive = Pointer to structure for number of bytes received + * RETURNS: + * Status of operation + * NOTES: + * This is the high level interface for receiving RawIp datagrams + */ +{ + KIRQL OldIrql; + NTSTATUS Status; + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (AF_IS_VALID(AddrFile)) + { + ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST)); + if (ReceiveRequest) + { + /* Initialize a receive request */ + + /* Extract the remote address filter from the request (if any) */ + if ((ConnInfo->RemoteAddressLength != 0) && + (ConnInfo->RemoteAddress)) + { + Status = AddrGetAddress(ConnInfo->RemoteAddress, + &ReceiveRequest->RemoteAddress, + &ReceiveRequest->RemotePort); + if (!NT_SUCCESS(Status)) + { + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + exFreePool(ReceiveRequest); + return Status; + } + } + else + { + ReceiveRequest->RemotePort = 0; + } + ReceiveRequest->ReturnInfo = ReturnInfo; + ReceiveRequest->Buffer = BufferData; + ReceiveRequest->BufferSize = ReceiveLength; + ReceiveRequest->UserComplete = Complete; + ReceiveRequest->UserContext = Context; + ReceiveRequest->Complete = + (PDATAGRAM_COMPLETION_ROUTINE)RawIpReceiveComplete; + ReceiveRequest->Context = ReceiveRequest; + + /* Queue receive request */ + InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry); + AF_SET_PENDING(AddrFile, AFF_RECEIVE); + + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + + return STATUS_PENDING; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + Status = STATUS_INVALID_ADDRESS; + } + + TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status)); + return Status; } -VOID RawIPReceive( - PIP_INTERFACE Interface, - PIP_PACKET IPPacket) +VOID RawIpReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) /* - * FUNCTION: Receives and queues a raw IP datagram + * FUNCTION: Receives and queues a RawIp datagram * ARGUMENTS: * NTE = Pointer to net table entry which the packet was received on - * IPPacket = Pointer to an IP packet that was received - * NOTES: - * This is the low level interface for receiving ICMP datagrams. - * It delivers the packet header and data to anyone that wants it - * When we get here the datagram has already passed sanity checks +* IPPacket = Pointer to an IP packet that was received +* NOTES: +* This is the low level interface for receiving RawIp datagrams. It strips +* the RawIp header from a packet and delivers the data to anyone that wants it +*/ +{ + AF_SEARCH SearchContext; + PIPv4_HEADER IPv4Header; + PADDRESS_FILE AddrFile; + PIP_ADDRESS DstAddress, SrcAddress; + UINT DataSize; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (IPPacket->Type) { + /* IPv4 packet */ + case IP_ADDRESS_V4: + IPv4Header = IPPacket->Header; + DstAddress = &IPPacket->DstAddr; + SrcAddress = &IPPacket->SrcAddr; + DataSize = IPPacket->TotalSize; + break; + + /* IPv6 packet */ + case IP_ADDRESS_V6: + TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 datagram (%i bytes).\n", IPPacket->TotalSize)); + + /* FIXME: IPv6 is not supported */ + return; + + default: + return; + } + + /* Locate a receive request on destination address file object + and deliver the packet if one is found. If there is no receive + request on the address file object, call the associated receive + handler. If no receive handler is registered, drop the packet */ + + AddrFile = AddrSearchFirst(DstAddress, + 0, + IPv4Header->Protocol, + &SearchContext); + if (AddrFile) { + do { + DGDeliverData(AddrFile, + SrcAddress, + DstAddress, + 0, + 0, + IPPacket, + DataSize); + } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); + } else { + /* There are no open address files that will take this datagram */ + /* FIXME: IPv4 only */ + TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 raw datagram to address (0x%X).\n", + DN2H(DstAddress->Address.IPv4Address))); + + /* FIXME: Send ICMP reply */ + } + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS RawIPStartup(VOID) +/* + * FUNCTION: Initializes the UDP subsystem + * RETURNS: + * Status of operation */ { - PIP_ADDRESS DstAddress; - - TI_DbgPrint(MAX_TRACE, ("Called.\n")); - - switch (IPPacket->Type) { - /* IPv4 packet */ - case IP_ADDRESS_V4: - DstAddress = &IPPacket->DstAddr; - break; - - /* IPv6 packet */ - case IP_ADDRESS_V6: - TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 raw IP datagram (%i bytes).\n", - IPPacket->TotalSize)); - - /* FIXME: IPv6 is not supported */ - return; - - default: - return; - } - - /* Locate a receive request on destination address file object - and deliver the packet if one is found. If there is no receive - request on the address file object, call the associated receive - handler. If no receive handler is registered, drop the packet */ - -#if 0 /* Decide what to do here */ - AddrFile = AddrSearchFirst(DstAddress, - 0, - IPPROTO_ICMP, - &SearchContext); - if (AddrFile) { - do { - DGDeliverData(AddrFile, - DstAddress, - IPPacket, - IPPacket->TotalSize); - } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); - } else { - /* There are no open address files that will take this datagram */ - /* FIXME: IPv4 only */ - TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 ICMP datagram to address (0x%X).\n", - DN2H(DstAddress->Address.IPv4Address))); - } +#ifdef __NTDRIVER__ + RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS)); #endif - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + /* Register this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_ICMP, RawIpReceive); + + return STATUS_SUCCESS; } -NTSTATUS RawIPStartup( - VOID) +NTSTATUS RawIPShutdown(VOID) /* - * FUNCTION: Initializes the Raw IP subsystem + * FUNCTION: Shuts down the UDP subsystem * RETURNS: * Status of operation */ { - RawIPInitialized = TRUE; + /* Deregister this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_ICMP, NULL); - return STATUS_SUCCESS; -} - - -NTSTATUS RawIPShutdown( - VOID) -/* - * FUNCTION: Shuts down the Raw IP subsystem - * RETURNS: - * Status of operation - */ -{ - if (!RawIPInitialized) - return STATUS_SUCCESS; - - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/drivers/lib/ip/transport/tcp/accept.c b/reactos/drivers/lib/ip/transport/tcp/accept.c index 1b79bed5aa3..40287184187 100644 --- a/reactos/drivers/lib/ip/transport/tcp/accept.c +++ b/reactos/drivers/lib/ip/transport/tcp/accept.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS TCP/IP protocol driver - * FILE: transport/tcp/tcp.c + * FILE: transport/tcp/accept.c * PURPOSE: Transmission Control Protocol Listen/Accept code * PROGRAMMERS: Art Yerkes (arty@users.sf.net) * REVISIONS: @@ -16,8 +16,7 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, NTSTATUS Status; SOCKADDR_IN OutAddr; OSK_UINT OutAddrLen; - PTA_ADDRESS RequestAddressReturn; - SOCKADDR_IN AddressConnecting; + PTA_IP_ADDRESS RequestAddressReturn; PTDI_CONNECTION_INFORMATION WhoIsConnecting; /* Unpack TDI info -- We need the return connection information @@ -38,22 +37,23 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener, TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status)); if( NT_SUCCESS(Status) && Status != STATUS_PENDING ) { + RequestAddressReturn = WhoIsConnecting->RemoteAddress; + TI_DbgPrint(DEBUG_TCP,("Copying address to %x (Who %x)\n", RequestAddressReturn, WhoIsConnecting)); - RequestAddressReturn = (PTA_ADDRESS)WhoIsConnecting->RemoteAddress; - RequestAddressReturn->AddressLength = OutAddrLen; - RequestAddressReturn->AddressType = - AddressConnecting.sin_family; - TI_DbgPrint(DEBUG_TCP,("Copying address proper: from %x to %x,%x\n", - ((PCHAR)&AddressConnecting) + - sizeof(AddressConnecting.sin_family), - RequestAddressReturn->Address, - RequestAddressReturn->AddressLength)); - RtlCopyMemory( RequestAddressReturn->Address, - ((PCHAR)&AddressConnecting) + - sizeof(AddressConnecting.sin_family), - RequestAddressReturn->AddressLength ); + RequestAddressReturn->TAAddressCount = 1; + RequestAddressReturn->Address[0].AddressLength = OutAddrLen; + + /* BSD uses the first byte of the sockaddr struct as a length. + * Since windows doesn't do that we strip it */ + RequestAddressReturn->Address[0].AddressType = + (OutAddr.sin_family >> 8) & 0xff; + + RtlCopyMemory( &RequestAddressReturn->Address[0].Address, + ((PCHAR)&OutAddr) + sizeof(USHORT), + sizeof(RequestAddressReturn->Address[0].Address[0]) ); + TI_DbgPrint(DEBUG_TCP,("Done copying\n")); } @@ -151,7 +151,7 @@ NTSTATUS TCPAccept } TcpipRecursiveMutexLeave( &TCPLock ); - + TI_DbgPrint(DEBUG_TCP,("TCPAccept finished %x\n", Status)); return Status; } diff --git a/reactos/drivers/lib/ip/transport/tcp/event.c b/reactos/drivers/lib/ip/transport/tcp/event.c index 401d4444b9c..d22ed771af8 100644 --- a/reactos/drivers/lib/ip/transport/tcp/event.c +++ b/reactos/drivers/lib/ip/transport/tcp/event.c @@ -41,9 +41,10 @@ int TCPSocketState(void *ClientData, TI_DbgPrint(MID_TRACE,("Connection signalled: %d\n", Connection->Signalled)); + + Connection->SignalState |= NewState; if( !Connection->Signalled ) { Connection->Signalled = TRUE; - Connection->SignalState = NewState; InsertTailList( &SignalledConnections, &Connection->SignalList ); } diff --git a/reactos/drivers/lib/ip/transport/tcp/tcp.c b/reactos/drivers/lib/ip/transport/tcp/tcp.c index c46b8ce7fa5..167add772ee 100644 --- a/reactos/drivers/lib/ip/transport/tcp/tcp.c +++ b/reactos/drivers/lib/ip/transport/tcp/tcp.c @@ -30,24 +30,35 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, PIRP Irp; PMDL Mdl; + TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n", + Connection, Connection->SocketContext)); + /* Things that can happen when we try the initial connection */ - if( ((NewState & SEL_CONNECT) || (NewState & SEL_FIN)) && - !(Connection->State & (SEL_CONNECT | SEL_FIN)) ) { + if( NewState & SEL_CONNECT ) { while( !IsListEmpty( &Connection->ConnectRequest ) ) { - Connection->State |= NewState & (SEL_CONNECT | SEL_FIN); - Entry = RemoveHeadList( &Connection->ConnectRequest ); - Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - Complete = Bucket->Request.RequestNotifyObject; - TI_DbgPrint(DEBUG_TCP, - ("Completing Connect Request %x\n", Bucket->Request)); - if( NewState & SEL_FIN ) Status = STATUS_CONNECTION_REFUSED; - Complete( Bucket->Request.RequestContext, Status, 0 ); - /* Frees the bucket allocated in TCPConnect */ - PoolFreeBuffer( Bucket ); - } + Connection->State |= NewState; + Entry = RemoveHeadList( &Connection->ConnectRequest ); + TI_DbgPrint(DEBUG_TCP, ("Connect Event\n")); + + Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); + Complete = Bucket->Request.RequestNotifyObject; + TI_DbgPrint(DEBUG_TCP, + ("Completing Request %x\n", Bucket->Request)); + + if( (NewState & (SEL_CONNECT | SEL_FIN)) == + (SEL_CONNECT | SEL_FIN) ) + Status = STATUS_CONNECTION_REFUSED; + else + Status = STATUS_SUCCESS; + + Complete( Bucket->Request.RequestContext, Status, 0 ); + + /* Frees the bucket allocated in TCPConnect */ + PoolFreeBuffer( Bucket ); + } } - if( (NewState & SEL_ACCEPT) ) { + if( NewState & SEL_ACCEPT ) { /* Handle readable on a listening socket -- * TODO: Implement filtering */ @@ -84,7 +95,7 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, } /* Things that happen after we're connected */ - if( (NewState & SEL_READ) ) { + if( NewState & SEL_READ ) { TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n", IsListEmpty(&Connection->ReceiveRequest) ? "empty" : "nonempty")); @@ -142,6 +153,7 @@ static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection, } } } + if( NewState & SEL_FIN ) { TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n")); @@ -529,7 +541,8 @@ NTSTATUS TCPReceiveData NTSTATUS Status; PTDI_BUCKET Bucket; - TI_DbgPrint(DEBUG_TCP,("Called for %d bytes\n", ReceiveLength)); + TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n", + ReceiveLength, Connection->SocketContext)); ASSERT_KM_POINTER(Connection->SocketContext); @@ -616,7 +629,11 @@ VOID TCPTimeout(VOID) { UINT TCPAllocatePort( UINT HintPort ) { if( HintPort ) { if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort; - else return (UINT)-1; + else { + TI_DbgPrint + (MID_TRACE,("We got a hint port but couldn't allocate it\n")); + return (UINT)-1; + } } else return AllocatePortFromRange( &TCPPorts, 1024, 5000 ); } @@ -624,4 +641,25 @@ VOID TCPFreePort( UINT Port ) { DeallocatePort( &TCPPorts, Port ); } +NTSTATUS TCPGetPeerAddress +( PCONNECTION_ENDPOINT Connection, + PTRANSPORT_ADDRESS Address ) { + OSK_UINT LocalAddress, RemoteAddress; + OSK_UI16 LocalPort, RemotePort; + PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address; + + OskitTCPGetAddress + ( Connection->SocketContext, + &LocalAddress, &LocalPort, + &RemoteAddress, &RemotePort ); + + AddressIP->TAAddressCount = 1; + AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; + AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; + AddressIP->Address[0].Address[0].sin_port = RemotePort; + AddressIP->Address[0].Address[0].in_addr = RemoteAddress; + + return STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/drivers/lib/ip/transport/udp/udp.c b/reactos/drivers/lib/ip/transport/udp/udp.c index 3cff36b752f..0fbb5d61545 100644 --- a/reactos/drivers/lib/ip/transport/udp/udp.c +++ b/reactos/drivers/lib/ip/transport/udp/udp.c @@ -14,7 +14,6 @@ BOOLEAN UDPInitialized = FALSE; PORT_SET UDPPorts; - NTSTATUS AddUDPHeaderIPv4( PIP_ADDRESS RemoteAddress, USHORT RemotePort, @@ -33,51 +32,19 @@ NTSTATUS AddUDPHeaderIPv4( * Status of operation */ { - PIPv4_HEADER IPHeader; PUDP_HEADER UDPHeader; - ULONG BufferSize; TI_DbgPrint(MID_TRACE, ("Packet: %x NdisPacket %x\n", IPPacket, IPPacket->NdisPacket)); - - BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(UDP_HEADER); - - GetDataPtr( IPPacket->NdisPacket, - MaxLLHeaderSize, - (PCHAR *)&IPPacket->Header, - &IPPacket->ContigSize ); - - IPPacket->HeaderSize = 20; - - TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", - BufferSize, IPPacket->Header)); - TI_DbgPrint(MAX_TRACE, ("Packet total length %d\n", IPPacket->TotalSize)); - - /* Build IPv4 header */ - IPHeader = (PIPv4_HEADER)IPPacket->Header; - /* Version = 4, Length = 5 DWORDs */ - IPHeader->VerIHL = 0x45; - /* Normal Type-of-Service */ - IPHeader->Tos = 0; - /* Length of header and data */ - IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); - /* Identification */ - IPHeader->Id = 0; - /* One fragment at offset 0 */ - IPHeader->FlagsFragOfs = 0; - /* Time-to-Live is 128 */ - IPHeader->Ttl = 128; - /* User Datagram Protocol */ - IPHeader->Protocol = IPPROTO_UDP; - /* Checksum is 0 (for later calculation of this) */ - IPHeader->Checksum = 0; - /* Source address */ - IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; - /* Destination address. FIXME: IPv4 only */ - IPHeader->DstAddr = RemoteAddress->Address.IPv4Address; + + AddGenericHeaderIPv4 + ( RemoteAddress, RemotePort, + LocalAddress, LocalPort, + IPPacket, DataLength, IPPROTO_UDP, + sizeof(UDP_HEADER), (PVOID *)&UDPHeader ); /* Build UDP header */ - UDPHeader = (PUDP_HEADER)(((PCHAR)IPHeader) + sizeof(IPv4_HEADER)); + UDPHeader = (PUDP_HEADER)(IPPacket->Data - sizeof(UDP_HEADER)); /* Port values are already big-endian values */ UDPHeader->SourcePort = LocalPort; UDPHeader->DestPort = RemotePort; @@ -89,7 +56,7 @@ NTSTATUS AddUDPHeaderIPv4( IPPacket->Data = ((PCHAR)UDPHeader) + sizeof(UDP_HEADER); TI_DbgPrint(MID_TRACE, ("Packet: %d ip %d udp %d payload\n", - (PCHAR)UDPHeader - (PCHAR)IPHeader, + (PCHAR)UDPHeader - (PCHAR)IPPacket->Header, (PCHAR)IPPacket->Data - (PCHAR)UDPHeader, DataLength)); @@ -440,7 +407,7 @@ NTSTATUS UDPStartup( RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS)); #endif - PortsStartup( &UDPPorts, UDP_STARTING_PORT, UDP_DYNAMIC_PORTS ); + PortsStartup( &UDPPorts, 1, 0xfffe ); /* Register this protocol with IP layer */ IPRegisterProtocol(IPPROTO_UDP, UDPReceive); @@ -472,9 +439,11 @@ NTSTATUS UDPShutdown( UINT UDPAllocatePort( UINT HintPort ) { if( HintPort ) { - if( AllocatePort( &UDPPorts, HintPort ) ) return HintPort; - else return (UINT)-1; - } else return AllocateAnyPort( &UDPPorts ); + if( AllocatePort( &UDPPorts, HintPort ) ) return HintPort; + else return (UINT)-1; + } else return AllocatePortFromRange + ( &UDPPorts, UDP_STARTING_PORT, + UDP_STARTING_PORT + UDP_DYNAMIC_PORTS ); } VOID UDPFreePort( UINT Port ) { diff --git a/reactos/drivers/lib/oskittcp/oskittcp/interface.c b/reactos/drivers/lib/oskittcp/oskittcp/interface.c index bb60fd5255a..5d9bb3bf70c 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/interface.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/interface.c @@ -22,8 +22,8 @@ struct linker_set domain_set; OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 }; -OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA; -//OSK_UINT OskitDebugTraceLevel = 0; +//OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA; +OSK_UINT OskitDebugTraceLevel = 0; /* SPL */ unsigned cpl; @@ -295,6 +295,7 @@ int OskitTCPAccept( void *socket, struct socket *so = socket; struct sockaddr_in sa; struct mbuf mnam; + struct inpcb *inp; int namelen = 0, error = 0, s; OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n", @@ -308,8 +309,6 @@ int OskitTCPAccept( void *socket, s = splnet(); - OskitDumpBuffer( so, sizeof(*so) ); - #if 0 if ((head->so_options & SO_ACCEPTCONN) == 0) { splx(s); @@ -363,6 +362,13 @@ int OskitTCPAccept( void *socket, */ so = head->so_q; + inp = so ? so->so_pcb : 0; + if( inp ) { + ((struct sockaddr_in *)AddrOut)->sin_addr.s_addr = + inp->inp_faddr.s_addr; + ((struct sockaddr_in *)AddrOut)->sin_port = inp->inp_fport; + } + OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); if( FinishAccepting ) { head->so_q = so->so_q; @@ -380,8 +386,6 @@ int OskitTCPAccept( void *socket, so->so_state = SS_NBIO | SS_ISCONNECTED; - OskitDumpBuffer( so, sizeof(*so) ); - OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error)); if (name) { /* check sa_len before it is destroyed */ diff --git a/reactos/drivers/lib/oskittcp/oskittcp/uipc_domain.c b/reactos/drivers/lib/oskittcp/oskittcp/uipc_domain.c index 08a1800eb41..7ab1555b6f3 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/uipc_domain.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/uipc_domain.c @@ -64,7 +64,7 @@ domaininit() register struct domain *dp, **dpp; register struct protosw *pr; - printf("domaininit starting\n"); + //printf("domaininit starting\n"); /* * NB - local domain is always present. @@ -73,7 +73,7 @@ domaininit() ADDDOMAIN(inet); for (dpp = (struct domain **)domain_set.ls_items; *dpp; dpp++) { - printf("(1) Domain %s counting\n", (**dpp).dom_name); + //printf("(1) Domain %s counting\n", (**dpp).dom_name); (**dpp).dom_next = domains; domains = *dpp; } @@ -84,11 +84,11 @@ domaininit() #endif */ for (dp = domains; dp; dp = dp->dom_next) { - printf("(1) Domain %s initializing\n", dp->dom_name); + //printf("(1) Domain %s initializing\n", dp->dom_name); if (dp->dom_init) (*dp->dom_init)(); for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { - printf("Registering protocols for %s\n", dp->dom_name); + //printf("Registering protocols for %s\n", dp->dom_name); if (pr->pr_init) (*pr->pr_init)(); } @@ -103,7 +103,7 @@ domaininit() timeout(pffasttimo, (void *)0, 1); timeout(pfslowtimo, (void *)0, 1); - printf("Domaininit done\n"); + //printf("Domaininit done\n"); } struct protosw * diff --git a/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c b/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c index fa031f8ce7f..b9b4a41fee6 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/uipc_mbuf.c @@ -79,11 +79,11 @@ mbinit() #else #define NCL_INIT 1 #endif - printf("Here1\n"); + //printf("Here1\n"); s = splimp(); if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) goto bad; - printf("Here2\n"); + //printf("Here2\n"); splx(s); return; bad: @@ -116,12 +116,12 @@ m_clalloc(ncl, nowait) npg = ncl * CLSIZE; - printf("kmem_malloc(%d)\n", npg); + //printf("kmem_malloc(%d)\n", npg); p = (caddr_t)kmem_malloc(mb_map, ctob(npg), nowait ? M_NOWAIT : M_WAITOK); - printf("kmem_malloc done\n"); + //printf("kmem_malloc done\n"); /* * Either the map is now full, or this is nowait and there @@ -133,13 +133,13 @@ m_clalloc(ncl, nowait) ncl = ncl * CLBYTES / MCLBYTES; for (i = 0; i < ncl; i++) { ((union mcluster *)p)->mcl_next = mclfree; - printf( "Freeing %x onto the free list\n", p); + //printf( "Freeing %x onto the free list\n", p); mclfree = (union mcluster *)p; p += MCLBYTES; mbstat.m_clfree++; } mbstat.m_clusters += ncl; - printf( "done with m_clalloc\n"); + //printf( "done with m_clalloc\n"); return (1); } #endif /* !OSKIT */ @@ -363,9 +363,7 @@ m_copym(m, off0, len, wait) #ifdef OSKIT oskit_bufio_addref(m->m_ext.ext_bufio); #else -#ifdef __REACTOS__ - m->m_data = malloc(m->m_len); -#else +#ifndef __REACTOS__ mclrefcnt[mtocl(m->m_ext.ext_buf)]++; #endif #endif /* OSKIT */ @@ -416,6 +414,7 @@ m_copydata(m, off, len, cp) if (m == 0) panic("m_copydata"); count = min(m->m_len - off, len); + OS_DbgPrint(OSK_MID_TRACE,("count %d len %d\n", count, len)); bcopy(mtod(m, caddr_t) + off, cp, count); len -= count; cp += count; diff --git a/reactos/drivers/net/afd/afd/bind.c b/reactos/drivers/net/afd/afd/bind.c index 7312c9fc6f6..68235244ff6 100644 --- a/reactos/drivers/net/afd/afd/bind.c +++ b/reactos/drivers/net/afd/afd/bind.c @@ -74,10 +74,6 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* This will be the from address for subsequent recvfrom calls */ TdiBuildConnectionInfo( &FCB->AddressFrom, FCB->LocalAddress ); - /* Allocate our backup buffer */ - FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size ); - FCB->PollState |= AFD_EVENT_SEND; - /* A datagram socket is always sendable */ AFD_DbgPrint(MID_TRACE,("Calling TdiReceiveDatagram\n")); diff --git a/reactos/drivers/net/afd/afd/connect.c b/reactos/drivers/net/afd/afd/connect.c index b653fa0af5b..c453940de03 100644 --- a/reactos/drivers/net/afd/afd/connect.c +++ b/reactos/drivers/net/afd/afd/connect.c @@ -41,7 +41,7 @@ NTSTATUS WarmSocketForConnection( PAFD_FCB FCB ) { } NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) { - NTSTATUS Status; + NTSTATUS Status = STATUS_NO_MEMORY; /* Allocate the receive area and start receiving */ FCB->Recv.Window = @@ -61,7 +61,7 @@ NTSTATUS MakeSocketIntoConnection( PAFD_FCB FCB ) { ReceiveComplete, FCB ); } - + return Status; } diff --git a/reactos/drivers/net/afd/afd/info.c b/reactos/drivers/net/afd/afd/info.c index 560a970e3fc..f521fade070 100644 --- a/reactos/drivers/net/afd/afd/info.c +++ b/reactos/drivers/net/afd/afd/info.c @@ -62,12 +62,14 @@ AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, } NTSTATUS STDCALL -AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, - PIO_STACK_LOCATION IrpSp ) { +AfdGetSockOrPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp, BOOLEAN Local ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; PAFD_FCB FCB = FileObject->FsContext; - PMDL Mdl; + PMDL Mdl = NULL, SysMdl = NULL; + PTDI_CONNECTION_INFORMATION ConnInfo = NULL; + PTRANSPORT_ADDRESS TransAddr = NULL; AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); @@ -94,12 +96,50 @@ AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, } _SEH_END; if( NT_SUCCESS(Status) ) { - Status = TdiQueryInformation - ( FCB->AddressFile.Object, - TDI_QUERY_ADDRESS_INFO, - Mdl ); - } + if( Local ) { + Status = TdiQueryInformation + ( FCB->AddressFile.Object, + TDI_QUERY_ADDRESS_INFO, + Mdl ); + } else { + if( !NT_SUCCESS + ( Status = TdiBuildNullConnectionInfo + ( &ConnInfo, + FCB->LocalAddress->Address[0].AddressType ) ) ) { + SysMdl = IoAllocateMdl + ( ConnInfo, + sizeof( TDI_CONNECTION_INFORMATION ) + + TaLengthOfTransportAddress + ( ConnInfo->RemoteAddress ), + FALSE, + FALSE, + NULL ); + } + if( SysMdl ) { + MmBuildMdlForNonPagedPool( SysMdl ); + Status = TdiQueryInformation + ( FCB->AddressFile.Object, + TDI_QUERY_CONNECTION_INFO, + SysMdl ); + } else Status = STATUS_NO_MEMORY; + + if( NT_SUCCESS(Status) ) { + TransAddr = + (PTRANSPORT_ADDRESS)MmMapLockedPages + ( Mdl, IoModifyAccess ); + } + + if( TransAddr ) + RtlCopyMemory( TransAddr, ConnInfo->RemoteAddress, + TaLengthOfTransportAddress + ( ConnInfo->RemoteAddress ) ); + + if( ConnInfo ) ExFreePool( ConnInfo ); + if( SysMdl ) IoFreeMdl( SysMdl ); + } + } + /* MmUnlockPages( Mdl ); */ IoFreeMdl( Mdl ); } else { diff --git a/reactos/drivers/net/afd/afd/listen.c b/reactos/drivers/net/afd/afd/listen.c index b38d4514d26..26ef02e0fe7 100644 --- a/reactos/drivers/net/afd/afd/listen.c +++ b/reactos/drivers/net/afd/afd/listen.c @@ -12,7 +12,9 @@ #include "tdiconn.h" #include "debug.h" -VOID SatisfyAccept( PIRP Irp, PFILE_OBJECT NewFileObject, +VOID SatisfyAccept( PAFD_DEVICE_EXTENSION DeviceExt, + PIRP Irp, + PFILE_OBJECT NewFileObject, PAFD_TDI_OBJECT_QELT Qelt ) { PAFD_FCB FCB = NewFileObject->FsContext; @@ -23,32 +25,49 @@ VOID SatisfyAccept( PIRP Irp, PFILE_OBJECT NewFileObject, FCB->State = SOCKET_STATE_CONNECTED; FCB->Connection = Qelt->Object; -#if 0 FCB->RemoteAddress = TaCopyTransportAddress( Qelt->ConnInfo->RemoteAddress ); -#endif Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); MakeSocketIntoConnection( FCB ); - + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( DeviceExt, NewFileObject ); + SocketStateUnlock( FCB ); } VOID SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) { PAFD_RECEIVED_ACCEPT_DATA ListenReceive = (PAFD_RECEIVED_ACCEPT_DATA)Irp->AssociatedIrp.SystemBuffer; + PTA_IP_ADDRESS IPAddr; ListenReceive->SequenceNumber = Qelt->Seq; + AFD_DbgPrint(MID_TRACE,("Giving SEQ %d to userland\n", Qelt->Seq)); -#if 0 + AFD_DbgPrint(MID_TRACE,("Socket Address (K) %x (U) %x\n", + &ListenReceive->Address, + Qelt->ConnInfo->RemoteAddress)); + TaCopyTransportAddressInPlace( &ListenReceive->Address, Qelt->ConnInfo->RemoteAddress ); -#endif - Irp->IoStatus.Information = sizeof(*ListenReceive); + IPAddr = (PTA_IP_ADDRESS)&ListenReceive->Address; + + AFD_DbgPrint(MID_TRACE,("IPAddr->TAAddressCount %d\n", + IPAddr->TAAddressCount)); + AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressType %d\n", + IPAddr->Address[0].AddressType)); + AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressLength %d\n", + IPAddr->Address[0].AddressLength)); + AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_port %x\n", + IPAddr->Address[0].Address[0].sin_port)); + AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_addr %x\n", + IPAddr->Address[0].Address[0].in_addr)); + + Irp->IoStatus.Information = ((PCHAR)&IPAddr[1]) - ((PCHAR)ListenReceive); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); } @@ -79,8 +98,21 @@ NTSTATUS DDKAPI ListenComplete TdiCloseDevice( FCB->Connection.Handle, FCB->Connection.Object ); } else { + UINT AddressType = + FCB->LocalAddress->Address[0].AddressType; + Qelt->Object = FCB->Connection; Qelt->Seq = FCB->ConnSeq++; + AFD_DbgPrint(MID_TRACE,("Address Type: %d (RA %x)\n", + AddressType, + FCB->ListenIrp. + ConnectionReturnInfo->RemoteAddress)); + + TdiBuildNullConnectionInfo( &Qelt->ConnInfo, AddressType ); + TaCopyTransportAddressInPlace + ( Qelt->ConnInfo->RemoteAddress, + FCB->ListenIrp.ConnectionReturnInfo->RemoteAddress ); + InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry ); } @@ -103,8 +135,6 @@ NTSTATUS DDKAPI ListenComplete if( !IsListEmpty( &FCB->PendingConnections ) ) { FCB->PollState |= AFD_EVENT_ACCEPT; PollReeval( FCB->DeviceExt, FCB->FileObject ); - } else { - FCB->PollState &= ~AFD_EVENT_ACCEPT; } SocketStateUnlock( FCB ); @@ -119,7 +149,7 @@ NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_FCB FCB = FileObject->FsContext; PAFD_LISTEN_DATA ListenReq; - AFD_DbgPrint(MID_TRACE,("Called\n")); + AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE ); @@ -186,6 +216,9 @@ NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, AFD_DbgPrint(MID_TRACE,("Completed a wait for accept\n")); + FCB->PollState &= ~AFD_EVENT_ACCEPT; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + SocketStateUnlock( FCB ); return Status; } else { @@ -199,6 +232,8 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ) { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_DEVICE_EXTENSION DeviceExt = + (PAFD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; PAFD_FCB FCB = FileObject->FsContext; PAFD_ACCEPT_DATA AcceptData = Irp->AssociatedIrp.SystemBuffer; PLIST_ENTRY PendingConn; @@ -207,6 +242,8 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, TRUE ); + FCB->EventsFired &= ~AFD_EVENT_ACCEPT; + if( FCB->NeedsNewListen ) { AFD_DbgPrint(MID_TRACE,("ADDRESSFILE: %x\n", FCB->AddressFile.Handle)); @@ -240,7 +277,7 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, PendingConnObj->Seq)); if( PendingConnObj->Seq == AcceptData->SequenceNumber ) { - PFILE_OBJECT NewFileObject; + PFILE_OBJECT NewFileObject = NULL; RemoveEntryList( PendingConn ); @@ -252,8 +289,11 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, (PVOID *)&NewFileObject, NULL ); + ASSERT(NewFileObject != FileObject); + ASSERT(NewFileObject->FsContext != FCB); + /* We have a pending connection ... complete this irp right away */ - SatisfyAccept( Irp, NewFileObject, PendingConnObj ); + SatisfyAccept( DeviceExt, Irp, NewFileObject, PendingConnObj ); ObDereferenceObject( NewFileObject ); diff --git a/reactos/drivers/net/afd/afd/main.c b/reactos/drivers/net/afd/afd/main.c index e70d4a4f178..1b9ab1d032d 100644 --- a/reactos/drivers/net/afd/afd/main.c +++ b/reactos/drivers/net/afd/afd/main.c @@ -19,8 +19,6 @@ #ifdef DBG -extern NTSTATUS DDKAPI MmCopyFromCaller( PVOID Dst, PVOID Src, UINT Size ); - /* See debug.h for debug/trace constants */ //DWORD DebugTraceLevel = DEBUG_ULTRA; DWORD DebugTraceLevel = 0; @@ -132,6 +130,18 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, } FileObject->FsContext = FCB; + + /* It seems that UDP sockets are writable from inception */ + if( FCB->Flags & SGID_CONNECTIONLESS ) { + AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n")); + /* Allocate our backup buffer */ + FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size ); + FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size ); + /* A datagram socket is always sendable */ + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); @@ -140,6 +150,7 @@ AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, VOID DestroySocket( PAFD_FCB FCB ) { UINT i; + BOOLEAN ReturnEarly = FALSE; PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS]; AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", FCB)); @@ -161,8 +172,7 @@ VOID DestroySocket( PAFD_FCB FCB ) { FCB->ListenIrp.InFlightRequest, FCB->ReceiveIrp.InFlightRequest, FCB->SendIrp.InFlightRequest)); - SocketStateUnlock( FCB ); - return; + ReturnEarly = TRUE; } /* After PoolReeval, this FCB should not be involved in any outstanding @@ -181,6 +191,8 @@ VOID DestroySocket( PAFD_FCB FCB ) { } SocketStateUnlock( FCB ); + + if( ReturnEarly ) return; if( FCB->Recv.Window ) ExFreePool( FCB->Recv.Window ); @@ -213,6 +225,8 @@ AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->PollState |= AFD_EVENT_CLOSE; PollReeval( FCB->DeviceExt, FileObject ); + KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE ); + if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect ); FileObject->FsContext = NULL; @@ -367,7 +381,10 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) return AfdDisconnect( DeviceObject, Irp, IrpSp ); case IOCTL_AFD_GET_SOCK_NAME: - return AfdGetSockName( DeviceObject, Irp, IrpSp ); + return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, TRUE ); + + case IOCTL_AFD_GET_PEER_NAME: + return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, FALSE ); case IOCTL_AFD_GET_TDI_HANDLES: AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n")); diff --git a/reactos/drivers/net/afd/afd/read.c b/reactos/drivers/net/afd/afd/read.c index cf83360977e..125615a0794 100644 --- a/reactos/drivers/net/afd/afd/read.c +++ b/reactos/drivers/net/afd/afd/read.c @@ -28,6 +28,13 @@ static VOID ProcessClose( PAFD_FCB FCB ); +BOOLEAN CantReadMore( PAFD_FCB FCB ) { + UINT BytesAvailable = FCB->Recv.Content - FCB->Recv.BytesUsed; + + return !BytesAvailable && + (FCB->PollState & (AFD_EVENT_CLOSE | AFD_EVENT_DISCONNECT)); +} + NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB, PAFD_RECV_INFO RecvReq, PUINT TotalBytesCopied ) { @@ -41,7 +48,7 @@ NTSTATUS TryToSatisfyRecvRequestFromBuffer( PAFD_FCB FCB, AFD_DbgPrint(MID_TRACE,("Called, BytesAvailable = %d\n", BytesAvailable)); - if( FCB->PollState & AFD_EVENT_CLOSE ) return STATUS_SUCCESS; + if( CantReadMore(FCB) ) return STATUS_SUCCESS; if( !BytesAvailable ) return STATUS_PENDING; Map = (PAFD_MAPBUF)(RecvReq->BufferArray + RecvReq->BufferCount); @@ -131,7 +138,7 @@ static VOID ProcessClose( PAFD_FCB FCB ) { } /* Handle closing signal */ - FCB->PollState |= AFD_EVENT_CLOSE; + FCB->PollState |= AFD_EVENT_DISCONNECT; PollReeval( FCB->DeviceExt, FCB->FileObject ); } @@ -159,9 +166,14 @@ NTSTATUS DDKAPI ReceiveComplete FCB->Recv.BytesUsed = 0; if( FCB->State == SOCKET_STATE_CLOSED ) { + AFD_DbgPrint(MIN_TRACE,("!!! CLOSED SOCK GOT A RECEIVE COMPLETE !!!\n")); SocketStateUnlock( FCB ); DestroySocket( FCB ); return STATUS_SUCCESS; + } else if( FCB->State == SOCKET_STATE_LISTENING ) { + AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n")); + SocketStateUnlock( FCB ); + return STATUS_UNSUCCESSFUL; } if( NT_SUCCESS(Irp->IoStatus.Status) && @@ -208,6 +220,24 @@ NTSTATUS DDKAPI ReceiveComplete Status = STATUS_SUCCESS; } else { + /* Success here means that we got an EOF. Close all pending reads + * with EOF. Data won't have been available before. */ + while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { + NextIrpEntry = + RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); + NextIrp = + CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); + NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); + RecvReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + + AFD_DbgPrint(MID_TRACE,("Completing recv %x (%d)\n", NextIrp, + TotalBytesCopied)); + UnlockBuffers( RecvReq->BufferArray, + RecvReq->BufferCount, FALSE ); + NextIrp->IoStatus.Status = Status; + NextIrp->IoStatus.Information = 0; + IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); + } ProcessClose( FCB ); } @@ -240,6 +270,12 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE ); + if( FCB->State != SOCKET_STATE_CONNECTED ) { + AFD_DbgPrint(MID_TRACE,("Called recv on wrong kind of socket (s%x)\n", + FCB->State)); + return STATUS_UNSUCCESSFUL; + } + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { AFD_DbgPrint(MID_TRACE,("Receive on connection-less sockets not implemented\n")); @@ -261,7 +297,7 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Check if we're not closed down yet */ - if( !(FCB->PollState & AFD_EVENT_CLOSE ) ) { + if( !CantReadMore(FCB) ) { AFD_DbgPrint(MID_TRACE,("Not EOF yet\n")); if( FCB->ReceiveIrp.InFlightRequest ) { AFD_DbgPrint(MID_TRACE,("We're waiting on a previous irp\n")); @@ -277,6 +313,9 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = STATUS_END_OF_FILE; ProcessClose( FCB ); + + return UnlockAndMaybeComplete + ( FCB, STATUS_SUCCESS, Irp, 0, NULL, FALSE); } if( NT_SUCCESS(Status) ) { @@ -295,6 +334,7 @@ AfdConnectedSocketReadData(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE ); } else { + AFD_DbgPrint(MID_TRACE,("Leaving read irp\n")); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_RECV ); } } diff --git a/reactos/drivers/net/afd/afd/select.c b/reactos/drivers/net/afd/afd/select.c index e5507b8b32b..aae2412693a 100644 --- a/reactos/drivers/net/afd/afd/select.c +++ b/reactos/drivers/net/afd/afd/select.c @@ -12,6 +12,25 @@ #include "tdiconn.h" #include "debug.h" +VOID PrintEvents( ULONG Events ) { + char *events_list[] = { "AFD_EVENT_RECEIVE", + "AFD_EVENT_OOB_RECEIVE", + "AFD_EVENT_SEND", + "AFD_EVENT_DISCONNECT", + "AFD_EVENT_ABORT", + "AFD_EVENT_CLOSE", + "AFD_EVENT_CONNECT", + "AFD_EVENT_ACCEPT", + "AFD_EVENT_CONNECT_FAIL", + "AFD_EVENT_QOS", + "AFD_EVENT_GROUP_QOS", + NULL }; + int i; + + for( i = 0; events_list[i]; i++ ) + if( Events & (1 << i) ) DbgPrint("%s ", events_list[i] ); +} + VOID CopyBackStatus( PAFD_HANDLE HandleArray, UINT HandleCount ) { UINT i; @@ -43,13 +62,23 @@ VOID RemoveSelect( PAFD_ACTIVE_POLL Poll ) { VOID SignalSocket( PAFD_ACTIVE_POLL Poll, PAFD_POLL_INFO PollReq, NTSTATUS Status ) { + int i; PIRP Irp = Poll->Irp; AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status)); + KeCancelTimer( &Poll->Timer ); Poll->Irp->IoStatus.Status = Status; Poll->Irp->IoStatus.Information = FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount; CopyBackStatus( PollReq->Handles, PollReq->HandleCount ); + for( i = 0; i < PollReq->HandleCount; i++ ) { + AFD_DbgPrint + (MAX_TRACE, + ("Handle(%x): Got %x,%x\n", + PollReq->Handles[i].Handle, + PollReq->Handles[i].Events, + PollReq->Handles[i].Status)); + } UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount ); AFD_DbgPrint(MID_TRACE,("Completing\n")); IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); @@ -83,12 +112,17 @@ VOID SelectTimeout( PKDPC Dpc, AFD_DbgPrint(MID_TRACE,("Timeout\n")); } -VOID KillExclusiveSelects( PAFD_DEVICE_EXTENSION DeviceExt ) { +VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + BOOLEAN OnlyExclusive ) { KIRQL OldIrql; PLIST_ENTRY ListEntry; PAFD_ACTIVE_POLL Poll; PIRP Irp; PAFD_POLL_INFO PollReq; + int i; + + AFD_DbgPrint(MID_TRACE,("Killing selects that refer to %x\n", FileObject)); KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql ); @@ -96,15 +130,23 @@ VOID KillExclusiveSelects( PAFD_DEVICE_EXTENSION DeviceExt ) { while ( ListEntry != &DeviceExt->Polls ) { Poll = CONTAINING_RECORD(ListEntry, AFD_ACTIVE_POLL, ListEntry); ListEntry = ListEntry->Flink; - if( Poll->Exclusive ) { - Irp = Poll->Irp; - PollReq = Irp->AssociatedIrp.SystemBuffer; - ZeroEvents( PollReq->Handles, PollReq->HandleCount ); - SignalSocket( Poll, PollReq, STATUS_CANCELLED ); + Irp = Poll->Irp; + PollReq = Irp->AssociatedIrp.SystemBuffer; + + for( i = 0; i < PollReq->HandleCount; i++ ) { + AFD_DbgPrint(MAX_TRACE,("Req: %x, This %x\n", + PollReq->Handles[i].Handle, FileObject)); + if( (PVOID)PollReq->Handles[i].Handle == FileObject && + (!OnlyExclusive || (OnlyExclusive && Poll->Exclusive)) ) { + ZeroEvents( PollReq->Handles, PollReq->HandleCount ); + SignalSocket( Poll, PollReq, STATUS_SUCCESS ); + } } } - + KeReleaseSpinLock( &DeviceExt->Lock, OldIrql ); + + AFD_DbgPrint(MID_TRACE,("Done\n")); } NTSTATUS STDCALL @@ -130,9 +172,6 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, SET_AFD_HANDLES(PollReq, LockHandles( PollReq->Handles, PollReq->HandleCount )); - if( Exclusive ) KillExclusiveSelects( DeviceExt ); - - if( !AFD_HANDLES(PollReq) ) { Irp->IoStatus.Status = STATUS_NO_MEMORY; Irp->IoStatus.Information = 0; @@ -140,6 +179,16 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, return Irp->IoStatus.Status; } + if( Exclusive ) { + for( i = 0; i < PollReq->HandleCount; i++ ) { + if( !AFD_HANDLES(PollReq)[i].Handle ) continue; + + KillSelectsForFCB( DeviceExt, + (PFILE_OBJECT)AFD_HANDLES(PollReq)[i].Handle, + TRUE ); + } + } + ZeroEvents( PollReq->Handles, PollReq->HandleCount ); @@ -173,6 +222,12 @@ AfdSelect( PDEVICE_OBJECT DeviceObject, PIRP Irp, PollReq->Handles[i].Status = AFD_EVENT_CLOSE; Signalled++; } else { +#ifdef DBG + DbgPrint("AFD: Select Events: "); + PrintEvents( PollReq->Handles[i].Events ); + DbgPrint("\n"); +#endif + PollReq->Handles[i].Status = PollReq->Handles[i].Events & FCB->PollState; if( PollReq->Handles[i].Status ) { diff --git a/reactos/drivers/net/afd/afd/tdiconn.c b/reactos/drivers/net/afd/afd/tdiconn.c index 2528a55aa58..45a3792356e 100644 --- a/reactos/drivers/net/afd/afd/tdiconn.c +++ b/reactos/drivers/net/afd/afd/tdiconn.c @@ -80,7 +80,8 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace */ { ULONG TdiAddressSize; - + PTRANSPORT_ADDRESS TransportAddress; + TdiAddressSize = TdiAddressSizeFromType(Type); RtlZeroMemory(ConnInfo, @@ -88,8 +89,11 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace TdiAddressSize); ConnInfo->OptionsLength = sizeof(ULONG); - ConnInfo->RemoteAddressLength = 0; - ConnInfo->RemoteAddress = NULL; + ConnInfo->RemoteAddressLength = TdiAddressSize; + ConnInfo->RemoteAddress = TransportAddress = + (PTRANSPORT_ADDRESS)&ConnInfo[1]; + TransportAddress->TAAddressCount = 1; + TransportAddress->Address[0].AddressType = Type; return STATUS_SUCCESS; } diff --git a/reactos/drivers/net/afd/afd/write.c b/reactos/drivers/net/afd/afd/write.c index bf0f7d007b3..69d09ed1311 100644 --- a/reactos/drivers/net/afd/afd/write.c +++ b/reactos/drivers/net/afd/afd/write.c @@ -22,7 +22,7 @@ NTSTATUS DDKAPI SendComplete PLIST_ENTRY NextIrpEntry; PIRP NextIrp = NULL; PIO_STACK_LOCATION NextIrpSp; - PAFD_SEND_INFO SendReq; + PAFD_SEND_INFO SendReq = NULL; PAFD_MAPBUF Map; UINT TotalBytesCopied = 0, SpaceAvail, i, CopySize = 0; @@ -165,6 +165,9 @@ NTSTATUS DDKAPI PacketSocketSendComplete /* It's ok if the FCB already died */ if( !SocketAcquireStateLock( FCB ) ) return STATUS_SUCCESS; + FCB->PollState |= AFD_EVENT_SEND; + PollReeval( FCB->DeviceExt, FCB->FileObject ); + FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ @@ -208,6 +211,12 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !(SendReq = LockRequest( Irp, IrpSp )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, FALSE ); + + /* Must lock buffers before handing off user data */ + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, + SendReq->BufferCount, + NULL, NULL, + FALSE, FALSE ); TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); @@ -260,7 +269,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, SendReq->BufferCount, NULL, NULL, FALSE, FALSE ); - + AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n", FCB->Send.BytesUsed)); @@ -355,6 +364,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE ); FCB->EventsFired &= ~AFD_EVENT_SEND; + FCB->PollState &= ~AFD_EVENT_SEND; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND ) diff --git a/reactos/drivers/net/afd/include/afd.h b/reactos/drivers/net/afd/include/afd.h index 22bceceed26..b58f1d1f49d 100644 --- a/reactos/drivers/net/afd/include/afd.h +++ b/reactos/drivers/net/afd/include/afd.h @@ -191,8 +191,8 @@ AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ); NTSTATUS STDCALL -AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp, - PIO_STACK_LOCATION IrpSp ); +AfdGetSockOrPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp, BOOLEAN Local ); /* listen.c */ NTSTATUS AfdWaitForListen( PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -262,6 +262,8 @@ NTSTATUS STDCALL AfdEnumEvents( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp ); VOID PollReeval( PAFD_DEVICE_EXTENSION DeviceObject, PFILE_OBJECT FileObject ); +VOID KillSelectsForFCB( PAFD_DEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, BOOLEAN ExclusiveOnly ); /* tdi.c */ diff --git a/reactos/drivers/net/ndis/ndis/miniport.c b/reactos/drivers/net/ndis/ndis/miniport.c index aaaf07c667d..0a792aaf10b 100644 --- a/reactos/drivers/net/ndis/ndis/miniport.c +++ b/reactos/drivers/net/ndis/ndis/miniport.c @@ -1933,7 +1933,7 @@ NdisMSetAttributes( */ { NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); - NdisMSetAttributesEx(MiniportAdapterContext, MiniportAdapterContext, 0, + NdisMSetAttributesEx(MiniportAdapterHandle, MiniportAdapterContext, 0, BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0, AdapterType); } diff --git a/reactos/drivers/net/ndis/ndis/protocol.c b/reactos/drivers/net/ndis/ndis/protocol.c index f83ff42aea6..f0d61d0efd1 100644 --- a/reactos/drivers/net/ndis/ndis/protocol.c +++ b/reactos/drivers/net/ndis/ndis/protocol.c @@ -855,7 +855,7 @@ NdisRegisterProtocol( } wcscpy(RegistryPathStr, SERVICES_KEY); - wcscat(RegistryPathStr, (((WCHAR *)(KeyInformation->Data)) +8 )); + wcscat(RegistryPathStr, DataPtr + 8 ); wcscat(RegistryPathStr, PARAMETERS_KEY); wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) ); diff --git a/reactos/drivers/net/tcpip/datalink/lan.c b/reactos/drivers/net/tcpip/datalink/lan.c index 731706ed0c9..4633b63c543 100644 --- a/reactos/drivers/net/tcpip/datalink/lan.c +++ b/reactos/drivers/net/tcpip/datalink/lan.c @@ -907,6 +907,14 @@ VOID BindAdapter( if(NT_SUCCESS(Status)) Status = ReadIPAddressFromRegistry( RegHandle, L"SubnetMask", &IF->Netmask ); + + IF->Broadcast.Type = IP_ADDRESS_V4; + IF->Broadcast.Address.IPv4Address = + IF->Unicast.Address.IPv4Address | + ~IF->Netmask.Address.IPv4Address; + + TI_DbgPrint(MID_TRACE,("BCAST(IF) %s\n", A2S(&IF->Broadcast))); + if(NT_SUCCESS(Status)) { Status = ReadStringFromRegistry( RegHandle, L"DeviceDesc", &IF->Name ); diff --git a/reactos/drivers/net/tcpip/datalink/loopback.c b/reactos/drivers/net/tcpip/datalink/loopback.c deleted file mode 100644 index 5213cd2d3e9..00000000000 --- a/reactos/drivers/net/tcpip/datalink/loopback.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS TCP/IP protocol driver - * FILE: datalink/loopback.c - * PURPOSE: Loopback adapter - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/08-2000 Created - */ - -#include "precomp.h" - -VOID LoopTransmit( - PVOID Context, - PNDIS_PACKET NdisPacket, - UINT Offset, - PVOID LinkAddress, - USHORT Type) -/* - * FUNCTION: Transmits a packet - * ARGUMENTS: - * Context = Pointer to context information (NULL) - * NdisPacket = Pointer to NDIS packet to send - * Offset = Offset in packet where packet data starts - * LinkAddress = Pointer to link address - * Type = LAN protocol type (unused) - */ -{ - IP_PACKET IPPacket; - - TI_DbgPrint(MAX_TRACE, ("Called (NdisPacket = %x)\n", NdisPacket)); - - IPPacket.NdisPacket = NdisPacket; - - IPReceive(Context, &IPPacket); - TI_DbgPrint(MAX_TRACE, ("Finished receive\n")); - ASSERT_KM_POINTER(Packet); - ASSERT_KM_POINTER(PC(Packet)); - ASSERT_KM_POINTER(PC(Packet)->DLComplete); - PC(NdisPacket)->DLComplete(Context, NdisPacket, NDIS_STATUS_SUCCESS); - TI_DbgPrint(MAX_TRACE, ("Done\n")); -} - -NDIS_STATUS LoopRegisterAdapter( - PNDIS_STRING AdapterName, - PLAN_ADAPTER *Adapter) -/* - * FUNCTION: Registers loopback adapter with the network layer - * ARGUMENTS: - * AdapterName = Unused - * Adapter = Unused - * RETURNS: - * Status of operation - */ -{ - PIP_ADDRESS Address; - NDIS_STATUS Status; - - Status = NDIS_STATUS_SUCCESS; - - TI_DbgPrint(MID_TRACE, ("Called.\n")); - - Address = AddrBuildIPv4(LOOPBACK_ADDRESS_IPv4); - if (Address != NULL) - { - LLIP_BIND_INFO BindInfo; - - /* Bind the adapter to network (IP) layer */ - BindInfo.Context = NULL; - BindInfo.HeaderSize = 0; - BindInfo.MinFrameSize = 0; - BindInfo.MTU = 16384; - BindInfo.Address = NULL; - BindInfo.AddressLength = 0; - BindInfo.Transmit = LoopTransmit; - - Loopback = IPCreateInterface(&BindInfo); - - if ((Loopback != NULL) && (IPCreateNTE(Loopback, Address, 8))) - { - /* Reference the interface for the NTE. The reference for - the address is just passed on to the NTE */ - ReferenceObject(Loopback); - - IPRegisterInterface(Loopback); - } - else - { - Status = NDIS_STATUS_RESOURCES; - } - } - else - { - Status = NDIS_STATUS_RESOURCES; - } - - if (!NT_SUCCESS(Status)) - { - LoopUnregisterAdapter(NULL); - } - - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); - - return Status; -} - - -NDIS_STATUS LoopUnregisterAdapter( - PLAN_ADAPTER Adapter) -/* - * FUNCTION: Unregisters loopback adapter with the network layer - * ARGUMENTS: - * Adapter = Unused - * RETURNS: - * Status of operation - * NOTES: - * Does not care wether we have registered loopback adapter - */ -{ - TI_DbgPrint(MID_TRACE, ("Called.\n")); - - if (Loopback != NULL) - { - IPUnregisterInterface(Loopback); - IPDestroyInterface(Loopback); - Loopback = NULL; - } - - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); - - return NDIS_STATUS_SUCCESS; -} diff --git a/reactos/drivers/net/tcpip/include/rawip.h b/reactos/drivers/net/tcpip/include/rawip.h index 26efd3d8b50..26b7a35398a 100644 --- a/reactos/drivers/net/tcpip/include/rawip.h +++ b/reactos/drivers/net/tcpip/include/rawip.h @@ -7,6 +7,8 @@ #ifndef __RAWIP_H #define __RAWIP_H + + NTSTATUS RawIPSendDatagram( PADDRESS_FILE AddrFile, PTDI_CONNECTION_INFORMATION ConnInfo, @@ -24,6 +26,17 @@ NTSTATUS RawIPStartup( NTSTATUS RawIPShutdown( VOID); +NTSTATUS AddGenericHeaderIPv4( + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET IPPacket, + UINT DataLength, + UINT Protocol, + UINT ExtraLength, + PVOID *NextHeader ); + #endif /* __RAWIP_H */ /* EOF */ diff --git a/reactos/drivers/net/tcpip/include/tcp.h b/reactos/drivers/net/tcpip/include/tcp.h index 08a0e4cdba1..8279db48685 100644 --- a/reactos/drivers/net/tcpip/include/tcp.h +++ b/reactos/drivers/net/tcpip/include/tcp.h @@ -164,6 +164,10 @@ UINT TCPAllocatePort( UINT HintPort ); VOID TCPFreePort( UINT Port ); +NTSTATUS TCPGetPeerAddress +( PCONNECTION_ENDPOINT Connection, + PTRANSPORT_ADDRESS TransportAddress ); + NTSTATUS TCPStartup( VOID); diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index c4450d66b17..378f2665c38 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -63,7 +63,7 @@ VOID DispCancelComplete( * Context = Pointer to context information (FILE_OBJECT) */ { - KIRQL OldIrql; + /*KIRQL OldIrql;*/ PFILE_OBJECT FileObject; PTRANSPORT_CONTEXT TranContext; @@ -76,80 +76,12 @@ VOID DispCancelComplete( KeSetEvent(&TranContext->CleanupEvent, 0, FALSE); /* We are expected to release the cancel spin lock */ - IoReleaseCancelSpinLock(OldIrql); + /*IoReleaseCancelSpinLock(OldIrql);*/ TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); } -VOID DDKAPI DispCancelRequest( - PDEVICE_OBJECT Device, - PIRP Irp) -/* - * FUNCTION: Cancels an IRP - * ARGUMENTS: - * Device = Pointer to device object - * Irp = Pointer to an I/O request packet - */ -{ - PIO_STACK_LOCATION IrpSp; - PTRANSPORT_CONTEXT TranContext; - PFILE_OBJECT FileObject; - UCHAR MinorFunction; - NTSTATUS Status = STATUS_SUCCESS; - - TI_DbgPrint(DEBUG_IRP, ("Called.\n")); - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - FileObject = IrpSp->FileObject; - TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; - MinorFunction = IrpSp->MinorFunction; - - TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp)); - -#ifdef DBG - if (!Irp->Cancel) - TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); -#endif - - IoReleaseCancelSpinLock(Irp->CancelIrql); - - /* Try canceling the request */ - switch(MinorFunction) { - case TDI_SEND: - case TDI_RECEIVE: - /* FIXME: Close connection */ - break; - - case TDI_SEND_DATAGRAM: - if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { - TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n")); - break; - } - - /*DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);*/ - break; - - case TDI_RECEIVE_DATAGRAM: - if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { - TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n")); - break; - } - - /*DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);*/ - break; - - default: - TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction)); - break; - } - - if (Status != STATUS_PENDING) - DispCancelComplete(FileObject); - - TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); -} - VOID DispDataRequestComplete( PVOID Context, NTSTATUS Status, @@ -204,6 +136,89 @@ VOID DispDataRequestComplete( } +VOID DDKAPI DispCancelRequest( + PDEVICE_OBJECT Device, + PIRP Irp) +/* + * FUNCTION: Cancels an IRP + * ARGUMENTS: + * Device = Pointer to device object + * Irp = Pointer to an I/O request packet + */ +{ + PIO_STACK_LOCATION IrpSp; + PTRANSPORT_CONTEXT TranContext; + PFILE_OBJECT FileObject; + UCHAR MinorFunction; + /*NTSTATUS Status = STATUS_SUCCESS;*/ + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + FileObject = IrpSp->FileObject; + TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; + MinorFunction = IrpSp->MinorFunction; + + TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp)); + +#ifdef DBG + if (!Irp->Cancel) + TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); +#endif + + /* Try canceling the request */ + switch(MinorFunction) { + case TDI_SEND: + TCPDisconnect + ( TranContext->Handle.ConnectionContext, + TDI_DISCONNECT_RELEASE, + NULL, + NULL, + DispDataRequestComplete, + Irp ); + break; + + case TDI_RECEIVE: + TCPDisconnect + ( TranContext->Handle.ConnectionContext, + TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE, + NULL, + NULL, + DispDataRequestComplete, + Irp ); + break; + + case TDI_SEND_DATAGRAM: + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { + TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n")); + break; + } + + /*DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);*/ + break; + + case TDI_RECEIVE_DATAGRAM: + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { + TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n")); + break; + } + + /*DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);*/ + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction)); + break; + } + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + DispCancelComplete(FileObject); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + NTSTATUS DispTdiAccept( PIRP Irp) /* @@ -580,7 +595,9 @@ NTSTATUS DispTdiQueryInformation( break; case TDI_CONNECTION_FILE: - AddrFile = ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->AddressFile; + AddrFile = + ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)-> + AddressFile; break; default: @@ -605,13 +622,53 @@ NTSTATUS DispTdiQueryInformation( Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; Address->Address[0].Address[0].sin_port = AddrFile->Port; - Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address; + Address->Address[0].Address[0].in_addr = + AddrFile->Address.Address.IPv4Address; RtlZeroMemory( &Address->Address[0].Address[0].sin_zero, sizeof(Address->Address[0].Address[0].sin_zero)); return STATUS_SUCCESS; } + + case TDI_QUERY_CONNECTION_INFO: + { + PTDI_CONNECTION_INFORMATION AddressInfo; + PADDRESS_FILE AddrFile; + PCONNECTION_ENDPOINT Endpoint = NULL; + + AddressInfo = (PTDI_CONNECTION_INFORMATION) + MmGetSystemAddressForMdl(Irp->MdlAddress); + + switch ((ULONG)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; + break; + + case TDI_CONNECTION_FILE: + Endpoint = + (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); + return STATUS_INVALID_PARAMETER; + } + + if (!Endpoint) { + TI_DbgPrint(MID_TRACE, ("No connection object.\n")); + return STATUS_INVALID_PARAMETER; + } + + if (MmGetMdlByteCount(Irp->MdlAddress) < + (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) + + sizeof(PVOID))) { + TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n")); + return STATUS_BUFFER_OVERFLOW; + } + + return TCPGetPeerAddress( Endpoint, AddressInfo->RemoteAddress ); + } } return STATUS_NOT_IMPLEMENTED; @@ -867,12 +924,15 @@ NTSTATUS DispTdiSendDatagram( ("About to call send routine %x\n", (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); - Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( - Request.Handle.AddressHandle, - DgramInfo->SendDatagramInformation, - DataBuffer, - BufferSize, - &Irp->IoStatus.Information); + if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send) ) + Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( + Request.Handle.AddressHandle, + DgramInfo->SendDatagramInformation, + DataBuffer, + BufferSize, + &Irp->IoStatus.Information); + else + Status = STATUS_UNSUCCESSFUL; if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); diff --git a/reactos/drivers/net/tcpip/tcpip/fileobjs.c b/reactos/drivers/net/tcpip/tcpip/fileobjs.c index f219bf3631b..77a623ff00b 100644 --- a/reactos/drivers/net/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/net/tcpip/tcpip/fileobjs.c @@ -43,6 +43,20 @@ PADDRESS_FILE AddrSearchFirst( return AddrSearchNext(SearchContext); } +BOOLEAN AddrIsBroadcast( + PIP_ADDRESS PossibleMatch, + PIP_ADDRESS TargetAddress ) { + IF_LIST_ITER(IF); + + ForEachInterface(IF) { + if( AddrIsEqual( &IF->Unicast, PossibleMatch ) && + AddrIsEqual( &IF->Broadcast, TargetAddress ) ) + return TRUE; + } EndFor(IF); + + return FALSE; +} + /* * FUNCTION: Searches through address file entries to find next match * ARGUMENTS: @@ -80,10 +94,11 @@ PADDRESS_FILE AddrSearchNext( A2S(SearchContext->Address))); /* See if this address matches the search criteria */ - if (((Current->Port == SearchContext->Port) && + if ((Current->Port == SearchContext->Port) && (Current->Protocol == SearchContext->Protocol) && - (AddrIsEqual(IPAddress, SearchContext->Address))) || - (AddrIsUnspecified(IPAddress))) { + (AddrIsEqual(IPAddress, SearchContext->Address) || + AddrIsBroadcast(IPAddress, SearchContext->Address) || + AddrIsUnspecified(IPAddress))) { /* We've found a match */ Found = TRUE; break; @@ -268,16 +283,18 @@ NTSTATUS FileOpenAddress( /* Protocol specific handling */ switch (Protocol) { case IPPROTO_TCP: - /* FIXME: If specified port is 0, a port is chosen dynamically */ - AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port); - AddrFile->Send = NULL; /* TCPSendData */ - break; + AddrFile->Port = + TCPAllocatePort(Address->Address[0].Address[0].sin_port); + AddrFile->Send = NULL; /* TCPSendData */ + break; case IPPROTO_UDP: TI_DbgPrint(MID_TRACE,("Allocating udp port\n")); AddrFile->Port = UDPAllocatePort(Address->Address[0].Address[0].sin_port); - TI_DbgPrint(MID_TRACE,("Setting port %d\n", AddrFile->Port)); + TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n", + AddrFile->Port, + Address->Address[0].Address[0].sin_port)); AddrFile->Send = UDPSendDatagram; break; diff --git a/reactos/drivers/net/tcpip/tcpip/info.c b/reactos/drivers/net/tcpip/tcpip/info.c index fa009f61ba7..42f042ee292 100644 --- a/reactos/drivers/net/tcpip/tcpip/info.c +++ b/reactos/drivers/net/tcpip/tcpip/info.c @@ -129,10 +129,10 @@ TDI_STATUS InfoTdiQueryInformationEx( { KIRQL OldIrql; UINT i; - PVOID context; + PVOID context = NULL; NTSTATUS Status = STATUS_SUCCESS; BOOL FoundEntity = FALSE; - InfoRequest_f InfoRequest; + InfoRequest_f InfoRequest = NULL; TI_DbgPrint(MAX_TRACE, ("InfoEx Req: %x %x %x!%04x:%d\n", diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index 9853b02ccfa..21aa80e9894 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -9,10 +9,10 @@ */ #include "precomp.h" -//#define NDEBUG +#define NDEBUG #ifndef NDEBUG -DWORD DebugTraceLevel = MAX_TRACE | DEBUG_TCP; +DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER); #else DWORD DebugTraceLevel = 0; #endif /* NDEBUG */ diff --git a/reactos/drivers/net/tcpip/tcpip/ninfo.c b/reactos/drivers/net/tcpip/tcpip/ninfo.c index 7fab2c17bc7..85409b37694 100644 --- a/reactos/drivers/net/tcpip/tcpip/ninfo.c +++ b/reactos/drivers/net/tcpip/tcpip/ninfo.c @@ -121,7 +121,7 @@ TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) { EntityList[RtCurrent->Index - 1].context; RtCurrent->Index-- ); - RtCurrent->Index = EntityList[RtCurrent->Index].tei_instance; + RtCurrent->Index = EntityList[RtCurrent->Index - 1].tei_instance; TcpipReleaseSpinLock(&EntityListLock, OldIrql); RtCurrent++; RCacheCur++; diff --git a/reactos/drivers/storage/cdrom/cdrom.c b/reactos/drivers/storage/cdrom/cdrom.c index e849a749a08..2a41355a2b0 100644 --- a/reactos/drivers/storage/cdrom/cdrom.c +++ b/reactos/drivers/storage/cdrom/cdrom.c @@ -134,6 +134,10 @@ VOID STDCALL CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context); +VOID +CdromWorkItem(IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context); + /* FUNCTIONS ****************************************************************/ @@ -1203,7 +1207,10 @@ CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject, Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; /* FIXME: Update drive capacity */ - + IoCompleteRequest (Irp, + IO_DISK_INCREMENT); + IoStartNextPacket (DeviceObject, + FALSE); return; } } @@ -1614,11 +1621,68 @@ CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject, VOID STDCALL -CdromTimerRoutine(PDEVICE_OBJECT DeviceObject, - PVOID Context) +CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) { - DPRINT ("CdromTimerRoutine() called\n"); + PIO_WORKITEM WorkItem; + DPRINT ("CdromTimerRoutine() called\n"); + WorkItem = IoAllocateWorkItem(DeviceObject); + if (!WorkItem) + { + return; + } + + IoQueueWorkItem(WorkItem, + CdromWorkItem, + DelayedWorkQueue, + WorkItem); +} + + +VOID +CdromWorkItem(IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + PIRP Irp; + KEVENT Event; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + DPRINT("CdromWorkItem() called\n"); + + IoFreeWorkItem((PIO_WORKITEM) Context); + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_CHECK_VERIFY, + DeviceObject, + NULL, + 0, + NULL, + 0, + FALSE, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest failed\n"); + return; + } + + Status = IoCallDriver(DeviceObject, Irp); + DPRINT("Status: %x\n", Status); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + } } /* EOF */ diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index 81561dbc908..a76ce6532eb 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -1026,6 +1026,46 @@ ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject, } +/* + * Implements part of the directives on: + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/other_c694d732-fa95-4841-8d61-2a55ee787905.xml.asp + */ +static VOID +ScsiClassInvalidateMedia(IN PDEVICE_OBJECT DeviceObject, + OUT NTSTATUS *Status) +{ + PDEVICE_EXTENSION DeviceExtension; + PDEVICE_EXTENSION PhysicalExtension; + + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + PhysicalExtension = (PDEVICE_EXTENSION)DeviceExtension->PhysicalDevice->DeviceExtension; + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + DPRINT("Invalidate: test char yields TRUE\n"); + } + else + { + DPRINT("Invalidate: test char yields FALSE\n"); + } + + if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) && + (DeviceObject->Vpb->Flags & VPB_MOUNTED)) + { + DPRINT("Set DO_VERIFY_VOLUME\n"); + DeviceObject->Flags |= DO_VERIFY_VOLUME; + *Status = STATUS_VERIFY_REQUIRED; + } + else + { + *Status = STATUS_IO_DEVICE_ERROR; + } + + /* Increment the media change count */ + PhysicalExtension->MediaChangeCount++; +} + + /* * @implemented */ @@ -1106,9 +1146,12 @@ ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject, case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE: DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n"); - *Status = STATUS_NO_MEDIA_IN_DEVICE; + ScsiClassInvalidateMedia(DeviceObject, + Status); + + *Status = STATUS_NO_MEDIA_IN_DEVICE; Retry = FALSE; - + if((DeviceExtension->MediaChangeEvent != NULL) && (!DeviceExtension->MediaChangeEvent)) { @@ -1200,22 +1243,9 @@ ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject, break; } - if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) && - (DeviceObject->Vpb->Flags & VPB_MOUNTED)) - { - DPRINT("SCSI_SENSE_UNIT_ATTENTION set DoVerifyVol\n"); - - DeviceObject->Flags |= DO_VERIFY_VOLUME; - *Status = STATUS_VERIFY_REQUIRED; - Retry = FALSE; - } - else - { - *Status = STATUS_IO_DEVICE_ERROR; - } - - /* Increment the media change count */ - PhysicalExtension->MediaChangeCount++; + ScsiClassInvalidateMedia(DeviceObject, + Status); + Retry = FALSE; break; case SCSI_SENSE_DATA_PROTECT: diff --git a/reactos/drivers/storage/disk/disk.c b/reactos/drivers/storage/disk/disk.c index e2910de8862..2d68cf862a0 100644 --- a/reactos/drivers/storage/disk/disk.c +++ b/reactos/drivers/storage/disk/disk.c @@ -390,6 +390,8 @@ DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, { PDEVICE_EXTENSION DeviceExtension; PDISK_DATA DiskData; + PIO_STACK_LOCATION IrpStack; + ULARGE_INTEGER EndingOffset; DPRINT("DiskClassCheckReadWrite() called\n"); @@ -404,6 +406,16 @@ DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, return(STATUS_INVALID_PARAMETER); } + IrpStack = IoGetCurrentIrpStackLocation(Irp); + EndingOffset.QuadPart = IrpStack->Parameters.Read.ByteOffset.QuadPart + + IrpStack->Parameters.Read.Length; + + if (EndingOffset.QuadPart > DeviceExtension->PartitionLength.QuadPart) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + return(STATUS_INVALID_PARAMETER); + } + return(STATUS_SUCCESS); } diff --git a/reactos/drivers/usb/Makefile b/reactos/drivers/usb/Makefile new file mode 100644 index 00000000000..d389c4503d3 --- /dev/null +++ b/reactos/drivers/usb/Makefile @@ -0,0 +1,50 @@ +# +# ReactOS USB Drivers +# + +PATH_TO_TOP = ../.. + +include $(PATH_TO_TOP)/rules.mak + +DRIVERS = usbport miniport/usbuhci miniport/usbehci miniport/usbohci usbhub usbd + +all: $(DRIVERS) + +depends: + +implib: $(DRIVERS:%=%_implib) + +clean: $(DRIVERS:%=%_clean) + +install: $(DRIVERS:%=%_install) + +bootcd: $(DRIVERS:%=%_bootcd) + +.PHONY: all depends implib clean install bootcd + + +# +# USB DRIVERS +# +$(DRIVERS): %: + $(MAKE) -C $* + +$(DRIVERS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(DRIVERS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(DRIVERS:%=%_install): %_install: + $(MAKE) -C $* install + +$(DRIVERS:%=%_bootcd): %_bootcd: + $(MAKE) -C $* bootcd + +.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd) + + +etags: + find . -name "*.[ch]" -print | etags --language=c - + +# EOF diff --git a/reactos/drivers/usb/cromwell/Makefile b/reactos/drivers/usb/cromwell/Makefile new file mode 100644 index 00000000000..b38e31bc053 --- /dev/null +++ b/reactos/drivers/usb/cromwell/Makefile @@ -0,0 +1,50 @@ +# +# ReactOS USB-Cromwell Drivers +# + +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +DRIVERS = core host + +all: $(DRIVERS) + +depends: + +implib: $(DRIVERS:%=%_implib) + +clean: $(DRIVERS:%=%_clean) + +install: $(DRIVERS:%=%_install) + +bootcd: $(DRIVERS:%=%_bootcd) + +.PHONY: all depends implib clean install bootcd + + +# +# USB DRIVERS +# +$(DRIVERS): %: + $(MAKE) -C $* + +$(DRIVERS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(DRIVERS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(DRIVERS:%=%_install): %_install: + $(MAKE) -C $* install + +$(DRIVERS:%=%_bootcd): %_bootcd: + $(MAKE) -C $* bootcd + +.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd) + + +etags: + find . -name "*.[ch]" -print | etags --language=c - + +# EOF diff --git a/reactos/drivers/usb/cromwell/core/buffer_simple.c b/reactos/drivers/usb/cromwell/core/buffer_simple.c new file mode 100644 index 00000000000..7ac70ce30cb --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/buffer_simple.c @@ -0,0 +1,42 @@ +/* + * buffer_simple.c -- replacement for usb/core/buffer.c + * + * (c) Georg Acher, georg@acher.org + * + */ + +#include "../usb_wrapper.h" +#define __KERNEL__ +#define CONFIG_PCI +#include "hcd.h" + +/*------------------------------------------------------------------------*/ +int hcd_buffer_create (struct usb_hcd *hcd) +{ + return 0; +} +/*------------------------------------------------------------------------*/ +void hcd_buffer_destroy (struct usb_hcd *hcd) +{ +} +/*------------------------------------------------------------------------*/ +void *hcd_buffer_alloc ( + struct usb_bus *bus, + size_t size, + int mem_flags, + dma_addr_t *dma +) +{ + return kmalloc(size,0); +} +/*------------------------------------------------------------------------*/ +void hcd_buffer_free ( + struct usb_bus *bus, + size_t size, + void *addr, + dma_addr_t dma +) +{ + kfree(addr); +} + diff --git a/reactos/drivers/usb/cromwell/core/config.c b/reactos/drivers/usb/cromwell/core/config.c new file mode 100644 index 00000000000..7d400e982d8 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/config.c @@ -0,0 +1,508 @@ +#if 0 +#include +#include +#include +#include +#include +#else +#include "../usb_wrapper.h" +#endif + +#define USB_MAXALTSETTING 128 /* Hard limit */ +#define USB_MAXENDPOINTS 30 /* Hard limit */ + +/* these maximums are arbitrary */ +#define USB_MAXCONFIG 8 +#define USB_ALTSETTINGALLOC 4 +#define USB_MAXINTERFACES 32 + +static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char *buffer, int size) +{ + struct usb_descriptor_header *header; + unsigned char *begin; + int parsed = 0, len, numskipped; + + header = (struct usb_descriptor_header *)buffer; + + /* Everything should be fine being passed into here, but we sanity */ + /* check JIC */ + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + if (header->bDescriptorType != USB_DT_ENDPOINT) { + warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X", + header->bDescriptorType, USB_DT_ENDPOINT); + return parsed; + } + + if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) + memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); + else + memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE); + + le16_to_cpus(&endpoint->desc.wMaxPacketSize); + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + + /* Skip over the rest of the Class Specific or Vendor Specific */ + /* descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", + header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for drivers */ + /* to later parse */ + len = (int)(buffer - begin); + if (!len) { + endpoint->extra = NULL; + endpoint->extralen = 0; + return parsed; + } + + endpoint->extra = kmalloc(len, GFP_KERNEL); + + if (!endpoint->extra) { + err("couldn't allocate memory for endpoint extra descriptors"); + endpoint->extralen = 0; + return parsed; + } + + memcpy(endpoint->extra, begin, len); + endpoint->extralen = len; + + return parsed; +} + +static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) +{ + int i, len, numskipped, retval, parsed = 0; + struct usb_descriptor_header *header; + struct usb_host_interface *ifp; + unsigned char *begin; + + interface->act_altsetting = 0; + interface->num_altsetting = 0; + interface->max_altsetting = USB_ALTSETTINGALLOC; + device_initialize(&interface->dev); + + interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, + GFP_KERNEL); + + if (!interface->altsetting) { + err("couldn't kmalloc interface->altsetting"); + return -1; + } + + while (size > 0) { + struct usb_interface_descriptor *d; + + if (interface->num_altsetting >= interface->max_altsetting) { + struct usb_host_interface *ptr; + int oldmas; + + oldmas = interface->max_altsetting; + interface->max_altsetting += USB_ALTSETTINGALLOC; + if (interface->max_altsetting > USB_MAXALTSETTING) { + warn("too many alternate settings (incr %d max %d)\n", + USB_ALTSETTINGALLOC, USB_MAXALTSETTING); + return -1; + } + + ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); + if (ptr == NULL) { + err("couldn't kmalloc interface->altsetting"); + return -1; + } + memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); + kfree(interface->altsetting); + interface->altsetting = ptr; + } + + ifp = interface->altsetting + interface->num_altsetting; + ifp->endpoint = NULL; + ifp->extra = NULL; + ifp->extralen = 0; + interface->num_altsetting++; + + memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); + + /* Skip over the interface */ + buffer += ifp->desc.bLength; + parsed += ifp->desc.bLength; + size -= ifp->desc.bLength; + + begin = buffer; + numskipped = 0; + + /* Skip over any interface, class or vendor descriptors */ + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + numskipped++; + + buffer += header->bLength; + parsed += header->bLength; + size -= header->bLength; + } + + if (numskipped) + dbg("skipped %d class/vendor specific interface descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + ifp->extra = kmalloc(len, GFP_KERNEL); + + if (!ifp->extra) { + err("couldn't allocate memory for interface extra descriptors"); + ifp->extralen = 0; + return -1; + } + memcpy(ifp->extra, begin, len); + ifp->extralen = len; + } + + /* Did we hit an unexpected descriptor? */ + header = (struct usb_descriptor_header *)buffer; + if ((size >= sizeof(struct usb_descriptor_header)) && + ((header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE))) + return parsed; + + if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) { + warn("too many endpoints"); + return -1; + } + + ifp->endpoint = (struct usb_host_endpoint *) + kmalloc(ifp->desc.bNumEndpoints * + sizeof(struct usb_host_endpoint), GFP_KERNEL); + if (!ifp->endpoint) { + err("out of memory"); + return -1; + } + + memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints * + sizeof(struct usb_host_endpoint)); + + for (i = 0; i < ifp->desc.bNumEndpoints; i++) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + parsed += retval; + size -= retval; + } + + /* We check to see if it's an alternate to this one */ + d = (struct usb_interface_descriptor *)buffer; + if (size < USB_DT_INTERFACE_SIZE + || d->bDescriptorType != USB_DT_INTERFACE + || !d->bAlternateSetting) + return parsed; + } + + return parsed; +} + +int usb_parse_configuration(struct usb_host_config *config, char *buffer) +{ + int i, retval, size; + struct usb_descriptor_header *header; + + memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); + le16_to_cpus(&config->desc.wTotalLength); + size = config->desc.wTotalLength; + + if (config->desc.bNumInterfaces > USB_MAXINTERFACES) { + warn("too many interfaces"); + return -1; + } + + config->interface = (struct usb_interface *) + kmalloc(config->desc.bNumInterfaces * + sizeof(struct usb_interface), GFP_KERNEL); + dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces); + if (!config->interface) { + err("out of memory"); + return -1; + } + + memset(config->interface, 0, + config->desc.bNumInterfaces * sizeof(struct usb_interface)); + + buffer += config->desc.bLength; + size -= config->desc.bLength; + + config->extra = NULL; + config->extralen = 0; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + int numskipped, len; + char *begin; + + /* Skip over the rest of the Class Specific or Vendor */ + /* Specific descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if ((header->bLength > size) || (header->bLength < 2)) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + if (config->extralen) { + warn("extra config descriptor"); + } else { + config->extra = kmalloc(len, GFP_KERNEL); + if (!config->extra) { + err("couldn't allocate memory for config extra descriptors"); + config->extralen = 0; + return -1; + } + + memcpy(config->extra, begin, len); + config->extralen = len; + } + } + + retval = usb_parse_interface(config->interface + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + size -= retval; + } + + return size; +} + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally on disconnect/destroy path +void usb_destroy_configuration(struct usb_device *dev) +{ + int c, i, j, k; + + if (!dev->config) + return; + + if (dev->rawdescriptors) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + kfree(dev->rawdescriptors[i]); + + kfree(dev->rawdescriptors); + } + + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + struct usb_host_config *cf = &dev->config[c]; + + if (!cf->interface) + break; + + for (i = 0; i < cf->desc.bNumInterfaces; i++) { + struct usb_interface *ifp = + &cf->interface[i]; + + if (!ifp->altsetting) + break; + + for (j = 0; j < ifp->num_altsetting; j++) { + struct usb_host_interface *as = + &ifp->altsetting[j]; + + if(as->extra) { + kfree(as->extra); + } + + if (!as->endpoint) + break; + + for(k = 0; k < as->desc.bNumEndpoints; k++) { + if(as->endpoint[k].extra) { + kfree(as->endpoint[k].extra); + } + } + kfree(as->endpoint); + } + + kfree(ifp->altsetting); + } + kfree(cf->interface); + } + kfree(dev->config); +} + + +// hub-only!! ... and only in reset path, or usb_new_device() +// (used by real hubs and virtual root hubs) +int usb_get_configuration(struct usb_device *dev) +{ + int result; + unsigned int cfgno, length; + unsigned char *buffer; + unsigned char *bigbuffer; + struct usb_config_descriptor *desc; + + if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { + warn("too many configurations"); + return -EINVAL; + } + + if (dev->descriptor.bNumConfigurations < 1) { + warn("not enough configurations"); + return -EINVAL; + } + + dev->config = (struct usb_host_config *) + kmalloc(dev->descriptor.bNumConfigurations * + sizeof(struct usb_host_config), GFP_KERNEL); + if (!dev->config) { + err("out of memory"); + return -ENOMEM; + } + memset(dev->config, 0, dev->descriptor.bNumConfigurations * + sizeof(struct usb_host_config)); + + dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * + dev->descriptor.bNumConfigurations, GFP_KERNEL); + if (!dev->rawdescriptors) { + err("out of memory"); + return -ENOMEM; + } + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return -ENOMEM; + } + desc = (struct usb_config_descriptor *)buffer; + + for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { + /* We grab the first 8 bytes so we know how long the whole */ + /* configuration is */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); + if (result < 8) { + if (result < 0) + err("unable to get descriptor"); + else { + err("config descriptor too short (expected %i, got %i)", 8, result); + result = -EINVAL; + } + goto err; + } + + /* Get the full buffer */ + length = le16_to_cpu(desc->wTotalLength); + + bigbuffer = kmalloc(length, GFP_KERNEL); + if (!bigbuffer) { + err("unable to allocate memory for configuration descriptors"); + result = -ENOMEM; + goto err; + } + + /* Now that we know the length, get the whole thing */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); + if (result < 0) { + err("couldn't get all of config descriptors"); + kfree(bigbuffer); + goto err; + } + + if (result < length) { + err("config descriptor too short (expected %i, got %i)", length, result); + result = -EINVAL; + kfree(bigbuffer); + goto err; + } + + dev->rawdescriptors[cfgno] = bigbuffer; + + result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); + if (result > 0) + dbg("descriptor data left"); + else if (result < 0) { + result = -EINVAL; + goto err; + } + } + + kfree(buffer); + return 0; +err: + kfree(buffer); + dev->descriptor.bNumConfigurations = cfgno; + return result; +} + diff --git a/reactos/drivers/usb/cromwell/core/hcd-pci.c b/reactos/drivers/usb/cromwell/core/hcd-pci.c new file mode 100644 index 00000000000..ca7182c0b2a --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/hcd-pci.c @@ -0,0 +1,365 @@ +/* + * (C) Copyright David Brownell 2000-2002 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if 0 +#include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include "hcd.h" +#else +#define DEBUG +#include "../usb_wrapper.h" +#include "hcd.h" +#endif + + +/* PCI-based HCs are normal, but custom bus glue should be ok */ + + +/*-------------------------------------------------------------------------*/ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_hcd_pci_probe - initialize PCI-based HCDs + * @dev: USB Host Controller being probed + * @id: pci hotplug id connecting controller to HCD framework + * Context: !in_interrupt() + * + * Allocates basic PCI resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + * Store this function in the HCD's struct pci_driver as probe(). + */ +int STDCALL usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + struct hc_driver *driver; + unsigned long resource, len; + void *base; + struct usb_hcd *hcd; + int retval, region; + char buf [8]; + //char *bufp = buf; + + if (usb_disabled()) + return -ENODEV; + + if (!id || !(driver = (struct hc_driver *) id->driver_data)) + return -EINVAL; + + if (pci_enable_device (dev) < 0) + return -ENODEV; + + if (!dev->irq) { + err ("Found HC with no IRQ. Check BIOS/PCI %s setup!", + dev->slot_name); + return -ENODEV; + } + + if (driver->flags & HCD_MEMORY) { // EHCI, OHCI + region = 0; + resource = pci_resource_start (dev, 0); + len = pci_resource_len (dev, 0); + if (!request_mem_region (resource, len, driver->description)) { + dbg ("controller already in use"); + return -EBUSY; + } + base = ioremap_nocache (resource, len); + if (base == NULL) { + dbg ("error mapping memory"); + retval = -EFAULT; +clean_1: + release_mem_region (resource, len); + err ("init %s fail, %d", dev->slot_name, retval); + return retval; + } + + } else { // UHCI + resource = len = 0; + for (region = 0; region < PCI_ROM_RESOURCE; region++) { + if (!(pci_resource_flags (dev, region) & IORESOURCE_IO)) + continue; + + resource = pci_resource_start (dev, region); + len = pci_resource_len (dev, region); + if (request_region (resource, len, + driver->description)) + break; + } + if (region == PCI_ROM_RESOURCE) { + dbg ("no i/o regions available"); + return -EBUSY; + } + base = (void *) resource; + } + + // driver->start(), later on, will transfer device from + // control by SMM/BIOS to control by Linux (if needed) + + pci_set_master (dev); + + hcd = driver->hcd_alloc (); + if (hcd == NULL){ + dbg ("hcd alloc fail"); + retval = -ENOMEM; +clean_2: + if (driver->flags & HCD_MEMORY) { + iounmap (base); + goto clean_1; + } else { + release_region (resource, len); + err ("init %s fail, %d", dev->slot_name, retval); + return retval; + } + } + pci_set_drvdata (dev, hcd); + hcd->driver = driver; + hcd->description = driver->description; + hcd->pdev = dev; + hcd->self.bus_name = dev->slot_name; + hcd->product_desc = dev->dev.name; + hcd->self.controller = &dev->dev; + hcd->controller = hcd->self.controller; + + if ((retval = hcd_buffer_create (hcd)) != 0) { +clean_3: + driver->hcd_free (hcd); + goto clean_2; + } + + dev_info (hcd->controller, "%s\n", hcd->product_desc); + +#ifndef __sparc__ + sprintf (buf, "%d", dev->irq); +#else + bufp = __irq_itoa(dev->irq); +#endif + if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd) + != 0) { + dev_err (hcd->controller, + "request interrupt %s failed\n", bufp); + retval = -EBUSY; + goto clean_3; + } + hcd->irq = dev->irq; + + hcd->regs = base; + hcd->region = region; + dev_info (hcd->controller, "irq %s, %s %p\n", bufp, + (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", + base); + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.hcpriv = (void *) hcd; + + INIT_LIST_HEAD (&hcd->dev_list); + + usb_register_bus (&hcd->self); + + if ((retval = driver->start (hcd)) < 0) + usb_hcd_pci_remove (dev); + + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_probe); + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_pci_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + * Store this function in the HCD's struct pci_driver as remove(). + */ +void STDCALL usb_hcd_pci_remove (struct pci_dev *dev) +{ + struct usb_hcd *hcd; + struct usb_device *hub; + + hcd = pci_get_drvdata(dev); + if (!hcd) + return; + dev_info (hcd->controller, "remove, state %x\n", hcd->state); + + if (in_interrupt ()) + BUG (); + + hub = hcd->self.root_hub; + hcd->state = USB_STATE_QUIESCING; + + dev_dbg (hcd->controller, "roothub graceful disconnect\n"); + usb_disconnect (&hub); + + hcd->driver->stop (hcd); + hcd_buffer_destroy (hcd); + hcd->state = USB_STATE_HALT; + pci_set_drvdata (dev, 0); + + free_irq (hcd->irq, hcd); + if (hcd->driver->flags & HCD_MEMORY) { + iounmap (hcd->regs); + release_mem_region (pci_resource_start (dev, 0), + pci_resource_len (dev, 0)); + } else { + release_region (pci_resource_start (dev, hcd->region), + pci_resource_len (dev, hcd->region)); + } + + usb_deregister_bus (&hcd->self); + if (atomic_read (&hcd->self.refcnt) != 1) { + dev_warn (hcd->controller, + "dangling refs (%d) to bus %d!\n", + atomic_read (&hcd->self.refcnt) - 1, + hcd->self.busnum); + } + hcd->driver->hcd_free (hcd); +} +EXPORT_SYMBOL (usb_hcd_pci_remove); + + +#ifdef CONFIG_PM + +/* + * Some "sleep" power levels imply updating struct usb_driver + * to include a callback asking hcds to do their bit by checking + * if all the drivers can suspend. Gets involved with remote wakeup. + * + * If there are pending urbs, then HCs will need to access memory, + * causing extra power drain. New sleep()/wakeup() PM calls might + * be needed, beyond PCI suspend()/resume(). The root hub timer + * still be accessing memory though ... + * + * FIXME: USB should have some power budgeting support working with + * all kinds of hubs. + * + * FIXME: This assumes only D0->D3 suspend and D3->D0 resume. + * D1 and D2 states should do something, yes? + * + * FIXME: Should provide generic enable_wake(), calling pci_enable_wake() + * for all supported states, so that USB remote wakeup can work for any + * devices that support it (and are connected via powered hubs). + * + * FIXME: resume doesn't seem to work right any more... + */ + + +// 2.4 kernels have issued concurrent resumes (w/APM) +// we defend against that error; PCI doesn't yet. + +/** + * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD + * @dev: USB Host Controller being suspended + * + * Store this function in the HCD's struct pci_driver as suspend(). + */ +int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) +{ + struct usb_hcd *hcd; + int retval; + + hcd = pci_get_drvdata(dev); + dev_info (hcd->controller, "suspend to state %d\n", state); + + pci_save_state (dev, hcd->pci_state); + + // FIXME for all connected devices, leaf-to-root: + // driver->suspend() + // proposed "new 2.5 driver model" will automate that + + /* driver may want to disable DMA etc */ + retval = hcd->driver->suspend (hcd, state); + hcd->state = USB_STATE_SUSPENDED; + + pci_set_power_state (dev, state); + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_suspend); + +/** + * usb_hcd_pci_resume - power management resume of a PCI-based HCD + * @dev: USB Host Controller being resumed + * + * Store this function in the HCD's struct pci_driver as resume(). + */ +int usb_hcd_pci_resume (struct pci_dev *dev) +{ + struct usb_hcd *hcd; + int retval; + + hcd = pci_get_drvdata(dev); + dev_info (hcd->controller, "resume\n"); + + /* guard against multiple resumes (APM bug?) */ + atomic_inc (&hcd->resume_count); + if (atomic_read (&hcd->resume_count) != 1) { + dev_err (hcd->controller, "concurrent PCI resumes\n"); + retval = 0; + goto done; + } + + retval = -EBUSY; + if (hcd->state != USB_STATE_SUSPENDED) { + dev_dbg (hcd->controller, "can't resume, not suspended!\n"); + goto done; + } + hcd->state = USB_STATE_RESUMING; + + pci_set_power_state (dev, 0); + pci_restore_state (dev, hcd->pci_state); + + retval = hcd->driver->resume (hcd); + if (!HCD_IS_RUNNING (hcd->state)) { + dev_dbg (hcd->controller, "resume fail, retval %d\n", retval); + usb_hc_died (hcd); +// FIXME: recover, reset etc. + } else { + // FIXME for all connected devices, root-to-leaf: + // driver->resume (); + // proposed "new 2.5 driver model" will automate that + } + +done: + atomic_dec (&hcd->resume_count); + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_resume); + +#endif /* CONFIG_PM */ + + diff --git a/reactos/drivers/usb/cromwell/core/hcd.c b/reactos/drivers/usb/cromwell/core/hcd.c new file mode 100644 index 00000000000..a9efdf7a77f --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/hcd.c @@ -0,0 +1,1499 @@ +/* + * (C) Copyright Linus Torvalds 1999 + * (C) Copyright Johannes Erdfelt 1999-2001 + * (C) Copyright Andreas Gal 1999 + * (C) Copyright Gregory P. Smith 1999 + * (C) Copyright Deti Fliegl 1999 + * (C) Copyright Randy Dunlap 2000 + * (C) Copyright David Brownell 2000-2002 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if 0 +#include + +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include /* for UTS_SYSNAME */ +#include /* for hcd->pdev and dma addressing */ +#include +#include + +#include +#else +#include "../usb_wrapper.h" +//#define DEBUG +#endif + +#include "hcd.h" + +// #define USB_BANDWIDTH_MESSAGES + +/*-------------------------------------------------------------------------*/ + +/* + * USB Host Controller Driver framework + * + * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing + * HCD-specific behaviors/bugs. + * + * This does error checks, tracks devices and urbs, and delegates to a + * "hc_driver" only for code (and data) that really needs to know about + * hardware differences. That includes root hub registers, i/o queues, + * and so on ... but as little else as possible. + * + * Shared code includes most of the "root hub" code (these are emulated, + * though each HC's hardware works differently) and PCI glue, plus request + * tracking overhead. The HCD code should only block on spinlocks or on + * hardware handshaking; blocking on software events (such as other kernel + * threads releasing resources, or completing actions) is all generic. + * + * Happens the USB 2.0 spec says this would be invisible inside the "USBD", + * and includes mostly a "HCDI" (HCD Interface) along with some APIs used + * only by the hub driver ... and that neither should be seen or used by + * usb client device drivers. + * + * Contributors of ideas or unattributed patches include: David Brownell, + * Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ... + * + * HISTORY: + * 2002-02-21 Pull in most of the usb_bus support from usb.c; some + * associated cleanup. "usb_hcd" still != "usb_bus". + * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. + */ + +/*-------------------------------------------------------------------------*/ + +/* host controllers we manage */ +LIST_HEAD (usb_bus_list); +EXPORT_SYMBOL_GPL (usb_bus_list); + +/* used when allocating bus numbers */ +#define USB_MAXBUS 64 +struct usb_busmap { + unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))]; +}; +static struct usb_busmap busmap; + +/* used when updating list of hcds */ +DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ +EXPORT_SYMBOL_GPL (usb_bus_list_lock); + +/* used when updating hcd data */ +static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED; + +/*-------------------------------------------------------------------------*/ + +/* + * Sharable chunks of root hub code. + */ + +/*-------------------------------------------------------------------------*/ + +#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff) +#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff) + +/* usb 2.0 root hub device descriptor */ +static const u8 usb2_rh_dev_descriptor [18] = { + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, 0x02, /* __u16 bcdUSB; v2.0 */ + + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + + 0x00, 0x00, /* __u16 idVendor; */ + 0x00, 0x00, /* __u16 idProduct; */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + +/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */ + +/* usb 1.1 root hub device descriptor */ +static const u8 usb11_rh_dev_descriptor [18] = { + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, 0x01, /* __u16 bcdUSB; v1.1 */ + + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + + 0x00, 0x00, /* __u16 idVendor; */ + 0x00, 0x00, /* __u16 idProduct; */ + KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/*-------------------------------------------------------------------------*/ + +/* Configuration descriptors for our root hubs */ + +static const u8 fs_rh_config_descriptor [] = { + + /* one configuration */ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, 0x00, /* __u16 wTotalLength; */ + 0x01, /* __u8 bNumInterfaces; (1) */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, + 6: Self-powered, + 5 Remote-wakwup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* USB 1.1: + * USB 2.0, single TT organization (mandatory): + * one interface, protocol 0 + * + * USB 2.0, multiple TT organization (optional): + * two interfaces, protocols 1 (like single TT) + * and 2 (multiple TT mode) ... config is + * sometimes settable + * NOT IMPLEMENTED + */ + + /* one interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ + 0x00, /* __u8 if_iInterface; */ + + /* one endpoint (status change endpoint) */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + 0xff /* __u8 ep_bInterval; (255ms -- usb 2.0 spec) */ +}; + +static const u8 hs_rh_config_descriptor [] = { + + /* one configuration */ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, 0x00, /* __u16 wTotalLength; */ + 0x01, /* __u8 bNumInterfaces; (1) */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, + 6: Self-powered, + 5 Remote-wakwup, + 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* USB 1.1: + * USB 2.0, single TT organization (mandatory): + * one interface, protocol 0 + * + * USB 2.0, multiple TT organization (optional): + * two interfaces, protocols 1 (like single TT) + * and 2 (multiple TT mode) ... config is + * sometimes settable + * NOT IMPLEMENTED + */ + + /* one interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ + 0x00, /* __u8 if_iInterface; */ + + /* one endpoint (status change endpoint) */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ +}; + +/*-------------------------------------------------------------------------*/ + +/* + * helper routine for returning string descriptors in UTF-16LE + * input can actually be ISO-8859-1; ASCII is its 7-bit subset + */ +static int ascii2utf (char *s, u8 *utf, int utfmax) +{ + int retval; + + for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { + *utf++ = *s++; + *utf++ = 0; + } + return retval; +} + +/* + * rh_string - provides manufacturer, product and serial strings for root hub + * @id: the string ID number (1: serial number, 2: product, 3: vendor) + * @hcd: the host controller for this root hub + * @type: string describing our driver + * @data: return packet in UTF-16 LE + * @len: length of the return packet + * + * Produces either a manufacturer, product or serial number string for the + * virtual root hub device. + */ +static int rh_string ( + int id, + struct usb_hcd *hcd, + u8 *data, + int len +) { + char buf [100]; + + // language ids + if (id == 0) { + *data++ = 4; *data++ = 3; /* 4 bytes string data */ + *data++ = 0x09; *data++ = 0x04; /* MSFT-speak for "en-us" */ + return 4; + + // serial number + } else if (id == 1) { + strcpy (buf, hcd->self.bus_name); + + // product description + } else if (id == 2) { + strcpy (buf, hcd->product_desc); + + // id 3 == vendor description + } else if (id == 3) { + sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, + hcd->description); + + // unsupported IDs --> "protocol stall" + } else + return 0; + + data [0] = 2 * (strlen (buf) + 1); + data [1] = 3; /* type == string */ + return 2 + ascii2utf (buf, data + 2, len - 2); +} + + +/* Root hub control transfers execute synchronously */ +static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) +{ + struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; + u16 typeReq, wValue, wIndex, wLength; + const u8 *bufp = 0; + u8 *ubuf = urb->transfer_buffer; + int len = 0; + //unsigned long flags; + + typeReq = (cmd->bRequestType << 8) | cmd->bRequest; + wValue = le16_to_cpu (cmd->wValue); + wIndex = le16_to_cpu (cmd->wIndex); + wLength = le16_to_cpu (cmd->wLength); + + if (wLength > urb->transfer_buffer_length) + goto error; + + /* set up for success */ + urb->status = 0; + urb->actual_length = wLength; + switch (typeReq) { + + /* DEVICE REQUESTS */ + + case DeviceRequest | USB_REQ_GET_STATUS: + // DEVICE_REMOTE_WAKEUP + ubuf [0] = 1; // selfpowered + ubuf [1] = 0; + /* FALLTHROUGH */ + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: + case DeviceOutRequest | USB_REQ_SET_FEATURE: + dev_dbg (hcd->controller, "no device features yet yet\n"); + break; + case DeviceRequest | USB_REQ_GET_CONFIGURATION: + ubuf [0] = 1; + /* FALLTHROUGH */ + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: + break; + case DeviceRequest | USB_REQ_GET_DESCRIPTOR: + switch (wValue & 0xff00) { + case USB_DT_DEVICE << 8: + if (hcd->driver->flags & HCD_USB2) + bufp = usb2_rh_dev_descriptor; + else if (hcd->driver->flags & HCD_USB11) + bufp = usb11_rh_dev_descriptor; + else + goto error; + len = 18; + break; + case USB_DT_CONFIG << 8: + if (hcd->driver->flags & HCD_USB2) { + bufp = hs_rh_config_descriptor; + len = sizeof hs_rh_config_descriptor; + } else { + bufp = fs_rh_config_descriptor; + len = sizeof fs_rh_config_descriptor; + } + break; + case USB_DT_STRING << 8: + urb->actual_length = rh_string ( + wValue & 0xff, hcd, + ubuf, wLength); + break; + default: + goto error; + } + break; + case DeviceRequest | USB_REQ_GET_INTERFACE: + ubuf [0] = 0; + /* FALLTHROUGH */ + case DeviceOutRequest | USB_REQ_SET_INTERFACE: + break; + case DeviceOutRequest | USB_REQ_SET_ADDRESS: + // wValue == urb->dev->devaddr + dev_dbg (hcd->controller, "root hub device address %d\n", + wValue); + break; + + /* INTERFACE REQUESTS (no defined feature/status flags) */ + + /* ENDPOINT REQUESTS */ + + case EndpointRequest | USB_REQ_GET_STATUS: + // ENDPOINT_HALT flag + ubuf [0] = 0; + ubuf [1] = 0; + /* FALLTHROUGH */ + case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: + case EndpointOutRequest | USB_REQ_SET_FEATURE: + dev_dbg (hcd->controller, "no endpoint features yet\n"); + break; + + /* CLASS REQUESTS (and errors) */ + + default: + /* non-generic request */ + urb->status = hcd->driver->hub_control (hcd, + typeReq, wValue, wIndex, + ubuf, wLength); + break; +error: + /* "protocol stall" on error */ + urb->status = -EPIPE; + dev_dbg (hcd->controller, "unsupported hub control message (maxchild %d)\n", + urb->dev->maxchild); + } + if (urb->status) { + urb->actual_length = 0; + dev_dbg (hcd->controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n", + typeReq, wValue, wIndex, wLength, urb->status); + } + if (bufp) { + if (urb->transfer_buffer_length < len) + len = urb->transfer_buffer_length; + urb->actual_length = len; + // always USB_DIR_IN, toward host + memcpy (ubuf, bufp, len); + } + + /* any errors get returned through the urb completion */ + local_irq_save (flags); + usb_hcd_giveback_urb (hcd, urb, NULL); + local_irq_restore (flags); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* + * Root Hub interrupt transfers are synthesized with a timer. + * Completions are called in_interrupt() but not in_irq(). + */ + +static void rh_report_status (unsigned long ptr); + +static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) +{ + int len = 1 + (urb->dev->maxchild / 8); + + /* rh_timer protected by hcd_data_lock */ + if (hcd->rh_timer.data + || urb->status != -EINPROGRESS + || urb->transfer_buffer_length < len) { + dev_dbg (hcd->controller, + "not queuing rh status urb, stat %d\n", + urb->status); + return -EINVAL; + } + + init_timer (&hcd->rh_timer); + + hcd->rh_timer.function = rh_report_status; + hcd->rh_timer.data = (unsigned long) urb; + /* USB 2.0 spec says 256msec; this is close enough */ + hcd->rh_timer.expires = jiffies + HZ/4; + add_timer (&hcd->rh_timer); + urb->hcpriv = hcd; /* nonzero to indicate it's queued */ + return 0; +} + +/* timer callback */ + +static void rh_report_status (unsigned long ptr) +{ + struct urb *urb; + struct usb_hcd *hcd; + int length; + //unsigned long flags; + + urb = (struct urb *) ptr; + local_irq_save (flags); + spin_lock (&urb->lock); + + /* do nothing if the hc is gone or the urb's been unlinked */ + if (!urb->dev + || urb->status != -EINPROGRESS + || (hcd = urb->dev->bus->hcpriv) == 0 + || !HCD_IS_RUNNING (hcd->state)) { + spin_unlock (&urb->lock); + local_irq_restore (flags); + return; + } + + length = hcd->driver->hub_status_data (hcd, urb->transfer_buffer); + + /* complete the status urb, or retrigger the timer */ + spin_lock (&hcd_data_lock); + if (length > 0) { + hcd->rh_timer.data = 0; + urb->actual_length = length; + urb->status = 0; + urb->hcpriv = 0; + } else + mod_timer (&hcd->rh_timer, jiffies + HZ/4); + spin_unlock (&hcd_data_lock); + spin_unlock (&urb->lock); + + /* local irqs are always blocked in completions */ + if (length > 0) + usb_hcd_giveback_urb (hcd, urb, NULL); + local_irq_restore (flags); +} + +/*-------------------------------------------------------------------------*/ + +static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) +{ + if (usb_pipeint (urb->pipe)) { + int retval; + unsigned long flags; + + spin_lock_irqsave (&hcd_data_lock, flags); + retval = rh_status_urb (hcd, urb); + spin_unlock_irqrestore (&hcd_data_lock, flags); + return retval; + } + if (usb_pipecontrol (urb->pipe)) + return rh_call_control (hcd, urb); + else + return -EINVAL; +} + +/*-------------------------------------------------------------------------*/ + +void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) +{ + //unsigned long flags; + + /* note: always a synchronous unlink */ + del_timer_sync (&hcd->rh_timer); + hcd->rh_timer.data = 0; + + local_irq_save (flags); + urb->hcpriv = 0; + usb_hcd_giveback_urb (hcd, urb, NULL); + local_irq_restore (flags); +} + +/*-------------------------------------------------------------------------*/ + +/* exported only within usbcore */ +void usb_bus_get (struct usb_bus *bus) +{ + atomic_inc (&bus->refcnt); +} + +/* exported only within usbcore */ +void usb_bus_put (struct usb_bus *bus) +{ + if (atomic_dec_and_test (&bus->refcnt)) + kfree (bus); +} + +/*-------------------------------------------------------------------------*/ + +/** + * usb_bus_init - shared initialization code + * @bus: the bus structure being initialized + * + * This code is used to initialize a usb_bus structure, memory for which is + * separately managed. + */ +void STDCALL usb_bus_init (struct usb_bus *bus) +{ + memset (&bus->devmap, 0, sizeof(struct usb_devmap)); + + bus->devnum_next = 1; + + bus->root_hub = NULL; + bus->hcpriv = NULL; + bus->busnum = -1; + bus->bandwidth_allocated = 0; + bus->bandwidth_int_reqs = 0; + bus->bandwidth_isoc_reqs = 0; + + INIT_LIST_HEAD (&bus->bus_list); + + atomic_set (&bus->refcnt, 1); +} + +/** + * usb_alloc_bus - creates a new USB host controller structure + * @op: pointer to a struct usb_operations that this bus structure should use + * Context: !in_interrupt() + * + * Creates a USB host controller bus structure with the specified + * usb_operations and initializes all the necessary internal objects. + * + * If no memory is available, NULL is returned. + * + * The caller should call usb_free_bus() when it is finished with the structure. + */ +struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *op) +{ + struct usb_bus *bus; + + bus = kmalloc (sizeof *bus, GFP_KERNEL); + if (!bus) + return NULL; + usb_bus_init (bus); + bus->op = op; + return bus; +} + +/** + * usb_free_bus - frees the memory used by a bus structure + * @bus: pointer to the bus to free + * + * To be invoked by a HCD, only as the last step of decoupling from + * hardware. It is an error to call this if the reference count is + * anything but one. That would indicate that some system component + * did not correctly shut down, and thought the hardware was still + * accessible. + */ +void STDCALL usb_free_bus (struct usb_bus *bus) +{ + if (!bus) + return; + if (atomic_read (&bus->refcnt) != 1) + err ("usb_free_bus #%d, count != 1", bus->busnum); + usb_bus_put (bus); +} + +/*-------------------------------------------------------------------------*/ + +/** + * usb_register_bus - registers the USB host controller with the usb core + * @bus: pointer to the bus to register + * Context: !in_interrupt() + * + * Assigns a bus number, and links the controller into usbcore data + * structures so that it can be seen by scanning the bus list. + */ +void STDCALL usb_register_bus(struct usb_bus *bus) +{ + int busnum; + + down (&usb_bus_list_lock); + busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); + if (busnum < USB_MAXBUS) { + set_bit (busnum, busmap.busmap); + bus->busnum = busnum; + } else + warn ("too many buses"); + + usb_bus_get (bus); + + /* Add it to the list of buses */ + list_add (&bus->bus_list, &usb_bus_list); + up (&usb_bus_list_lock); + + usbfs_add_bus (bus); + + dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); +} + +/** + * usb_deregister_bus - deregisters the USB host controller + * @bus: pointer to the bus to deregister + * Context: !in_interrupt() + * + * Recycles the bus number, and unlinks the controller from usbcore data + * structures so that it won't be seen by scanning the bus list. + */ +void STDCALL usb_deregister_bus (struct usb_bus *bus) +{ + dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum); + + /* + * NOTE: make sure that all the devices are removed by the + * controller code, as well as having it call this when cleaning + * itself up + */ + down (&usb_bus_list_lock); + list_del (&bus->bus_list); + up (&usb_bus_list_lock); + + usbfs_remove_bus (bus); + + clear_bit (bus->busnum, busmap.busmap); + + usb_bus_put (bus); +} + +/** + * usb_register_root_hub - called by HCD to register its root hub + * @usb_dev: the usb root hub device to be registered. + * @parent_dev: the parent device of this root hub. + * + * The USB host controller calls this function to register the root hub + * properly with the USB subsystem. It sets up the device properly in + * the driverfs tree, and then calls usb_new_device() to register the + * usb device. + */ +int STDCALL usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) +{ + int retval; + + sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum); + usb_dev->state = USB_STATE_DEFAULT; + retval = usb_new_device (usb_dev, parent_dev); + if (retval) + dev_err (parent_dev, "can't register root hub for %s, %d\n", + usb_dev->dev.bus_id, retval); + return retval; +} + + +/*-------------------------------------------------------------------------*/ + +/** + * usb_calc_bus_time - approximate periodic transaction time in nanoseconds + * @speed: from dev->speed; USB_SPEED_{LOW,FULL,HIGH} + * @is_input: true iff the transaction sends data to the host + * @isoc: true for isochronous transactions, false for interrupt ones + * @bytecount: how many bytes in the transaction. + * + * Returns approximate bus time in nanoseconds for a periodic transaction. + * See USB 2.0 spec section 5.11.3; only periodic transfers need to be + * scheduled in software, this function is only used for such scheduling. + */ +long STDCALL usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) +{ + unsigned long tmp; + + switch (speed) { + case USB_SPEED_LOW: /* INTR only */ + if (is_input) { + tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } else { + tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); + } + case USB_SPEED_FULL: /* ISOC or INTR */ + if (isoc) { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); + } else { + tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; + return (9107L + BW_HOST_DELAY + tmp); + } + case USB_SPEED_HIGH: /* ISOC or INTR */ + // FIXME adjust for input vs output + if (isoc) + tmp = HS_USECS (bytecount); + else + tmp = HS_USECS_ISO (bytecount); + return tmp; + default: + dbg ("bogus device speed!"); + return -1; + } +} + +/* + * usb_check_bandwidth(): + * + * old_alloc is from host_controller->bandwidth_allocated in microseconds; + * bustime is from calc_bus_time(), but converted to microseconds. + * + * returns if successful, + * or -ENOSPC if bandwidth request fails. + * + * FIXME: + * This initial implementation does not use Endpoint.bInterval + * in managing bandwidth allocation. + * It probably needs to be expanded to use Endpoint.bInterval. + * This can be done as a later enhancement (correction). + * + * This will also probably require some kind of + * frame allocation tracking...meaning, for example, + * that if multiple drivers request interrupts every 10 USB frames, + * they don't all have to be allocated at + * frame numbers N, N+10, N+20, etc. Some of them could be at + * N+11, N+21, N+31, etc., and others at + * N+12, N+22, N+32, etc. + * + * Similarly for isochronous transfers... + * + * Individual HCDs can schedule more directly ... this logic + * is not correct for high speed transfers. + */ +int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb) +{ + unsigned int pipe = urb->pipe; + long bustime; + int is_in = usb_pipein (pipe); + int is_iso = usb_pipeisoc (pipe); + int old_alloc = dev->bus->bandwidth_allocated; + int new_alloc; + + + bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso, + usb_maxpacket (dev, pipe, !is_in))); + if (is_iso) + bustime /= urb->number_of_packets; + + new_alloc = old_alloc + (int) bustime; + if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) { +#ifdef DEBUG + char *mode = +#ifdef CONFIG_USB_BANDWIDTH + ""; +#else + "would have "; +#endif + dev_dbg (&dev->dev, "usb_check_bandwidth %sFAILED: %d + %ld = %d usec\n", + mode, old_alloc, bustime, new_alloc); +#endif +#ifdef CONFIG_USB_BANDWIDTH + bustime = -ENOSPC; /* report error */ +#endif + } + + return bustime; +} + + +/** + * usb_claim_bandwidth - records bandwidth for a periodic transfer + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @bustime: bandwidth consumed, in (average) microseconds per frame + * @isoc: true iff the request is isochronous + * + * Bus bandwidth reservations are recorded purely for diagnostic purposes. + * HCDs are expected not to overcommit periodic bandwidth, and to record such + * reservations whenever endpoints are added to the periodic schedule. + * + * FIXME averaging per-frame is suboptimal. Better to sum over the HCD's + * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable + * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how + * large its periodic schedule is. + */ +void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc) +{ + dev->bus->bandwidth_allocated += bustime; + if (isoc) + dev->bus->bandwidth_isoc_reqs++; + else + dev->bus->bandwidth_int_reqs++; + urb->bandwidth = bustime; + +#ifdef USB_BANDWIDTH_MESSAGES + dev_dbg (&dev->dev, "bandwidth alloc increased by %d (%s) to %d for %d requesters\n", + bustime, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif +} + + +/** + * usb_release_bandwidth - reverses effect of usb_claim_bandwidth() + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @isoc: true iff the request is isochronous + * + * This records that previously allocated bandwidth has been released. + * Bandwidth is released when endpoints are removed from the host controller's + * periodic schedule. + */ +void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc) +{ + dev->bus->bandwidth_allocated -= urb->bandwidth; + if (isoc) + dev->bus->bandwidth_isoc_reqs--; + else + dev->bus->bandwidth_int_reqs--; + +#ifdef USB_BANDWIDTH_MESSAGES + dev_dbg (&dev->dev, "bandwidth alloc reduced by %d (%s) to %d for %d requesters\n", + urb->bandwidth, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif + urb->bandwidth = 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * Generic HC operations. + */ + +/*-------------------------------------------------------------------------*/ + +/* called from khubd, or root hub init threads for hcd-private init */ +static int hcd_alloc_dev (struct usb_device *udev) +{ + struct hcd_dev *dev; + struct usb_hcd *hcd; + unsigned long flags; + + if (!udev || udev->hcpriv) + return -EINVAL; + if (!udev->bus || !udev->bus->hcpriv) + return -ENODEV; + hcd = udev->bus->hcpriv; + if (hcd->state == USB_STATE_QUIESCING) + return -ENOLINK; + + dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL); + if (dev == NULL) + return -ENOMEM; + memset (dev, 0, sizeof *dev); + + INIT_LIST_HEAD (&dev->dev_list); + INIT_LIST_HEAD (&dev->urb_list); + + spin_lock_irqsave (&hcd_data_lock, flags); + list_add (&dev->dev_list, &hcd->dev_list); + // refcount is implicit + udev->hcpriv = dev; + spin_unlock_irqrestore (&hcd_data_lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static void urb_unlink (struct urb *urb) +{ + unsigned long flags; + struct usb_device *dev; + + /* Release any periodic transfer bandwidth */ + if (urb->bandwidth) + usb_release_bandwidth (urb->dev, urb, + usb_pipeisoc (urb->pipe)); + + /* clear all state linking urb to this dev (and hcd) */ + + spin_lock_irqsave (&hcd_data_lock, flags); + list_del_init (&urb->urb_list); + dev = urb->dev; + spin_unlock_irqrestore (&hcd_data_lock, flags); + usb_put_dev (dev); +} + + +/* may be called in any context with a valid urb->dev usecount + * caller surrenders "ownership" of urb + * expects usb_submit_urb() to have sanity checked and conditioned all + * inputs in the urb + */ +static int hcd_submit_urb (struct urb *urb, int mem_flags) +{ + int status; + struct usb_hcd *hcd = urb->dev->bus->hcpriv; + struct hcd_dev *dev = urb->dev->hcpriv; + unsigned long flags; + + + if (!hcd || !dev) + return -ENODEV; +// printk("submit_urb %p, # %i, t %i\n",urb,urb->dev->devnum,usb_pipetype(urb->pipe)); + /* + * FIXME: make urb timeouts be generic, keeping the HCD cores + * as simple as possible. + */ + + // NOTE: a generic device/urb monitoring hook would go here. + // hcd_monitor_hook(MONITOR_URB_SUBMIT, urb) + // It would catch submission paths for all urbs. + + /* + * Atomically queue the urb, first to our records, then to the HCD. + * Access to urb->status is controlled by urb->lock ... changes on + * i/o completion (normal or fault) or unlinking. + */ + + // FIXME: verify that quiescing hc works right (RH cleans up) + + spin_lock_irqsave (&hcd_data_lock, flags); + if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) { + usb_get_dev (urb->dev); + list_add_tail (&urb->urb_list, &dev->urb_list); + status = 0; + } else { + INIT_LIST_HEAD (&urb->urb_list); + status = -ESHUTDOWN; + } + spin_unlock_irqrestore (&hcd_data_lock, flags); + if (status) + return status; + + /* increment urb's reference count as part of giving it to the HCD + * (which now controls it). HCD guarantees that it either returns + * an error or calls giveback(), but not both. + */ + + urb = usb_get_urb (urb); + if (urb->dev == hcd->self.root_hub) { + /* NOTE: requirement on hub callers (usbfs and the hub + * driver, for now) that URBs' urb->transfer_buffer be + * valid and usb_buffer_{sync,unmap}() not be needed, since + * they could clobber root hub response data. + */ + urb->transfer_flags |= URB_NO_DMA_MAP; + status = rh_urb_enqueue (hcd, urb); + goto done; + } + + /* lower level hcd code should use *_dma exclusively, + * unless it uses pio or talks to another transport. + */ + if (!(urb->transfer_flags & URB_NO_DMA_MAP) + && hcd->controller->dma_mask) { + if (usb_pipecontrol (urb->pipe)) + urb->setup_dma = dma_map_single ( + hcd->controller, + urb->setup_packet, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); + if (urb->transfer_buffer_length != 0) + urb->transfer_dma = dma_map_single ( + hcd->controller, + urb->transfer_buffer, + urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? DMA_FROM_DEVICE + : DMA_TO_DEVICE); + } + + status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); +done: + if (status) { + usb_put_urb (urb); + urb_unlink (urb); + } + return status; +} + +/*-------------------------------------------------------------------------*/ + +/* called in any context */ +static int hcd_get_frame_number (struct usb_device *udev) +{ + struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; + return hcd->driver->get_frame_number (hcd); +} + +/*-------------------------------------------------------------------------*/ + +/* this makes the hcd giveback() the urb more quickly, by kicking it + * off hardware queues (which may take a while) and returning it as + * soon as practical. we've already set up the urb's return status, + * but we can't know if the callback completed already. + */ +static void +unlink1 (struct usb_hcd *hcd, struct urb *urb) +{ + if (urb == (struct urb *) hcd->rh_timer.data) + usb_rh_status_dequeue (hcd, urb); + else { + int value; + + /* failures "should" be harmless */ + value = hcd->driver->urb_dequeue (hcd, urb); + if (value != 0) + dev_dbg (hcd->controller, + "dequeue %p --> %d\n", + urb, value); + } +} + +struct completion_splice { // modified urb context: + /* did we complete? */ + struct completion done; + + /* original urb data */ + usb_complete_t complete; + void *context; +}; + +static void unlink_complete (struct urb *urb, struct pt_regs *regs) +{ + struct completion_splice *splice; + + splice = (struct completion_splice *) urb->context; + + /* issue original completion call */ + urb->complete = splice->complete; + urb->context = splice->context; + urb->complete (urb, regs); + + /* then let the synchronous unlink call complete */ + complete (&splice->done); +} + +/* + * called in any context; note ASYNC_UNLINK restrictions + * + * caller guarantees urb won't be recycled till both unlink() + * and the urb's completion function return + */ +static int hcd_unlink_urb (struct urb *urb) +{ + struct hcd_dev *dev; + struct usb_hcd *hcd = 0; + struct device *sys = 0; + unsigned long flags; + struct completion_splice splice; + int retval; + + if (!urb) + return -EINVAL; + + /* + * we contend for urb->status with the hcd core, + * which changes it while returning the urb. + * + * Caller guaranteed that the urb pointer hasn't been freed, and + * that it was submitted. But as a rule it can't know whether or + * not it's already been unlinked ... so we respect the reversed + * lock sequence needed for the usb_hcd_giveback_urb() code paths + * (urb lock, then hcd_data_lock) in case some other CPU is now + * unlinking it. + */ + spin_lock_irqsave (&urb->lock, flags); + spin_lock (&hcd_data_lock); + + if (!urb->dev || !urb->dev->bus) { + retval = -ENODEV; + goto done; + } + + dev = urb->dev->hcpriv; + sys = &urb->dev->dev; + hcd = urb->dev->bus->hcpriv; + if (!dev || !hcd) { + retval = -ENODEV; + goto done; + } + + if (!urb->hcpriv) { + retval = -EINVAL; + goto done; + } + + /* Any status except -EINPROGRESS means something already started to + * unlink this URB from the hardware. So there's no more work to do. + * + * FIXME use better explicit urb state + */ + if (urb->status != -EINPROGRESS) { + retval = -EBUSY; + goto done; + } + + /* maybe set up to block until the urb's completion fires. the + * lower level hcd code is always async, locking on urb->status + * updates; an intercepted completion unblocks us. + */ + if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { + if (in_interrupt ()) { + dev_dbg (hcd->controller, "non-async unlink in_interrupt"); + retval = -EWOULDBLOCK; + goto done; + } + /* synchronous unlink: block till we see the completion */ + init_completion (&splice.done); + splice.complete = urb->complete; + splice.context = urb->context; + urb->complete = unlink_complete; + urb->context = &splice; + urb->status = -ENOENT; + } else { + /* asynchronous unlink */ + urb->status = -ECONNRESET; + } + spin_unlock (&hcd_data_lock); + spin_unlock_irqrestore (&urb->lock, flags); + + // FIXME remove splicing, so this becomes unlink1 (hcd, urb); + if (urb == (struct urb *) hcd->rh_timer.data) { + usb_rh_status_dequeue (hcd, urb); + retval = 0; + } else { + retval = hcd->driver->urb_dequeue (hcd, urb); + + /* hcds shouldn't really fail these calls, but... */ + if (retval) { + dev_dbg (sys, "dequeue %p --> %d\n", urb, retval); + if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { + spin_lock_irqsave (&urb->lock, flags); + urb->complete = splice.complete; + urb->context = splice.context; + spin_unlock_irqrestore (&urb->lock, flags); + } + goto bye; + } + } + + /* block till giveback, if needed */ + if (urb->transfer_flags & URB_ASYNC_UNLINK) + return -EINPROGRESS; + + wait_for_completion (&splice.done); + return 0; + +done: + spin_unlock (&hcd_data_lock); + spin_unlock_irqrestore (&urb->lock, flags); +bye: + if (retval && sys && sys->driver) + dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); + return retval; +} + +/*-------------------------------------------------------------------------*/ + +/* disables the endpoint: cancels any pending urbs, then synchronizes with + * the hcd to make sure all endpoint state is gone from hardware. use for + * set_configuration, set_interface, driver removal, physical disconnect. + * + * example: a qh stored in hcd_dev.ep[], holding state related to endpoint + * type, maxpacket size, toggle, halt status, and scheduling. + */ +static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) +{ + unsigned long flags; + struct hcd_dev *dev; + struct usb_hcd *hcd; + struct urb *urb; + unsigned epnum = endpoint & USB_ENDPOINT_NUMBER_MASK; + + dev = udev->hcpriv; + hcd = udev->bus->hcpriv; + +rescan: + /* (re)block new requests, as best we can */ + if (endpoint & USB_DIR_IN) { + usb_endpoint_halt (udev, epnum, 0); + udev->epmaxpacketin [epnum] = 0; + } else { + usb_endpoint_halt (udev, epnum, 1); + udev->epmaxpacketout [epnum] = 0; + } + + /* then kill any current requests */ + spin_lock_irqsave (&hcd_data_lock, flags); + list_for_each_entry (urb, &dev->urb_list, urb_list) { + int tmp = urb->pipe; + + /* ignore urbs for other endpoints */ + if (usb_pipeendpoint (tmp) != epnum) + continue; + if ((tmp ^ endpoint) & USB_DIR_IN) + continue; + + /* another cpu may be in hcd, spinning on hcd_data_lock + * to giveback() this urb. the races here should be + * small, but a full fix needs a new "can't submit" + * urb state. + */ + if (urb->status != -EINPROGRESS) + continue; + usb_get_urb (urb); + spin_unlock_irqrestore (&hcd_data_lock, flags); + + spin_lock_irqsave (&urb->lock, flags); + tmp = urb->status; + if (tmp == -EINPROGRESS) + urb->status = -ESHUTDOWN; + spin_unlock_irqrestore (&urb->lock, flags); + + /* kick hcd unless it's already returning this */ + if (tmp == -EINPROGRESS) { + tmp = urb->pipe; + unlink1 (hcd, urb); + dev_dbg (hcd->controller, + "shutdown urb %p pipe %08x ep%d%s%s\n", + urb, tmp, usb_pipeendpoint (tmp), + (tmp & USB_DIR_IN) ? "in" : "out", + ({ char *s; \ + switch (usb_pipetype (tmp)) { \ + case PIPE_CONTROL: s = ""; break; \ + case PIPE_BULK: s = "-bulk"; break; \ + case PIPE_INTERRUPT: s = "-intr"; break; \ + default: s = "-iso"; break; \ + }; s;})); + } + usb_put_urb (urb); + + /* list contents may have changed */ + goto rescan; + } + spin_unlock_irqrestore (&hcd_data_lock, flags); + + /* synchronize with the hardware, so old configuration state + * clears out immediately (and will be freed). + */ + might_sleep (); + if (hcd->driver->endpoint_disable) + hcd->driver->endpoint_disable (hcd, dev, endpoint); +} + +/*-------------------------------------------------------------------------*/ + +/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup. + * we're guaranteed that the device is fully quiesced. also, that each + * endpoint has been hcd_endpoint_disabled. + */ + +static int hcd_free_dev (struct usb_device *udev) +{ + struct hcd_dev *dev; + struct usb_hcd *hcd; + unsigned long flags; + + if (!udev || !udev->hcpriv) + return -EINVAL; + + if (!udev->bus || !udev->bus->hcpriv) + return -ENODEV; + + // should udev->devnum == -1 ?? + + dev = udev->hcpriv; + hcd = udev->bus->hcpriv; + + /* device driver problem with refcounts? */ + if (!list_empty (&dev->urb_list)) { + dev_dbg (hcd->controller, "free busy dev, %s devnum %d (bug!)\n", + hcd->self.bus_name, udev->devnum); + return -EINVAL; + } + + spin_lock_irqsave (&hcd_data_lock, flags); + list_del (&dev->dev_list); + udev->hcpriv = NULL; + spin_unlock_irqrestore (&hcd_data_lock, flags); + + kfree (dev); + return 0; +} + +/* + * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue) + * + * When registering a USB bus through the HCD framework code, use this + * usb_operations vector. The PCI glue layer does so automatically; only + * bus glue for non-PCI system busses will need to use this. + */ +struct usb_operations usb_hcd_operations = { + .allocate = hcd_alloc_dev, + .get_frame_number = hcd_get_frame_number, + .submit_urb = hcd_submit_urb, + .unlink_urb = hcd_unlink_urb, + .deallocate = hcd_free_dev, + .buffer_alloc = hcd_buffer_alloc, + .buffer_free = hcd_buffer_free, + .disable = hcd_endpoint_disable, +}; +EXPORT_SYMBOL (usb_hcd_operations); + +/*-------------------------------------------------------------------------*/ + +/** + * usb_hcd_giveback_urb - return URB from HCD to device driver + * @hcd: host controller returning the URB + * @urb: urb being returned to the USB device driver. + * @regs: pt_regs, passed down to the URB completion handler + * Context: in_interrupt() + * + * This hands the URB from HCD to its USB device driver, using its + * completion function. The HCD has freed all per-urb resources + * (and is done using urb->hcpriv). It also released all HCD locks; + * the device driver won't cause problems if it frees, modifies, + * or resubmits this URB. + */ +void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) +{ + urb_unlink (urb); + + // NOTE: a generic device/urb monitoring hook would go here. + // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev) + // It would catch exit/unlink paths for all urbs. + + /* lower level hcd code should use *_dma exclusively */ + if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { + if (usb_pipecontrol (urb->pipe)) + pci_unmap_single (hcd->pdev, urb->setup_dma, + sizeof (struct usb_ctrlrequest), + PCI_DMA_TODEVICE); + if (urb->transfer_buffer_length != 0) + pci_unmap_single (hcd->pdev, urb->transfer_dma, + urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? PCI_DMA_FROMDEVICE + : PCI_DMA_TODEVICE); + } + + /* pass ownership to the completion handler */ + urb->complete (urb, regs); + usb_put_urb (urb); +} + +/*-------------------------------------------------------------------------*/ + +/** + * usb_hcd_irq - hook IRQs to HCD framework (bus glue) + * @irq: the IRQ being raised + * @__hcd: pointer to the HCD whose IRQ is beinng signaled + * @r: saved hardware registers + * + * When registering a USB bus through the HCD framework code, use this + * to handle interrupts. The PCI glue layer does so automatically; only + * bus glue for non-PCI system busses will need to use this. + */ +irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) +{ + struct usb_hcd *hcd = __hcd; + int start = hcd->state; + + if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ + return IRQ_NONE; + + hcd->driver->irq (hcd, r); + if (hcd->state != start && hcd->state == USB_STATE_HALT) + usb_hc_died (hcd); + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +static void hcd_panic (void *_hcd) +{ + struct usb_hcd *hcd = _hcd; + hcd->driver->stop (hcd); +} + +/** + * usb_hc_died - report abnormal shutdown of a host controller (bus glue) + * @hcd: pointer to the HCD representing the controller + * + * This is called by bus glue to report a USB host controller that died + * while operations may still have been pending. It's called automatically + * by the PCI glue, so only glue for non-PCI busses should need to call it. + */ +void STDCALL usb_hc_died (struct usb_hcd *hcd) +{ + struct list_head *devlist, *urblist; + struct hcd_dev *dev; + struct urb *urb; + unsigned long flags; + + /* flag every pending urb as done */ + spin_lock_irqsave (&hcd_data_lock, flags); + list_for_each (devlist, &hcd->dev_list) { + dev = list_entry (devlist, struct hcd_dev, dev_list); + list_for_each (urblist, &dev->urb_list) { + urb = list_entry (urblist, struct urb, urb_list); + dev_dbg (hcd->controller, "shutdown %s urb %p pipe %x, current status %d\n", + hcd->self.bus_name, urb, urb->pipe, urb->status); + if (urb->status == -EINPROGRESS) + urb->status = -ESHUTDOWN; + } + } + urb = (struct urb *) hcd->rh_timer.data; + if (urb) + urb->status = -ESHUTDOWN; + spin_unlock_irqrestore (&hcd_data_lock, flags); + + /* hcd->stop() needs a task context */ + INIT_WORK (&hcd->work, hcd_panic, hcd); + (void) schedule_work (&hcd->work); +} + diff --git a/reactos/drivers/usb/cromwell/core/hcd.h b/reactos/drivers/usb/cromwell/core/hcd.h new file mode 100644 index 00000000000..15eae1d8949 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/hcd.h @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2001-2002 by David Brownell + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifdef __KERNEL__ + +/* This file contains declarations of usbcore internals that are mostly + * used or exposed by Host Controller Drivers. + */ + +/* + * USB Packet IDs (PIDs) + */ +#define USB_PID_UNDEF_0 0xf0 +#define USB_PID_OUT 0xe1 +#define USB_PID_ACK 0xd2 +#define USB_PID_DATA0 0xc3 +#define USB_PID_PING 0xb4 /* USB 2.0 */ +#define USB_PID_SOF 0xa5 +#define USB_PID_NYET 0x96 /* USB 2.0 */ +#define USB_PID_DATA2 0x87 /* USB 2.0 */ +#define USB_PID_SPLIT 0x78 /* USB 2.0 */ +#define USB_PID_IN 0x69 +#define USB_PID_NAK 0x5a +#define USB_PID_DATA1 0x4b +#define USB_PID_PREAMBLE 0x3c /* Token mode */ +#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ +#define USB_PID_SETUP 0x2d +#define USB_PID_STALL 0x1e +#define USB_PID_MDATA 0x0f /* USB 2.0 */ + +/*-------------------------------------------------------------------------*/ + +/* + * USB Host Controller Driver (usb_hcd) framework + * + * Since "struct usb_bus" is so thin, you can't share much code in it. + * This framework is a layer over that, and should be more sharable. + */ + +/*-------------------------------------------------------------------------*/ + +struct usb_hcd { /* usb_bus.hcpriv points to this */ + + /* + * housekeeping + */ + struct usb_bus self; /* hcd is-a bus */ + + const char *product_desc; /* product/vendor string */ + const char *description; /* "ehci-hcd" etc */ + + struct timer_list rh_timer; /* drives root hub */ + struct list_head dev_list; /* devices on this bus */ + struct work_struct work; + + /* + * hardware info/state + */ + struct hc_driver *driver; /* hw-specific hooks */ + int irq; /* irq allocated */ + void *regs; /* device memory/io */ + struct device *controller; /* handle to hardware */ + + /* a few non-PCI controllers exist, mostly for OHCI */ + struct pci_dev *pdev; /* pci is typical */ +#ifdef CONFIG_PCI + int region; /* pci region for regs */ + u32 pci_state [16]; /* for PM state save */ + atomic_t resume_count; /* multiple resumes issue */ +#endif + +#define HCD_BUFFER_POOLS 4 + struct pci_pool *pool [HCD_BUFFER_POOLS]; + + int state; +# define __ACTIVE 0x01 +# define __SLEEPY 0x02 +# define __SUSPEND 0x04 +# define __TRANSIENT 0x80 + +# define USB_STATE_HALT 0 +# define USB_STATE_RUNNING (__ACTIVE) +# define USB_STATE_READY (__ACTIVE|__SLEEPY) +# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) +# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT) +# define USB_STATE_SUSPENDED (__SUSPEND) + +#define HCD_IS_RUNNING(state) ((state) & __ACTIVE) +#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND) + + /* more shared queuing code would be good; it should support + * smarter scheduling, handle transaction translators, etc; + * input size of periodic table to an interrupt scheduler. + * (ohci 32, uhci 1024, ehci 256/512/1024). + */ +}; + +/* 2.4 does this a bit differently ... */ +static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) +{ + return &hcd->self; +} + + +struct hcd_dev { /* usb_device.hcpriv points to this */ + struct list_head dev_list; /* on this hcd */ + struct list_head urb_list; /* pending on this dev */ + + /* per-configuration HC/HCD state, such as QH or ED */ + void *ep[32]; +}; + +// urb.hcpriv is really hardware-specific + +struct hcd_timeout { /* timeouts we allocate */ + struct list_head timeout_list; + struct timer_list timer; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * FIXME usb_operations should vanish or become hc_driver, + * when usb_bus and usb_hcd become the same thing. + */ + +struct usb_operations { + int (*allocate)(struct usb_device *); + int (*deallocate)(struct usb_device *); + int (*get_frame_number) (struct usb_device *usb_dev); + int (*submit_urb) (struct urb *urb, int mem_flags); + int (*unlink_urb) (struct urb *urb); + + /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ + void *(*buffer_alloc)(struct usb_bus *bus, size_t size, + int mem_flags, + dma_addr_t *dma); + void (*buffer_free)(struct usb_bus *bus, size_t size, + void *addr, dma_addr_t dma); + + void (*disable)(struct usb_device *udev, int bEndpointAddress); +}; + +/* each driver provides one of these, and hardware init support */ + +struct pt_regs; + +struct hc_driver { + const char *description; /* "ehci-hcd" etc */ + + /* irq handler */ + void (*irq) (struct usb_hcd *hcd, struct pt_regs *regs); + + int flags; +#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ +#define HCD_USB11 0x0010 /* USB 1.1 */ +#define HCD_USB2 0x0020 /* USB 2.0 */ + + /* called to init HCD and root hub */ + int (*start) (struct usb_hcd *hcd); + + /* called after all devices were suspended */ + int (*suspend) (struct usb_hcd *hcd, u32 state); + + /* called before any devices get resumed */ + int (*resume) (struct usb_hcd *hcd); + + /* cleanly make HCD stop writing memory and doing I/O */ + void (*stop) (struct usb_hcd *hcd); + + /* return current frame number */ + int (*get_frame_number) (struct usb_hcd *hcd); + + /* memory lifecycle */ + struct usb_hcd *(*hcd_alloc) (void); + void (*hcd_free) (struct usb_hcd *hcd); + + /* manage i/o requests, device state */ + int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb, + int mem_flags); + int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); + + /* hw synch, freeing endpoint resources that urb_dequeue can't */ + void (*endpoint_disable)(struct usb_hcd *hcd, + struct hcd_dev *dev, int bEndpointAddress); + + /* root hub support */ + int (*hub_status_data) (struct usb_hcd *hcd, char *buf); + int (*hub_control) (struct usb_hcd *hcd, + u16 typeReq, u16 wValue, u16 wIndex, + char *buf, u16 wLength); +}; + +extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); +extern void STDCALL usb_bus_init (struct usb_bus *bus); +extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb); + +#ifdef CONFIG_PCI +struct pci_dev; +struct pci_device_id; +extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev, + const struct pci_device_id *id); +extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev); + +#ifdef CONFIG_PM +// FIXME: see Documentation/power/pci.txt (2.4.6 and later?) +// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state); +extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state); +extern int usb_hcd_pci_resume (struct pci_dev *dev); +// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg); +#endif /* CONFIG_PM */ + +#endif /* CONFIG_PCI */ + +/* pci-ish (pdev null is ok) buffer alloc/mapping support */ +int hcd_buffer_create (struct usb_hcd *hcd); +void hcd_buffer_destroy (struct usb_hcd *hcd); + +void *hcd_buffer_alloc (struct usb_bus *bus, size_t size, + int mem_flags, dma_addr_t *dma); +void hcd_buffer_free (struct usb_bus *bus, size_t size, + void *addr, dma_addr_t dma); + +/* generic bus glue, needed for host controllers that don't use PCI */ +extern struct usb_operations usb_hcd_operations; +extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); +extern void STDCALL usb_hc_died (struct usb_hcd *hcd); + +/* -------------------------------------------------------------------------- */ + +/* Enumeration is only for the hub driver, or HCD virtual root hubs */ +extern int usb_new_device(struct usb_device *dev, struct device *parent); +extern void STDCALL usb_connect(struct usb_device *dev); +extern void usb_disconnect(struct usb_device **); + +/* exported to hub driver ONLY to support usb_reset_device () */ +extern int usb_get_configuration(struct usb_device *dev); +extern void usb_set_maxpacket(struct usb_device *dev); +extern void usb_destroy_configuration(struct usb_device *dev); +extern int usb_set_address(struct usb_device *dev); + +/* use these only before the device's address has been set */ +#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30)) +#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN) + +/*-------------------------------------------------------------------------*/ + +/* + * HCD Root Hub support + */ + +#include "hub.h" + +/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ +#define DeviceRequest \ + ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) +#define DeviceOutRequest \ + ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) + +#define InterfaceRequest \ + ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) + +#define EndpointRequest \ + ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +#define EndpointOutRequest \ + ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) + +/* table 9.6 standard features */ +#define DEVICE_REMOTE_WAKEUP 1 +#define ENDPOINT_HALT 0 + +/* class requests from the USB 2.0 hub spec, table 11-15 */ +/* GetBusState and SetHubDescriptor are optional, omitted */ +#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) +#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) +#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) +#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) +#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) +#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) +#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) + + +/*-------------------------------------------------------------------------*/ + +/* + * Generic bandwidth allocation constants/support + */ +#define FRAME_TIME_USECS 1000L +#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ + /* Trying not to use worst-case bit-stuffing + of (7/6 * 8 * bytecount) = 9.33 * bytecount */ + /* bytecount = data payload byte count */ + +#define NS_TO_US(ns) ((ns + 500L) / 1000L) + /* convert & round nanoseconds to microseconds */ + +extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, + int bustime, int isoc); +extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb, + int isoc); + +/* + * Full/low speed bandwidth allocation constants/support. + */ +#define BW_HOST_DELAY 1000L /* nanoseconds */ +#define BW_HUB_LS_SETUP 333L /* nanoseconds */ + /* 4 full-speed bit times (est.) */ + +#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ +#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) +#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) + +extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb); + +/* + * Ceiling microseconds (typical) for that many bytes at high speed + * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed + * to preallocate bandwidth) + */ +#define USB2_HOST_DELAY 5 /* nsec, guess */ +#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ + + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + + USB2_HOST_DELAY) +#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \ + + ((2083UL * (3167 + BitTime (bytes)))/1000) \ + + USB2_HOST_DELAY) + +extern long STDCALL usb_calc_bus_time (int speed, int is_input, + int isoc, int bytecount); + +/*-------------------------------------------------------------------------*/ + +extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *); +extern void STDCALL usb_free_bus (struct usb_bus *); + +extern void STDCALL usb_register_bus (struct usb_bus *); +extern void STDCALL usb_deregister_bus (struct usb_bus *); + +extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev, + struct device *parent_dev); + +/* for portability to 2.4, hcds should call this */ +static inline int hcd_register_root (struct usb_hcd *hcd) +{ + return usb_register_root_hub ( + hcd_to_bus (hcd)->root_hub, hcd->controller); +} + +/*-------------------------------------------------------------------------*/ + +/* exported only within usbcore */ + +extern struct list_head usb_bus_list; +extern struct semaphore usb_bus_list_lock; + +extern void usb_bus_get (struct usb_bus *bus); +extern void usb_bus_put (struct usb_bus *bus); + +extern int usb_find_interface_driver (struct usb_device *dev, + struct usb_interface *interface); + +#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) + +#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) + +/* + * USB device fs stuff + */ + +#ifdef CONFIG_USB_DEVICEFS + +/* + * these are expected to be called from the USB core/hub thread + * with the kernel lock held + */ +extern void usbfs_add_bus(struct usb_bus *bus); +extern void usbfs_remove_bus(struct usb_bus *bus); +extern void usbfs_add_device(struct usb_device *dev); +extern void usbfs_remove_device(struct usb_device *dev); +extern void usbfs_update_special (void); + +extern int usbfs_init(void); +extern void usbfs_cleanup(void); + +#else /* CONFIG_USB_DEVICEFS */ + +static inline void usbfs_add_bus(struct usb_bus *bus) {} +static inline void usbfs_remove_bus(struct usb_bus *bus) {} +static inline void usbfs_add_device(struct usb_device *dev) {} +static inline void usbfs_remove_device(struct usb_device *dev) {} +static inline void usbfs_update_special (void) {} + +static inline int usbfs_init(void) { return 0; } +static inline void usbfs_cleanup(void) { } + +#endif /* CONFIG_USB_DEVICEFS */ + +/*-------------------------------------------------------------------------*/ + +/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ +// bleech -- resurfaced in 2.4.11 or 2.4.12 +#define bitmap DeviceRemovable + + +/*-------------------------------------------------------------------------*/ + +/* random stuff */ + +#define RUN_CONTEXT (in_irq () ? "in_irq" \ + : (in_interrupt () ? "in_interrupt" : "can sleep")) + + +#endif /* __KERNEL__ */ + diff --git a/reactos/drivers/usb/cromwell/core/hub.c b/reactos/drivers/usb/cromwell/core/hub.c new file mode 100644 index 00000000000..744ec729b87 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/hub.c @@ -0,0 +1,1383 @@ +/* + * USB hub driver. + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Gregory P. Smith + * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au) + * + */ +#define DEBUG +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include +#include +#include + +#include +#include +#include + +#include "hcd.h" +#include "hub.h" +#else +#include "../usb_wrapper.h" +#include "hcd.h" +#include "hub.h" +#define DEBUG +#endif + +/* Wakes up khubd */ +static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_MUTEX(usb_address0_sem); + +static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ +static LIST_HEAD(hub_list); /* List of all hubs (for cleanup) */ + +static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); +static pid_t khubd_pid = 0; /* PID of khubd */ +static DECLARE_COMPLETION(khubd_exited); + +#ifdef DEBUG +static inline char *portspeed (int portstatus) +{ + if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) + return "480 Mb/s"; + else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) + return "1.5 Mb/s"; + else + return "12 Mb/s"; +} +#endif + +/* for dev_info, dev_dbg, etc */ +static inline struct device *hubdev (struct usb_device *dev) +{ + return &dev->actconfig->interface [0].dev; +} + +/* USB 2.0 spec Section 11.24.4.5 */ +static int get_hub_descriptor(struct usb_device *dev, void *data, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, + USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT); +} + +/* + * USB 2.0 spec Section 11.24.2.1 + */ +static int clear_hub_feature(struct usb_device *dev, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ); +} + +/* + * USB 2.0 spec Section 11.24.2.2 + * BUG: doesn't handle port indicator selector in high byte of wIndex + */ +static int clear_port_feature(struct usb_device *dev, int port, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); +} + +/* + * USB 2.0 spec Section 11.24.2.13 + * BUG: doesn't handle port indicator selector in high byte of wIndex + */ +static int set_port_feature(struct usb_device *dev, int port, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); +} + +/* + * USB 2.0 spec Section 11.24.2.6 + */ +static int get_hub_status(struct usb_device *dev, + struct usb_hub_status *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, + data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); +} + +/* + * USB 2.0 spec Section 11.24.2.7 + */ +static int get_port_status(struct usb_device *dev, int port, + struct usb_port_status *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, + data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); +} + +/* completion function, fires on port status changes and various faults */ +static void hub_irq(struct urb *urb, struct pt_regs *regs) +{ + struct usb_hub *hub = (struct usb_hub *)urb->context; + unsigned long flags; + int status; + + switch (urb->status) { + case -ENOENT: /* synchronous unlink */ + case -ECONNRESET: /* async unlink */ + case -ESHUTDOWN: /* hardware going away */ + return; + + default: /* presumably an error */ + /* Cause a hub reset after 10 consecutive errors */ + dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status); + if ((++hub->nerrors < 10) || hub->error) + goto resubmit; + hub->error = urb->status; + /* FALL THROUGH */ + + /* let khubd handle things */ + case 0: /* we got data: port status changed */ + break; + } + + hub->nerrors = 0; + + /* Something happened, let khubd figure it out */ + spin_lock_irqsave(&hub_event_lock, flags); + if (list_empty(&hub->event_list)) { + list_add(&hub->event_list, &hub_event_list); + wake_up(&khubd_wait); + } + spin_unlock_irqrestore(&hub_event_lock, flags); + +resubmit: + if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 + /* ENODEV means we raced disconnect() */ + && status != -ENODEV) + dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status); +} + +/* USB 2.0 spec Section 11.24.2.3 */ +static inline int +hub_clear_tt_buffer (struct usb_device *hub, u16 devinfo, u16 tt) +{ + return usb_control_msg (hub, usb_rcvctrlpipe (hub, 0), + HUB_CLEAR_TT_BUFFER, USB_DIR_IN | USB_RECIP_OTHER, + devinfo, tt, 0, 0, HZ); +} + +/* + * enumeration blocks khubd for a long time. we use keventd instead, since + * long blocking there is the exception, not the rule. accordingly, HCDs + * talking to TTs must queue control transfers (not just bulk and iso), so + * both can talk to the same hub concurrently. + */ +static void hub_tt_kevent (void *arg) +{ + struct usb_hub *hub = arg; + unsigned long flags; + + spin_lock_irqsave (&hub->tt.lock, flags); + while (!list_empty (&hub->tt.clear_list)) { + struct list_head *temp; + struct usb_tt_clear *clear; + struct usb_device *dev; + int status; + + temp = hub->tt.clear_list.next; + clear = list_entry (temp, struct usb_tt_clear, clear_list); + list_del (&clear->clear_list); + + /* drop lock so HCD can concurrently report other TT errors */ + spin_unlock_irqrestore (&hub->tt.lock, flags); + dev = interface_to_usbdev (hub->intf); + status = hub_clear_tt_buffer (dev, clear->devinfo, clear->tt); + spin_lock_irqsave (&hub->tt.lock, flags); + + if (status) + err ("usb-%s-%s clear tt %d (%04x) error %d", + dev->bus->bus_name, dev->devpath, + clear->tt, clear->devinfo, status); + kfree (clear); + } + spin_unlock_irqrestore (&hub->tt.lock, flags); +} + +/** + * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub + * @dev: the device whose split transaction failed + * @pipe: identifies the endpoint of the failed transaction + * + * High speed HCDs use this to tell the hub driver that some split control or + * bulk transaction failed in a way that requires clearing internal state of + * a transaction translator. This is normally detected (and reported) from + * interrupt context. + * + * It may not be possible for that hub to handle additional full (or low) + * speed transactions until that state is fully cleared out. + */ +void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) +{ + struct usb_tt *tt = dev->tt; + unsigned long flags; + struct usb_tt_clear *clear; + + /* we've got to cope with an arbitrary number of pending TT clears, + * since each TT has "at least two" buffers that can need it (and + * there can be many TTs per hub). even if they're uncommon. + */ + if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == 0) { + err ("can't save CLEAR_TT_BUFFER state for hub at usb-%s-%s", + dev->bus->bus_name, tt->hub->devpath); + /* FIXME recover somehow ... RESET_TT? */ + return; + } + + /* info that CLEAR_TT_BUFFER needs */ + clear->tt = tt->multi ? dev->ttport : 1; + clear->devinfo = usb_pipeendpoint (pipe); + clear->devinfo |= dev->devnum << 4; + clear->devinfo |= usb_pipecontrol (pipe) + ? (USB_ENDPOINT_XFER_CONTROL << 11) + : (USB_ENDPOINT_XFER_BULK << 11); + if (usb_pipein (pipe)) + clear->devinfo |= 1 << 15; + + /* tell keventd to clear state for this TT */ + spin_lock_irqsave (&tt->lock, flags); + list_add_tail (&clear->clear_list, &tt->clear_list); + schedule_work (&tt->kevent); + spin_unlock_irqrestore (&tt->lock, flags); +} + +static void hub_power_on(struct usb_hub *hub) +{ + struct usb_device *dev; + int i; + + /* Enable power to the ports */ + dev_dbg(hubdev(interface_to_usbdev(hub->intf)), + "enabling power on all ports\n"); + dev = interface_to_usbdev(hub->intf); + + for (i = 0; i < hub->descriptor->bNbrPorts; i++) + set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + + /* Wait for power to be enabled */ + wait_ms(hub->descriptor->bPwrOn2PwrGood * 2); +} + +static int hub_hub_status(struct usb_hub *hub, + u16 *status, u16 *change) +{ + struct usb_device *dev = interface_to_usbdev (hub->intf); + int ret; + + ret = get_hub_status(dev, &hub->status->hub); + if (ret < 0) + dev_err (hubdev (dev), + "%s failed (err = %d)\n", __FUNCTION__, ret); + else { + *status = le16_to_cpu(hub->status->hub.wHubStatus); + *change = le16_to_cpu(hub->status->hub.wHubChange); + ret = 0; + } + return ret; +} + +static int hub_configure(struct usb_hub *hub, + struct usb_endpoint_descriptor *endpoint) +{ + struct usb_device *dev = interface_to_usbdev (hub->intf); + struct device *hub_dev; + u16 hubstatus, hubchange; + unsigned int pipe; + int maxp, ret; + char *message; + + hub->buffer = usb_buffer_alloc(dev, sizeof(*hub->buffer), GFP_KERNEL, + &hub->buffer_dma); + if (!hub->buffer) { + message = "can't allocate hub irq buffer"; + ret = -ENOMEM; + goto fail; + } + + hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); + if (!hub->status) { + message = "can't kmalloc hub status buffer"; + ret = -ENOMEM; + goto fail; + } + + hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); + if (!hub->descriptor) { + message = "can't kmalloc hub descriptor"; + ret = -ENOMEM; + goto fail; + } + + /* Request the entire hub descriptor. + * hub->descriptor can handle USB_MAXCHILDREN ports, + * but the hub can/will return fewer bytes here. + */ + ret = get_hub_descriptor(dev, hub->descriptor, + sizeof(*hub->descriptor)); + if (ret < 0) { + message = "can't read hub descriptor"; + goto fail; + } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { + message = "hub has too many ports!"; + ret = -ENODEV; + goto fail; + } + + hub_dev = hubdev(dev); + dev->maxchild = hub->descriptor->bNbrPorts; + dev_info (hub_dev, "%d port%s detected\n", dev->maxchild, + (dev->maxchild == 1) ? "" : "s"); + + le16_to_cpus(&hub->descriptor->wHubCharacteristics); + + if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) { + int i; + char portstr [USB_MAXCHILDREN + 1]; + + for (i = 0; i < dev->maxchild; i++) + portstr[i] = hub->descriptor->DeviceRemovable + [((i + 1) / 8)] & (1 << ((i + 1) % 8)) + ? 'F' : 'R'; + portstr[dev->maxchild] = 0; + dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr); + } else + dev_dbg(hub_dev, "standalone hub\n"); + + switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { + case 0x00: + dev_dbg(hub_dev, "ganged power switching\n"); + break; + case 0x01: + dev_dbg(hub_dev, "individual port power switching\n"); + break; + case 0x02: + case 0x03: + dev_dbg(hub_dev, "unknown reserved power switching mode\n"); + break; + } + + switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { + case 0x00: + dev_dbg(hub_dev, "global over-current protection\n"); + break; + case 0x08: + dev_dbg(hub_dev, "individual port over-current protection\n"); + break; + case 0x10: + case 0x18: + dev_dbg(hub_dev, "no over-current protection\n"); + break; + } + + spin_lock_init (&hub->tt.lock); + INIT_LIST_HEAD (&hub->tt.clear_list); + INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); + switch (dev->descriptor.bDeviceProtocol) { + case 0: + break; + case 1: + dev_dbg(hub_dev, "Single TT\n"); + hub->tt.hub = dev; + break; + case 2: + dev_dbg(hub_dev, "TT per port\n"); + hub->tt.hub = dev; + hub->tt.multi = 1; + break; + default: + dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", + dev->descriptor.bDeviceProtocol); + break; + } + + switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { + case 0x00: + if (dev->descriptor.bDeviceProtocol != 0) + dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); + break; + case 0x20: + dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n"); + break; + case 0x40: + dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n"); + break; + case 0x60: + dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n"); + break; + } + + dev_dbg(hub_dev, "Port indicators are %s supported\n", + (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) + ? "" : "not"); + + dev_dbg(hub_dev, "power on to power good time: %dms\n", + hub->descriptor->bPwrOn2PwrGood * 2); + dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", + hub->descriptor->bHubContrCurrent); + + ret = hub_hub_status(hub, &hubstatus, &hubchange); + if (ret < 0) { + message = "can't get hub status"; + goto fail; + } + + dev_dbg(hub_dev, "local power source is %s\n", + (hubstatus & HUB_STATUS_LOCAL_POWER) + ? "lost (inactive)" : "good"); + + dev_dbg(hub_dev, "%sover-current condition exists\n", + (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); + + /* Start the interrupt endpoint */ + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + if (maxp > sizeof(*hub->buffer)) + maxp = sizeof(*hub->buffer); + + hub->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!hub->urb) { + message = "couldn't allocate interrupt urb"; + ret = -ENOMEM; + goto fail; + } + + usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq, + hub, endpoint->bInterval); + hub->urb->transfer_dma = hub->buffer_dma; + hub->urb->transfer_flags |= URB_NO_DMA_MAP; + ret = usb_submit_urb(hub->urb, GFP_KERNEL); + if (ret) { + message = "couldn't submit status urb"; + goto fail; + } + + /* Wake up khubd */ + wake_up(&khubd_wait); + + hub_power_on(hub); + + return 0; + +fail: + dev_err (&hub->intf->dev, "config failed, %s (err %d)\n", + message, ret); + /* hub_disconnect() frees urb and descriptor */ + return ret; +} + +static void hub_disconnect(struct usb_interface *intf) +{ + struct usb_hub *hub = usb_get_intfdata (intf); + unsigned long flags; + + if (!hub) + return; + + usb_set_intfdata (intf, NULL); + spin_lock_irqsave(&hub_event_lock, flags); + + /* Delete it and then reset it */ + list_del(&hub->event_list); + INIT_LIST_HEAD(&hub->event_list); + list_del(&hub->hub_list); + INIT_LIST_HEAD(&hub->hub_list); + + spin_unlock_irqrestore(&hub_event_lock, flags); + + down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */ + up(&hub->khubd_sem); + + /* assuming we used keventd, it must quiesce too */ + if (hub->tt.hub) + flush_scheduled_work (); + + if (hub->urb) { + usb_unlink_urb(hub->urb); + usb_free_urb(hub->urb); + hub->urb = NULL; + } + + if (hub->descriptor) { + kfree(hub->descriptor); + hub->descriptor = NULL; + } + + if (hub->status) { + kfree(hub->status); + hub->status = NULL; + } + + if (hub->buffer) { + usb_buffer_free(interface_to_usbdev(intf), + sizeof(*hub->buffer), hub->buffer, + hub->buffer_dma); + hub->buffer = NULL; + } + + /* Free the memory */ + kfree(hub); +} + +static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_host_interface *desc; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *dev; + struct usb_hub *hub; + unsigned long flags; + + desc = intf->altsetting + intf->act_altsetting; + dev = interface_to_usbdev(intf); + + /* Some hubs have a subclass of 1, which AFAICT according to the */ + /* specs is not defined, but it works */ + if ((desc->desc.bInterfaceSubClass != 0) && + (desc->desc.bInterfaceSubClass != 1)) { +descriptor_error: + dev_err (&intf->dev, "bad descriptor, ignoring hub\n"); + return -EIO; + } + + /* Multiple endpoints? What kind of mutant ninja-hub is this? */ + if (desc->desc.bNumEndpoints != 1) { + goto descriptor_error; + } + + endpoint = &desc->endpoint[0].desc; + + /* Output endpoint? Curiouser and curiouser.. */ + if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { + goto descriptor_error; + } + + /* If it's not an interrupt endpoint, we'd better punt! */ + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_INT) { + goto descriptor_error; + return -EIO; + } + + /* We found a hub */ + dev_info (hubdev (dev), "USB hub found\n"); + + hub = kmalloc(sizeof(*hub), GFP_KERNEL); + if (!hub) { + err("couldn't kmalloc hub struct"); + return -ENOMEM; + } + + memset(hub, 0, sizeof(*hub)); + + INIT_LIST_HEAD(&hub->event_list); + hub->intf = intf; + init_MUTEX(&hub->khubd_sem); + + /* Record the new hub's existence */ + spin_lock_irqsave(&hub_event_lock, flags); + INIT_LIST_HEAD(&hub->hub_list); + list_add(&hub->hub_list, &hub_list); + spin_unlock_irqrestore(&hub_event_lock, flags); + + usb_set_intfdata (intf, hub); + + if (hub_configure(hub, endpoint) >= 0) { + strcpy (intf->dev.name, "Hub"); + return 0; + } + + hub_disconnect (intf); + return -ENODEV; +} + +static int +hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) +{ + struct usb_device *hub = interface_to_usbdev (intf); + + /* assert ifno == 0 (part of hub spec) */ + switch (code) { + case USBDEVFS_HUB_PORTINFO: { + struct usbdevfs_hub_portinfo *info = user_data; + unsigned long flags; + int i; + + spin_lock_irqsave(&hub_event_lock, flags); + if (hub->devnum <= 0) + info->nports = 0; + else { + info->nports = hub->maxchild; + for (i = 0; i < info->nports; i++) { + if (hub->children[i] == NULL) + info->port[i] = 0; + else + info->port[i] = + hub->children[i]->devnum; + } + } + spin_unlock_irqrestore(&hub_event_lock, flags); + + return info->nports + 1; + } + + default: + return -ENOSYS; + } +} + +static int hub_reset(struct usb_hub *hub) +{ + struct usb_device *dev = interface_to_usbdev(hub->intf); + int i; + + /* Disconnect any attached devices */ + for (i = 0; i < hub->descriptor->bNbrPorts; i++) { + if (dev->children[i]) + usb_disconnect(&dev->children[i]); + } + + /* Attempt to reset the hub */ + if (hub->urb) + usb_unlink_urb(hub->urb); + else + return -1; + + if (usb_reset_device(dev)) + return -1; + + hub->urb->dev = dev; + if (usb_submit_urb(hub->urb, GFP_KERNEL)) + return -1; + + hub_power_on(hub); + + return 0; +} + +static void hub_start_disconnect(struct usb_device *dev) +{ + struct usb_device *parent = dev->parent; + int i; + + /* Find the device pointer to disconnect */ + if (parent) { + for (i = 0; i < parent->maxchild; i++) { + if (parent->children[i] == dev) { + usb_disconnect(&parent->children[i]); + return; + } + } + } + + err("cannot disconnect hub %s", dev->devpath); +} + +static int hub_port_status(struct usb_device *dev, int port, + u16 *status, u16 *change) +{ + struct usb_hub *hub = usb_get_intfdata (dev->actconfig->interface); + int ret; + + ret = get_port_status(dev, port + 1, &hub->status->port); + if (ret < 0) + dev_err (hubdev (dev), + "%s failed (err = %d)\n", __FUNCTION__, ret); + else { + *status = le16_to_cpu(hub->status->port.wPortStatus); + *change = le16_to_cpu(hub->status->port.wPortChange); + ret = 0; + } + return ret; +} + +#define HUB_RESET_TRIES 5 +#define HUB_PROBE_TRIES 2 +#define HUB_SHORT_RESET_TIME 10 +#define HUB_LONG_RESET_TIME 200 +#define HUB_RESET_TIMEOUT 500 + +/* return: -1 on error, 0 on success, 1 on disconnect. */ +static int hub_port_wait_reset(struct usb_device *hub, int port, + struct usb_device *dev, unsigned int delay) +{ + int delay_time, ret; + u16 portstatus; + u16 portchange; + + for (delay_time = 0; + delay_time < HUB_RESET_TIMEOUT; + delay_time += delay) { + /* wait to give the device a chance to reset */ + wait_ms(delay); + + /* read and decode port status */ + ret = hub_port_status(hub, port, &portstatus, &portchange); + if (ret < 0) { + return -1; + } + + /* Device went away? */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return 1; + + /* bomb out completely if something weird happened */ + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + return -1; + + /* if we`ve finished resetting, then break out of the loop */ + if (!(portstatus & USB_PORT_STAT_RESET) && + (portstatus & USB_PORT_STAT_ENABLE)) { + if (portstatus & USB_PORT_STAT_HIGH_SPEED) + dev->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + dev->speed = USB_SPEED_LOW; + else + dev->speed = USB_SPEED_FULL; + return 0; + } + + /* switch to the long delay after two short delay failures */ + if (delay_time >= 2 * HUB_SHORT_RESET_TIME) + delay = HUB_LONG_RESET_TIME; + + dev_dbg (hubdev (hub), + "port %d not reset yet, waiting %dms\n", + port + 1, delay); + } + + return -1; +} + +/* return: -1 on error, 0 on success, 1 on disconnect. */ +static int hub_port_reset(struct usb_device *hub, int port, + struct usb_device *dev, unsigned int delay) +{ + int i, status; + + /* Reset the port */ + for (i = 0; i < HUB_RESET_TRIES; i++) { + set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); + + /* return on disconnect or reset */ + status = hub_port_wait_reset(hub, port, dev, delay); + if (status != -1) { + clear_port_feature(hub, + port + 1, USB_PORT_FEAT_C_RESET); + dev->state = status + ? USB_STATE_NOTATTACHED + : USB_STATE_DEFAULT; + return status; + } + + dev_dbg (hubdev (hub), + "port %d not enabled, trying reset again...\n", + port + 1); + delay = HUB_LONG_RESET_TIME; + } + + dev_err (hubdev (hub), + "Cannot enable port %i. Maybe the USB cable is bad?\n", + port + 1); + + return -1; +} + +int hub_port_disable(struct usb_device *hub, int port) +{ + int ret; + + ret = clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); + if (ret) + dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", + port + 1, ret); + + return ret; +} + +/* USB 2.0 spec, 7.1.7.3 / fig 7-29: + * + * Between connect detection and reset signaling there must be a delay + * of 100ms at least for debounce and power-settling. The corresponding + * timer shall restart whenever the downstream port detects a disconnect. + * + * Apparently there are some bluetooth and irda-dongles and a number + * of low-speed devices which require longer delays of about 200-400ms. + * Not covered by the spec - but easy to deal with. + * + * This implementation uses 400ms minimum debounce timeout and checks + * every 25ms for transient disconnects to restart the delay. + */ + +#define HUB_DEBOUNCE_TIMEOUT 400 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 4 + +/* return: -1 on error, 0 on success, 1 on disconnect. */ +static int hub_port_debounce(struct usb_device *hub, int port) +{ + int ret; + int delay_time, stable_count; + u16 portchange, portstatus; + unsigned connection; + + connection = 0; + stable_count = 0; + for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) { + wait_ms(HUB_DEBOUNCE_STEP); + + ret = hub_port_status(hub, port, &portstatus, &portchange); + if (ret < 0) + return -1; + + if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) { + if (connection) { + if (++stable_count == HUB_DEBOUNCE_STABLE) + break; + } + } else { + stable_count = 0; + } + connection = portstatus & USB_PORT_STAT_CONNECTION; + + if ((portchange & USB_PORT_STAT_C_CONNECTION)) { + clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION); + } + } + + /* XXX Replace this with dbg() when 2.6 is about to ship. */ + dev_dbg (hubdev (hub), + "debounce: port %d: delay %dms stable %d status 0x%x\n", + port + 1, delay_time, stable_count, portstatus); + + return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; +} + +static void hub_port_connect_change(struct usb_hub *hubstate, int port, + u16 portstatus, u16 portchange) +{ + struct usb_device *hub = interface_to_usbdev(hubstate->intf); + struct usb_device *dev; + unsigned int delay = HUB_SHORT_RESET_TIME; + int i; + + dev_dbg (&hubstate->intf->dev, + "port %d, status %x, change %x, %s\n", + port + 1, portstatus, portchange, portspeed (portstatus)); + + /* Clear the connection change status */ + clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); + + /* Disconnect any existing devices under this port */ + if (hub->children[port]) + usb_disconnect(&hub->children[port]); + + /* Return now if nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + if (portstatus & USB_PORT_STAT_ENABLE) + hub_port_disable(hub, port); + + return; + } + + if (hub_port_debounce(hub, port)) { + dev_err (&hubstate->intf->dev, + "connect-debounce failed, port %d disabled\n", + port+1); + hub_port_disable(hub, port); + return; + } + + /* Some low speed devices have problems with the quick delay, so */ + /* be a bit pessimistic with those devices. RHbug #23670 */ + if (portstatus & USB_PORT_STAT_LOW_SPEED) + delay = HUB_LONG_RESET_TIME; + + down(&usb_address0_sem); + + for (i = 0; i < HUB_PROBE_TRIES; i++) { + struct usb_device *pdev; + int len; + + /* Allocate a new device struct */ + dev = usb_alloc_dev(hub, hub->bus); + if (!dev) { + dev_err (&hubstate->intf->dev, + "couldn't allocate usb_device\n"); + break; + } + + hub->children[port] = dev; + dev->state = USB_STATE_POWERED; + + /* Reset the device, and detect its speed */ + if (hub_port_reset(hub, port, dev, delay)) { + usb_put_dev(dev); + break; + } + + /* Find a new address for it */ + usb_connect(dev); + + /* Set up TT records, if needed */ + if (hub->tt) { + dev->tt = hub->tt; + dev->ttport = hub->ttport; + } else if (dev->speed != USB_SPEED_HIGH + && hub->speed == USB_SPEED_HIGH) { + dev->tt = &hubstate->tt; + dev->ttport = port + 1; + } + + /* Save readable and stable topology id, distinguishing + * devices by location for diagnostics, tools, etc. The + * string is a path along hub ports, from the root. Each + * device's id will be stable until USB is re-cabled, and + * hubs are often labeled with these port numbers. + * + * Initial size: ".NN" times five hubs + NUL = 16 bytes max + * (quite rare, since most hubs have 4-6 ports). + */ + pdev = dev->parent; + if (pdev->devpath [0] != '0') /* parent not root? */ + len = snprintf (dev->devpath, sizeof dev->devpath, + "%s.%d", pdev->devpath, port + 1); + /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ + else + len = snprintf (dev->devpath, sizeof dev->devpath, + "%d", port + 1); + if (len == sizeof dev->devpath) + dev_err (&hubstate->intf->dev, + "devpath size! usb/%03d/%03d path %s\n", + dev->bus->busnum, dev->devnum, dev->devpath); + dev_info (&hubstate->intf->dev, + "new USB device on port %d, assigned address %d\n", + port + 1, dev->devnum); + + /* put the device in the global device tree. the hub port + * is the "bus_id"; hubs show in hierarchy like bridges + */ + dev->dev.parent = dev->parent->dev.parent->parent; + + /* Run it through the hoops (find a driver, etc) */ + if (!usb_new_device(dev, &hub->dev)) + goto done; + + /* Free the configuration if there was an error */ + usb_put_dev(dev); + + /* Switch to a long reset time */ + delay = HUB_LONG_RESET_TIME; + } + + hub->children[port] = NULL; + hub_port_disable(hub, port); +done: + up(&usb_address0_sem); +} + +static void hub_events(void) +{ + unsigned long flags; + struct list_head *tmp; + struct usb_device *dev; + struct usb_hub *hub; + u16 hubstatus; + u16 hubchange; + u16 portstatus; + u16 portchange; + int i, ret; + int m=0; + /* + * We restart the list every time to avoid a deadlock with + * deleting hubs downstream from this one. This should be + * safe since we delete the hub from the event list. + * Not the most efficient, but avoids deadlocks. + */ + + while (m<5) { + m++; + spin_lock_irqsave(&hub_event_lock, flags); + + if (list_empty(&hub_event_list)) + break; + + /* Grab the next entry from the beginning of the list */ + tmp = hub_event_list.next; + + hub = list_entry(tmp, struct usb_hub, event_list); + dev = interface_to_usbdev(hub->intf); + + list_del_init(tmp); + + if (unlikely(down_trylock(&hub->khubd_sem))) + BUG(); /* never blocks, we were on list */ + + spin_unlock_irqrestore(&hub_event_lock, flags); + + if (hub->error) { + dev_dbg (&hub->intf->dev, "resetting for error %d\n", + hub->error); + + if (hub_reset(hub)) { + dev_dbg (&hub->intf->dev, + "can't reset; disconnecting\n"); + up(&hub->khubd_sem); + hub_start_disconnect(dev); + continue; + } + + hub->nerrors = 0; + hub->error = 0; + } + + for (i = 0; i < hub->descriptor->bNbrPorts; i++) { + ret = hub_port_status(dev, i, &portstatus, &portchange); + if (ret < 0) { + continue; + } + + if (portchange & USB_PORT_STAT_C_CONNECTION) { + hub_port_connect_change(hub, i, portstatus, portchange); + } else if (portchange & USB_PORT_STAT_C_ENABLE) { + dev_dbg (hubdev (dev), + "port %d enable change, status %x\n", + i + 1, portstatus); + clear_port_feature(dev, + i + 1, USB_PORT_FEAT_C_ENABLE); + + /* + * EM interference sometimes causes badly + * shielded USB devices to be shutdown by + * the hub, this hack enables them again. + * Works at least with mouse driver. + */ + if (!(portstatus & USB_PORT_STAT_ENABLE) + && (portstatus & USB_PORT_STAT_CONNECTION) + && (dev->children[i])) { + dev_err (&hub->intf->dev, + "port %i " + "disabled by hub (EMI?), " + "re-enabling...", + i + 1); + hub_port_connect_change(hub, + i, portstatus, portchange); + } + } + + if (portchange & USB_PORT_STAT_C_SUSPEND) { + dev_dbg (&hub->intf->dev, + "suspend change on port %d\n", + i + 1); + clear_port_feature(dev, + i + 1, USB_PORT_FEAT_C_SUSPEND); + } + + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + dev_err (&hub->intf->dev, + "over-current change on port %d\n", + i + 1); + clear_port_feature(dev, + i + 1, USB_PORT_FEAT_C_OVER_CURRENT); + hub_power_on(hub); + } + + if (portchange & USB_PORT_STAT_C_RESET) { + dev_dbg (&hub->intf->dev, + "reset change on port %d\n", + i + 1); + clear_port_feature(dev, + i + 1, USB_PORT_FEAT_C_RESET); + } + } /* end for i */ + + /* deal with hub status changes */ + if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) + dev_err (&hub->intf->dev, "get_hub_status failed\n"); + else { + if (hubchange & HUB_CHANGE_LOCAL_POWER) { + dev_dbg (&hub->intf->dev, "power change\n"); + clear_hub_feature(dev, C_HUB_LOCAL_POWER); + } + if (hubchange & HUB_CHANGE_OVERCURRENT) { + dev_dbg (&hub->intf->dev, "overcurrent change\n"); + wait_ms(500); /* Cool down */ + clear_hub_feature(dev, C_HUB_OVER_CURRENT); + hub_power_on(hub); + } + } + up(&hub->khubd_sem); + } /* end while (1) */ + + spin_unlock_irqrestore(&hub_event_lock, flags); +} + +static int hub_thread(void *__hub) +{ + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources + */ + + daemonize("khubd"); + allow_signal(SIGKILL); + /* Send me a signal to get me die (for debugging) */ + do { + + hub_events(); + wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); + + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); + + } while (!signal_pending(current)); + +// dbg("hub_thread exiting"); + complete_and_exit(&khubd_exited, 0); +} + +static struct usb_device_id hub_id_table [] = { + { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, + .bDeviceClass = USB_CLASS_HUB}, + { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, + .bInterfaceClass = USB_CLASS_HUB}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, hub_id_table); + +static struct usb_driver hub_driver = { + .owner = THIS_MODULE, + .name = "hub", + .probe = hub_probe, + .disconnect = hub_disconnect, + .ioctl = hub_ioctl, + .id_table = hub_id_table, +}; + +/* + * This should be a separate module. + */ +int usb_hub_init(void) +{ + pid_t pid; + + if (usb_register(&hub_driver) < 0) { + err("Unable to register USB hub driver"); + return -1; + } + + pid = kernel_thread(hub_thread, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (pid >= 0) { + khubd_pid = pid; + return 0; + } + + /* Fall through if kernel_thread failed */ + usb_deregister(&hub_driver); + err("failed to start hub_thread"); + + return -1; +} + +void usb_hub_cleanup(void) +{ + int ret; + + /* Kill the thread */ + ret = kill_proc(khubd_pid, SIGKILL, 1); + + wait_for_completion(&khubd_exited); + + /* + * Hub resources are freed for us by usb_deregister. It calls + * usb_driver_purge on every device which in turn calls that + * devices disconnect function if it is using this driver. + * The hub_disconnect function takes care of releasing the + * individual hub resources. -greg + */ + usb_deregister(&hub_driver); +} /* usb_hub_cleanup() */ + +/* + * WARNING - If a driver calls usb_reset_device, you should simulate a + * disconnect() and probe() for other interfaces you doesn't claim. This + * is left up to the driver writer right now. This insures other drivers + * have a chance to re-setup their interface. + * + * Take a look at proc_resetdevice in devio.c for some sample code to + * do this. + * Use this only from within your probe function, otherwise use + * usb_reset_device() below, which ensure proper locking + */ +int usb_physical_reset_device(struct usb_device *dev) +{ + struct usb_device *parent = dev->parent; + struct usb_device_descriptor *descriptor; + int i, ret, port = -1; + + if (!parent) { + err("attempting to reset root hub!"); + return -EINVAL; + } + + for (i = 0; i < parent->maxchild; i++) + if (parent->children[i] == dev) { + port = i; + break; + } + + if (port < 0) + return -ENOENT; + + descriptor = kmalloc(sizeof *descriptor, GFP_NOIO); + if (!descriptor) { + return -ENOMEM; + } + + down(&usb_address0_sem); + + /* Send a reset to the device */ + if (hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { + hub_port_disable(parent, port); + up(&usb_address0_sem); + kfree(descriptor); + return(-ENODEV); + } + + /* Reprogram the Address */ + ret = usb_set_address(dev); + if (ret < 0) { + err("USB device not accepting new address (error=%d)", ret); + hub_port_disable(parent, port); + up(&usb_address0_sem); + kfree(descriptor); + return ret; + } + + /* Let the SET_ADDRESS settle */ + wait_ms(10); + + up(&usb_address0_sem); + + /* + * Now we fetch the configuration descriptors for the device and + * see if anything has changed. If it has, we dump the current + * parsed descriptors and reparse from scratch. Then we leave + * the device alone for the caller to finish setting up. + * + * If nothing changed, we reprogram the configuration and then + * the alternate settings. + */ + + ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor, + sizeof(*descriptor)); + if (ret < 0) { + kfree(descriptor); + return ret; + } + + le16_to_cpus(&descriptor->bcdUSB); + le16_to_cpus(&descriptor->idVendor); + le16_to_cpus(&descriptor->idProduct); + le16_to_cpus(&descriptor->bcdDevice); + + if (RtlCompareMemory(&dev->descriptor, descriptor, sizeof(*descriptor))) { + kfree(descriptor); + usb_destroy_configuration(dev); + + ret = usb_get_device_descriptor(dev); + if (ret < sizeof(dev->descriptor)) { + if (ret < 0) + err("unable to get device %s descriptor " + "(error=%d)", dev->devpath, ret); + else + err("USB device %s descriptor short read " + "(expected %Zi, got %i)", + dev->devpath, + sizeof(dev->descriptor), ret); + + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return -EIO; + } + + ret = usb_get_configuration(dev); + if (ret < 0) { + err("unable to get configuration (error=%d)", ret); + usb_destroy_configuration(dev); + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + dev->actconfig = dev->config; + usb_set_maxpacket(dev); + + return 1; + } + + kfree(descriptor); + + ret = usb_set_configuration(dev, dev->actconfig->desc.bConfigurationValue); + if (ret < 0) { + err("failed to set dev %s active configuration (error=%d)", + dev->devpath, ret); + return ret; + } + + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf = &dev->actconfig->interface[i]; + struct usb_interface_descriptor *as; + + as = &intf->altsetting[intf->act_altsetting].desc; + ret = usb_set_interface(dev, as->bInterfaceNumber, + as->bAlternateSetting); + if (ret < 0) { + err("failed to set active alternate setting " + "for dev %s interface %d (error=%d)", + dev->devpath, i, ret); + return ret; + } + } + + return 0; +} + +int usb_reset_device(struct usb_device *udev) +{ + //struct device *gdev = &udev->dev; + int r; + + down_read(&gdev->bus->subsys.rwsem); + r = usb_physical_reset_device(udev); + up_read(&gdev->bus->subsys.rwsem); + + return r; +} + + diff --git a/reactos/drivers/usb/cromwell/core/hub.h b/reactos/drivers/usb/cromwell/core/hub.h new file mode 100644 index 00000000000..f51a9992cc6 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/hub.h @@ -0,0 +1,195 @@ +#ifndef __LINUX_HUB_H +#define __LINUX_HUB_H + +/* + * Hub protocol and driver data structures. + * + * Some of these are known to the "virtual root hub" code + * in host controller drivers. + */ +#if 0 +#include +#include +#include /* likely()/unlikely() */ +#endif +/* + * Hub request types + */ + +#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) + +/* + * Hub class requests + * See USB 2.0 spec Table 11-16 + */ +#define HUB_CLEAR_TT_BUFFER 8 +#define HUB_RESET_TT 9 +#define HUB_GET_TT_STATE 10 +#define HUB_STOP_TT 11 + +/* + * Hub Class feature numbers + * See USB 2.0 spec Table 11-17 + */ +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 + +/* + * Port feature numbers + * See USB 2.0 spec Table 11-17 + */ +#define USB_PORT_FEAT_CONNECTION 0 +#define USB_PORT_FEAT_ENABLE 1 +#define USB_PORT_FEAT_SUSPEND 2 +#define USB_PORT_FEAT_OVER_CURRENT 3 +#define USB_PORT_FEAT_RESET 4 +#define USB_PORT_FEAT_POWER 8 +#define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_HIGHSPEED 10 +#define USB_PORT_FEAT_C_CONNECTION 16 +#define USB_PORT_FEAT_C_ENABLE 17 +#define USB_PORT_FEAT_C_SUSPEND 18 +#define USB_PORT_FEAT_C_OVER_CURRENT 19 +#define USB_PORT_FEAT_C_RESET 20 +#define USB_PORT_FEAT_TEST 21 +#define USB_PORT_FEAT_INDICATOR 22 + +/* + * Hub Status and Hub Change results + * See USB 2.0 spec Table 11-19 and Table 11-20 + */ +struct usb_port_status { + __u16 wPortStatus; + __u16 wPortChange; +} __attribute__ ((packed)); + +/* + * wPortStatus bit field + * See USB 2.0 spec Table 11-21 + */ +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +/* bits 5 to 7 are reserved */ +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_TEST 0x0800 +#define USB_PORT_STAT_INDICATOR 0x1000 +/* bits 13 to 15 are reserved */ + +/* + * wPortChange bit field + * See USB 2.0 spec Table 11-22 + * Bits 0 to 4 shown, bits 5 to 15 are reserved + */ +#define USB_PORT_STAT_C_CONNECTION 0x0001 +#define USB_PORT_STAT_C_ENABLE 0x0002 +#define USB_PORT_STAT_C_SUSPEND 0x0004 +#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +#define USB_PORT_STAT_C_RESET 0x0010 + +/* + * wHubCharacteristics (masks) + * See USB 2.0 spec Table 11-13, offset 3 + */ +#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ +#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ +#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ +#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ +#define HUB_CHAR_PORTIND 0x0080 /* D7 */ + +struct usb_hub_status { + __u16 wHubStatus; + __u16 wHubChange; +} __attribute__ ((packed)); + +/* + * Hub Status & Hub Change bit masks + * See USB 2.0 spec Table 11-19 and Table 11-20 + * Bits 0 and 1 for wHubStatus and wHubChange + * Bits 2 to 15 are reserved for both + */ +#define HUB_STATUS_LOCAL_POWER 0x0001 +#define HUB_STATUS_OVERCURRENT 0x0002 +#define HUB_CHANGE_LOCAL_POWER 0x0001 +#define HUB_CHANGE_OVERCURRENT 0x0002 + + +/* + * Hub descriptor + * See USB 2.0 spec Table 11-13 + */ + +#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +#define USB_DT_HUB_NONVAR_SIZE 7 + +struct usb_hub_descriptor { + __u8 bDescLength; + __u8 bDescriptorType; + __u8 bNbrPorts; + __u16 wHubCharacteristics; + __u8 bPwrOn2PwrGood; + __u8 bHubContrCurrent; + /* add 1 bit for hub status change; round to bytes */ + __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; + __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; +} __attribute__ ((packed)); + +struct usb_device; + +/* + * As of USB 2.0, full/low speed devices are segregated into trees. + * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). + * The other type grows from high speed hubs when they connect to + * full/low speed devices using "Transaction Translators" (TTs). + * + * TTs should only be known to the hub driver, and high speed bus + * drivers (only EHCI for now). They affect periodic scheduling and + * sometimes control/bulk error recovery. + */ +struct usb_tt { + struct usb_device *hub; /* upstream highspeed hub */ + int multi; /* true means one TT per port */ + + /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ + spinlock_t lock; + struct list_head clear_list; /* of usb_tt_clear */ + struct work_struct kevent; +}; + +struct usb_tt_clear { + struct list_head clear_list; + unsigned tt; + u16 devinfo; +}; + +extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); + +struct usb_hub { + struct usb_interface *intf; /* the "real" device */ + struct urb *urb; /* for interrupt polling pipe */ + + /* buffer for urb ... 1 bit each for hub and children, rounded up */ + char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; + dma_addr_t buffer_dma; /* DMA address for buffer */ + union { + struct usb_hub_status hub; + struct usb_port_status port; + } *status; /* buffer for status reports */ + + int error; /* last reported error */ + int nerrors; /* track consecutive errors */ + + struct list_head hub_list; /* all hubs */ + struct list_head event_list; /* hubs w/data or errs ready */ + + struct usb_hub_descriptor *descriptor; /* class descriptor */ + struct semaphore khubd_sem; + struct usb_tt tt; /* Transaction Translator */ +}; + +#endif /* __LINUX_HUB_H */ diff --git a/reactos/drivers/usb/cromwell/core/makefile b/reactos/drivers/usb/cromwell/core/makefile new file mode 100644 index 00000000000..eeba46f94d7 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/makefile @@ -0,0 +1,18 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = usbcore + +TARGET_DDKLIBS = ntoskrnl.a + +TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_OBJECTS = \ + message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o \ + buffer_simple.o usb-debug.o ../sys/ros_wrapper.o \ + ../sys/linuxwrapper.o usbcore.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/cromwell/core/makefile.crom b/reactos/drivers/usb/cromwell/core/makefile.crom new file mode 100644 index 00000000000..489af5802be --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/makefile.crom @@ -0,0 +1,6 @@ + +O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o + +#O_TARGET := urb.o + +include $(TOPDIR)/Rules.make diff --git a/reactos/drivers/usb/cromwell/core/message.c b/reactos/drivers/usb/cromwell/core/message.c new file mode 100644 index 00000000000..b43a52dc4e6 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/message.c @@ -0,0 +1,1053 @@ +/* + * message.c - synchronous message handling + */ +#if 0 +#include /* for scatterlist macros */ +#include +#include +#include +#include +#include +#include +#else +#include "../usb_wrapper.h" +#endif + +#include "hcd.h" /* for usbcore internals */ + +struct usb_api_data { + wait_queue_head_t wqh; + int done; +}; + +static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) +{ + struct usb_api_data *awd = (struct usb_api_data *)urb->context; + + awd->done = 1; + wmb(); + wake_up(&awd->wqh); +} + +// Starts urb and waits for completion or timeout +static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) +{ + //DECLARE_WAITQUEUE(wait, current); // Fireball, 24Jan05 - silent gcc complaining about unused wait variable + struct usb_api_data awd; + int status; + + init_waitqueue_head(&awd.wqh); + awd.done = 0; + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&awd.wqh, &wait); + + urb->context = &awd; + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + // something went wrong + usb_free_urb(urb); + set_current_state(TASK_RUNNING); + remove_wait_queue(&awd.wqh, &wait); + return status; + } + + while (timeout && !awd.done) + { + timeout = schedule_timeout(timeout); + set_current_state(TASK_UNINTERRUPTIBLE); + rmb(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&awd.wqh, &wait); + + if (!timeout && !awd.done) { + if (urb->status != -EINPROGRESS) { /* No callback?!! */ + printk(KERN_ERR "usb: raced timeout, " + "pipe 0x%x status %d time left %d\n", + urb->pipe, urb->status, timeout); + status = urb->status; + } else { + warn("usb_control/bulk_msg: timeout"); + usb_unlink_urb(urb); // remove urb safely + status = -ETIMEDOUT; + } + } else + status = urb->status; + + if (actual_length) + *actual_length = urb->actual_length; + + usb_free_urb(urb); + return status; +} + +/*-------------------------------------------------------------------*/ +// returns status (negative) or length (positive) +int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, + struct usb_ctrlrequest *cmd, void *data, int len, int timeout) +{ + struct urb *urb; + int retv; + int length; + + urb = usb_alloc_urb(0, GFP_NOIO); + if (!urb) + return -ENOMEM; + + usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, + usb_api_blocking_completion, 0); + + retv = usb_start_wait_urb(urb, timeout, &length); + + if (retv < 0) + return retv; + else + return length; +} + +/** + * usb_control_msg - Builds a control urb, sends it off and waits for completion + * @dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @request: USB message request value + * @requesttype: USB message request type value + * @value: USB message value + * @index: USB message index value + * @data: pointer to the data to send + * @size: length in bytes of the data to send + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple control message to a specified endpoint + * and waits for the message to complete, or timeout. + * + * If successful, it returns the number of bytes transferred, otherwise a negative error number. + * + * Don't use this function from within an interrupt context, like a + * bottom half handler. If you need an asynchronous message, or need to send + * a message from within interrupt context, use usb_submit_urb() + * If a thread in your driver uses this call, make sure your disconnect() + * method can wait for it to complete. Since you don't have a handle on + * the URB used, you can't cancel the request. + */ +int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, + __u16 value, __u16 index, void *data, __u16 size, int timeout) +{ + struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); + int ret; + + if (!dr) + return -ENOMEM; + + dr->bRequestType= requesttype; + dr->bRequest = request; + dr->wValue = cpu_to_le16p(&value); + dr->wIndex = cpu_to_le16p(&index); + dr->wLength = cpu_to_le16p(&size); + + //dbg("usb_control_msg"); + + ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + + kfree(dr); + + return ret; +} + + +/** + * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion + * @usb_dev: pointer to the usb device to send the message to + * @pipe: endpoint "pipe" to send the message to + * @data: pointer to the data to send + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred in bytes + * @timeout: time in jiffies to wait for the message to complete before + * timing out (if 0 the wait is forever) + * Context: !in_interrupt () + * + * This function sends a simple bulk message to a specified endpoint + * and waits for the message to complete, or timeout. + * + * If successful, it returns 0, otherwise a negative error number. + * The number of actual bytes transferred will be stored in the + * actual_length paramater. + * + * Don't use this function from within an interrupt context, like a + * bottom half handler. If you need an asynchronous message, or need to + * send a message from within interrupt context, use usb_submit_urb() + * If a thread in your driver uses this call, make sure your disconnect() + * method can wait for it to complete. Since you don't have a handle on + * the URB used, you can't cancel the request. + */ +int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout) +{ + struct urb *urb; + + if (len < 0) + return -EINVAL; + + urb=usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, + usb_api_blocking_completion, 0); + + return usb_start_wait_urb(urb,timeout,actual_length); +} + +/*-------------------------------------------------------------------*/ +//#warning "Scatter-gather stuff disabled" +#if 0 +static void sg_clean (struct usb_sg_request *io) +{ + if (io->urbs) { + while (io->entries--) + usb_free_urb (io->urbs [io->entries]); + kfree (io->urbs); + io->urbs = 0; + } + if (io->dev->dev.dma_mask != 0) + usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); + io->dev = 0; +} + +static void sg_complete (struct urb *urb, struct pt_regs *regs) +{ + struct usb_sg_request *io = (struct usb_sg_request *) urb->context; + unsigned long flags; + + spin_lock_irqsave (&io->lock, flags); + + /* In 2.5 we require hcds' endpoint queues not to progress after fault + * reports, until the completion callback (this!) returns. That lets + * device driver code (like this routine) unlink queued urbs first, + * if it needs to, since the HC won't work on them at all. So it's + * not possible for page N+1 to overwrite page N, and so on. + * + * That's only for "hard" faults; "soft" faults (unlinks) sometimes + * complete before the HCD can get requests away from hardware, + * though never during cleanup after a hard fault. + */ + if (io->status + && (io->status != -ECONNRESET + || urb->status != -ECONNRESET) + && urb->actual_length) { + dev_err (io->dev->bus->controller, + "dev %s ep%d%s scatterlist error %d/%d\n", + io->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) ? "in" : "out", + urb->status, io->status); + // BUG (); + } + + if (urb->status && urb->status != -ECONNRESET) { + int i, found, status; + + io->status = urb->status; + + /* the previous urbs, and this one, completed already. + * unlink the later ones so they won't rx/tx bad data, + * + * FIXME don't bother unlinking urbs that haven't yet been + * submitted; those non-error cases shouldn't be syslogged + */ + for (i = 0, found = 0; i < io->entries; i++) { + if (found) { + status = usb_unlink_urb (io->urbs [i]); + if (status && status != -EINPROGRESS) + err ("sg_complete, unlink --> %d", + status); + } else if (urb == io->urbs [i]) + found = 1; + } + } + + /* on the last completion, signal usb_sg_wait() */ + io->bytes += urb->actual_length; + io->count--; + if (!io->count) + complete (&io->complete); + + spin_unlock_irqrestore (&io->lock, flags); +} + + +/** + * usb_sg_init - initializes scatterlist-based bulk/interrupt I/O request + * @io: request block being initialized. until usb_sg_wait() returns, + * treat this as a pointer to an opaque block of memory, + * @dev: the usb device that will send or receive the data + * @pipe: endpoint "pipe" used to transfer the data + * @period: polling rate for interrupt endpoints, in frames or + * (for high speed endpoints) microframes; ignored for bulk + * @sg: scatterlist entries + * @nents: how many entries in the scatterlist + * @length: how many bytes to send from the scatterlist, or zero to + * send every byte identified in the list. + * @mem_flags: SLAB_* flags affecting memory allocations in this call + * + * Returns zero for success, else a negative errno value. This initializes a + * scatter/gather request, allocating resources such as I/O mappings and urb + * memory (except maybe memory used by USB controller drivers). + * + * The request must be issued using usb_sg_wait(), which waits for the I/O to + * complete (or to be canceled) and then cleans up all resources allocated by + * usb_sg_init(). + * + * The request may be canceled with usb_sg_cancel(), either before or after + * usb_sg_wait() is called. + */ +int usb_sg_init ( + struct usb_sg_request *io, + struct usb_device *dev, + unsigned pipe, + unsigned period, + struct scatterlist *sg, + int nents, + size_t length, + int mem_flags +) +{ + int i; + int urb_flags; + int dma; + + if (!io || !dev || !sg + || usb_pipecontrol (pipe) + || usb_pipeisoc (pipe) + || nents <= 0) + return -EINVAL; + + spin_lock_init (&io->lock); + io->dev = dev; + io->pipe = pipe; + io->sg = sg; + io->nents = nents; + + /* not all host controllers use DMA (like the mainstream pci ones); + * they can use PIO (sl811) or be software over another transport. + */ + dma = (dev->dev.dma_mask != 0); + if (dma) + io->entries = usb_buffer_map_sg (dev, pipe, sg, nents); + else + io->entries = nents; + + /* initialize all the urbs we'll use */ + if (io->entries <= 0) + return io->entries; + + io->count = 0; + io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); + if (!io->urbs) + goto nomem; + + urb_flags = URB_ASYNC_UNLINK | URB_NO_DMA_MAP | URB_NO_INTERRUPT; + if (usb_pipein (pipe)) + urb_flags |= URB_SHORT_NOT_OK; + + for (i = 0; i < io->entries; i++, io->count = i) { + unsigned len; + + io->urbs [i] = usb_alloc_urb (0, mem_flags); + if (!io->urbs [i]) { + io->entries = i; + goto nomem; + } + + io->urbs [i]->dev = dev; + io->urbs [i]->pipe = pipe; + io->urbs [i]->interval = period; + io->urbs [i]->transfer_flags = urb_flags; + + io->urbs [i]->complete = sg_complete; + io->urbs [i]->context = io; + io->urbs [i]->status = -EINPROGRESS; + io->urbs [i]->actual_length = 0; + + if (dma) { + /* hc may use _only_ transfer_dma */ + io->urbs [i]->transfer_dma = sg_dma_address (sg + i); + len = sg_dma_len (sg + i); + } else { + /* hc may use _only_ transfer_buffer */ + io->urbs [i]->transfer_buffer = + page_address (sg [i].page) + sg [i].offset; + len = sg [i].length; + } + + if (length) { + len = min_t (unsigned, len, length); + length -= len; + if (length == 0) + io->entries = i + 1; + } + io->urbs [i]->transfer_buffer_length = len; + } + io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT; + + /* transaction state */ + io->status = 0; + io->bytes = 0; + init_completion (&io->complete); + return 0; + +nomem: + sg_clean (io); + return -ENOMEM; +} + + +/** + * usb_sg_wait - synchronously execute scatter/gather request + * @io: request block handle, as initialized with usb_sg_init(). + * some fields become accessible when this call returns. + * Context: !in_interrupt () + * + * This function blocks until the specified I/O operation completes. It + * leverages the grouping of the related I/O requests to get good transfer + * rates, by queueing the requests. At higher speeds, such queuing can + * significantly improve USB throughput. + * + * There are three kinds of completion for this function. + * (1) success, where io->status is zero. The number of io->bytes + * transferred is as requested. + * (2) error, where io->status is a negative errno value. The number + * of io->bytes transferred before the error is usually less + * than requested, and can be nonzero. + * (3) cancelation, a type of error with status -ECONNRESET that + * is initiated by usb_sg_cancel(). + * + * When this function returns, all memory allocated through usb_sg_init() or + * this call will have been freed. The request block parameter may still be + * passed to usb_sg_cancel(), or it may be freed. It could also be + * reinitialized and then reused. + * + * Data Transfer Rates: + * + * Bulk transfers are valid for full or high speed endpoints. + * The best full speed data rate is 19 packets of 64 bytes each + * per frame, or 1216 bytes per millisecond. + * The best high speed data rate is 13 packets of 512 bytes each + * per microframe, or 52 KBytes per millisecond. + * + * The reason to use interrupt transfers through this API would most likely + * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond + * could be transferred. That capability is less useful for low or full + * speed interrupt endpoints, which allow at most one packet per millisecond, + * of at most 8 or 64 bytes (respectively). + */ +void usb_sg_wait (struct usb_sg_request *io) +{ + int i; + unsigned long flags; + + /* queue the urbs. */ + spin_lock_irqsave (&io->lock, flags); + for (i = 0; i < io->entries && !io->status; i++) { + int retval; + + retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); + + /* after we submit, let completions or cancelations fire; + * we handshake using io->status. + */ + spin_unlock_irqrestore (&io->lock, flags); + switch (retval) { + /* maybe we retrying will recover */ + case -ENXIO: // hc didn't queue this one + case -EAGAIN: + case -ENOMEM: + retval = 0; + i--; + // FIXME: should it usb_sg_cancel() on INTERRUPT? + yield (); + break; + + /* no error? continue immediately. + * + * NOTE: to work better with UHCI (4K I/O buffer may + * need 3K of TDs) it may be good to limit how many + * URBs are queued at once; N milliseconds? + */ + case 0: + cpu_relax (); + break; + + /* fail any uncompleted urbs */ + default: + io->urbs [i]->status = retval; + dbg ("usb_sg_msg, submit --> %d", retval); + usb_sg_cancel (io); + } + spin_lock_irqsave (&io->lock, flags); + if (retval && io->status == -ECONNRESET) + io->status = retval; + } + spin_unlock_irqrestore (&io->lock, flags); + + /* OK, yes, this could be packaged as non-blocking. + * So could the submit loop above ... but it's easier to + * solve neither problem than to solve both! + */ + wait_for_completion (&io->complete); + + sg_clean (io); +} + +/** + * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait() + * @io: request block, initialized with usb_sg_init() + * + * This stops a request after it has been started by usb_sg_wait(). + * It can also prevents one initialized by usb_sg_init() from starting, + * so that call just frees resources allocated to the request. + */ +void usb_sg_cancel (struct usb_sg_request *io) +{ + unsigned long flags; + + spin_lock_irqsave (&io->lock, flags); + + /* shut everything down, if it didn't already */ + if (!io->status) { + int i; + + io->status = -ECONNRESET; + for (i = 0; i < io->entries; i++) { + int retval; + + if (!io->urbs [i]->dev) + continue; + retval = usb_unlink_urb (io->urbs [i]); + if (retval && retval != -EINPROGRESS) + warn ("usb_sg_cancel, unlink --> %d", retval); + // FIXME don't warn on "not yet submitted" error + } + } + spin_unlock_irqrestore (&io->lock, flags); +} +#endif +/*-------------------------------------------------------------------*/ + +/** + * usb_get_descriptor - issues a generic GET_DESCRIPTOR request + * @dev: the device whose descriptor is being retrieved + * @type: the descriptor type (USB_DT_*) + * @index: the number of the descriptor + * @buf: where to put the descriptor + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * Gets a USB descriptor. Convenience functions exist to simplify + * getting some types of descriptors. Use + * usb_get_device_descriptor() for USB_DT_DEVICE, + * and usb_get_string() or usb_string() for USB_DT_STRING. + * Configuration descriptors (USB_DT_CONFIG) are part of the device + * structure, at least for the current configuration. + * In addition to a number of USB-standard descriptors, some + * devices also use class-specific or vendor-specific descriptors. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) +{ + int i = 5; + int result; + + memset(buf,0,size); // Make sure we parse really received data + + while (i--) { + /* retries if the returned length was 0; flakey device */ + if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, buf, size, + HZ * USB_CTRL_GET_TIMEOUT)) > 0 + || result == -EPIPE) + break; + } + return result; +} + +/** + * usb_get_string - gets a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @langid: code for language chosen (from string descriptor zero) + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, + * in little-endian byte order). + * The usb_string() function will often be a convenient way to turn + * these strings into kernel-printable form. + * + * Strings may be referenced in device, configuration, interface, or other + * descriptors, and could also be used in vendor-specific ways. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); +} + +/** + * usb_get_device_descriptor - (re)reads the device descriptor + * @dev: the device whose device descriptor is being updated + * Context: !in_interrupt () + * + * Updates the copy of the device descriptor stored in the device structure, + * which dedicates space for this purpose. Note that several fields are + * converted to the host CPU's byte order: the USB version (bcdUSB), and + * vendors product and version fields (idVendor, idProduct, and bcdDevice). + * That lets device drivers compare against non-byteswapped constants. + * + * There's normally no need to use this call, although some devices + * will change their descriptors after events like updating firmware. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_device_descriptor(struct usb_device *dev) +{ + int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, + sizeof(dev->descriptor)); + if (ret >= 0) { + le16_to_cpus(&dev->descriptor.bcdUSB); + le16_to_cpus(&dev->descriptor.idVendor); + le16_to_cpus(&dev->descriptor.idProduct); + le16_to_cpus(&dev->descriptor.bcdDevice); + } + return ret; +} + +/** + * usb_get_status - issues a GET_STATUS call + * @dev: the device whose status is being checked + * @type: USB_RECIP_*; for device, interface, or endpoint + * @target: zero (for device), else interface or endpoint number + * @data: pointer to two bytes of bitmap data + * Context: !in_interrupt () + * + * Returns device, interface, or endpoint status. Normally only of + * interest to see if the device is self powered, or has enabled the + * remote wakeup facility; or whether a bulk or interrupt endpoint + * is halted ("stalled"). + * + * Bits in these status bitmaps are set using the SET_FEATURE request, + * and cleared using the CLEAR_FEATURE request. The usb_clear_halt() + * function should be used to clear halt ("stall") status. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns the number of bytes received on success, or else the status code + * returned by the underlying usb_control_msg() call. + */ +int usb_get_status(struct usb_device *dev, int type, int target, void *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, + HZ * USB_CTRL_GET_TIMEOUT); +} + + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally, when setting up a config +void usb_set_maxpacket(struct usb_device *dev) +{ + int i, b; + + /* NOTE: affects all endpoints _except_ ep0 */ + for (i=0; iactconfig->desc.bNumInterfaces; i++) { + struct usb_interface *ifp = dev->actconfig->interface + i; + struct usb_host_interface *as = ifp->altsetting + ifp->act_altsetting; + struct usb_host_endpoint *ep = as->endpoint; + int e; + + for (e=0; edesc.bNumEndpoints; e++) { + struct usb_endpoint_descriptor *d; + d = &ep [e].desc; + b = d->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((d->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + dev->epmaxpacketout[b] = d->wMaxPacketSize; + dev->epmaxpacketin [b] = d->wMaxPacketSize; + } + else if (usb_endpoint_out(d->bEndpointAddress)) { + if (d->wMaxPacketSize > dev->epmaxpacketout[b]) + dev->epmaxpacketout[b] = d->wMaxPacketSize; + } + else { + if (d->wMaxPacketSize > dev->epmaxpacketin [b]) + dev->epmaxpacketin [b] = d->wMaxPacketSize; + } + } + } +} + +/** + * usb_clear_halt - tells device to clear endpoint halt/stall condition + * @dev: device whose endpoint is halted + * @pipe: endpoint "pipe" being cleared + * Context: !in_interrupt () + * + * This is used to clear halt conditions for bulk and interrupt endpoints, + * as reported by URB completion status. Endpoints that are halted are + * sometimes referred to as being "stalled". Such endpoints are unable + * to transmit or receive data until the halt status is cleared. Any URBs + * queued for such an endpoint should normally be unlinked by the driver + * before clearing the halt condition, as described in sections 5.7.5 + * and 5.8.5 of the USB 2.0 spec. + * + * Note that control and isochronous endpoints don't halt, although control + * endpoints report "protocol stall" (for unsupported requests) using the + * same status code used to report a true stall. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_clear_halt(struct usb_device *dev, int pipe) +{ + int result; + int endp = usb_pipeendpoint(pipe); + + if (usb_pipein (pipe)) + endp |= USB_DIR_IN; + + /* we don't care if it wasn't halted first. in fact some devices + * (like some ibmcam model 1 units) seem to expect hosts to make + * this request for iso endpoints, which can't halt! + */ + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, + HZ * USB_CTRL_SET_TIMEOUT); + + /* don't un-halt or force to DATA0 except on success */ + if (result < 0) + return result; + + /* NOTE: seems like Microsoft and Apple don't bother verifying + * the clear "took", so some devices could lock up if you check... + * such as the Hagiwara FlashGate DUAL. So we won't bother. + * + * NOTE: make sure the logic here doesn't diverge much from + * the copy in usb-storage, for as long as we need two copies. + */ + + /* toggle was reset by the clear, then ep was reactivated */ + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); + usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); + + return 0; +} + +/** + * usb_set_interface - Makes a particular alternate setting be current + * @dev: the device whose interface is being updated + * @interface: the interface being updated + * @alternate: the setting being chosen. + * Context: !in_interrupt () + * + * This is used to enable data transfers on interfaces that may not + * be enabled by default. Not all devices support such configurability. + * Only the driver bound to an interface may change its setting. + * + * Within any given configuration, each interface may have several + * alternative settings. These are often used to control levels of + * bandwidth consumption. For example, the default setting for a high + * speed interrupt endpoint may not send more than 64 bytes per microframe, + * while interrupt transfers of up to 3KBytes per microframe are legal. + * Also, isochronous endpoints may never be part of an + * interface's default setting. To access such bandwidth, alternate + * interface settings must be made current. + * + * Note that in the Linux USB subsystem, bandwidth associated with + * an endpoint in a given alternate setting is not reserved until an URB + * is submitted that needs that bandwidth. Some other operating systems + * allocate bandwidth early, when a configuration is chosen. + * + * This call is synchronous, and may not be used in an interrupt context. + * Also, drivers must not change altsettings while urbs are scheduled for + * endpoints in that interface; all such urbs must first be completed + * (perhaps forced by unlinking). + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_set_interface(struct usb_device *dev, int interface, int alternate) +{ + struct usb_interface *iface; + struct usb_host_interface *iface_as; + int i, ret; + void (*disable)(struct usb_device *, int) = dev->bus->op->disable; + + iface = usb_ifnum_to_if(dev, interface); + if (!iface) { + warn("selecting invalid interface %d", interface); + return -EINVAL; + } + + /* 9.4.10 says devices don't need this, if the interface + only has one alternate setting */ + if (iface->num_altsetting == 1) { + dbg("ignoring set_interface for dev %d, iface %d, alt %d", + dev->devnum, interface, alternate); + return 0; + } + + if (alternate < 0 || alternate >= iface->num_altsetting) + return -EINVAL; + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, + iface->altsetting[alternate] + .desc.bAlternateSetting, + interface, NULL, 0, HZ * 5)) < 0) + return ret; + + /* FIXME drivers shouldn't need to replicate/bugfix the logic here + * when they implement async or easily-killable versions of this or + * other "should-be-internal" functions (like clear_halt). + * should hcd+usbcore postprocess control requests? + */ + + /* prevent submissions using previous endpoint settings */ + iface_as = iface->altsetting + iface->act_altsetting; + for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { + u8 ep = iface_as->endpoint [i].desc.bEndpointAddress; + int out = !(ep & USB_DIR_IN); + + /* clear out hcd state, then usbcore state */ + if (disable) + disable (dev, ep); + ep &= USB_ENDPOINT_NUMBER_MASK; + (out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0; + } + iface->act_altsetting = alternate; + + /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as + * + * Note: + * Despite EP0 is always present in all interfaces/AS, the list of + * endpoints from the descriptor does not contain EP0. Due to its + * omnipresence one might expect EP0 being considered "affected" by + * any SetInterface request and hence assume toggles need to be reset. + * However, EP0 toggles are re-synced for every individual transfer + * during the SETUP stage - hence EP0 toggles are "don't care" here. + * (Likewise, EP0 never "halts" on well designed devices.) + */ + + iface_as = &iface->altsetting[alternate]; + for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { + u8 ep = iface_as->endpoint[i].desc.bEndpointAddress; + int out = !(ep & USB_DIR_IN); + + ep &= USB_ENDPOINT_NUMBER_MASK; + usb_settoggle (dev, ep, out, 0); + (out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep] + = iface_as->endpoint [i].desc.wMaxPacketSize; + usb_endpoint_running (dev, ep, out); + } + + return 0; +} + +/** + * usb_set_configuration - Makes a particular device setting be current + * @dev: the device whose configuration is being updated + * @configuration: the configuration being chosen. + * Context: !in_interrupt () + * + * This is used to enable non-default device modes. Not all devices + * support this kind of configurability. By default, configuration + * zero is selected after enumeration; many devices only have a single + * configuration. + * + * USB devices may support one or more configurations, which affect + * power consumption and the functionality available. For example, + * the default configuration is limited to using 100mA of bus power, + * so that when certain device functionality requires more power, + * and the device is bus powered, that functionality will be in some + * non-default device configuration. Other device modes may also be + * reflected as configuration options, such as whether two ISDN + * channels are presented as independent 64Kb/s interfaces or as one + * bonded 128Kb/s interface. + * + * Note that USB has an additional level of device configurability, + * associated with interfaces. That configurability is accessed using + * usb_set_interface(). + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns zero on success, or else the status code returned by the + * underlying usb_control_msg() call. + */ +int usb_set_configuration(struct usb_device *dev, int configuration) +{ + int i, ret; + struct usb_host_config *cp = NULL; + void (*disable)(struct usb_device *, int) = dev->bus->op->disable; + + for (i=0; idescriptor.bNumConfigurations; i++) { + if (dev->config[i].desc.bConfigurationValue == configuration) { + cp = &dev->config[i]; + break; + } + } + if ((!cp && configuration != 0) || (cp && configuration == 0)) { + warn("selecting invalid configuration %d", configuration); + return -EINVAL; + } + + /* if it's already configured, clear out old state first. */ + if (dev->state != USB_STATE_ADDRESS && disable) { + for (i = 1 /* skip ep0 */; i < 15; i++) { + disable (dev, i); + disable (dev, USB_DIR_IN | i); + } + } + dev->toggle[0] = dev->toggle[1] = 0; + dev->halted[0] = dev->halted[1] = 0; + dev->state = USB_STATE_ADDRESS; + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, + NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) + return ret; + if (configuration) + dev->state = USB_STATE_CONFIGURED; + dev->actconfig = cp; + + /* reset more hc/hcd endpoint state */ + usb_set_maxpacket(dev); + + return 0; +} + + +/** + * usb_string - returns ISO 8859-1 version of a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * This converts the UTF-16LE encoded strings returned by devices, from + * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones + * that are more usable in most kernel contexts. Note that all characters + * in the chosen descriptor that can't be encoded using ISO-8859-1 + * are converted to the question mark ("?") character, and this function + * chooses strings in the first language supported by the device. + * + * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit + * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, + * and is appropriate for use many uses of English and several other + * Western European languages. (But it doesn't include the "Euro" symbol.) + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns length of the string (>= 0) or usb_control_msg status (< 0). + */ +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + unsigned char *tbuf; + int err, len; + unsigned int u, idx; + + if (size <= 0 || !buf || !index) + return -EINVAL; + buf[0] = 0; + tbuf = kmalloc(256, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + /* get langid for strings if it's not yet known */ + if (!dev->have_langid) { + err = usb_get_string(dev, 0, 0, tbuf, 4); + if (err < 0) { + err("error getting string descriptor 0 (error=%d)", err); + goto errout; + } else if (tbuf[0] < 4) { + err("string descriptor 0 too short"); + err = -EINVAL; + goto errout; + } else { + dev->have_langid = -1; + dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + /* always use the first langid listed */ + dbg("USB device number %d default language ID 0x%x", + dev->devnum, dev->string_langid); + } + } + + /* + * ask for the length of the string + */ + + err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); + if(err<2) + goto errout; + len=tbuf[0]; + + err = usb_get_string(dev, dev->string_langid, index, tbuf, len); + if (err < 0) + goto errout; + + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non ISO-8859-1 character */ + else + buf[idx++] = tbuf[u]; + } + buf[idx] = 0; + err = idx; + + errout: + kfree(tbuf); + return err; +} + +// synchronous request completion model +EXPORT_SYMBOL(usb_control_msg); +EXPORT_SYMBOL(usb_bulk_msg); + +EXPORT_SYMBOL(usb_sg_init); +EXPORT_SYMBOL(usb_sg_cancel); +EXPORT_SYMBOL(usb_sg_wait); + +// synchronous control message convenience routines +EXPORT_SYMBOL(usb_get_descriptor); +EXPORT_SYMBOL(usb_get_device_descriptor); +EXPORT_SYMBOL(usb_get_status); +EXPORT_SYMBOL(usb_get_string); +EXPORT_SYMBOL(usb_string); +EXPORT_SYMBOL(usb_clear_halt); +EXPORT_SYMBOL(usb_set_configuration); +EXPORT_SYMBOL(usb_set_interface); + diff --git a/reactos/drivers/usb/cromwell/core/urb.c b/reactos/drivers/usb/cromwell/core/urb.c new file mode 100644 index 00000000000..08b691fd1ff --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/urb.c @@ -0,0 +1,398 @@ +#include "../usb_wrapper.h" +#include "hcd.h" + +/** + * usb_init_urb - initializes a urb so that it can be used by a USB driver + * @urb: pointer to the urb to initialize + * + * Initializes a urb so that the USB subsystem can use it properly. + * + * If a urb is created with a call to usb_alloc_urb() it is not + * necessary to call this function. Only use this if you allocate the + * space for a struct urb on your own. If you call this function, be + * careful when freeing the memory for your urb that it is no longer in + * use by the USB core. + * + * Only use this function if you _really_ understand what you are doing. + */ +void STDCALL usb_init_urb(struct urb *urb) +{ + if (urb) { + memset(urb, 0, sizeof(*urb)); + urb->count = (atomic_t)ATOMIC_INIT(1); + spin_lock_init(&urb->lock); + } +} + +/** + * usb_alloc_urb - creates a new urb for a USB driver to use + * @iso_packets: number of iso packets for this urb + * @mem_flags: the type of memory to allocate, see kmalloc() for a list of + * valid options for this. + * + * Creates an urb for the USB driver to use, initializes a few internal + * structures, incrementes the usage counter, and returns a pointer to it. + * + * If no memory is available, NULL is returned. + * + * If the driver want to use this urb for interrupt, control, or bulk + * endpoints, pass '0' as the number of iso packets. + * + * The driver must call usb_free_urb() when it is finished with the urb. + */ +struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags) +{ + struct urb *urb; + + urb = (struct urb *)kmalloc(sizeof(struct urb) + + iso_packets * sizeof(struct usb_iso_packet_descriptor), + mem_flags); + if (!urb) { + err("alloc_urb: kmalloc failed"); + return NULL; + } + usb_init_urb(urb); + return urb; +} + +/** + * usb_free_urb - frees the memory used by a urb when all users of it are finished + * @urb: pointer to the urb to free + * + * Must be called when a user of a urb is finished with it. When the last user + * of the urb calls this function, the memory of the urb is freed. + * + * Note: The transfer buffer associated with the urb is not freed, that must be + * done elsewhere. + */ +void STDCALL usb_free_urb(struct urb *urb) +{ + if (urb) + if (atomic_dec_and_test(&urb->count)) + { + kfree(urb); + } +} + +/** + * usb_get_urb - increments the reference count of the urb + * @urb: pointer to the urb to modify + * + * This must be called whenever a urb is transferred from a device driver to a + * host controller driver. This allows proper reference counting to happen + * for urbs. + * + * A pointer to the urb with the incremented reference counter is returned. + */ +struct urb STDCALL * usb_get_urb(struct urb *urb) +{ + if (urb) { + atomic_inc(&urb->count); + return urb; + } else + return NULL; +} + + +/*-------------------------------------------------------------------*/ + +/** + * usb_submit_urb - issue an asynchronous transfer request for an endpoint + * @urb: pointer to the urb describing the request + * @mem_flags: the type of memory to allocate, see kmalloc() for a list + * of valid options for this. + * + * This submits a transfer request, and transfers control of the URB + * describing that request to the USB subsystem. Request completion will + * be indicated later, asynchronously, by calling the completion handler. + * The three types of completion are success, error, and unlink + * (also called "request cancellation"). + * URBs may be submitted in interrupt context. + * + * The caller must have correctly initialized the URB before submitting + * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are + * available to ensure that most fields are correctly initialized, for + * the particular kind of transfer, although they will not initialize + * any transfer flags. + * + * Successful submissions return 0; otherwise this routine returns a + * negative error number. If the submission is successful, the complete() + * callback from the urb will be called exactly once, when the USB core and + * host controller driver are finished with the urb. When the completion + * function is called, control of the URB is returned to the device + * driver which issued the request. The completion handler may then + * immediately free or reuse that URB. + * + * For control endpoints, the synchronous usb_control_msg() call is + * often used (in non-interrupt context) instead of this call. + * That is often used through convenience wrappers, for the requests + * that are standardized in the USB 2.0 specification. For bulk + * endpoints, a synchronous usb_bulk_msg() call is available. + * + * Request Queuing: + * + * URBs may be submitted to endpoints before previous ones complete, to + * minimize the impact of interrupt latencies and system overhead on data + * throughput. This is required for continuous isochronous data streams, + * and may also be required for some kinds of interrupt transfers. Such + * queueing also maximizes bandwidth utilization by letting USB controllers + * start work on later requests before driver software has finished the + * completion processing for earlier requests. + * + * Bulk and Isochronous URBs may always be queued. At this writing, all + * mainstream host controller drivers support queueing for control and + * interrupt transfer requests. + * + * Reserved Bandwidth Transfers: + * + * Periodic transfers (interrupt or isochronous) are performed repeatedly, + * using the interval specified in the urb. Submitting the first urb to + * the endpoint reserves the bandwidth necessary to make those transfers. + * If the USB subsystem can't allocate sufficient bandwidth to perform + * the periodic request, submitting such a periodic request should fail. + * + * Device drivers must explicitly request that repetition, by ensuring that + * some URB is always on the endpoint's queue (except possibly for short + * periods during completion callacks). When there is no longer an urb + * queued, the endpoint's bandwidth reservation is canceled. This means + * drivers can use their completion handlers to ensure they keep bandwidth + * they need, by reinitializing and resubmitting the just-completed urb + * until the driver longer needs that periodic bandwidth. + * + * Memory Flags: + * + * The general rules for how to decide which mem_flags to use + * are the same as for kmalloc. There are four + * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and + * GFP_ATOMIC. + * + * GFP_NOFS is not ever used, as it has not been implemented yet. + * + * GFP_ATOMIC is used when + * (a) you are inside a completion handler, an interrupt, bottom half, + * tasklet or timer, or + * (b) you are holding a spinlock or rwlock (does not apply to + * semaphores), or + * (c) current->state != TASK_RUNNING, this is the case only after + * you've changed it. + * + * GFP_NOIO is used in the block io path and error handling of storage + * devices. + * + * All other situations use GFP_KERNEL. + * + * Some more specific rules for mem_flags can be inferred, such as + * (1) start_xmit, timeout, and receive methods of network drivers must + * use GFP_ATOMIC (they are called with a spinlock held); + * (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also + * called with a spinlock held); + * (3) If you use a kernel thread with a network driver you must use + * GFP_NOIO, unless (b) or (c) apply; + * (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c) + * apply or your are in a storage driver's block io path; + * (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and + * (6) changing firmware on a running storage or net device uses + * GFP_NOIO, unless b) or c) apply + * + */ +int STDCALL usb_submit_urb(struct urb *urb, int mem_flags) +{ + int pipe, temp, max; + struct usb_device *dev; + struct usb_operations *op; + int is_out; +// printk("sub dev %p bus %p num %i op %p sub %p\n", +// urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb); + if (!urb || urb->hcpriv || !urb->complete) + return -EINVAL; + if (!(dev = urb->dev) || + (dev->state < USB_STATE_DEFAULT) || + (!dev->bus) || (dev->devnum <= 0)) + return -ENODEV; + if (!(op = dev->bus->op) || !op->submit_urb) + return -ENODEV; + + urb->status = -EINPROGRESS; + urb->actual_length = 0; + urb->bandwidth = 0; + + /* Lots of sanity checks, so HCDs can rely on clean data + * and don't need to duplicate tests + */ + pipe = urb->pipe; + temp = usb_pipetype (pipe); + is_out = usb_pipeout (pipe); + + if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) + return -ENODEV; + + /* (actually HCDs may need to duplicate this, endpoint might yet + * stall due to queued bulk/intr transactions that complete after + * we check) + */ + if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out)) + return -EPIPE; + + /* FIXME there should be a sharable lock protecting us against + * config/altsetting changes and disconnects, kicking in here. + * (here == before maxpacket, and eventually endpoint type, + * checks get made.) + */ + + max = usb_maxpacket (dev, pipe, is_out); + if (max <= 0) { + dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)", + __FUNCTION__, + usb_pipeendpoint (pipe), is_out ? "OUT" : "IN", + dev->bus->bus_name, dev->devpath, + max); + return -EMSGSIZE; + } + + /* periodic transfers limit size per frame/uframe, + * but drivers only control those sizes for ISO. + * while we're checking, initialize return status. + */ + if (temp == PIPE_ISOCHRONOUS) { + int n, len; + + /* "high bandwidth" mode, 1-3 packets/uframe? */ + if (dev->speed == USB_SPEED_HIGH) { + int mult = 1 + ((max >> 11) & 0x03); + max &= 0x03ff; + max *= mult; + } + + if (urb->number_of_packets <= 0) + return -EINVAL; + for (n = 0; n < urb->number_of_packets; n++) { + len = urb->iso_frame_desc [n].length; + if (len < 0 || len > max) + return -EMSGSIZE; + urb->iso_frame_desc [n].status = -EXDEV; + urb->iso_frame_desc [n].actual_length = 0; + } + } + + /* the I/O buffer must be mapped/unmapped, except when length=0 */ + if (urb->transfer_buffer_length < 0) + return -EMSGSIZE; + +#ifdef DEBUG + /* stuff that drivers shouldn't do, but which shouldn't + * cause problems in HCDs if they get it wrong. + */ + { + unsigned int orig_flags = urb->transfer_flags; + unsigned int allowed; + + /* enforce simple/standard policy */ + allowed = URB_ASYNC_UNLINK; // affects later unlinks + allowed |= URB_NO_DMA_MAP; + allowed |= URB_NO_INTERRUPT; + switch (temp) { + case PIPE_BULK: + if (is_out) + allowed |= URB_ZERO_PACKET; + /* FALLTHROUGH */ + case PIPE_CONTROL: + allowed |= URB_NO_FSBR; /* only affects UHCI */ + /* FALLTHROUGH */ + default: /* all non-iso endpoints */ + if (!is_out) + allowed |= URB_SHORT_NOT_OK; + break; + case PIPE_ISOCHRONOUS: + allowed |= URB_ISO_ASAP; + break; + } + urb->transfer_flags &= allowed; + + /* fail if submitter gave bogus flags */ + if (urb->transfer_flags != orig_flags) { + err ("BOGUS urb flags, %x --> %x", + orig_flags, urb->transfer_flags); + return -EINVAL; + } + } +#endif + /* + * Force periodic transfer intervals to be legal values that are + * a power of two (so HCDs don't need to). + * + * FIXME want bus->{intr,iso}_sched_horizon values here. Each HC + * supports different values... this uses EHCI/UHCI defaults (and + * EHCI can use smaller non-default values). + */ + switch (temp) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + /* too small? */ + if (urb->interval <= 0) + return -EINVAL; + /* too big? */ + switch (dev->speed) { + case USB_SPEED_HIGH: /* units are microframes */ + // NOTE usb handles 2^15 + if (urb->interval > (1024 * 8)) + urb->interval = 1024 * 8; + temp = 1024 * 8; + break; + case USB_SPEED_FULL: /* units are frames/msec */ + case USB_SPEED_LOW: + if (temp == PIPE_INTERRUPT) { + if (urb->interval > 255) + return -EINVAL; + // NOTE ohci only handles up to 32 + temp = 128; + } else { + if (urb->interval > 1024) + urb->interval = 1024; + // NOTE usb and ohci handle up to 2^15 + temp = 1024; + } + break; + default: + return -EINVAL; + } + /* power of two? */ + while (temp > urb->interval) + temp >>= 1; + urb->interval = temp; + } + + return op->submit_urb (urb, mem_flags); +} + +/*-------------------------------------------------------------------*/ + +/** + * usb_unlink_urb - abort/cancel a transfer request for an endpoint + * @urb: pointer to urb describing a previously submitted request + * + * This routine cancels an in-progress request. The requests's + * completion handler will be called with a status code indicating + * that the request has been canceled, and that control of the URB + * has been returned to that device driver. + * + * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this + * request is synchronous. Success is indicated by returning zero, + * at which time the urb will have been unlinked, + * and the completion function will see status -ENOENT. Failure is + * indicated by any other return value. This mode may not be used + * when unlinking an urb from an interrupt context, such as a bottom + * half or a completion handler, + * + * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this + * request is asynchronous. Success is indicated by returning -EINPROGRESS, + * at which time the urb will normally not have been unlinked, + * and the completion function will see status -ECONNRESET. Failure is + * indicated by any other return value. + */ +int STDCALL usb_unlink_urb(struct urb *urb) +{ + if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) + return urb->dev->bus->op->unlink_urb(urb); + else + return -ENODEV; +} diff --git a/reactos/drivers/usb/cromwell/core/usb-debug.c b/reactos/drivers/usb/cromwell/core/usb-debug.c new file mode 100644 index 00000000000..a2a3404f4c6 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usb-debug.c @@ -0,0 +1,206 @@ +/* + * debug.c - USB debug helper routines. + * + * I just want these out of the way where they aren't in your + * face, but so that you can still use them.. + */ +#define CONFIG_USB_DEBUG +#if 0 +#include +#include +#include +#include +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include +#else +#include "../usb_wrapper.h" +#endif + +static void usb_show_endpoint(struct usb_host_endpoint *endpoint) +{ + usb_show_endpoint_descriptor(&endpoint->desc); +} + +static void usb_show_interface(struct usb_host_interface *altsetting) +{ + int i; + + usb_show_interface_descriptor(&altsetting->desc); + + for (i = 0; i < altsetting->desc.bNumEndpoints; i++) + usb_show_endpoint(altsetting->endpoint + i); +} + +static void usb_show_config(struct usb_host_config *config) +{ + int i, j; + struct usb_interface *ifp; + + usb_show_config_descriptor(&config->desc); + for (i = 0; i < config->desc.bNumInterfaces; i++) { + ifp = config->interface + i; + + if (!ifp) + break; + + printk("\n Interface: %d\n", i); + for (j = 0; j < ifp->num_altsetting; j++) + usb_show_interface(ifp->altsetting + j); + } +} + +void usb_show_device(struct usb_device *dev) +{ + int i; + + usb_show_device_descriptor(&dev->descriptor); + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + usb_show_config(dev->config + i); +} + +/* + * Parse and show the different USB descriptors. + */ +void usb_show_device_descriptor(struct usb_device_descriptor *desc) +{ + if (!desc) + { + printk("Invalid USB device descriptor (NULL POINTER)\n"); + return; + } + printk(" Length = %2d%s\n", desc->bLength, + desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)"); + printk(" DescriptorType = %02x\n", desc->bDescriptorType); + + printk(" USB version = %x.%02x\n", + desc->bcdUSB >> 8, desc->bcdUSB & 0xff); + printk(" Vendor:Product = %04x:%04x\n", + desc->idVendor, desc->idProduct); + printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0); + printk(" NumConfigurations = %d\n", desc->bNumConfigurations); + printk(" Device version = %x.%02x\n", + desc->bcdDevice >> 8, desc->bcdDevice & 0xff); + + printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n", + desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol); + switch (desc->bDeviceClass) { + case 0: + printk(" Per-interface classes\n"); + break; + case USB_CLASS_AUDIO: + printk(" Audio device class\n"); + break; + case USB_CLASS_COMM: + printk(" Communications class\n"); + break; + case USB_CLASS_HID: + printk(" Human Interface Devices class\n"); + break; + case USB_CLASS_PRINTER: + printk(" Printer device class\n"); + break; + case USB_CLASS_MASS_STORAGE: + printk(" Mass Storage device class\n"); + break; + case USB_CLASS_HUB: + printk(" Hub device class\n"); + break; + case USB_CLASS_VENDOR_SPEC: + printk(" Vendor class\n"); + break; + default: + printk(" Unknown class\n"); + } +} + +void usb_show_config_descriptor(struct usb_config_descriptor *desc) +{ + printk("Configuration:\n"); + printk(" bLength = %4d%s\n", desc->bLength, + desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)"); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" wTotalLength = %04x\n", desc->wTotalLength); + printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces); + printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue); + printk(" iConfiguration = %02x\n", desc->iConfiguration); + printk(" bmAttributes = %02x\n", desc->bmAttributes); + printk(" bMaxPower = %4dmA\n", desc->bMaxPower * 2); +} + +void usb_show_interface_descriptor(struct usb_interface_descriptor *desc) +{ + printk(" Alternate Setting: %2d\n", desc->bAlternateSetting); + printk(" bLength = %4d%s\n", desc->bLength, + desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)"); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber); + printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting); + printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints); + printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n", + desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); + printk(" iInterface = %02x\n", desc->iInterface); +} + +void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc) +{ + char *LengthCommentString = (desc->bLength == + USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength == + USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)"; + char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" }; + + printk(" Endpoint:\n"); + printk(" bLength = %4d%s\n", + desc->bLength, LengthCommentString); + printk(" bDescriptorType = %02x\n", desc->bDescriptorType); + printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress, + (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL ? "i/o" : + (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out"); + printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes, + EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]); + printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize); + printk(" bInterval = %02x\n", desc->bInterval); + + /* Audio extensions to the endpoint descriptor */ + if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) { + printk(" bRefresh = %02x\n", desc->bRefresh); + printk(" bSynchAddress = %02x\n", desc->bSynchAddress); + } +} + +void usb_show_string(struct usb_device *dev, char *id, int index) +{ + char *buf; + + if (!index) + return; + if (!(buf = kmalloc(256, GFP_KERNEL))) + return; + if (usb_string(dev, index, buf, 256) > 0) + dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf); + kfree(buf); +} + +void usb_dump_urb (struct urb *urb) +{ + printk ("urb :%p\n", urb); + printk ("dev :%p\n", urb->dev); + printk ("pipe :%08X\n", urb->pipe); + printk ("status :%d\n", urb->status); + printk ("transfer_flags :%08X\n", urb->transfer_flags); + printk ("transfer_buffer :%p\n", urb->transfer_buffer); + printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length); + printk ("actual_length :%d\n", urb->actual_length); + printk ("setup_packet :%p\n", urb->setup_packet); + printk ("start_frame :%d\n", urb->start_frame); + printk ("number_of_packets :%d\n", urb->number_of_packets); + printk ("interval :%d\n", urb->interval); + printk ("error_count :%d\n", urb->error_count); + printk ("context :%p\n", urb->context); + printk ("complete :%p\n", urb->complete); +} + diff --git a/reactos/drivers/usb/cromwell/core/usb.c b/reactos/drivers/usb/cromwell/core/usb.c new file mode 100644 index 00000000000..4206935def1 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usb.c @@ -0,0 +1,1596 @@ +/* + * drivers/usb/usb.c + * + * (C) Copyright Linus Torvalds 1999 + * (C) Copyright Johannes Erdfelt 1999-2001 + * (C) Copyright Andreas Gal 1999 + * (C) Copyright Gregory P. Smith 1999 + * (C) Copyright Deti Fliegl 1999 (new USB architecture) + * (C) Copyright Randy Dunlap 2000 + * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id, + more docs, etc) + * (C) Copyright Yggdrasil Computing, Inc. 2000 + * (usb_device_id matching changes by Adam J. Richter) + * (C) Copyright Greg Kroah-Hartman 2002-2003 + * + * NOTE! This is not actually a driver at all, rather this is + * just a collection of helper routines that implement the + * generic USB things that the real drivers can use.. + * + * Think of this as a "USB library" rather than anything else. + * It should be considered a slave, with no callbacks. Callbacks + * are evil. + */ + +#if 0 +#include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include +#include +#include +#include +#include /* for in_interrupt() */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "hcd.h" +#include "usb.h" +#else +#include "../usb_wrapper.h" +#include "hcd.h" +#endif + + +extern int usb_hub_init(void); +extern void usb_hub_cleanup(void); +extern int usb_major_init(void); +extern void usb_major_cleanup(void); + + +int nousb; /* Disable USB when built into kernel image */ + /* Not honored on modular build */ + + +static int generic_probe (struct device *dev) +{ + return 0; +} +static int generic_remove (struct device *dev) +{ + return 0; +} + +static struct device_driver usb_generic_driver = { + .name = "usb", + .bus = &usb_bus_type, + .probe = generic_probe, + .remove = generic_remove, +}; + +static int usb_generic_driver_data; + +/* needs to be called with BKL held */ +int usb_device_probe(struct device *dev) +{ + struct usb_interface * intf = to_usb_interface(dev); + struct usb_driver * driver = to_usb_driver(dev->driver); + const struct usb_device_id *id; + int error = -ENODEV; + + dev_dbg(dev, "%s\n", __FUNCTION__); + + if (!driver->probe) + return error; + + id = usb_match_id (intf, driver->id_table); + if (id) { + dev_dbg (dev, "%s - got id\n", __FUNCTION__); + down (&driver->serialize); + error = driver->probe (intf, id); + up (&driver->serialize); + } + if (!error) + intf->driver = driver; + + return error; +} + +int usb_device_remove(struct device *dev) +{ + struct usb_interface *intf; + struct usb_driver *driver; + + intf = list_entry(dev,struct usb_interface,dev); + driver = to_usb_driver(dev->driver); + + down(&driver->serialize); + + if (intf->driver && intf->driver->disconnect) + intf->driver->disconnect(intf); + + /* if driver->disconnect didn't release the interface */ + if (intf->driver) + usb_driver_release_interface(driver, intf); + + up(&driver->serialize); + + return 0; +} + +/** + * usb_register - register a USB driver + * @new_driver: USB operations for the driver + * + * Registers a USB driver with the USB core. The list of unattached + * interfaces will be rescanned whenever a new driver is added, allowing + * the new driver to attach to any recognized devices. + * Returns a negative error code on failure and 0 on success. + * + * NOTE: if you want your driver to use the USB major number, you must call + * usb_register_dev() to enable that functionality. This function no longer + * takes care of that. + */ +int usb_register(struct usb_driver *new_driver) +{ + int retval = 0; + + if (nousb) + return -ENODEV; + + new_driver->driver.name = (char *)new_driver->name; + new_driver->driver.bus = &usb_bus_type; + new_driver->driver.probe = usb_device_probe; + new_driver->driver.remove = usb_device_remove; + + init_MUTEX(&new_driver->serialize); + + retval = driver_register(&new_driver->driver); + + if (!retval) { + info("registered new driver %s", new_driver->name); + usbfs_update_special(); + } else { + err("problem %d when registering driver %s", + retval, new_driver->name); + } + + return retval; +} + +/** + * usb_deregister - unregister a USB driver + * @driver: USB operations of the driver to unregister + * Context: !in_interrupt (), must be called with BKL held + * + * Unlinks the specified driver from the internal USB driver list. + * + * NOTE: If you called usb_register_dev(), you still need to call + * usb_deregister_dev() to clean up your driver's allocated minor numbers, + * this * call will no longer do it for you. + */ +void usb_deregister(struct usb_driver *driver) +{ + info("deregistering driver %s", driver->name); + + driver_unregister (&driver->driver); + + usbfs_update_special(); +} + +/** + * usb_ifnum_to_if - get the interface object with a given interface number (usbcore-internal) + * @dev: the device whose current configuration is considered + * @ifnum: the desired interface + * + * This walks the device descriptor for the currently active configuration + * and returns a pointer to the interface with that particular interface + * number, or null. + * + * Note that configuration descriptors are not required to assign interface + * numbers sequentially, so that it would be incorrect to assume that + * the first interface in that descriptor corresponds to interface zero. + * This routine helps device drivers avoid such mistakes. + * However, you should make sure that you do the right thing with any + * alternate settings available for this interfaces. + */ +struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) +{ + int i; + + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) + if (dev->actconfig->interface[i].altsetting[0] + .desc.bInterfaceNumber == ifnum) + return &dev->actconfig->interface[i]; + + return NULL; +} + +/** + * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number + * @dev: the device whose current configuration is considered + * @epnum: the desired endpoint + * + * This walks the device descriptor for the currently active configuration, + * and returns a pointer to the endpoint with that particular endpoint + * number, or null. + * + * Note that interface descriptors are not required to assign endpont + * numbers sequentially, so that it would be incorrect to assume that + * the first endpoint in that descriptor corresponds to interface zero. + * This routine helps device drivers avoid such mistakes. + */ +struct usb_endpoint_descriptor * +usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) +{ + int i, j, k; + + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) + for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++) + for (k = 0; k < dev->actconfig->interface[i] + .altsetting[j].desc.bNumEndpoints; k++) + if (epnum == dev->actconfig->interface[i] + .altsetting[j].endpoint[k] + .desc.bEndpointAddress) + return &dev->actconfig->interface[i] + .altsetting[j].endpoint[k] + .desc; + + return NULL; +} + +/** + * usb_driver_claim_interface - bind a driver to an interface + * @driver: the driver to be bound + * @iface: the interface to which it will be bound + * @priv: driver data associated with that interface + * + * This is used by usb device drivers that need to claim more than one + * interface on a device when probing (audio and acm are current examples). + * No device driver should directly modify internal usb_interface or + * usb_device structure members. + * + * Few drivers should need to use this routine, since the most natural + * way to bind to an interface is to return the private data from + * the driver's probe() method. Any driver that does use this must + * first be sure that no other driver has claimed the interface, by + * checking with usb_interface_claimed(). + */ +void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) +{ + if (!iface || !driver) + return; + + // FIXME change API to report an error in this case + if (iface->driver) + err ("%s driver booted %s off interface %p", + driver->name, iface->driver->name, iface); + else + dbg("%s driver claimed interface %p", driver->name, iface); + + iface->driver = driver; + usb_set_intfdata(iface, priv); +} + +/** + * usb_interface_claimed - returns true iff an interface is claimed + * @iface: the interface being checked + * + * This should be used by drivers to check other interfaces to see if + * they are available or not. If another driver has claimed the interface, + * they may not claim it. Otherwise it's OK to claim it using + * usb_driver_claim_interface(). + * + * Returns true (nonzero) iff the interface is claimed, else false (zero). + */ +int usb_interface_claimed(struct usb_interface *iface) +{ + if (!iface) + return 0; + + return (iface->driver != NULL); +} /* usb_interface_claimed() */ + +/** + * usb_driver_release_interface - unbind a driver from an interface + * @driver: the driver to be unbound + * @iface: the interface from which it will be unbound + * + * This should be used by drivers to release their claimed interfaces. + * It is normally called in their disconnect() methods, and only for + * drivers that bound to more than one interface in their probe(). + * + * When the USB subsystem disconnect()s a driver from some interface, + * it automatically invokes this method for that interface. That + * means that even drivers that used usb_driver_claim_interface() + * usually won't need to call this. + */ +void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface) +{ + /* this should never happen, don't release something that's not ours */ + if (!iface || iface->driver != driver) + return; + + iface->driver = NULL; + usb_set_intfdata(iface, NULL); +} + +/** + * usb_match_id - find first usb_device_id matching device or interface + * @interface: the interface of interest + * @id: array of usb_device_id structures, terminated by zero entry + * + * usb_match_id searches an array of usb_device_id's and returns + * the first one matching the device or interface, or null. + * This is used when binding (or rebinding) a driver to an interface. + * Most USB device drivers will use this indirectly, through the usb core, + * but some layered driver frameworks use it directly. + * These device tables are exported with MODULE_DEVICE_TABLE, through + * modutils and "modules.usbmap", to support the driver loading + * functionality of USB hotplugging. + * + * What Matches: + * + * The "match_flags" element in a usb_device_id controls which + * members are used. If the corresponding bit is set, the + * value in the device_id must match its corresponding member + * in the device or interface descriptor, or else the device_id + * does not match. + * + * "driver_info" is normally used only by device drivers, + * but you can create a wildcard "matches anything" usb_device_id + * as a driver's "modules.usbmap" entry if you provide an id with + * only a nonzero "driver_info" field. If you do this, the USB device + * driver's probe() routine should use additional intelligence to + * decide whether to bind to the specified interface. + * + * What Makes Good usb_device_id Tables: + * + * The match algorithm is very simple, so that intelligence in + * driver selection must come from smart driver id records. + * Unless you have good reasons to use another selection policy, + * provide match elements only in related groups, and order match + * specifiers from specific to general. Use the macros provided + * for that purpose if you can. + * + * The most specific match specifiers use device descriptor + * data. These are commonly used with product-specific matches; + * the USB_DEVICE macro lets you provide vendor and product IDs, + * and you can also match against ranges of product revisions. + * These are widely used for devices with application or vendor + * specific bDeviceClass values. + * + * Matches based on device class/subclass/protocol specifications + * are slightly more general; use the USB_DEVICE_INFO macro, or + * its siblings. These are used with single-function devices + * where bDeviceClass doesn't specify that each interface has + * its own class. + * + * Matches based on interface class/subclass/protocol are the + * most general; they let drivers bind to any interface on a + * multiple-function device. Use the USB_INTERFACE_INFO + * macro, or its siblings, to match class-per-interface style + * devices (as recorded in bDeviceClass). + * + * Within those groups, remember that not all combinations are + * meaningful. For example, don't give a product version range + * without vendor and product IDs; or specify a protocol without + * its associated class and subclass. + */ +const struct usb_device_id * +usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_host_interface *intf; + struct usb_device *dev; + + /* proc_connectinfo in devio.c may call us with id == NULL. */ + if (id == NULL) + return NULL; + + intf = &interface->altsetting [interface->act_altsetting]; + dev = interface_to_usbdev(interface); + + /* It is important to check that id->driver_info is nonzero, + since an entry that is all zeroes except for a nonzero + id->driver_info is the way to create an entry that + indicates that the driver want to examine every + device and interface. */ + for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || + id->driver_info; id++) { + + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + id->idVendor != dev->descriptor.idVendor) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && + id->idProduct != dev->descriptor.idProduct) + continue; + + /* No need to test id->bcdDevice_lo != 0, since 0 is never + greater than any unsigned number. */ + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && + (id->bcdDevice_lo > dev->descriptor.bcdDevice)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && + (id->bcdDevice_hi < dev->descriptor.bcdDevice)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && + (id->bDeviceClass != dev->descriptor.bDeviceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && + (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && + (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && + (id->bInterfaceClass != intf->desc.bInterfaceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && + (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && + (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) + continue; + + return id; + } + + return NULL; +} + +/** + * usb_find_interface - find usb_interface pointer for driver and device + * @drv: the driver whose current configuration is considered + * @minor: the minor number of the desired device + * + * This walks the driver device list and returns a pointer to the interface + * with the matching minor. Note, this only works for devices that share the + * USB major number. + */ +struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) +{ + struct list_head *entry; + struct device *dev; + struct usb_interface *intf; + + list_for_each(entry, &drv->driver.devices) { + dev = container_of(entry, struct device, driver_list); + + /* can't look at usb devices, only interfaces */ + if (dev->driver == &usb_generic_driver) + continue; + + intf = to_usb_interface(dev); + if (intf->minor == -1) + continue; + if (intf->minor == minor) + return intf; + } + + /* no device found that matches */ + return NULL; +} + +static int usb_device_match (struct device *dev, struct device_driver *drv) +{ + struct usb_interface *intf; + struct usb_driver *usb_drv; + const struct usb_device_id *id; + + /* check for generic driver, which we don't match any device with */ + if (drv == &usb_generic_driver) + return 0; + + intf = to_usb_interface(dev); + + usb_drv = to_usb_driver(drv); + id = usb_drv->id_table; + + id = usb_match_id (intf, usb_drv->id_table); + if (id) + return 1; + + return 0; +} + + +#ifdef CONFIG_HOTPLUG + +/* + * USB hotplugging invokes what /proc/sys/kernel/hotplug says + * (normally /sbin/hotplug) when USB devices get added or removed. + * + * This invokes a user mode policy agent, typically helping to load driver + * or other modules, configure the device, and more. Drivers can provide + * a MODULE_DEVICE_TABLE to help with module loading subtasks. + * + * We're called either from khubd (the typical case) or from root hub + * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle + * delays in event delivery. Use sysfs (and DEVPATH) to make sure the + * device (and this configuration!) are still present. + */ +static int usb_hotplug (struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct usb_interface *intf; + struct usb_device *usb_dev; + char *scratch; + int i = 0; + int length = 0; + + dbg ("%s", __FUNCTION__); + + if (!dev) + return -ENODEV; + + /* Must check driver_data here, as on remove driver is always NULL */ + if ((dev->driver == &usb_generic_driver) || + (dev->driver_data == &usb_generic_driver_data)) + return 0; + + intf = to_usb_interface(dev); + usb_dev = interface_to_usbdev (intf); + + if (usb_dev->devnum < 0) { + dbg ("device already deleted ??"); + return -ENODEV; + } + if (!usb_dev->bus) { + dbg ("bus already removed?"); + return -ENODEV; + } + + scratch = buffer; + +#ifdef CONFIG_USB_DEVICEFS + /* If this is available, userspace programs can directly read + * all the device descriptors we don't tell them about. Or + * even act as usermode drivers. + * + * FIXME reduce hardwired intelligence here + */ + envp [i++] = scratch; + length += snprintf (scratch, buffer_size - length, + "DEVICE=/proc/bus/usb/%03d/%03d", + usb_dev->bus->busnum, usb_dev->devnum); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; + ++length; + scratch += length; +#endif + + /* per-device configurations are common */ + envp [i++] = scratch; + length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x", + usb_dev->descriptor.idVendor, + usb_dev->descriptor.idProduct, + usb_dev->descriptor.bcdDevice); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; + ++length; + scratch += length; + + /* class-based driver binding models */ + envp [i++] = scratch; + length += snprintf (scratch, buffer_size - length, "TYPE=%d/%d/%d", + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; + ++length; + scratch += length; + + if (usb_dev->descriptor.bDeviceClass == 0) { + int alt = intf->act_altsetting; + + /* 2.4 only exposed interface zero. in 2.5, hotplug + * agents are called for all interfaces, and can use + * $DEVPATH/bInterfaceNumber if necessary. + */ + envp [i++] = scratch; + length += snprintf (scratch, buffer_size - length, + "INTERFACE=%d/%d/%d", + intf->altsetting[alt].desc.bInterfaceClass, + intf->altsetting[alt].desc.bInterfaceSubClass, + intf->altsetting[alt].desc.bInterfaceProtocol); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; + ++length; + scratch += length; + + } + envp [i++] = 0; + + return 0; +} + +#else + +static int usb_hotplug (struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + return -ENODEV; +} + +#endif /* CONFIG_HOTPLUG */ + +/** + * usb_alloc_dev - allocate a usb device structure (usbcore-internal) + * @parent: hub to which device is connected + * @bus: bus used to access the device + * Context: !in_interrupt () + * + * Only hub drivers (including virtual root hub drivers for host + * controllers) should ever call this. + * + * This call is synchronous, and may not be used in an interrupt context. + */ +struct usb_device STDCALL *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) +{ + struct usb_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + memset(dev, 0, sizeof(*dev)); + + device_initialize(&dev->dev); + dev->state = USB_STATE_ATTACHED; + + usb_bus_get(bus); + + if (!parent) + dev->devpath [0] = '0'; + dev->bus = bus; + dev->parent = parent; + INIT_LIST_HEAD(&dev->filelist); + + init_MUTEX(&dev->serialize); + + if (dev->bus->op->allocate) + dev->bus->op->allocate(dev); + + return dev; +} + +/** + * usb_get_dev - increments the reference count of the usb device structure + * @dev: the device being referenced + * + * Each live reference to a device should be refcounted. + * + * Drivers for USB interfaces should normally record such references in + * their probe() methods, when they bind to an interface, and release + * them by calling usb_put_dev(), in their disconnect() methods. + * + * A pointer to the device with the incremented reference counter is returned. + */ +struct usb_device *usb_get_dev (struct usb_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + + tmp = get_device(&dev->dev); + if (tmp) + return to_usb_device(tmp); + else + return NULL; +} + +/** + * usb_put_dev - release a use of the usb device structure + * @dev: device that's been disconnected + * + * Must be called when a user of a device is finished with it. When the last + * user of the device calls this function, the memory of the device is freed. + */ +void STDCALL usb_put_dev(struct usb_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + +/** + * usb_release_dev - free a usb device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this usb device are + * done. + */ +static void usb_release_dev(struct device *dev) +{ + struct usb_device *udev; + + udev = to_usb_device(dev); + + if (udev->bus && udev->bus->op && udev->bus->op->deallocate) + udev->bus->op->deallocate(udev); + usb_destroy_configuration (udev); + usb_bus_put (udev->bus); + kfree (udev); +} + + +static struct usb_device *match_device(struct usb_device *dev, + u16 vendor_id, u16 product_id) +{ + struct usb_device *ret_dev = NULL; + int child; + + dbg("looking at vendor %d, product %d", + dev->descriptor.idVendor, + dev->descriptor.idProduct); + + /* see if this device matches */ + if ((dev->descriptor.idVendor == vendor_id) && + (dev->descriptor.idProduct == product_id)) { + dbg ("found the device!"); + ret_dev = usb_get_dev(dev); + goto exit; + } + + /* look through all of the children of this device */ + for (child = 0; child < dev->maxchild; ++child) { + if (dev->children[child]) { + ret_dev = match_device(dev->children[child], + vendor_id, product_id); + if (ret_dev) + goto exit; + } + } +exit: + return ret_dev; +} + +/** + * usb_find_device - find a specific usb device in the system + * @vendor_id: the vendor id of the device to find + * @product_id: the product id of the device to find + * + * Returns a pointer to a struct usb_device if such a specified usb + * device is present in the system currently. The usage count of the + * device will be incremented if a device is found. Make sure to call + * usb_put_dev() when the caller is finished with the device. + * + * If a device with the specified vendor and product id is not found, + * NULL is returned. + */ +struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) +{ + struct list_head *buslist; + struct usb_bus *bus; + struct usb_device *dev = NULL; + + down(&usb_bus_list_lock); + for (buslist = usb_bus_list.next; + buslist != &usb_bus_list; + buslist = buslist->next) { + bus = container_of(buslist, struct usb_bus, bus_list); + dev = match_device(bus->root_hub, vendor_id, product_id); + if (dev) + goto exit; + } +exit: + up(&usb_bus_list_lock); + return dev; +} + +/** + * usb_get_current_frame_number - return current bus frame number + * @dev: the device whose bus is being queried + * + * Returns the current frame number for the USB host controller + * used with the given USB device. This can be used when scheduling + * isochronous requests. + * + * Note that different kinds of host controller have different + * "scheduling horizons". While one type might support scheduling only + * 32 frames into the future, others could support scheduling up to + * 1024 frames into the future. + */ +int usb_get_current_frame_number(struct usb_device *dev) +{ + return dev->bus->op->get_frame_number (dev); +} + +/*-------------------------------------------------------------------*/ +/* + * __usb_get_extra_descriptor() finds a descriptor of specific type in the + * extra field of the interface and endpoint descriptor structs. + */ + +int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr) +{ + struct usb_descriptor_header *header; + + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + if (header->bDescriptorType == type) { + *ptr = header; + return 0; + } + + buffer += header->bLength; + size -= header->bLength; + } + return -1; +} + +/** + * usb_disconnect - disconnect a device (usbcore-internal) + * @pdev: pointer to device being disconnected + * Context: !in_interrupt () + * + * Something got disconnected. Get rid of it, and all of its children. + * + * Only hub drivers (including virtual root hub drivers for host + * controllers) should ever call this. + * + * This call is synchronous, and may not be used in an interrupt context. + */ +void usb_disconnect(struct usb_device **pdev) +{ + struct usb_device *dev = *pdev; + struct usb_bus *bus; + struct usb_operations *ops; + int i; + + might_sleep (); + + if (!dev) { + pr_debug ("%s nodev\n", __FUNCTION__); + return; + } + bus = dev->bus; + if (!bus) { + pr_debug ("%s nobus\n", __FUNCTION__); + return; + } + ops = bus->op; + + *pdev = NULL; + + /* mark the device as inactive, so any further urb submissions for + * this device will fail. + */ + dev->state = USB_STATE_NOTATTACHED; + + dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum); + + /* Free up all the children before we remove this device */ + for (i = 0; i < USB_MAXCHILDREN; i++) { + struct usb_device **child = dev->children + i; + if (*child) + usb_disconnect(child); + } + + /* disconnect() drivers from interfaces (a key side effect) */ + dev_dbg (&dev->dev, "unregistering interfaces\n"); + if (dev->actconfig) { + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *interface; + + /* remove this interface */ + interface = &dev->actconfig->interface[i]; + device_unregister(&interface->dev); + } + } + + /* deallocate hcd/hardware state */ + if (ops->disable) { + void (*disable)(struct usb_device *, int) = ops->disable; + + for (i = 0; i < 15; i++) { + disable (dev, i); + disable (dev, USB_DIR_IN | i); + } + } + + dev_dbg (&dev->dev, "unregistering device\n"); + /* Free the device number and remove the /proc/bus/usb entry */ + if (dev->devnum > 0) { + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + usbfs_remove_device(dev); + } + device_unregister(&dev->dev); + + /* Decrement the reference count, it'll auto free everything when */ + /* it hits 0 which could very well be now */ + usb_put_dev(dev); +} + +/** + * usb_connect - pick device address (usbcore-internal) + * @dev: newly detected device (in DEFAULT state) + * + * Picks a device address. It's up to the hub (or root hub) driver + * to handle and manage enumeration, starting from the DEFAULT state. + * Only hub drivers (including virtual root hub drivers for host + * controllers) should ever call this. + */ +void STDCALL usb_connect(struct usb_device *dev) +{ + int devnum; + // FIXME needs locking for SMP!! + /* why? this is called only from the hub thread, + * which hopefully doesn't run on multiple CPU's simultaneously 8-) + * ... it's also called from modprobe/rmmod/apmd threads as part + * of virtual root hub init/reinit. In the init case, the hub code + * won't have seen this, but not so for reinit ... + */ + dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ + + /* Try to allocate the next devnum beginning at bus->devnum_next. */ + devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next); + if (devnum >= 128) + devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); + + dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); + + if (devnum < 128) { + set_bit(devnum, dev->bus->devmap.devicemap); + dev->devnum = devnum; + } +} + + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally, for usb_new_device() +int usb_set_address(struct usb_device *dev) +{ + int retval; + + if (dev->devnum == 0) + return -EINVAL; + if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS) + return -EINVAL; + retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, + 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); + if (retval == 0) + dev->state = USB_STATE_ADDRESS; + return retval; +} + + +/* improve on the default device description, if we can ... and + * while we're at it, maybe show the vendor and product strings. + */ +static void set_device_description (struct usb_device *dev) +{ + void *buf; + int mfgr = dev->descriptor.iManufacturer; + int prod = dev->descriptor.iProduct; + int vendor_id = dev->descriptor.idVendor; + int product_id = dev->descriptor.idProduct; + char *mfgr_str, *prod_str; + + /* set default; keep it if there are no strings, or kmalloc fails */ + sprintf (dev->dev.name, "USB device %04x:%04x", + vendor_id, product_id); + + if (!(buf = kmalloc(256 * 2, GFP_KERNEL))) + return; + + prod_str = (char *) buf; + mfgr_str = (char *) buf + 256; + + if (prod && usb_string (dev, prod, prod_str, 256) > 0) { +#ifdef DEBUG + dev_printk (KERN_INFO, &dev->dev, "Product: %s\n", prod_str); +#endif + } else { + prod_str = 0; + } + + if (mfgr && usb_string (dev, mfgr, mfgr_str, 256) > 0) { +#ifdef DEBUG + dev_printk (KERN_INFO, &dev->dev, "Manufacturer: %s\n", mfgr_str); +#endif + } else { + mfgr_str = 0; + } + + /* much like pci ... describe as either: + * - both strings: 'product descr (vendor descr)' + * - product only: 'product descr (USB device vvvv:pppp)' + * - vendor only: 'USB device vvvv:pppp (vendor descr)' + * - neither string: 'USB device vvvv:pppp' + */ + + if (prod_str && mfgr_str) { + + snprintf(dev->dev.name, sizeof dev->dev.name, + "%s (%s)", prod_str, mfgr_str); + } else if (prod_str) { + snprintf(dev->dev.name, sizeof dev->dev.name, + "%s (USB device %04x:%04x)", + prod_str, vendor_id, product_id); + + } else if (mfgr_str) { + snprintf(dev->dev.name, sizeof dev->dev.name, + "USB device %04x:%04x (%s)", + vendor_id, product_id, mfgr_str); + } + //usbprintk("USB connected: %s\n",dev->dev.name); + kfree(buf); +} + +/* + * By the time we get here, we chose a new device address + * and is in the default state. We need to identify the thing and + * get the ball rolling.. + * + * Returns 0 for success, != 0 for error. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Only hub drivers (including virtual root hub drivers for host + * controllers) should ever call this. + */ +#define NEW_DEVICE_RETRYS 2 +#define SET_ADDRESS_RETRYS 2 +int usb_new_device(struct usb_device *dev, struct device *parent) +{ + int err = 0; + int i; + int j; + + /* + * Set the driver for the usb device to point to the "generic" driver. + * This prevents the main usb device from being sent to the usb bus + * probe function. Yes, it's a hack, but a nice one :) + * + * Do it asap, so more driver model stuff (like the device.h message + * utilities) can be used in hcd submit/unlink code paths. + */ + usb_generic_driver.bus = &usb_bus_type; + dev->dev.parent = parent; + dev->dev.driver = &usb_generic_driver; + dev->dev.bus = &usb_bus_type; + dev->dev.release = usb_release_dev; + dev->dev.driver_data = &usb_generic_driver_data; + usb_get_dev(dev); + if (dev->dev.bus_id[0] == 0) + sprintf (&dev->dev.bus_id[0], "%d-%s", + dev->bus->busnum, dev->devpath); + + /* dma masks come from the controller; readonly, except to hcd */ + dev->dev.dma_mask = parent->dma_mask; + + /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... + * it's fixed size except for full speed devices. + */ + switch (dev->speed) { + case USB_SPEED_HIGH: /* fixed at 64 */ + i = 64; + break; + case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ + /* to determine the ep0 maxpacket size, read the first 8 + * bytes from the device descriptor to get bMaxPacketSize0; + * then correct our initial (small) guess. + */ + // FALLTHROUGH + case USB_SPEED_LOW: /* fixed at 8 */ + i = 8; + break; + default: + return -EINVAL; + } + dev->epmaxpacketin [0] = i; + dev->epmaxpacketout[0] = i; + + for (i = 0; i < NEW_DEVICE_RETRYS; ++i) { + + for (j = 0; j < SET_ADDRESS_RETRYS; ++j) { + err = usb_set_address(dev); + if (err >= 0) + break; + wait_ms(200); + } + if (err < 0) { + dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n", + dev->devnum, err); + dev->state = USB_STATE_DEFAULT; + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + wait_ms(10); /* Let the SET_ADDRESS settle */ + + /* high and low speed devices don't need this... */ + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); + if (err >= 8) + break; + wait_ms(100); + } + + if (err < 8) { + if (err < 0) + dev_err(&dev->dev, "USB device not responding, giving up (error=%d)\n", err); + else + dev_err(&dev->dev, "USB device descriptor short read (expected %i, got %i)\n", 8, err); + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + if (dev->speed == USB_SPEED_FULL) { + dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + } + + /* USB device state == addressed ... still not usable */ + + err = usb_get_device_descriptor(dev); + if (err < (signed)sizeof(dev->descriptor)) { + if (err < 0) + dev_err(&dev->dev, "unable to get device descriptor (error=%d)\n", err); + else + dev_err(&dev->dev, "USB device descriptor short read (expected %Zi, got %i)\n", + sizeof(dev->descriptor), err); + + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + err = usb_get_configuration(dev); + if (err < 0) { + dev_err(&dev->dev, "unable to get device %d configuration (error=%d)\n", + dev->devnum, err); + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + /* we set the default configuration here */ + err = usb_set_configuration(dev, dev->config[0].desc.bConfigurationValue); + if (err) { + dev_err(&dev->dev, "failed to set device %d default configuration (error=%d)\n", + dev->devnum, err); + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; + } + + /* USB device state == configured ... tell the world! */ + + dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", + dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); + set_device_description (dev); + +#ifdef DEBUG + if (dev->descriptor.iSerialNumber) + usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); +#endif + /* put into sysfs, with device and config specific files */ + err = device_add (&dev->dev); + if (err) + return err; + usb_create_driverfs_dev_files (dev); + + /* Register all of the interfaces for this device with the driver core. + * Remember, interfaces get bound to drivers, not devices. */ + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *interface = &dev->actconfig->interface[i]; + struct usb_interface_descriptor *desc; + + desc = &interface->altsetting [interface->act_altsetting].desc; + interface->dev.parent = &dev->dev; + interface->dev.driver = NULL; + interface->dev.bus = &usb_bus_type; + interface->dev.dma_mask = parent->dma_mask; + sprintf (&interface->dev.bus_id[0], "%d-%s:%d", + dev->bus->busnum, dev->devpath, + desc->bInterfaceNumber); + if (!desc->iInterface + || usb_string (dev, desc->iInterface, + interface->dev.name, + sizeof interface->dev.name) <= 0) { + /* typically devices won't bother with interface + * descriptions; this is the normal case. an + * interface's driver might describe it better. + * (also: iInterface is per-altsetting ...) + */ + sprintf (&interface->dev.name[0], + "usb-%s-%s interface %d", + dev->bus->bus_name, dev->devpath, + desc->bInterfaceNumber); + } + dev_dbg (&dev->dev, "%s - registering interface %s\n", __FUNCTION__, interface->dev.bus_id); + device_add (&interface->dev); + usb_create_driverfs_intf_files (interface); + } + /* add a /proc/bus/usb entry */ + usbfs_add_device(dev); + + return 0; +} + +/** + * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP + * @dev: device the buffer will be used with + * @size: requested buffer size + * @mem_flags: affect whether allocation may block + * @dma: used to return DMA address of buffer + * + * Return value is either null (indicating no buffer could be allocated), or + * the cpu-space pointer to a buffer that may be used to perform DMA to the + * specified device. Such cpu-space buffers are returned along with the DMA + * address (through the pointer provided). + * + * These buffers are used with URB_NO_DMA_MAP set in urb->transfer_flags to + * avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping + * hardware for long idle periods. The implementation varies between + * platforms, depending on details of how DMA will work to this device. + * Using these buffers also helps prevent cacheline sharing problems on + * architectures where CPU caches are not DMA-coherent. + * + * When the buffer is no longer used, free it with usb_buffer_free(). + */ +void *usb_buffer_alloc ( + struct usb_device *dev, + size_t size, + int mem_flags, + dma_addr_t *dma +) +{ + if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc) + return 0; + return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma); +} + +/** + * usb_buffer_free - free memory allocated with usb_buffer_alloc() + * @dev: device the buffer was used with + * @size: requested buffer size + * @addr: CPU address of buffer + * @dma: DMA address of buffer + * + * This reclaims an I/O buffer, letting it be reused. The memory must have + * been allocated using usb_buffer_alloc(), and the parameters must match + * those provided in that allocation request. + */ +void usb_buffer_free ( + struct usb_device *dev, + size_t size, + void *addr, + dma_addr_t dma +) +{ + if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free) + return; + dev->bus->op->buffer_free (dev->bus, size, addr, dma); +} + +/** + * usb_buffer_map - create DMA mapping(s) for an urb + * @urb: urb whose transfer_buffer will be mapped + * + * Return value is either null (indicating no buffer could be mapped), or + * the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the + * operation succeeds. If the device is connected to this system through + * a non-DMA controller, this operation always succeeds. + * + * This call would normally be used for an urb which is reused, perhaps + * as the target of a large periodic transfer, with usb_buffer_dmasync() + * calls to synchronize memory and dma state. It may not be used for + * control requests. + * + * Reverse the effect of this call with usb_buffer_unmap(). + */ +struct urb *usb_buffer_map (struct urb *urb) +{ + struct usb_bus *bus; + struct device *controller; + + if (!urb + || usb_pipecontrol (urb->pipe) + || !urb->dev + || !(bus = urb->dev->bus) + || !(controller = bus->controller)) + return 0; + + if (controller->dma_mask) { + urb->transfer_dma = dma_map_single (controller, + urb->transfer_buffer, urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + // FIXME generic api broken like pci, can't report errors + // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; + } else + urb->transfer_dma = ~0; + urb->transfer_flags |= URB_NO_DMA_MAP; + return urb; +} + +/** + * usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s) + * @urb: urb whose transfer_buffer will be synchronized + */ +void usb_buffer_dmasync (struct urb *urb) +{ + struct usb_bus *bus; + struct device *controller; + + if (!urb + || !(urb->transfer_flags & URB_NO_DMA_MAP) + || !urb->dev + || !(bus = urb->dev->bus) + || !(controller = bus->controller)) + return; + + if (controller->dma_mask) + dma_sync_single (controller, + urb->transfer_dma, urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? DMA_FROM_DEVICE : DMA_TO_DEVICE); +} + +/** + * usb_buffer_unmap - free DMA mapping(s) for an urb + * @urb: urb whose transfer_buffer will be unmapped + * + * Reverses the effect of usb_buffer_map(). + */ +void usb_buffer_unmap (struct urb *urb) +{ + struct usb_bus *bus; + struct device *controller; + + if (!urb + || !(urb->transfer_flags & URB_NO_DMA_MAP) + || !urb->dev + || !(bus = urb->dev->bus) + || !(controller = bus->controller)) + return; + + if (controller->dma_mask) + dma_unmap_single (controller, + urb->transfer_dma, urb->transfer_buffer_length, + usb_pipein (urb->pipe) + ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + urb->transfer_flags &= ~URB_NO_DMA_MAP; +} + +/** + * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint + * @dev: device to which the scatterlist will be mapped + * @pipe: endpoint defining the mapping direction + * @sg: the scatterlist to map + * @nents: the number of entries in the scatterlist + * + * Return value is either < 0 (indicating no buffers could be mapped), or + * the number of DMA mapping array entries in the scatterlist. + * + * The caller is responsible for placing the resulting DMA addresses from + * the scatterlist into URB transfer buffer pointers, and for setting the + * URB_NO_DMA_MAP transfer flag in each of those URBs. + * + * Top I/O rates come from queuing URBs, instead of waiting for each one + * to complete before starting the next I/O. This is particularly easy + * to do with scatterlists. Just allocate and submit one URB for each DMA + * mapping entry returned, stopping on the first error or when all succeed. + * Better yet, use the usb_sg_*() calls, which do that (and more) for you. + * + * This call would normally be used when translating scatterlist requests, + * rather than usb_buffer_map(), since on some hardware (with IOMMUs) it + * may be able to coalesce mappings for improved I/O efficiency. + * + * Reverse the effect of this call with usb_buffer_unmap_sg(). + */ +int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int nents) +{ + struct usb_bus *bus; + struct device *controller; + + if (!dev + || usb_pipecontrol (pipe) + || !(bus = dev->bus) + || !(controller = bus->controller) + || !controller->dma_mask) + return -1; + + // FIXME generic api broken like pci, can't report errors + return dma_map_sg (controller, sg, nents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); +} + +/** + * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s) + * @dev: device to which the scatterlist will be mapped + * @pipe: endpoint defining the mapping direction + * @sg: the scatterlist to synchronize + * @n_hw_ents: the positive return value from usb_buffer_map_sg + * + * Use this when you are re-using a scatterlist's data buffers for + * another USB request. + */ +void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents) +{ + struct usb_bus *bus; + struct device *controller; + + if (!dev + || !(bus = dev->bus) + || !(controller = bus->controller) + || !controller->dma_mask) + return; + + dma_sync_sg (controller, sg, n_hw_ents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); +} + +/** + * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist + * @dev: device to which the scatterlist will be mapped + * @pipe: endpoint defining the mapping direction + * @sg: the scatterlist to unmap + * @n_hw_ents: the positive return value from usb_buffer_map_sg + * + * Reverses the effect of usb_buffer_map_sg(). + */ +void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents) +{ + struct usb_bus *bus; + struct device *controller; + + if (!dev + || !(bus = dev->bus) + || !(controller = bus->controller) + || !controller->dma_mask) + return; + + dma_unmap_sg (controller, sg, n_hw_ents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); +} + + +struct bus_type usb_bus_type = { + .name = "usb", + .match = usb_device_match, + .hotplug = usb_hotplug, +}; + +#ifndef MODULE + +static int __init usb_setup_disable(char *str) +{ + nousb = 1; + return 1; +} + +/* format to disable USB on kernel command line is: nousb */ +__setup("nousb", usb_setup_disable); + +#endif + +/* + * for external read access to + */ +int STDCALL usb_disabled(void) +{ + return nousb; +} + +/* + * Init + */ +static int __init usb_init(void) +{ + if (nousb) { + info("USB support disabled\n"); + return 0; + } + + bus_register(&usb_bus_type); + usb_major_init(); + usbfs_init(); + usb_hub_init(); + + driver_register(&usb_generic_driver); + + return 0; +} + +/* + * Cleanup + */ +static void __exit usb_exit(void) +{ + /* This will matter if shutdown/reboot does exitcalls. */ + if (nousb) + return; + + driver_unregister(&usb_generic_driver); + usb_major_cleanup(); + usbfs_cleanup(); + usb_hub_cleanup(); + bus_unregister(&usb_bus_type); +} + +subsys_initcall(usb_init); +module_exit(usb_exit); + +/* + * USB may be built into the kernel or be built as modules. + * These symbols are exported for device (or host controller) + * driver modules to use. + */ +EXPORT_SYMBOL(usb_epnum_to_ep_desc); + +EXPORT_SYMBOL(usb_register); +EXPORT_SYMBOL(usb_deregister); +EXPORT_SYMBOL(usb_disabled); + +EXPORT_SYMBOL(usb_device_probe); +EXPORT_SYMBOL(usb_device_remove); + +EXPORT_SYMBOL(usb_alloc_dev); +EXPORT_SYMBOL(usb_put_dev); +EXPORT_SYMBOL(usb_get_dev); +EXPORT_SYMBOL(usb_hub_tt_clear_buffer); + +EXPORT_SYMBOL(usb_driver_claim_interface); +EXPORT_SYMBOL(usb_interface_claimed); +EXPORT_SYMBOL(usb_driver_release_interface); +EXPORT_SYMBOL(usb_match_id); +EXPORT_SYMBOL(usb_find_interface); +EXPORT_SYMBOL(usb_ifnum_to_if); + +EXPORT_SYMBOL(usb_new_device); +EXPORT_SYMBOL(usb_reset_device); +EXPORT_SYMBOL(usb_connect); +EXPORT_SYMBOL(usb_disconnect); + +EXPORT_SYMBOL(__usb_get_extra_descriptor); + +EXPORT_SYMBOL(usb_find_device); +EXPORT_SYMBOL(usb_get_current_frame_number); + +EXPORT_SYMBOL (usb_buffer_alloc); +EXPORT_SYMBOL (usb_buffer_free); + +EXPORT_SYMBOL (usb_buffer_map); +EXPORT_SYMBOL (usb_buffer_dmasync); +EXPORT_SYMBOL (usb_buffer_unmap); + +EXPORT_SYMBOL (usb_buffer_map_sg); +EXPORT_SYMBOL (usb_buffer_dmasync_sg); +EXPORT_SYMBOL (usb_buffer_unmap_sg); + +MODULE_LICENSE("GPL"); diff --git a/reactos/drivers/usb/cromwell/core/usb.h b/reactos/drivers/usb/cromwell/core/usb.h new file mode 100644 index 00000000000..52210ef7fa6 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usb.h @@ -0,0 +1,5 @@ +/* Functions local to drivers/usb/core/ */ + +extern void usb_create_driverfs_dev_files (struct usb_device *dev); +extern void usb_create_driverfs_intf_files (struct usb_interface *intf); + diff --git a/reactos/drivers/usb/cromwell/core/usbcore.c b/reactos/drivers/usb/cromwell/core/usbcore.c new file mode 100644 index 00000000000..0c8e0c50a9a --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usbcore.c @@ -0,0 +1,16 @@ +/* + ReactOS specific functions for usbcore module + by Aleksey Bragin (aleksey@reactos.com) +*/ + +#include + + +/* + * Standard DriverEntry method. + */ +NTSTATUS STDCALL +DriverEntry(IN PVOID Context1, IN PVOID Context2) +{ + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/usb/cromwell/core/usbcore.def b/reactos/drivers/usb/cromwell/core/usbcore.def new file mode 100644 index 00000000000..cc6e7687e2d --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usbcore.def @@ -0,0 +1,29 @@ +; +; Exports definition file for usbcore.sys +; +EXPORTS +usb_init_urb@4 +usb_alloc_urb@8 +usb_free_urb@4 +usb_get_urb@4 +usb_submit_urb@8 +usb_unlink_urb@4 +usb_bus_init@4 +usb_alloc_bus@4 +usb_free_bus@4 +usb_register_bus@4 +usb_deregister_bus@4 +usb_register_root_hub@8 +usb_calc_bus_time@16 +usb_check_bandwidth@8 +usb_claim_bandwidth@16 +usb_release_bandwidth@12 +usb_hcd_giveback_urb@12 +;usb_hcd_irq@12 +usb_hc_died@4 +usb_alloc_dev@8 +usb_connect@4 +usb_put_dev@4 +usb_disabled@0 +usb_hcd_pci_probe@8 +usb_hcd_pci_remove@4 \ No newline at end of file diff --git a/reactos/drivers/usb/cromwell/core/usbcore.rc b/reactos/drivers/usb/cromwell/core/usbcore.rc new file mode 100644 index 00000000000..bccb64ac3d2 --- /dev/null +++ b/reactos/drivers/usb/cromwell/core/usbcore.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbcore\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0" +#include diff --git a/reactos/drivers/usb/cromwell/host/makefile b/reactos/drivers/usb/cromwell/host/makefile new file mode 100644 index 00000000000..0cc14867050 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = ohci + +TARGET_DDKLIBS = ntoskrnl.a usbcore.a + +TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_OBJECTS = \ + ohci-hcd.o ohci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/cromwell/host/makefile.crom b/reactos/drivers/usb/cromwell/host/makefile.crom new file mode 100644 index 00000000000..c23390585ae --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/makefile.crom @@ -0,0 +1,3 @@ +O_TARGET := ohci-hcd.o + +include $(TOPDIR)/Rules.make diff --git a/reactos/drivers/usb/cromwell/host/ohci-dbg.c b/reactos/drivers/usb/cromwell/host/ohci-dbg.c new file mode 100644 index 00000000000..6c9661b6738 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-dbg.c @@ -0,0 +1,666 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * This file is licenced under the GPL. + */ + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG + +#define edstring(ed_type) ({ char *temp; \ + switch (ed_type) { \ + case PIPE_CONTROL: temp = "ctrl"; break; \ + case PIPE_BULK: temp = "bulk"; break; \ + case PIPE_INTERRUPT: temp = "intr"; break; \ + default: temp = "isoc"; break; \ + }; temp;}) +#define pipestring(pipe) edstring(usb_pipetype(pipe)) + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header + */ +static void __attribute__((unused)) +urb_print (struct urb * urb, char * str, int small) +{ + unsigned int pipe= urb->pipe; + + if (!urb->dev || !urb->dev->bus) { + dbg("%s URB: no dev", str); + return; + } + +#ifndef OHCI_VERBOSE_DEBUG + if (urb->status != 0) +#endif + dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", + str, + urb, + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? "out" : "in", + pipestring (pipe), + urb->transfer_flags, + urb->actual_length, + urb->transfer_buffer_length, + urb->status); + +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printk (KERN_DEBUG __FILE__ ": setup(8):"); + for (i = 0; i < 8 ; i++) + printk (" %02x", ((__u8 *) urb->setup_packet) [i]); + printk ("\n"); + } + if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { + printk (KERN_DEBUG __FILE__ ": data(%d/%d):", + urb->actual_length, + urb->transfer_buffer_length); + len = usb_pipeout (pipe)? + urb->transfer_buffer_length: urb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); + printk ("%s stat:%d\n", i < len? "...": "", urb->status); + } + } +#endif +} + +#define ohci_dbg_sw(ohci, next, size, format, arg...) \ + do { \ + if (next) { \ + unsigned s_len; \ + s_len = snprintf (*next, *size, format, ## arg ); \ + *size -= s_len; *next += s_len; \ + } else \ + ohci_dbg(ohci,format, ## arg ); \ + } while (0); + + +static void ohci_dump_intr_mask ( + struct ohci_hcd *ohci, + char *label, + u32 mask, + char **next, + unsigned *size) +{ + ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds ( + struct ohci_hcd *ohci, + char *label, + u32 value, + char **next, + unsigned *size) +{ + if (value) + ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value); +} + +static char *hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +// dump control and status registers +static void +ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) +{ + struct ohci_regs *regs = controller->regs; + u32 temp; + + temp = readl (®s->revision) & 0xff; + ohci_dbg_sw (controller, next, size, + "OHCI %d.%d, %s legacy support registers\n", + 0x03 & (temp >> 4), (temp & 0x0f), + (temp & 0x10) ? "with" : "NO"); + + temp = readl (®s->control); + ohci_dbg_sw (controller, next, size, + "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", + temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + ohci_dbg_sw (controller, next, size, + "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask (controller, "intrstatus", + readl (®s->intrstatus), next, size); + ohci_dump_intr_mask (controller, "intrenable", + readl (®s->intrenable), next, size); + // intrdisable always same as intrenable + + maybe_print_eds (controller, "ed_periodcurrent", + readl (®s->ed_periodcurrent), next, size); + + maybe_print_eds (controller, "ed_controlhead", + readl (®s->ed_controlhead), next, size); + maybe_print_eds (controller, "ed_controlcurrent", + readl (®s->ed_controlcurrent), next, size); + + maybe_print_eds (controller, "ed_bulkhead", + readl (®s->ed_bulkhead), next, size); + maybe_print_eds (controller, "ed_bulkcurrent", + readl (®s->ed_bulkcurrent), next, size); + + maybe_print_eds (controller, "donehead", + readl (®s->donehead), next, size); +} + +#define dbg_port_sw(hc,num,value,next,size) \ + ohci_dbg_sw (hc, next, size, \ + "roothub.portstatus [%d] " \ + "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ + num, temp, \ + (temp & RH_PS_PRSC) ? " PRSC" : "", \ + (temp & RH_PS_OCIC) ? " OCIC" : "", \ + (temp & RH_PS_PSSC) ? " PSSC" : "", \ + (temp & RH_PS_PESC) ? " PESC" : "", \ + (temp & RH_PS_CSC) ? " CSC" : "", \ + \ + (temp & RH_PS_LSDA) ? " LSDA" : "", \ + (temp & RH_PS_PPS) ? " PPS" : "", \ + (temp & RH_PS_PRS) ? " PRS" : "", \ + (temp & RH_PS_POCI) ? " POCI" : "", \ + (temp & RH_PS_PSS) ? " PSS" : "", \ + \ + (temp & RH_PS_PES) ? " PES" : "", \ + (temp & RH_PS_CCS) ? " CCS" : "" \ + ); + + +static void +ohci_dump_roothub ( + struct ohci_hcd *controller, + int verbose, + char **next, + unsigned *size) +{ + u32 temp, ndp, i; + + temp = roothub_a (controller); + if (temp == ~(u32)0) + return; + ndp = (temp & RH_A_NDP); + + if (verbose) { + ohci_dbg_sw (controller, next, size, + "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + ohci_dbg_sw (controller, next, size, + "roothub.b %08x PPCM=%04x DR=%04x\n", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + ohci_dbg_sw (controller, next, size, + "roothub.status %08x%s%s%s%s%s%s\n", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg_port_sw (controller, i, temp, next, size); + } +} + +static void ohci_dump (struct ohci_hcd *controller, int verbose) +{ + ohci_dbg (controller, "OHCI controller state\n"); + + // dumps some of the state we know about + ohci_dump_status (controller, NULL, 0); + if (controller->hcca) + ohci_dbg (controller, + "hcca frame #%04x\n", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1, NULL, 0); +} + +static const char data0 [] = "DATA0"; +static const char data1 [] = "DATA1"; + +static void ohci_dump_td (struct ohci_hcd *ohci, char *label, struct td *td) +{ + u32 tmp = le32_to_cpup (&td->hwINFO); + + ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x", + label, td, + (tmp & TD_DONE) ? " (DONE)" : "", + td->urb, td->index, + le32_to_cpup (&td->hwNextTD)); + if ((tmp & TD_ISO) == 0) { + const char *toggle, *pid; + u32 cbp, be; + + switch (tmp & TD_T) { + case TD_T_DATA0: toggle = data0; break; + case TD_T_DATA1: toggle = data1; break; + case TD_T_TOGGLE: toggle = "(CARRY)"; break; + default: toggle = "(?)"; break; + } + switch (tmp & TD_DP) { + case TD_DP_SETUP: pid = "SETUP"; break; + case TD_DP_IN: pid = "IN"; break; + case TD_DP_OUT: pid = "OUT"; break; + default: pid = "(bad pid)"; break; + } + ohci_dbg (ohci, " info %08x CC=%x %s DI=%d %s %s", tmp, + TD_CC_GET(tmp), /* EC, */ toggle, + (tmp & TD_DI) >> 21, pid, + (tmp & TD_R) ? "R" : ""); + cbp = le32_to_cpup (&td->hwCBP); + be = le32_to_cpup (&td->hwBE); + ohci_dbg (ohci, " cbp %08x be %08x (len %d)", cbp, be, + cbp ? (be + 1 - cbp) : 0); + } else { + unsigned i; + ohci_dbg (ohci, " info %08x CC=%x FC=%d DI=%d SF=%04x", tmp, + TD_CC_GET(tmp), + (tmp >> 24) & 0x07, + (tmp & TD_DI) >> 21, + tmp & 0x0000ffff); + ohci_dbg (ohci, " bp0 %08x be %08x", + le32_to_cpup (&td->hwCBP) & ~0x0fff, + le32_to_cpup (&td->hwBE)); + for (i = 0; i < MAXPSW; i++) { + u16 psw = le16_to_cpup (&td->hwPSW [i]); + int cc = (psw >> 12) & 0x0f; + ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d", i, + psw, cc, + (cc >= 0x0e) ? "OFFSET" : "SIZE", + psw & 0x0fff); + } + } +} + +/* caller MUST own hcd spinlock if verbose is set! */ +static void __attribute__((unused)) +ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) +{ + u32 tmp = ed->hwINFO; + char *type = ""; + + ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x", + label, + ed, ed->state, edstring (ed->type), + le32_to_cpup (&ed->hwNextED)); + switch (tmp & (ED_IN|ED_OUT)) { + case ED_OUT: type = "-OUT"; break; + case ED_IN: type = "-IN"; break; + /* else from TDs ... control */ + } + ohci_dbg (ohci, + " info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp), + 0x03ff & (le32_to_cpu (tmp) >> 16), + (tmp & ED_DEQUEUE) ? " DQ" : "", + (tmp & ED_ISO) ? " ISO" : "", + (tmp & ED_SKIP) ? " SKIP" : "", + (tmp & ED_LOWSPEED) ? " LOW" : "", + 0x000f & (le32_to_cpu (tmp) >> 7), + type, + 0x007f & le32_to_cpu (tmp)); + ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s", + tmp = le32_to_cpup (&ed->hwHeadP), + (ed->hwHeadP & ED_C) ? data1 : data0, + (ed->hwHeadP & ED_H) ? " HALT" : "", + le32_to_cpup (&ed->hwTailP), + verbose ? "" : " (not listing)"); + if (verbose) { + struct list_head *tmp; + + /* use ed->td_list because HC concurrently modifies + * hwNextTD as it accumulates ed_donelist. + */ + list_for_each (tmp, &ed->td_list) { + struct td *td; + td = list_entry (tmp, struct td, td_list); + ohci_dump_td (ohci, " ->", td); + } + } +} + +#else +static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} + +#undef OHCI_VERBOSE_DEBUG + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files (struct ohci_hcd *bus) { } +static inline void remove_debug_files (struct ohci_hcd *bus) { } + +#else + +static inline struct ohci_hcd *dev_to_ohci (struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata (dev); + + return hcd_to_ohci (hcd); +} + +static ssize_t +show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) +{ + unsigned temp, size = count; + + if (!ed) + return 0; + + /* print first --> last */ + while (ed->ed_prev) + ed = ed->ed_prev; + + /* dump a snapshot of the bulk or control schedule */ + while (ed) { + u32 info = ed->hwINFO; + u32 scratch = cpu_to_le32p (&ed->hwINFO); + struct list_head *entry; + struct td *td; + + temp = snprintf (buf, size, + "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s", + ed, + (info & ED_LOWSPEED) ? 'l' : 'f', + scratch & 0x7f, + (scratch >> 7) & 0xf, + (info & ED_IN) ? "in" : "out", + 0x03ff & (scratch >> 16), + scratch, + (info & ED_SKIP) ? " s" : "", + (ed->hwHeadP & ED_H) ? " H" : "", + (ed->hwHeadP & ED_C) ? data1 : data0); + size -= temp; + buf += temp; + + list_for_each (entry, &ed->td_list) { + u32 cbp, be; + + td = list_entry (entry, struct td, td_list); + scratch = cpu_to_le32p (&td->hwINFO); + cbp = le32_to_cpup (&td->hwCBP); + be = le32_to_cpup (&td->hwBE); + temp = snprintf (buf, size, + "\n\ttd %p %s %d cc=%x urb %p (%08x)", + td, + ({ char *pid; + switch (scratch & TD_DP) { + case TD_DP_SETUP: pid = "setup"; break; + case TD_DP_IN: pid = "in"; break; + case TD_DP_OUT: pid = "out"; break; + default: pid = "(?)"; break; + } pid;}), + cbp ? (be + 1 - cbp) : 0, + TD_CC_GET (scratch), td->urb, scratch); + size -= temp; + buf += temp; + } + + temp = snprintf (buf, size, "\n"); + size -= temp; + buf += temp; + + ed = ed->ed_next; + } + return count - size; +} + +static ssize_t +show_async (struct device *dev, char *buf) +{ + struct ohci_hcd *ohci; + size_t temp; + unsigned long flags; + + ohci = dev_to_ohci(dev); + + /* display control and bulk lists together, for simplicity */ + spin_lock_irqsave (&ohci->lock, flags); + temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail); + temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail); + spin_unlock_irqrestore (&ohci->lock, flags); + + return temp; +} +static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); + + +#define DBG_SCHED_LIMIT 64 + +static ssize_t +show_periodic (struct device *dev, char *buf) +{ + struct ohci_hcd *ohci; + struct ed **seen, *ed; + unsigned long flags; + unsigned temp, size, seen_count; + char *next; + unsigned i; + + if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) + return 0; + seen_count = 0; + + ohci = dev_to_ohci(dev); + next = buf; + size = PAGE_SIZE; + + temp = snprintf (next, size, "size = %d\n", NUM_INTS); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule (and load) */ + spin_lock_irqsave (&ohci->lock, flags); + for (i = 0; i < NUM_INTS; i++) { + if (!(ed = ohci->periodic [i])) + continue; + + temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]); + size -= temp; + next += temp; + + do { + temp = snprintf (next, size, " ed%d/%p", + ed->interval, ed); + size -= temp; + next += temp; + for (temp = 0; temp < seen_count; temp++) { + if (seen [temp] == ed) + break; + } + + /* show more info the first time around */ + if (temp == seen_count) { + u32 info = ed->hwINFO; + u32 scratch = cpu_to_le32p (&ed->hwINFO); + + temp = snprintf (next, size, + " (%cs dev%d%s ep%d%s" + " max %d %08x%s%s)", + (info & ED_LOWSPEED) ? 'l' : 'f', + scratch & 0x7f, + (info & ED_ISO) ? " iso" : "", + (scratch >> 7) & 0xf, + (info & ED_IN) ? "in" : "out", + 0x03ff & (scratch >> 16), + scratch, + (info & ED_SKIP) ? " s" : "", + (ed->hwHeadP & ED_H) ? " H" : ""); + size -= temp; + next += temp; + + // FIXME some TD info too + + if (seen_count < DBG_SCHED_LIMIT) + seen [seen_count++] = ed; + + ed = ed->ed_next; + + } else { + /* we've seen it and what's after */ + temp = 0; + ed = 0; + } + + } while (ed); + + temp = snprintf (next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore (&ohci->lock, flags); + kfree (seen); + + return PAGE_SIZE - size; +} +static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); + + +#undef DBG_SCHED_LIMIT + +static ssize_t +show_registers (struct device *dev, char *buf) +{ + struct ohci_hcd *ohci; + struct ohci_regs *regs; + unsigned long flags; + unsigned temp, size; + char *next; + u32 rdata; + + ohci = dev_to_ohci(dev); + regs = ohci->regs; + next = buf; + size = PAGE_SIZE; + + spin_lock_irqsave (&ohci->lock, flags); + + /* dump driver info, then registers in spec order */ + + ohci_dbg_sw (ohci, &next, &size, + "%s version " DRIVER_VERSION "\n", hcd_name); + + ohci_dump_status(ohci, &next, &size); + + /* hcca */ + if (ohci->hcca) + ohci_dbg_sw (ohci, &next, &size, + "hcca frame 0x%04x\n", ohci->hcca->frame_no); + + /* other registers mostly affect frame timings */ + rdata = readl (®s->fminterval); + temp = snprintf (next, size, + "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", + rdata, (rdata >> 31) ? " FIT" : "", + (rdata >> 16) & 0xefff, rdata & 0xffff); + size -= temp; + next += temp; + + rdata = readl (®s->fmremaining); + temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", + rdata, (rdata >> 31) ? " FRT" : "", + rdata & 0x3fff); + size -= temp; + next += temp; + + rdata = readl (®s->periodicstart); + temp = snprintf (next, size, "periodicstart 0x%04x\n", + rdata & 0x3fff); + size -= temp; + next += temp; + + rdata = readl (®s->lsthresh); + temp = snprintf (next, size, "lsthresh 0x%04x\n", + rdata & 0x3fff); + size -= temp; + next += temp; + + /* roothub */ + ohci_dump_roothub (ohci, 1, &next, &size); + + spin_unlock_irqrestore (&ohci->lock, flags); + + return PAGE_SIZE - size; +} +static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); + + +static inline void create_debug_files (struct ohci_hcd *bus) +{ + device_create_file (bus->hcd.controller, &dev_attr_async); + device_create_file (bus->hcd.controller, &dev_attr_periodic); + device_create_file (bus->hcd.controller, &dev_attr_registers); + ohci_dbg (bus, "created debug files\n"); +} + +static inline void remove_debug_files (struct ohci_hcd *bus) +{ + device_remove_file (bus->hcd.controller, &dev_attr_async); + device_remove_file (bus->hcd.controller, &dev_attr_periodic); + device_remove_file (bus->hcd.controller, &dev_attr_registers); +} + +#endif + +/*-------------------------------------------------------------------------*/ + diff --git a/reactos/drivers/usb/cromwell/host/ohci-hcd.c b/reactos/drivers/usb/cromwell/host/ohci-hcd.c new file mode 100644 index 00000000000..fec58a01b5a --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-hcd.c @@ -0,0 +1,703 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * + * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller + * interfaces (though some non-x86 Intel chips use it). It supports + * smarter hardware than UHCI. A download link for the spec available + * through the http://www.usb.org website. + * + * History: + * + * 2003/02/24 show registers in sysfs (Kevin Brosius) + * + * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and + * bandwidth accounting; if debugging, show schedules in driverfs + * 2002/07/19 fixes to management of ED and schedule state. + * 2002/06/09 SA-1111 support (Christopher Hoover) + * 2002/06/01 remember frame when HC won't see EDs any more; use that info + * to fix urb unlink races caused by interrupt latency assumptions; + * minor ED field and function naming updates + * 2002/01/18 package as a patch for 2.5.3; this should match the + * 2.4.17 kernel modulo some bugs being fixed. + * + * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes + * from post-2.4.5 patches. + * 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning + * 2001/09/07 match PCI PM changes, errnos from Linus' tree + * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify; + * pbook pci quirks gone (please fix pbook pci sw!) (db) + * + * 2001/04/08 Identify version on module load (gb) + * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); + pci_map_single (db) + * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) + * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) + * + * 2000/09/26 fixed races in removing the private portion of the urb + * 2000/09/07 disable bulk and control lists when unlinking the last + * endpoint descriptor in order to avoid unrecoverable errors on + * the Lucent chips. (rwc@sgi) + * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some + * urb unlink probs, indentation fixes + * 2000/08/11 various oops fixes mostly affecting iso and cleanup from + * device unplugs. + * 2000/06/28 use PCI hotplug framework, for better power management + * and for Cardbus support (David Brownell) + * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling + * when the controller loses power; handle UE; cleanup; ... + * + * v5.2 1999/12/07 URB 3rd preview, + * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) + * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume + * i386: HUB, Keyboard, Mouse, Printer + * + * v4.3 1999/10/27 multiple HCs, bulk_request + * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes + * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. + * v4.0 1999/08/18 + * v3.0 1999/06/25 + * v2.1 1999/05/09 code clean up + * v2.0 1999/05/04 + * v1.0 1999/04/27 initial release + * + * This file is licenced under the GPL. + */ + +#if 0 +#include + +#ifdef CONFIG_USB_DEBUG +# define DEBUG +#else +# undef DEBUG +#endif + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt () */ +#include +#include "../core/hcd.h" + +#include +#include +#include +#include +#include +#else +#include "ohci_config.h" + +#include "../usb_wrapper.h" +#include "../core/hcd.h" + +//#define OHCI_VERBOSE_DEBUG +#endif + +/* + * TO DO: + * + * - "disabled" and "sleeping" should be in hcd->state + * - lots more testing!! + */ + +#define DRIVER_VERSION "2003 Feb 24" +#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" +#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" + +/*-------------------------------------------------------------------------*/ + +// #define OHCI_VERBOSE_DEBUG /* not always helpful */ + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define OHCI_UNLINK_TIMEOUT (HZ / 10) + +/*-------------------------------------------------------------------------*/ + +static const char hcd_name [] = "ohci-hcd"; + +#include "ohci.h" + +static inline void disable (struct ohci_hcd *ohci) +{ + ohci->disabled = 1; + ohci->hcd.state = USB_STATE_HALT; +} + +#include "ohci-hub.c" +#include "ohci-dbg.c" +#include "ohci-mem.c" +#include "ohci-q.c" + +/*-------------------------------------------------------------------------*/ + +/* + * queue up an urb for anything except the root hub + */ +static int ohci_urb_enqueue ( + struct usb_hcd *hcd, + struct urb *urb, + int mem_flags +) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ed *ed; + urb_priv_t *urb_priv; + unsigned int pipe = urb->pipe; + int i, size = 0; + unsigned long flags; + int retval = 0; + +#ifdef OHCI_VERBOSE_DEBUG + urb_print (urb, "SUB", usb_pipein (pipe)); +#endif + + /* every endpoint has a ed, locate and maybe (re)initialize it */ + if (! (ed = ed_get (ohci, urb->dev, pipe, urb->interval))) + return -ENOMEM; + + /* for the private part of the URB we need the number of TDs (size) */ + switch (ed->type) { + case PIPE_CONTROL: + /* td_submit_urb() doesn't yet handle these */ + if (urb->transfer_buffer_length > 4096) + return -EMSGSIZE; + + /* 1 TD for setup, 1 for ACK, plus ... */ + size = 2; + /* FALLTHROUGH */ + // case PIPE_INTERRUPT: + // case PIPE_BULK: + default: + /* one TD for every 4096 Bytes (can be upto 8K) */ + size += urb->transfer_buffer_length / 4096; + /* ... and for any remaining bytes ... */ + if ((urb->transfer_buffer_length % 4096) != 0) + size++; + /* ... and maybe a zero length packet to wrap it up */ + if (size == 0) + size++; + else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 + && (urb->transfer_buffer_length + % usb_maxpacket (urb->dev, pipe, + usb_pipeout (pipe))) == 0) + size++; + break; + case PIPE_ISOCHRONOUS: /* number of packets from URB */ + size = urb->number_of_packets; + break; + } + + /* allocate the private part of the URB */ + urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *), + mem_flags); + if (!urb_priv) + return -ENOMEM; + memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); + + /* fill the private part of the URB */ + urb_priv->length = size; + urb_priv->ed = ed; + + /* allocate the TDs (deferring hash chain updates) */ + for (i = 0; i < size; i++) { + urb_priv->td [i] = td_alloc (ohci, mem_flags); + if (!urb_priv->td [i]) { + urb_priv->length = i; + urb_free_priv (ohci, urb_priv); + return -ENOMEM; + } + } + + spin_lock_irqsave (&ohci->lock, flags); + + /* don't submit to a dead HC */ + if (ohci->disabled || ohci->sleeping) { + retval = -ENODEV; + goto fail; + } + + /* schedule the ed if needed */ + if (ed->state == ED_IDLE) { + retval = ed_schedule (ohci, ed); + if (retval < 0) + goto fail; + if (ed->type == PIPE_ISOCHRONOUS) { + u16 frame = le16_to_cpu (ohci->hcca->frame_no); + + /* delay a few frames before the first TD */ + frame += max_t (u16, 8, ed->interval); + frame &= ~(ed->interval - 1); + frame |= ed->branch; + urb->start_frame = frame; + + /* yes, only URB_ISO_ASAP is supported, and + * urb->start_frame is never used as input. + */ + } + } else if (ed->type == PIPE_ISOCHRONOUS) + urb->start_frame = ed->last_iso + ed->interval; + + /* fill the TDs and link them to the ed; and + * enable that part of the schedule, if needed + * and update count of queued periodic urbs + */ + urb->hcpriv = urb_priv; + td_submit_urb (ohci, urb); + +fail: + if (retval) + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&ohci->lock, flags); + return retval; +} + +/* + * decouple the URB from the HC queues (TDs, urb_priv); it's + * already marked using urb->status. reporting is always done + * asynchronously, and we might be dealing with an urb that's + * partially transferred, or an ED with other urbs being unlinked. + */ +static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + +#ifdef OHCI_VERBOSE_DEBUG + urb_print (urb, "UNLINK", 1); +#endif + + spin_lock_irqsave (&ohci->lock, flags); + if (!ohci->disabled) { + urb_priv_t *urb_priv; + + /* Unless an IRQ completed the unlink while it was being + * handed to us, flag it for unlink and giveback, and force + * some upcoming INTR_SF to call finish_unlinks() + */ + urb_priv = urb->hcpriv; + if (urb_priv) { + urb_priv->state = URB_DEL; + if (urb_priv->ed->state == ED_OPER) + start_urb_unlink (ohci, urb_priv->ed); + } + } else { + /* + * with HC dead, we won't respect hc queue pointers + * any more ... just clean up every urb's memory. + */ + if (urb->hcpriv) { + spin_unlock (&ohci->lock); + finish_urb (ohci, urb, NULL); + spin_lock (&ohci->lock); + } + } + spin_unlock_irqrestore (&ohci->lock, flags); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* frees config/altsetting state for endpoints, + * including ED memory, dummy TD, and bulk/intr data toggle + */ + +static void +ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int epnum = ep & USB_ENDPOINT_NUMBER_MASK; + unsigned long flags; + struct ed *ed; + + /* ASSERT: any requests/urbs are being unlinked */ + /* ASSERT: nobody can be submitting urbs for this any more */ + + epnum <<= 1; + if (epnum != 0 && !(ep & USB_DIR_IN)) + epnum |= 1; + +rescan: + spin_lock_irqsave (&ohci->lock, flags); + ed = dev->ep [epnum]; + if (!ed) + goto done; + + if (!HCD_IS_RUNNING (ohci->hcd.state) || ohci->disabled) + ed->state = ED_IDLE; + switch (ed->state) { + case ED_UNLINK: /* wait for hw to finish? */ + spin_unlock_irqrestore (&ohci->lock, flags); + set_current_state (TASK_UNINTERRUPTIBLE); + schedule_timeout (1); + goto rescan; + case ED_IDLE: /* fully unlinked */ + if (list_empty (&ed->td_list)) { + td_free (ohci, ed->dummy); + ed_free (ohci, ed); + break; + } + /* else FALL THROUGH */ + default: + /* caller was supposed to have unlinked any requests; + * that's not our job. can't recover; must leak ed. + */ + ohci_err (ohci, "ed %p (#%d) state %d%s\n", + ed, epnum, ed->state, + list_empty (&ed->td_list) ? "" : "(has tds)"); + td_free (ohci, ed->dummy); + break; + } + dev->ep [epnum] = 0; +done: + spin_unlock_irqrestore (&ohci->lock, flags); + return; +} + +static int ohci_get_frame (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + return le16_to_cpu (ohci->hcca->frame_no); +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (struct ohci_hcd *ohci) +{ + u32 temp; + u32 ints; + u32 control; + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + // acknowledge all pending interrupts + ints = readl(&ohci->regs->intrstatus); + writel (ints, &ohci->regs->intrstatus); + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + // takeover without negotiation - there is noone to negotiate with + control = readl (&ohci->regs->control) & ~OHCI_CTRL_IR; + writel (control, &ohci->regs->control); + } + + ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n", + hcd_to_bus (&ohci->hcd)->bus_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers); RemoteWakeupConnected + * saved if boot firmware (BIOS/SMM/...) told us it's connected + */ + ohci->hc_control = readl (&ohci->regs->control); + ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ + writel (ohci->hc_control, &ohci->regs->control); + // flush those pci writes + (void) readl (&ohci->regs->control); + wait_ms (50); + + /* HC Reset requires max 10 us delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + temp = 30; /* ... allow extra time */ + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--temp == 0) { + ohci_err (ohci, "USB HC reset timed out!\n"); + return -1; + } + udelay (1); + } + + /* now we're in the SUSPEND state ... must go OPERATIONAL + * within 2msec else HC enters RESUME + * + * ... but some hardware won't init fmInterval "by the book" + * (SiS, OPTi ...), so reset again instead. SiS doesn't need + * this if we write fmInterval after we're OPERATIONAL. + */ + writel (ohci->hc_control, &ohci->regs->control); + // flush those pci writes + (void) readl (&ohci->regs->control); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#define FI 0x2edf /* 12000 bits per frame (-1) */ +#define LSTHRESH 0x628 /* lowspeed bit threshold */ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub + */ +static int hc_start (struct ohci_hcd *ohci) +{ + u32 mask, tmp; + struct usb_device *udev; + struct usb_bus *bus; + + spin_lock_init (&ohci->lock); + ohci->disabled = 1; + ohci->sleeping = 0; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + /* a reset clears this */ + writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); +// usbprintk("HCCA: %p \n",ohci->regs->hcca); + + /* force default fmInterval (we won't adjust it); init thresholds + * for last FS and LS packets, reserve 90% for periodic. + */ + writel ((((6 * (FI - 210)) / 7) << 16) | FI, &ohci->regs->fminterval); + writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart); + writel (LSTHRESH, &ohci->regs->lsthresh); + + /* some OHCI implementations are finicky about how they init. + * bogus values here mean not even enumeration could work. + */ + if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 + || !readl (&ohci->regs->periodicstart)) { + ohci_err (ohci, "init err\n"); + return -EOVERFLOW; + } + + /* start controller operations */ + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* Choose the interrupts we care about now, others later on demand */ + mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH; + writel (mask, &ohci->regs->intrstatus); + writel (mask, &ohci->regs->intrenable); + + /* handle root hub init quirks ... */ + tmp = roothub_a (ohci); + tmp &= ~(RH_A_PSM | RH_A_OCPM); + if (ohci->flags & OHCI_QUIRK_SUPERIO) { + /* NSC 87560 and maybe others */ + tmp |= RH_A_NOCP; + tmp &= ~(RH_A_POTPGT | RH_A_NPS); + } else { + /* hub power always on; required for AMD-756 and some + * Mac platforms, use this mode everywhere by default + */ + tmp |= RH_A_NPS; + } + writel (tmp, &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); + writel (0, &ohci->regs->roothub.b); + // flush those pci writes + (void) readl (&ohci->regs->control); + + // POTPGT delay is bits 24-31, in 2 ms units. + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + bus = hcd_to_bus (&ohci->hcd); + bus->root_hub = udev = usb_alloc_dev (NULL, bus); + ohci->hcd.state = USB_STATE_READY; + if (!udev) { + disable (ohci); + ohci->hc_control &= ~OHCI_CTRL_HCFS; + writel (ohci->hc_control, &ohci->regs->control); + ohci_err(ohci,"out of mem"); + return -ENOMEM; + } + + usb_connect (udev); + udev->speed = USB_SPEED_FULL; + if (hcd_register_root (&ohci->hcd) != 0) { + usb_put_dev (udev); + bus->root_hub = NULL; + disable (ohci); + ohci->hc_control &= ~OHCI_CTRL_HCFS; + writel (ohci->hc_control, &ohci->regs->control); + return -ENODEV; + } + create_debug_files (ohci); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ohci_regs *regs = ohci->regs; + int ints; + + /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */ + if ((ohci->hcca->done_head != 0) + && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + + /* cardbus/... hardware gone before remove() */ + } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { + disable (ohci); + ohci_dbg (ohci, "device removed!\n"); + return; + + /* interrupt for some other device? */ + } else if ((ints &= readl (®s->intrenable)) == 0) { + return; + } + + if (ints & OHCI_INTR_UE) { + disable (ohci); + ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); + // e.g. due to PCI Master/Target Abort + + ohci_dump (ohci, 1); + hc_reset (ohci); + } + + if (ints & OHCI_INTR_WDH) { + writel (OHCI_INTR_WDH, ®s->intrdisable); + dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + /* could track INTR_SO to reduce available PCI/... bandwidth */ + + /* handle any pending URB/ED unlinks, leaving INTR_SF enabled + * when there's still unlinking to be done (next frame). + */ + spin_lock (&ohci->lock); + if (ohci->ed_rm_list) + finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no), + ptregs); + if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list) + writel (OHCI_INTR_SF, ®s->intrdisable); + spin_unlock (&ohci->lock); + + writel (ints, ®s->intrstatus); + writel (OHCI_INTR_MIE, ®s->intrenable); + // flush those pci writes + (void) readl (&ohci->regs->control); +} + +/*-------------------------------------------------------------------------*/ + +static void ohci_stop (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ohci_regs *regs = ohci->regs; + int ints; + + ohci_dbg (ohci, "stop %s controller%s\n", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + ohci->disabled ? " (disabled)" : "" + ); + ohci_dump (ohci, 1); + + if (!ohci->disabled) + hc_reset (ohci); + + // Disable all interrupts + writel (OHCI_INTR_MIE, ®s->intrdisable); + // acknowledge all pending interrupts + ints = readl(®s->intrstatus); + writel (ints, ®s->intrstatus); + // flush register writes + (void) readl (&ohci->regs->control); + + remove_debug_files (ohci); + ohci_mem_cleanup (ohci); + if (ohci->hcca) { + pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); + ohci->hcca = NULL; + ohci->hcca_dma = 0; + } +} + +/*-------------------------------------------------------------------------*/ + +// FIXME: this restart logic should be generic, +// and handle full hcd state cleanup + +/* controller died; cleanup debris, then restart */ +/* must not be called from interrupt context */ + +#ifdef CONFIG_PM +static int hc_restart (struct ohci_hcd *ohci) +{ + int temp; + int i; + + ohci->disabled = 1; + ohci->sleeping = 0; + if (hcd_to_bus (&ohci->hcd)->root_hub) + usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub); + + /* empty the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; + + /* no EDs to remove */ + ohci->ed_rm_list = NULL; + + /* empty control and bulk lists */ + ohci->ed_controltail = NULL; + ohci->ed_bulktail = NULL; + + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + ohci_err (ohci, "can't restart, %d\n", temp); + return temp; + } else + ohci_dbg (ohci, "restart complete\n"); + return 0; +} +#endif + +/*-------------------------------------------------------------------------*/ + +#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC + +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_LICENSE ("GPL"); + +#ifdef CONFIG_PCI +#include "ohci-pci.c" +#endif + +#ifdef CONFIG_SA1111 +#include "ohci-sa1111.c" +#endif + +#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111)) +#error "missing bus glue for ohci-hcd" +#endif diff --git a/reactos/drivers/usb/cromwell/host/ohci-hub.c b/reactos/drivers/usb/cromwell/host/ohci-hub.c new file mode 100644 index 00000000000..03be82741e0 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-hub.c @@ -0,0 +1,271 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * This file is licenced under GPL + */ + +/*-------------------------------------------------------------------------*/ + +/* + * OHCI Root Hub ... the nonsharable stuff + * + * Registers don't need cpu_to_le32, that happens transparently + */ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (temp == -1) \ + disable (hc); \ + else if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci_hcd *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci_hcd *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci_hcd *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci_hcd *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + +/*-------------------------------------------------------------------------*/ + +#define dbg_port(hc,label,num,value) \ + ohci_dbg (hc, \ + "%s roothub.portstatus [%d] " \ + "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ + label, num, temp, \ + (temp & RH_PS_PRSC) ? " PRSC" : "", \ + (temp & RH_PS_OCIC) ? " OCIC" : "", \ + (temp & RH_PS_PSSC) ? " PSSC" : "", \ + (temp & RH_PS_PESC) ? " PESC" : "", \ + (temp & RH_PS_CSC) ? " CSC" : "", \ + \ + (temp & RH_PS_LSDA) ? " LSDA" : "", \ + (temp & RH_PS_PPS) ? " PPS" : "", \ + (temp & RH_PS_PRS) ? " PRS" : "", \ + (temp & RH_PS_POCI) ? " POCI" : "", \ + (temp & RH_PS_PSS) ? " PSS" : "", \ + \ + (temp & RH_PS_PES) ? " PES" : "", \ + (temp & RH_PS_CCS) ? " CCS" : "" \ + ); + + +/*-------------------------------------------------------------------------*/ + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +ohci_hub_status_data (struct usb_hcd *hcd, char *buf) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ports, i, changed = 0, length = 1; + + ports = roothub_a (ohci) & RH_A_NDP; + if (ports > MAX_ROOT_PORTS) { + if (ohci->disabled) + return -ESHUTDOWN; + ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", + ports, readl (&ohci->regs->roothub.a) & RH_A_NDP); + /* retry later; "should not happen" */ + return 0; + } + + /* init status */ + if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) + buf [0] = changed = 1; + else + buf [0] = 0; + if (ports > 7) { + buf [1] = 0; + length++; + } + + /* look at each port */ + for (i = 0; i < ports; i++) { + u32 status = roothub_portstatus (ohci, i); + + status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC + | RH_PS_OCIC | RH_PS_PRSC; + if (status) { + changed = 1; + if (i < 7) + buf [0] |= 1 << (i + 1); + else + buf [1] |= 1 << (i - 7); + } + } + return changed ? length : 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +ohci_hub_descriptor ( + struct ohci_hcd *ohci, + struct usb_hub_descriptor *desc +) { + u32 rh = roothub_a (ohci); + int ports = rh & RH_A_NDP; + u16 temp; + + desc->bDescriptorType = 0x29; + desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; + temp = 1 + (ports / 8); + desc->bDescLength = 7 + 2 * temp; + + temp = 0; + if (rh & RH_A_PSM) /* per-port power switching? */ + temp |= 0x0001; + if (rh & RH_A_NOCP) /* no overcurrent reporting? */ + temp |= 0x0010; + else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */ + temp |= 0x0008; + desc->wHubCharacteristics = cpu_to_le16 (temp); + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + rh = roothub_b (ohci); + desc->bitmap [0] = rh & RH_B_DR; + if (ports > 7) { + desc->bitmap [1] = (rh & RH_B_DR) >> 8; + desc->bitmap [2] = desc->bitmap [3] = 0xff; + } else + desc->bitmap [1] = 0xff; +} + +/*-------------------------------------------------------------------------*/ + +static int ohci_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ports = hcd_to_bus (hcd)->root_hub->maxchild; + u32 temp; + int retval = 0; + + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: + writel (RH_HS_OCIC, &ohci->regs->roothub.status); + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + temp = RH_PS_CCS; + break; + case USB_PORT_FEAT_C_ENABLE: + temp = RH_PS_PESC; + break; + case USB_PORT_FEAT_SUSPEND: + temp = RH_PS_POCI; + break; + case USB_PORT_FEAT_C_SUSPEND: + temp = RH_PS_PSSC; + break; + case USB_PORT_FEAT_POWER: + temp = RH_PS_LSDA; + break; + case USB_PORT_FEAT_C_CONNECTION: + temp = RH_PS_CSC; + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + temp = RH_PS_OCIC; + break; + case USB_PORT_FEAT_C_RESET: + temp = RH_PS_PRSC; + break; + default: + goto error; + } + writel (temp, &ohci->regs->roothub.portstatus [wIndex]); + // readl (&ohci->regs->roothub.portstatus [wIndex]); + break; + case GetHubDescriptor: + ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); + break; + case GetHubStatus: + temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE); + *(u32 *) buf = cpu_to_le32 (temp); + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = roothub_portstatus (ohci, wIndex); + *(u32 *) buf = cpu_to_le32 (temp); + +#ifndef OHCI_VERBOSE_DEBUG + if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ +#endif + dbg_port (ohci, "GetStatus", wIndex + 1, temp); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: + // FIXME: this can be cleared, yes? + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case SetPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + writel (RH_PS_PSS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + case USB_PORT_FEAT_POWER: + writel (RH_PS_PPS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + case USB_PORT_FEAT_RESET: + temp = readl (&ohci->regs->roothub.portstatus [wIndex]); + if (temp & RH_PS_CCS) + writel (RH_PS_PRS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + default: + goto error; + } + break; + + default: +error: + /* "protocol stall" on error */ + retval = -EPIPE; + } + return retval; +} + diff --git a/reactos/drivers/usb/cromwell/host/ohci-mem.c b/reactos/drivers/usb/cromwell/host/ohci-mem.c new file mode 100644 index 00000000000..85371e9756a --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-mem.c @@ -0,0 +1,146 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * This file is licenced under the GPL. + */ + +/*-------------------------------------------------------------------------*/ + +/* + * There's basically three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use pci_pool or pci_alloc_consistent + * - driver buffers, read/written by HC ... the hcd glue or the + * device driver provides us with dma addresses + * + * There's also PCI "register" data, which is memory mapped. + * No memory seen by this driver is pagable. + */ + +/*-------------------------------------------------------------------------*/ + +static struct usb_hcd *ohci_hcd_alloc (void) +{ + struct ohci_hcd *ohci; + + ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL); + if (ohci != 0) { + memset (ohci, 0, sizeof (struct ohci_hcd)); + return &ohci->hcd; + } + return 0; +} + +static void ohci_hcd_free (struct usb_hcd *hcd) +{ + kfree (hcd_to_ohci (hcd)); +} + +/*-------------------------------------------------------------------------*/ + +static int ohci_mem_init (struct ohci_hcd *ohci) +{ + ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, + sizeof (struct td), + 32 /* byte alignment */, + 0 /* no page-crossing issues */); + if (!ohci->td_cache) + return -ENOMEM; + ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev, + sizeof (struct ed), + 16 /* byte alignment */, + 0 /* no page-crossing issues */); + if (!ohci->ed_cache) { + pci_pool_destroy (ohci->td_cache); + return -ENOMEM; + } + return 0; +} + +static void ohci_mem_cleanup (struct ohci_hcd *ohci) +{ + if (ohci->td_cache) { + pci_pool_destroy (ohci->td_cache); + ohci->td_cache = 0; + } + if (ohci->ed_cache) { + pci_pool_destroy (ohci->ed_cache); + ohci->ed_cache = 0; + } +} + +/*-------------------------------------------------------------------------*/ + +/* ohci "done list" processing needs this mapping */ +static inline struct td * +dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) +{ + struct td *td; + + td_dma &= TD_MASK; + td = hc->td_hash [TD_HASH_FUNC(td_dma)]; + while (td && td->td_dma != td_dma) + td = td->td_hash; + return td; +} + +/* TDs ... */ +static struct td * +td_alloc (struct ohci_hcd *hc, int mem_flags) +{ + dma_addr_t dma; + struct td *td; + + td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); + if (td) { + /* in case hc fetches it, make it look dead */ + memset (td, 0, sizeof *td); + td->hwNextTD = cpu_to_le32 (dma); + td->td_dma = dma; + /* hashed in td_fill */ + } + return td; +} + +static void +td_free (struct ohci_hcd *hc, struct td *td) +{ + struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)]; + + while (*prev && *prev != td) + prev = &(*prev)->td_hash; + if (*prev) + *prev = td->td_hash; + else if ((td->hwINFO & TD_DONE) != 0) + ohci_dbg (hc, "no hash for td %p\n", td); + pci_pool_free (hc->td_cache, td, td->td_dma); +} + +/*-------------------------------------------------------------------------*/ + +/* EDs ... */ +static struct ed * +ed_alloc (struct ohci_hcd *hc, int mem_flags) +{ + dma_addr_t dma; + struct ed *ed; + + ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma); + if (ed) { + memset (ed, 0, sizeof (*ed)); + INIT_LIST_HEAD (&ed->td_list); + ed->dma = dma; + } + return ed; +} + +static void +ed_free (struct ohci_hcd *hc, struct ed *ed) +{ + pci_pool_free (hc->ed_cache, ed, ed->dma); +} + diff --git a/reactos/drivers/usb/cromwell/host/ohci-pci.c b/reactos/drivers/usb/cromwell/host/ohci-pci.c new file mode 100644 index 00000000000..1e7fd945f21 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-pci.c @@ -0,0 +1,405 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * PCI Bus Glue + * + * This file is licenced under the GPL. + */ + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#include +#include +#ifndef CONFIG_PM +# define CONFIG_PM +#endif +#endif + +#ifndef CONFIG_PCI +#error "This file is PCI bus glue. CONFIG_PCI must be defined." +#endif + +#include "../linux/pci_ids.h" + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_pci_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if (hcd->pdev) { + ohci->hcca = pci_alloc_consistent (hcd->pdev, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; + + /* AMD 756, for most chips (early revs), corrupts register + * values on read ... so enable the vendor workaround. + */ + if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD + && hcd->pdev->device == 0x740c) { + ohci->flags = OHCI_QUIRK_AMD756; + ohci_info (ohci, "AMD756 erratum 4 workaround\n"); + } + + /* FIXME for some of the early AMD 760 southbridges, OHCI + * won't work at all. blacklist them. + */ + + /* Apple's OHCI driver has a lot of bizarre workarounds + * for this chip. Evidently control and bulk lists + * can get confused. (B&W G3 models, and ...) + */ + else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI + && hcd->pdev->device == 0xc861) { + ohci_info (ohci, + "WARNING: OPTi workarounds unavailable\n"); + } + + /* Check for NSC87560. We have to look at the bridge (fn1) to + * identify the USB (fn2). This quirk might apply to more or + * even all NSC stuff. + */ + else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { + struct pci_dev *b, *hc; + + hc = hcd->pdev; + b = pci_find_slot (hc->bus->number, + PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); + if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO + && b->vendor == PCI_VENDOR_ID_NS) { + ohci->flags |= OHCI_QUIRK_SUPERIO; + ohci_info (ohci, "Using NSC SuperIO setup\n"); + } + } + + } + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + ohci_err (ohci, "can't start\n"); + ohci_stop (hcd); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +#ifdef CONFIG_PM + +static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + u16 cmd; + + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { + ohci_dbg (ohci, "can't suspend (state is %s)\n", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); + return -EIO; + } + + /* act as if usb suspend can always be used */ + ohci_dbg (ohci, "suspend to %d\n", state); + ohci->sleeping = 1; + + /* First stop processing */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->hc_control &= + ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + (void) readl (&ohci->regs->intrstatus); + spin_unlock_irqrestore (&ohci->lock, flags); + + /* Wait a frame or two */ + mdelay (1); + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + mdelay (1); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (hcd->pdev->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ +#endif + + /* Enable remote wakeup */ + writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, + &ohci->regs->intrenable); + + /* Suspend chip and let things settle down a bit */ + ohci->hc_control = OHCI_USB_SUSPEND; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (500); /* No schedule here ! */ + + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { + case OHCI_USB_RESET: + ohci_dbg (ohci, "suspend->reset ?\n"); + break; + case OHCI_USB_RESUME: + ohci_dbg (ohci, "suspend->resume ?\n"); + break; + case OHCI_USB_OPER: + ohci_dbg (ohci, "suspend->operational ?\n"); + break; + case OHCI_USB_SUSPEND: + ohci_dbg (ohci, "suspended\n"); + break; + } + + /* In some rare situations, Apple's OHCI have happily trashed + * memory during sleep. We disable its bus master bit during + * suspend + */ + pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); + } +#endif + return 0; +} + + +static int ohci_pci_resume (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int temp; + int retval = 0; + unsigned long flags; + +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif + /* did we suspend, or were we powered off? */ + ohci->hc_control = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + +#ifdef DEBUG + /* the registers may look crazy here */ + ohci_dump_status (ohci, 0, 0); +#endif + + /* Re-enable bus mastering */ + pci_set_master (ohci->hcd.pdev); + + switch (temp) { + + case OHCI_USB_RESET: // lost power + ohci_info (ohci, "USB restart\n"); + retval = hc_restart (ohci); + break; + + case OHCI_USB_SUSPEND: // host wakeup + case OHCI_USB_RESUME: // remote wakeup + ohci_info (ohci, "USB continue from %s wakeup\n", + (temp == OHCI_USB_SUSPEND) + ? "host" : "remote"); + ohci->hc_control = OHCI_USB_RESUME; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (20); /* no schedule here ! */ + /* Some controllers (lucent) need a longer delay here */ + mdelay (15); + + temp = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + ohci_err (ohci, "controller won't resume\n"); + ohci->disabled = 1; + retval = -EIO; + break; + } + + /* Some chips likes being resumed first */ + writel (OHCI_USB_OPER, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (3); + + /* Then re-enable operations */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->disabled = 0; + ohci->sleeping = 0; + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } + hcd->state = USB_STATE_READY; + writel (ohci->hc_control, &ohci->regs->control); + + /* trigger a start-frame interrupt (why?) */ + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + + /* Check for a pending done list */ + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); + (void) readl (&ohci->regs->intrdisable); + spin_unlock_irqrestore (&ohci->lock, flags); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + enable_irq (hcd->pdev->irq); +#endif + if (ohci->hcca->done_head) + dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); + writel (OHCI_INTR_WDH, &ohci->regs->intrenable); + + /* assume there are TDs on the bulk and control lists */ + writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); + +// ohci_dump_status (ohci); +ohci_dbg (ohci, "sleeping = %d, disabled = %d\n", + ohci->sleeping, ohci->disabled); + break; + + default: + ohci_warn (ohci, "odd PCI resume\n"); + } + return retval; +} + +#endif /* CONFIG_PM */ + + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_pci_hc_driver = { + .description = hcd_name, + + /* + * generic hardware linkage + */ + .irq = ohci_irq, + .flags = HCD_MEMORY | HCD_USB11, + + /* + * basic lifecycle operations + */ + .start = ohci_pci_start, +#ifdef CONFIG_PM + .suspend = ohci_pci_suspend, + .resume = ohci_pci_resume, +#endif + .stop = ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + .hcd_alloc = ohci_hcd_alloc, + .hcd_free = ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = ohci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata pci_ids [] = { { + + /* handle any USB OHCI controller */ + .class = (PCI_CLASS_SERIAL_USB << 8) | 0x10, + .class_mask = ~0, + .driver_data = (unsigned long) &ohci_pci_hc_driver, + + /* no matter who makes it */ + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE (pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver ohci_pci_driver = { + .name = (char *) hcd_name, + .id_table = pci_ids, + + .probe = usb_hcd_pci_probe, + .remove = usb_hcd_pci_remove, + +#ifdef CONFIG_PM + .suspend = usb_hcd_pci_suspend, + .resume = usb_hcd_pci_resume, +#endif +}; + + +static int __init ohci_hcd_pci_init (void) +{ + printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); + if (usb_disabled()) + return -ENODEV; + + printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof (struct ed), sizeof (struct td)); + return pci_module_init (&ohci_pci_driver); +} +module_init (ohci_hcd_pci_init); + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_pci_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} +module_exit (ohci_hcd_pci_cleanup); diff --git a/reactos/drivers/usb/cromwell/host/ohci-q.c b/reactos/drivers/usb/cromwell/host/ohci-q.c new file mode 100644 index 00000000000..71e6350b87b --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci-q.c @@ -0,0 +1,1014 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * This file is licenced under the GPL. + */ + +static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) +{ + int last = urb_priv->length - 1; + + if (last >= 0) { + int i; + struct td *td; + + for (i = 0; i <= last; i++) { + td = urb_priv->td [i]; + if (td) + td_free (hc, td); + } + } + + kfree (urb_priv); +} + +/*-------------------------------------------------------------------------*/ + +/* + * URB goes back to driver, and isn't reissued. + * It's completely gone from HC data structures. + * PRECONDITION: no locks held, irqs blocked (Giveback can call into HCD.) + */ +static void +finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) +{ + // ASSERT (urb->hcpriv != 0); + + urb_free_priv (ohci, urb->hcpriv); + urb->hcpriv = NULL; + + spin_lock (&urb->lock); + if (likely (urb->status == -EINPROGRESS)) + urb->status = 0; + spin_unlock (&urb->lock); + + // what lock protects these? + switch (usb_pipetype (urb->pipe)) { + case PIPE_ISOCHRONOUS: + hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--; + break; + case PIPE_INTERRUPT: + hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--; + break; + } + +#ifdef OHCI_VERBOSE_DEBUG + urb_print (urb, "RET", usb_pipeout (urb->pipe)); +#endif + usb_hcd_giveback_urb (&ohci->hcd, urb, regs); +} + + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* search for the right schedule branch to use for a periodic ed. + * does some load balancing; returns the branch, or negative errno. + */ +static int balance (struct ohci_hcd *ohci, int interval, int load) +{ + int i, branch = -ENOSPC; + + /* iso periods can be huge; iso tds specify frame numbers */ + if (interval > NUM_INTS) + interval = NUM_INTS; + + /* search for the least loaded schedule branch of that period + * that has enough bandwidth left unreserved. + */ + for (i = 0; i < interval ; i++) { + if (branch < 0 || ohci->load [branch] > ohci->load [i]) { +#if 1 /* CONFIG_USB_BANDWIDTH */ + int j; + + /* usb 1.1 says 90% of one frame */ + for (j = i; j < NUM_INTS; j += interval) { + if ((ohci->load [j] + load) > 900) + break; + } + if (j < NUM_INTS) + continue; +#endif + branch = i; + } + } + return branch; +} + +/*-------------------------------------------------------------------------*/ + +/* both iso and interrupt requests have periods; this routine puts them + * into the schedule tree in the apppropriate place. most iso devices use + * 1msec periods, but that's not required. + */ +static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) +{ + unsigned i; + + ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n", + (ed->hwINFO & ED_ISO) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); + + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed **prev = &ohci->periodic [i]; + u32 *prev_p = &ohci->hcca->int_table [i]; + struct ed *here = *prev; + + /* sorting each branch by period (slow before fast) + * lets us share the faster parts of the tree. + * (plus maybe: put interrupt eds before iso) + */ + while (here && ed != here) { + if (ed->interval > here->interval) + break; + prev = &here->ed_next; + prev_p = &here->hwNextED; + here = *prev; + } + if (ed != here) { + ed->ed_next = here; + if (here) + ed->hwNextED = *prev_p; + wmb (); + *prev = ed; + *prev_p = cpu_to_le32p (&ed->dma); + } + ohci->load [i] += ed->load; + } + hcd_to_bus (&ohci->hcd)->bandwidth_allocated += ed->load / ed->interval; +} + +/* link an ed into one of the HC chains */ + +static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) +{ + int branch; + + ed->state = ED_OPER; + ed->ed_prev = 0; + ed->ed_next = 0; + ed->hwNextED = 0; + wmb (); + + /* we care about rm_list when setting CLE/BLE in case the HC was at + * work on some TD when CLE/BLE was turned off, and isn't quiesced + * yet. finish_unlinks() restarts as needed, some upcoming INTR_SF. + * + * control and bulk EDs are doubly linked (ed_next, ed_prev), but + * periodic ones are singly linked (ed_next). that's because the + * periodic schedule encodes a tree like figure 3-5 in the ohci + * spec: each qh can have several "previous" nodes, and the tree + * doesn't have unused/idle descriptors. + */ + switch (ed->type) { + case PIPE_CONTROL: + if (ohci->ed_controltail == NULL) { + writel (ed->dma, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->ed_next = ed; + ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (0, &ohci->regs->ed_controlcurrent); + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = ed; + break; + + case PIPE_BULK: + if (ohci->ed_bulktail == NULL) { + writel (ed->dma, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->ed_next = ed; + ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (0, &ohci->regs->ed_bulkcurrent); + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = ed; + break; + + // case PIPE_INTERRUPT: + // case PIPE_ISOCHRONOUS: + default: + branch = balance (ohci, ed->interval, ed->load); + if (branch < 0) { + ohci_dbg (ohci, + "ERR %d, interval %d msecs, load %d\n", + branch, ed->interval, ed->load); + // FIXME if there are TDs queued, fail them! + return branch; + } + ed->branch = branch; + periodic_link (ohci, ed); + } + + /* the HC may not see the schedule updates yet, but if it does + * then they'll be properly ordered. + */ + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) +{ + int i; + + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed *temp; + struct ed **prev = &ohci->periodic [i]; + u32 *prev_p = &ohci->hcca->int_table [i]; + + while (*prev && (temp = *prev) != ed) { + prev_p = &temp->hwNextED; + prev = &temp->ed_next; + } + if (*prev) { + *prev_p = ed->hwNextED; + *prev = ed->ed_next; + } + ohci->load [i] -= ed->load; + } + hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval; + + ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", + (ed->hwINFO & ED_ISO) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); +} + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed + */ +static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) +{ + ed->hwINFO |= ED_SKIP; + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + writel (0, &ohci->regs->ed_controlcurrent); + // post those pci writes + (void) readl (&ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->ed_next = ed->ed_next; + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + if (ohci->ed_controltail) + ohci->ed_controltail->ed_next = 0; + } else if (ed->ed_next) { + ed->ed_next->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + writel (0, &ohci->regs->ed_bulkcurrent); + // post those pci writes + (void) readl (&ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->ed_next = ed->ed_next; + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + if (ohci->ed_bulktail) + ohci->ed_bulktail->ed_next = 0; + } else if (ed->ed_next) { + ed->ed_next->ed_prev = ed->ed_prev; + } + break; + + // case PIPE_INTERRUPT: + // case PIPE_ISOCHRONOUS: + default: + periodic_unlink (ohci, ed); + break; + } + + /* NOTE: Except for a couple of exceptionally clean unlink cases + * (like unlinking the only c/b ED, with no TDs) HCs may still be + * caching this operational ED (or its address). Safe unlinking + * involves not marking it ED_IDLE till INTR_SF; we always do that + * if td_list isn't empty. Otherwise the race is small; but ... + */ + if (ed->state == ED_OPER) { + ed->state = ED_IDLE; + ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); + ed->hwHeadP &= ~ED_H; + wmb (); + } +} + + +/*-------------------------------------------------------------------------*/ + +/* get and maybe (re)init an endpoint. init _should_ be done only as part + * of usb_set_configuration() or usb_set_interface() ... but the USB stack + * isn't very stateful, so we re-init whenever the HC isn't looking. + */ +static struct ed *ed_get ( + struct ohci_hcd *ohci, + struct usb_device *udev, + unsigned int pipe, + int interval +) { + int is_out = !usb_pipein (pipe); + int type = usb_pipetype (pipe); + struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; + struct ed *ed; + unsigned ep; + unsigned long flags; + + ep = usb_pipeendpoint (pipe) << 1; + if (type != PIPE_CONTROL && is_out) + ep |= 1; + + spin_lock_irqsave (&ohci->lock, flags); + + if (!(ed = dev->ep [ep])) { + struct td *td; + + ed = ed_alloc (ohci, SLAB_ATOMIC); + if (!ed) { + /* out of memory */ + goto done; + } + dev->ep [ep] = ed; + + /* dummy td; end of td list for ed */ + td = td_alloc (ohci, SLAB_ATOMIC); + if (!td) { + /* out of memory */ + ed_free (ohci, ed); + ed = 0; + goto done; + } + ed->dummy = td; + ed->hwTailP = cpu_to_le32 (td->td_dma); + ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ + ed->state = ED_IDLE; + ed->type = type; + } + + /* NOTE: only ep0 currently needs this "re"init logic, during + * enumeration (after set_address, or if ep0 maxpacket >8). + */ + if (ed->state == ED_IDLE) { + u32 info; + + info = usb_pipedevice (pipe); + info |= (ep >> 1) << 7; + info |= usb_maxpacket (udev, pipe, is_out) << 16; + info = cpu_to_le32 (info); + if (udev->speed == USB_SPEED_LOW) + info |= ED_LOWSPEED; + /* only control transfers store pids in tds */ + if (type != PIPE_CONTROL) { + info |= is_out ? ED_OUT : ED_IN; + if (type != PIPE_BULK) { + /* periodic transfers... */ + if (type == PIPE_ISOCHRONOUS) + info |= ED_ISO; + else if (interval > 32) /* iso can be bigger */ + interval = 32; + ed->interval = interval; + ed->load = usb_calc_bus_time ( + udev->speed, !is_out, + type == PIPE_ISOCHRONOUS, + usb_maxpacket (udev, pipe, is_out)) + / 1000; + } + } + ed->hwINFO = info; + } + +done: + spin_unlock_irqrestore (&ohci->lock, flags); + return ed; +} + +/*-------------------------------------------------------------------------*/ + +/* request unlinking of an endpoint from an operational HC. + * put the ep on the rm_list + * real work is done at the next start frame (SF) hardware interrupt + */ +static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) +{ + ed->hwINFO |= ED_DEQUEUE; + ed->state = ED_UNLINK; + ed_deschedule (ohci, ed); + + /* SF interrupt might get delayed; record the frame counter value that + * indicates when the HC isn't looking at it, so concurrent unlinks + * behave. frame_no wraps every 2^16 msec, and changes right before + * SF is triggered. + */ + ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1; + + /* rm_list is just singly linked, for simplicity */ + ed->ed_next = ohci->ed_rm_list; + ed->ed_prev = 0; + ohci->ed_rm_list = ed; + + /* enable SOF interrupt */ + if (!ohci->sleeping) { + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + // flush those pci writes + (void) readl (&ohci->regs->control); + } +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void +td_fill (struct ohci_hcd *ohci, u32 info, + dma_addr_t data, int len, + struct urb *urb, int index) +{ + struct td *td, *td_pt; + struct urb_priv *urb_priv = urb->hcpriv; + int is_iso = info & TD_ISO; + int hash; + + // ASSERT (index < urb_priv->length); + + /* aim for only one interrupt per urb. mostly applies to control + * and iso; other urbs rarely need more than one TD per urb. + * this way, only final tds (or ones with an error) cause IRQs. + * at least immediately; use DI=6 in case any control request is + * tempted to die part way through. + * + * NOTE: could delay interrupts even for the last TD, and get fewer + * interrupts ... increasing per-urb latency by sharing interrupts. + * Drivers that queue bulk urbs may request that behavior. + */ + if (index != (urb_priv->length - 1) + || (urb->transfer_flags & URB_NO_INTERRUPT)) + info |= TD_DI_SET (6); + + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = urb_priv->ed->dummy; + urb_priv->ed->dummy = td_pt; + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->urb = urb; + td->data_dma = data; + if (!len) + data = 0; + + td->hwINFO = cpu_to_le32 (info); + if (is_iso) { + td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); + td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); + td->ed->last_iso = info & 0xffff; + } else { + td->hwCBP = cpu_to_le32 (data); + } + if (data) + td->hwBE = cpu_to_le32 (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = cpu_to_le32 (td_pt->td_dma); + + /* append to queue */ + list_add_tail (&td->td_list, &td->ed->td_list); + + /* hash it for later reverse mapping */ + hash = TD_HASH_FUNC (td->td_dma); + td->td_hash = ohci->td_hash [hash]; + ohci->td_hash [hash] = td; + + /* HC might read the TD (or cachelines) right away ... */ + wmb (); + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* Prepare all TDs of a transfer, and queue them onto the ED. + * Caller guarantees HC is active. + * Usually the ED is already on the schedule, so TDs might be + * processed as soon as they're queued. + */ +static void td_submit_urb ( + struct ohci_hcd *ohci, + struct urb *urb +) { + struct urb_priv *urb_priv = urb->hcpriv; + dma_addr_t data; + int data_len = urb->transfer_buffer_length; + int cnt = 0; + u32 info = 0; + int is_out = usb_pipeout (urb->pipe); + + /* OHCI handles the bulk/interrupt data toggles itself. We just + * use the device toggle bits for resetting, and rely on the fact + * that resetting toggle is meaningless if the endpoint is active. + */ + if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), + is_out, 1); + urb_priv->ed->hwHeadP &= ~ED_C; + } + + urb_priv->td_cnt = 0; + + if (data_len) + data = urb->transfer_dma; + else + data = 0; + + /* NOTE: TD_CC is set so we can tell which TDs the HC processed by + * using TD_CC_GET, as well as by seeing them on the done list. + * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.) + */ + switch (urb_priv->ed->type) { + + /* Bulk and interrupt are identical except for where in the schedule + * their EDs live. + */ + case PIPE_INTERRUPT: + /* ... and periodic urbs have extra accounting */ + hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++; + /* FALLTHROUGH */ + case PIPE_BULK: + info = is_out + ? TD_T_TOGGLE | TD_CC | TD_DP_OUT + : TD_T_TOGGLE | TD_CC | TD_DP_IN; + /* TDs _could_ transfer up to 8K each */ + while (data_len > 4096) { + td_fill (ohci, info, data, 4096, urb, cnt); + data += 4096; + data_len -= 4096; + cnt++; + } + /* maybe avoid ED halt on final TD short read */ + if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + info |= TD_R; + td_fill (ohci, info, data, data_len, urb, cnt); + cnt++; + if ((urb->transfer_flags & URB_ZERO_PACKET) + && cnt < urb_priv->length) { + td_fill (ohci, info, 0, 0, urb, cnt); + cnt++; + } + /* maybe kickstart bulk list */ + if (urb_priv->ed->type == PIPE_BULK) { + wmb (); + writel (OHCI_BLF, &ohci->regs->cmdstatus); + } + break; + + /* control manages DATA0/DATA1 toggle per-request; SETUP resets it, + * any DATA phase works normally, and the STATUS ack is special. + */ + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++); + if (data_len > 0) { + info = TD_CC | TD_R | TD_T_DATA1; + info |= is_out ? TD_DP_OUT : TD_DP_IN; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, urb, cnt++); + } + info = is_out + ? TD_CC | TD_DP_IN | TD_T_DATA1 + : TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, urb, cnt++); + /* maybe kickstart control list */ + wmb (); + writel (OHCI_CLF, &ohci->regs->cmdstatus); + break; + + /* ISO has no retransmit, so no toggle; and it uses special TDs. + * Each TD could handle multiple consecutive frames (interval 1); + * we could often reduce the number of TDs here. + */ + case PIPE_ISOCHRONOUS: + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + int frame = urb->start_frame; + + // FIXME scheduling should handle frame counter + // roll-around ... exotic case (and OHCI has + // a 2^16 iso range, vs other HCs max of 2^10) + frame += cnt * urb->interval; + frame &= 0xffff; + td_fill (ohci, TD_CC | TD_ISO | frame, + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } + hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++; + break; + } + // ASSERT (urb_priv->length == cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + +/* calculate transfer length/status and update the urb + * PRECONDITION: irqsafe (only for urb->status locking) + */ +static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) +{ + u32 tdINFO = le32_to_cpup (&td->hwINFO); + int cc = 0; + + list_del (&td->td_list); + + /* ISO ... drivers see per-TD length/status */ + if (tdINFO & TD_ISO) { + u16 tdPSW = le16_to_cpu (td->hwPSW [0]); + int dlen = 0; + + /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ + + cc = (tdPSW >> 12) & 0xF; + if (tdINFO & TD_CC) /* hc didn't touch? */ + return; + + if (usb_pipeout (urb->pipe)) + dlen = urb->iso_frame_desc [td->index].length; + else { + /* short reads are always OK for ISO */ + if (cc == TD_DATAUNDERRUN) + cc = TD_CC_NOERROR; + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc [td->index].actual_length = dlen; + urb->iso_frame_desc [td->index].status = cc_to_error [cc]; + + if (cc != TD_CC_NOERROR) + ohci_vdbg (ohci, + "urb %p iso td %p (%d) len %d cc %d\n", + urb, td, 1 + td->index, dlen, cc); + + /* BULK, INT, CONTROL ... drivers see aggregate length/status, + * except that "setup" bytes aren't counted and "short" transfers + * might not be reported as errors. + */ + } else { + int type = usb_pipetype (urb->pipe); + u32 tdBE = le32_to_cpup (&td->hwBE); + + cc = TD_CC_GET (tdINFO); + + /* control endpoints only have soft stalls */ + if (type != PIPE_CONTROL && cc == TD_CC_STALL) + usb_endpoint_halt (urb->dev, + usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)); + + /* update packet status if needed (short is normally ok) */ + if (cc == TD_DATAUNDERRUN + && !(urb->transfer_flags & URB_SHORT_NOT_OK)) + cc = TD_CC_NOERROR; + if (cc != TD_CC_NOERROR && cc < 0x0E) { + spin_lock (&urb->lock); + if (urb->status == -EINPROGRESS) + urb->status = cc_to_error [cc]; + spin_unlock (&urb->lock); + } + + /* count all non-empty packets except control SETUP packet */ + if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) { + if (td->hwCBP == 0) + urb->actual_length += tdBE - td->data_dma + 1; + else + urb->actual_length += + le32_to_cpup (&td->hwCBP) + - td->data_dma; + } + + if (cc != TD_CC_NOERROR && cc < 0x0E) + ohci_vdbg (ohci, + "urb %p td %p (%d) cc %d, len=%d/%d\n", + urb, td, 1 + td->index, cc, + urb->actual_length, + urb->transfer_buffer_length); + } +} + +/*-------------------------------------------------------------------------*/ + +static inline struct td * +ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) +{ + struct urb *urb = td->urb; + struct ed *ed = td->ed; + struct list_head *tmp = td->td_list.next; + u32 toggle = ed->hwHeadP & ED_C; + + /* clear ed halt; this is the td that caused it, but keep it inactive + * until its urb->complete() has a chance to clean up. + */ + ed->hwINFO |= ED_SKIP; + wmb (); + ed->hwHeadP &= ~ED_H; + + /* put any later tds from this urb onto the donelist, after 'td', + * order won't matter here: no errors, and nothing was transferred. + * also patch the ed so it looks as if those tds completed normally. + */ + while (tmp != &ed->td_list) { + struct td *next; + u32 info; + + next = list_entry (tmp, struct td, td_list); + tmp = next->td_list.next; + + if (next->urb != urb) + break; + + /* NOTE: if multi-td control DATA segments get supported, + * this urb had one of them, this td wasn't the last td + * in that segment (TD_R clear), this ed halted because + * of a short read, _and_ URB_SHORT_NOT_OK is clear ... + * then we need to leave the control STATUS packet queued + * and clear ED_SKIP. + */ + info = next->hwINFO; + info |= cpu_to_le32 (TD_DONE); + info &= ~cpu_to_le32 (TD_CC); + next->hwINFO = info; + + next->next_dl_td = rev; + rev = next; + + if (ed->hwTailP == cpu_to_le32 (next->td_dma)) + ed->hwTailP = next->hwNextTD; + ed->hwHeadP = next->hwNextTD | toggle; + } + + /* help for troubleshooting: report anything that + * looks odd ... that doesn't include protocol stalls + * (or maybe some other things) + */ + if (cc != TD_CC_STALL || !usb_pipecontrol (urb->pipe)) + ohci_dbg (ohci, + "urb %p path %s ep%d%s %08x cc %d --> status %d\n", + urb, urb->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) ? "in" : "out", + le32_to_cpu (td->hwINFO), + cc, cc_to_error [cc]); + + return rev; +} + +/* replies to the request have to be on a FIFO basis so + * we unreverse the hc-reversed done-list + */ +static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) +{ + u32 td_dma; + struct td *td_rev = NULL; + struct td *td = NULL; + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); + td_dma = le32_to_cpup (&ohci->hcca->done_head); + ohci->hcca->done_head = 0; + + /* get TD from hc's singly linked list, and + * prepend to ours. ed->td_list changes later. + */ + while (td_dma) { + int cc; + + td = dma_to_td (ohci, td_dma); + if (!td) { + ohci_err (ohci, "bad entry %8x\n", td_dma); + break; + } + + td->hwINFO |= cpu_to_le32 (TD_DONE); + cc = TD_CC_GET (le32_to_cpup (&td->hwINFO)); + + /* Non-iso endpoints can halt on error; un-halt, + * and dequeue any other TDs from this urb. + * No other TD could have caused the halt. + */ + if (cc != TD_CC_NOERROR && (td->ed->hwHeadP & ED_H)) + td_rev = ed_halted (ohci, td, cc, td_rev); + + td->next_dl_td = td_rev; + td_rev = td; + td_dma = le32_to_cpup (&td->hwNextTD); + } + spin_unlock_irqrestore (&ohci->lock, flags); + return td_rev; +} + +/*-------------------------------------------------------------------------*/ + +/* wrap-aware logic stolen from */ +#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) + +/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ +static void +finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) +{ + struct ed *ed, **last; + +rescan_all: + for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) { + struct list_head *entry, *tmp; + int completed, modified; + u32 *prev; + + /* only take off EDs that the HC isn't using, accounting for + * frame counter wraps. + */ + if (tick_before (tick, ed->tick) && !ohci->disabled) { + last = &ed->ed_next; + continue; + } + + /* reentrancy: if we drop the schedule lock, someone might + * have modified this list. normally it's just prepending + * entries (which we'd ignore), but paranoia won't hurt. + */ + *last = ed->ed_next; + ed->ed_next = 0; + modified = 0; + + /* unlink urbs as requested, but rescan the list after + * we call a completion since it might have unlinked + * another (earlier) urb + */ +rescan_this: + completed = 0; + prev = &ed->hwHeadP; + list_for_each_safe (entry, tmp, &ed->td_list) { + struct td *td; + struct urb *urb; + urb_priv_t *urb_priv; + u32 savebits; + + td = list_entry (entry, struct td, td_list); + urb = td->urb; + urb_priv = td->urb->hcpriv; + + if (urb_priv->state != URB_DEL) { + prev = &td->hwNextTD; + continue; + } + + /* patch pointers hc uses ... tail, if we're removing + * an otherwise active td, and whatever td pointer + * points to this td + */ + if (ed->hwTailP == cpu_to_le32 (td->td_dma)) + ed->hwTailP = td->hwNextTD; + savebits = *prev & ~cpu_to_le32 (TD_MASK); + *prev = td->hwNextTD | savebits; + + /* HC may have partly processed this TD */ + td_done (ohci, urb, td); + urb_priv->td_cnt++; + + /* if URB is done, clean up */ + if (urb_priv->td_cnt == urb_priv->length) { + modified = completed = 1; + spin_unlock (&ohci->lock); + finish_urb (ohci, urb, regs); + spin_lock (&ohci->lock); + } + } + if (completed && !list_empty (&ed->td_list)) + goto rescan_this; + + /* ED's now officially unlinked, hc doesn't see */ + ed->state = ED_IDLE; + ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); + ed->hwHeadP &= ~ED_H; + ed->hwNextED = 0; + + /* but if there's work queued, reschedule */ + if (!list_empty (&ed->td_list)) { + if (!ohci->disabled && !ohci->sleeping) + ed_schedule (ohci, ed); + } + + if (modified) + goto rescan_all; + } + + /* maybe reenable control and bulk lists */ + if (!ohci->disabled && !ohci->ed_rm_list) { + u32 command = 0, control = 0; + + if (ohci->ed_controltail) { + command |= OHCI_CLF; + if (!(ohci->hc_control & OHCI_CTRL_CLE)) { + control |= OHCI_CTRL_CLE; + writel (0, &ohci->regs->ed_controlcurrent); + } + } + if (ohci->ed_bulktail) { + command |= OHCI_BLF; + if (!(ohci->hc_control & OHCI_CTRL_BLE)) { + control |= OHCI_CTRL_BLE; + writel (0, &ohci->regs->ed_bulkcurrent); + } + } + + /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ + if (control) { + ohci->hc_control |= control; + writel (ohci->hc_control, &ohci->regs->control); + } + if (command) + writel (command, &ohci->regs->cmdstatus); + } +} + + + +/*-------------------------------------------------------------------------*/ + +/* + * Process normal completions (error or success) and clean the schedules. + * + * This is the main path for handing urbs back to drivers. The only other + * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of + * scanning the (re-reversed) donelist as this does. + */ +static void +dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs) +{ + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); + while (td) { + struct td *td_next = td->next_dl_td; + struct urb *urb = td->urb; + urb_priv_t *urb_priv = urb->hcpriv; + struct ed *ed = td->ed; + + /* update URB's length and status from TD */ + td_done (ohci, urb, td); + urb_priv->td_cnt++; + + /* If all this urb's TDs are done, call complete() */ + if (urb_priv->td_cnt == urb_priv->length) { + spin_unlock (&ohci->lock); + finish_urb (ohci, urb, regs); + spin_lock (&ohci->lock); + } + + /* clean schedule: unlink EDs that are no longer busy */ + if (list_empty (&ed->td_list)) + ed_deschedule (ohci, ed); + /* ... reenabling halted EDs only after fault cleanup */ + else if (!(ed->hwINFO & ED_DEQUEUE)) { + td = list_entry (ed->td_list.next, struct td, td_list); + if (!(td->hwINFO & TD_DONE)) + ed->hwINFO &= ~ED_SKIP; + } + + td = td_next; + } + spin_unlock_irqrestore (&ohci->lock, flags); +} diff --git a/reactos/drivers/usb/cromwell/host/ohci.def b/reactos/drivers/usb/cromwell/host/ohci.def new file mode 100644 index 00000000000..9bc5544dd2f --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci.def @@ -0,0 +1,2 @@ +LIBRARY ohci.sys +EXPORTS diff --git a/reactos/drivers/usb/cromwell/host/ohci.h b/reactos/drivers/usb/cromwell/host/ohci.h new file mode 100644 index 00000000000..400b505e65a --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci.h @@ -0,0 +1,406 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * This file is licenced under the GPL. + */ + +/* + * OHCI Endpoint Descriptor (ED) ... holds TD queue + * See OHCI spec, section 4.2 + * + * This is a "Queue Head" for those transfers, which is why + * both EHCI and UHCI call similar structures a "QH". + */ +struct ed { + /* first fields are hardware-specified, le32 */ + __u32 hwINFO; /* endpoint config bitmap */ + /* info bits defined by hcd */ +#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27) + /* info bits defined by the hardware */ +#define ED_ISO __constant_cpu_to_le32(1 << 15) +#define ED_SKIP __constant_cpu_to_le32(1 << 14) +#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13) +#define ED_OUT __constant_cpu_to_le32(0x01 << 11) +#define ED_IN __constant_cpu_to_le32(0x02 << 11) + __u32 hwTailP; /* tail of TD list */ + __u32 hwHeadP; /* head of TD list (hc r/w) */ +#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */ +#define ED_H __constant_cpu_to_le32(0x01) /* halted */ + __u32 hwNextED; /* next ED in list */ + + /* rest are purely for the driver's use */ + dma_addr_t dma; /* addr of ED */ + struct td *dummy; /* next TD to activate */ + + /* host's view of schedule */ + struct ed *ed_next; /* on schedule or rm_list */ + struct ed *ed_prev; /* for non-interrupt EDs */ + struct list_head td_list; /* "shadow list" of our TDs */ + + /* create --> IDLE --> OPER --> ... --> IDLE --> destroy + * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... + * some special cases : OPER --> IDLE ... + */ + u8 state; /* ED_{IDLE,UNLINK,OPER} */ +#define ED_IDLE 0x00 /* NOT linked to HC */ +#define ED_UNLINK 0x01 /* being unlinked from hc */ +#define ED_OPER 0x02 /* IS linked to hc */ + + u8 type; /* PIPE_{BULK,...} */ + + /* periodic scheduling params (for intr and iso) */ + u8 branch; + u16 interval; + u16 load; + u16 last_iso; /* iso only */ + + /* HC may see EDs on rm_list until next frame (frame_no == tick) */ + u16 tick; +} __attribute__ ((aligned(16))); + +#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ + + +/* + * OHCI Transfer Descriptor (TD) ... one per transfer segment + * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) + * and 4.3.2 (iso) + */ +struct td { + /* first fields are hardware-specified, le32 */ + __u32 hwINFO; /* transfer info bitmask */ + + /* hwINFO bits for both general and iso tds: */ +#define TD_CC 0xf0000000 /* condition code */ +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_DI 0x00E00000 /* frames before interrupt */ +#define TD_DI_SET(X) (((X) & 0x07)<< 21) + /* these two bits are available for definition/use by HCDs in both + * general and iso tds ... others are available for only one type + */ +#define TD_DONE 0x00020000 /* retired to donelist */ +#define TD_ISO 0x00010000 /* copy of ED_ISO */ + + /* hwINFO bits for general tds: */ +#define TD_EC 0x0C000000 /* error count */ +#define TD_T 0x03000000 /* data toggle state */ +#define TD_T_DATA0 0x02000000 /* DATA0 */ +#define TD_T_DATA1 0x03000000 /* DATA1 */ +#define TD_T_TOGGLE 0x00000000 /* uses ED_C */ +#define TD_DP 0x00180000 /* direction/pid */ +#define TD_DP_SETUP 0x00000000 /* SETUP pid */ +#define TD_DP_IN 0x00100000 /* IN pid */ +#define TD_DP_OUT 0x00080000 /* OUT pid */ + /* 0x00180000 rsvd */ +#define TD_R 0x00040000 /* round: short packets OK? */ + + /* (no hwINFO #defines yet for iso tds) */ + + __u32 hwCBP; /* Current Buffer Pointer (or 0) */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + /* PSW is only for ISO */ +#define MAXPSW 1 /* hardware allows 8 */ + __u16 hwPSW [MAXPSW]; + + /* rest are purely for the driver's use */ + __u8 index; + struct ed *ed; + struct td *td_hash; /* dma-->td hashtable */ + struct td *next_dl_td; + struct urb *urb; + + dma_addr_t td_dma; /* addr of this TD */ + dma_addr_t data_dma; /* addr of data it points to */ + + struct list_head td_list; /* "shadow list", TDs on same ED */ +} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */ + +#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */ + +/* + * Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW + */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 + /* 0x0A, 0x0B reserved for hardware */ +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D + /* 0x0E, 0x0F reserved for HCD */ +#define TD_NOTACCESSED 0x0F + + +/* map OHCI TD status codes (CC) to errno values */ +static const int cc_to_error [16] = { + /* No Error */ 0, + /* CRC Error */ -EILSEQ, + /* Bit Stuff */ -EPROTO, + /* Data Togg */ -EILSEQ, + /* Stall */ -EPIPE, + /* DevNotResp */ -ETIMEDOUT, + /* PIDCheck */ -EPROTO, + /* UnExpPID */ -EPROTO, + /* DataOver */ -EOVERFLOW, + /* DataUnder */ -EREMOTEIO, + /* (for hw) */ -EIO, + /* (for hw) */ -EIO, + /* BufferOver */ -ECOMM, + /* BuffUnder */ -ENOSR, + /* (for HCD) */ -EALREADY, + /* (for HCD) */ -EALREADY +}; + + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined section 4.4.1 of the OHCI spec. The HC is + * told the base address of it. It must be 256-byte aligned. + */ +struct ohci_hcca { +#define NUM_INTS 32 + __u32 int_table [NUM_INTS]; /* periodic schedule */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc [116]; + u8 what [4]; /* spec only identifies 252 bytes :) */ +} __attribute__ ((aligned(256))); + + +/* + * This is the structure of the OHCI controller's memory mapped I/O region. + * You must use readl() and writel() (in ) to access these fields!! + * Layout is in section 7 (and appendix B) of the spec. + */ +struct ohci_regs { + /* control and status registers (section 7.1) */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + + /* memory pointers (section 7.2) */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + + /* frame counters (section 7.3) */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + + /* Root hub ports (section 7.4) */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */ + __u32 portstatus [MAX_ROOT_PORTS]; + } roothub; + + /* and optional "legacy support" registers (appendix B) at 0x0100 */ + +} __attribute__ ((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + + +/* hcd-private per-urb state */ +typedef struct urb_priv { + struct ed *ed; + __u16 length; // # tds in this request + __u16 td_cnt; // tds already serviced + int state; + struct td *td [0]; // all TDs in this request + +} urb_priv_t; + +#define URB_DEL 1 + +#define TD_HASH_SIZE 64 /* power'o'two */ +// sizeof (struct td) ~= 64 == 2^6 ... +#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) + + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + +struct ohci_hcd { + spinlock_t lock; + + /* + * I/O memory used to communicate with the HC (dma-consistent) + */ + struct ohci_regs *regs; + + /* + * main memory used to communicate with the HC (dma-consistent). + * hcd adds to schedule for a live hc any time, but removals finish + * only at the start of the next frame. + */ + struct ohci_hcca *hcca; + dma_addr_t hcca_dma; + + struct ed *ed_rm_list; /* to be removed */ + + struct ed *ed_bulktail; /* last in bulk list */ + struct ed *ed_controltail; /* last in ctrl list */ + struct ed *periodic [NUM_INTS]; /* shadow int_table */ + + /* + * memory management for queue data structures + */ + struct pci_pool *td_cache; + struct pci_pool *ed_cache; + struct td *td_hash [TD_HASH_SIZE]; + + /* + * driver state + */ + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + int load [NUM_INTS]; + u32 hc_control; /* copy of hc control reg */ + + unsigned long flags; /* for HC bugs */ +#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ +#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ + // there are also chip quirks/bugs in init logic + + /* + * framework state + */ + struct usb_hcd hcd; +}; + +#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd) + +/*-------------------------------------------------------------------------*/ + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +#define ohci_dbg(ohci, fmt, args...) \ + dev_dbg ((ohci)->hcd.controller , fmt , ## args ) +#define ohci_err(ohci, fmt, args...) \ + dev_err ((ohci)->hcd.controller , fmt , ## args ) +#define ohci_info(ohci, fmt, args...) \ + dev_info ((ohci)->hcd.controller , fmt , ## args ) +#define ohci_warn(ohci, fmt, args...) \ + dev_warn ((ohci)->hcd.controller , fmt , ## args ) + +#ifdef OHCI_VERBOSE_DEBUG +# define ohci_vdbg ohci_dbg +#else +# define ohci_vdbg(ohci, fmt, args...) do { } while (0) +#endif + diff --git a/reactos/drivers/usb/cromwell/host/ohci.rc b/reactos/drivers/usb/cromwell/host/ohci.rc new file mode 100644 index 00000000000..fa183242a97 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "ohci\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0" +#include diff --git a/reactos/drivers/usb/cromwell/host/ohci_config.h b/reactos/drivers/usb/cromwell/host/ohci_config.h new file mode 100644 index 00000000000..ec73b9099f3 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci_config.h @@ -0,0 +1,5 @@ +/* + * Configs for OHCI + */ + +#define CONFIG_PCI diff --git a/reactos/drivers/usb/cromwell/host/ohci_main.c b/reactos/drivers/usb/cromwell/host/ohci_main.c new file mode 100644 index 00000000000..ffb37c81999 --- /dev/null +++ b/reactos/drivers/usb/cromwell/host/ohci_main.c @@ -0,0 +1,16 @@ +/* + ReactOS specific functions for ohci module + by Aleksey Bragin (aleksey@reactos.com) +*/ + +#include + + +/* + * Standard DriverEntry method. + */ +NTSTATUS STDCALL +DriverEntry(IN PVOID Context1, IN PVOID Context2) +{ + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/usb/cromwell/linux/asm/bitops.h b/reactos/drivers/usb/cromwell/linux/asm/bitops.h new file mode 100644 index 00000000000..f16396ad4ac --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/asm/bitops.h @@ -0,0 +1,384 @@ +#ifndef _I386_BITOPS_H +#define _I386_BITOPS_H + +/* + * Copyright 1992, Linus Torvalds. + */ + +//#include + +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +#define ADDR (*(volatile long *) addr) + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void set_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __set_bit(int nr, volatile void * addr) +{ + __asm__( + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static __inline__ void clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() + +/** + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__( + "btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__( + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +/* WARNING: non atomic and it can be reordered! */ +static __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +#if 0 /* Fool kernel-doc since it doesn't do macros yet */ +/** + * test_bit - Determine whether a bit is set + * @nr: bit number to test + * @addr: Address to start counting from + */ +static int test_bit(int nr, const volatile void * addr); +#endif + +static __inline__ int constant_test_bit(int nr, const volatile void * addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +static __inline__ int variable_test_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (ADDR),"Ir" (nr)); + return oldbit; +} + +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + constant_test_bit((nr),(addr)) : \ + variable_test_bit((nr),(addr))) + +/** + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +static __inline__ int find_first_zero_bit(void * addr, unsigned size) +{ + int d0, d1, d2; + int res; + + if (!size) + return 0; + /* This looks at memory. Mark it volatile to tell gcc not to move it around */ + __asm__ __volatile__( + "movl $-1,%%eax\n\t" + "xorl %%edx,%%edx\n\t" + "repe; scasl\n\t" + "je 1f\n\t" + "xorl -4(%%edi),%%eax\n\t" + "subl $4,%%edi\n\t" + "bsfl %%eax,%%edx\n" + "1:\tsubl %%ebx,%%edi\n\t" + "shll $3,%%edi\n\t" + "addl %%edi,%%edx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); + return res; +} + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +static __inline__ int find_next_zero_bit (void * addr, int size, int offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for zero in first byte + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (~(*p >> bit))); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No zero yet, search remaining full bytes for a zero + */ + res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); + return (offset + set + res); +} + +/** + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +static __inline__ unsigned long ffz(unsigned long word) +{ + __asm__("bsfl %1,%0" + :"=r" (word) + :"r" (~word)); + return word; +} + +#ifdef __KERNEL__ + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __inline__ int ffs(int x) +{ + int r; + + __asm__("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "rm" (x)); + return r+1; +} + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ + +#ifdef __KERNEL__ + +#define ext2_set_bit __test_and_set_bit +#define ext2_clear_bit __test_and_clear_bit +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit + +/* Bitmap functions for the minix filesystem. */ +#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) __set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ + +#endif /* _I386_BITOPS_H */ diff --git a/reactos/drivers/usb/cromwell/linux/bitops.h b/reactos/drivers/usb/cromwell/linux/bitops.h new file mode 100644 index 00000000000..6509d07ba90 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/bitops.h @@ -0,0 +1,72 @@ +#ifndef _LINUX_BITOPS_H +#define _LINUX_BITOPS_H + + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +static inline int generic_ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +static inline unsigned int generic_hweight32(unsigned int w) +{ + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +static inline unsigned int generic_hweight16(unsigned int w) +{ + unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); + res = (res & 0x3333) + ((res >> 2) & 0x3333); + res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); + return (res & 0x00FF) + ((res >> 8) & 0x00FF); +} + +static inline unsigned int generic_hweight8(unsigned int w) +{ + unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); + res = (res & 0x33) + ((res >> 2) & 0x33); + return (res & 0x0F) + ((res >> 4) & 0x0F); +} + +#include "asm/bitops.h" + + +#endif diff --git a/reactos/drivers/usb/cromwell/linux/boot.h b/reactos/drivers/usb/cromwell/linux/boot.h new file mode 100644 index 00000000000..d99b7f22427 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/boot.h @@ -0,0 +1,337 @@ +#ifndef _Boot_H_ +#define _Boot_H_ + +#include "config.h" + +/*************************************************************************** + Includes used by XBox boot code + ***************************************************************************/ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +///////////////////////////////// +// configuration + +#include "consts.h" +#include "stdint.h" +#include "cromwell_types.h" + + +unsigned int cromwell_config; +unsigned int cromwell_retryload; +unsigned int cromwell_loadbank; +unsigned int cromwell_Biostype; + +unsigned int xbox_ram; + +#define XROMWELL 0 +#define CROMWELL 1 + +#define ICON_WIDTH 64 +#define ICON_HEIGHT 64 +/* +static double min (double a, double b) +{ + if (a < b) return a; else return b; +} + +static inline double max (double a, double b) +{ + if (a > b) return a; else return b; +} +*/ +//#include "iso_fs.h" +//#include "BootVideo.h" + +//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } } + +#if 0 +extern volatile CURRENT_VIDEO_MODE_DETAILS vmode; +unsigned int video_encoder; + +volatile u32 VIDEO_CURSOR_POSX; +volatile u32 VIDEO_CURSOR_POSY; +volatile u32 VIDEO_ATTR; +volatile u32 VIDEO_LUMASCALING; +volatile u32 VIDEO_RSCALING; +volatile u32 VIDEO_BSCALING; +volatile u32 BIOS_TICK_COUNT; +volatile u32 VIDEO_VSYNC_POSITION; +volatile u32 VIDEO_VSYNC_DIR; +volatile u32 DVD_TRAY_STATE; + +u8 VIDEO_AV_MODE ; + +#define DVD_CLOSED 0 +#define DVD_CLOSING 1 +#define DVD_OPEN 2 +#define DVD_OPENING 3 + +///////////////////////////////// +// Superfunky i386 internal structures + +typedef struct gdt_t { + unsigned short m_wSize __attribute__ ((packed)); + unsigned long m_dwBase32 __attribute__ ((packed)); + unsigned short m_wDummy __attribute__ ((packed)); +} ts_descriptor_pointer; + +typedef struct { // inside an 8-byte protected mode interrupt vector + u16 m_wHandlerHighAddressLow16; + u16 m_wSelector; + u16 m_wType; + u16 m_wHandlerLinearAddressHigh16; +} ts_pm_interrupt; + +typedef enum { + EDT_UNKNOWN= 0, + EDT_XBOXFS +} enumDriveType; + +typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init + unsigned short m_fwPortBase; + unsigned short m_wCountHeads; + unsigned short m_wCountCylinders; + unsigned short m_wCountSectorsPerTrack; + unsigned long m_dwCountSectorsTotal; /* total */ + unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */ + unsigned char m_szIdentityModelNumber[40]; + unsigned char term_space_1[2]; + unsigned char m_szSerial[20]; + unsigned char term_space_2[2]; + char m_szFirmware[8]; + unsigned char term_space_3[2]; + unsigned char m_fDriveExists; + unsigned char m_fAtapi; // true if a CDROM, etc + enumDriveType m_enumDriveType; + unsigned char m_bCableConductors; // valid for device 0 if present + unsigned short m_wAtaRevisionSupported; + unsigned char s_length; + unsigned char m_length; + unsigned char m_fHasMbr; + unsigned short m_securitySettings; //This contains the contents of the ATA security regs +} tsHarddiskInfo; + +///////////////////////////////// +// LED-flashing codes +// or these together as argument to I2cSetFrontpanelLed + +enum { + I2C_LED_RED0 = 0x80, + I2C_LED_RED1 = 0x40, + I2C_LED_RED2 = 0x20, + I2C_LED_RED3 = 0x10, + I2C_LED_GREEN0 = 0x08, + I2C_LED_GREEN1 = 0x04, + I2C_LED_GREEN2 = 0x02, + I2C_LED_GREEN3 = 0x01 +}; + +/////////////////////////////// +/* BIOS-wide error codes all have b31 set */ + +enum { + ERR_SUCCESS = 0, // completed without error + + ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time + ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error + + ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test +}; + +///////////////////////////////// +// some Boot API prototypes + +//////// BootPerformPicChallengeResponseAction.c + +/* ---------------------------- IO primitives ----------------------------------------------------------- +*/ + +static __inline void IoOutputByte(u16 wAds, u8 bValue) { +// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) ); + __asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds)); +} + +static __inline void IoOutputWord(u16 wAds, u16 wValue) { +// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); + __asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds)); + } + +static __inline void IoOutputDword(u16 wAds, u32 dwValue) { +// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); + __asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds)); +} + + +static __inline u8 IoInputByte(u16 wAds) { + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds)); + return _v; +} + +static __inline u16 IoInputWord(u16 wAds) { + u16 _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds)); + return _v; +} + +static __inline u32 IoInputDword(u16 wAds) { + u32 _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds)); + return _v; +} + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + + +void BootPciInterruptEnable(void); + + // boot process +int BootPerformPicChallengeResponseAction(void); + // LED control (see associated enum above) +int I2cSetFrontpanelLed(u8 b); + +#define bprintf(...) + +#if PRINT_TRACE +#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__); +#else +#define TRACE +#endif + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *m_plistentryNext; + struct _LIST_ENTRY *m_plistentryPrevious; +} LIST_ENTRY; + +void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew); +void ListEntryRemove(LIST_ENTRY *plistentryCurrent); + +////////// BootPerformXCodeActions.c + +int BootPerformXCodeActions(void); + +#include "BootEEPROM.h" +#include "BootParser.h" + +////////// BootStartBios.c + +void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom); +int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent); + +////////// BootResetActions.c +void ClearIDT (void); +void BootResetAction(void); +void BootCpuCache(bool fEnable) ; +int printk(const char *szFormat, ...); +void BiosCmosWrite(u8 bAds, u8 bData); +u8 BiosCmosRead(u8 bAds); + + +///////// BootPciPeripheralInitialization.c +void BootPciPeripheralInitialization(void); +void BootAGPBUSInitialization(void); +void BootDetectMemorySize(void); +extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval); +extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval); +extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval); +extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval); +extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes); +extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes); + +void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func, + unsigned int reg_off, unsigned char byteval); +u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); +u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw); +u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); + +///////// BootPerformPicChallengeResponseAction.c + +int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite); +int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite); +bool I2CGetTemperature(int *, int *); +void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask); + +///////// BootIde.c + +extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives +int BootIdeInit(void); +int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes); +int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult); +int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn); +int BootIdeSetTransferMode(int nIndexDrive, int nMode); +int BootIdeWaitNotBusy(unsigned uIoBase); +bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError); +void BootIdeAtapiPrintkFriendlyError(int nDriveIndex); + +///////// BootUSB.c + +void BootStopUSB(void); +void BootStartUSB(void); +void USBGetEvents(void); + +#include "xpad.h" + +extern struct xpad_data XPAD_current[4]; +extern struct xpad_data XPAD_last[4]; + +extern void wait_ms(u32 ticks); +extern void wait_us(u32 ticks); +extern void wait_smalldelay(void); + + +void * memcpy(void *dest, const void *src, size_t size); +void * memset(void *dest, int data, size_t size); +int memcmp(const void *buffer1, const void *buffer2, size_t num); +int _strncmp(const char *sz1, const char *sz2, int nMax); +char * strcpy(char *sz, const char *szc); +char * _strncpy (char * dest, const char * src, size_t n); +void chrreplace(char *string, char search, char ch); + +#define printf printk +#define sleep wait_ms +int tolower(int ch); +int isspace (int c); + +void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength); +void * malloc(size_t size); +void free(void *); + +extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde; +extern volatile bool fSeenPowerdown; +typedef enum { + ETS_OPEN_OR_OPENING=0, + ETS_CLOSING, + ETS_CLOSED +} TRAY_STATE; +extern volatile TRAY_STATE traystate; + + +extern void BootInterruptsWriteIdt(void); +#endif +int copy_swap_trim(unsigned char *dst, unsigned char *src, int len); +void HMAC_SHA1( unsigned char *result, + unsigned char *key, int key_length, + unsigned char *text1, int text1_length, + unsigned char *text2, int text2_length ); + +char *strrchr0(char *string, char ch); + +#endif // _Boot_H_ diff --git a/reactos/drivers/usb/cromwell/linux/consts.h b/reactos/drivers/usb/cromwell/linux/consts.h new file mode 100644 index 00000000000..755bf6a5128 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/consts.h @@ -0,0 +1,70 @@ +#ifndef _Consts_H_ +#define _Consts_H_ + +/* + * + * includes for startup code in a form usable by the .S files + * + */ + + /*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#define PCI_CFG_ADDR 0x0CF8 +#define PCI_CFG_DATA 0x0CFC + + +#define I2C_IO_BASE 0xc000 + +#define BUS_0 0 +#define BUS_1 1 + +#define DEV_0 0 +#define DEV_1 1 +#define DEV_2 2 +#define DEV_3 3 +#define DEV_4 4 +#define DEV_5 5 +#define DEV_6 6 +#define DEV_7 7 +#define DEV_8 8 +#define DEV_9 9 +#define DEV_a 0xa +#define DEV_b 0xb +#define DEV_c 0xc +#define DEV_d 0xd +#define DEV_e 0xe +#define DEV_f 0xf +#define DEV_10 0x10 +#define DEV_11 0x11 +#define DEV_12 0x12 +#define DEV_13 0x13 +#define DEV_14 0x14 +#define DEV_15 0x15 +#define DEV_16 0x16 +#define DEV_17 0x17 +#define DEV_18 0x18 +#define DEV_19 0x19 +#define DEV_1a 0x1a +#define DEV_1b 0x1b +#define DEV_1c 0x1c +#define DEV_1d 0x1d +#define DEV_1e 0x1e +#define DEV_1f 0x1f + +#define FUNC_0 0 +/* +#define boot_post_macro(value) \ + movb $(value), %al ;\ + outb %al, $0x80 +*/ + +#endif // _Consts_H_ + + diff --git a/reactos/drivers/usb/cromwell/linux/cromwell_types.h b/reactos/drivers/usb/cromwell/linux/cromwell_types.h new file mode 100644 index 00000000000..d03e9158393 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/cromwell_types.h @@ -0,0 +1,27 @@ +#ifndef cromwell_types_h +#define cromwell_types_h + +///////////////////////////////// +// some typedefs to make for easy sizing + +//typedef unsigned long ULONG; +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; +#ifndef bool_already_defined_ + typedef int bool; +#endif +typedef unsigned long RGBA; // LSB=R -> MSB = A +//typedef long long __int64; + +#define guint int +#define guint8 unsigned char + +#define true 1 +#define false 0 + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#endif /* #ifndef cromwell_types_h */ diff --git a/reactos/drivers/usb/cromwell/linux/errno.h b/reactos/drivers/usb/cromwell/linux/errno.h new file mode 100644 index 00000000000..dcd2ede98d7 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/errno.h @@ -0,0 +1,132 @@ +#ifndef _I386_ERRNO_H +#define _I386_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#endif diff --git a/reactos/drivers/usb/cromwell/linux/linux_wrapper.h b/reactos/drivers/usb/cromwell/linux/linux_wrapper.h new file mode 100644 index 00000000000..bcb1987b98b --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/linux_wrapper.h @@ -0,0 +1,722 @@ +/* + * linux-wrapper.h + * + * Hard coded Linux kernel replacements for x86 + * + * (c) 2003 Georg Acher (georg@acher.org) + * + * Emulation of: + * typedefs + * structs + * macros + * + * All structs and prototypes are based on kernel source 2.5.72 + * + * #include + */ + +/*------------------------------------------------------------------------*/ +/* Typedefs */ +/*------------------------------------------------------------------------*/ +#include "cromwell_types.h" + +typedef unsigned int __u32; +//typedef __u32 u32; +typedef unsigned short __u16; +//typedef __u16 u16; +typedef unsigned char __u8; +//typedef __u8 u8; + +typedef short s16; + +typedef u32 dma_addr_t; + +typedef int spinlock_t; +typedef int atomic_t; +#ifndef STANDALONE +typedef int mode_t; +typedef int pid_t; +typedef int ssize_t; + +#endif +typedef int irqreturn_t; +typedef unsigned long kernel_ulong_t; + +typedef int wait_queue_head_t; +/*------------------------------------------------------------------------*/ +/* Stuff from xbox/linux environment */ +/*------------------------------------------------------------------------*/ + +#include "list.h" + +#ifndef STANDALONE +#ifdef MODULE +typedef int size_t; +#define NULL ((void*)0) +extern void * memset(void *,int,unsigned int); +extern void * memcpy(void *,const void *,unsigned int); +#if 0 +extern char * strcpy(char *,const char *); +#else +static inline char * strcpy(char * dest,const char *src) +{ +int d0, d1, d2; +__asm__ __volatile__( + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); +return dest; +} +#endif +extern size_t strlen(const char *); + +extern int memcmp(const void *,const void *,unsigned int); + +#else +#include "boot.h" +#include "config.h" +#endif +#else +#include +#include +#include +#include "consts.h" +#include +#endif + +/*------------------------------------------------------------------------*/ +/* General structs */ +/*------------------------------------------------------------------------*/ + +struct timer_list { + void (*function)(unsigned long); + unsigned long data; + int expires; + struct list_head timer_list; +}; + +struct work_struct { + void (*func)(void *); +}; +struct device { + char name[128]; + struct bus_type *bus; + int dma_mask; + char bus_id[16]; + struct device_driver* driver; + void *driver_data; + struct device *parent; + struct list_head driver_list; + void (*release)(struct device * dev); +}; +struct class_device{int a;}; +struct semaphore{int a;}; + +struct device_driver{ + char *name; + struct bus_type *bus; + int (*probe) (struct device * dev); + int (*remove) (struct device * dev); + struct list_head devices; +}; + +struct bus_type { + char * name; + int (*match)(struct device * dev, struct device_driver * drv); + struct device * (*add) (struct device * parent, char * bus_id); + int (*hotplug) (struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); +}; + +struct dummy_process +{ + int flags; +}; + +struct pt_regs +{ + int a; +}; +struct completion { + unsigned int done; + wait_queue_head_t wait; +}; + +/* from mod_devicetable.h */ + +struct usb_device_id { + /* which fields to match against? */ + __u16 match_flags; + + /* Used for product specific matches; range is inclusive */ + __u16 idVendor; + __u16 idProduct; + __u16 bcdDevice_lo; + __u16 bcdDevice_hi; + + /* Used for device class matches */ + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + + /* Used for interface class matches */ + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + + /* not matched against */ + kernel_ulong_t driver_info; +}; + +/* Some useful macros to use to create struct usb_device_id */ +#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 +#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 +#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 +#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 +#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 +#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 +#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 + +/*------------------------------------------------------------------------*/ +/* imported functions from top-level */ +/*------------------------------------------------------------------------*/ + +//void zxprintf(char* fmt, ...); +//void zxsprintf(char *buffer, char* fmt, ...); +//int zxsnprintf(char *buffer, size_t s, char* fmt, ...); + +/*------------------------------------------------------------------------*/ +/* PCI structs (taken from linux/pci.h et al., but slightly modified) */ +/*------------------------------------------------------------------------*/ + +struct pci_dev { + int vendor; + int device; + struct pci_bus *bus; + int irq; + char *slot_name; + struct device dev; + int base[4]; + int flags[4]; + void * data; +}; + +struct pci_bus { + unsigned char number; +}; + +struct pci_device_id { + __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ + __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ + __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +struct pci_driver { + struct list_head node; + char *name; + const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ + int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ + void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */ + int (*suspend) (struct pci_dev *dev, u32 state); /* Device suspended */ + int (*resume) (struct pci_dev *dev); /* Device woken up */ + int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ +}; + +struct scatterlist +{ + int page; + int offset; + int length; +}; + +struct usbdevfs_hub_portinfo +{ + int nports; + int port[8]; +}; + +/*------------------------------------------------------------------------*/ +/* constant defines */ +/*------------------------------------------------------------------------*/ + +#define TASK_UNINTERRUPTIBLE 0 +#define HZ 100 /* Don't rely on that... */ +#define KERN_DEBUG "DBG: " +#define KERN_ERR "ERR: " +#define KERN_WARNING "WRN: " +#define KERN_INFO "INF: " +#define GFP_KERNEL 0 +#define GFP_ATOMIC 0 +#define GFP_NOIO 0 +#define SLAB_ATOMIC 0 +#define PCI_ANY_ID (~0) +#define SIGKILL 9 +#define THIS_MODULE 0 +//#define PAGE_SIZE 4096 + + +#define CLONE_FS 0 +#define CLONE_FILES 0 +#define CLONE_SIGHAND 0 +#define PF_FREEZE 0 +#define PF_IOTHREAD 0 + + +#define USBDEVFS_HUB_PORTINFO 1234 +#define SA_SHIRQ 0 + +#undef PCI_COMMAND +#define PCI_COMMAND 0 +#undef PCI_COMMAND_MASTER +#define PCI_COMMAND_MASTER 0 +/*------------------------------------------------------------------------*/ +/* Module/export macros */ +/*------------------------------------------------------------------------*/ + +#define MODULE_AUTHOR(a) +#define MODULE_DESCRIPTION(a) +#define MODULE_LICENSE(a) +#define MODULE_DEVICE_TABLE(type,name) void* module_table_##name=&name + +#define __devinit +#define __exit +#define __init +#define __devinitdata +#define module_init(x) static void module_init_##x(void){ x();} +#define module_exit(x) void module_exit_##x(void){ x();} +#define EXPORT_SYMBOL_GPL(x) +#define EXPORT_SYMBOL(x) + +#define __setup(x,y) int setup_##y=(int)y +#define subsys_initcall(x) void subsys_##x(void){x();} + +/*------------------------------------------------------------------------*/ +/* Access macros */ +/*------------------------------------------------------------------------*/ + +#define dev_get_drvdata(a) (a)->driver_data +#define dev_set_drvdata(a,b) (a)->driver_data=(b) + +#define __io_virt(x) ((void *)(x)) +#define readl(addr) (*(volatile unsigned int *) __io_virt(addr)) +#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b)) +#define likely(x) (x) +#define unlikely(x) (x) +#define prefetch(x) 1 + +/* The kernel macro for list_for_each_entry makes nonsense (have no clue + * why, this is just the same definition...) */ + +#undef list_for_each_entry +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/*------------------------------------------------------------------------*/ +/* function wrapper macros */ +/*------------------------------------------------------------------------*/ +#define kmalloc(x,y) ExAllocatePool(PagedPool,x) +#define kfree(x) ExFreePool(x) + +//#define sprintf(a,b,format, arg...) zxsprintf((a),(b),format, ## arg) +//#define snprintf(a,b,format, arg...) zxsnprintf((a),(b),format, ##arg) +//#define printk(format, arg...) zxprintf(format, ## arg) +#define snprintf(a,b,format, arg...) _snprintf((a),(b),format, ##arg) +#define printk(format, arg...) DPRINT1(format, ## arg) +#define BUG(...) do {} while(0) + +/* Locks & friends */ + +#define DECLARE_MUTEX(x) struct semaphore x +#define init_MUTEX(x) + +#define SPIN_LOCK_UNLOCKED 0 +#define spin_lock_init(a) do {} while(0) +#define spin_lock(a) *(int*)a=1 +#define spin_unlock(a) do {} while(0) + +#define spin_lock_irqsave(a,b) b=0 +#define spin_unlock_irqrestore(a,b) + +#if 0 +#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") +#define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc") +#else +#define local_irq_save(x) do {} while(0) +#define local_irq_restore(x) do {} while(0) +#endif + +#define atomic_inc(x) *(x)+=1 +#define atomic_dec(x) *(x)-=1 +#define atomic_dec_and_test(x) (*(x)-=1,(*(x))==0) +#define atomic_set(x,a) *(x)=a +#define atomic_read(x) *(x) +#define ATOMIC_INIT(x) (x) + +#define down(x) do {} while(0) +#define up(x) do {} while(0) +#define down_trylock(a) 0 + +#define down_read(a) do {} while(0) +#define up_read(a) do {} while(0) + +#define DECLARE_WAIT_QUEUE_HEAD(x) int x + +#define DECLARE_COMPLETION(x) struct completion x + +/* driver */ + +#define driver_unregister(a) do {} while(0) +#define put_device(a) do {} while(0) + + +/* PCI */ +#define pci_pool_create(a,b,c,d,e) (void*)1 + +#define pci_pool_alloc(a,b,c) my_pci_pool_alloc(a,b,c) + +static void __inline__ *my_pci_pool_alloc(void* pool, size_t size, + dma_addr_t *dma_handle) +{ + void* a; + a=kmalloc(size,0); //FIXME +#ifdef MODULE + *dma_handle=((u32)a)&0xfffffff; +#else + *dma_handle=(u32)a; +#endif + return a; +} + + +#define pci_pool_free(a,b,c) kfree(b) +#define pci_alloc_consistent(a,b,c) my_pci_alloc_consistent(a,b,c) + +static void __inline__ *my_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void* a; + + a=kmalloc(size+256,0); //FIXME + a=(void*)(((int)a+255)&~255); // 256 alignment + *dma_handle=((u32)a)&0xfffffff; + + return a; +} + +#define pci_free_consistent(a,b,c,d) kfree(c) +#define pci_pool_destroy(a) do {} while(0) + +#define pci_module_init(x) my_pci_module_init(x) +int my_pci_module_init(struct pci_driver *x); + +#define pci_unregister_driver(a) do {} while(0) + +#define bus_register(a) do {} while(0) +#define bus_unregister(a) do {} while(0) + +#define dma_map_single(a,b,c,d) ((u32)(b)&0xfffffff) +#define dma_unmap_single(a,b,c,d) do {} while(0) +#define pci_unmap_single(a,b,c,d) do {} while(0) +#define dma_sync_single(a,b,c,d) do {} while(0) +#define dma_sync_sg(a,b,c,d) do {} while(0) +#define dma_map_sg(a,b,c,d) 0 +#define dma_unmap_sg(a,b,c,d) do {} while(0) + +#define usb_create_driverfs_dev_files(a) do {} while(0) +#define usb_create_driverfs_intf_files(a) do {} while(0) +#define sg_dma_address(x) ((u32)((x)->page*4096 + (x)->offset)) +#define sg_dma_len(x) ((x)->length) + +#define page_address(x) ((void*)(x/4096)) + +#define DMA_TO_DEVICE 0 +#define DMA_FROM_DEVICE 0 +#define PCI_DMA_TODEVICE +#define PCI_DMA_FROMDEVICE +#define PCI_DMA_TODEVICE + +#define PCI_ROM_RESOURCE 0 +#define IORESOURCE_IO 1 + +#define DECLARE_WAITQUEUE(a,b) wait_queue_head_t a=0 +#define init_waitqueue_head(a) do {} while(0) +#define add_wait_queue(a,b) do {} while(0) +#define remove_wait_queue(a,b) do {} while(0) + +#define wmb() __asm__ __volatile__ ("": : :"memory") +#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") + +#define in_interrupt() 0 + +#define init_completion(x) (x)->done=0 +#define wait_for_completion(x) my_wait_for_completion(x) +void my_wait_for_completion(struct completion*); + +#define IRQ_NONE 0 +#define IRQ_HANDLED 1 + +#define INIT_WORK(a,b,c) (a)->func=b + +#define set_current_state(a) do {} while(0) + +#define might_sleep() do {} while(0) +#define daemonize(a) do {} while(0) +#define allow_signal(a) do {} while(0) +#define wait_event_interruptible(x,y) do {} while(0) +#define flush_scheduled_work() do {} while(0) +#define refrigerator(x) do {} while(0) +#define signal_pending(x) 1 // fall through threads +#define complete_and_exit(a,b) return 0 + +#define kill_proc(a,b,c) 0 +#define yield() do {} while(0) +#define cpu_relax() do {} while(0) + +/*------------------------------------------------------------------------*/ +/* Kernel macros */ +/*------------------------------------------------------------------------*/ + +#define LINUX_VERSION_CODE 0x020572 +#define UTS_SYSNAME "XBOX" +#define UTS_RELEASE "----" + +/* from linux/kernel.h */ +#define max_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) + +#define min_t(type,x,y) \ + ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* from linux/stddef.h */ + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/*------------------------------------------------------------------------*/ +/* Conversion macros */ +/*------------------------------------------------------------------------*/ + +#define __constant_cpu_to_le32(x) (x) +#define cpu_to_le16(x) (x) +#define le16_to_cpu(x) (x) +#define cpu_to_le32(x) (x) +#define cpu_to_le32p(x) (*(__u32*)(x)) +#define le32_to_cpup(x) (*(__u32*)(x)) +#define le32_to_cpu(x) ((u32)x) +#define le16_to_cpus(x) do {} while (0) +#define le16_to_cpup(x) (*(__u16*)(x)) +#define cpu_to_le16p(x) (*(__u16*)(x)) + +/*------------------------------------------------------------------------*/ +/* Debug output */ +/*------------------------------------------------------------------------*/ +#ifdef DEBUG_MODE +#define dev_printk(lvl,x,f,arg...) printk(f, ## arg) +#define dev_dbg(x,f,arg...) do {} while (0) //printk(f, ## arg) +#define dev_info(x,f,arg...) printk(f,## arg) +#define dev_warn(x,f,arg...) printk(f,## arg) +#define dev_err(x,f,arg...) printk(f,## arg) +#define pr_debug(x,f,arg...) printk(f,## arg) +#define usbprintk printk +#endif + +#ifndef DEBUG_MODE +#define dev_printk(lvl,x,f,arg...) do {} while (0) +#define dev_dbg(x,f,arg...) do {} while (0) //printk(f, ## arg) +#define dev_info(x,f,arg...) do {} while (0) +#define dev_warn(x,f,arg...) do {} while (0) +#define dev_err(x,f,arg...) do {} while (0) +#define pr_debug(x,f,arg...) do {} while (0) +#define usbprintk +#endif + + + +#define PCI_DEVFN(a,b) 0 +#define PCI_SLOT(a) 0 + +/*------------------------------------------------------------------------*/ +/* Stuff from kernel */ +/*------------------------------------------------------------------------*/ + +#include "errno.h" +#include "bitops.h" +//#include "linux/pci_ids.h" + +/*------------------------------------------------------------------------*/ +/* global variables */ +/*------------------------------------------------------------------------*/ + +#define jiffies my_jiffies +extern int my_jiffies; +#define current my_current +extern struct dummy_process *my_current; + +extern struct list_head interrupt_list; + +/*------------------------------------------------------------------------*/ +/* Function prototypes */ +/*------------------------------------------------------------------------*/ +void STDCALL usb_hcd_pci_remove (struct pci_dev *dev); + +#define my_wait_ms(x) wait_ms(x) + +#define my_udelay(x) wait_ms(x) +#define udelay(x) my_udelay(x) + +#define my_mdelay(x) wait_ms(1+x/1000); +#define mdelay(x) my_mdelay(x); + +#define pci_find_slot(a,b) my_pci_find_slot(a,b) +struct pci_dev *my_pci_find_slot(int a,int b); + +/*------------------------------------------------------------------------*/ +/* Timer management */ +/*------------------------------------------------------------------------*/ + +#define MAX_TIMERS 20 +extern struct timer_list *main_timer_list[MAX_TIMERS]; + +static void __inline__ init_timer(struct timer_list* t) +{ + INIT_LIST_HEAD(&t->timer_list); + t->function=NULL; + t->expires=0; +} + +static void __inline__ add_timer(struct timer_list* t) +{ + int n; + for(n=0;nexpires=ex; + add_timer(t); +} + +/*------------------------------------------------------------------------*/ +/* Device driver and process related stuff */ +/*------------------------------------------------------------------------*/ + +static int __inline__ usb_major_init(void){return 0;} +static void __inline__ usb_major_cleanup(void){} +static void __inline__ schedule_work(void* p){} + +#define device_initialize(x) my_device_initialize(x) +void my_device_initialize(struct device *dev); + +#define get_device(x) my_get_device(x) +struct device *my_get_device(struct device *dev); + +#define device_add(x) my_device_add(x) +int my_device_add(struct device *dev); + +#define driver_register(x) my_driver_register(x) +int my_driver_register(struct device_driver *driver); + +#define device_unregister(a) my_device_unregister(a) +int my_device_unregister(struct device *dev); + +#define DEVICE_ATTR(a,b,c,d) int xxx_##a +#define device_create_file(a,b) do {} while(0) +#define device_remove_file(a,b) do {} while(0) + +#define schedule_timeout(x) my_schedule_timeout(x) +int my_schedule_timeout(int x); + +#define wake_up(x) my_wake_up(x) +void my_wake_up(void*); + +// cannot be mapped via macro due to collision with urb->complete +static void __inline__ complete(struct completion *p) +{ + /* Wake up x->wait */ + p->done++; + wake_up(&p->wait); +} + +#define kernel_thread(a,b,c) my_kernel_thread(a,b,c) +int my_kernel_thread(int (*handler)(void*), void* parm, int flags); + +/*------------------------------------------------------------------------*/ +/* PCI, simple and inlined... */ +/*------------------------------------------------------------------------*/ +#include "pci_hal.c" + +/*------------------------------------------------------------------------*/ +/* IRQ handling */ +/*------------------------------------------------------------------------*/ + +#define request_irq(a,b,c,d,e) my_request_irq(a,b,c,d,e) +int my_request_irq(unsigned int irq, + int (*handler)(int, void *, struct pt_regs *), + unsigned long mode, const char *desc, void *data); + +#define free_irq(a,b) my_free_irq(a,b) +int free_irq(int irq, void* p); + + + +struct my_irqs { + int (*handler)(int, void *, struct pt_regs *); + int irq; + void* data; +}; + +#define MAX_IRQS 8 + +// Exported to top level + +void handle_irqs(int irq); +void inc_jiffies(int); +void init_wrapper(void); +void do_all_timers(void); + +#define __KERNEL_DS 0x18 + + diff --git a/reactos/drivers/usb/cromwell/linux/list.h b/reactos/drivers/usb/cromwell/linux/list.h new file mode 100644 index 00000000000..fbbfabed39a --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/list.h @@ -0,0 +1,224 @@ +#ifndef _BOOT_LIST_H +#define _BOOT_LIST_H + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member) \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +#endif diff --git a/reactos/drivers/usb/cromwell/linux/pci_hal.c b/reactos/drivers/usb/cromwell/linux/pci_hal.c new file mode 100644 index 00000000000..4008b8412ff --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/pci_hal.c @@ -0,0 +1,123 @@ +// PCI -> HAL interface +// this file is part of linux_wrapper.h + +/* + Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory. + Wake up the device if it was suspended. Beware, this function can fail. + */ +static int __inline__ pci_enable_device(struct pci_dev *dev) +{ + return 0; +} + +// Get physical address where resource x resides +static unsigned long __inline__ pci_resource_start (struct pci_dev *dev, int x) +{ + // HalGetBusData... + // HalAssignSlotResources ? + return dev->base[x]; +} + +// ??? +static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x){return 0;} + +// ??? +static int __inline__ pci_resource_flags(struct pci_dev *dev, int x) +{ + return dev->flags[x]; +} + +/* + Enables bus-mastering for device dev +*/ +static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;} + +// Store pointer to data for this device +static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d) +{ + dev->data=(void*)d; + return 0; +} + +// Get pointer to previously saved data +static void __inline__ *pci_get_drvdata(struct pci_dev *dev) +{ + return dev->data; +} + + +/* + =========================================================================== + I/O mem related stuff below +*/ + +/* +Allocate I/O memory region. + +Parameters: +start begin of region +n length of region +name name of requester +*/ +static int __inline__ request_region(unsigned long addr, unsigned long len, const char * d){return 0;} + +/* +Unmap I/O memory from kernel address space. + +Parameters: +addr virtual start address +*/ +static int __inline__ iounmap(void* p) +{ + return 0; +} + +/* +Release I/O port region. + +Parameters: +start begin of region +n length of region +*/ +static int __inline__ release_region(unsigned long addr, unsigned long len){return 0;} + +/* +Allocate I/O memory region. + +Parameters: +start begin of region +n length of region +name name of requester +*/ +static int __inline__ request_mem_region(unsigned long addr, unsigned long len, const char * d) +{ + return 1; +} + +/* +Remap I/O memory into kernel address space (no cache). + +Parameters: +phys_addr begin of physical address range +size size of physical address range + +Returns: +virtual start address of mapped range +*/ +static void __inline__ *ioremap_nocache(unsigned long addr, unsigned long len) +{ + // MmMapIoSpace ? + return (void*)addr; +} + +/* +Release I/O memory region. + +Parameters: +start begin of region +n length of region +*/ +static int __inline__ release_mem_region(unsigned long addr, unsigned long len) +{ + return 0; +} diff --git a/reactos/drivers/usb/cromwell/linux/pci_ids.h b/reactos/drivers/usb/cromwell/linux/pci_ids.h new file mode 100644 index 00000000000..73c93372e04 --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/pci_ids.h @@ -0,0 +1,11 @@ +#ifndef PCI_IDS__H +#define PCI_IDS__H + +#define PCI_VENDOR_ID_NS 0x100b +#define PCI_DEVICE_ID_NS_87560_LIO 0x000e +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_VENDOR_ID_OPTI 0x1045 + +#define PCI_CLASS_SERIAL_USB (PCI_CLASS_SERIAL_BUS_CTLR << 8 + PCI_SUBCLASS_SB_USB) + +#endif \ No newline at end of file diff --git a/reactos/drivers/usb/cromwell/linux/usb.h b/reactos/drivers/usb/cromwell/linux/usb.h new file mode 100644 index 00000000000..530d7ad1f7b --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/usb.h @@ -0,0 +1,1032 @@ +#ifndef __LINUX_USB_H +#define __LINUX_USB_H + + +#include "usb_ch9.h" + +#define USB_MAJOR 180 + + +#ifdef __KERNEL__ +#if 0 +#include +#include /* for -ENODEV */ +#include /* for mdelay() */ +#include /* for in_interrupt() */ +#include /* for struct list_head */ +#include /* for struct device */ +#include /* for struct file_operations */ +#include /* for struct completion */ +#include /* for current && schedule_timeout */ + + +static __inline__ void wait_ms(unsigned int ms) +{ + if(!in_interrupt()) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(1 + ms * HZ / 1000); + } + else + mdelay(ms); +} +#endif +struct usb_device; + +/*-------------------------------------------------------------------------*/ + +/* + * Host-side wrappers for standard USB descriptors ... these are parsed + * from the data provided by devices. Parsing turns them from a flat + * sequence of descriptors into a hierarchy: + * + * - devices have one (usually) or more configs; + * - configs have one (often) or more interfaces; + * - interfaces have one (usually) or more settings; + * - each interface setting has zero or (usually) more endpoints. + * + * And there might be other descriptors mixed in with those. + * + * Devices may also have class-specific or vendor-specific descriptors. + */ + +/* host-side wrapper for parsed endpoint descriptors */ +struct usb_host_endpoint { + struct usb_endpoint_descriptor desc; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +/* host-side wrapper for one interface setting's parsed descriptors */ +struct usb_host_interface { + struct usb_interface_descriptor desc; + + /* array of desc.bNumEndpoint endpoints associated with this + * interface setting. these will be in no particular order. + */ + struct usb_host_endpoint *endpoint; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +/** + * struct usb_interface - what usb device drivers talk to + * @altsetting: array of interface descriptors, one for each alternate + * setting that may be selected. Each one includes a set of + * endpoint configurations and will be in numberic order, + * 0..num_altsetting. + * @num_altsetting: number of altsettings defined. + * @act_altsetting: index of current altsetting. this number is always + * less than num_altsetting. after the device is configured, each + * interface uses its default setting of zero. + * @max_altsetting: + * @minor: the minor number assigned to this interface, if this + * interface is bound to a driver that uses the USB major number. + * If this interface does not use the USB major, this field should + * be unused. The driver should set this value in the probe() + * function of the driver, after it has been assigned a minor + * number from the USB core by calling usb_register_dev(). + * @dev: driver model's view of this device + * @class_dev: driver model's class view of this device. + * + * USB device drivers attach to interfaces on a physical device. Each + * interface encapsulates a single high level function, such as feeding + * an audio stream to a speaker or reporting a change in a volume control. + * Many USB devices only have one interface. The protocol used to talk to + * an interface's endpoints can be defined in a usb "class" specification, + * or by a product's vendor. The (default) control endpoint is part of + * every interface, but is never listed among the interface's descriptors. + * + * The driver that is bound to the interface can use standard driver model + * calls such as dev_get_drvdata() on the dev member of this structure. + * + * Each interface may have alternate settings. The initial configuration + * of a device sets the first of these, but the device driver can change + * that setting using usb_set_interface(). Alternate settings are often + * used to control the the use of periodic endpoints, such as by having + * different endpoints use different amounts of reserved USB bandwidth. + * All standards-conformant USB devices that use isochronous endpoints + * will use them in non-default settings. + */ +struct usb_interface { + /* array of alternate settings for this interface. + * these will be in numeric order, 0..num_altsettting + */ + struct usb_host_interface *altsetting; + + unsigned act_altsetting; /* active alternate setting */ + unsigned num_altsetting; /* number of alternate settings */ + unsigned max_altsetting; /* total memory allocated */ + + struct usb_driver *driver; /* driver */ + int minor; /* minor number this interface is bound to */ + struct device dev; /* interface specific device info */ + struct class_device class_dev; +}; +#define to_usb_interface(d) container_of(d, struct usb_interface, dev) +#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev) +#define interface_to_usbdev(intf) \ + container_of(intf->dev.parent, struct usb_device, dev) + +static inline void *usb_get_intfdata (struct usb_interface *intf) +{ + return dev_get_drvdata (&intf->dev); +} + +static inline void usb_set_intfdata (struct usb_interface *intf, void *data) +{ + dev_set_drvdata(&intf->dev, data); +} + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG. + */ +struct usb_host_config { + struct usb_config_descriptor desc; + + /* the interfaces associated with this configuration + * these will be in numeric order, 0..desc.bNumInterfaces + */ + struct usb_interface *interface; + + unsigned char *extra; /* Extra descriptors */ + int extralen; +}; + +// FIXME remove; exported only for drivers/usb/misc/auserwald.c +// prefer usb_device->epnum[0..31] +extern struct usb_endpoint_descriptor * + usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum); + +int __usb_get_extra_descriptor(char *buffer, unsigned size, + unsigned char type, void **ptr); +#define usb_get_extra_descriptor(ifpoint,type,ptr)\ + __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\ + type,(void**)ptr) + +/* -------------------------------------------------------------------------- */ + +struct usb_operations; + +/* USB device number allocation bitmap */ +struct usb_devmap { + unsigned long devicemap[128 / (8*sizeof(unsigned long))]; +}; + +/* + * Allocated per bus (tree of devices) we have: + */ +struct usb_bus { + struct device *controller; /* host/master side hardware */ + int busnum; /* Bus number (in order of reg) */ + char *bus_name; /* stable id (PCI slot_name etc) */ + + int devnum_next; /* Next open device number in round-robin allocation */ + + struct usb_devmap devmap; /* device address allocation map */ + struct usb_operations *op; /* Operations (specific to the HC) */ + struct usb_device *root_hub; /* Root hub */ + struct list_head bus_list; /* list of busses */ + void *hcpriv; /* Host Controller private data */ + + int bandwidth_allocated; /* on this bus: how much of the time + * reserved for periodic (intr/iso) + * requests is used, on average? + * Units: microseconds/frame. + * Limits: Full/low speed reserve 90%, + * while high speed reserves 80%. + */ + int bandwidth_int_reqs; /* number of Interrupt requests */ + int bandwidth_isoc_reqs; /* number of Isoc. requests */ + + struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ + struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */ + + atomic_t refcnt; +}; + + +/* -------------------------------------------------------------------------- */ + +/* This is arbitrary. + * From USB 2.0 spec Table 11-13, offset 7, a hub can + * have up to 255 ports. The most yet reported is 10. + */ +#define USB_MAXCHILDREN (16) + +struct usb_tt; + +struct usb_device { + int devnum; /* Address on USB bus */ + char devpath [16]; /* Use in messages: /port/port/... */ + enum usb_device_state state; /* configured, not attached, etc */ + enum usb_device_speed speed; /* high/full/low (or error) */ + + struct usb_tt *tt; /* low/full speed dev, highspeed hub */ + int ttport; /* device port on that tt hub */ + + struct semaphore serialize; + + unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ + unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ + /* [0] = IN, [1] = OUT */ + int epmaxpacketin[16]; /* INput endpoint specific maximums */ + int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ + + struct usb_device *parent; /* our hub, unless we're the root */ + struct usb_bus *bus; /* Bus we're part of */ + + struct device dev; /* Generic device interface */ + + struct usb_device_descriptor descriptor;/* Descriptor */ + struct usb_host_config *config; /* All of the configs */ + struct usb_host_config *actconfig;/* the active configuration */ + + char **rawdescriptors; /* Raw descriptors for each config */ + + int have_langid; /* whether string_langid is valid yet */ + int string_langid; /* language ID for strings */ + + void *hcpriv; /* Host Controller private data */ + + struct list_head filelist; + struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ + struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the device */ + + /* + * Child devices - these can be either new devices + * (if this is a hub device), or different instances + * of this same device. + * + * Each instance needs its own set of data structures. + */ + + int maxchild; /* Number of ports if hub */ + struct usb_device *children[USB_MAXCHILDREN]; +}; +#define to_usb_device(d) container_of(d, struct usb_device, dev) + +extern struct usb_device STDCALL *usb_alloc_dev(struct usb_device *parent, struct usb_bus *); +extern struct usb_device *usb_get_dev(struct usb_device *dev); +extern void STDCALL usb_put_dev(struct usb_device *dev); + +/* mostly for devices emulating SCSI over USB */ +extern int usb_reset_device(struct usb_device *dev); + +extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); + +/* for drivers using iso endpoints */ +extern int usb_get_current_frame_number (struct usb_device *usb_dev); + +/* used these for multi-interface device registration */ +extern void usb_driver_claim_interface(struct usb_driver *driver, + struct usb_interface *iface, void* priv); +extern int usb_interface_claimed(struct usb_interface *iface); +extern void usb_driver_release_interface(struct usb_driver *driver, + struct usb_interface *iface); +const struct usb_device_id *usb_match_id(struct usb_interface *interface, + const struct usb_device_id *id); + +extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor); +extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); + + +/** + * usb_make_path - returns stable device path in the usb tree + * @dev: the device whose path is being constructed + * @buf: where to put the string + * @size: how big is "buf"? + * + * Returns length of the string (> 0) or negative if size was too small. + * + * This identifier is intended to be "stable", reflecting physical paths in + * hardware such as physical bus addresses for host controllers or ports on + * USB hubs. That makes it stay the same until systems are physically + * reconfigured, by re-cabling a tree of USB devices or by moving USB host + * controllers. Adding and removing devices, including virtual root hubs + * in host controller driver modules, does not change these path identifers; + * neither does rebooting or re-enumerating. These are more useful identifiers + * than changeable ("unstable") ones like bus numbers or device addresses. + * + * With a partial exception for devices connected to USB 2.0 root hubs, these + * identifiers are also predictable. So long as the device tree isn't changed, + * plugging any USB device into a given hub port always gives it the same path. + * Because of the use of "companion" controllers, devices connected to ports on + * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are + * high speed, and a different one if they are full or low speed. + */ +static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) +{ + int actual; + actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath); + return (actual >= size) ? -1 : actual; +} + +/*-------------------------------------------------------------------------*/ + +#define USB_DEVICE_ID_MATCH_DEVICE (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) +#define USB_DEVICE_ID_MATCH_DEV_RANGE (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI) +#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE) +#define USB_DEVICE_ID_MATCH_DEV_INFO \ + (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL) +#define USB_DEVICE_ID_MATCH_INT_INFO \ + (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL) + +/** + * USB_DEVICE - macro used to describe a specific usb device + * @vend: the 16 bit USB Vendor ID + * @prod: the 16 bit USB Product ID + * + * This macro is used to create a struct usb_device_id that matches a + * specific device. + */ +#define USB_DEVICE(vend,prod) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), .idProduct = (prod) +/** + * USB_DEVICE_VER - macro used to describe a specific usb device with a version range + * @vend: the 16 bit USB Vendor ID + * @prod: the 16 bit USB Product ID + * @lo: the bcdDevice_lo value + * @hi: the bcdDevice_hi value + * + * This macro is used to create a struct usb_device_id that matches a + * specific device, with a version range. + */ +#define USB_DEVICE_VER(vend,prod,lo,hi) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi) + +/** + * USB_DEVICE_INFO - macro used to describe a class of usb devices + * @cl: bDeviceClass value + * @sc: bDeviceSubClass value + * @pr: bDeviceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific class of devices. + */ +#define USB_DEVICE_INFO(cl,sc,pr) \ + .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), .bDeviceSubClass = (sc), .bDeviceProtocol = (pr) + +/** + * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific class of interfaces. + */ +#define USB_INTERFACE_INFO(cl,sc,pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr) + +/* -------------------------------------------------------------------------- */ + +/** + * struct usb_driver - identifies USB driver to usbcore + * @owner: Pointer to the module owner of this driver; initialize + * it using THIS_MODULE. + * @name: The driver name should be unique among USB drivers, + * and should normally be the same as the module name. + * @probe: Called to see if the driver is willing to manage a particular + * interface on a device. If it is, probe returns zero and uses + * dev_set_drvdata() to associate driver-specific data with the + * interface. It may also use usb_set_interface() to specify the + * appropriate altsetting. If unwilling to manage the interface, + * return a negative errno value. + * @disconnect: Called when the interface is no longer accessible, usually + * because its device has been (or is being) disconnected or the + * driver module is being unloaded. + * @ioctl: Used for drivers that want to talk to userspace through + * the "usbfs" filesystem. This lets devices provide ways to + * expose information to user space regardless of where they + * do (or don't) show up otherwise in the filesystem. + * @id_table: USB drivers use ID table to support hotplugging. + * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set + * or your driver's probe function will never get called. + * + * USB drivers must provide a name, probe() and disconnect() methods, + * and an id_table. Other driver fields are optional. + * + * The id_table is used in hotplugging. It holds a set of descriptors, + * and specialized data may be associated with each entry. That table + * is used by both user and kernel mode hotplugging support. + * + * The probe() and disconnect() methods are called in a context where + * they can sleep, but they should avoid abusing the privilege. Most + * work to connect to a device should be done when the device is opened, + * and undone at the last close. The disconnect code needs to address + * concurrency issues with respect to open() and close() methods, as + * well as forcing all pending I/O requests to complete (by unlinking + * them as necessary, and blocking until the unlinks complete). + */ +struct usb_driver { + struct module *owner; + + const char *name; + + int (*probe) (struct usb_interface *intf, + const struct usb_device_id *id); + + void (*disconnect) (struct usb_interface *intf); + + int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf); + + const struct usb_device_id *id_table; + + struct device_driver driver; + + struct semaphore serialize; +}; +#define to_usb_driver(d) container_of(d, struct usb_driver, driver) + +extern struct bus_type usb_bus_type; + +/** + * struct usb_class_driver - identifies a USB driver that wants to use the USB major number + * @name: devfs name for this driver. Will also be used by the driver + * class code to create a usb class device. + * @fops: pointer to the struct file_operations of this driver. + * @mode: the mode for the devfs file to be created for this driver. + * @minor_base: the start of the minor range for this driver. + * + * This structure is used for the usb_register_dev() and + * usb_unregister_dev() functions, to consolodate a number of the + * paramaters used for them. + */ +struct usb_class_driver { + char *name; + struct file_operations *fops; + mode_t mode; + int minor_base; +}; + +/* + * use these in module_init()/module_exit() + * and don't forget MODULE_DEVICE_TABLE(usb, ...) + */ +extern int usb_register(struct usb_driver *); +extern void usb_deregister(struct usb_driver *); + +extern int usb_register_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver); +extern void usb_deregister_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver); + +extern int usb_device_probe(struct device *dev); +extern int usb_device_remove(struct device *dev); +extern int STDCALL usb_disabled(void); + +/* -------------------------------------------------------------------------- */ + +/* + * URB support, for asynchronous request completions + */ + +/* + * urb->transfer_flags: + */ +#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ +#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */ +#define URB_NO_DMA_MAP 0x0004 /* urb->*_dma are valid on submit */ +#define URB_ASYNC_UNLINK 0x0008 /* usb_unlink_urb() returns asap */ +#define URB_NO_FSBR 0x0020 /* UHCI-specific */ +#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */ +#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */ + +struct usb_iso_packet_descriptor { + unsigned int offset; + unsigned int length; /* expected length */ + unsigned int actual_length; + unsigned int status; +}; + +struct urb; +struct pt_regs; + +typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); + +/** + * struct urb - USB Request Block + * @urb_list: For use by current owner of the URB. + * @pipe: Holds endpoint number, direction, type, and more. + * Create these values with the eight macros available; + * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl" + * (control), "bulk", "int" (interrupt), or "iso" (isochronous). + * For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint + * numbers range from zero to fifteen. Note that "in" endpoint two + * is a different endpoint (and pipe) from "out" endpoint two. + * The current configuration controls the existence, type, and + * maximum packet size of any given endpoint. + * @dev: Identifies the USB device to perform the request. + * @status: This is read in non-iso completion functions to get the + * status of the particular request. ISO requests only use it + * to tell whether the URB was unlinked; detailed status for + * each frame is in the fields of the iso_frame-desc. + * @transfer_flags: A variety of flags may be used to affect how URB + * submission, unlinking, or operation are handled. Different + * kinds of URB can use different flags. + * @transfer_buffer: This identifies the buffer to (or from) which + * the I/O request will be performed (unless URB_NO_DMA_MAP is set). + * This buffer must be suitable for DMA; allocate it with kmalloc() + * or equivalent. For transfers to "in" endpoints, contents of + * this buffer will be modified. This buffer is used for data + * phases of control transfers. + * @transfer_dma: When transfer_flags includes URB_NO_DMA_MAP, the device + * driver is saying that it provided this DMA address, which the host + * controller driver should use instead of the transfer_buffer. + * @transfer_buffer_length: How big is transfer_buffer. The transfer may + * be broken up into chunks according to the current maximum packet + * size for the endpoint, which is a function of the configuration + * and is encoded in the pipe. When the length is zero, neither + * transfer_buffer nor transfer_dma is used. + * @actual_length: This is read in non-iso completion functions, and + * it tells how many bytes (out of transfer_buffer_length) were + * transferred. It will normally be the same as requested, unless + * either an error was reported or a short read was performed. + * The URB_SHORT_NOT_OK transfer flag may be used to make such + * short reads be reported as errors. + * @setup_packet: Only used for control transfers, this points to eight bytes + * of setup data. Control transfers always start by sending this data + * to the device. Then transfer_buffer is read or written, if needed. + * (Not used when URB_NO_DMA_MAP is set.) + * @setup_dma: For control transfers with URB_NO_DMA_MAP set, the device + * driver has provided this DMA address for the setup packet. The + * host controller driver should use this instead of setup_buffer. + * If there is a data phase, its buffer is identified by transfer_dma. + * @start_frame: Returns the initial frame for interrupt or isochronous + * transfers. + * @number_of_packets: Lists the number of ISO transfer buffers. + * @interval: Specifies the polling interval for interrupt or isochronous + * transfers. The units are frames (milliseconds) for for full and low + * speed devices, and microframes (1/8 millisecond) for highspeed ones. + * @error_count: Returns the number of ISO transfers that reported errors. + * @context: For use in completion functions. This normally points to + * request-specific driver context. + * @complete: Completion handler. This URB is passed as the parameter to the + * completion function. The completion function may then do what + * it likes with the URB, including resubmitting or freeing it. + * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to + * collect the transfer status for each buffer. + * + * This structure identifies USB transfer requests. URBs must be allocated by + * calling usb_alloc_urb() and freed with a call to usb_free_urb(). + * Initialization may be done using various usb_fill_*_urb() functions. URBs + * are submitted using usb_submit_urb(), and pending requests may be canceled + * using usb_unlink_urb(). + * + * Data Transfer Buffers: + * + * Normally drivers provide I/O buffers allocated with kmalloc() or otherwise + * taken from the general page pool. That is provided by transfer_buffer + * (control requests also use setup_packet), and host controller drivers + * perform a dma mapping (and unmapping) for each buffer transferred. Those + * mapping operations can be expensive on some platforms (perhaps using a dma + * bounce buffer or talking to an IOMMU), + * although they're cheap on commodity x86 and ppc hardware. + * + * Alternatively, drivers may pass the URB_NO_DMA_MAP transfer flag, which + * tells the host controller driver that no such mapping is needed since + * the device driver is DMA-aware. For example, they might allocate a DMA + * buffer with usb_buffer_alloc(), or call usb_buffer_map(). + * When this transfer flag is provided, host controller drivers will use the + * dma addresses found in the transfer_dma and/or setup_dma fields rather than + * determing a dma address themselves. + * + * Initialization: + * + * All URBs submitted must initialize dev, pipe, + * transfer_flags (may be zero), complete, timeout (may be zero). + * The URB_ASYNC_UNLINK transfer flag affects later invocations of + * the usb_unlink_urb() routine. + * + * All URBs must also initialize + * transfer_buffer and transfer_buffer_length. They may provide the + * URB_SHORT_NOT_OK transfer flag, indicating that short reads are + * to be treated as errors; that flag is invalid for write requests. + * + * Bulk URBs may + * use the URB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers + * should always terminate with a short packet, even if it means adding an + * extra zero length packet. + * + * Control URBs must provide a setup_packet. + * + * Interrupt UBS must provide an interval, saying how often (in milliseconds + * or, for highspeed devices, 125 microsecond units) + * to poll for transfers. After the URB has been submitted, the interval + * and start_frame fields reflect how the transfer was actually scheduled. + * The polling interval may be more frequent than requested. + * For example, some controllers have a maximum interval of 32 microseconds, + * while others support intervals of up to 1024 microseconds. + * Isochronous URBs also have transfer intervals. (Note that for isochronous + * endpoints, as well as high speed interrupt endpoints, the encoding of + * the transfer interval in the endpoint descriptor is logarithmic.) + * + * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling + * the host controller to schedule the transfer as soon as bandwidth + * utilization allows, and then set start_frame to reflect the actual frame + * selected during submission. Otherwise drivers must specify the start_frame + * and handle the case where the transfer can't begin then. However, drivers + * won't know how bandwidth is currently allocated, and while they can + * find the current frame using usb_get_current_frame_number () they can't + * know the range for that frame number. (Ranges for frame counter values + * are HC-specific, and can go from 256 to 65536 frames from "now".) + * + * Isochronous URBs have a different data transfer model, in part because + * the quality of service is only "best effort". Callers provide specially + * allocated URBs, with number_of_packets worth of iso_frame_desc structures + * at the end. Each such packet is an individual ISO transfer. Isochronous + * URBs are normally queued, submitted by drivers to arrange that + * transfers are at least double buffered, and then explicitly resubmitted + * in completion handlers, so + * that data (such as audio or video) streams at as constant a rate as the + * host controller scheduler can support. + * + * Completion Callbacks: + * + * The completion callback is made in_interrupt(), and one of the first + * things that a completion handler should do is check the status field. + * The status field is provided for all URBs. It is used to report + * unlinked URBs, and status for all non-ISO transfers. It should not + * be examined before the URB is returned to the completion handler. + * + * The context field is normally used to link URBs back to the relevant + * driver or request state. + * + * When completion callback is invoked for non-isochronous URBs, the + * actual_length field tells how many bytes were transferred. + * + * ISO transfer status is reported in the status and actual_length fields + * of the iso_frame_desc array, and the number of errors is reported in + * error_count. Completion callbacks for ISO transfers will normally + * (re)submit URBs to ensure a constant transfer rate. + */ +struct urb +{ + spinlock_t lock; /* lock for the URB */ + atomic_t count; /* reference count of the URB */ + void *hcpriv; /* private data for host controller */ + struct list_head urb_list; /* list pointer to all active urbs */ + struct usb_device *dev; /* (in) pointer to associated device */ + unsigned int pipe; /* (in) pipe information */ + int status; /* (return) non-ISO status */ + unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ + void *transfer_buffer; /* (in) associated data buffer */ + dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ + int transfer_buffer_length; /* (in) data buffer length */ + int actual_length; /* (return) actual transfer length */ + int bandwidth; /* bandwidth for INT/ISO request */ + unsigned char *setup_packet; /* (in) setup packet (control only) */ + dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ + int start_frame; /* (modify) start frame (INT/ISO) */ + int number_of_packets; /* (in) number of ISO packets */ + int interval; /* (in) transfer interval (INT/ISO) */ + int error_count; /* (return) number of ISO errors */ + int timeout; /* (in) timeout, in jiffies */ + void *context; /* (in) context for completion */ + usb_complete_t complete; /* (in) completion routine */ + struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ +}; + +/* -------------------------------------------------------------------------- */ + +/** + * usb_fill_control_urb - initializes a control urb + * @urb: pointer to the urb to initialize. + * @dev: pointer to the struct usb_device for this urb. + * @pipe: the endpoint pipe + * @setup_packet: pointer to the setup_packet buffer + * @transfer_buffer: pointer to the transfer buffer + * @buffer_length: length of the transfer buffer + * @complete: pointer to the usb_complete_t function + * @context: what to set the urb context to. + * + * Initializes a control urb with the proper information needed to submit + * it to a device. + */ +static inline void usb_fill_control_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + unsigned char *setup_packet, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete, + void *context) +{ + spin_lock_init(&urb->lock); + urb->dev = dev; + urb->pipe = pipe; + urb->setup_packet = setup_packet; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete; + urb->context = context; +} + +/** + * usb_fill_bulk_urb - macro to help initialize a bulk urb + * @urb: pointer to the urb to initialize. + * @dev: pointer to the struct usb_device for this urb. + * @pipe: the endpoint pipe + * @transfer_buffer: pointer to the transfer buffer + * @buffer_length: length of the transfer buffer + * @complete: pointer to the usb_complete_t function + * @context: what to set the urb context to. + * + * Initializes a bulk urb with the proper information needed to submit it + * to a device. + */ +static inline void usb_fill_bulk_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete, + void *context) +{ + spin_lock_init(&urb->lock); + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete; + urb->context = context; +} + +/** + * usb_fill_int_urb - macro to help initialize a interrupt urb + * @urb: pointer to the urb to initialize. + * @dev: pointer to the struct usb_device for this urb. + * @pipe: the endpoint pipe + * @transfer_buffer: pointer to the transfer buffer + * @buffer_length: length of the transfer buffer + * @complete: pointer to the usb_complete_t function + * @context: what to set the urb context to. + * @interval: what to set the urb interval to, encoded like + * the endpoint descriptor's bInterval value. + * + * Initializes a interrupt urb with the proper information needed to submit + * it to a device. + * Note that high speed interrupt endpoints use a logarithmic encoding of + * the endpoint interval, and express polling intervals in microframes + * (eight per millisecond) rather than in frames (one per millisecond). + */ +static inline void usb_fill_int_urb (struct urb *urb, + struct usb_device *dev, + unsigned int pipe, + void *transfer_buffer, + int buffer_length, + usb_complete_t complete, + void *context, + int interval) +{ + spin_lock_init(&urb->lock); + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = transfer_buffer; + urb->transfer_buffer_length = buffer_length; + urb->complete = complete; + urb->context = context; + if (dev->speed == USB_SPEED_HIGH) + urb->interval = 1 << (interval - 1); + else + urb->interval = interval; + urb->start_frame = -1; +} + +extern void STDCALL usb_init_urb(struct urb *urb); +extern struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags); +extern void STDCALL usb_free_urb(struct urb *urb); +#define usb_put_urb usb_free_urb +extern struct urb STDCALL *usb_get_urb(struct urb *urb); +extern int STDCALL usb_submit_urb(struct urb *urb, int mem_flags); +extern int STDCALL usb_unlink_urb(struct urb *urb); + +#define HAVE_USB_BUFFERS +void *usb_buffer_alloc (struct usb_device *dev, size_t size, + int mem_flags, dma_addr_t *dma); +void usb_buffer_free (struct usb_device *dev, size_t size, + void *addr, dma_addr_t dma); + +struct urb *usb_buffer_map (struct urb *urb); +void usb_buffer_dmasync (struct urb *urb); +void usb_buffer_unmap (struct urb *urb); + +struct scatterlist; +int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int nents); +void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents); +void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, + struct scatterlist *sg, int n_hw_ents); + +/*-------------------------------------------------------------------* + * SYNCHRONOUS CALL SUPPORT * + *-------------------------------------------------------------------*/ + +extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout); +extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, + int timeout); + +/* wrappers around usb_control_msg() for the most common standard requests */ +extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, + unsigned char descindex, void *buf, int size); +extern int usb_get_device_descriptor(struct usb_device *dev); +extern int usb_get_status(struct usb_device *dev, + int type, int target, void *data); +extern int usb_get_string(struct usb_device *dev, + unsigned short langid, unsigned char index, void *buf, int size); +extern int usb_string(struct usb_device *dev, int index, + char *buf, size_t size); + +/* wrappers that also update important state inside usbcore */ +extern int usb_clear_halt(struct usb_device *dev, int pipe); +extern int usb_set_configuration(struct usb_device *dev, int configuration); +extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); + +/* + * timeouts, in seconds, used for sending/receiving control messages + * they typically complete within a few frames (msec) after they're issued + * USB identifies 5 second timeouts, maybe more in a few cases, and a few + * slow devices (like some MGE Ellipse UPSes) actually push that limit. + */ +#define USB_CTRL_GET_TIMEOUT 5 +#define USB_CTRL_SET_TIMEOUT 5 + + +/** + * struct usb_sg_request - support for scatter/gather I/O + * @status: zero indicates success, else negative errno + * @bytes: counts bytes transferred. + * + * These requests are initialized using usb_sg_init(), and then are used + * as request handles passed to usb_sg_wait() or usb_sg_cancel(). Most + * members of the request object aren't for driver access. + * + * The status and bytecount values are valid only after usb_sg_wait() + * returns. If the status is zero, then the bytecount matches the total + * from the request. + * + * After an error completion, drivers may need to clear a halt condition + * on the endpoint. + */ +struct usb_sg_request { + int status; + size_t bytes; + + // members not documented above are private to usbcore, + // and are not provided for driver access! + spinlock_t lock; + + struct usb_device *dev; + int pipe; + struct scatterlist *sg; + int nents; + + int entries; + struct urb **urbs; + + int count; + struct completion complete; +}; + +int usb_sg_init ( + struct usb_sg_request *io, + struct usb_device *dev, + unsigned pipe, + unsigned period, + struct scatterlist *sg, + int nents, + size_t length, + int mem_flags +); +void usb_sg_cancel (struct usb_sg_request *io); +void usb_sg_wait (struct usb_sg_request *io); + + +/* -------------------------------------------------------------------------- */ + +/* + * Calling this entity a "pipe" is glorifying it. A USB pipe + * is something embarrassingly simple: it basically consists + * of the following information: + * - device number (7 bits) + * - endpoint number (4 bits) + * - current Data0/1 state (1 bit) [Historical; now gone] + * - direction (1 bit) + * - speed (1 bit) [Historical and specific to USB 1.1; now gone.] + * - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.] + * - pipe type (2 bits: control, interrupt, bulk, isochronous) + * + * That's 18 bits. Really. Nothing more. And the USB people have + * documented these eighteen bits as some kind of glorious + * virtual data structure. + * + * Let's not fall in that trap. We'll just encode it as a simple + * unsigned int. The encoding is: + * + * - max size: bits 0-1 [Historical; now gone.] + * - direction: bit 7 (0 = Host-to-Device [Out], + * 1 = Device-to-Host [In] ... + * like endpoint bEndpointAddress) + * - device: bits 8-14 ... bit positions known to uhci-hcd + * - endpoint: bits 15-18 ... bit positions known to uhci-hcd + * - Data0/1: bit 19 [Historical; now gone. ] + * - lowspeed: bit 26 [Historical; now gone. ] + * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, + * 10 = control, 11 = bulk) + * + * Why? Because it's arbitrary, and whatever encoding we select is really + * up to us. This one happens to share a lot of bit positions with the UHCI + * specification, so that much of the uhci driver can just mask the bits + * appropriately. + */ + +/* NOTE: these are not the standard USB_ENDPOINT_XFER_* values!! */ +#define PIPE_ISOCHRONOUS 0 +#define PIPE_INTERRUPT 1 +#define PIPE_CONTROL 2 +#define PIPE_BULK 3 + +#define usb_maxpacket(dev, pipe, out) (out \ + ? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \ + : (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] ) + +#define usb_pipein(pipe) ((pipe) & USB_DIR_IN) +#define usb_pipeout(pipe) (!usb_pipein(pipe)) +#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) +#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) +#define usb_pipetype(pipe) (((pipe) >> 30) & 3) +#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) +#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) +#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) +#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) + +/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ +#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) +#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) +#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep))) + +/* Endpoint halt control/status ... likewise USE WITH CAUTION */ +#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) +#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) + + +static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint) +{ + return (dev->devnum << 8) | (endpoint << 15); +} + +/* Create various pipes... */ +#define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) +#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint)) +#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) + +/* -------------------------------------------------------------------------- */ + +/* + * Debugging and troubleshooting/diagnostic helpers. + */ +void usb_show_device_descriptor(struct usb_device_descriptor *); +void usb_show_config_descriptor(struct usb_config_descriptor *); +void usb_show_interface_descriptor(struct usb_interface_descriptor *); +void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *); +void usb_show_device(struct usb_device *); +void usb_show_string(struct usb_device *dev, char *id, int index); + +#ifdef DEBUG +#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg) +#else +#define dbg(format, arg...) do {} while (0) +#endif + + + +#ifdef DEBUG_MODE +#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg) +#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg) +#endif + +#ifndef DEBUG_MODE +#define info(format, arg...) do {} while (0) +#define err(format, arg...) do {} while (0) +#define warn(format, arg...) do {} while (0) +#endif + +#endif /* __KERNEL__ */ + +#endif diff --git a/reactos/drivers/usb/cromwell/linux/usb_ch9.h b/reactos/drivers/usb/cromwell/linux/usb_ch9.h new file mode 100644 index 00000000000..a679168973a --- /dev/null +++ b/reactos/drivers/usb/cromwell/linux/usb_ch9.h @@ -0,0 +1,315 @@ +/* + * This file holds USB constants and structures that are needed for USB + * device APIs. These are used by the USB device model, which is defined + * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C + * that need these: + * + * - the master/host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - (eventually) a Linux "gadget" slave/device side driver API. + * + * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems + * act either as a USB master/host or as a USB slave/device. That means + * the master and slave side APIs will benefit from working well together. + */ + +#ifndef __LINUX_USB_CH9_H +#define __LINUX_USB_CH9_H +#if 0 +#include /* __u8 etc */ +#endif +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + + +/** + * struct usb_ctrlrequest - SETUP data for a USB device control request + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (le16 byte order) + * @wIndex: matches the USB wIndex field (le16 byte order) + * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. + */ +struct usb_ctrlrequest { + __u8 bRequestType; + __u8 bRequest; + __u16 wValue; + __u16 wIndex; + __u16 wLength; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or + * (rarely) accepted by SET_DESCRIPTOR. + * + * Note that all multi-byte values here are encoded in little endian + * byte order "on the wire". But when exposed through Linux-USB APIs, + * they've been converted to cpu byte order. + */ + +/* + * Descriptor types ... USB 2.0 spec table 9.5 + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 + +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + __u8 bLength; + __u8 bDescriptorType; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE: Device descriptor */ +struct usb_device_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __u16 idVendor; + __u16 idProduct; + __u16 bcdDevice; + __u8 iManufacturer; + __u8 iProduct; + __u8 iSerialNumber; + __u8 bNumConfigurations; +} __attribute__ ((packed)); + +#define USB_DT_DEVICE_SIZE 18 + + +/* + * Device and/or Interface Class codes + * as found in bDeviceClass or bInterfaceClass + * and defined by www.usb.org documents + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG + * descriptors. + */ +struct usb_config_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u16 wTotalLength; + __u8 bNumInterfaces; + __u8 bConfigurationValue; + __u8 iConfiguration; + __u8 bmAttributes; + __u8 bMaxPower; +} __attribute__ ((packed)); + +#define USB_DT_CONFIG_SIZE 9 + +/* from config descriptor bmAttributes */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_STRING: String descriptor */ +struct usb_string_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u16 wData[1]; /* UTF-16LE encoded */ +} __attribute__ ((packed)); + +/* note that "string" zero is special, it holds language codes that + * the device supports, not Unicode characters. + */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE: Interface descriptor */ +struct usb_interface_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bInterfaceNumber; + __u8 bAlternateSetting; + __u8 bNumEndpoints; + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + __u8 iInterface; +} __attribute__ ((packed)); + +#define USB_DT_INTERFACE_SIZE 9 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +struct usb_endpoint_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEndpointAddress; + __u8 bmAttributes; + __u16 wMaxPacketSize; + __u8 bInterval; + + // NOTE: these two are _only_ in audio endpoints. + // use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. + __u8 bRefresh; + __u8 bSynchAddress; +} __attribute__ ((packed)); + +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_qualifier_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __u8 bNumConfigurations; + __u8 bRESERVED; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB 2.0 defines three speeds, here's how Linux identifies them */ + +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH /* usb 2.0 */ +}; + +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* the chapter 9 device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + */ +}; + +#endif /* __LINUX_USB_CH9_H */ diff --git a/reactos/drivers/usb/cromwell/sys/BootUSB.c b/reactos/drivers/usb/cromwell/sys/BootUSB.c new file mode 100644 index 00000000000..2f582c5925a --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/BootUSB.c @@ -0,0 +1,90 @@ +/* + * USB support for XBOX, based on Linux kernel source + * + * 2003-06-21 Georg Acher (georg@acher.org) + * +*/ + +#include "../usb_wrapper.h" + +void subsys_usb_init(void); +void module_exit_usb_exit(void); + +extern struct pci_device_id *module_table_pci_ids; + +// straigth call... +int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id); +void usb_hcd_pci_remove (struct pci_dev *dev); + +void XPADInit(void); +void XPADRemove(void); +void XRemoteInit(void); +void XRemoteRemove(void); + +extern int (*thread_handler)(void*); +int (*hub_thread_handler)(void*); + +extern int nousb; +extern int xpad_num; + +struct pci_dev xx_ohci_dev={ + .vendor = 0, + .device = 0, + .bus = NULL, + .irq = 1, // currently not used... + .slot_name = "OHCI", + .dev = {.name = "PCI",.dma_mask=1}, + .base = {0xfed00000}, + .flags = {} +}; + +/*------------------------------------------------------------------------*/ +void BootStartUSB(void) +{ + int n; + + nousb=0; + + init_wrapper(); + subsys_usb_init(); + hub_thread_handler=thread_handler; + usb_hcd_pci_probe(&xx_ohci_dev, module_table_pci_ids); + XPADInit(); + + XRemoteInit(); + + UsbKeyBoardInit(); + + for(n=0;n<30;n++) { + USBGetEvents(); + wait_ms(1); + } +} +/*------------------------------------------------------------------------*/ +void USBGetEvents(void) +{ + inc_jiffies(1); + do_all_timers(); + hub_thread_handler(NULL); + handle_irqs(-1); +} +/*------------------------------------------------------------------------*/ +void BootStopUSB(void) +{ + int n; + + XPADRemove(); + XRemoteRemove(); + UsbKeyBoardRemove(); + + for(n=0;n<100;n++) + { + USBGetEvents(); + wait_ms(1); + } + + module_exit_usb_exit(); + usb_hcd_pci_remove(&xx_ohci_dev); + +} +/*------------------------------------------------------------------------*/ diff --git a/reactos/drivers/usb/cromwell/sys/Makefile b/reactos/drivers/usb/cromwell/sys/Makefile new file mode 100644 index 00000000000..a57d8cec5c6 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/Makefile @@ -0,0 +1,4 @@ + +O_TARGET := usbwrapper.o BootUSB.o linuxwrapper.o xpad.o xremote.o usbkey.o risefall.o + +include $(TOPDIR)/Rules.make diff --git a/reactos/drivers/usb/cromwell/sys/linuxwrapper.c b/reactos/drivers/usb/cromwell/sys/linuxwrapper.c new file mode 100644 index 00000000000..fce04d21250 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/linuxwrapper.c @@ -0,0 +1,271 @@ +/* + * USB support based on Linux kernel source + * + * 2003-06-21 Georg Acher (georg@acher.org) + * + * Concept: + * + * 1) Forget all device interrupts, scheduling, semaphores, threads etc. + * 1a) Forget all DMA and PCI helper functions + * 2) Forget usbdevfs, procfs and ioctls + * 3) Emulate OHCI interrupts and root hub timer by polling + * 4) Emulate hub kernel thread by polling + * 5) Emulate synchronous USB-messages (usb_*_msg) with busy waiting + * + * To be done: + * 6) Remove code bloat + * + */ + +#include "../usb_wrapper.h" + +/* internal state */ + +static struct pci_dev *pci_probe_dev; +extern int (*thread_handler)(void*); +extern void* thread_parm; + +struct my_irqs reg_irqs[MAX_IRQS]; +int num_irqs; +int need_wakeup; + +int my_jiffies; + +struct timer_list *main_timer_list[MAX_TIMERS]; +struct dummy_process act_cur={0}; +struct dummy_process *my_current; + +int (*thread_handler)(void*); +void* thread_parm; + +#define MAX_DRVS 8 +static struct device_driver *m_drivers[MAX_DRVS]; +static int drvs_num; + +/*------------------------------------------------------------------------*/ +/* + * Helper functions for top-level system + */ +/*------------------------------------------------------------------------*/ +void init_wrapper(void) +{ + int n; + for(n=0;nfunction && main_timer_list[n]->expires) + { + void (*function)(unsigned long)=main_timer_list[n]->function; + unsigned long data=main_timer_list[n]->data; + main_timer_list[n]->expires=0; + + main_timer_list[n]=NULL; // remove timer +// printk("do timer %i fn %p\n",n,function); + + function(data); + } + } +} +/*------------------------------------------------------------------------*/ +// Purpose: Remember thread procedure and data in global var +int my_kernel_thread(int (*handler)(void*), void* parm, int flags) +{ + thread_handler=handler; + thread_parm=parm; + return 42; // PID :-) +} +/*------------------------------------------------------------------------*/ +/* Device management + * As simple as possible, but as complete as necessary ... + */ +/*------------------------------------------------------------------------*/ + + +/* calls probe function for hotplug (which does device matching), this is the +only link between usbcore and the registered device drivers! */ +int my_device_add(struct device *dev) +{ + int n,found=0; +// printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe); + if (dev->driver) + { + if (dev->driver->probe) + return dev->driver->probe(dev); + } + else + { + for(n=0;nprobe) + { + dev->driver=m_drivers[n]; +// printk("probe%i %p ",n,m_drivers[n]->probe); + if (m_drivers[n]->probe(dev) == 0) + { +// return 0; + found=1; + } + } + } + if (found) return 0; + } + dev->driver=NULL; + return -ENODEV; +} +/*------------------------------------------------------------------------*/ +int my_driver_register(struct device_driver *driver) +{ + + if (drvs_numprobe); + m_drivers[drvs_num++]=driver; + return 0; + } + return -1; +} +/*------------------------------------------------------------------------*/ +int my_device_unregister(struct device *dev) +{ + if (dev->driver && dev->driver->remove) + dev->driver->remove(dev); + return 0; + +} +/*------------------------------------------------------------------------*/ +struct device *my_get_device(struct device *dev) +{ + return NULL; +} +/*------------------------------------------------------------------------*/ +void my_device_initialize(struct device *dev) +{ +} +/*------------------------------------------------------------------------*/ +void my_wake_up(void* p) +{ + need_wakeup=1; +} +/*------------------------------------------------------------------------*/ +/* wait until woken up (only one wait allowed!) */ +int my_schedule_timeout(int x) +{ + int wait=1; + x+=10; // safety +// printk("schedule_timeout %i\n",x); + while(x>0) + { + do_all_timers(); +#ifndef HAVE_IRQS + handle_irqs(-1); + +#endif + if (need_wakeup) + break; + wait_ms(wait); + inc_jiffies(wait); + x-=wait; + } + need_wakeup=0; +// printk("schedule DONE!!!!!!\n"); + return x; +} +/*------------------------------------------------------------------------*/ +void my_wait_for_completion(struct completion *x) +{ + int n=100; +// printk("wait for completion\n"); + while(!x->done && (n>0)) + { + do_all_timers(); +#ifndef HAVE_IRQS + handle_irqs(-1); + +#endif + wait_ms(10); + n--; + } +// printk("wait for completion done %i\n",x->done); +} +/*------------------------------------------------------------------------*/ +// Helper for pci_module_init +/*------------------------------------------------------------------------*/ +int my_pci_module_init(struct pci_driver *x) +{ + struct pci_dev *dev=pci_probe_dev; + const struct pci_device_id *id=NULL; + if (!pci_probe_dev) + { + printk(KERN_ERR "PCI device not set!\n"); + return 0; + } + x->probe(dev, id); + return 0; +} +/*------------------------------------------------------------------------*/ +struct pci_dev *my_pci_find_slot(int a,int b) +{ + return NULL; +} +/*------------------------------------------------------------------------*/ +int my_request_irq(unsigned int irq, + int (*handler)(int,void *, struct pt_regs *), + unsigned long mode, const char *desc, void *data) +{ + if (num_irqs0x30)&&(xpad_button_history[selected_Button]==0)) { + // Button Rising Edge + xpad_button_history[selected_Button] = 1; + return 1; + } + + if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) { + // Button Falling Edge + xpad_button_history[selected_Button] = 0; + return -1; + } + } + + if ((selected_Button > 5) & (selected_Button < 10) ) { + + unsigned char Buttonmask; + + switch (selected_Button) { + case TRIGGER_XPAD_PAD_UP : + Buttonmask = XPAD_PAD_UP; + break; + case TRIGGER_XPAD_PAD_DOWN : + Buttonmask = XPAD_PAD_DOWN; + break; + case TRIGGER_XPAD_PAD_LEFT : + Buttonmask = XPAD_PAD_LEFT; + break; + case TRIGGER_XPAD_PAD_RIGHT : + Buttonmask = XPAD_PAD_RIGHT; + break; + } + + // Rising Edge + if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) { + xpad_button_history[6] ^= Buttonmask; // Flip the Bit + return 1; + } + // Falling Edge + if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) { + xpad_button_history[6] ^= Buttonmask; // Flip the Bit + return -1; + } + } + return 0; +} diff --git a/reactos/drivers/usb/cromwell/sys/ros_wrapper.c b/reactos/drivers/usb/cromwell/sys/ros_wrapper.c new file mode 100644 index 00000000000..d97f1c6aa40 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/ros_wrapper.c @@ -0,0 +1,10 @@ +#include "../usb_wrapper.h" + + +void wait_ms(int mils) +{ + LARGE_INTEGER Interval; + + Interval.QuadPart = -mils*10; + KeDelayExecutionThread(KernelMode, FALSE, &Interval); +} diff --git a/reactos/drivers/usb/cromwell/sys/usbkey.c b/reactos/drivers/usb/cromwell/sys/usbkey.c new file mode 100644 index 00000000000..efb237d49a9 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/usbkey.c @@ -0,0 +1,123 @@ +#include "../usb_wrapper.h" + +#define keyboarddebug 0 + +#if keyboarddebug +extern int printe(const char *szFormat, ...); +int ycoffset = 0; +#endif + +unsigned int current_keyboard_key; + +struct usb_kbd_info { + struct urb *urb; + unsigned char kbd_pkt[8]; + unsigned char old[8]; + + /* + struct input_dev dev; + struct usb_device *usbdev; + struct urb irq, led; + struct usb_ctrlrequest dr; + unsigned char leds, newleds; + char name[128]; + int open; + */ +}; + +static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs) +{ + struct usb_kbd_info *kbd = urb->context; + int i; + + if (urb->status) return; + + memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8); + + current_keyboard_key = kbd->kbd_pkt[2]; + + + #if keyboarddebug + ycoffset += 15; + ycoffset = ycoffset % 600; + VIDEO_CURSOR_POSX=20; + VIDEO_CURSOR_POSY=ycoffset; + printe(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]); + #endif + + usb_submit_urb(urb,GFP_ATOMIC); + +} + +static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct urb *urb; + struct usb_device *udev = interface_to_usbdev (intf); + struct usb_endpoint_descriptor *ep_irq_in; + struct usb_endpoint_descriptor *ep_irq_out; + struct usb_kbd_info *usbk; + + int i, pipe, maxp; + char *buf; + + usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0); + if (!usbk) return -1; + + urb=usb_alloc_urb(0,0); + if (!urb) return -1; + + usbk->urb=urb; + + ep_irq_in = &intf->altsetting[0].endpoint[0].desc; + usb_fill_int_urb(urb, udev, + usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), + usbk->kbd_pkt, 8, usb_kbd_irq, + usbk, 8); + + usb_submit_urb(urb,GFP_ATOMIC); + usb_set_intfdata(intf,usbk); + #if keyboarddebug + printe("USB Keyboard Connected\n"); + #endif +} + + +static void usb_kbd_disconnect(struct usb_interface *intf) +{ + struct usb_kbd_info *usbk = usb_get_intfdata (intf); + usbprintk("Keyboard disconnected\n "); + usb_unlink_urb(usbk->urb); + usb_free_urb(usbk->urb); + kfree(usbk); +} + +static struct usb_device_id usb_kbd_id_table [] = { + { USB_INTERFACE_INFO(3, 1, 1) }, + { } /* Terminating entry */ +}; + + +static struct usb_driver usb_kbd_driver = { + .owner = THIS_MODULE, + .name = "keyboard", + .probe = usb_kbd_probe, + .disconnect = usb_kbd_disconnect, + .id_table = usb_kbd_id_table, +}; + +void UsbKeyBoardInit(void) +{ + + //current_remote_key=0; + //sbprintk("Keyboard probe %p ",xremote_probe); + if (usb_register(&usb_kbd_driver) < 0) { + #if keyboarddebug + printe("Unable to register Keyboard driver"); + #endif + return; + } +} + +void UsbKeyBoardRemove(void) { + usb_deregister(&usb_kbd_driver); +} diff --git a/reactos/drivers/usb/cromwell/sys/usbwrapper.c b/reactos/drivers/usb/cromwell/sys/usbwrapper.c new file mode 100644 index 00000000000..f2de2204543 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/usbwrapper.c @@ -0,0 +1,65 @@ +/* + * Interface calls to BIOS + * + * 2003-06-21 Georg Acher (georg@acher.org) + * + */ + +#include "boot.h" +#include +#include "video.h" + +/*------------------------------------------------------------------------*/ +// Output window for USB messages +int usb_curs_x=0; +int usb_curs_y=0; + +void zxprintf(char* fmt, ...) +{ + va_list ap; + char buffer[1024]; + int tmp_x, tmp_y; + tmp_x=VIDEO_CURSOR_POSX; + tmp_y=VIDEO_CURSOR_POSY; + + VIDEO_CURSOR_POSX=usb_curs_x; + VIDEO_CURSOR_POSY=usb_curs_y; + + if ((VIDEO_CURSOR_POSY==0) || (VIDEO_CURSOR_POSY > (vmode.height -16))) + { + BootVideoClearScreen(&jpegBackdrop, 3*vmode.height/4, + vmode.height); + VIDEO_CURSOR_POSY=3*vmode.height/4; + } + + va_start(ap, fmt); + vsprintf(buffer,fmt,ap); + //printk(buffer); + va_end(ap); + + usb_curs_x=VIDEO_CURSOR_POSX; + usb_curs_y=VIDEO_CURSOR_POSY; + VIDEO_CURSOR_POSX=tmp_x; + VIDEO_CURSOR_POSY=tmp_y; +} +/*------------------------------------------------------------------------*/ +int zxsnprintf(char *buffer, size_t s, char* fmt, ...) +{ + va_list ap; + int x; + va_start(ap, fmt); + x=vsprintf(buffer,fmt,ap); + va_end(ap); + return x; +} +/*------------------------------------------------------------------------*/ +int zxsprintf(char *buffer, char* fmt, ...) +{ + va_list ap; + int x; + va_start(ap, fmt); + x=vsprintf(buffer,fmt,ap); + va_end(ap); + return x; +} +/*------------------------------------------------------------------------*/ diff --git a/reactos/drivers/usb/cromwell/sys/xpad.c b/reactos/drivers/usb/cromwell/sys/xpad.c new file mode 100644 index 00000000000..e6d3122c80f --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/xpad.c @@ -0,0 +1,183 @@ +/* + * Simple XPAD driver for XBOX + * + * (c) 2003-07-04, Georg Acher (georg@acher.org) + * + * Inspired by linux/drivers/usb/input/xpad.c + * by Marko Friedemann + * + */ + + + +#include "../usb_wrapper.h" +#include "config.h" + +// history for the Rising - falling events +unsigned char xpad_button_history[7]; + +/* Stores time and XPAD state */ +struct xpad_data XPAD_current[4]; +struct xpad_data XPAD_last[4]; + +struct xpad_info +{ + struct urb *urb; + int num; + unsigned char data[32]; +}; + +int xpad_num=0; +/*------------------------------------------------------------------------*/ +static void xpad_irq(struct urb *urb, struct pt_regs *regs) +{ + struct xpad_info *xpi = urb->context; + unsigned char* data= urb->transfer_buffer; + +// struct xpad_data *xp=&XPAD_current[xpi->num]; +// struct xpad_data *xpo=&XPAD_last[xpi->num]; + + /* This hack means the xpad event always gets posted to the + * first xpad - avoids problems iterating over multiple xpads + * as the xpi->num entries are not reused when xpads are + * connected, then removed */ + + struct xpad_data *xp=&XPAD_current[0]; + struct xpad_data *xpo=&XPAD_last[0]; + + if (xpi->num<0 || xpi->num>3) + return; + + memcpy(xpo,xp,sizeof(struct xpad_data)); + + xp->stick_left_x=(short) (((short)data[13] << 8) | data[12]); + xp->stick_left_y=(short) (((short)data[15] << 8) | data[14]); + xp->stick_right_x=(short) (((short)data[17] << 8) | data[16]); + xp->stick_right_y=(short) (((short)data[19] << 8) | data[18]); + xp->trig_left= data[10]; + xp->trig_right= data[11]; + xp->pad = data[2]&0xf; + xp->state = (data[2]>>4)&0xf; + xp->keys[0] = data[4]; // a + xp->keys[1] = data[5]; // b + xp->keys[2] = data[6]; // x + xp->keys[3] = data[7]; // y + xp->keys[4] = data[8]; // black + xp->keys[5] = data[9]; // white + xp->timestamp=jiffies; // FIXME: A more uniform flowing time would be better... + usb_submit_urb(urb,GFP_ATOMIC); + +} +/*------------------------------------------------------------------------*/ +static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct urb *urb; + struct usb_device *udev = interface_to_usbdev (intf); + struct usb_endpoint_descriptor *ep_irq_in; + struct usb_endpoint_descriptor *ep_irq_out; + struct xpad_info *xpi; + + xpi=kmalloc(sizeof(struct xpad_info),GFP_KERNEL); + if (!xpi) return -1; + + urb=usb_alloc_urb(0,0); + if (!urb) return -1; + + xpi->urb=urb; + xpi->num=xpad_num; + ep_irq_in = &intf->altsetting[0].endpoint[0].desc; + usb_fill_int_urb(urb, udev, + usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), + xpi->data, 32, xpad_irq, + xpi, 32); + + usb_submit_urb(urb,GFP_ATOMIC); + + usb_set_intfdata(intf,xpi); + usbprintk("XPAD #%i connected\n",xpad_num); + #ifdef XPAD_VIBRA_STARTUP + { + // Brum Brum + char data1[6]={0,6,0,120,0,120}; + char data2[6]={0,6,0,0,0,0}; + int dummy; + + usb_bulk_msg(udev, usb_sndbulkpipe(udev,2), + data1, 6, &dummy, 500); + wait_ms(500); + usb_bulk_msg(udev, usb_sndbulkpipe(udev,2), + data2, 6, &dummy, 500); + } + #endif + xpad_num++; + return 0; +} +/*------------------------------------------------------------------------*/ +static void xpad_disconnect(struct usb_interface *intf) +{ + struct xpad_info *xpi=usb_get_intfdata (intf); + usb_unlink_urb(xpi->urb); + usb_free_urb(xpi->urb); + kfree(xpi); + xpad_num--; +} +/*------------------------------------------------------------------------*/ +static struct usb_device_id xpad_ids [] = { + { USB_DEVICE(0x044f, 0x0f07) },//Thrustmaster, Inc. Controller + { USB_DEVICE(0x045e, 0x0202) },//Microsoft Xbox Controller + { USB_DEVICE(0x045e, 0x0285) },//Microsoft Xbox Controller S + { USB_DEVICE(0x045e, 0x0289) },//Microsoft Xbox Controller S + { USB_DEVICE(0x046d, 0xca88) },//Logitech Compact Controller for Xbox + { USB_DEVICE(0x05fd, 0x1007) },//???Mad Catz Controller??? + { USB_DEVICE(0x05fd, 0x107a) },//InterAct PowerPad Pro + { USB_DEVICE(0x0738, 0x4516) },//Mad Catz Control Pad + { USB_DEVICE(0x0738, 0x4522) },//Mad Catz LumiCON + { USB_DEVICE(0x0738, 0x4526) },//Mad Catz Control Pad Pro + { USB_DEVICE(0x0738, 0x4536) },//Mad Catz MicroCON + { USB_DEVICE(0x0738, 0x4556) },//Mad Catz Lynx Wireless Controller + { USB_DEVICE(0x0c12, 0x9902) },//HAMA VibraX - *FAULTY HARDWARE* + { USB_DEVICE(0x0e4c, 0x1097) },//Radica Gamester Controller + { USB_DEVICE(0x0e4c, 0x2390) },//Radica Games Jtech Controller + { USB_DEVICE(0x0e6f, 0x0003) },//Logic3 Freebird wireless Controller + { USB_DEVICE(0x0e6f, 0x0005) },//Eclipse wireless Controlle + { USB_DEVICE(0x0f30, 0x0202) },//Joytech Advanced Controller + { USB_DEVICE(0xffff, 0xffff) },//Chinese-made Xbox Controller + { USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL + { } /* Terminating entry */ +}; + + +static struct usb_driver xpad_driver = { + .owner = THIS_MODULE, + .name = "XPAD", + .probe = xpad_probe, + .disconnect = xpad_disconnect, + .id_table = xpad_ids, +}; + +/*------------------------------------------------------------------------*/ +void XPADInit(void) +{ + int n; + for(n=0;n<4;n++) + { + memset(&XPAD_current[n], 0, sizeof(struct xpad_data)); + memset(&XPAD_last[n], 0, sizeof(struct xpad_data)); + } + memset(&xpad_button_history, 0, sizeof(xpad_button_history)); + + usbprintk("XPAD probe %p ",xpad_probe); + if (usb_register(&xpad_driver) < 0) { + err("Unable to register XPAD driver"); + return; + } +} +/*------------------------------------------------------------------------*/ +void XPADRemove(void) { + usb_deregister(&xpad_driver); +} + +/*------------------------------------------------------------------------*/ + + + diff --git a/reactos/drivers/usb/cromwell/sys/xremote.c b/reactos/drivers/usb/cromwell/sys/xremote.c new file mode 100644 index 00000000000..7f53f211cc7 --- /dev/null +++ b/reactos/drivers/usb/cromwell/sys/xremote.c @@ -0,0 +1,142 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * $Id: xremote.c,v 1.5 2004/11/22 19:10:57 davidmpye Exp $ + * + * Copyright (c) 2002 Steven Toth + * + * XBOX DVD dongle infrared device driver for the input driver suite. + * + * This work was derived from the usbkbd.c kernel module. + * + * History: + * + * 2002_08_31 - 0.1 - Initial release + * 2002_09_02 - 0.2 - Added IOCTL support enabling user space administration + * of the translation matrix. + * + */ + +#include "../usb_wrapper.h" + + +u16 current_remote_key; +u8 remotekeyIsRepeat; + +struct xremote_info +{ + struct urb *urb; + unsigned char irpkt[8]; +}; + +/* USB callback completion handler + * Code in transfer_buffer is received as six unsigned chars + * Example PLAY=00 06 ea 0a 40 00 + * The command is located in byte[2], the rest are ignored. + * Key position is byte[4] bit0 (7-0 format) 0=down, 1=up + * All other bits are unknown / now required. + */ + +static void xremote_irq(struct urb *urb, struct pt_regs *regs) +{ + struct xremote_info *xri = urb->context; + + if (urb->status) return; + if (urb->actual_length < 6) return; + + /* Messy/unnecessary, fix this */ + memcpy(xri->irpkt, urb->transfer_buffer, 6); + + /* Set the key action based in the sent action */ + current_remote_key = ((xri->irpkt[2] & 0xff)<<8) | (xri->irpkt[3] & 0xff); + + if (((xri->irpkt[4] & 0xff) + ((xri->irpkt[5] & 0xff ) << 8))>0x41) { + remotekeyIsRepeat=0; + } + else remotekeyIsRepeat=1; + + usb_submit_urb(urb,GFP_ATOMIC); +} + +static int xremote_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct urb *urb; + struct usb_device *udev = interface_to_usbdev (intf); + struct usb_endpoint_descriptor *ep_irq_in; + struct usb_endpoint_descriptor *ep_irq_out; + struct xremote_info *xri; + + xri=(struct xremote_info *)kmalloc(sizeof(struct xremote_info),0); + if (!xri) return -1; + + urb=usb_alloc_urb(0,0); + if (!urb) return -1; + + xri->urb=urb; + + ep_irq_in = &intf->altsetting[0].endpoint[0].desc; + usb_fill_int_urb(urb, udev, + usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), + xri->irpkt, 8, xremote_irq, + xri, 8); + + usb_submit_urb(urb,GFP_ATOMIC); + usb_set_intfdata(intf,xri); + + usbprintk("DVD Remote connected\n"); + return 0; +} + +static void xremote_disconnect(struct usb_interface *intf) +{ + struct xremote_info *xri = usb_get_intfdata (intf); + usbprintk("DVD Remote disconnected\n "); + usb_unlink_urb(xri->urb); + usb_free_urb(xri->urb); + kfree(xri); +} + +static struct usb_device_id xremote_id_table [] = { + { USB_DEVICE(0x040b, 0x6521) }, /* Gamester Xbox DVD Movie Playback Kit IR */ + { USB_DEVICE(0x045e, 0x0284) }, /* Microsoft Xbox DVD Movie Playback Kit IR */ + { USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL + { } /* Terminating entry */ +}; + +static struct usb_driver xremote_driver = { + .owner = THIS_MODULE, + .name = "XRemote", + .probe = xremote_probe, + .disconnect = xremote_disconnect, + .id_table = xremote_id_table, +}; + +void XRemoteInit(void) +{ + + current_remote_key=0; + usbprintk("XRemote probe %p ",xremote_probe); + if (usb_register(&xremote_driver) < 0) { + err("Unable to register XRemote driver"); + return; + } +} + +void XRemoteRemove(void) { + usb_deregister(&xremote_driver); +} diff --git a/reactos/drivers/usb/cromwell/usb_wrapper.h b/reactos/drivers/usb/cromwell/usb_wrapper.h new file mode 100644 index 00000000000..47e0d9bbb83 --- /dev/null +++ b/reactos/drivers/usb/cromwell/usb_wrapper.h @@ -0,0 +1,14 @@ +//#include +//#include +//#include +#include +#include + +void wait_ms(int mils); + +#include "linux/linux_wrapper.h" +#define __KERNEL__ +#undef CONFIG_PCI +#define CONFIG_PCI + +#include "linux/usb.h" diff --git a/reactos/drivers/usb/miniport/usbehci/makefile b/reactos/drivers/usb/miniport/usbehci/makefile new file mode 100644 index 00000000000..bf4be62e7e4 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbehci/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = usbehci + +TARGET_DDKLIBS = ntoskrnl.a usbport.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + usbehci.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/miniport/usbehci/usbehci.c b/reactos/drivers/usb/miniport/usbehci/usbehci.c new file mode 100644 index 00000000000..9289968a2db --- /dev/null +++ b/reactos/drivers/usb/miniport/usbehci/usbehci.c @@ -0,0 +1,41 @@ +/* + * ReactOS USB EHCI miniport driver + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* INCLUDES *******************************************************************/ + +#include "usbehci.h" +#include "../../usbport/usbport.h" + +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) +{ + PUSB_CONTROLLER_INTERFACE ControllerInterface; + + USBPORT_AllocateUsbControllerInterface(&ControllerInterface); + + /* + * Set up the list of callbacks here. + * TODO TODO TODO + */ + + return USBPORT_RegisterUSBPortDriver(DriverObject, 0, ControllerInterface); +} diff --git a/reactos/drivers/usb/miniport/usbehci/usbehci.h b/reactos/drivers/usb/miniport/usbehci/usbehci.h new file mode 100644 index 00000000000..7eccf7ae6fc --- /dev/null +++ b/reactos/drivers/usb/miniport/usbehci/usbehci.h @@ -0,0 +1,45 @@ +/* + * ReactOS USB EHCI miniport driver + * + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef USBEHCI_H +#define USBEHCI_H + +/* INCLUDES *******************************************************************/ + +#include "stddef.h" +#include "windef.h" +//#include +#include + +#ifdef DBG +#define DPRINT(arg) DbgPrint arg; +#else +#define DPRINT(arg) +#endif + +// Export funcs here +/* +BOOL FASTCALL +VBESetColorRegisters( + PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_CLUT ColorLookUpTable, + PSTATUS_BLOCK StatusBlock); +*/ +#endif /* USBEHCI_H */ diff --git a/reactos/drivers/usb/miniport/usbehci/usbehci.rc b/reactos/drivers/usb/miniport/usbehci/usbehci.rc new file mode 100644 index 00000000000..241bf2b6713 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbehci/usbehci.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB EHCI miniport Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbehci\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbehci.sys\0" +#include diff --git a/reactos/drivers/usb/miniport/usbohci/makefile b/reactos/drivers/usb/miniport/usbohci/makefile new file mode 100644 index 00000000000..f16a9d8aea0 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbohci/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = usbohci + +TARGET_DDKLIBS = ntoskrnl.a usbport.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + usbohci.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/miniport/usbohci/usbohci.c b/reactos/drivers/usb/miniport/usbohci/usbohci.c new file mode 100644 index 00000000000..f8faf8991ca --- /dev/null +++ b/reactos/drivers/usb/miniport/usbohci/usbohci.c @@ -0,0 +1,41 @@ +/* + * ReactOS USB OpenHCI miniport driver + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* INCLUDES *******************************************************************/ + +#include "usbohci.h" +#include "../../usbport/usbport.h" + +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) +{ + PUSB_CONTROLLER_INTERFACE ControllerInterface; + + USBPORT_AllocateUsbControllerInterface(&ControllerInterface); + + /* + * Set up the list of callbacks here. + * TODO TODO TODO + */ + + return USBPORT_RegisterUSBPortDriver(DriverObject, 0, ControllerInterface); +} diff --git a/reactos/drivers/usb/miniport/usbohci/usbohci.h b/reactos/drivers/usb/miniport/usbohci/usbohci.h new file mode 100644 index 00000000000..c6f3aa09707 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbohci/usbohci.h @@ -0,0 +1,45 @@ +/* + * ReactOS USB OpenHCI miniport driver + * + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef USBOHCI_H +#define USBOHCI_H + +/* INCLUDES *******************************************************************/ + +#include "stddef.h" +#include "windef.h" +//#include +#include + +#ifdef DBG +#define DPRINT(arg) DbgPrint arg; +#else +#define DPRINT(arg) +#endif + +// Export funcs here +/* +BOOL FASTCALL +VBESetColorRegisters( + PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_CLUT ColorLookUpTable, + PSTATUS_BLOCK StatusBlock); +*/ +#endif /* USBOHCI_H */ diff --git a/reactos/drivers/usb/miniport/usbohci/usbohci.rc b/reactos/drivers/usb/miniport/usbohci/usbohci.rc new file mode 100644 index 00000000000..2badbbf8b5f --- /dev/null +++ b/reactos/drivers/usb/miniport/usbohci/usbohci.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB OpenHCI miniport Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbohci\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbohci.sys\0" +#include diff --git a/reactos/drivers/usb/miniport/usbuhci/makefile b/reactos/drivers/usb/miniport/usbuhci/makefile new file mode 100644 index 00000000000..b89c935ff71 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbuhci/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = usbuhci + +TARGET_DDKLIBS = ntoskrnl.a usbport.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + usbuhci.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/miniport/usbuhci/usbuhci.c b/reactos/drivers/usb/miniport/usbuhci/usbuhci.c new file mode 100644 index 00000000000..7f057121a5d --- /dev/null +++ b/reactos/drivers/usb/miniport/usbuhci/usbuhci.c @@ -0,0 +1,43 @@ +/* + * ReactOS USB UHCI miniport driver + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* INCLUDES *******************************************************************/ + +#include "usbuhci.h" +#include "../../usbport/usbport.h" +#include +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) +{ + //return STATUS_SUCCESS; + //DPRINT1("USBUHCI.SYS DriverEntry\n"); + PUSB_CONTROLLER_INTERFACE ControllerInterface; + + USBPORT_AllocateUsbControllerInterface(&ControllerInterface); + + /* + * Set up the list of callbacks here. + * TODO TODO TODO + */ + + return USBPORT_RegisterUSBPortDriver(DriverObject, 0, ControllerInterface); +} diff --git a/reactos/drivers/usb/miniport/usbuhci/usbuhci.h b/reactos/drivers/usb/miniport/usbuhci/usbuhci.h new file mode 100644 index 00000000000..adf09f913b0 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbuhci/usbuhci.h @@ -0,0 +1,39 @@ +/* + * ReactOS USB UHCI miniport driver + * + * Copyright (C) 2004 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef USBUHCI_H +#define USBUHCI_H + +/* INCLUDES *******************************************************************/ + +#include "stddef.h" +#include "windef.h" +//#include +#include + +// Export funcs here +/* +BOOL FASTCALL +VBESetColorRegisters( + PVBE_DEVICE_EXTENSION DeviceExtension, + PVIDEO_CLUT ColorLookUpTable, + PSTATUS_BLOCK StatusBlock); +*/ +#endif /* USBUHCI_H */ diff --git a/reactos/drivers/usb/miniport/usbuhci/usbuhci.rc b/reactos/drivers/usb/miniport/usbuhci/usbuhci.rc new file mode 100644 index 00000000000..fbd26dd2978 --- /dev/null +++ b/reactos/drivers/usb/miniport/usbuhci/usbuhci.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI miniport Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbuhci\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbuhci.sys\0" +#include diff --git a/reactos/drivers/usb/usbd/makefile b/reactos/drivers/usb/usbd/makefile new file mode 100644 index 00000000000..4e3ba95dc41 --- /dev/null +++ b/reactos/drivers/usb/usbd/makefile @@ -0,0 +1,17 @@ +# $Id: $ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = usbd + +TARGET_OBJECTS = usbd.o + +TARGET_GCCLIBS = gcc + +TARGET_CFLAGS = -D__USE_W32API -O3 -s + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/usbd/test.c b/reactos/drivers/usb/usbd/test.c new file mode 100644 index 00000000000..193a9200ba1 --- /dev/null +++ b/reactos/drivers/usb/usbd/test.c @@ -0,0 +1,33 @@ +#include +#include +#include + +typedef ULONG STDCALL +(*USBD_GetInterfaceLengthTYPE)( + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, + PUCHAR BufferEnd + ); + +int main() +{ + HMODULE Lib; + USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + USBD_GetInterfaceLengthTYPE USBD_GetInterfaceLength; + + InterfaceDescriptor.bLength = 10; + InterfaceDescriptor.bNumEndpoints = 2; + InterfaceDescriptor.bDescriptorType = /*USB_INTERFACE_DESCRIPTOR_TYPE*/2; + InterfaceDescriptor.iInterface = 0x1; + + Lib = LoadLibraryEx("usbd.sys", NULL, DONT_RESOLVE_DLL_REFERENCES); + USBD_GetInterfaceLength = (USBD_GetInterfaceLengthTYPE)GetProcAddress(Lib, "USBD_GetInterfaceLength"); + printf("%X\n", USBD_GetInterfaceLength(&InterfaceDescriptor, (PUCHAR)((DWORD)&InterfaceDescriptor + sizeof(InterfaceDescriptor)))); + FreeLibrary(Lib); + + Lib = LoadLibraryEx("usbd.ms", NULL, DONT_RESOLVE_DLL_REFERENCES); + USBD_GetInterfaceLength = (USBD_GetInterfaceLengthTYPE)GetProcAddress(Lib, "USBD_GetInterfaceLength"); + printf("%X\n", USBD_GetInterfaceLength(&InterfaceDescriptor, (PUCHAR)((DWORD)&InterfaceDescriptor + sizeof(InterfaceDescriptor)))); + FreeLibrary(Lib); + return 0; +} + diff --git a/reactos/drivers/usb/usbd/usbd.c b/reactos/drivers/usb/usbd/usbd.c new file mode 100644 index 00000000000..66ae4a1fb4c --- /dev/null +++ b/reactos/drivers/usb/usbd/usbd.c @@ -0,0 +1,457 @@ +/* + * Universal Serial Bus Driver/Helper Library + * + * Written by Filip Navara + * + * Notes: + * This driver was obsoleted in Windows XP and most functions + * became pure stubs. But some of them were retained for backward + * compatibilty with existing drivers. + * + * Preserved functions: + * + * USBD_Debug_GetHeap (implemented) + * USBD_Debug_RetHeap (implemented) + * USBD_CalculateUsbBandwidth (implemented, tested) + * USBD_CreateConfigurationRequestEx (implemented) + * USBD_CreateConfigurationRequest + * USBD_GetInterfaceLength (implemented) + * USBD_ParseConfigurationDescriptorEx + * USBD_ParseDescriptors + * USBD_GetPdoRegistryParameters (implemented) + */ + +#include +#include +#ifndef PLUGPLAY_REGKEY_DRIVER +#define PLUGPLAY_REGKEY_DRIVER 2 +#endif +typedef struct _USBD_INTERFACE_LIST_ENTRY { + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + PUSBD_INTERFACE_INFORMATION Interface; +} USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY; + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +DWORD STDCALL +DllInitialize(DWORD Unknown) +{ + return 0; +} + +/* + * @implemented + */ +DWORD STDCALL +DllUnload(VOID) +{ + return 0; +} + +/* + * @implemented + */ +PVOID STDCALL +USBD_Debug_GetHeap(DWORD Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes, + ULONG Tag) +{ + return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); +} + +/* + * @implemented + */ +VOID STDCALL +USBD_Debug_RetHeap(PVOID Heap, DWORD Unknown2, DWORD Unknown3) +{ + ExFreePool(Heap); +} + +/* + * @implemented + */ +VOID STDCALL +USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2, + ULONG_PTR Info3) +{ +} + +/* + * @implemented + */ +PVOID STDCALL +USBD_AllocateDeviceName(DWORD Unknown) +{ + return NULL; +} + +/* + * @implemented + */ +DWORD STDCALL +USBD_CalculateUsbBandwidth( + ULONG MaxPacketSize, + UCHAR EndpointType, + BOOLEAN LowSpeed + ) +{ + DWORD OverheadTable[] = { + 0x00, /* UsbdPipeTypeControl */ + 0x09, /* UsbdPipeTypeIsochronous */ + 0x00, /* UsbdPipeTypeBulk */ + 0x0d /* UsbdPipeTypeInterrupt */ + }; + DWORD Result; + + if (OverheadTable[EndpointType] != 0) + { + Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6; + if (LowSpeed) + return Result << 3; + return Result; + } + return 0; +} + +/* + * @implemented + */ +DWORD STDCALL +USBD_Dispatch(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + return 1; +} + +/* + * @implemented + */ +VOID STDCALL +USBD_FreeDeviceMutex(PVOID Unknown) +{ +} + +/* + * @implemented + */ +VOID STDCALL +USBD_FreeDeviceName(PVOID Unknown) +{ +} + +/* + * @implemented + */ +VOID STDCALL +USBD_WaitDeviceMutex(PVOID Unknown) +{ +} + +/* + * @implemented + */ +DWORD STDCALL +USBD_GetSuspendPowerState(DWORD Unknown1) +{ + return 0; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_InitializeDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, + DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_RegisterHostController(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, + DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7, + DWORD Unknown8, DWORD Unknown9, DWORD Unknown10) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_GetDeviceInformation(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_CreateDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, + DWORD Unknown4, DWORD Unknown5) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_RemoveDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +VOID STDCALL +USBD_CompleteRequest(DWORD Unknown1, DWORD Unknown2) +{ +} + +/* + * @implemented + */ +VOID STDCALL +USBD_RegisterHcFilter( + PDEVICE_OBJECT DeviceObject, + PDEVICE_OBJECT FilterDeviceObject + ) +{ +} + +/* + * @implemented + */ +VOID STDCALL +USBD_SetSuspendPowerState(DWORD Unknown1, DWORD Unknown2) +{ +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_MakePdoName(DWORD Unknown1, DWORD Unknown2) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_QueryBusTime( + PDEVICE_OBJECT RootHubPdo, + PULONG CurrentFrame + ) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +VOID STDCALL +USBD_GetUSBDIVersion( + PUSBD_VERSION_INFORMATION Version + ) +{ + if (Version != NULL) + { + Version->USBDI_Version = USBDI_VERSION; + Version->Supported_USB_Version = 0x100; + } +} + +/* + * @implemented + */ +NTSTATUS STDCALL +USBD_RestoreDevice(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + return STATUS_NOT_SUPPORTED; +} + +/* + * @implemented + */ +VOID STDCALL +USBD_RegisterHcDeviceCapabilities(DWORD Unknown1, DWORD Unknown2, + DWORD Unknown3) +{ +} + +/* + * @implemented + * FIXME: Test + */ +PURB +STDCALL +USBD_CreateConfigurationRequestEx( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PUSBD_INTERFACE_LIST_ENTRY InterfaceList + ) +{ + PURB Urb; + DWORD UrbSize; + DWORD InterfaceCount; + + for (InterfaceCount = 0; + InterfaceList[InterfaceCount].InterfaceDescriptor != NULL; + ++InterfaceCount) + ; + /* Include the NULL entry */ + ++InterfaceCount; + + UrbSize = sizeof(Urb->UrbSelectConfiguration) + + (InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY)); + Urb = ExAllocatePool(NonPagedPool, UrbSize); + Urb->UrbSelectConfiguration.Hdr.Function = + URB_FUNCTION_SELECT_CONFIGURATION; + Urb->UrbSelectConfiguration.Hdr.Length = + sizeof(Urb->UrbSelectConfiguration); + Urb->UrbSelectConfiguration.ConfigurationDescriptor = + ConfigurationDescriptor; + memcpy((PVOID)&Urb->UrbSelectConfiguration.Interface, (PVOID)InterfaceList, + InterfaceCount * sizeof(PUSBD_INTERFACE_LIST_ENTRY)); + + return Urb; +} + +/* + * @unimplemented + */ +PURB STDCALL +USBD_CreateConfigurationRequest( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PUSHORT Size + ) +{ + return NULL; +} + +/* + * @unimplemented + */ +ULONG STDCALL +USBD_GetInterfaceLength( + PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, + PUCHAR BufferEnd + ) +{ + PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor; + DWORD Length = CurrentDescriptor->bLength; + + // USB_ENDPOINT_DESCRIPTOR_TYPE + if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) + { + for (; + (PUCHAR)CurrentDescriptor < BufferEnd; + (PVOID)CurrentDescriptor += CurrentDescriptor->bLength) + Length += CurrentDescriptor->bLength; + + } + return Length; +} + +/* + * @unimplemented + */ +PUSB_INTERFACE_DESCRIPTOR STDCALL +USBD_ParseConfigurationDescriptorEx( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + PVOID StartPosition, + LONG InterfaceNumber, + LONG AlternateSetting, + LONG InterfaceClass, + LONG InterfaceSubClass, + LONG InterfaceProtocol + ) +{ + return NULL; +} + +/* + * @implemented + */ +PUSB_INTERFACE_DESCRIPTOR STDCALL +USBD_ParseConfigurationDescriptor( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, + UCHAR InterfaceNumber, + UCHAR AlternateSetting + ) +{ + return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, + (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting, + -1, -1, -1); +} + +/* + * @unimplemented + */ +PUSB_COMMON_DESCRIPTOR STDCALL +USBD_ParseDescriptors( + PVOID DescriptorBuffer, + ULONG TotalLength, + PVOID StartPosition, + LONG DescriptorType + ) +{ + return NULL; +} + +/* + * @implemented + */ +DWORD STDCALL +USBD_GetPdoRegistryParameter( + PDEVICE_OBJECT PhysicalDeviceObject, + PVOID Parameter, + ULONG ParameterLength, + PWCHAR KeyName, + ULONG KeyNameLength + ) +{ + NTSTATUS Status; + HANDLE DevInstRegKey; + + Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject, + PLUGPLAY_REGKEY_DRIVER, STANDARD_RIGHTS_ALL, &DevInstRegKey); + if (NT_SUCCESS(Status)) + { + PKEY_VALUE_FULL_INFORMATION FullInfo; + UNICODE_STRING ValueName; + ULONG Length; + + RtlInitUnicodeString(&ValueName, KeyName); + Length = ParameterLength + KeyNameLength + sizeof(KEY_VALUE_FULL_INFORMATION); + FullInfo = ExAllocatePool(PagedPool, Length); + if (FullInfo) + { + Status = ZwQueryValueKey(DevInstRegKey, &ValueName, + KeyValueFullInformation, FullInfo, Length, &Length); + if (NT_SUCCESS(Status)) + { + RtlCopyMemory(Parameter, + ((PUCHAR)FullInfo) + FullInfo->DataOffset, + ParameterLength /*FullInfo->DataLength*/); + } + ExFreePool(FullInfo); + } else + Status = STATUS_NO_MEMORY; + ZwClose(DevInstRegKey); + } + return Status; +} diff --git a/reactos/drivers/usb/usbd/usbd.def b/reactos/drivers/usb/usbd/usbd.def new file mode 100644 index 00000000000..249dca88b66 --- /dev/null +++ b/reactos/drivers/usb/usbd/usbd.def @@ -0,0 +1,13 @@ +; +; Exports definition file for usbd.sys +; +EXPORTS +USBD_Debug_GetHeap@16 +USBD_Debug_RetHeap@12 +USBD_CalculateUsbBandwidth@12 +USBD_CreateConfigurationRequestEx@8 +USBD_CreateConfigurationRequest@8 +USBD_GetInterfaceLength@8 +USBD_ParseConfigurationDescriptorEx@28 +USBD_ParseDescriptors@16 +;USBD_GetPdoRegistryParameters diff --git a/reactos/drivers/usb/usbd/usbd.rc b/reactos/drivers/usb/usbd/usbd.rc new file mode 100644 index 00000000000..ee8239384d8 --- /dev/null +++ b/reactos/drivers/usb/usbd/usbd.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USBD Legacy Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbd\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbd.sys\0" +#include diff --git a/reactos/drivers/usb/usbhub/makefile b/reactos/drivers/usb/usbhub/makefile new file mode 100644 index 00000000000..644f5bd9a33 --- /dev/null +++ b/reactos/drivers/usb/usbhub/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = usbhub + +TARGET_DDKLIBS = ntoskrnl.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + usbhub.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/usbhub/usbhub.c b/reactos/drivers/usb/usbhub/usbhub.c new file mode 100644 index 00000000000..561f0568a9b --- /dev/null +++ b/reactos/drivers/usb/usbhub/usbhub.c @@ -0,0 +1,38 @@ +/* + * ReactOS USB hub driver + * Copyright (C) 2004 Aleksey Bragin + * (C) 2005 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* INCLUDES *******************************************************************/ +#include +#include +#include +#include "../usbport/usbport.h" + +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +/* + * Standard DriverEntry method. + */ +NTSTATUS STDCALL +DriverEntry(IN PVOID Context1, IN PVOID Context2) +{ + return STATUS_SUCCESS; +} + diff --git a/reactos/drivers/usb/usbhub/usbhub.def b/reactos/drivers/usb/usbhub/usbhub.def new file mode 100644 index 00000000000..b1a9fe457c3 --- /dev/null +++ b/reactos/drivers/usb/usbhub/usbhub.def @@ -0,0 +1,4 @@ +; +; Exports definition file for usbhub.sys +; +EXPORTS diff --git a/reactos/drivers/usb/usbhub/usbhub.h b/reactos/drivers/usb/usbhub/usbhub.h new file mode 100644 index 00000000000..01a26a42a1c --- /dev/null +++ b/reactos/drivers/usb/usbhub/usbhub.h @@ -0,0 +1,10 @@ +/* + * Declarations for undocumented usbport.sys calls + * + * Written by Mark Tempel + */ + +#ifndef _USBHUB_H +#define _USBHUB_H + +#endif /* _USBHUB_H */ diff --git a/reactos/drivers/usb/usbhub/usbhub.rc b/reactos/drivers/usb/usbhub/usbhub.rc new file mode 100644 index 00000000000..9f253e2e890 --- /dev/null +++ b/reactos/drivers/usb/usbhub/usbhub.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB Hub Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbhub\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbhub.sys\0" +#include diff --git a/reactos/drivers/usb/usbport/makefile b/reactos/drivers/usb/usbport/makefile new file mode 100644 index 00000000000..40ead05a02c --- /dev/null +++ b/reactos/drivers/usb/usbport/makefile @@ -0,0 +1,16 @@ +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = usbport + +TARGET_DDKLIBS = ntoskrnl.a + +TARGET_CFLAGS = -Werror -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -D__USE_W32API + +TARGET_OBJECTS = \ + usbport.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/usb/usbport/usbport.c b/reactos/drivers/usb/usbport/usbport.c new file mode 100644 index 00000000000..d27e4a21d3b --- /dev/null +++ b/reactos/drivers/usb/usbport/usbport.c @@ -0,0 +1,86 @@ +/* + * ReactOS USB Port driver + * Copyright (C) 2004 Aleksey Bragin + * (C) 2005 Mark Tempel + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * STATUS: + * 19-Dec-2004 - just a stub for now, but with useful info by Filip + */ + +/* INCLUDES *******************************************************************/ +#include +#include +#include +#include "usbport.h" +#include + +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +/* +** Standard DriverEntry method. +** We do nothing here. All real work is done in USBPRORT_RegisterUSBPortDriver. +*/ +NTSTATUS STDCALL +DriverEntry(IN PVOID Context1, IN PVOID Context2) +{ + DPRINT1("USBPORT.SYS DriverEntry\n"); + return STATUS_SUCCESS; +} +/* + * This method is used by miniports to connect set up + */ +NTSTATUS STDCALL +USBPORT_RegisterUSBPortDriver(PDRIVER_OBJECT DriverObject, DWORD Unknown1, + PUSB_CONTROLLER_INTERFACE Interface) +{ + //DPRINT1("USBPORT_RegisterUSBPortDriver\n"); + ASSERT(KeGetCurrentIRQL() < DISPATCH_LEVEL); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +USBPORT_GetHciMn(VOID) +{ + return 0x10000001; +} +/* + * This method is to allow miniports to create + */ +NTSTATUS STDCALL +USBPORT_AllocateUsbControllerInterface(OUT PUSB_CONTROLLER_INTERFACE *pControllerInterface) +{ + //DPRINT1("USBPORT_AllocateUsbControllerInterface\n"); + ASSERT(KeGetCurrentIRQL() < DISPATCH_LEVEL); + ASSERT(0 != ControllerObject); + + *pControllerInterface = (PUSB_CONTROLLER_INTERFACE)ExAllocatePoolWithTag(PagedPool, sizeof(USB_CONTROLLER_INTERFACE),USB_CONTROLLER_INTERFACE_TAG); + RtlZeroMemory(*pControllerInterface, sizeof(USB_CONTROLLER_INTERFACE)); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +USBPORT_FreeUsbControllerInterface(IN PUSB_CONTROLLER_INTERFACE ControllerInterface) +{ + //DPRINT1("USBPORT_FreeUsbControllerInterface\n"); + ASSERT(KeGetCurrentIRQL() < DISPATCH_LEVEL); + + ExFreePool(ControllerInterface); + + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/usb/usbport/usbport.def b/reactos/drivers/usb/usbport/usbport.def new file mode 100644 index 00000000000..c647cb15917 --- /dev/null +++ b/reactos/drivers/usb/usbport/usbport.def @@ -0,0 +1,8 @@ +; +; Exports definition file for usbport.sys +; +EXPORTS +USBPORT_RegisterUSBPortDriver@12 +USBPORT_GetHciMn@0 +USBPORT_AllocateUsbControllerInterface@4 +USBPORT_FreeUsbControllerInterface@4 \ No newline at end of file diff --git a/reactos/drivers/usb/usbport/usbport.h b/reactos/drivers/usb/usbport/usbport.h new file mode 100644 index 00000000000..36cfc509be0 --- /dev/null +++ b/reactos/drivers/usb/usbport/usbport.h @@ -0,0 +1,130 @@ +/* + * Declarations for undocumented usbport.sys calls + * + * Written by Filip Navara + * Updates by Mark Tempel + */ + +#ifndef _USBPORT_H +#define _USBPORT_H + +#define USB_CONTROLLER_INTERFACE_TAG 0x001E1E10 + +/**** B E G I N M S I N T E R N A L P R O T O C O L ****/ +typedef DWORD (*POPEN_ENDPOINT)( + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 +); + +typedef NTSTATUS (*PPOKE_ENDPOINT)( + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 +); + +typedef DWORD (*PQUERY_ENDPOINT_REQUIREMENTS)( + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 +); + +typedef VOID (*PCLOSE_ENDPOINT)( + DWORD Unknown1, + DWORD Unknown2 +); + + + +typedef struct { + DWORD Unknown1; /* 2 (UHCI), 3 (EHCI) */ + DWORD Unknown2; /* 2C3 (UHCI), 95 (EHCI) */ + DWORD Unknown3; /* 2EE0 (UHCI), 61A80 (EHCI) */ + DWORD Unknown4; /* - */ + DWORD Unknown5; /* 164 (UHCI), 178 (EHCI) */ + DWORD Unknown6; /* 8C (UHCI), A0 (EHCI) */ + DWORD Unknown7; /* 1C (UHCI), 30 (EHCI) */ /* Offset: 118 */ + DWORD Unknown8; /* - */ + DWORD Unknown9; /* - */ + DWORD Unknown10; /* 2280 (UHCI), 2C800 (EHCI) */ /* Offset: 124 */ + POPEN_ENDPOINT OpenEndpoint; + PPOKE_ENDPOINT PokeEndpoint; + PQUERY_ENDPOINT_REQUIREMENTS QueryEndpointRequirements; + PCLOSE_ENDPOINT CloseEndpoint; + PVOID StartController; /* P00010A1C (2) */ /* Offset: 138 */ + PVOID StopController; /* P00010952 */ /* Offset: 13C */ + PVOID SuspendController; /* P00011584 */ /* Offset: 140 */ + PVOID ResumeController; /* P0001164C */ /* Offset: 144 */ + PVOID InterruptService; /* P00013C72 */ /* Offset: 148 */ + PVOID InterruptDpc; /* P00013D8E */ /* Offset: 14C */ + PVOID SubmitTransfer; /* P00011010 */ /* Offset: 150 */ + PVOID IsochTransfer; /* P000136E8 */ /* Offset: 154 */ + PVOID AbortTransfer; /* P00011092 */ /* Offset: 158 */ + PVOID GetEndpointState; /* P00010F48 */ /* Offset: 15C */ + PVOID SetEndpointState; /* P00010EFA */ /* Offset: 160 */ + PVOID PollEndpoint; /* P00010D32 */ /* Offset: 164 */ + PVOID CheckController; /* P00011794 */ /* Offset: 168 */ + PVOID Get32BitFrameNumber; /* P00010F86 */ /* Offset: 16C */ + PVOID InterruptNextSOF; /* P00013F56 */ /* Offset: 170 */ + PVOID EnableInterrupts; /* P00013ED0 */ /* Offset: 174 */ + PVOID DisableInterrupts; /* P00013E18 */ /* Offset: 178 */ + PVOID PollController; /* P00010FF2 */ /* Offset: 17C */ + PVOID SetEndpointDataToggle; /* P000110E6 */ /* Offset: 180 */ + PVOID GetEndpointStatus; /* P00010ECE */ /* Offset: 184 */ + PVOID SetEndpointStatus; /* P00010E52 */ /* Offset: 188 */ + DWORD Unknown36; /* - */ + PVOID RHGetRootHubData; /* P00011AC6 */ /* Offset: 190 */ + PVOID RHGetStatus; /* P00011B1A */ /* Offset: 194 */ + PVOID RHGetPortStatus; /* P00011BBA */ /* Offset: 198 */ + PVOID RHGetHubStatus; /* P00011B28 */ /* Offset: 19C */ + PVOID RHSetFeaturePortReset; /* P00011F84 */ /* Offset: 1A0 */ + PVOID RHSetFeaturePortPower; /* P00011BB4 */ /* Offset: 1A4 */ + PVOID RHSetFeaturePortEnable; /* P00011BA2 */ /* Offset: 1A8 */ + PVOID RHSetFeaturePortSuspend; /* P00011FF8 */ /* Offset: 1AC */ + PVOID RHClearFeaturePortEnable; /* P00011B90 */ /* Offset: 1B0 */ + PVOID RHClearFeaturePortPower; /* P00011BB4 */ /* Offset: 1B4 */ + PVOID RHClearFeaturePortSuspend; /* P0001210E */ /* Offset: 1B8 */ + PVOID RHClearFeaturePortEnableChange; /* P00012236 */ /* Offset: 1BC */ + PVOID RHClearFeaturePortConnectChange; /* P000121DE */ /* Offset: 1C0 */ + PVOID RHClearFeaturePortResetChange; /* P00012284 */ /* Offset: 1C4 */ + PVOID RHClearFeaturePortSuspendChange; /* P0001229C */ /* Offset: 1C8 */ + PVOID RHClearFeaturePortOvercurrentChange; /* P000122B4 */ /* Offset: 1CC */ + PVOID RHDisableIrq; /* P00013F52 */ /* Offset: 1D0 */ + PVOID RHDisableIrq2; /* P00013F52 */ /* Offset: 1D4 */ + PVOID StartSendOnePacket; /* P00011144 */ /* Offset: 1D8 */ + PVOID EndSendOnePacket; /* P000119B6 */ /* Offset: 1DC */ + PVOID PassThru; /* P000110E0 */ /* Offset: 1E0 */ + DWORD Unknown58[17]; /* - */ + PVOID FlushInterrupts; /* P00013EA0 */ /* Offset: 228 */ + /* ... */ +} USB_CONTROLLER_INTERFACE, *PUSB_CONTROLLER_INTERFACE; +/**** E N D M S I N T E R N A L P R O T O C O L ****/ + +/* + * With this call USB miniport driver registers itself with usbport.sys + * + * Unknown1 - Could be 0x64 or 0xC8. (0x9A also ?) + * Unknown2 - Pointer to structure which contains function entry points + */ +NTSTATUS STDCALL +USBPORT_RegisterUSBPortDriver(PDRIVER_OBJECT DriverObject, DWORD Unknown1, + PUSB_CONTROLLER_INTERFACE Interface); + +/* + * This function always returns 0x10000001 in Windows XP SP1 + */ +NTSTATUS STDCALL +USBPORT_GetHciMn(VOID); + +/* + * This method is provided for miniports to use to allocate their USB_CONTROLLER_INTERFACEs. + */ +NTSTATUS STDCALL +USBPORT_AllocateUsbControllerInterface(OUT PUSB_CONTROLLER_INTERFACE *pControllerInterface); + +/* + * We can't have an allocate without a free. + */ +NTSTATUS STDCALL +USBPORT_FreeUsbControllerInterface(IN PUSB_CONTROLLER_INTERFACE ControllerInterface); +#endif /* _USBPORT_H */ diff --git a/reactos/drivers/usb/usbport/usbport.rc b/reactos/drivers/usb/usbport/usbport.rc new file mode 100644 index 00000000000..e8482bb8fc0 --- /dev/null +++ b/reactos/drivers/usb/usbport/usbport.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USB Port Driver\0" +#define REACTOS_STR_INTERNAL_NAME "usbport\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbport.sys\0" +#include diff --git a/reactos/drivers/video/displays/vga/objects/bitblt.c b/reactos/drivers/video/displays/vga/objects/bitblt.c index 4726dffe890..fbdc29c46cb 100644 --- a/reactos/drivers/video/displays/vga/objects/bitblt.c +++ b/reactos/drivers/video/displays/vga/objects/bitblt.c @@ -188,20 +188,21 @@ VGADDI_BltBrush(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* MaskSurf, } /* Punt pattern fills. */ - if ((Rop4 == PATCOPY || Rop4 == PATINVERT) && + if ((GET_OPINDEX_FROM_ROP4(Rop4) == GET_OPINDEX_FROM_ROP3(PATCOPY) + || GET_OPINDEX_FROM_ROP4(Rop4) == GET_OPINDEX_FROM_ROP3(PATINVERT)) && Brush->iSolidColor == 0xFFFFFFFF) { return(FALSE); } /* Get the brush colour. */ - switch (Rop4) + switch (GET_OPINDEX_FROM_ROP4(Rop4)) { - case PATCOPY: SolidColor = Brush->iSolidColor; break; - case PATINVERT: SolidColor = Brush->iSolidColor; RasterOp = VGA_XOR; break; - case WHITENESS: SolidColor = 0xF; break; - case BLACKNESS: SolidColor = 0x0; break; - case DSTINVERT: SolidColor = 0xF; RasterOp = VGA_XOR; break; + case GET_OPINDEX_FROM_ROP3(PATCOPY): SolidColor = Brush->iSolidColor; break; + case GET_OPINDEX_FROM_ROP3(PATINVERT): SolidColor = Brush->iSolidColor; RasterOp = VGA_XOR; break; + case GET_OPINDEX_FROM_ROP3(WHITENESS): SolidColor = 0xF; break; + case GET_OPINDEX_FROM_ROP3(BLACKNESS): SolidColor = 0x0; break; + case GET_OPINDEX_FROM_ROP3(DSTINVERT): SolidColor = 0xF; RasterOp = VGA_XOR; break; } /* Select write mode 3. */ @@ -398,15 +399,15 @@ DrvBitBlt(SURFOBJ *Dest, switch (rop4) { - case BLACKNESS: - case PATCOPY: - case WHITENESS: - case PATINVERT: - case DSTINVERT: + case ROP3_TO_ROP4(BLACKNESS): + case ROP3_TO_ROP4(PATCOPY): + case ROP3_TO_ROP4(WHITENESS): + case ROP3_TO_ROP4(PATINVERT): + case ROP3_TO_ROP4(DSTINVERT): BltRectFunc = VGADDI_BltBrush; break; - case SRCCOPY: + case ROP3_TO_ROP4(SRCCOPY): if (BMF_4BPP == Source->iBitmapFormat && BMF_4BPP == Dest->iBitmapFormat) { BltRectFunc = VGADDI_BltSrc; @@ -417,7 +418,7 @@ DrvBitBlt(SURFOBJ *Dest, } break; - case 0xAACC: + case R4_MASK: BltRectFunc = VGADDI_BltMask; break; diff --git a/reactos/drivers/video/displays/vga/objects/bitblt.h b/reactos/drivers/video/displays/vga/objects/bitblt.h index 2f5d359eb81..e52edf9247b 100644 --- a/reactos/drivers/video/displays/vga/objects/bitblt.h +++ b/reactos/drivers/video/displays/vga/objects/bitblt.h @@ -20,3 +20,10 @@ #define BB_TARGET_ONLY 0x0002 #define BB_SOURCE_COPY 0x0004 #define BB_PATTERN_COPY 0x0008 + +#define GET_OPINDEX_FROM_ROP3(Rop3) (((Rop3) >> 16) & 0xff) +#define GET_OPINDEX_FROM_ROP4(Rop4) ((Rop4) & 0xff) +#define ROP3_TO_ROP4(Rop3) ((((Rop3) >> 8) & 0xff00) | (((Rop3) >> 16) & 0x00ff)) +#define R3_OPINDEX_SRCCOPY 0xcc +#define R3_OPINDEX_NOOP 0xaa +#define R4_MASK ((R3_OPINDEX_NOOP << 8) | R3_OPINDEX_SRCCOPY) diff --git a/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c index 620dbfd7431..2f06df440a2 100644 --- a/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c +++ b/reactos/drivers/video/displays/vga/vgavideo/vgavideo.c @@ -18,8 +18,8 @@ static unsigned char leftMask; static int byteCounter; static unsigned char rightMask; -#define READ_REGISTER_UCHAR(p) (*((PUCHAR)(p))) -#define WRITE_REGISTER_UCHAR(p,c) (*((PCHAR)(p))) = (c) +#define READ_REGISTER_UCHAR(p) (*((volatile UCHAR *)(p))) +#define WRITE_REGISTER_UCHAR(p,c) (*((volatile CHAR *)(p))) = (c) INT abs(INT nm) { diff --git a/reactos/drivers/video/videoprt/Makefile b/reactos/drivers/video/videoprt/Makefile index b9d8197ed7e..68b83b0da9e 100644 --- a/reactos/drivers/video/videoprt/Makefile +++ b/reactos/drivers/video/videoprt/Makefile @@ -9,6 +9,8 @@ TARGET_NAME = videoprt TARGET_CFLAGS += -Wall -Werror -D__USE_W32API -I$(PATH_TO_TOP)/ntoskrnl/include TARGET_OBJECTS = \ + agp.o \ + ddc.o \ dispatch.o \ dma.o \ event.o \ diff --git a/reactos/drivers/video/videoprt/agp.c b/reactos/drivers/video/videoprt/agp.c new file mode 100644 index 00000000000..a40d96bcb09 --- /dev/null +++ b/reactos/drivers/video/videoprt/agp.c @@ -0,0 +1,566 @@ +/* + * VideoPort driver + * + * Copyright (C) 2002, 2003, 2004 ReactOS Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#include "videoprt.h" +#include +#include + +/* PRIVATE FUNCTIONS **********************************************************/ + +STATIC NTSTATUS +IopInitiatePnpIrp( + PDEVICE_OBJECT DeviceObject, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG MinorFunction, + PIO_STACK_LOCATION Stack OPTIONAL) +{ + PDEVICE_OBJECT TopDeviceObject; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + /* Always call the top of the device stack */ + TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); + + KeInitializeEvent( + &Event, + NotificationEvent, + FALSE); + + Irp = IoBuildSynchronousFsdRequest( + IRP_MJ_PNP, + TopDeviceObject, + NULL, + 0, + NULL, + &Event, + IoStatusBlock); + + /* PNP IRPs are always initialized with a status code of + STATUS_NOT_IMPLEMENTED */ + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->MinorFunction = MinorFunction; + + if (Stack) + { + RtlMoveMemory( + &IrpSp->Parameters, + &Stack->Parameters, + sizeof(Stack->Parameters)); + } + + Status = IoCallDriver(TopDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject( + &Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock->Status; + } + + ObDereferenceObject(TopDeviceObject); + + return Status; +} + + +BOOLEAN STDCALL +IntAgpCommitPhysical( + IN PVOID HwDeviceExtension, + IN PVOID PhysicalContext, + IN ULONG Pages, + IN ULONG Offset) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + PHYSICAL_ADDRESS MappingAddr = {{0}}; + PVIDEO_PORT_AGP_MAPPING AgpMapping; + NTSTATUS Status; + + DPRINT("AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n", + PhysicalContext, Pages, Offset); + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext; + + Status = AgpBusInterface->CommitMemory(AgpBusInterface->AgpContext, + AgpMapping->MapHandle, Pages, Offset, + NULL, &MappingAddr); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n", + Status); + } + return NT_SUCCESS(Status); +} + +VOID STDCALL +IntAgpFreePhysical( + IN PVOID HwDeviceExtension, + IN PVOID PhysicalContext, + IN ULONG Pages, + IN ULONG Offset) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + PVIDEO_PORT_AGP_MAPPING AgpMapping; + NTSTATUS Status; + + DPRINT("AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n", + PhysicalContext, Pages, Offset); + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext; + + Status = AgpBusInterface->FreeMemory(AgpBusInterface->AgpContext, + AgpMapping->MapHandle, Pages, Offset); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n", + Status); + } +} + +VOID STDCALL +IntAgpReleasePhysical( + IN PVOID HwDeviceExtension, + IN PVOID PhysicalContext) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + PVIDEO_PORT_AGP_MAPPING AgpMapping; + NTSTATUS Status; + + DPRINT("AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext); + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext; + + /* Release memory */ + Status = AgpBusInterface->ReleaseMemory(AgpBusInterface->AgpContext, + AgpMapping->MapHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n", + Status); + } + + /* Free resources */ + ExFreePool(AgpMapping); +} + +PHYSICAL_ADDRESS STDCALL +IntAgpReservePhysical( + IN PVOID HwDeviceExtension, + IN ULONG Pages, + IN VIDEO_PORT_CACHE_TYPE Caching, + OUT PVOID *PhysicalContext) +{ + PHYSICAL_ADDRESS ZeroAddress = {{0}}; + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + MEMORY_CACHING_TYPE MemCachingType; + PVIDEO_PORT_AGP_MAPPING AgpMapping; + NTSTATUS Status; + + DPRINT("AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages, Caching); + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + + /* Translate memory caching type */ + if (Caching == VpNonCached) + MemCachingType = MmNonCached; + else if (Caching == VpCached) + MemCachingType = MmCached; + else if (Caching == VpWriteCombined) + MemCachingType = MmWriteCombined; + else + { + DPRINT1("Invalid caching type %d!\n", Caching); + return ZeroAddress; + } + + /* Allocate an AGP mapping structure */ + AgpMapping = ExAllocatePoolWithTag(PagedPool, + sizeof(VIDEO_PORT_AGP_MAPPING), + TAG_VIDEO_PORT); + if (AgpMapping == NULL) + { + DPRINT1("Out of memory! Couldn't allocate AGP mapping structure!\n"); + return ZeroAddress; + } + RtlZeroMemory(AgpMapping, sizeof(VIDEO_PORT_AGP_MAPPING)); + + /* Reserve memory for the AGP bus */ + Status = AgpBusInterface->ReserveMemory(AgpBusInterface->AgpContext, + Pages, + MemCachingType, + &AgpMapping->MapHandle, + &AgpMapping->PhysicalAddress); + if (!NT_SUCCESS(Status) || AgpMapping->MapHandle == NULL) + { + ExFreePool(AgpMapping); + DPRINT1("Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n", + Status); + return ZeroAddress; + } + + /* Fill the rest of the AGP mapping */ + AgpMapping->NumberOfPages = Pages; + + *PhysicalContext = (PVOID)AgpMapping; + return AgpMapping->PhysicalAddress; +} + + +PVOID STDCALL +IntAgpCommitVirtual( + IN PVOID HwDeviceExtension, + IN PVOID VirtualContext, + IN ULONG Pages, + IN ULONG Offset) +{ + PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping; + PVOID BaseAddress = NULL; + NTSTATUS Status; + + DPRINT("AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n", + VirtualContext, Pages, Offset); + + VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext; + + /* I think the NT API provides no way of reserving a part of the address space + * and setting it up to map into a specified range of physical memory later. + * This means that we will have to release some of the reserved virtual memory + * and map the physical memory into it using MapViewOfSection. + * + * - blight (2004-12-21) + */ + + if (VirtualMapping->ProcessHandle == NULL) + { + /* FIXME: not implemented */ + } + else /* ProcessHandle != NULL */ + { + /* Release some virtual memory */ + ULONG Size = Pages * PAGE_SIZE; + ULONG OffsetInBytes = Offset * PAGE_SIZE; + BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes); + PHYSICAL_ADDRESS PhysicalAddress = VirtualMapping->AgpMapping->PhysicalAddress; + PhysicalAddress.QuadPart += OffsetInBytes; + + Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle, + &BaseAddress, + &Size, MEM_RELEASE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status); + return NULL; + } + ASSERT(Size == Pages * PAGE_SIZE); + ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes)); + + /* Map the physical memory into the released virtual memory area */ + Status = IntVideoPortMapPhysicalMemory(VirtualMapping->ProcessHandle, + PhysicalAddress, + Size, + PAGE_READWRITE, + &BaseAddress); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: IntVideoPortMapPhysicalMemory() failed: Status = 0x%x\n", Status); + /* Reserve the released virtual memory area again */ + Status = ZwAllocateVirtualMemory(VirtualMapping->ProcessHandle, + &BaseAddress, 0, &Size, MEM_RESERVE, + PAGE_NOACCESS); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status); + /* FIXME: What to do now?? */ + ASSERT(0); + return NULL; + } + ASSERT(Size == Pages * PAGE_SIZE); + ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes)); + return NULL; + } + ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes)); + } + + return BaseAddress; +} + +VOID STDCALL +IntAgpFreeVirtual( + IN PVOID HwDeviceExtension, + IN PVOID VirtualContext, + IN ULONG Pages, + IN ULONG Offset) +{ + PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping; + PVOID BaseAddress = NULL; + NTSTATUS Status; + + DPRINT("AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n", + VirtualContext, Pages, Offset); + + VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext; + + if (VirtualMapping->ProcessHandle == NULL) + { + /* FIXME: not implemented */ + } + else /* ProcessHandle != NULL */ + { + /* Unmap the section view */ + ULONG Size = Pages * PAGE_SIZE; + ULONG OffsetInBytes = Offset * PAGE_SIZE; + BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes); + + Status = ZwUnmapViewOfSection(VirtualMapping->ProcessHandle, BaseAddress); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status); + /* FIXME: What to do now?? */ + ASSERT(0); + return; + } + + /* And reserve the virtual memory area again */ + Status = ZwAllocateVirtualMemory(VirtualMapping->ProcessHandle, + &BaseAddress, 0, &Size, MEM_RESERVE, + PAGE_NOACCESS); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status); + /* FIXME: What to do now?? */ + ASSERT(0); + return; + } + ASSERT(Size == Pages * PAGE_SIZE); + ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress + + OffsetInBytes)); + } +} + +VOID STDCALL +IntAgpReleaseVirtual( + IN PVOID HwDeviceExtension, + IN PVOID VirtualContext) +{ + PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping; + NTSTATUS Status; + + DPRINT("AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext); + + VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext; + + /* Release the virtual memory */ + if (VirtualMapping->ProcessHandle == NULL) + { + /* FIXME: not implemented */ + } + else /* ProcessHandle != NULL */ + { + /* Release the allocated virtual memory */ + ULONG Size = VirtualMapping->AgpMapping->NumberOfPages * PAGE_SIZE; + Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle, + &VirtualMapping->MappedAddress, + &Size, MEM_RELEASE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status); + } + } + + /* Free resources */ + ExFreePool(VirtualMapping); +} + +PVOID STDCALL +IntAgpReserveVirtual( + IN PVOID HwDeviceExtension, + IN HANDLE ProcessHandle, + IN PVOID PhysicalContext, + OUT PVOID *VirtualContext) +{ + PVIDEO_PORT_AGP_MAPPING AgpMapping; + PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping; + PVOID MappedAddress; + NTSTATUS Status; + + DPRINT("AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n", + ProcessHandle, PhysicalContext); + + AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext; + + /* Allocate an AGP virtual mapping structure */ + VirtualMapping = ExAllocatePoolWithTag(PagedPool, + sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING), + TAG_VIDEO_PORT); + if (VirtualMapping == NULL) + { + DPRINT1("Out of memory! Couldn't allocate AGP virtual mapping structure!\n"); + return NULL; + } + RtlZeroMemory(VirtualMapping, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING)); + + /* Reserve a virtual memory area for the physical pages. */ + if (ProcessHandle == NULL) + { + /* FIXME: What to do in this case? */ + ExFreePool(VirtualMapping); + return NULL; + } + else /* ProcessHandle != NULL */ + { + /* Reserve memory for usermode */ + ULONG Size = AgpMapping->NumberOfPages * PAGE_SIZE; + MappedAddress = NULL; + Status = ZwAllocateVirtualMemory(ProcessHandle, &MappedAddress, 0, &Size, + MEM_RESERVE, PAGE_NOACCESS); + if (!NT_SUCCESS(Status)) + { + ExFreePool(VirtualMapping); + DPRINT("ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status); + return NULL; + } + } + + /* Fill the AGP virtual mapping */ + VirtualMapping->AgpMapping = AgpMapping; + VirtualMapping->ProcessHandle = ProcessHandle; + VirtualMapping->MappedAddress = MappedAddress; + + *VirtualContext = (PVOID)VirtualMapping; + return MappedAddress; +} + + +BOOLEAN STDCALL +IntAgpSetRate( + IN PVOID HwDeviceExtension, + IN ULONG Rate) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + + DPRINT("AgpSetRate - Rate: %d\n", Rate); + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + + return NT_SUCCESS(AgpBusInterface->SetRate(AgpBusInterface->AgpContext, Rate)); +} + + +NTSTATUS STDCALL +IntAgpGetInterface( + IN PVOID HwDeviceExtension, + IN OUT PINTERFACE Interface) +{ + IO_STATUS_BLOCK IoStatusBlock; + IO_STACK_LOCATION IoStack; + NTSTATUS Status; + PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface; + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PAGP_BUS_INTERFACE_STANDARD AgpBusInterface; + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + AgpBusInterface = &DeviceExtension->AgpInterface; + AgpInterface = (PVIDEO_PORT_AGP_INTERFACE_2)Interface; + + ASSERT((Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_2 && + Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE_2)) || + (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1 && + Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE))); + + if (DeviceExtension->NextDeviceObject == NULL) + { + DPRINT("DeviceExtension->NextDeviceObject is NULL!\n"); + return STATUS_UNSUCCESSFUL; + } + + /* Query the interface from the AGP bus driver */ + if (DeviceExtension->AgpInterface.Size == 0) + { + AgpBusInterface->Size = sizeof(AGP_BUS_INTERFACE_STANDARD); + if (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1) + AgpBusInterface->Version = AGP_BUS_INTERFACE_V1; + else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */ + AgpBusInterface->Version = AGP_BUS_INTERFACE_V2; + IoStack.Parameters.QueryInterface.Size = AgpBusInterface->Size; + IoStack.Parameters.QueryInterface.Version = AgpBusInterface->Version; + IoStack.Parameters.QueryInterface.Interface = (PINTERFACE)AgpBusInterface; + IoStack.Parameters.QueryInterface.InterfaceType = + &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD; + Status = IopInitiatePnpIrp(DeviceExtension->NextDeviceObject, + &IoStatusBlock, IRP_MN_QUERY_INTERFACE, &IoStack); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status); + return Status; + } + DPRINT("Got AGP driver interface!\n"); + } + + /* FIXME: Not sure if we should wrap the reference/dereference functions */ + AgpInterface->Context = AgpBusInterface->AgpContext; + AgpInterface->InterfaceReference = AgpBusInterface->InterfaceReference; + AgpInterface->InterfaceDereference = AgpBusInterface->InterfaceDereference; + AgpInterface->AgpReservePhysical = IntAgpReservePhysical; + AgpInterface->AgpReleasePhysical = IntAgpReleasePhysical; + AgpInterface->AgpCommitPhysical = IntAgpCommitPhysical; + AgpInterface->AgpFreePhysical = IntAgpFreePhysical; + AgpInterface->AgpReserveVirtual = IntAgpReserveVirtual; + AgpInterface->AgpReleaseVirtual = IntAgpReleaseVirtual; + AgpInterface->AgpCommitVirtual = IntAgpCommitVirtual; + AgpInterface->AgpFreeVirtual = IntAgpFreeVirtual; + AgpInterface->AgpAllocationLimit = 0x1000000; /* FIXME: using 16 MB for now */ + + if (AgpInterface->Version >= VIDEO_PORT_AGP_INTERFACE_VERSION_2) + { + AgpInterface->AgpSetRate = IntAgpSetRate; + } + + return STATUS_SUCCESS; +} + diff --git a/reactos/drivers/video/videoprt/ddc.c b/reactos/drivers/video/videoprt/ddc.c new file mode 100644 index 00000000000..c200c3a827f --- /dev/null +++ b/reactos/drivers/video/videoprt/ddc.c @@ -0,0 +1,227 @@ +/* + * VideoPort driver + * + * Copyright (C) 2002, 2003, 2004 ReactOS Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#include "videoprt.h" + +#define DDC_EEPROM_ADDRESS 0xA0 + +/* PRIVATE FUNCTIONS **********************************************************/ + +#define LOW 0 +#define HIGH 1 +#define WRITE 0 +#define READ 1 +#define READ_SDA() (i2c->ReadDataLine(HwDeviceExtension)) +#define READ_SCL() (i2c->ReadClockLine(HwDeviceExtension)) +#define WRITE_SDA(state) (i2c->WriteDataLine(HwDeviceExtension, state)) +#define WRITE_SCL(state) (i2c->WriteClockLine(HwDeviceExtension, state)) + +STATIC LARGE_INTEGER HalfPeriodDelay = { { 70LL } }; +#define DELAY_HALF() KeDelayExecutionThread(KernelMode, FALSE, &HalfPeriodDelay) + + +STATIC BOOL +I2CWrite(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Data) +{ + UCHAR Bit; + BOOL Ack; + + /* transmit data */ + for (Bit = (1 << 7); Bit != 0; Bit >>= 1) + { + WRITE_SCL(LOW); + WRITE_SDA((Data & Bit) ? HIGH : LOW); + DELAY_HALF(); + WRITE_SCL(HIGH); + DELAY_HALF(); + } + + /* get ack */ + WRITE_SCL(LOW); + WRITE_SDA(HIGH); + DELAY_HALF(); + WRITE_SCL(HIGH); + do + { + DELAY_HALF(); + } + while (READ_SCL() != HIGH); + Ack = (READ_SDA() == LOW); + DELAY_HALF(); + + DPRINT("I2CWrite: %s\n", Ack ? "Ack" : "Nak"); + return Ack; +} + + +STATIC UCHAR +I2CRead(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, BOOL Ack) +{ + INT Bit = 0x80; + UCHAR Data = 0; + + /* pull down SCL and release SDA */ + WRITE_SCL(LOW); + WRITE_SDA(HIGH); + + /* read byte */ + for (Bit = (1 << 7); Bit != 0; Bit >>= 1) + { + WRITE_SCL(LOW); + DELAY_HALF(); + WRITE_SCL(HIGH); + DELAY_HALF(); + if (READ_SDA() == HIGH) + Data |= Bit; + } + + /* send ack/nak */ + WRITE_SCL(LOW); + WRITE_SDA(Ack ? LOW : HIGH); + DELAY_HALF(); + WRITE_SCL(HIGH); + do + { + DELAY_HALF(); + } + while (READ_SCL() != HIGH); + + return Data; +} + + +STATIC VOID +I2CStop(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c) +{ + WRITE_SCL(LOW); + WRITE_SDA(LOW); + DELAY_HALF(); + WRITE_SCL(HIGH); + DELAY_HALF(); + WRITE_SDA(HIGH); +} + + +STATIC BOOL +I2CStart(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Address) +{ + /* make sure the bus is free */ + if (READ_SDA() == LOW || READ_SCL() == LOW) + { + DPRINT1("I2CStart: Bus is not free!\n"); + return FALSE; + } + + /* send address */ + WRITE_SDA(LOW); + DELAY_HALF(); + if (!I2CWrite(HwDeviceExtension, i2c, Address)) + { + /* ??release the bus?? */ + I2CStop(HwDeviceExtension, i2c); + DPRINT1("I2CStart: Device not found (Address = 0x%x)\n", Address); + return FALSE; + } + + DPRINT("I2CStart: SUCCESS!\n"); + return TRUE; +} + + +STATIC BOOL +I2CRepStart(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Address) +{ + /* setup lines for repeated start condition */ + WRITE_SCL(LOW); + DELAY_HALF(); + WRITE_SDA(HIGH); + DELAY_HALF(); + WRITE_SCL(HIGH); + DELAY_HALF(); + + return I2CStart(HwDeviceExtension, i2c, Address); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ + +BOOLEAN STDCALL +VideoPortDDCMonitorHelper( + PVOID HwDeviceExtension, + PVOID I2CFunctions, + PUCHAR pEdidBuffer, + ULONG EdidBufferSize + ) +{ + PDDC_CONTROL ddc = (PDDC_CONTROL)I2CFunctions; + PI2C_CALLBACKS i2c = &ddc->I2CCallbacks; + INT Count, i; + PUCHAR pBuffer = (PUCHAR)pEdidBuffer; + BOOL Ack; + + DPRINT("VideoPortDDCMonitorHelper()\n"); + + ASSERT_IRQL(PASSIVE_LEVEL); + if (ddc->Size != sizeof (ddc)) + { + DPRINT("ddc->Size != %d (%d)\n", sizeof (ddc), ddc->Size); + return FALSE; + } + + /* select eeprom */ + if (!I2CStart(HwDeviceExtension, i2c, DDC_EEPROM_ADDRESS | WRITE)) + return FALSE; + /* set address */ + if (!I2CWrite(HwDeviceExtension, i2c, 0x00)) + return FALSE; + /* change into read mode */ + if (!I2CRepStart(HwDeviceExtension, i2c, DDC_EEPROM_ADDRESS | READ)) + return FALSE; + /* read eeprom */ + RtlZeroMemory(pEdidBuffer, EdidBufferSize); + Count = min(128, EdidBufferSize); + for (i = 0; i < Count; i++) + { + Ack = ((i + 1) < Count); + pBuffer[i] = I2CRead(HwDeviceExtension, i2c, Ack); + } + I2CStop(HwDeviceExtension, i2c); + + /* check EDID header */ + if (pBuffer[0] != 0x00 || pBuffer[1] != 0xff || + pBuffer[2] != 0xff || pBuffer[3] != 0xff || + pBuffer[4] != 0xff || pBuffer[5] != 0xff || + pBuffer[6] != 0xff || pBuffer[7] != 0x00) + { + DPRINT1("VideoPortDDCMonitorHelper(): Invalid EDID header!\n"); + return FALSE; + } + + DPRINT("VideoPortDDCMonitorHelper(): EDID version %d rev. %d\n", pBuffer[18], pBuffer[19]); + DPRINT("VideoPortDDCMonitorHelper() - SUCCESS!\n"); + return TRUE; +} + diff --git a/reactos/drivers/video/videoprt/dispatch.c b/reactos/drivers/video/videoprt/dispatch.c index 170fbe22266..504cbbde074 100644 --- a/reactos/drivers/video/videoprt/dispatch.c +++ b/reactos/drivers/video/videoprt/dispatch.c @@ -78,13 +78,14 @@ IntVideoPortAddDevice( DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); /* - * Use generic routine to find the adapter and create device object. + * Create adapter device object. */ - return IntVideoPortFindAdapter( + return IntVideoPortCreateAdapterDeviceObject( DriverObject, DriverExtension, - PhysicalDeviceObject); + PhysicalDeviceObject, + NULL); } /* @@ -264,18 +265,149 @@ IntVideoPortDispatchDeviceControl( return Status; } +NTSTATUS STDCALL +IntVideoPortPnPStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PDRIVER_OBJECT DriverObject; + PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + PCM_RESOURCE_LIST AllocatedResources; + + /* + * Get the initialization data we saved in VideoPortInitialize. + */ + + DriverObject = DeviceObject->DriverObject; + DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); + DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* + * Store some resources in the DeviceExtension. + */ + + AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources; + if (AllocatedResources != NULL) + { + CM_FULL_RESOURCE_DESCRIPTOR *FullList; + CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor; + ULONG ResourceCount; + ULONG ResourceListSize; + + /* Save the resource list */ + ResourceCount = AllocatedResources->List[0].PartialResourceList.Count; + ResourceListSize = + FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList. + PartialDescriptors[ResourceCount]); + DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize); + if (DeviceExtension->AllocatedResources == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlCopyMemory(DeviceExtension->AllocatedResources, + AllocatedResources, + ResourceListSize); + + /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */ + for (FullList = AllocatedResources->List; + FullList < AllocatedResources->List + AllocatedResources->Count; + FullList++) + { + /* FIXME: Is this ASSERT ok for resources from the PNP manager? */ + ASSERT(FullList->InterfaceType == PCIBus && + FullList->BusNumber == DeviceExtension->SystemIoBusNumber && + 1 == FullList->PartialResourceList.Version && + 1 == FullList->PartialResourceList.Revision); + for (Descriptor = FullList->PartialResourceList.PartialDescriptors; + Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count; + Descriptor++) + { + if (Descriptor->Type == CmResourceTypeInterrupt) + { + DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level; + DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector; + } + } + } + } + DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n", + DeviceExtension->InterruptLevel, + DeviceExtension->InterruptVector); + + /* + * Create adapter device object. + */ + + return IntVideoPortFindAdapter( + DriverObject, + DriverExtension, + DeviceObject); +} + + +NTSTATUS +STDCALL +IntVideoPortForwardIrpAndWaitCompletionRoutine( + PDEVICE_OBJECT Fdo, + PIRP Irp, + PVOID Context) +{ + PKEVENT Event = Context; + + if (Irp->PendingReturned) + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + + +NTSTATUS +STDCALL +IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + KEVENT Event; + NTSTATUS Status; + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = + (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine, + &Event, TRUE, TRUE, TRUE); + Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = Irp->IoStatus.Status; + } + return Status; +} + + NTSTATUS STDCALL IntVideoPortDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; IrpSp = IoGetCurrentIrpStackLocation(Irp); switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: + Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp); + if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) + Status = IntVideoPortPnPStartDevice(DeviceObject, Irp); + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + case IRP_MN_REMOVE_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: @@ -283,16 +415,28 @@ IntVideoPortDispatchPnp( case IRP_MN_SURPRISE_REMOVAL: case IRP_MN_STOP_DEVICE: + Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp); + if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) + Status = STATUS_SUCCESS; + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: + Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; + break; + + default: + return STATUS_NOT_IMPLEMENTED; + break; } - return STATUS_NOT_IMPLEMENTED; + return Status; } NTSTATUS STDCALL diff --git a/reactos/drivers/video/videoprt/int10.c b/reactos/drivers/video/videoprt/int10.c index 2b65079d5ee..105a868f150 100644 --- a/reactos/drivers/video/videoprt/int10.c +++ b/reactos/drivers/video/videoprt/int10.c @@ -212,6 +212,11 @@ VideoPortInt10( DPRINT("VideoPortInt10\n"); + if (!CsrssInitialized) + { + return ERROR_INVALID_PARAMETER; + } + IntAttachToCSRSS(&CallingProcess, &PrevAttachedProcess); memset(&Regs, 0, sizeof(Regs)); diff --git a/reactos/drivers/video/videoprt/resource.c b/reactos/drivers/video/videoprt/resource.c index b6cd32a17a9..ece08ed857a 100644 --- a/reactos/drivers/video/videoprt/resource.c +++ b/reactos/drivers/video/videoprt/resource.c @@ -25,16 +25,68 @@ /* PRIVATE FUNCTIONS **********************************************************/ +NTSTATUS STDCALL +IntVideoPortMapPhysicalMemory( + IN HANDLE Process, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG SizeInBytes, + IN ULONG Protect, + IN OUT PVOID *VirtualAddress OPTIONAL) +{ + OBJECT_ATTRIBUTES ObjAttribs; + UNICODE_STRING UnicodeString; + HANDLE hMemObj; + NTSTATUS Status; + SIZE_T Size; + + /* Initialize object attribs */ + RtlInitUnicodeString(&UnicodeString, L"\\Device\\PhysicalMemory"); + InitializeObjectAttributes(&ObjAttribs, + &UnicodeString, + OBJ_CASE_INSENSITIVE/* | OBJ_KERNEL_HANDLE*/, + NULL, NULL); + + /* Open physical memory section */ + Status = ZwOpenSection(&hMemObj, SECTION_ALL_ACCESS, &ObjAttribs); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenSection() failed! (0x%x)\n", Status); + return Status; + } + + /* Map view of section */ + Size = SizeInBytes; + Status = ZwMapViewOfSection(hMemObj, + Process, + VirtualAddress, + 0, + Size, + (PLARGE_INTEGER)(&PhysicalAddress), + &Size, + ViewUnmap, + 0, + Protect); + ZwClose(hMemObj); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwMapViewOfSection() failed! (0x%x)\n", Status); + } + + return Status; +} + + PVOID STDCALL IntVideoPortMapMemory( IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension, IN PHYSICAL_ADDRESS IoAddress, IN ULONG NumberOfUchars, IN UCHAR InIoSpace, + IN HANDLE ProcessHandle, OUT VP_STATUS *Status) { PHYSICAL_ADDRESS TranslatedAddress; - PVIDEO_PORT_ADDRESS_MAPPING AddressMapping = NULL; + PVIDEO_PORT_ADDRESS_MAPPING AddressMapping; ULONG AddressSpace; PVOID MappedAddress; PLIST_ENTRY Entry; @@ -50,7 +102,25 @@ IntVideoPortMapMemory( InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE; } - if (!IsListEmpty(&DeviceExtension->AddressMappingListHead)) + if (ProcessHandle != NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0) + { + DPRINT("ProcessHandle is not NULL (0x%x) but InIoSpace does not have " + "VIDEO_MEMORY_SPACE_USER_MODE set! Setting " + "VIDEO_MEMORY_SPACE_USER_MODE.\n", + ProcessHandle); + InIoSpace |= VIDEO_MEMORY_SPACE_USER_MODE; + } + else if (ProcessHandle == NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0) + { + DPRINT("ProcessHandle is NULL (0x%x) but InIoSpace does have " + "VIDEO_MEMORY_SPACE_USER_MODE set! Setting ProcessHandle " + "to NtCurrentProcess()\n", + ProcessHandle); + ProcessHandle = NtCurrentProcess(); + } + + if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 && + !IsListEmpty(&DeviceExtension->AddressMappingListHead)) { Entry = DeviceExtension->AddressMappingListHead.Flink; while (Entry != &DeviceExtension->AddressMappingListHead) @@ -62,28 +132,15 @@ IntVideoPortMapMemory( if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart && NumberOfUchars <= AddressMapping->NumberOfUchars) { - if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0 && - AddressMapping->MappedUserAddress != NULL) - { - AddressMapping->UserMappingCount++; - if (Status) - *Status = NO_ERROR; - return AddressMapping->MappedUserAddress; - } - else if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 && - AddressMapping->MappedUserAddress != NULL) { AddressMapping->MappingCount++; if (Status) *Status = NO_ERROR; return AddressMapping->MappedAddress; } - break; } Entry = Entry->Flink; } - if (Entry == &DeviceExtension->AddressMappingListHead) - AddressMapping = NULL; } AddressSpace = (ULONG)InIoSpace; @@ -114,46 +171,20 @@ IntVideoPortMapMemory( /* user space */ if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0) { - OBJECT_ATTRIBUTES ObjAttribs; - UNICODE_STRING UnicodeString; - HANDLE hMemObj; NTSTATUS NtStatus; - SIZE_T Size; - - RtlInitUnicodeString(&UnicodeString, L"\\Device\\PhysicalMemory"); - InitializeObjectAttributes(&ObjAttribs, - &UnicodeString, - OBJ_CASE_INSENSITIVE/* | OBJ_KERNEL_HANDLE*/, - NULL, NULL); - NtStatus = ZwOpenSection(&hMemObj, SECTION_ALL_ACCESS, &ObjAttribs); - if (!NT_SUCCESS(NtStatus)) - { - DPRINT("ZwOpenSection() failed! (0x%x)\n", NtStatus); - if (Status) - *Status = NO_ERROR; - return NULL; - } - Size = NumberOfUchars; MappedAddress = NULL; - NtStatus = ZwMapViewOfSection(hMemObj, - NtCurrentProcess(), - &MappedAddress, - 0, - NumberOfUchars, - (PLARGE_INTEGER)(&TranslatedAddress), - &Size, - ViewUnmap, - 0, - PAGE_READWRITE/* | PAGE_WRITECOMBINE*/); + NtStatus = IntVideoPortMapPhysicalMemory(ProcessHandle, + TranslatedAddress, + NumberOfUchars, + PAGE_READWRITE/* | PAGE_WRITECOMBINE*/, + &MappedAddress); if (!NT_SUCCESS(NtStatus)) { - DPRINT("ZwMapViewOfSection() failed! (0x%x)\n", NtStatus); - ZwClose(hMemObj); + DPRINT("IntVideoPortMapPhysicalMemory() failed! (0x%x)\n", NtStatus); if (Status) *Status = NO_ERROR; return NULL; } - ZwClose(hMemObj); DPRINT("Mapped user address = 0x%08x\n", MappedAddress); } else /* kernel space */ @@ -166,13 +197,11 @@ IntVideoPortMapMemory( if (MappedAddress != NULL) { - BOOL InsertIntoList = FALSE; - if (Status) { *Status = NO_ERROR; } - if (AddressMapping == NULL) + if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0) { AddressMapping = ExAllocatePoolWithTag( PagedPool, @@ -182,26 +211,12 @@ IntVideoPortMapMemory( if (AddressMapping == NULL) return MappedAddress; - InsertIntoList = TRUE; RtlZeroMemory(AddressMapping, sizeof(VIDEO_PORT_ADDRESS_MAPPING)); AddressMapping->NumberOfUchars = NumberOfUchars; AddressMapping->IoAddress = IoAddress; AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber; - } - - if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0) - { - AddressMapping->MappedUserAddress = MappedAddress; - AddressMapping->UserMappingCount = 1; - } - else - { AddressMapping->MappedAddress = MappedAddress; AddressMapping->MappingCount = 1; - } - - if (InsertIntoList) - { InsertHeadList( &DeviceExtension->AddressMappingListHead, &AddressMapping->List); @@ -223,6 +238,7 @@ IntVideoPortUnmapMemory( { PVIDEO_PORT_ADDRESS_MAPPING AddressMapping; PLIST_ENTRY Entry; + NTSTATUS Status; Entry = DeviceExtension->AddressMappingListHead.Flink; while (Entry != &DeviceExtension->AddressMappingListHead) @@ -231,24 +247,7 @@ IntVideoPortUnmapMemory( Entry, VIDEO_PORT_ADDRESS_MAPPING, List); - if (AddressMapping->MappedUserAddress == MappedAddress) - { - ASSERT(AddressMapping->UserMappingCount > 0); - AddressMapping->UserMappingCount--; - if (AddressMapping->UserMappingCount == 0) - { - ZwUnmapViewOfSection(NtCurrentProcess(), - AddressMapping->MappedUserAddress); - AddressMapping->MappedUserAddress = NULL; - if (AddressMapping->MappingCount == 0) - { - RemoveEntryList(Entry); - ExFreePool(AddressMapping); - } - } - return; - } - else if (AddressMapping->MappedAddress == MappedAddress) + if (AddressMapping->MappedAddress == MappedAddress) { ASSERT(AddressMapping->MappingCount > 0); AddressMapping->MappingCount--; @@ -257,18 +256,25 @@ IntVideoPortUnmapMemory( MmUnmapIoSpace( AddressMapping->MappedAddress, AddressMapping->NumberOfUchars); - AddressMapping->MappedAddress = NULL; - if (AddressMapping->UserMappingCount == 0) - { - RemoveEntryList(Entry); - ExFreePool(AddressMapping); - } + RemoveEntryList(Entry); + ExFreePool(AddressMapping); } return; } Entry = Entry->Flink; } + + /* If there was no kernelmode mapping for the given address found we assume + * that the given address is a usermode mapping and try to unmap it. + * + * FIXME: Is it ok to use NtCurrentProcess? + */ + Status = ZwUnmapViewOfSection(NtCurrentProcess(), MappedAddress); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Warning: Mapping for address 0x%x not found!\n", (ULONG)MappedAddress); + } } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -290,6 +296,7 @@ VideoPortGetDeviceBase( IoAddress, NumberOfUchars, InIoSpace, + NULL, NULL); } @@ -346,6 +353,7 @@ VideoPortMapMemory( NTSTATUS Status; DPRINT("VideoPortMapMemory\n"); + DPRINT("- *VirtualAddress: 0x%x\n", *VirtualAddress); DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); *VirtualAddress = IntVideoPortMapMemory( @@ -353,6 +361,7 @@ VideoPortMapMemory( PhysicalAddress, *Length, *InIoSpace, + (HANDLE)*VirtualAddress, &Status); return Status; @@ -410,86 +419,93 @@ VideoPortGetAccessRanges( DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); - if (NumRequestedResources == 0 && - DeviceExtension->AdapterInterfaceType == PCIBus) + if (NumRequestedResources == 0) { - if (DeviceExtension->PhysicalDeviceObject != NULL) + AllocatedResources = DeviceExtension->AllocatedResources; + if (AllocatedResources == NULL && + DeviceExtension->AdapterInterfaceType == PCIBus) { - PciSlotNumber.u.AsULONG = DeviceExtension->SystemIoSlotNumber; - - ReturnedLength = HalGetBusData( - PCIConfiguration, - DeviceExtension->SystemIoBusNumber, - PciSlotNumber.u.AsULONG, - &Config, - sizeof(PCI_COMMON_CONFIG)); - - if (ReturnedLength != sizeof(PCI_COMMON_CONFIG)) + if (DeviceExtension->PhysicalDeviceObject != NULL) { - return ERROR_NO_SYSTEM_RESOURCES; - } - } - else - { - VendorIdToFind = VendorId != NULL ? *(PUSHORT)VendorId : 0; - DeviceIdToFind = DeviceId != NULL ? *(PUSHORT)DeviceId : 0; - SlotIdToFind = Slot != NULL ? *Slot : 0; - PciSlotNumber.u.AsULONG = SlotIdToFind; + PciSlotNumber.u.AsULONG = DeviceExtension->SystemIoSlotNumber; - DPRINT("Looking for VendorId 0x%04x DeviceId 0x%04x\n", - VendorIdToFind, DeviceIdToFind); - - /* - * Search for the device id and vendor id on this bus. - */ - - for (FunctionNumber = 0; FunctionNumber < 8; FunctionNumber++) - { - DPRINT("- Function number: %d\n", FunctionNumber); - PciSlotNumber.u.bits.FunctionNumber = FunctionNumber; ReturnedLength = HalGetBusData( - PCIConfiguration, + PCIConfiguration, DeviceExtension->SystemIoBusNumber, PciSlotNumber.u.AsULONG, &Config, sizeof(PCI_COMMON_CONFIG)); - DPRINT("- Length of data: %x\n", ReturnedLength); - if (ReturnedLength == sizeof(PCI_COMMON_CONFIG)) - { - DPRINT("- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x " - "DeviceId 0x%04x\n", - PciSlotNumber.u.AsULONG, - PciSlotNumber.u.bits.DeviceNumber, - PciSlotNumber.u.bits.FunctionNumber, - Config.VendorID, - Config.DeviceID); - if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) && - (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind)) + if (ReturnedLength != sizeof(PCI_COMMON_CONFIG)) + { + return ERROR_NO_SYSTEM_RESOURCES; + } + } + else + { + VendorIdToFind = VendorId != NULL ? *(PUSHORT)VendorId : 0; + DeviceIdToFind = DeviceId != NULL ? *(PUSHORT)DeviceId : 0; + SlotIdToFind = Slot != NULL ? *Slot : 0; + PciSlotNumber.u.AsULONG = SlotIdToFind; + + DPRINT("Looking for VendorId 0x%04x DeviceId 0x%04x\n", + VendorIdToFind, DeviceIdToFind); + + /* + * Search for the device id and vendor id on this bus. + */ + + for (FunctionNumber = 0; FunctionNumber < 8; FunctionNumber++) + { + DPRINT("- Function number: %d\n", FunctionNumber); + PciSlotNumber.u.bits.FunctionNumber = FunctionNumber; + ReturnedLength = HalGetBusData( + PCIConfiguration, + DeviceExtension->SystemIoBusNumber, + PciSlotNumber.u.AsULONG, + &Config, + sizeof(PCI_COMMON_CONFIG)); + DPRINT("- Length of data: %x\n", ReturnedLength); + if (ReturnedLength == sizeof(PCI_COMMON_CONFIG)) { - break; + DPRINT("- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x " + "DeviceId 0x%04x\n", + PciSlotNumber.u.AsULONG, + PciSlotNumber.u.bits.DeviceNumber, + PciSlotNumber.u.bits.FunctionNumber, + Config.VendorID, + Config.DeviceID); + + if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) && + (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind)) + { + break; + } } } + + if (FunctionNumber == 8) + { + DPRINT("Didn't find device.\n"); + return ERROR_DEV_NOT_EXIST; + } } - if (FunctionNumber == 8) + Status = HalAssignSlotResources( + NULL, NULL, NULL, NULL, + DeviceExtension->AdapterInterfaceType, + DeviceExtension->SystemIoBusNumber, + PciSlotNumber.u.AsULONG, + &AllocatedResources); + + if (!NT_SUCCESS(Status)) { - DPRINT("Didn't find device.\n"); - return ERROR_DEV_NOT_EXIST; + return Status; } + DeviceExtension->AllocatedResources = AllocatedResources; } - - Status = HalAssignSlotResources( - NULL, NULL, NULL, NULL, - DeviceExtension->AdapterInterfaceType, - DeviceExtension->SystemIoBusNumber, - PciSlotNumber.u.AsULONG, - &AllocatedResources); - - if (!NT_SUCCESS(Status)) - { - return Status; - } + if (AllocatedResources == NULL) + return ERROR_NO_SYSTEM_RESOURCES; AssignedCount = 0; for (FullList = AllocatedResources->List; @@ -509,7 +525,6 @@ VideoPortGetAccessRanges( AssignedCount >= NumAccessRanges) { DPRINT1("Too many access ranges found\n"); - ExFreePool(AllocatedResources); return ERROR_NO_SYSTEM_RESOURCES; } if (Descriptor->Type == CmResourceTypeMemory) @@ -517,7 +532,6 @@ VideoPortGetAccessRanges( if (NumAccessRanges <= AssignedCount) { DPRINT1("Too many access ranges found\n"); - ExFreePool(AllocatedResources); return ERROR_NO_SYSTEM_RESOURCES; } DPRINT("Memory range starting at 0x%08x length 0x%08x\n", @@ -548,7 +562,6 @@ VideoPortGetAccessRanges( } } } - ExFreePool(AllocatedResources); } else { diff --git a/reactos/drivers/video/videoprt/services.c b/reactos/drivers/video/videoprt/services.c index 379aacb65a9..c313649a514 100644 --- a/reactos/drivers/video/videoprt/services.c +++ b/reactos/drivers/video/videoprt/services.c @@ -41,6 +41,8 @@ VideoPortQueryServices( IN VIDEO_PORT_SERVICES ServicesType, IN OUT PINTERFACE Interface) { + DPRINT("VideoPortQueryServices - ServicesType: 0x%x\n", ServicesType); + switch (ServicesType) { case VideoPortServicesInt10: @@ -62,8 +64,22 @@ VideoPortQueryServices( break; case VideoPortServicesAGP: + if ((Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_2 && + Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE_2)) || + (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1 && + Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE))) + { + if (NT_SUCCESS(IntAgpGetInterface(HwDeviceExtension, Interface))) + { + return NO_ERROR; + } + } + break; + case VideoPortServicesI2C: case VideoPortServicesHeadless: + DPRINT1("VideoPortServices%s is UNIMPLEMENTED!\n", + (ServicesType == VideoPortServicesI2C) ? "I2C" : "Headless"); return ERROR_CALL_NOT_IMPLEMENTED; default: @@ -76,9 +92,24 @@ VideoPortQueryServices( BOOLEAN STDCALL VideoPortGetAgpServices( IN PVOID HwDeviceExtension, - IN PVIDEO_PORT_AGP_SERVICES AgpServices) + OUT PVIDEO_PORT_AGP_SERVICES AgpServices) { + VIDEO_PORT_AGP_INTERFACE Interface; + VP_STATUS Status; + DPRINT("VideoPortGetAgpServices\n"); - UNIMPLEMENTED; - return FALSE; + + Interface.Size = sizeof(Interface); + Interface.Version = VIDEO_PORT_AGP_INTERFACE_VERSION_1; + + Status = VideoPortQueryServices(HwDeviceExtension, VideoPortServicesAGP, + (PINTERFACE)&Interface); + if (Status != NO_ERROR) + { + DPRINT("VideoPortQueryServices() failed!\n"); + return FALSE; + } + + RtlCopyMemory(AgpServices, &Interface.AgpReservePhysical, sizeof(AgpServices)); + return TRUE; } diff --git a/reactos/drivers/video/videoprt/videoprt.c b/reactos/drivers/video/videoprt/videoprt.c index 7384b5bf956..19c69f06160 100644 --- a/reactos/drivers/video/videoprt/videoprt.c +++ b/reactos/drivers/video/videoprt/videoprt.c @@ -162,25 +162,22 @@ IntVideoPortAllocateDeviceNumber(VOID) } NTSTATUS STDCALL -IntVideoPortFindAdapter( +IntVideoPortCreateAdapterDeviceObject( IN PDRIVER_OBJECT DriverObject, IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, - IN PDEVICE_OBJECT PhysicalDeviceObject) + IN PDEVICE_OBJECT PhysicalDeviceObject, + OUT PDEVICE_OBJECT *DeviceObject OPTIONAL) { - WCHAR DeviceVideoBuffer[20]; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; ULONG DeviceNumber; ULONG Size; NTSTATUS Status; - VIDEO_PORT_CONFIG_INFO ConfigInfo; - SYSTEM_BASIC_INFORMATION SystemBasicInfo; - UCHAR Again = FALSE; WCHAR DeviceBuffer[20]; UNICODE_STRING DeviceName; - WCHAR SymlinkBuffer[20]; - UNICODE_STRING SymlinkName; - PDEVICE_OBJECT DeviceObject; - BOOL LegacyDetection = FALSE; + PDEVICE_OBJECT DeviceObject_; + + if (DeviceObject == NULL) + DeviceObject = &DeviceObject_; /* * Find the first free device number that can be used for video device @@ -195,7 +192,7 @@ IntVideoPortFindAdapter( } /* - * Create the device object, we need it even for calling HwFindAdapter :( + * Create the device object. */ /* Create a unicode device name. */ @@ -211,7 +208,7 @@ IntVideoPortFindAdapter( FILE_DEVICE_VIDEO, 0, TRUE, - &DeviceObject); + DeviceObject); if (!NT_SUCCESS(Status)) { @@ -219,38 +216,35 @@ IntVideoPortFindAdapter( return Status; } - /* + /* * Set the buffering strategy here. If you change this, remember * to change VidDispatchDeviceControl too. */ - DeviceObject->Flags |= DO_BUFFERED_IO; + (*DeviceObject)->Flags |= DO_BUFFERED_IO; /* * Initialize device extension. */ - DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension); + DeviceExtension->DeviceNumber = DeviceNumber; DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; - DeviceExtension->FunctionalDeviceObject = DeviceObject; + DeviceExtension->FunctionalDeviceObject = *DeviceObject; DeviceExtension->DriverExtension = DriverExtension; - DeviceExtension->RegistryPath.Length = - DeviceExtension->RegistryPath.MaximumLength = + DeviceExtension->RegistryPath.Length = + DeviceExtension->RegistryPath.MaximumLength = DriverExtension->RegistryPath.Length + (9 * sizeof(WCHAR)); DeviceExtension->RegistryPath.Length -= sizeof(WCHAR); DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag( NonPagedPool, DeviceExtension->RegistryPath.MaximumLength, - TAG_VIDEO_PORT); + TAG_VIDEO_PORT); swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0", DriverExtension->RegistryPath.Buffer); - if (PhysicalDeviceObject == NULL) - { - LegacyDetection = TRUE; - } - else + if (PhysicalDeviceObject != NULL) { /* Get bus number from the upper level bus driver. */ Size = sizeof(ULONG); @@ -266,11 +260,10 @@ IntVideoPortFindAdapter( "use legacy detection method, but even that doesn't mean that\n" "it will work.\n"); DeviceExtension->PhysicalDeviceObject = NULL; - LegacyDetection = TRUE; } } - DeviceExtension->AdapterInterfaceType = + DeviceExtension->AdapterInterfaceType = DriverExtension->InitializationData.AdapterInterfaceType; if (PhysicalDeviceObject != NULL) @@ -291,7 +284,7 @@ IntVideoPortFindAdapter( DevicePropertyAddress, Size, &DeviceExtension->SystemIoSlotNumber, - &Size); + &Size); } InitializeListHead(&DeviceExtension->AddressMappingListHead); @@ -300,9 +293,43 @@ IntVideoPortFindAdapter( IntVideoPortDeferredRoutine, DeviceExtension); + KeInitializeMutex(&DeviceExtension->DeviceLock, 0); + + /* Attach the device. */ + if (PhysicalDeviceObject != NULL) + DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack( + *DeviceObject, PhysicalDeviceObject); + + return STATUS_SUCCESS; +} + + +/* FIXME: we have to detach the device object in IntVideoPortFindAdapter if it fails */ +NTSTATUS STDCALL +IntVideoPortFindAdapter( + IN PDRIVER_OBJECT DriverObject, + IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, + IN PDEVICE_OBJECT DeviceObject) +{ + WCHAR DeviceVideoBuffer[20]; + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + ULONG Size; + NTSTATUS Status; + VIDEO_PORT_CONFIG_INFO ConfigInfo; + SYSTEM_BASIC_INFORMATION SystemBasicInfo; + UCHAR Again = FALSE; + WCHAR DeviceBuffer[20]; + UNICODE_STRING DeviceName; + WCHAR SymlinkBuffer[20]; + UNICODE_STRING SymlinkName; + BOOL LegacyDetection = FALSE; + ULONG DeviceNumber; + + DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + DeviceNumber = DeviceExtension->DeviceNumber; + /* - * Uff, the DeviceExtension is setup. Now it's needed to setup - * a ConfigInfo structure that we will pass to HwFindAdapter. + * Setup a ConfigInfo structure that we will pass to HwFindAdapter. */ RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO)); @@ -315,6 +342,8 @@ IntVideoPortFindAdapter( ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer; ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress; ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber; + ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel; + ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector; Size = sizeof(SystemBasicInfo); Status = ZwQuerySystemInformation( @@ -337,7 +366,11 @@ IntVideoPortFindAdapter( * when we don't have information about what bus we're on. The * second case is the standard one for Plug & Play drivers. */ - + if (DeviceExtension->PhysicalDeviceObject == NULL) + { + LegacyDetection = TRUE; + } + if (LegacyDetection) { ULONG BusNumber, MaxBuses; @@ -370,7 +403,7 @@ IntVideoPortFindAdapter( } else { - DPRINT("HwFindAdapter call failed with error %X\n", Status); + DPRINT("HwFindAdapter call failed with error 0x%X\n", Status); RtlFreeUnicodeString(&DeviceExtension->RegistryPath); IoDeleteDevice(DeviceObject); @@ -391,7 +424,7 @@ IntVideoPortFindAdapter( if (Status != NO_ERROR) { - DPRINT("HwFindAdapter call failed with error %X\n", Status); + DPRINT("HwFindAdapter call failed with error 0x%X\n", Status); RtlFreeUnicodeString(&DeviceExtension->RegistryPath); IoDeleteDevice(DeviceObject); return Status; @@ -402,6 +435,10 @@ IntVideoPortFindAdapter( * such as creating symlinks or setting up interrupts and timer. */ + /* Create a unicode device name. */ + swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber); + RtlInitUnicodeString(&DeviceName, DeviceBuffer); + /* Create symbolic link "\??\DISPLAYx" */ swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1); RtlInitUnicodeString(&SymlinkName, SymlinkBuffer); @@ -444,9 +481,10 @@ IntVideoPortFindAdapter( return STATUS_INSUFFICIENT_RESOURCES; } - if (PhysicalDeviceObject != NULL) - DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack( - DeviceObject, PhysicalDeviceObject); + /* + * Query children of the device. + */ + VideoPortEnumerateChildren(&DeviceExtension->MiniPortDeviceExtension, NULL); DPRINT("STATUS_SUCCESS\n"); return STATUS_SUCCESS; @@ -537,6 +575,13 @@ VideoPortInitialize( HwInitializationData, min(sizeof(VIDEO_HW_INITIALIZATION_DATA), HwInitializationData->HwInitDataSize)); + if (sizeof(VIDEO_HW_INITIALIZATION_DATA) > HwInitializationData->HwInitDataSize) + { + RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData + + HwInitializationData->HwInitDataSize), + sizeof(VIDEO_HW_INITIALIZATION_DATA) - + HwInitializationData->HwInitDataSize); + } DriverExtension->HwContext = HwContext; RtlCopyMemory(&DriverExtension->RegistryPath, RegistryPath, sizeof(UNICODE_STRING)); @@ -578,7 +623,13 @@ VideoPortInitialize( if (LegacyDetection) { - Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, NULL); + PDEVICE_OBJECT DeviceObject; + Status = IntVideoPortCreateAdapterDeviceObject(DriverObject, DriverExtension, + NULL, &DeviceObject); + DPRINT("IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status); + if (!NT_SUCCESS(Status)) + return Status; + Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject); DPRINT("IntVideoPortFindAdapter returned 0x%x\n", Status); return Status; } @@ -909,23 +960,7 @@ VideoPortSynchronizeExecution( } /* - * @unimplemented - */ - -BOOLEAN STDCALL -VideoPortDDCMonitorHelper( - PVOID HwDeviceExtension, - /*PI2C_FNC_TABLE*/PVOID I2CFunctions, - PUCHAR pEdidBuffer, - ULONG EdidBufferSize - ) -{ - DPRINT1("VideoPortDDCMonitorHelper() - Unimplemented.\n"); - return FALSE; -} - -/* - * @unimplemented + * @implemented */ VP_STATUS STDCALL @@ -933,7 +968,82 @@ VideoPortEnumerateChildren( IN PVOID HwDeviceExtension, IN PVOID Reserved) { - DPRINT1("VideoPortEnumerateChildren(): Unimplemented.\n"); + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + ULONG Status; + VIDEO_CHILD_ENUM_INFO ChildEnumInfo; + VIDEO_CHILD_TYPE ChildType; + UCHAR ChildDescriptor[256]; + ULONG ChildId; + ULONG Unused; + INT i; + + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL) + { + DPRINT("Miniport's HwGetVideoChildDescriptor is NULL!\n"); + return NO_ERROR; + } + + /* Setup the ChildEnumInfo */ + ChildEnumInfo.Size = sizeof (ChildEnumInfo); + ChildEnumInfo.ChildDescriptorSize = sizeof (ChildDescriptor); + ChildEnumInfo.ACPIHwId = 0; + ChildEnumInfo.ChildHwDeviceExtension = NULL; /* FIXME: must be set to + ChildHwDeviceExtension... */ + + /* Enumerate the children */ + for (i = 1; ; i++) + { + ChildEnumInfo.ChildIndex = i; + RtlZeroMemory(ChildDescriptor, sizeof(ChildDescriptor)); + Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor( + HwDeviceExtension, + &ChildEnumInfo, + &ChildType, + ChildDescriptor, + &ChildId, + &Unused); + if (Status == VIDEO_ENUM_INVALID_DEVICE) + { + DPRINT("Child device %d is invalid!\n", ChildEnumInfo.ChildIndex); + continue; + } + else if (Status == VIDEO_ENUM_NO_MORE_DEVICES) + { + DPRINT("End of child enumeration! (%d children enumerated)\n", i - 1); + break; + } + else if (Status != VIDEO_ENUM_MORE_DEVICES) + { + DPRINT("HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status); + break; + } + +#ifndef NDEBUG + if (ChildType == Monitor) + { + INT j; + PUCHAR p = ChildDescriptor; + DPRINT("Monitor device enumerated! (ChildId = 0x%x)\n", ChildId); + for (j = 0; j < sizeof (ChildDescriptor); j += 8) + { + DPRINT("%02x %02x %02x %02x %02x %02x %02x %02x\n", + p[j+0], p[j+1], p[j+2], p[j+3], + p[j+4], p[j+5], p[j+6], p[j+7]); + } + } + else if (ChildType == Other) + { + DPRINT("\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildDescriptor); + } + else + { + DPRINT("HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildType); + } +#endif /* NDEBUG */ + + } + return NO_ERROR; } @@ -1064,3 +1174,41 @@ VideoPortQueryPerformanceCounter( Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency); return Result.QuadPart; } + +/* + * @implemented + */ + +VOID STDCALL +VideoPortAcquireDeviceLock( + IN PVOID HwDeviceExtension) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + (void)Status; + + DPRINT("VideoPortAcquireDeviceLock\n"); + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + Status = KeWaitForMutexObject(&DeviceExtension->DeviceLock, Executive, + KernelMode, FALSE, NULL); + ASSERT(Status == STATUS_SUCCESS); +} + +/* + * @implemented + */ + +VOID STDCALL +VideoPortReleaseDeviceLock( + IN PVOID HwDeviceExtension) +{ + PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; + LONG Status; + (void)Status; + + DPRINT("VideoPortReleaseDeviceLock\n"); + DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); + Status = KeReleaseMutex(&DeviceExtension->DeviceLock, FALSE); + ASSERT(Status == 0); +} + diff --git a/reactos/drivers/video/videoprt/videoprt.def b/reactos/drivers/video/videoprt/videoprt.def index 832fac4d167..28f3e14619b 100644 --- a/reactos/drivers/video/videoprt/videoprt.def +++ b/reactos/drivers/video/videoprt/videoprt.def @@ -3,7 +3,7 @@ ; videoprt.def - export definition file for ReactOS ; EXPORTS -;VideoPortAcquireDeviceLock +VideoPortAcquireDeviceLock@4 VideoPortAcquireSpinLock@12 VideoPortAcquireSpinLockAtDpcLevel@8 VideoPortAllocateBuffer@12 @@ -80,7 +80,7 @@ VideoPortReadRegisterBufferUlong@12=NTOSKRNL.READ_REGISTER_BUFFER_ULONG VideoPortRegisterBugcheckCallback@16 VideoPortReleaseBuffer@8 VideoPortReleaseCommonBuffer@28 -;VideoPortReleaseDeviceLock +VideoPortReleaseDeviceLock@4 VideoPortReleaseSpinLock@12 VideoPortReleaseSpinLockFromDpcLevel@8 VideoPortScanRom@16 diff --git a/reactos/drivers/video/videoprt/videoprt.h b/reactos/drivers/video/videoprt/videoprt.h index 3412b95b2e3..f25ed08a8a6 100644 --- a/reactos/drivers/video/videoprt/videoprt.h +++ b/reactos/drivers/video/videoprt/videoprt.h @@ -28,6 +28,7 @@ #include #include #include +#include #define NDEBUG #include @@ -51,14 +52,28 @@ typedef struct _VIDEO_PORT_ADDRESS_MAPPING { LIST_ENTRY List; PVOID MappedAddress; - PVOID MappedUserAddress; ULONG NumberOfUchars; PHYSICAL_ADDRESS IoAddress; ULONG SystemIoBusNumber; UINT MappingCount; - UINT UserMappingCount; } VIDEO_PORT_ADDRESS_MAPPING, *PVIDEO_PORT_ADDRESS_MAPPING; +struct _VIDEO_PORT_AGP_VIRTUAL_MAPPING; + +typedef struct _VIDEO_PORT_AGP_MAPPING +{ + ULONG NumberOfPages; + PVOID MapHandle; + PHYSICAL_ADDRESS PhysicalAddress; +} VIDEO_PORT_AGP_MAPPING, *PVIDEO_PORT_AGP_MAPPING; + +typedef struct _VIDEO_PORT_AGP_VIRTUAL_MAPPING +{ + PVIDEO_PORT_AGP_MAPPING AgpMapping; + HANDLE ProcessHandle; + PVOID MappedAddress; +} VIDEO_PORT_AGP_VIRTUAL_MAPPING, *PVIDEO_PORT_AGP_VIRTUAL_MAPPING; + typedef struct _VIDEO_PORT_DRIVER_EXTENSION { VIDEO_HW_INITIALIZATION_DATA InitializationData; @@ -68,12 +83,14 @@ typedef struct _VIDEO_PORT_DRIVER_EXTENSION typedef struct _VIDEO_PORT_DEVICE_EXTENSTION { + ULONG DeviceNumber; PDEVICE_OBJECT PhysicalDeviceObject; PDEVICE_OBJECT FunctionalDeviceObject; PDEVICE_OBJECT NextDeviceObject; UNICODE_STRING RegistryPath; PKINTERRUPT InterruptObject; KSPIN_LOCK InterruptSpinLock; + PCM_RESOURCE_LIST AllocatedResources; ULONG InterruptVector; ULONG InterruptLevel; ULONG AdapterInterfaceType; @@ -83,6 +100,8 @@ typedef struct _VIDEO_PORT_DEVICE_EXTENSTION KDPC DpcObject; VIDEO_PORT_DRIVER_EXTENSION *DriverExtension; ULONG DeviceOpened; + AGP_BUS_INTERFACE_STANDARD AgpInterface; + KMUTEX DeviceLock; CHAR MiniPortDeviceExtension[1]; } VIDEO_PORT_DEVICE_EXTENSION, *PVIDEO_PORT_DEVICE_EXTENSION; @@ -92,6 +111,13 @@ typedef struct _VIDEO_PORT_DEVICE_EXTENSTION VIDEO_PORT_DEVICE_EXTENSION, \ MiniPortDeviceExtension) +/* agp.c */ + +NTSTATUS STDCALL +IntAgpGetInterface( + IN PVOID HwDeviceExtension, + IN OUT PINTERFACE Interface); + /* dispatch.c */ NTSTATUS STDCALL @@ -147,11 +173,26 @@ IntVideoPortSetupInterrupt( IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, IN PVIDEO_PORT_CONFIG_INFO ConfigInfo); +/* resource.c */ + +NTSTATUS STDCALL +IntVideoPortMapPhysicalMemory( + IN HANDLE Process, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG SizeInBytes, + IN ULONG Protect, + IN OUT PVOID *VirtualAddress OPTIONAL); + /* videoprt.c */ extern ULONG CsrssInitialized; extern PEPROCESS Csrss; +VP_STATUS STDCALL +VideoPortEnumerateChildren( + IN PVOID HwDeviceExtension, + IN PVOID Reserved); + PVOID STDCALL VideoPortGetProcAddress( IN PVOID HwDeviceExtension, @@ -163,11 +204,18 @@ IntAttachToCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess); VOID FASTCALL IntDetachFromCSRSS(PEPROCESS *CallingProcess, PEPROCESS *PrevAttachedProcess); +NTSTATUS STDCALL +IntVideoPortCreateAdapterDeviceObject( + IN PDRIVER_OBJECT DriverObject, + IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + OUT PDEVICE_OBJECT *DeviceObject OPTIONAL); + NTSTATUS STDCALL IntVideoPortFindAdapter( IN PDRIVER_OBJECT DriverObject, IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, - IN PDEVICE_OBJECT PhysicalDeviceObject); + IN PDEVICE_OBJECT DeviceObject); /* int10.c */ diff --git a/reactos/drivers/video/videoprt/videoprt.xml b/reactos/drivers/video/videoprt/videoprt.xml index 9fcc6cd9ba2..2870d89da8c 100644 --- a/reactos/drivers/video/videoprt/videoprt.xml +++ b/reactos/drivers/video/videoprt/videoprt.xml @@ -5,6 +5,8 @@ ntoskrnl hal + agp.c + ddc.c dispatch.c dma.c event.c diff --git a/reactos/hal/halx86/generic/adapter.c b/reactos/hal/halx86/generic/adapter.c index 6fb678392c2..5debe5d853c 100644 --- a/reactos/hal/halx86/generic/adapter.c +++ b/reactos/hal/halx86/generic/adapter.c @@ -479,18 +479,13 @@ IoMapTransfer ( { PHYSICAL_ADDRESS Address; KIRQL OldIrql; - UCHAR Mode; + ULONG LengthShift = 0; -#if defined(__GNUC__) - Address.QuadPart = 0ULL; -#else Address.QuadPart = 0; -#endif /* Isa System (slave) DMA? */ if (MapRegisterBase && !AdapterObject->MasterDevice) { - KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql); /* @@ -510,11 +505,8 @@ IoMapTransfer ( * -- Filip Navara, 19/07/2004 */ - /* Get the mode for easier coding */ - Mode = AdapterObject->AdapterMode; - /* if it is a write to the device, copy the caller buffer to the low buffer */ - if ((WriteToDevice) && !((PDMA_MODE)&Mode)->AutoInitialize) + if (WriteToDevice && !AdapterObject->AdapterMode.AutoInitialize) { memcpy(MapRegisterBase, (char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)), @@ -522,59 +514,73 @@ IoMapTransfer ( } /* Writer Adapter Mode, transfer type */ - ((PDMA_MODE)&Mode)->TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER); + AdapterObject->AdapterMode.TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER); - // program up the dma controller, and return - if (!((PDMA_MODE)&Mode)->AutoInitialize) { + /* program up the dma controller, and return */ + if (!AdapterObject->AdapterMode.AutoInitialize) { Address = MmGetPhysicalAddress( MapRegisterBase ); } else { Address = MmGetPhysicalAddress( CurrentVa ); } /* 16-bit DMA has a shifted length */ - if (AdapterObject->Width16Bits) *Length = (*Length >> 1); + if (AdapterObject->Width16Bits) { + LengthShift = 1; + } /* Make the Transfer */ if (AdapterObject->AdapterNumber == 1) { PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */ + /* Mask the Channel */ + WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK); + /* Reset Register */ WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0); /* Set the Mode */ - WRITE_PORT_UCHAR(&DmaControl1->Mode, (UCHAR)(Mode)); + WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterObject->AdapterModeByte); - /* Set the Page Register (apparently always 0 for us if I trust the previous comment) */ + /* Set the Page Register */ + WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16)); + + /* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); /* Set the Length */ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((*Length) - 1)); + (UCHAR)((*Length >> LengthShift) - 1)); WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((*Length) - 1) >> 8); + (UCHAR)(((*Length >> LengthShift) - 1) >> 8)); /* Unmask the Channel */ WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); } else { PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */ + /* Mask the Channel */ + WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK); + /* Reset Register */ WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0); /* Set the Mode */ - WRITE_PORT_UCHAR(&DmaControl2->Mode, (UCHAR)(Mode)); + WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterObject->AdapterModeByte); - /* Set the Page Register (apparently always 0 for us if I trust the previous comment) */ + /* Set the Page Register */ + WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16)); + + /* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0); /* Set the Length */ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((*Length) - 1)); + (UCHAR)((*Length >> LengthShift) - 1)); WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount, - (UCHAR)((*Length) - 1) >> 8); + (UCHAR)(((*Length >> LengthShift) - 1) >> 8)); /* Unmask the Channel */ WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK); diff --git a/reactos/hal/halx86/generic/dma.c b/reactos/hal/halx86/generic/dma.c index 02793ffcb79..d2b05075c4d 100644 --- a/reactos/hal/halx86/generic/dma.c +++ b/reactos/hal/halx86/generic/dma.c @@ -121,7 +121,8 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, DWORD ChannelSelect; DWORD Controller; ULONG MaximumLength; - BOOLEAN ChannelSetup; + BOOLEAN ChannelSetup = FALSE; + DMA_MODE DmaMode; DPRINT("Entered Function\n"); @@ -254,16 +255,20 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, switch (ChannelSelect) { case 0: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel0)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel0) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; case 1: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel1)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel1) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; case 2: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel2)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel2) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; case 3: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel3)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel3) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; } @@ -273,13 +278,16 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, switch (ChannelSelect) { case 1: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel5)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel5) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; case 2: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel6)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel6) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; case 3: - AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel7)); + AdapterObject->PagePort = (PUCHAR)(FIELD_OFFSET(DMA_PAGE, Channel7) + + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages)); break; } @@ -341,7 +349,8 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, *((PUCHAR)&ExtendedMode)); } } - /* Do 8/16-bit validation */ + + /* Do 8/16-bit validation */ DPRINT("Validating an Adapter Object\n"); if (!DeviceDescription->Master) { if ((DeviceDescription->DmaWidth == Width8Bits) && (Controller != 1)) { @@ -354,18 +363,19 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, } } } - UCHAR DmaMode; - DPRINT("Final DMA Request Mode Setting of the Adapter Object\n"); + + DPRINT("Final DMA Request Mode Setting of the Adapter Object\n"); + /* Set the DMA Request Modes */ if (DeviceDescription->Master) { /* This is a cascade request */ - ((PDMA_MODE)&DmaMode)->RequestMode = CASCADE_REQUEST_MODE; + DmaMode.RequestMode = CASCADE_REQUEST_MODE; /* Send the request */ if (AdapterObject->AdapterNumber == 1) { /* Set the Request Data */ WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->Mode, - AdapterObject->AdapterMode); + AdapterObject->AdapterModeByte); /* Unmask DMA Channel */ WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask, @@ -373,7 +383,7 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, } else { /* Set the Request Data */ WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->Mode, - AdapterObject->AdapterMode); + AdapterObject->AdapterModeByte); /* Unmask DMA Channel */ WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterObject->AdapterBaseVa)->SingleMask, @@ -381,14 +391,14 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, } } else if (DeviceDescription->DemandMode) { /* This is a Demand request */ - ((PDMA_MODE)&DmaMode)->RequestMode = DEMAND_REQUEST_MODE; + DmaMode.RequestMode = DEMAND_REQUEST_MODE; } else { /* Normal Request */ - ((PDMA_MODE)&DmaMode)->RequestMode = SINGLE_REQUEST_MODE; + DmaMode.RequestMode = SINGLE_REQUEST_MODE; } /* Auto Initialize Enabled or Not*/ - ((PDMA_MODE)&DmaMode)->AutoInitialize = DeviceDescription->AutoInitialize; + DmaMode.AutoInitialize = DeviceDescription->AutoInitialize; AdapterObject->AdapterMode = DmaMode; return AdapterObject; } diff --git a/reactos/hal/halx86/include/hal.h b/reactos/hal/halx86/include/hal.h index f63247ef768..dbd54385860 100644 --- a/reactos/hal/halx86/include/hal.h +++ b/reactos/hal/halx86/include/hal.h @@ -354,8 +354,11 @@ struct _ADAPTER_OBJECT { UCHAR ChannelNumber; UCHAR AdapterNumber; USHORT DmaPortAddress; - UCHAR AdapterMode; - BOOLEAN NeedsMapRegisters; + union { + DMA_MODE AdapterMode; + UCHAR AdapterModeByte; + }; + BOOLEAN NeedsMapRegisters; BOOLEAN MasterDevice; UCHAR Width16Bits; UCHAR ScatterGather; diff --git a/reactos/hal/halx86/include/halirq.h b/reactos/hal/halx86/include/halirq.h index 1965f8ee337..aa8e8ae5d5d 100644 --- a/reactos/hal/halx86/include/halirq.h +++ b/reactos/hal/halx86/include/halirq.h @@ -5,7 +5,7 @@ #ifndef __INCLUDE_HAL_HALIRQ #define __INCLUDE_HAL_HALIRQ -#ifdef MP +#ifdef CONFIG_SMP #define FIRST_DEVICE_VECTOR (0x30) #define FIRST_SYSTEM_VECTOR (0xef) diff --git a/reactos/hal/halx86/mp/Makefile b/reactos/hal/halx86/mp/Makefile index 11d3df2341e..837237dfa0a 100644 --- a/reactos/hal/halx86/mp/Makefile +++ b/reactos/hal/halx86/mp/Makefile @@ -22,14 +22,14 @@ TARGET_TYPE = hal TARGET_DEFNAME = ../../hal/hal -TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ -DMP +TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ -DCONFIG_SMP -TARGET_CFLAGS = -I../include -I$(PATH_TO_TOP)/ntoskrnl/include -Wall -Werror -DMP +TARGET_CFLAGS = -I../include -I$(PATH_TO_TOP)/ntoskrnl/include -Wall -Werror -DCONFIG_SMP # require os code to explicitly request A/W version of structs/functions TARGET_CFLAGS += -D_DISABLE_TIDENTS -ifneq ($(MP), 1) +ifneq ($(CONFIG_SMP), 1) TARGET_INSTALL = no else TARGET_BOOTSTRAP = yes diff --git a/reactos/hal/halx86/mp/apic.c b/reactos/hal/halx86/mp/apic.c index e1ae197727e..f87fe831e26 100644 --- a/reactos/hal/halx86/mp/apic.c +++ b/reactos/hal/halx86/mp/apic.c @@ -755,7 +755,7 @@ VOID MpsSpuriousHandler(VOID) { ULONG tmp; - DPRINT1("Spurious interrupt on CPU(%d)\n", ThisCPU()); + DPRINT("Spurious interrupt on CPU(%d)\n", ThisCPU()); tmp = APICRead(APIC_ISR + ((SPURIOUS_VECTOR & ~0x1f) >> 1)); if (tmp & (1 << (SPURIOUS_VECTOR & 0x1f))) diff --git a/reactos/hal/halx86/mp/mpsboot.asm b/reactos/hal/halx86/mp/mpsboot.asm index 684b69ab823..2683eaa301c 100644 --- a/reactos/hal/halx86/mp/mpsboot.asm +++ b/reactos/hal/halx86/mp/mpsboot.asm @@ -14,17 +14,15 @@ ; 0x3000 Startup code for the APs (this code) ; -; -; Base address of common area for BSP and APs -; -LOAD_BASE equ 00200000h - ; ; Magic value to be put in EAX when multiboot.S is called as part of the ; application processor initialization process ; AP_MAGIC equ 12481020h + +X86_CR4_PAE equ 00000020h + ; ; Segment selectors ; @@ -48,9 +46,22 @@ _APstart: mov eax, 3000h + APgdt - _APstart lgdt [eax] + + mov eax, [2004h] ; Set the page directory + mov cr3, eax + + mov eax, [200ch] + cmp eax,0 + je NoPae + + mov eax,cr4 + or eax,X86_CR4_PAE + mov cr4,eax + +NoPae: mov eax, cr0 - or eax, 00010001h ; Turn on protected mode and write protection + or eax, 80010001h ; Turn on protected mode, paging and write protection mov cr0, eax db 0eah @@ -72,9 +83,10 @@ flush: mov eax, [eax] mov esp, eax - ; Jump to start of the kernel with AP magic in eax - mov eax, AP_MAGIC - jmp dword KERNEL_CS:(LOAD_BASE + 0x1000) + ; Jump to start of the kernel with AP magic in ecx + mov ecx, AP_MAGIC + mov eax,[2008h] + jmp eax ; Never get here diff --git a/reactos/hal/halx86/mp/processor_mp.c b/reactos/hal/halx86/mp/processor_mp.c index 2526ca9cf8a..db82d9d8bc1 100644 --- a/reactos/hal/halx86/mp/processor_mp.c +++ b/reactos/hal/halx86/mp/processor_mp.c @@ -38,8 +38,11 @@ typedef struct __attribute__((packed)) _COMMON_AREA_INFO { - ULONG Stack; /* Location of AP stack */ - ULONG Debug[16]; /* For debugging */ + ULONG Stack; /* Location of AP stack */ + ULONG PageDirectory; /* Page directory for an AP */ + ULONG NtProcessStartup; /* Kernel entry point for an AP */ + ULONG PaeModeEnabled; /* PAE mode is enabled */ + ULONG Debug[16]; /* For debugging */ } COMMON_AREA_INFO, *PCOMMON_AREA_INFO; CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ @@ -81,6 +84,7 @@ extern VOID MpsIpiInterrupt(VOID); WRITE_PORT_UCHAR((PUCHAR)0x71, value); \ }) +extern PVOID IMPORTED MmSystemRangeStart; /* FUNCTIONS *****************************************************************/ @@ -1094,6 +1098,15 @@ HalStartNextProcessor(ULONG Unknown1, /* Write the location of the AP stack */ Common->Stack = (ULONG)ProcessorStack; + /* Write the page directory page */ + Ke386GetPageTableDirectory(Common->PageDirectory); + /* Write the kernel entry point */ + Common->NtProcessStartup = (ULONG_PTR)RtlImageNtHeader(MmSystemRangeStart)->OptionalHeader.AddressOfEntryPoint + (ULONG_PTR)MmSystemRangeStart; + /* Write the state of the mae mode */ + Common->PaeModeEnabled = Ke386GetCr4() & X86_CR4_PAE ? 1 : 0; + + DPRINT1("%x %x %x %x\n", Common->Stack, Common->PageDirectory, Common->NtProcessStartup, Common->PaeModeEnabled); + DPRINT("CPU %d got stack at 0x%X\n", CPU, Common->Stack); #if 0 @@ -1220,7 +1233,7 @@ ULONG MPChecksum(PUCHAR Base, PCHAR HaliMPFamily(ULONG Family, ULONG Model) { - static CHAR str[32]; + static CHAR str[64]; static PCHAR CPUs[] = { "80486DX", "80486DX", diff --git a/reactos/hal/halx86/up/Makefile b/reactos/hal/halx86/up/Makefile index 00f51f346cf..779f90643c5 100644 --- a/reactos/hal/halx86/up/Makefile +++ b/reactos/hal/halx86/up/Makefile @@ -24,14 +24,14 @@ TARGET_TYPE = hal TARGET_DEFNAME = ../../hal/hal -TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ -DUP +TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ -TARGET_CFLAGS = -I../include -I$(PATH_TO_TOP)/ntoskrnl/include -Wall -Werror -DUP +TARGET_CFLAGS = -I../include -I$(PATH_TO_TOP)/ntoskrnl/include -Wall -Werror # require os code to explicitly request A/W version of structs/functions TARGET_CFLAGS += -D_DISABLE_TIDENTS -ifeq ($(MP), 1) +ifeq ($(CONFIG_SMP), 1) TARGET_INSTALL = no else TARGET_BOOTSTRAP = yes diff --git a/reactos/iface/addsys/addsys.xml b/reactos/iface/addsys/addsys.xml deleted file mode 100644 index e46f6d23ead..00000000000 --- a/reactos/iface/addsys/addsys.xml +++ /dev/null @@ -1,14 +0,0 @@ - - . - genw32k.c - - - w32ksvc.db - - - ../../subsys/win32k/main/svctab.c - ../../lib/gdi32/misc/win32k.c - ../../lib/user32/misc/win32k.c - - - diff --git a/reactos/iface/addsys/genw32k.c b/reactos/iface/addsys/genw32k.c deleted file mode 100644 index 4b1838fa582..00000000000 --- a/reactos/iface/addsys/genw32k.c +++ /dev/null @@ -1,363 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS version of ntdll - * FILE: iface/native/genntdll.c - * PURPOSE: Generates the system call stubs in ntdll - * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] - * 19990616 (ea) - * Four arguments now required; 4th is the file - * for ntoskrnl ZwXXX functions (which are merely calls - * to twin NtXXX calls, via int 0x2e (x86). - * 19990617 (ea) - * Fixed a bug in function numbers in kernel ZwXXX stubs. - * - */ - -/* INCLUDE ******************************************************************/ - -#include -#include -#include - -#define PARAMETERIZED_LIBS - -#define INPUT_BUFFER_SIZE 255 - -#define INDEX 0x1000 /* SSDT index 1 */ - - -/* FUNCTIONS ****************************************************************/ - -void write_stub_header(FILE * out) -{ - fputs - ( - "/* Machine generated, don't edit */\n" - "\n" - "#ifdef __cplusplus\n" - "#define EXTERN_C extern \"C\"\n" - "#else\n" - "#define EXTERN_C\n" - "#endif\n" - "\n" - "EXTERN_C static __inline__ __attribute__((regparm(2)))" - "void*ZwRosSystemServiceThunk(long n,void*a)" - "{" - "void*ret;" - "__asm__" - "(" - "\"int $0x2E\":" - "\"=a\"(ret):" - "\"a\"(n),\"d\"(a)" - ");" - "return ret;" - "}\n", - out - ); -} - -void write_syscall_stub_func(FILE* out, char* name, unsigned nr_args, - unsigned int sys_call_idx) -{ - unsigned i; - - fprintf(out, "EXTERN_C void*__stdcall %s(", name); - - if(nr_args == 0) - fputs("void", out); - else - for(i = 0; i < nr_args; ++ i) - { - if(i > 0) - fputs(",", out); - - fprintf(out, "void*a%u", i); - } - - fputs("){", out); - - if(nr_args > 1) - for(i = 1; i < nr_args; ++ i) - fprintf(out, "(void)a%u;", i); - - fprintf(out, "return ZwRosSystemServiceThunk(%u,", sys_call_idx); - - if(nr_args == 0) - fputs("0", out); - else - fputs("&a0", out); - - fputs(");}\n", out); -} - -void write_syscall_stub(FILE* out1, FILE* out2, char* name, - unsigned nr_args, unsigned int sys_call_idx) -{ - write_syscall_stub_func(out1, name, nr_args, sys_call_idx); - write_syscall_stub_func(out2, name, nr_args, sys_call_idx); -} - -int makeSystemServiceTable(FILE *in, FILE *out) -{ -char line [INPUT_BUFFER_SIZE]; -char *s; -char *name; -int sys_call_idx; -char *snr_args; - - /* - * Main SSDT Header - */ - fprintf(out,"// Machine generated, don't edit\n"); - fprintf(out,"\n\n"); - - /* - * First we build the Win32k SSDT - */ - fprintf(out,"SSDT Win32kSSDT[] = {\n"); - - /* First system call has index zero */ - sys_call_idx = 0; - - /* Go on until EOF or read zero bytes */ - while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's name - * in the service table. - */ - fprintf(out,"\t\t(PVOID (NTAPI *)(VOID))%s",name); - - /* Next system call index */ - sys_call_idx++; - } - } - /* Close the service table (C syntax) */ - fprintf(out,"\n};\n"); - - /* - * Now we build the Win32k SSPT - */ - rewind(in); - fprintf(out,"\n\n"); - fprintf(out,"SSPT Win32kSSPT[] = {\n"); - - /* First system call has index zero */ - sys_call_idx = 0; - - /* Go on until EOF or read zero bytes */ - while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the stack size */ - snr_args = (char *)strtok(NULL," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx|INDEX,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's ID - * in the service table along with its Parameters Size. - */ - fprintf(out,"\t\t%lu * sizeof(void*)", strtoul(snr_args, NULL, 0)); - - /* Next system call index */ - sys_call_idx++; - } - } - /* - * Close the service table (C syntax) - */ - fprintf(out,"\n};\n"); - - /* - * We write some useful defines - */ - fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); - fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); - fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); - fprintf(out, "ULONG Win32kNumberOfSysCalls = %d;\n", sys_call_idx); - - return(0); -} - - -int -process( - FILE * in, - FILE * out1, - FILE * out2 - ) -{ - char line [INPUT_BUFFER_SIZE]; - char * s; - char * name; /* NtXXX name */ - int sys_call_idx; /* NtXXX index number in the service table */ - char * snr_args; /* stack_size / machine_word_size */ - - /* - * GDI32 stubs file header - */ - write_stub_header(out1); - - /* - * USER32 stubs file header - */ - write_stub_header(out2); - - /* - * Scan the database. DB is a text file; each line - * is a record, which contains data for one system - * function. Each record has three columns: - * - * NT_NAME (e.g. NtCreateProcess) - * ZW_NAME (e.g. ZwCreateProcess) - * STACK_SIZE (in machine words: for x[3456]86 - * processors a machine word is 4 bytes) - */ - - /* First system call has index zero */ - sys_call_idx = 0; - while ( - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ) - ) - { - /* - * Remove, if present, the trailing CR. - * (os specific?) - */ - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the stack size */ - snr_args = (char *)strtok(NULL," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); -#endif - - write_syscall_stub(out1, out2, name, strtoul(snr_args, NULL, 0), sys_call_idx | INDEX); - - /* Next system call index */ - sys_call_idx++; - } - } - - return(0); -} - -void usage(char * argv0) -{ - printf("Usage: %s w32ksvc.db w32k.lst ssdt.h win32k.c win32k.c\n" - " w32k.lst system functions database\n" - " ssdt.h WIN32K service table\n" - " win32k.c GDI32 stubs\n" - " win32k.c USER32 stubs\n" - " w32ksvc.db input file(system calls database)\n", - argv0 - ); -} - -int main(int argc, char* argv[]) -{ - FILE * in; /* System calls database */ - FILE * out1; /* SERVICE_TABLE */ - FILE * out2; /* GDI32 stubs */ - FILE * out3; /* USER32 stubs */ - int ret; - - if (argc != 5) - { - usage(argv[0]); - return(1); - } - - out1 = fopen(argv[1],"wb"); - if (out1 == NULL) - { - perror("Failed to open output file (WIN32K service table)"); - return(1); - } - - out2 = fopen(argv[2],"wb"); - if (out2 == NULL) - { - perror("Failed to open output file (GDI32 stubs)"); - return(1); - } - - out3 = fopen(argv[3],"wb"); - if (out3 == NULL) - { - perror("Failed to open output file (USER32 stubs)"); - return(1); - } - - in = fopen(argv[4],"rb"); - if (in == NULL) - { - perror("Failed to open input file (system calls database)"); - return(1); - } - - ret = process(in,out2,out3); - rewind(in); - ret = makeSystemServiceTable(in, out1); - - fclose(in); - fclose(out1); - fclose(out2); - fclose(out3); - - return(ret); -} diff --git a/reactos/iface/addsys/makefile b/reactos/iface/addsys/makefile deleted file mode 100644 index c7024e2dc85..00000000000 --- a/reactos/iface/addsys/makefile +++ /dev/null @@ -1,51 +0,0 @@ -# $Id$ -# -# ReactOS Operating System -# -# Generate files for a kernel module that needs to add a service table. -# -PATH_TO_TOP = ../.. - -#TARGETNAME = mktab -TARGETNAME = genw32k - -# WIN32K.SYS -SVC_DB=w32ksvc.db -SVC_MASK=0x1000 - -# DOS and Win32 kernels handle Unix paths too. -SVC_SERVICE_TABLE=../../subsys/win32k/main/svctab.c -SVC_GDI_STUBS=../../lib/gdi32/misc/win32k.c -SVC_USER_STUBS=../../lib/user32/misc/win32k.c - -SVC_FILES = $(SVC_GDI_STUBS) $(SVC_USER_STUBS) $(SVC_SERVICE_TABLE) - -CLEAN_FILES = $(TARGETNAME)$(EXE_POSTFIX) $(SVC_FILES) - -BASE_CFLAGS = -I../../include - -CFLAGS += -Wall -Werror - -all: $(SVC_FILES) - -$(TARGETNAME)$(EXE_POSTFIX): $(TARGETNAME).c - $(HOST_CC) \ - $(CFLAGS) \ - -o $(TARGETNAME) \ - -O2 \ - $(TARGETNAME).c - -$(SVC_FILES): $(SVC_DB) $(TARGETNAME)$(EXE_POSTFIX) - @./$(TARGETNAME)$(EXE_POSTFIX) \ - $(SVC_DB) \ - $(SVC_SERVICE_TABLE) \ - $(SVC_GDI_STUBS) \ - $(SVC_USER_STUBS) - - -clean: - - $(RM) $(CLEAN_FILES) - -.PHONY: all clean - -include ../../rules.mak diff --git a/reactos/iface/native/genntdll.c b/reactos/iface/native/genntdll.c deleted file mode 100644 index c82860f08fe..00000000000 --- a/reactos/iface/native/genntdll.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS version of ntdll - * FILE: iface/native/genntdll.c - * PURPOSE: Generates the system call stubs in ntdll - * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] - * 19990616 (ea) - * Four arguments now required; 4th is the file - * for ntoskrnl ZwXXX functions (which are merely calls - * to twin NtXXX calls, via int 0x2e (x86). - * 19990617 (ea) - * Fixed a bug in function numbers in kernel ZwXXX stubs. - * 20040406 (kjkh) - * The sysfuncs.lst file now specifies the number of parameters, - * not their stack size, for obvious portability reastons. Also, we - * now generate real C functions to let the compiler do the correct - * name decoration and whatever else (this also makes this tool - * marginally more portable). - * - */ - -/* INCLUDE ******************************************************************/ - -#include -#include -#include - -#define PARAMETERIZED_LIBS - -/* #define VERBOSE */ - -#define INPUT_BUFFER_SIZE 255 - -/* FUNCTIONS ****************************************************************/ - -void write_stub_header(FILE * out) -{ - fputs - ( - "/* Machine generated, don't edit */\n" - "\n" - "#ifdef __cplusplus\n" - "#define EXTERN_C extern \"C\"\n" - "#else\n" - "#define EXTERN_C\n" - "#endif\n" - "\n" - "EXTERN_C static __inline__ __attribute__((regparm(2)))" - "void*ZwRosSystemServiceThunk(long n,void*a)" - "{" - "void*ret;" - "__asm__" - "(" - "\"int $0x2E\":" - "\"=a\"(ret):" - "\"a\"(n),\"d\"(a)" - ");" - "return ret;" - "}\n", - out - ); -} - -void write_syscall_stub_func(FILE* out, char* name, unsigned nr_args, - unsigned int sys_call_idx) -{ - unsigned i; - - fprintf(out, "EXTERN_C void*__stdcall %s(", name); - - if(nr_args == 0) - fputs("void", out); - else - for(i = 0; i < nr_args; ++ i) - { - if(i > 0) - fputs(",", out); - - fprintf(out, "void*a%u", i); - } - - fputs("){", out); - - if(nr_args > 1) - for(i = 1; i < nr_args; ++ i) - fprintf(out, "(void)a%u;", i); - - fprintf(out, "return ZwRosSystemServiceThunk(%u,", sys_call_idx); - - if(nr_args == 0) - fputs("0", out); - else - fputs("&a0", out); - - fputs(");}\n", out); -} - -void write_syscall_stub(FILE* out, FILE* out3, char* name, char* name2, - unsigned nr_args, unsigned int sys_call_idx) -{ - write_syscall_stub_func(out, name, nr_args, sys_call_idx); - write_syscall_stub_func(out, name2, nr_args, sys_call_idx); - - /* - * Now write the NTOSKRNL stub for the - * current system call. ZwXXX does NOT - * alias the corresponding NtXXX call. - */ - write_syscall_stub_func(out3, name2, nr_args, sys_call_idx); -} - -int makeSystemServiceTable(FILE *in, FILE *out) -{ -char line [INPUT_BUFFER_SIZE]; -char *s; -char *name; -char *name2; -int sys_call_idx; -char *snr_args; -char *stmp; - - /* - * Main SSDT Header - */ - fprintf(out,"/* Machine generated, don't edit */\n"); - fprintf(out,"\n\n"); - - /* - * First we build the Main SSDT - */ - fprintf(out,"\n\n\n"); - fprintf(out,"SSDT MainSSDT[] = {\n"); - - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); - /* - * Remove, if present, the trailing LF. - */ - if ((stmp = strchr(snr_args, '\n')) != NULL) - { - *stmp = '\0'; - } -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's name - * in the service table. - */ - fprintf(out,"\t\t(PVOID (NTAPI *)(VOID))%s",name); - } - } - /* Close the service table (C syntax) */ - fprintf(out,"\n};\n"); - - /* - * Now we build the Main SSPT - */ - rewind(in); - fprintf(out,"\n\n\n"); - fprintf(out,"SSPT MainSSPT[] = {\n"); - - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's ID - * in the service table along with its Parameters Size. - */ - fprintf(out,"\t\t%lu * sizeof(void *)",strtoul(snr_args, NULL, 0)); - } - } - /* - * Close the service table (C syntax) - */ - fprintf(out,"\n};\n"); - - /* - * We write some useful defines - */ - fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); - fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); - fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); - - return(0); -} - - -int -process( - FILE * in, - FILE * out, - FILE * out2, - FILE * out3 - ) -{ - char line [INPUT_BUFFER_SIZE]; - char * s; - char * name; /* NtXXX name */ - char * name2; /* ZwXXX name */ - int sys_call_idx; /* NtXXX index number in the service table */ - char * snr_args; /* stack_size / machine_word_size */ - - /* - * NTDLL stubs file header - */ - write_stub_header(out); - - /* - * NTOSKRNL Zw functions stubs header - */ - write_stub_header(out3); - - /* - * Scan the database. DB is a text file; each line - * is a record, which contains data for one system - * function. Each record has three columns: - * - * NT_NAME (e.g. NtCreateProcess) - * ZW_NAME (e.g. ZwCreateProcess) - * STACK_SIZE (in machine words: for x[3456]86 - * processors a machine word is 4 bytes) - */ - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - /* - * Remove, if present, the trailing CR. - * (os specific?) - */ - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - unsigned nr_args; - - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); - nr_args = strtoul(snr_args, NULL, 0); -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - /* - * Write the NTDLL stub for the current - * system call: NtXXX and ZwXXX symbols - * are aliases. - */ - write_syscall_stub(out, out3, name, name2, - nr_args, sys_call_idx); - } - } - - return(0); -} - -void usage(char * argv0) -{ - printf("Usage: %s sysfuncs.lst napi.c napi.h zw.c\n" - " sysfuncs.lst system functions database\n" - " napi.c NTDLL stubs\n" - " napi.h NTOSKRNL service table\n" - " zw.c NTOSKRNL Zw stubs\n", - argv0 - ); -} - -int main(int argc, char* argv[]) -{ - FILE * in; /* System calls database */ - FILE * out1; /* NTDLL stubs */ - FILE * out2; /* SERVICE_TABLE */ - FILE * out3; /* NTOSKRNL Zw stubs */ - int ret; - - if (argc != 5) - { - usage(argv[0]); - return(1); - } - - out1 = fopen(argv[1],"wb"); - if (out1 == NULL) - { - perror("Failed to open output file (NTDLL stubs)"); - return(1); - } - - out2 = fopen(argv[2],"wb"); - if (out2 == NULL) - { - perror("Failed to open output file (NTOSKRNL service table)"); - return(1); - } - - out3 = fopen(argv[3],"wb"); - if (out3 == NULL) - { - perror("Failed to open output file (NTOSKRNL Zw stubs)"); - return(1); - } - - in = fopen(argv[4],"rb"); - if (in == NULL) - { - perror("Failed to open input file (system calls database)"); - return(1); - } - - ret = process(in,out1,out2,out3); - rewind(in); - ret = makeSystemServiceTable(in, out2); - - fclose(in); - fclose(out1); - fclose(out2); - fclose(out3); - - return(ret); -} diff --git a/reactos/iface/native/genntdll.xml b/reactos/iface/native/genntdll.xml deleted file mode 100644 index 2b4aa5f6dbd..00000000000 --- a/reactos/iface/native/genntdll.xml +++ /dev/null @@ -1,14 +0,0 @@ - - . - genntdll.c - - - sysfuncs.lst - - - ../../lib/ntdll/napi.c - ../../include/ntdll/napi.h - ../../ntoskrnl/nt/zw.c - - - diff --git a/reactos/iface/native/makefile b/reactos/iface/native/makefile deleted file mode 100644 index b64374ddd81..00000000000 --- a/reactos/iface/native/makefile +++ /dev/null @@ -1,40 +0,0 @@ -# $Id$ -# -# ReactOS Operating System -# -# Generate: -# - genntdll -# - ntoskrnl.exe service table; -# - ntoskrnl.exe Zw functions stubs to call Nt functions from kernel mode; -# - ntdll.dll stubs to call system functions from user mode applications. -# -PATH_TO_TOP = ../.. - -TARGET = genntdll -SYSTEM_CALLS_DB = sysfuncs.lst -NTDLL_STUBS = ../../lib/ntdll/napi.c -KERNEL_SERVICE_TABLE = ../../include/ntdll/napi.h -KERNEL_ZW_CALLS = ../../ntoskrnl/nt/zw.c -NAPI_FILES = $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) - -BASE_CFLAGS = -I../../include - -all: $(TARGET)$(EXE_POSTFIX) $(NAPI_FILES) - -$(NAPI_FILES): $(SYSTEM_CALLS_DB) $(TARGET)$(EXE_POSTFIX) - @./$(TARGET)$(EXE_POSTFIX) \ - $(SYSTEM_CALLS_DB) \ - $(NTDLL_STUBS) \ - $(KERNEL_SERVICE_TABLE) \ - $(KERNEL_ZW_CALLS) - -# (rjj) i removed the following option from line below: -If:\gnu\mingw32\include -$(TARGET)$(EXE_POSTFIX): $(TARGET).c - $(HOST_CC) -g -Wall -Werror $(TARGET).c -o $(TARGET)$(EXE_POSTFIX) - -clean: - - $(RM) $(TARGET)$(EXE_POSTFIX) $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) - -.PHONY: all clean - -include ../../rules.mak diff --git a/reactos/iface/native/sysfuncs.lst b/reactos/iface/native/sysfuncs.lst deleted file mode 100644 index 2d512ef5874..00000000000 --- a/reactos/iface/native/sysfuncs.lst +++ /dev/null @@ -1,241 +0,0 @@ -NtAcceptConnectPort ZwAcceptConnectPort 6 -NtAccessCheck ZwAccessCheck 8 -NtAccessCheckAndAuditAlarm ZwAccessCheckAndAuditAlarm 11 -NtAddAtom ZwAddAtom 3 -NtAddBootEntry ZwAddBootEntry 2 -NtAdjustGroupsToken ZwAdjustGroupsToken 6 -NtAdjustPrivilegesToken ZwAdjustPrivilegesToken 6 -NtAlertResumeThread ZwAlertResumeThread 2 -NtAlertThread ZwAlertThread 1 -NtAllocateLocallyUniqueId ZwAllocateLocallyUniqueId 1 -NtAllocateUuids ZwAllocateUuids 4 -NtAllocateVirtualMemory ZwAllocateVirtualMemory 6 -NtAssignProcessToJobObject ZwAssignProcessToJobObject 2 -NtCallbackReturn ZwCallbackReturn 3 -NtCancelIoFile ZwCancelIoFile 2 -NtCancelTimer ZwCancelTimer 2 -NtClearEvent ZwClearEvent 1 -NtClose ZwClose 1 -NtCloseObjectAuditAlarm ZwCloseObjectAuditAlarm 3 -NtCompleteConnectPort ZwCompleteConnectPort 1 -NtConnectPort ZwConnectPort 8 -NtContinue ZwContinue 2 -NtCreateDirectoryObject ZwCreateDirectoryObject 3 -NtCreateEvent ZwCreateEvent 5 -NtCreateEventPair ZwCreateEventPair 3 -NtCreateFile ZwCreateFile 11 -NtCreateIoCompletion ZwCreateIoCompletion 4 -NtCreateJobObject ZwCreateJobObject 3 -NtCreateKey ZwCreateKey 7 -NtCreateMailslotFile ZwCreateMailslotFile 8 -NtCreateMutant ZwCreateMutant 4 -NtCreateNamedPipeFile ZwCreateNamedPipeFile 14 -NtCreatePagingFile ZwCreatePagingFile 4 -NtCreatePort ZwCreatePort 5 -NtCreateProcess ZwCreateProcess 8 -NtCreateProfile ZwCreateProfile 9 -NtCreateSection ZwCreateSection 7 -NtCreateSemaphore ZwCreateSemaphore 5 -NtCreateSymbolicLinkObject ZwCreateSymbolicLinkObject 4 -NtCreateThread ZwCreateThread 8 -NtCreateTimer ZwCreateTimer 4 -NtCreateToken ZwCreateToken 13 -NtCreateWaitablePort ZwCreateWaitablePort 5 -NtDelayExecution ZwDelayExecution 2 -NtDeleteAtom ZwDeleteAtom 1 -NtDeleteBootEntry ZwDeleteBootEntry 2 -NtDeleteFile ZwDeleteFile 1 -NtDeleteKey ZwDeleteKey 1 -NtDeleteObjectAuditAlarm ZwDeleteObjectAuditAlarm 3 -NtDeleteValueKey ZwDeleteValueKey 2 -NtDeviceIoControlFile ZwDeviceIoControlFile 10 -NtDisplayString ZwDisplayString 1 -NtDuplicateObject ZwDuplicateObject 7 -NtDuplicateToken ZwDuplicateToken 6 -NtEnumerateBootEntries ZwEnumerateBootEntries 2 -NtEnumerateKey ZwEnumerateKey 6 -NtEnumerateValueKey ZwEnumerateValueKey 6 -NtExtendSection ZwExtendSection 2 -NtFindAtom ZwFindAtom 3 -NtFlushBuffersFile ZwFlushBuffersFile 2 -NtFlushInstructionCache ZwFlushInstructionCache 3 -NtFlushKey ZwFlushKey 1 -NtFlushVirtualMemory ZwFlushVirtualMemory 4 -NtFlushWriteBuffer ZwFlushWriteBuffer 0 -NtFreeVirtualMemory ZwFreeVirtualMemory 4 -NtFsControlFile ZwFsControlFile 10 -NtGetContextThread ZwGetContextThread 2 -NtGetPlugPlayEvent ZwGetPlugPlayEvent 4 -NtGetTickCount ZwGetTickCount 0 -NtImpersonateClientOfPort ZwImpersonateClientOfPort 2 -NtImpersonateThread ZwImpersonateThread 3 -NtInitializeRegistry ZwInitializeRegistry 1 -NtInitiatePowerAction ZwInitiatePowerAction 4 -NtIsProcessInJob ZwIsProcessInJob 2 -NtListenPort ZwListenPort 2 -NtLoadDriver ZwLoadDriver 1 -NtLoadKey ZwLoadKey 2 -NtLoadKey2 ZwLoadKey2 3 -NtLockFile ZwLockFile 10 -NtLockVirtualMemory ZwLockVirtualMemory 4 -NtMakePermanentObject ZwMakePermanentObject 1 -NtMakeTemporaryObject ZwMakeTemporaryObject 1 -NtMapViewOfSection ZwMapViewOfSection 10 -NtNotifyChangeDirectoryFile ZwNotifyChangeDirectoryFile 9 -NtNotifyChangeKey ZwNotifyChangeKey 10 -NtOpenDirectoryObject ZwOpenDirectoryObject 3 -NtOpenEvent ZwOpenEvent 3 -NtOpenEventPair ZwOpenEventPair 3 -NtOpenFile ZwOpenFile 6 -NtOpenIoCompletion ZwOpenIoCompletion 3 -NtOpenJobObject ZwOpenJobObject 3 -NtOpenKey ZwOpenKey 3 -NtOpenMutant ZwOpenMutant 3 -NtOpenObjectAuditAlarm ZwOpenObjectAuditAlarm 12 -NtOpenProcess ZwOpenProcess 4 -NtOpenProcessToken ZwOpenProcessToken 3 -NtOpenProcessTokenEx ZwOpenProcessTokenEx 4 -NtOpenSection ZwOpenSection 3 -NtOpenSemaphore ZwOpenSemaphore 3 -NtOpenSymbolicLinkObject ZwOpenSymbolicLinkObject 3 -NtOpenThread ZwOpenThread 4 -NtOpenThreadToken ZwOpenThreadToken 4 -NtOpenThreadTokenEx ZwOpenThreadTokenEx 5 -NtOpenTimer ZwOpenTimer 3 -NtPlugPlayControl ZwPlugPlayControl 4 -NtPowerInformation ZwPowerInformation 5 -NtPrivilegeCheck ZwPrivilegeCheck 3 -NtPrivilegedServiceAuditAlarm ZwPrivilegedServiceAuditAlarm 5 -NtPrivilegeObjectAuditAlarm ZwPrivilegeObjectAuditAlarm 6 -NtProtectVirtualMemory ZwProtectVirtualMemory 5 -NtPulseEvent ZwPulseEvent 2 -NtQueryInformationAtom ZwQueryInformationAtom 5 -NtQueryAttributesFile ZwQueryAttributesFile 2 -NtQueryBootEntryOrder ZwQueryBootEntryOrder 2 -NtQueryBootOptions ZwQueryBootOptions 2 -NtQueryDefaultLocale ZwQueryDefaultLocale 2 -NtQueryDefaultUILanguage ZwQueryDefaultUILanguage 1 -NtQueryDirectoryFile ZwQueryDirectoryFile 11 -NtQueryDirectoryObject ZwQueryDirectoryObject 7 -NtQueryEaFile ZwQueryEaFile 9 -NtQueryEvent ZwQueryEvent 5 -NtQueryFullAttributesFile ZwQueryFullAttributesFile 2 -NtQueryInformationFile ZwQueryInformationFile 5 -NtQueryInformationJobObject ZwQueryInformationJobObject 5 -NtQueryInformationPort ZwQueryInformationPort 5 -NtQueryInformationProcess ZwQueryInformationProcess 5 -NtQueryInformationThread ZwQueryInformationThread 5 -NtQueryInformationToken ZwQueryInformationToken 5 -NtQueryInstallUILanguage ZwQueryInstallUILanguage 1 -NtQueryIntervalProfile ZwQueryIntervalProfile 2 -NtQueryIoCompletion ZwQueryIoCompletion 5 -NtQueryKey ZwQueryKey 5 -NtQueryMultipleValueKey ZwQueryMultipleValueKey 6 -NtQueryMutant ZwQueryMutant 5 -NtQueryObject ZwQueryObject 5 -NtQueryOleDirectoryFile ZwQueryOleDirectoryFile 11 -NtQueryPerformanceCounter ZwQueryPerformanceCounter 2 -NtQueryQuotaInformationFile ZwQueryQuotaInformationFile 9 -NtQuerySection ZwQuerySection 5 -NtQuerySecurityObject ZwQuerySecurityObject 5 -NtQuerySemaphore ZwQuerySemaphore 5 -NtQuerySymbolicLinkObject ZwQuerySymbolicLinkObject 3 -NtQuerySystemEnvironmentValue ZwQuerySystemEnvironmentValue 4 -NtQuerySystemInformation ZwQuerySystemInformation 4 -NtQuerySystemTime ZwQuerySystemTime 1 -NtQueryTimer ZwQueryTimer 5 -NtQueryTimerResolution ZwQueryTimerResolution 3 -NtQueryValueKey ZwQueryValueKey 6 -NtQueryVirtualMemory ZwQueryVirtualMemory 6 -NtQueryVolumeInformationFile ZwQueryVolumeInformationFile 5 -NtQueueApcThread ZwQueueApcThread 5 -NtRaiseException ZwRaiseException 3 -NtRaiseHardError ZwRaiseHardError 6 -NtReadFile ZwReadFile 9 -NtReadFileScatter ZwReadFileScatter 9 -NtReadRequestData ZwReadRequestData 6 -NtReadVirtualMemory ZwReadVirtualMemory 5 -NtRegisterThreadTerminatePort ZwRegisterThreadTerminatePort 1 -NtReleaseMutant ZwReleaseMutant 2 -NtReleaseSemaphore ZwReleaseSemaphore 3 -NtRemoveIoCompletion ZwRemoveIoCompletion 5 -NtReplaceKey ZwReplaceKey 3 -NtReplyPort ZwReplyPort 2 -NtReplyWaitReceivePort ZwReplyWaitReceivePort 4 -NtReplyWaitReplyPort ZwReplyWaitReplyPort 2 -NtRequestPort ZwRequestPort 2 -NtRequestWaitReplyPort ZwRequestWaitReplyPort 3 -NtResetEvent ZwResetEvent 2 -NtRestoreKey ZwRestoreKey 3 -NtResumeThread ZwResumeThread 2 -NtSaveKey ZwSaveKey 2 -NtSaveKeyEx ZwSaveKeyEx 3 -NtSetBootEntryOrder ZwSetBootEntryOrder 2 -NtSetBootOptions ZwSetBootOptions 2 -NtSetIoCompletion ZwSetIoCompletion 5 -NtSetContextThread ZwSetContextThread 2 -NtSetDefaultHardErrorPort ZwSetDefaultHardErrorPort 1 -NtSetDefaultLocale ZwSetDefaultLocale 2 -NtSetDefaultUILanguage ZwSetDefaultUILanguage 1 -NtSetEaFile ZwSetEaFile 4 -NtSetEvent ZwSetEvent 2 -NtSetHighEventPair ZwSetHighEventPair 1 -NtSetHighWaitLowEventPair ZwSetHighWaitLowEventPair 1 -NtSetHighWaitLowThread ZwSetHighWaitLowThread 0 -NtSetInformationFile ZwSetInformationFile 5 -NtSetInformationKey ZwSetInformationKey 4 -NtSetInformationJobObject ZwSetInformationJobObject 4 -NtSetInformationObject ZwSetInformationObject 4 -NtSetInformationProcess ZwSetInformationProcess 4 -NtSetInformationThread ZwSetInformationThread 4 -NtSetInformationToken ZwSetInformationToken 4 -NtSetIntervalProfile ZwSetIntervalProfile 2 -NtSetLdtEntries ZwSetLdtEntries 6 -NtSetLowEventPair ZwSetLowEventPair 1 -NtSetLowWaitHighEventPair ZwSetLowWaitHighEventPair 1 -NtSetLowWaitHighThread ZwSetLowWaitHighThread 0 -NtSetQuotaInformationFile ZwSetQuotaInformationFile 4 -NtSetSecurityObject ZwSetSecurityObject 3 -NtSetSystemEnvironmentValue ZwSetSystemEnvironmentValue 2 -NtSetSystemInformation ZwSetSystemInformation 3 -NtSetSystemPowerState ZwSetSystemPowerState 3 -NtSetSystemTime ZwSetSystemTime 2 -NtSetTimer ZwSetTimer 7 -NtSetTimerResolution ZwSetTimerResolution 3 -NtSetUuidSeed ZwSetUuidSeed 1 -NtSetValueKey ZwSetValueKey 6 -NtSetVolumeInformationFile ZwSetVolumeInformationFile 5 -NtShutdownSystem ZwShutdownSystem 1 -NtSignalAndWaitForSingleObject ZwSignalAndWaitForSingleObject 4 -NtStartProfile ZwStartProfile 1 -NtStopProfile ZwStopProfile 1 -NtSuspendThread ZwSuspendThread 2 -NtSystemDebugControl ZwSystemDebugControl 6 -NtTerminateJobObject ZwTerminateJobObject 2 -NtTerminateProcess ZwTerminateProcess 2 -NtTerminateThread ZwTerminateThread 2 -NtTestAlert ZwTestAlert 0 -NtTraceEvent ZwTraceEvent 4 -NtTranslateFilePath ZwTranslateFilePath 3 -NtUnloadDriver ZwUnloadDriver 1 -NtUnloadKey ZwUnloadKey 1 -NtUnlockFile ZwUnlockFile 5 -NtUnlockVirtualMemory ZwUnlockVirtualMemory 4 -NtUnmapViewOfSection ZwUnmapViewOfSection 2 -NtVdmControl ZwVdmControl 2 -NtWaitForMultipleObjects ZwWaitForMultipleObjects 5 -NtWaitForSingleObject ZwWaitForSingleObject 3 -NtWaitHighEventPair ZwWaitHighEventPair 1 -NtWaitLowEventPair ZwWaitLowEventPair 1 -NtWriteFile ZwWriteFile 9 -NtWriteFileGather ZwWriteFileGather 9 -NtWriteRequestData ZwWriteRequestData 6 -NtWriteVirtualMemory ZwWriteVirtualMemory 5 -NtW32Call ZwW32Call 5 -NtCreateChannel ZwCreateChannel 2 -NtListenChannel ZwListenChannel 2 -NtOpenChannel ZwOpenChannel 2 -NtReplyWaitSendChannel ZwReplyWaitSendChannel 3 -NtSendWaitReplyChannel ZwSendWaitReplyChannel 4 -NtSetContextChannel ZwSetContextChannel 1 -NtYieldExecution ZwYieldExecution 0 diff --git a/reactos/include/afd/shared.h b/reactos/include/afd/shared.h index bd560813470..ddf28233495 100644 --- a/reactos/include/afd/shared.h +++ b/reactos/include/afd/shared.h @@ -197,6 +197,7 @@ typedef struct _AFD_DISCONNECT_INFO { #define AFD_SELECT 9 #define AFD_DISCONNECT 10 #define AFD_GET_SOCK_NAME 11 +#define AFD_GET_PEER_NAME 12 #define AFD_GET_TDI_HANDLES 13 #define AFD_SET_INFO 14 #define AFD_GET_CONTEXT 16 @@ -245,6 +246,8 @@ typedef struct _AFD_DISCONNECT_INFO { _AFD_CONTROL_CODE(AFD_DISCONNECT, METHOD_NEITHER) #define IOCTL_AFD_GET_SOCK_NAME \ _AFD_CONTROL_CODE(AFD_GET_SOCK_NAME, METHOD_NEITHER) +#define IOCTL_AFD_GET_PEER_NAME \ + _AFD_CONTROL_CODE(AFD_GET_PEER_NAME, METHOD_NEITHER) #define IOCTL_AFD_GET_TDI_HANDLES \ _AFD_CONTROL_CODE(AFD_GET_TDI_HANDLES, METHOD_NEITHER) #define IOCTL_AFD_SET_INFO \ diff --git a/reactos/include/coff.h b/reactos/include/coff.h index 41993831c76..4ec6a8f3de6 100644 --- a/reactos/include/coff.h +++ b/reactos/include/coff.h @@ -6,12 +6,6 @@ extern "C" { #endif -/* - * #ifndef __dj_ENFORCE_ANSI_FREESTANDING - * #ifndef __STRICT_ANSI__ - * #ifndef _POSIX_SOURCE - */ - /*** coff information for Intel 386/486. */ /********************** FILE HEADER **********************/ @@ -329,13 +323,6 @@ struct external_reloc { /* For new sections we havn't heard of before */ #define DEFAULT_SECTION_ALIGNMENT 4 -/* - * #endif /* !_POSIX_SOURCE */ - * #endif /* !__STRICT_ANSI__ */ - * #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ - */ -#ifndef __dj_ENFORCE_FUNCTION_CALLS -#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ #ifdef __cplusplus } diff --git a/reactos/include/csrss/csrss.h b/reactos/include/csrss/csrss.h index e819f2cf5ba..ffcaf8d7f26 100644 --- a/reactos/include/csrss/csrss.h +++ b/reactos/include/csrss/csrss.h @@ -11,15 +11,15 @@ typedef __declspec(noreturn) VOID CALLBACK(*PCONTROLDISPATCHER)(DWORD); typedef struct { -} CSRSS_CONNECT_PROCESS_REQUEST, PCSRSS_CONNECT_PROCESS_REQUEST; +} CSRSS_CONNECT_PROCESS_REQUEST, *PCSRSS_CONNECT_PROCESS_REQUEST; typedef struct { -} CSRSS_CONNECT_PROCESS_REPLY, PCSRSS_CONNECT_PROCESS_REPLY; +} CSRSS_CONNECT_PROCESS_REPLY, *PCSRSS_CONNECT_PROCESS_REPLY; typedef struct { - ULONG NewProcessId; + HANDLE NewProcessId; ULONG Flags; PCONTROLDISPATCHER CtrlDispatcher; } CSRSS_CREATE_PROCESS_REQUEST, *PCSRSS_CREATE_PROCESS_REQUEST; @@ -33,11 +33,23 @@ typedef struct typedef struct { -} CSRSS_TERMINATE_PROCESS_REQUEST, PCSRSS_TERMINATE_PROCESS_REQUEST; +} CSRSS_TERMINATE_PROCESS_REQUEST, *PCSRSS_TERMINATE_PROCESS_REQUEST; typedef struct { -} CSRSS_TERMINATE_PROCESS_REPLY, PCSRSS_TERMINATE_PROCESS_REPLY; +} CSRSS_TERMINATE_PROCESS_REPLY, *PCSRSS_TERMINATE_PROCESS_REPLY; + +typedef struct +{ + ULONG nMaxIds; +} CSRSS_GET_PROCESS_LIST_REQUEST, *PCSRSS_GET_PROCESS_LIST_REQUEST; + +typedef struct +{ + ULONG nProcessIdsCopied; + ULONG nProcessIdsTotal; + HANDLE ProcessId[1]; +} CSRSS_GET_PROCESS_LIST_REPLY, *PCSRSS_GET_PROCESS_LIST_REPLY; typedef struct { @@ -250,12 +262,12 @@ typedef struct typedef struct { HANDLE UniqueThread; -} CSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST; +} CSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST, *PCSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST; typedef struct { CLIENT_ID Cid; -} CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY; +} CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY, *PCSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY; typedef struct { @@ -359,7 +371,7 @@ typedef struct typedef struct { - DWORD ProcessId; + HANDLE ProcessId; } CSRSS_REGISTER_SERVICES_PROCESS_REQUEST, *PCSRSS_REGISTER_SERVICES_PROCESS_REQUEST; typedef struct @@ -476,7 +488,7 @@ typedef struct typedef struct { HANDLE Handle; - DWORD ProcessId; + HANDLE ProcessId; } CSRSS_DUPLICATE_HANDLE_REQUEST, *PCSRSS_DUPLICATE_HANDLE_REQUEST; typedef struct @@ -562,7 +574,7 @@ typedef struct typedef struct { - DWORD ProcessId; + HANDLE ProcessId; BOOL Register; } CSRSS_REGISTER_LOGON_PROCESS_REQUEST, *PCSRSS_REGISTER_LOGON_PROCESS_REQUEST; @@ -687,6 +699,7 @@ typedef struct #define CSRSS_GET_CONSOLE_OUTPUT_CP (0x33) #define CSRSS_SET_CONSOLE_OUTPUT_CP (0x34) #define CSRSS_GET_INPUT_WAIT_HANDLE (0x35) +#define CSRSS_GET_PROCESS_LIST (0x36) /* Keep in sync with definition below. */ #define CSRSS_REQUEST_HEADER_SIZE (LPC_MESSAGE_BASE_SIZE + sizeof(ULONG)) @@ -752,6 +765,7 @@ typedef struct CSRSS_GET_CONSOLE_OUTPUT_CP_REQUEST GetConsoleOutputCodePage; CSRSS_SET_CONSOLE_OUTPUT_CP_REQUEST SetConsoleOutputCodePage; CSRSS_GET_INPUT_WAIT_HANDLE_REQUEST GetConsoleInputWaitHandle; + CSRSS_GET_PROCESS_LIST_REQUEST GetProcessListRequest; } Data; }; }; @@ -807,6 +821,7 @@ typedef struct CSRSS_GET_CONSOLE_OUTPUT_CP_REPLY GetConsoleOutputCodePage; CSRSS_SET_CONSOLE_OUTPUT_CP_REPLY SetConsoleOutputCodePage; CSRSS_GET_INPUT_WAIT_HANDLE_REPLY GetConsoleInputWaitHandle; + CSRSS_GET_PROCESS_LIST_REPLY GetProcessListReply; } Data; }; }; diff --git a/reactos/include/ddk/csq.h b/reactos/include/ddk/csq.h index 6b0ba5c03c6..d3d2d3ecb76 100644 --- a/reactos/include/ddk/csq.h +++ b/reactos/include/ddk/csq.h @@ -9,34 +9,37 @@ * * BACKGROUND * - * IRP queuing is a royal pain in the butt, due to the fact that there are tons of - * built-in race conditions. IRP handling is difficult in general, but the cancel - * logic has been particularly complicated due to some subtle races, coupled - * with the fact that the system interfaces have changed over time. + * IRP queuing is a royal pain in the butt, due to the fact that there are + * tons of built-in race conditions. IRP handling is difficult in general, + * but the cancel logic has been particularly complicated due to some subtle + * races, coupled with the fact that the system interfaces have changed over + * time. * - * Walter Oney (2nd. Ed. of Programming the Windows Driver Model) states a common - * opinion among driver developers when he says that it is foolish to try to roll - * your own cancel logic. There are only a very few people who have gotten it - * right in the past. He suggests, instead, that you either use his own well-tested - * code, or use the code in the Microsoft Cancel-Safe Queue Library. + * Walter Oney (2nd. Ed. of Programming the Windows Driver Model) states a + * common opinion among driver developers when he says that it is foolish + * to try to roll your own cancel logic. There are only a very few people + * who have gotten it right in the past. He suggests, instead, that you + * either use his own well-tested code, or use the code in the Microsoft + * Cancel-Safe Queue Library. * - * We cannot do either, of course, due to copyright issues. I have therefore created - * this clone of the Microsoft library in order to concentrate all of the IRP-queuing - * bugs in one place. I'm quite sure there are problems here, so if you are a - * driver writer, I'd be glad to hear your feedback. + * We cannot do either, of course, due to copyright issues. I have therefore + * created this clone of the Microsoft library in order to concentrate all + * of the IRP-queuing bugs in one place. I'm quite sure there are problems + * here, so if you are a driver writer, I'd be glad to hear your feedback. * - * Apart from that, please try to use these routines, rather than building your own. - * If you think you have found a bug, please bring it up with me or on-list, as this - * is complicated and non-obvious stuff. Don't just change this and hope for the best! + * Apart from that, please try to use these routines, rather than building + * your own. If you think you have found a bug, please bring it up with me + * or on-list, as this is complicated and non-obvious stuff. Don't just + * change this and hope for the best! * * USAGE * * This library follows exactly the same interface as the Microsoft Cancel-Safe Queue - * routines (IoCsqXxx()). As such, the authoritative reference is the current DDK. - * There is also a DDK sample called "cancel" that has an example of how to use this - * code. I have also provided a sample driver that makes use of this queue. Finally, - * please do read the header and the source if you're curious about the inner workings - * of these routines. + * routines (IoCsqXxx()). As such, the authoritative reference is the + * current DDK. There is also a DDK sample called "cancel" that has an + * example of how to use this code. I have also provided a sample driver + * that makes use of this queue. Finally, please do read the header and the + * source if you're curious about the inner workings of these routines. */ #ifndef _REACTOS_CSQ_H @@ -48,10 +51,11 @@ struct _IO_CSQ; /* * CSQ Callbacks * - * The cancel-safe queue is implemented as a set of IoCsqXxx() OS routines copuled - * with a set of driver callbacks to handle the basic operations of the queue. You - * need to supply one of each of these functions in your own driver. These routines - * are also documented in the DDK under CsqXxx(). That is the authoritative documentation. + * The cancel-safe queue is implemented as a set of IoCsqXxx() OS routines + * copuled with a set of driver callbacks to handle the basic operations of + * the queue. You need to supply one of each of these functions in your own + * driver. These routines are also documented in the DDK under CsqXxx(). + * That is the authoritative documentation. */ /* @@ -60,11 +64,11 @@ struct _IO_CSQ; * * Sample implementation: * - VOID NTAPI CsqInsertIrp(PIO_CSQ Csq, PIRP Irp) - { - KdPrint(("Inserting IRP 0x%x into CSQ\n", Irp)); - InsertTailList(&IrpQueue, &Irp->Tail.Overlay.ListEntry); - } + VOID NTAPI CsqInsertIrp(PIO_CSQ Csq, PIRP Irp) + { + KdPrint(("Inserting IRP 0x%x into CSQ\n", Irp)); + InsertTailList(&IrpQueue, &Irp->Tail.Overlay.ListEntry); + } * */ typedef VOID (NTAPI *PIO_CSQ_INSERT_IRP) (struct _IO_CSQ *Csq, @@ -73,16 +77,16 @@ typedef VOID (NTAPI *PIO_CSQ_INSERT_IRP) (struct _IO_CSQ *Csq, /* * Function to insert an IRP into the queue with extended context information. - * This is useful if you need to be able to de-queue particular IRPs more easily - * in some cases. + * This is useful if you need to be able to de-queue particular IRPs more + * easily in some cases. * * Same deal as above; sample implementation: * - NTSTATUS NTAPI CsqInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext) - { - CsqInsertIrp(Csq, Irp); - return STATUS_PENDING; - } + NTSTATUS NTAPI CsqInsertIrpEx(PIO_CSQ Csq, PIRP Irp, PVOID InsertContext) + { + CsqInsertIrp(Csq, Irp); + return STATUS_PENDING; + } * */ typedef NTSTATUS (NTAPI *PIO_CSQ_INSERT_IRP_EX) (struct _IO_CSQ *Csq, @@ -94,11 +98,11 @@ typedef NTSTATUS (NTAPI *PIO_CSQ_INSERT_IRP_EX) (struct _IO_CSQ *Csq, * * Sample: * - VOID NTAPI CsqRemoveIrp(PIO_CSQ Csq, PIRP Irp) - { - KdPrint(("Removing IRP 0x%x from CSQ\n", Irp)); - RemoveEntryList(&Irp->Tail.Overlay.ListEntry); - } + VOID NTAPI CsqRemoveIrp(PIO_CSQ Csq, PIRP Irp) + { + KdPrint(("Removing IRP 0x%x from CSQ\n", Irp)); + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + } * */ typedef VOID (NTAPI *PIO_CSQ_REMOVE_IRP) (struct _IO_CSQ *Csq, @@ -109,18 +113,18 @@ typedef VOID (NTAPI *PIO_CSQ_REMOVE_IRP) (struct _IO_CSQ *Csq, * * Sample: * - PIRP NTAPI CsqPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext) - { - KdPrint(("Peeking for next IRP\n")); + PIRP NTAPI CsqPeekNextIrp(PIO_CSQ Csq, PIRP Irp, PVOID PeekContext) + { + KdPrint(("Peeking for next IRP\n")); - if(Irp) - return CONTAINING_RECORD(&Irp->Tail.Overlay.ListEntry.Flink, IRP, Tail.Overlay.ListEntry); + if(Irp) + return CONTAINING_RECORD(&Irp->Tail.Overlay.ListEntry.Flink, IRP, Tail.Overlay.ListEntry); - if(IsListEmpty(&IrpQueue)) - return NULL; + if(IsListEmpty(&IrpQueue)) + return NULL; - return CONTAINING_RECORD(IrpQueue.Flink, IRP, Tail.Overlay.ListEntry); - } + return CONTAINING_RECORD(IrpQueue.Flink, IRP, Tail.Overlay.ListEntry); + } * */ typedef PIRP (NTAPI *PIO_CSQ_PEEK_NEXT_IRP) (struct _IO_CSQ *Csq, @@ -133,11 +137,11 @@ typedef PIRP (NTAPI *PIO_CSQ_PEEK_NEXT_IRP) (struct _IO_CSQ *Csq, * * Sample: * - VOID NTAPI CsqAcquireLock(PIO_CSQ Csq, PKIRQL Irql) - { - KdPrint(("Acquiring spin lock\n")); - KeAcquireSpinLock(&IrpQueueLock, Irql); - } + VOID NTAPI CsqAcquireLock(PIO_CSQ Csq, PKIRQL Irql) + { + KdPrint(("Acquiring spin lock\n")); + KeAcquireSpinLock(&IrpQueueLock, Irql); + } * */ typedef VOID (NTAPI *PIO_CSQ_ACQUIRE_LOCK) (struct _IO_CSQ *Csq, @@ -146,11 +150,11 @@ typedef VOID (NTAPI *PIO_CSQ_ACQUIRE_LOCK) (struct _IO_CSQ *Csq, /* * Unlock the queue: * - VOID NTAPI CsqReleaseLock(PIO_CSQ Csq, KIRQL Irql) - { - KdPrint(("Releasing spin lock\n")); - KeReleaseSpinLock(&IrpQueueLock, Irql); - } + VOID NTAPI CsqReleaseLock(PIO_CSQ Csq, KIRQL Irql) + { + KdPrint(("Releasing spin lock\n")); + KeReleaseSpinLock(&IrpQueueLock, Irql); + } * */ typedef VOID (NTAPI *PIO_CSQ_RELEASE_LOCK) (struct _IO_CSQ *Csq, @@ -162,13 +166,13 @@ typedef VOID (NTAPI *PIO_CSQ_RELEASE_LOCK) (struct _IO_CSQ *Csq, * * Sample: * - VOID NTAPI CsqCompleteCancelledIrp(PIO_CSQ Csq, PIRP Irp) - { - KdPrint(("cancelling irp 0x%x\n", Irp)); - Irp->IoStatus.Status = STATUS_CANCELLED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } + VOID NTAPI CsqCompleteCancelledIrp(PIO_CSQ Csq, PIRP Irp) + { + KdPrint(("cancelling irp 0x%x\n", Irp)); + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } * */ typedef VOID (NTAPI *PIO_CSQ_COMPLETE_CANCELED_IRP) (struct _IO_CSQ *Csq, @@ -179,8 +183,8 @@ typedef VOID (NTAPI *PIO_CSQ_COMPLETE_CANCELED_IRP) (struct _IO_CSQ *Csq, * STRUCTURES * * NOTE: Please do not use these directly. You will make incompatible code - * if you do. Always only use the documented IoCsqXxx() interfaces and you will - * amass much Good Karma. + * if you do. Always only use the documented IoCsqXxx() interfaces and you + * will amass much Good Karma. */ #define IO_TYPE_CSQ_IRP_CONTEXT 1 #define IO_TYPE_CSQ 2 @@ -213,9 +217,9 @@ typedef struct _IO_CSQ_IRP_CONTEXT { /* * CANCEL-SAFE QUEUE DDIs * - * These device driver interfaces are called to make use of the queue. Again, authoritative - * documentation for these functions is in the DDK. The csqtest driver also makes use of - * some of them. + * These device driver interfaces are called to make use of the queue. Again, + * authoritative documentation for these functions is in the DDK. The csqtest + * driver also makes use of some of them. */ @@ -274,4 +278,3 @@ PIRP NTAPI IoCsqRemoveNextIrp(PIO_CSQ Csq, PVOID PeekContext); #endif /* _REACTOS_CSQ_H */ - diff --git a/reactos/include/ddk/fsfuncs.h b/reactos/include/ddk/fsfuncs.h index 10f70b847b5..73318687be0 100644 --- a/reactos/include/ddk/fsfuncs.h +++ b/reactos/include/ddk/fsfuncs.h @@ -5,50 +5,13 @@ #include -/* Some comments on the Prototypes that aren't in the GNU IFS: +/* Some comments on the Prototypes that aren't in the IFS: -The following come from alternate sources, or guessed from documentation: -FsRtlNotifyFullChangeDirectory GOOGLE GROUPS -FsRtlIsPagingFile OSR DOCUMENTATION -FsRtlAcquireFileExclusive (GUESS: The function takes a single parameter. The function name is "AcquireFile". Logical assumption says this is a File Object. NTFSD ML Post confirms.) -FsRtlReleaseFile (GUESS: The function takes a single parameter. The function name is "AcquireFile". Logical assumption says this is a File Object. NTFSD ML Post confirms.) FsRtlMdlReadCompleteDev (FsRtlMdlReadComplete is on GNU IFS. The Dev Suffix simply means an extra PDEVICE_OBJECT param) FsRtlMdlReadDev (FsRtlMdlReadDev is on GNU IFS. The Dev Suffix simply means an extra PDEVICE_OBJECT param) FsRtlMdlWriteCompleteDev FsRtlMdlWriteCompleteDev is on GNU IFS. The Dev Suffix simply means an extra PDEVICE_OBJECT param) FsRtlPrepareMdlWrite (Compared with CcMdlWrite, which is already documented) FsRtlPrepareMdlWriteDev (Same as above, and add a pointer to device object (Dev suffix) -FsRtlGetNextMcbEntry(FsRtlGetNextLargeMcbEntry is documented and uses LONGLONGs. Logical assumption that this one only uses LONGS and non-large MCB (Documented)) - -Stream Context. Going along with public OSR documenttion: - -FsRtlInsertPerStreamContext: -"This call is used by the file system filter driver to associate a given context block -(allocated by the filter and initialized using FsRtlInitPerStreamContext) with the stream associated with the given file object." -Notice we are told "given context block...initialized using FsRtlInitPerStreamContext". This function description tells us: -" provide space for the FSRTL_PER_STREAM_CONTEXT block in the filter driver’s context structure" -Therefore, one of the parameters is PFSRTL_PER_STREAM_CONTEXT. -"with the stream associated with the given file object." The OSR Documentations then mentions: -"Tracking per-file (or “per stream”) context information in FSRTL_ADVANCED_FCB_HEADER" -So we are associating a FSRTL_PER_STREAM_CONTEXT block with the FSRTL_ADVANCED_FCB_HEADER associated with the file object. -FSRTL_ADVANCED_FCB_HEADER is documented by a search through Google. -FSRTL_PER_STREAM_CONTEXT is *NOT* documented anywhere else then in the IFS, so it has been removed. - -FsRtlLookupPerStreamContextInternal -"FsRtlLookupPerStreamContext – this call is used by the file system filter driver to locate a given context -block that is associated with the file object. Typically, a file system filter driver will identify its -own context block using unique OwnerId and InstanceId parameters when creating the context block and subsequently -when locating the associated information." -OSR tells us here that the last two parameters are OwnerId and InstanceId. It also says it will find a given context block, -so there's our Return Value. (Although, not being documented, we must put PVOID). It looks into a file object's stream, so we -probably need that FCB header again. - -FsRtlRemovePerStreamContext -OSR is vague, so all we know for sure is that we are sending an FCB Header. The return value isn't NTSTATUS, but seems to be a -pointer. We don't know what the two other parameters are, so they have been marked as unknown. - -FsRtlTeardownPerStreamContexts -OSR doens't tell a lot, but we only have one parameter. It must be the FCB Header. Furthermore, the CVS of Captive implements -this function as a stub, and confirms the theory. */ @@ -144,10 +107,10 @@ FsRtlAreNamesEqual ( IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL ); -DWORD +NTSTATUS STDCALL FsRtlBalanceReads ( - DWORD Unknown0 + PDEVICE_OBJECT TargetDevice ); BOOLEAN STDCALL @@ -368,30 +331,24 @@ FsRtlInsertPerStreamContext ( IN PFSRTL_PER_STREAM_CONTEXT Ptr ); +BOOLEAN STDCALL +FsRtlIsDbcsInExpression(IN PANSI_STRING Expression, + IN PANSI_STRING Name); + BOOLEAN STDCALL -FsRtlIsDbcsInExpression ( - DWORD Unknown0, - DWORD Unknown1 - ); +FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible); + BOOLEAN STDCALL -FsRtlIsFatDbcsLegal ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4 - ); -BOOLEAN -STDCALL -FsRtlIsHpfsDbcsLegal ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4 - ); +FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible); + BOOLEAN STDCALL FsRtlIsNameInExpression ( @@ -709,19 +666,15 @@ FsRtlNumberOfRunsInMcb (IN PMCB Mcb); VOID STDCALL -FsRtlPostPagingFileStackOverflow ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2 - ); +FsRtlPostPagingFileStackOverflow(IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine) ; VOID STDCALL -FsRtlPostStackOverflow ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2 - ); +FsRtlPostStackOverflow (IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine) ; BOOLEAN STDCALL @@ -750,10 +703,8 @@ FsRtlProcessFileLock ( NTSTATUS STDCALL -FsRtlRegisterFileSystemFilterCallbacks ( - IN PVOID Unknown1, - IN PVOID Unknown2 - ); +FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject, + IN PFS_FILTER_CALLBACKS Callbacks); NTSTATUS STDCALL FsRtlRegisterUncProvider(IN OUT PHANDLE Handle, @@ -780,8 +731,8 @@ PFSRTL_PER_STREAM_CONTEXT STDCALL FsRtlRemovePerStreamContext ( IN PFSRTL_ADVANCED_FCB_HEADER StreamContext, - IN PVOID Unknown1 OPTIONAL, - IN PVOID Unknown2 OPTIONAL + IN PVOID OwnerId OPTIONAL, + IN PVOID InstanceId OPTIONAL ); PVOID /* PFSRTL_PER_FILE_OBJECT_CONTEXT*/ @@ -807,9 +758,9 @@ FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, NTSTATUS STDCALL FsRtlSyncVolumes ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2 + ULONG Unknown0, + ULONG Unknown1, + ULONG Unknown2 ); VOID diff --git a/reactos/include/ddk/fstypes.h b/reactos/include/ddk/fstypes.h index 254219e46d7..8d1aaab22c4 100644 --- a/reactos/include/ddk/fstypes.h +++ b/reactos/include/ddk/fstypes.h @@ -30,6 +30,12 @@ typedef NTSTATUS (*PCOMPLETE_LOCK_IRP_ROUTINE) ( IN PIRP Irp ); +typedef VOID (*PFSRTL_STACK_OVERFLOW_ROUTINE) ( + IN PVOID Context, + IN PKEVENT Event +); + + typedef VOID (*PUNLOCK_ROUTINE) ( IN PVOID Context, IN PFILE_LOCK_INFO FileLockInfo diff --git a/reactos/include/ddk/iodef.h b/reactos/include/ddk/iodef.h index e35d19df60e..31a24cf34cf 100644 --- a/reactos/include/ddk/iodef.h +++ b/reactos/include/ddk/iodef.h @@ -160,6 +160,12 @@ enum #define SL_INVOKE_ON_SUCCESS 0x40 #define SL_INVOKE_ON_ERROR 0x80 +/* + * IoCreateFile options + */ +#define IO_NO_PARAMETER_CHECKING 0x0100 +#define IO_CHECK_CREATE_PARAMETERS 0x0200 + /* * Possible flags for the device object flags */ diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index 7f919780979..bca07696b55 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -196,6 +196,8 @@ typedef struct _CM_MCA_POS_DATA } CM_MCA_POS_DATA, *PCM_MCA_POS_DATA; +#include + /* Int13 drive geometry data */ typedef struct _CM_INT13_DRIVE_PARAMETER @@ -207,6 +209,8 @@ typedef struct _CM_INT13_DRIVE_PARAMETER USHORT NumberDrives; } CM_INT13_DRIVE_PARAMETER, *PCM_INT13_DRIVE_PARAMETER; +#include + /* Extended drive geometry data */ @@ -642,15 +646,6 @@ typedef struct _IO_COMPLETION_CONTEXT #define FO_HANDLE_CREATED 0x00040000 #define FO_FILE_FAST_IO_READ 0x00080000 -/* - * ReactOS specific flags - */ -#define FO_DIRECT_CACHE_READ 0x72000001 -#define FO_DIRECT_CACHE_WRITE 0x72000002 -#define FO_DIRECT_CACHE_PAGING_READ 0x72000004 -#define FO_DIRECT_CACHE_PAGING_WRITE 0x72000008 -#define FO_FCB_IS_VALID 0x72000010 - typedef struct _FILE_OBJECT { CSHORT Type; diff --git a/reactos/include/ddk/kefuncs.h b/reactos/include/ddk/kefuncs.h index 0f7d7013008..038bbd26cd3 100644 --- a/reactos/include/ddk/kefuncs.h +++ b/reactos/include/ddk/kefuncs.h @@ -113,7 +113,7 @@ KIRQL STDCALL KeGetCurrentIrql (VOID); #ifndef __USE_W32API #define KeGetCurrentProcessorNumber() (KeGetCurrentKPCR()->ProcessorNumber) ULONG KeGetDcacheFillSize(VOID); -ULONG STDCALL KeGetPreviousMode (VOID); +KPROCESSOR_MODE STDCALL KeGetPreviousMode (VOID); #endif struct _KTHREAD* STDCALL KeGetCurrentThread (VOID); @@ -218,9 +218,9 @@ VOID STDCALL KeLeaveCriticalRegion (VOID); VOID STDCALL KeLowerIrql (KIRQL NewIrql); -NTSTATUS STDCALL KePulseEvent (PKEVENT Event, - KPRIORITY Increment, - BOOLEAN Wait); +LONG STDCALL KePulseEvent (PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait); LARGE_INTEGER STDCALL diff --git a/reactos/include/ddk/ketypes.h b/reactos/include/ddk/ketypes.h index 549be03befc..ce77b02599c 100644 --- a/reactos/include/ddk/ketypes.h +++ b/reactos/include/ddk/ketypes.h @@ -99,6 +99,10 @@ typedef struct _KDEVICE_QUEUE BOOLEAN Busy; } KDEVICE_QUEUE, *PKDEVICE_QUEUE; +/* + * Size of the profile hash table. + */ +#define PROFILE_HASH_TABLE_SIZE (32) #include diff --git a/reactos/include/ddk/miniport.h b/reactos/include/ddk/miniport.h deleted file mode 100644 index fc364f591aa..00000000000 --- a/reactos/include/ddk/miniport.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * miniport.h - * - * Type definitions for miniport drivers - * - * This file is part of the w32api package. - * - * Contributors: - * Created by Casper S. Hornstrup - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef __MINIPORT_H -#define __MINIPORT_H - -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define DDKAPI - -#pragma pack(push,4) - -#include "ntddk.h" - - -#define EMULATOR_READ_ACCESS 0x01 -#define EMULATOR_WRITE_ACCESS 0x02 - -typedef enum _EMULATOR_PORT_ACCESS_TYPE { - Uchar, - Ushort, - Ulong -} EMULATOR_PORT_ACCESS_TYPE, *PEMULATOR_PORT_ACCESS_TYPE; - - -typedef struct _EMULATOR_ACCESS_ENTRY { - ULONG BasePort; - ULONG NumConsecutivePorts; - EMULATOR_PORT_ACCESS_TYPE AccessType; - UCHAR AccessMode; - UCHAR StringSupport; - PVOID Routine; -} EMULATOR_ACCESS_ENTRY, *PEMULATOR_ACCESS_ENTRY; - -#ifndef VIDEO_ACCESS_RANGE_DEFINED /* also in video.h */ -#define VIDEO_ACCESS_RANGE_DEFINED -typedef struct _VIDEO_ACCESS_RANGE { - PHYSICAL_ADDRESS RangeStart; - ULONG RangeLength; - UCHAR RangeInIoSpace; - UCHAR RangeVisible; - UCHAR RangeShareable; - UCHAR RangePassive; -} VIDEO_ACCESS_RANGE, *PVIDEO_ACCESS_RANGE; -#endif - -#ifndef BANKED_SECTION_ROUTINE_DEFINED /* also in video.h */ -#define BANKED_SECTION_ROUTINE_DEFINED -typedef VOID DDKAPI -(*PBANKED_SECTION_ROUTINE)( - IN ULONG ReadBank, - IN ULONG WriteBank, - IN PVOID Context); -#endif - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif - -#endif /* __MINIPORT_H */ diff --git a/reactos/include/ddk/mmfuncs.h b/reactos/include/ddk/mmfuncs.h index 7cffe6baa4f..bbf635a0414 100644 --- a/reactos/include/ddk/mmfuncs.h +++ b/reactos/include/ddk/mmfuncs.h @@ -26,21 +26,9 @@ extern POBJECT_TYPE IMPORTED MmSectionObjectType; * Size = Size of range * RETURNS: The number of pages */ -#if 0 -extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va, - ULONG Size) -{ - ULONG HighestAddr; - ULONG LowestAddr; - - HighestAddr = PAGE_ROUND_UP(Size + ((ULONG)Va)); - LowestAddr = PAGE_ROUND_DOWN((ULONG)Va); - return((HighestAddr - LowestAddr) / PAGE_SIZE); -} -#endif #define ADDRESS_AND_SIZE_TO_SPAN_PAGES(Va, Size) \ - (ULONG)((PAGE_ROUND_UP((Size) + ((ULONG)(Va))) - \ - PAGE_ROUND_DOWN((ULONG)(Va))) / PAGE_SIZE) + (ULONG)((PAGE_ROUND_UP((Size) + ((ULONG_PTR)(Va))) - \ + PAGE_ROUND_DOWN((ULONG_PTR)(Va))) / PAGE_SIZE) /* * FUNCTION: Returns FALSE is the pointer is NULL, TRUE otherwise @@ -50,7 +38,7 @@ extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va, /* * FUNCTION: Returns the byte offset of the address within its page */ -#define BYTE_OFFSET(va) (((ULONG)va)%PAGE_SIZE) +#define BYTE_OFFSET(va) (((ULONG_PTR)va)%PAGE_SIZE) #define PAGE_OFFSET(va) BYTE_OFFSET(va) @@ -59,10 +47,9 @@ extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va, * required to hold it */ #define BYTES_TO_PAGES(Size) \ - ((ULONG) ((ULONG_PTR) (Size) >> PAGE_SHIFT) + (((ULONG) (Size) & (PAGE_SIZE - 1)) != 0)) + (((Size) >> PAGE_SHIFT) + (((Size) & (PAGE_SIZE - 1)) != 0)) - -#define PAGE_ALIGN(va) ( (PVOID) (((ULONG)(va)) & (~(PAGE_SIZE-1))) ) +#define PAGE_ALIGN(va) ( (PVOID) (((ULONG_PTR)(va)) & (~(PAGE_SIZE-1))) ) #define PAGE_BASE(va) PAGE_ALIGN(va) NTSTATUS @@ -331,10 +318,10 @@ MmGrowKernelStack ( { \ (MemoryDescriptorList)->Next = (PMDL)NULL; \ (MemoryDescriptorList)->Size = (CSHORT)(sizeof(MDL) + \ - (ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(ULONG))); \ + (ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(PFN_NUMBER))); \ (MemoryDescriptorList)->MdlFlags = 0; \ - (MemoryDescriptorList)->StartVa = (PVOID)PAGE_BASE(BaseVa); \ - (MemoryDescriptorList)->ByteOffset = (ULONG)PAGE_OFFSET(BaseVa); \ + (MemoryDescriptorList)->StartVa = PAGE_ALIGN(BaseVa); \ + (MemoryDescriptorList)->ByteOffset = BYTE_OFFSET(BaseVa); \ (MemoryDescriptorList)->ByteCount = (Length); \ } diff --git a/reactos/include/ddk/mmtypes.h b/reactos/include/ddk/mmtypes.h index a4c87616e72..5eee4277254 100644 --- a/reactos/include/ddk/mmtypes.h +++ b/reactos/include/ddk/mmtypes.h @@ -15,7 +15,7 @@ * PURPOSE: Returns the byte offset of a field within a structure */ #ifndef FIELD_OFFSET -#define FIELD_OFFSET(Type,Field) ((LONG)(&(((Type *)(0))->Field))) +#define FIELD_OFFSET(Type,Field) ((ULONG_PTR)(&(((Type *)(0))->Field))) #endif /* @@ -27,9 +27,16 @@ * Field = Name of the field whose address is none */ #ifndef CONTAINING_RECORD -#define CONTAINING_RECORD(Address,Type,Field) ((Type *)(((LONG)Address) - FIELD_OFFSET(Type,Field))) +#define CONTAINING_RECORD(Address,Type,Field) ((Type *)(((ULONG_PTR)Address) - FIELD_OFFSET(Type,Field))) #endif +#ifdef _M_IX86 +typedef ULONG PFN_NUMBER, *PPFN_NUMBER; +#elif _M_IA64 +typedef ULONG64 PFN_NUMBER, *PPFN_NUMBER; +#else +#error Unknown architecture +#endif #define MDL_MAPPED_TO_SYSTEM_VA (0x1) #define MDL_PAGES_LOCKED (0x2) diff --git a/reactos/include/ddk/psfuncs.h b/reactos/include/ddk/psfuncs.h index 8ca1cac9c31..92bee18dc06 100644 --- a/reactos/include/ddk/psfuncs.h +++ b/reactos/include/ddk/psfuncs.h @@ -395,7 +395,7 @@ BOOLEAN STDCALL PsGetVersion (PULONG MajorVersion OPTIONAL, LARGE_INTEGER STDCALL PsGetProcessExitTime(VOID); BOOLEAN STDCALL PsIsThreadTerminating(struct _ETHREAD* Thread); -NTSTATUS STDCALL PsLookupProcessByProcessId(IN PVOID ProcessId, +NTSTATUS STDCALL PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process); NTSTATUS STDCALL PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, diff --git a/reactos/include/ddk/setypes.h b/reactos/include/ddk/setypes.h index 65cdd535d3f..f9890b4c988 100644 --- a/reactos/include/ddk/setypes.h +++ b/reactos/include/ddk/setypes.h @@ -50,55 +50,88 @@ #define FAILED_ACCESS_ACE_FLAG (0x80) /* SECURITY_DESCRIPTOR_CONTROL */ -#define SECURITY_DESCRIPTOR_REVISION (1) -#define SECURITY_DESCRIPTOR_REVISION1 (1) -#define SECURITY_DESCRIPTOR_MIN_LENGTH (20) -#define SE_OWNER_DEFAULTED (1) -#define SE_GROUP_DEFAULTED (2) -#define SE_DACL_PRESENT (4) -#define SE_DACL_DEFAULTED (8) -#define SE_SACL_PRESENT (16) -#define SE_SACL_DEFAULTED (32) -#define SE_SELF_RELATIVE (32768) +#define SECURITY_DESCRIPTOR_REVISION (1) +#define SECURITY_DESCRIPTOR_REVISION1 (1) +#define SECURITY_DESCRIPTOR_MIN_LENGTH (20) +#define SE_OWNER_DEFAULTED (0x0001) +#define SE_GROUP_DEFAULTED (0x0002) +#define SE_DACL_PRESENT (0x0004) +#define SE_DACL_DEFAULTED (0x0008) +#define SE_SACL_PRESENT (0x0010) +#define SE_SACL_DEFAULTED (0x0020) +#define SE_RM_CONTROL_VALID (0x4000) +#define SE_SELF_RELATIVE (0x8000) /* PRIVILEGE_SET */ -#define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x1L) -#define SE_PRIVILEGE_ENABLED (0x2L) -#define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L) -#define PRIVILEGE_SET_ALL_NECESSARY (0x1) +#define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x1L) +#define SE_PRIVILEGE_ENABLED (0x2L) +#define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L) +#define PRIVILEGE_SET_ALL_NECESSARY (0x1) /* SID */ #define SID_REVISION (1) #define SID_MAX_SUB_AUTHORITIES (15) -typedef struct _ACCESS_TOKEN -{ - TOKEN_SOURCE TokenSource; /* 0x00 */ +typedef struct _SEP_AUDIT_POLICY_CATEGORIES { + UCHAR System:4; + UCHAR Logon:4; + UCHAR ObjectAccess:4; + UCHAR PrivilegeUse:4; + UCHAR DetailedTracking:4; + UCHAR PolicyChange:4; + UCHAR AccountManagement:4; + UCHAR DirectoryServiceAccess:4; + UCHAR AccountLogon:4; +} SEP_AUDIT_POLICY_CATEGORIES, *PSEP_AUDIT_POLICY_CATEGORIES; + +typedef struct _SEP_AUDIT_POLICY_OVERLAY { + ULONGLONG PolicyBits:36; + UCHAR SetBit:1; +} SEP_AUDIT_POLICY_OVERLAY, *PSEP_AUDIT_POLICY_OVERLAY; + +typedef struct _SEP_AUDIT_POLICY { + union { + SEP_AUDIT_POLICY_CATEGORIES PolicyElements; + SEP_AUDIT_POLICY_OVERLAY PolicyOverlay; + ULONGLONG Overlay; + }; +} SEP_AUDIT_POLICY, *PSEP_AUDIT_POLICY; + +typedef struct _TOKEN { + TOKEN_SOURCE TokenSource; /* 0x00 */ LUID TokenId; /* 0x10 */ LUID AuthenticationId; /* 0x18 */ - LARGE_INTEGER ExpirationTime; /* 0x20 */ - LUID ModifiedId; /* 0x28 */ - ULONG UserAndGroupCount; /* 0x30 */ - ULONG PrivilegeCount; /* 0x34 */ - ULONG VariableLength; /* 0x38 */ - ULONG DynamicCharged; /* 0x3C */ - ULONG DynamicAvailable; /* 0x40 */ - ULONG DefaultOwnerIndex; /* 0x44 */ - PSID_AND_ATTRIBUTES UserAndGroups; /* 0x48 */ - PSID PrimaryGroup; /* 0x4C */ - PLUID_AND_ATTRIBUTES Privileges; /* 0x50 */ - ULONG Unknown1; /* 0x54 */ - PACL DefaultDacl; /* 0x58 */ - TOKEN_TYPE TokenType; /* 0x5C */ - SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; /* 0x60 */ - UCHAR TokenFlags; /* 0x64 */ - UCHAR TokenInUse; /* 0x65 */ - UCHAR Unused[2]; /* 0x66 */ - PVOID ProxyData; /* 0x68 */ - PVOID AuditData; /* 0x6c */ - UCHAR VariablePart[1]; /* 0x70 */ -} ACCESS_TOKEN, *PACCESS_TOKEN; + LUID ParentTokenId; /* 0x20 */ + LARGE_INTEGER ExpirationTime; /* 0x28 */ + struct _ERESOURCE *TokenLock; /* 0x30 */ + ULONG Padding; /* 0x34 */ + SEP_AUDIT_POLICY AuditPolicy; /* 0x38 */ + LUID ModifiedId; /* 0x40 */ + ULONG SessionId; /* 0x48 */ + ULONG UserAndGroupCount; /* 0x4C */ + ULONG RestrictedSidCount; /* 0x50 */ + ULONG PrivilegeCount; /* 0x54 */ + ULONG VariableLength; /* 0x58 */ + ULONG DynamicCharged; /* 0x5C */ + ULONG DynamicAvailable; /* 0x60 */ + ULONG DefaultOwnerIndex; /* 0x64 */ + PSID_AND_ATTRIBUTES UserAndGroups; /* 0x68 */ + PSID_AND_ATTRIBUTES RestrictedSids; /* 0x6C */ + PSID PrimaryGroup; /* 0x70 */ + PLUID_AND_ATTRIBUTES Privileges; /* 0x74 */ + PULONG DynamicPart; /* 0x78 */ + PACL DefaultDacl; /* 0x7C */ + TOKEN_TYPE TokenType; /* 0x80 */ + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; /* 0x84 */ + ULONG TokenFlags; /* 0x88 */ + ULONG TokenInUse; /* 0x8C */ + PVOID ProxyData; /* 0x90 */ + PVOID AuditData; /* 0x94 */ + LUID OriginatingLogonSession; /* 0x98 */ + UCHAR VariablePart[1]; /* 0xA0 */ +} TOKEN, *PTOKEN; +typedef PVOID PACCESS_TOKEN; typedef struct _SECURITY_SUBJECT_CONTEXT { @@ -111,12 +144,12 @@ typedef struct _SECURITY_SUBJECT_CONTEXT typedef struct _SECURITY_CLIENT_CONTEXT { - SECURITY_QUALITY_OF_SERVICE SecurityQos; /* 0x00 */ - PACCESS_TOKEN Token; /* 0x0C */ - BOOLEAN DirectlyAccessClientToken; /* 0x10 */ - BOOLEAN DirectAccessEffectiveOnly; /* 0x11 */ - BOOLEAN ServerIsRemote; /* 0x12 */ - TOKEN_CONTROL ClientTokenControl; /* 0x14 */ + SECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_TOKEN ClientToken; + BOOLEAN DirectlyAccessClientToken; + BOOLEAN DirectAccessEffectiveOnly; + BOOLEAN ServerIsRemote; + TOKEN_CONTROL ClientTokenControl; } SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT; diff --git a/reactos/include/ddk/status.h b/reactos/include/ddk/status.h index b23f14e2db9..629f9c386c3 100644 --- a/reactos/include/ddk/status.h +++ b/reactos/include/ddk/status.h @@ -669,6 +669,9 @@ Note that !NT_SUCCESS(errCode) is NOT the same as NT_ERROR(errCode) #define STATUS_RANGE_NOT_FOUND ((NTSTATUS)0xC000028C) +#define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS)0xC00002B4L) +#define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS)0xC00002B5L) + #define STATUS_SAM_INIT_FAILURE ((NTSTATUS)0xC00002CB) diff --git a/reactos/include/defines.h b/reactos/include/defines.h index 961a9ce3463..7a9868022d5 100644 --- a/reactos/include/defines.h +++ b/reactos/include/defines.h @@ -771,6 +771,7 @@ extern "C" { #define DS_SETFONT (0x40L) #define DS_SETFOREGROUND (0x200L) #define DS_SYSMODAL (0x2L) +#define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS) /* CreateWindowEx */ #define WS_EX_ACCEPTFILES (0x10L) diff --git a/reactos/include/fslib/vfatxlib.h b/reactos/include/fslib/vfatxlib.h new file mode 100644 index 00000000000..b100710dc7b --- /dev/null +++ b/reactos/include/fslib/vfatxlib.h @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFAT filesystem library + * FILE: include/fslib/vfatlib.h + * PURPOSE: Public definitions for vfat filesystem library + */ +#ifndef __VFATXLIB_H +#define __VFATXLIB_H + +#include + +NTSTATUS +VfatxInitialize (VOID); + +NTSTATUS +VfatxCleanup (VOID); + +NTSTATUS +VfatxFormat (PUNICODE_STRING DriveRoot, + ULONG MediaFlag, + BOOLEAN QuickFormat, + PFMIFSCALLBACK Callback); + +#endif /*__VFATLIB_H */ diff --git a/reactos/include/funcs.h b/reactos/include/funcs.h index 852e2269674..52a153c4962 100644 --- a/reactos/include/funcs.h +++ b/reactos/include/funcs.h @@ -2082,8 +2082,6 @@ VOID STDCALL WEP(); DWORD STDCALL RtlDeleteSecurityObject(DWORD x1); DWORD STDCALL RtlNewSecurityObject(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6); NTSTATUS STDCALL RtlWalkHeap( HANDLE heap, PVOID entry_ptr ); -NTSTATUS STDCALL RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *crit); -NTSTATUS STDCALL RtlpWaitForCriticalSection(RTL_CRITICAL_SECTION *crit); NTSTATUS STDCALL LdrLockLoaderLock(ULONG flags, ULONG *result, ULONG *magic); NTSTATUS STDCALL LdrUnlockLoaderLock(ULONG flags, ULONG magic); @@ -4603,7 +4601,7 @@ AccessCheck( LPBOOL AccessStatus ); -#ifndef __NTDRIVER__ +#if !defined(__NTDRIVER__) LONG STDCALL InterlockedIncrement( @@ -4623,12 +4621,12 @@ InterlockedExchange( LONG Value ); -PVOID +LONG STDCALL InterlockedCompareExchange( - PVOID *Destination, - PVOID Exchange, - PVOID Comperand + PLONG Destination, + LONG Exchange, + LONG Comperand ); #endif diff --git a/reactos/include/msvcrt/crttypes.h b/reactos/include/msvcrt/crttypes.h index 0900ce1a341..e8e066318a2 100644 --- a/reactos/include/msvcrt/crttypes.h +++ b/reactos/include/msvcrt/crttypes.h @@ -49,20 +49,6 @@ struct _ETHREAD { int foobar; }; struct _EPROCESS { int foobar; }; #endif -#ifndef _DEBUG -#pragma function(_disable,_enable) -#pragma function(_inp,_inpw,_outp,_outpw) -#pragma function(_lrotl,_lrotr,_rotl,_rotr) -#pragma function(abs,fabs,labs) -#pragma function(memcpy,memcmp,memset) -#pragma function(strcat,strcmp,strcpy,strlen,_strset) -#pragma function(fmod,sqrt) -#pragma function(log,log10,pow,exp) -#pragma function(tan,atan,atan2,tanh) -#pragma function(cos,acos,cosh) -#pragma function(sin,asin,sinh) -#endif - #endif /*__GNUC__*/ diff --git a/reactos/include/msvcrt/internal/file.h b/reactos/include/msvcrt/internal/file.h index 73358805391..6630ffa66d3 100644 --- a/reactos/include/msvcrt/internal/file.h +++ b/reactos/include/msvcrt/internal/file.h @@ -70,6 +70,8 @@ extern __file_rec* __file_rec_list; void _dosmaperr(unsigned long oserrcode); +extern int __fmode; + #ifdef __cplusplus } #endif diff --git a/reactos/include/msvcrt/stddef.h b/reactos/include/msvcrt/stddef.h index 9dd4ee6edba..6a3e3df7c73 100644 --- a/reactos/include/msvcrt/stddef.h +++ b/reactos/include/msvcrt/stddef.h @@ -154,7 +154,11 @@ typedef __WINT_TYPE__ wint_t; #if defined (__MSVCRT_STDDEF_H_) || defined (__need_NULL) #undef NULL +#ifdef __cplusplus #define NULL (0) +#else +#define NULL ((void *)0) +#endif #endif /* __MSVCRT_STDDEF_H_ or __need_NULL */ #undef __need_NULL diff --git a/reactos/lib/msvcrt/wine/cppexcept.h b/reactos/include/msvcrt/wine/cppexcept.h similarity index 100% rename from reactos/lib/msvcrt/wine/cppexcept.h rename to reactos/include/msvcrt/wine/cppexcept.h diff --git a/reactos/lib/msvcrt/wine/eh.h b/reactos/include/msvcrt/wine/eh.h similarity index 100% rename from reactos/lib/msvcrt/wine/eh.h rename to reactos/include/msvcrt/wine/eh.h diff --git a/reactos/lib/msvcrt/wine/msvcrt.h b/reactos/include/msvcrt/wine/msvcrt.h similarity index 100% rename from reactos/lib/msvcrt/wine/msvcrt.h rename to reactos/include/msvcrt/wine/msvcrt.h diff --git a/reactos/include/napi/dbg.h b/reactos/include/napi/dbg.h index d273e607f0a..2b0eccfd8c6 100644 --- a/reactos/include/napi/dbg.h +++ b/reactos/include/napi/dbg.h @@ -62,7 +62,7 @@ typedef struct _LPC_DBG_MESSAGE typedef struct _LPC_TERMINATION_MESSAGE { LPC_MESSAGE Header; - TIME CreationTime; + LARGE_INTEGER CreationTime; } LPC_TERMINATION_MESSAGE, *PLPC_TERMINATION_MESSAGE; #endif /* __INCLUDE_NAPI_DBG_H */ diff --git a/reactos/include/napi/shared_data.h b/reactos/include/napi/shared_data.h index acb1baa2956..10e5209dcb5 100644 --- a/reactos/include/napi/shared_data.h +++ b/reactos/include/napi/shared_data.h @@ -13,6 +13,8 @@ #define PF_PAE_ENABLED 9 #define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10 +#ifndef __ASM__ + typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE { StandardDesign, @@ -62,13 +64,15 @@ typedef struct _KUSER_SHARED_DATA { BOOLEAN SafeBootMode; ULONG TraceLogging; ULONGLONG Fill0; - ULONGLONG SystemCall[4]; + UCHAR SystemCall[16]; union { volatile KSYSTEM_TIME TickCount; volatile ULONG64 TickCountQuad; }; } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; +#endif + /* Values for DosDeviceDriveType */ #define DOSDEVICE_DRIVE_UNKNOWN 0 #define DOSDEVICE_DRIVE_CALCULATE 1 @@ -102,5 +106,7 @@ typedef struct _KUSER_SHARED_DATA { #define SharedUserData ((KUSER_SHARED_DATA * const)USER_SHARED_DATA) #endif +#define KUSER_SHARED_SYSCALL 0x7FFE0300 +#define KUSER_SHARED_SYSCALL_RET 0x7FFE0304 #endif /* __INCLUDE_NAPI_SHARED_DATA_H */ diff --git a/reactos/include/napi/teb.h b/reactos/include/napi/teb.h index c6f1ea00346..ed58fff818b 100644 --- a/reactos/include/napi/teb.h +++ b/reactos/include/napi/teb.h @@ -286,7 +286,7 @@ unsigned __gregister_get(unsigned const regnum); #define NtCurrentTeb() ((struct _TEB *)__gregister_get(13)) #else -#error Unsupported architecture or no architecture specified. +struct _TEB * NtCurrentTeb(void); #endif #endif diff --git a/reactos/include/napi/win32.h b/reactos/include/napi/win32.h index 3807f97b7af..fa740bd1eac 100644 --- a/reactos/include/napi/win32.h +++ b/reactos/include/napi/win32.h @@ -28,8 +28,8 @@ typedef struct _W32PROCESS LIST_ENTRY MenuListHead; FAST_MUTEX PrivateFontListLock; LIST_ENTRY PrivateFontListHead; - FAST_MUTEX CursorIconListLock; - LIST_ENTRY CursorIconListHead; + FAST_MUTEX DriverObjListLock; + LIST_ENTRY DriverObjListHead; struct _KBDTABLES* KeyboardLayout; ULONG Flags; LONG GDIObjects; diff --git a/reactos/include/ntdll/ldr.h b/reactos/include/ntdll/ldr.h index d002bc8e6da..05d2de392c2 100644 --- a/reactos/include/ntdll/ldr.h +++ b/reactos/include/ntdll/ldr.h @@ -1,9 +1,9 @@ #ifndef __NTOSKRNL_INCLUDE_INTERNAL_LDR_H #define __NTOSKRNL_INCLUDE_INTERNAL_LDR_H -#include #include #include +#include typedef NTSTATUS STDCALL_FUNC (*PEPFUNC)(PPEB); @@ -59,7 +59,7 @@ typedef struct _LDR_MODULE LIST_ENTRY InInitializationOrderModuleList; /* not used */ PVOID BaseAddress; ULONG EntryPoint; - ULONG SizeOfImage; + ULONG ResidentSize; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; @@ -69,7 +69,7 @@ typedef struct _LDR_MODULE ULONG CheckSum; ULONG TimeDateStamp; #if defined(DBG) || defined(KDBG) - IMAGE_SYMBOL_INFO SymbolInfo; + PROSSYM_INFO RosSymInfo; #endif /* KDBG */ } LDR_MODULE, *PLDR_MODULE; @@ -92,6 +92,9 @@ LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule); #endif +ULONG +LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders); + PEPFUNC LdrPEStartup (PVOID ImageBase, HANDLE SectionHandle, PLDR_MODULE* Module, @@ -102,7 +105,7 @@ NTSTATUS LdrMapSections(HANDLE ProcessHandle, PIMAGE_NT_HEADERS NTHeaders); NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle, PHANDLE NTDllSectionHandle); - +BOOLEAN LdrMappedAsDataFile(PVOID *BaseAddress); NTSTATUS STDCALL LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress); diff --git a/reactos/include/ntdll/ntdll.h b/reactos/include/ntdll/ntdll.h index 8c2aaeeb5cd..1cdacb5d863 100644 --- a/reactos/include/ntdll/ntdll.h +++ b/reactos/include/ntdll/ntdll.h @@ -17,7 +17,7 @@ #ifdef NDEBUG #if defined(__GNUC__) -#define TRACE_LDR(args...) if (NtGlobalFlag & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } +#define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } #define DPRINT(args...) #else #define DPRINT diff --git a/reactos/include/ntdll/rtl.h b/reactos/include/ntdll/rtl.h index 15bd0fd7455..7c8dbf4695a 100644 --- a/reactos/include/ntdll/rtl.h +++ b/reactos/include/ntdll/rtl.h @@ -17,6 +17,13 @@ extern "C" { #ifndef __USE_W32API +#define RTL_CONSTANT_STRING(__SOURCE_STRING__) \ +{ \ + sizeof(__SOURCE_STRING__) - sizeof((__SOURCE_STRING__)[0]), \ + sizeof(__SOURCE_STRING__), \ + (__SOURCE_STRING__) \ +} + typedef struct _DEBUG_BUFFER { HANDLE SectionHandle; @@ -99,8 +106,7 @@ typedef struct _CRITICAL_SECTION_DEBUG LIST_ENTRY ProcessLocksList; ULONG EntryCount; ULONG ContentionCount; - ULONG Depth; - PVOID OwnerBackTrace[ 5 ]; + PVOID Spare[2]; } CRITICAL_SECTION_DEBUG, *PCRITICAL_SECTION_DEBUG; @@ -114,9 +120,13 @@ typedef struct _CRITICAL_SECTION ULONG_PTR SpinCount; } CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; +#define RTL_CRITSECT_TYPE 0 + typedef CRITICAL_SECTION RTL_CRITICAL_SECTION; typedef PCRITICAL_SECTION PRTL_CRITICAL_SECTION; typedef LPCRITICAL_SECTION LPRTL_CRITICAL_SECTION; +typedef CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG; +typedef PCRITICAL_SECTION_DEBUG PRTL_CRITICAL_SECTION_DEBUG; #endif /* !__USE_W32API */ @@ -166,6 +176,41 @@ typedef struct _RTL_HANDLE_TABLE #define PDI_HEAP_BLOCKS 0x10 /* The heap blocks */ #define PDI_LOCKS 0x20 /* The locks created by the process */ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection +); + +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID +); + +VOID +STDCALL +RtlpFreeDebugInfo( + PRTL_CRITICAL_SECTION_DEBUG DebugInfo +); + +PRTL_CRITICAL_SECTION_DEBUG +STDCALL +RtlpAllocateDebugInfo( + VOID +); NTSTATUS STDCALL RtlAddAccessAllowedAceEx (IN OUT PACL Acl, @@ -190,20 +235,20 @@ RtlAddAuditAccessAceEx(IN OUT PACL Acl, IN BOOLEAN Success, IN BOOLEAN Failure); -VOID STDCALL -RtlDeleteCriticalSection (PCRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL +RtlDeleteCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); WCHAR STDCALL RtlDowncaseUnicodeChar(IN WCHAR Source); -VOID STDCALL -RtlEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL +RtlEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlInitializeCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); NTSTATUS STDCALL -RtlInitializeCriticalSectionAndSpinCount (PCRITICAL_SECTION CriticalSection, +RtlInitializeCriticalSectionAndSpinCount (PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount); NTSTATUS STDCALL @@ -211,11 +256,11 @@ RtlInt64ToUnicodeString (IN ULONGLONG Value, IN ULONG Base, PUNICODE_STRING String); -VOID STDCALL -RtlLeaveCriticalSection (PCRITICAL_SECTION CriticalSection); +NTSTATUS STDCALL +RtlLeaveCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); BOOLEAN STDCALL -RtlTryEnterCriticalSection (PCRITICAL_SECTION CriticalSection); +RtlTryEnterCriticalSection (PRTL_CRITICAL_SECTION CriticalSection); DWORD STDCALL RtlCompactHeap ( @@ -317,7 +362,7 @@ RtlGetCurrentDirectory_U ( ULONG STDCALL RtlGetFullPathName_U ( - WCHAR *dosname, + const WCHAR *dosname, ULONG size, WCHAR *buf, WCHAR **shortname @@ -744,12 +789,12 @@ InterlockedExchange ( LONG Value ); -PVOID +LONG STDCALL InterlockedCompareExchange ( - PVOID *Destination, - PVOID Exchange, - PVOID Comperand + PLONG Destination, + LONG Exchange, + LONG Comperand ); LONG @@ -759,6 +804,26 @@ InterlockedExchangeAdd ( LONG Increment ); +#ifndef InterlockedExchangePointer + #ifdef _WIN64 + #define InterlockedExchangePointer(Target, Value) \ + (PVOID)InterlockedExchange64((PLONGLONG)(Target), (LONGLONG)(Value)) + #else + #define InterlockedExchangePointer(Target, Value) \ + (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value)) + #endif +#endif + +#ifndef InterlockedCompareExchangePointer + #ifdef _WIN64 + #define InterlockedCompareExchangePointer(Target, Exchange, Comperand) \ + (PVOID)InterlockedCompareExchange64((PLONGLONG)(Target), (LONGLONG)(Exchange), (LONGLONG)(Comperand)) + #else + #define InterlockedCompareExchangePointer(Target, Exchange, Comperand) \ + (PVOID)InterlockedCompareExchange((PLONG)Target, (LONG)Exchange, (LONG)Comperand) + #endif +#endif + #endif /* __INTERLOCKED_DECLARED */ #endif /* __NTDRIVER__ */ diff --git a/reactos/include/ntos.h b/reactos/include/ntos.h index c4b3c1eeb19..96b6e6e3a9a 100644 --- a/reactos/include/ntos.h +++ b/reactos/include/ntos.h @@ -20,7 +20,6 @@ #include "ntos/gditypes.h" #include "ntos/fstypes.h" /* AG */ #include "ntos/heap.h" -#include "ntos/kdbgsyms.h" #include "ntos/keyboard.h" #include "ntos/minmax.h" #include "ntos/mm.h" @@ -61,7 +60,6 @@ #include "ntos/file.h" #include "ntos/gditypes.h" #include "ntos/heap.h" -#include "ntos/kdbgsyms.h" #include "ntos/keyboard.h" #include "ntos/minmax.h" #include "ntos/mm.h" diff --git a/reactos/include/ntos/kdbgsyms.h b/reactos/include/ntos/kdbgsyms.h deleted file mode 100644 index 9fd15094c5f..00000000000 --- a/reactos/include/ntos/kdbgsyms.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __KDBGSYMS_H -#define __KDBGSYMS_H - -#include - -typedef struct _IMAGE_SYMBOL_INFO -{ - ULONG_PTR ImageBase; - ULONG_PTR ImageSize; - PVOID FileBuffer; - PVOID SymbolsBase; - ULONG SymbolsLength; - PVOID SymbolStringsBase; - ULONG SymbolStringsLength; -} IMAGE_SYMBOL_INFO, *PIMAGE_SYMBOL_INFO; - -#endif /* __KDBGSYMS_H */ - diff --git a/reactos/include/ntos/mm.h b/reactos/include/ntos/mm.h index d6f763ca02e..ca752bca38e 100644 --- a/reactos/include/ntos/mm.h +++ b/reactos/include/ntos/mm.h @@ -62,7 +62,7 @@ #endif /* __USE_W32API */ -#define PAGE_ROUND_UP(x) ( (((ULONG)x)%PAGE_SIZE) ? ((((ULONG)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG)x) ) -#define PAGE_ROUND_DOWN(x) (((ULONG)x)&(~(PAGE_SIZE-1))) +#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)x)%PAGE_SIZE) ? ((((ULONG_PTR)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG_PTR)x) ) +#define PAGE_ROUND_DOWN(x) (((ULONG_PTR)x)&(~(PAGE_SIZE-1))) #endif /* __INCLUDE_MM_H */ diff --git a/reactos/include/ntos/ntdef.h b/reactos/include/ntos/ntdef.h index e9a6b6aa341..4b3eb851277 100644 --- a/reactos/include/ntos/ntdef.h +++ b/reactos/include/ntos/ntdef.h @@ -32,18 +32,45 @@ # define PROBE_ALIGNMENT(_s) TYPE_ALIGNMENT(DWORD) #endif + +#if defined(_MSC_VER) + #define Const64(a) (a##i64) + static __inline LARGE_INTEGER MK_LARGE_INTEGER(__int64 i) + { + LARGE_INTEGER li; + li.QuadPart = i; + return li; + } + #define INIT_LARGE_INTEGER(a) {{(ULONG)a, (LONG)(a>>32)}} +#elif defined (__GNUC__) + #define Const64(a) (a##LL) + #define MK_LARGE_INTEGER(a) ((LARGE_INTEGER)(LONGLONG)(a)) + #define INIT_LARGE_INTEGER(a) MK_LARGE_INTEGER(Const64(a)) +#endif + +#define LargeInteger0 MK_LARGE_INTEGER(0) + + +/* Compile time asserts */ +#define C_ASSERT(e) do{extern char __C_ASSERT__[(e)?1:-1]; (void)__C_ASSERT__;}while(0) + + /* Helpers for easy conversion to system time units (100ns) */ #define ABSOLUTE_TIME(wait) (wait) #define RELATIVE_TIME(wait) (-(wait)) -#define NANOS_TO_100NS(nanos) (((LONGLONG)(nanos)) / 100L) -#define MICROS_TO_100NS(micros) (((LONGLONG)(micros)) * NANOS_TO_100NS(1000L)) -#define MILLIS_TO_100NS(milli) (((LONGLONG)(milli)) * MICROS_TO_100NS(1000L)) -#define SECONDS_TO_100NS(seconds) (((LONGLONG)(seconds)) * MILLIS_TO_100NS(1000L)) +#define NANOS_TO_100NS(nanos) (((LONGLONG)(nanos)) / 100) +#define MICROS_TO_100NS(micros) (((LONGLONG)(micros)) * NANOS_TO_100NS(1000)) +#define MILLIS_TO_100NS(milli) (((LONGLONG)(milli)) * MICROS_TO_100NS(1000)) +#define SECONDS_TO_100NS(seconds) (((LONGLONG)(seconds)) * MILLIS_TO_100NS(1000)) +#define MINUTES_TO_100NS(minutes) (((LONGLONG)(minutes)) * SECONDS_TO_100NS(60)) +#define HOURS_TO_100NS(hours) (((LONGLONG)(hours)) * MINUTES_TO_100NS(60)) + + /* Helpers for enumarating lists */ #define LIST_FOR_EACH(entry, head) \ - for(entry = (head)->Flink; entry != (head); entry = entry->Flink) + for((entry) = (head)->Flink; (entry) != (head); (entry) = (entry)->Flink) /* Safe version which saves pointer to the next entry so the current ptr->field entry diff --git a/reactos/include/ntos/ntpnp.h b/reactos/include/ntos/ntpnp.h new file mode 100644 index 00000000000..bf551f71e08 --- /dev/null +++ b/reactos/include/ntos/ntpnp.h @@ -0,0 +1,257 @@ +/* + * ntpnp.h + * + * Plug-and-play interface routines + * + * Contributors: + * Created by Filip Navara + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __NTPNP_H +#define __NTPNP_H + +/* + * TODO: + * - Describe the undocumented GUIDs. + * - Finish the description of NtPlugPlayControl. + */ + +/* + * Undocumented GUIDs used by NtGetPlugPlayEvent. + */ + +DEFINE_GUID(GUID_DEVICE_STANDBY_VETOED, 0x03B21C13, 0x18D6, 0x11D3, 0x97, 0xDB, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_KERNEL_INITIATED_EJECT, 0x14689B54, 0x0703, 0x11D3, 0x97, 0xD2, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_THERMAL_ZONE, 0x4AFA3D51, 0x74A7, 0x11D0, 0xBE, 0x5E, 0x00, 0xA0, 0xC9, 0x06, 0x28, 0x57); +DEFINE_GUID(GUID_DEVICE_SYS_BUTTON, 0x4AFA3D53, 0x74A7, 0x11D0, 0xBE, 0x5E, 0x00, 0xA0, 0xC9, 0x06, 0x28, 0x57); +DEFINE_GUID(GUID_DEVICE_REMOVAL_VETOED, 0x60DBD5FA, 0xDDD2, 0x11D2, 0x97, 0xB8, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_HIBERNATE_VETOED, 0x61173AD9, 0x194F, 0x11D3, 0x97, 0xDC, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_BATTERY, 0x72631E54, 0x78A4, 0x11D0, 0xBC, 0xF7, 0x00, 0xAA, 0x00, 0xB7, 0xB3, 0x2A); +DEFINE_GUID(GUID_DEVICE_SAFE_REMOVAL, 0x8FBEF967, 0xD6C5, 0x11D2, 0x97, 0xB5, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +/* DEFINE_GUID(GUID_DEVICE_INTERFACE_ARRIVAL, 0xCB3A4004, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); */ +/* DEFINE_GUID(GUID_DEVICE_INTERFACE_REMOVAL, 0xCB3A4005, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); */ +DEFINE_GUID(GUID_DEVICE_ARRIVAL, 0xCB3A4009, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_ENUMERATED, 0xCB3A400A, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_ENUMERATE_REQUEST, 0xCB3A400B, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_START_REQUEST, 0xCB3A400C, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_REMOVE_PENDING, 0xCB3A400D, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_QUERY_AND_REMOVE, 0xCB3A400E, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_EJECT, 0xCB3A400F, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_NOOP, 0xCB3A4010, 0x46F0, 0x11D0, 0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F); +DEFINE_GUID(GUID_DEVICE_WARM_EJECT_VETOED, 0xCBF4C1F9, 0x18D5, 0x11D3, 0x97, 0xDB, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_SURPRISE_REMOVAL, 0xCE5AF000, 0x80DD, 0x11D2, 0xA8, 0x8D, 0x00, 0xA0, 0xC9, 0x69, 0x6B, 0x4B); +DEFINE_GUID(GUID_DEVICE_EJECT_VETOED, 0xCF7B71E8, 0xD8FD, 0x11D2, 0x97, 0xB5, 0x00, 0xA0, 0xC9, 0x40, 0x52, 0x2E); +DEFINE_GUID(GUID_DEVICE_EVENT_RBC, 0xD0744792, 0xA98E, 0x11D2, 0x91, 0x7A, 0x00, 0xA0, 0xC9, 0x06, 0x8F, 0xF3); + + +#ifndef __GUIDS_ONLY__ /* This is defined to build libwdmguid.a */ + +typedef enum _PLUGPLAY_EVENT_CATEGORY { + HardwareProfileChangeEvent, + TargetDeviceChangeEvent, + DeviceClassChangeEvent, + CustomDeviceEvent, + DeviceInstallEvent, + DeviceArrivalEvent, + PowerEvent, + VetoEvent, + BlockedDriverEvent, + MaxPlugEventCategory +} PLUGPLAY_EVENT_CATEGORY; + +typedef enum _PNP_VETO_TYPE { + PNP_VetoTypeUnknown, + PNP_VetoLegacyDevice, + PNP_VetoPendingClose, + PNP_VetoWindowsApp, + PNP_VetoWindowsService, + PNP_VetoOutstandingOpen, + PNP_VetoDevice, + PNP_VetoDriver, + PNP_VetoIllegalDeviceRequest, + PNP_VetoInsufficientPower, + PNP_VetoNonDisableable, + PNP_VetoLegacyDriver, + PNP_VetoInsufficientRights, +} PNP_VETO_TYPE; + +/* + * Plug and Play event structure used by NtGetPlugPlayEvent. + * + * EventGuid + * Can be one of the following values: + * GUID_HWPROFILE_QUERY_CHANGE + * GUID_HWPROFILE_CHANGE_CANCELLED + * GUID_HWPROFILE_CHANGE_COMPLETE + * GUID_TARGET_DEVICE_QUERY_REMOVE + * GUID_TARGET_DEVICE_REMOVE_CANCELLED + * GUID_TARGET_DEVICE_REMOVE_COMPLETE + * GUID_PNP_CUSTOM_NOTIFICATION + * GUID_PNP_POWER_NOTIFICATION + * GUID_DEVICE_* (see above) + * + * EventCategory + * Type of the event that happened. + * + * Result + * ? + * + * Flags + * ? + * + * TotalSize + * Size of the event block including the device IDs and other + * per category specific fields. + */ + +typedef struct _PLUGPLAY_EVENT_BLOCK { + GUID EventGuid; + PLUGPLAY_EVENT_CATEGORY EventCategory; + PULONG Result; + ULONG Flags; + ULONG TotalSize; + PDEVICE_OBJECT DeviceObject; + union { + struct { + GUID ClassGuid; + WCHAR SymbolicLinkName[ANYSIZE_ARRAY]; + } DeviceClass; + struct { + WCHAR DeviceIds[ANYSIZE_ARRAY]; + } TargetDevice; + struct { + WCHAR DeviceId[ANYSIZE_ARRAY]; + } InstallDevice; + struct { + PVOID NotificationStructure; + WCHAR DeviceIds[ANYSIZE_ARRAY]; + } CustomNotification; + struct { + PVOID Notification; + } ProfileNotification; + struct { + ULONG NotificationCode; + ULONG NotificationData; + } PowerNotification; + struct { + PNP_VETO_TYPE VetoType; + WCHAR DeviceIdVetoNameBuffer[ANYSIZE_ARRAY]; + } VetoNotification; + struct { + GUID BlockedDriverGuid; + } BlockedDriverNotification; + }; +} PLUGPLAY_EVENT_BLOCK, *PPLUGPLAY_EVENT_BLOCK; + +/* + * NtGetPlugPlayEvent + * + * Returns one Plug & Play event from a global queue. + * + * Parameters + * Reserved1 + * Reserved2 + * Always set to zero. + * + * Buffer + * The buffer that will be filled with the event information on + * successful return from the function. + * + * BufferSize + * Size of the buffer pointed by the Buffer parameter. If the + * buffer size is not large enough to hold the whole event + * information, error STATUS_BUFFER_TOO_SMALL is returned and + * the buffer remains untouched. + * + * Return Values + * STATUS_PRIVILEGE_NOT_HELD + * STATUS_BUFFER_TOO_SMALL + * STATUS_SUCCESS + * + * Remarks + * This function isn't multi-thread safe! + */ + +NTSTATUS STDCALL +NtGetPlugPlayEvent( + ULONG Reserved1, + ULONG Reserved2, + PPLUGPLAY_EVENT_BLOCK Buffer, + ULONG BufferSize); + +/* + * NtPlugPlayControl + * + * A function for doing various Plug & Play operations from user mode. + * + * Parameters + * ControlCode + * 0x00 Reenumerate device tree + * + * Buffer points to UNICODE_STRING decribing the instance + * path (like "HTREE\ROOT\0" or "Root\ACPI_HAL\0000"). For + * more information about instance paths see !devnode command + * in kernel debugger or look at "Inside Windows 2000" book, + * chapter "Driver Loading, Initialization, and Installation". + * + * 0x01 Register new device + * 0x02 Deregister device + * 0x03 Initialize device + * 0x04 Start device + * 0x06 Query and remove device + * 0x07 User response + * + * Called after processing the message from NtGetPlugPlayEvent. + * + * 0x08 Generate legacy device + * 0x09 Get interface device list + * 0x0A Get property data + * 0x0B Device class association (Registration) + * 0x0C Get related device + * 0x0D Get device interface alias + * 0x0E Get/set device status + * 0x0F Get device depth + * 0x10 Query device relations + * 0x11 Query target device relation + * 0x12 Query conflict list + * 0x13 Retrieve dock data + * 0x14 Reset device + * 0x15 Halt device + * 0x16 Get blocked driver data + * + * Buffer + * The buffer contains information that is specific to each control + * code. The buffer is read-only. + * + * BufferSize + * Size of the buffer pointed by the Buffer parameter. If the + * buffer size specifies incorrect value for specified control + * code, error ??? is returned. + * + * Return Values + * STATUS_PRIVILEGE_NOT_HELD + * STATUS_SUCCESS + * ... + */ + +#define PLUGPLAY_USER_RESPONSE 0x07 + +NTSTATUS STDCALL +NtPlugPlayControl( + ULONG ControlCode, + PVOID Buffer, + ULONG BufferSize); + +#endif /* __GUIDS_ONLY__ */ + +#endif /* __NTPNP_H */ diff --git a/reactos/include/ntos/obtypes.h b/reactos/include/ntos/obtypes.h index 63218cb77fa..9094b0688e6 100755 --- a/reactos/include/ntos/obtypes.h +++ b/reactos/include/ntos/obtypes.h @@ -35,23 +35,28 @@ typedef struct _OBJECT_NAME_INFORMATION } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; -typedef struct _OBJECT_TYPE_INFORMATION -{ - UNICODE_STRING Name; - ULONG ObjectCount; - ULONG ReferenceCount; - ULONG Reserved1[4]; - ULONG PeakObjectCount; - ULONG PeakHandleCount; - ULONG Reserved2[4]; - ULONG InvalidAttributes; - GENERIC_MAPPING GenericMapping; - ULONG ValidAccess; - UCHAR Unknown; - BOOLEAN MainitainHandleDatabase; - POOL_TYPE PoolType; - ULONG PagedPoolUsage; - ULONG NonPagedPoolUsage; +typedef struct _OBJECT_TYPE_INFORMATION { + UNICODE_STRING TypeName; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG PeakNumberOfObjects; + ULONG PeakNumberOfHandles; + ULONG PeakPagedPoolUsage; + ULONG PeakNonPagedPoolUsage; + ULONG PeakNamePoolUsage; + ULONG PeakHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccessMask; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + ULONG PoolType; + ULONG DefaultPagedPoolCharge; + ULONG DefaultNonPagedPoolCharge; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; @@ -68,168 +73,9 @@ typedef struct _OBJECT_HANDLE_ATTRIBUTE_INFORMATION BOOLEAN ProtectFromClose; } OBJECT_HANDLE_ATTRIBUTE_INFORMATION, *POBJECT_HANDLE_ATTRIBUTE_INFORMATION; -#endif /* __USE_W32API */ - -typedef struct _OBJECT_TYPE -{ - /* - * PURPOSE: Tag to be used when allocating objects of this type - */ - ULONG Tag; - - /* - * PURPOSE: Name of the type - */ - UNICODE_STRING TypeName; - - /* - * PURPOSE: Total number of objects of this type - */ - ULONG TotalObjects; - - /* - * PURPOSE: Total number of handles of this type - */ - ULONG TotalHandles; - - /* - * PURPOSE: Maximum objects of this type - */ - ULONG MaxObjects; - - /* - * PURPOSE: Maximum handles of this type - */ - ULONG MaxHandles; - - /* - * PURPOSE: Paged pool charge - */ - ULONG PagedPoolCharge; - - /* - * PURPOSE: Nonpaged pool charge - */ - ULONG NonpagedPoolCharge; - - /* - * PURPOSE: Mapping of generic access rights - */ - PGENERIC_MAPPING Mapping; - - /* - * PURPOSE: Dumps the object - * NOTE: To be defined - */ - VOID STDCALL_FUNC (*Dump)(VOID); - - /* - * PURPOSE: Opens the object - * NOTE: To be defined - */ - VOID STDCALL_FUNC (*Open)(VOID); - - /* - * PURPOSE: Called to close an object if OkayToClose returns true - */ - VOID STDCALL_FUNC (*Close)(PVOID ObjectBody, - ULONG HandleCount); - - /* - * PURPOSE: Called to delete an object when the last reference is removed - */ - VOID STDCALL_FUNC (*Delete)(PVOID ObjectBody); - - /* - * PURPOSE: Called when an open attempts to open a file apparently - * residing within the object - * RETURNS - * STATUS_SUCCESS NextObject was found - * STATUS_UNSUCCESSFUL NextObject not found - * STATUS_REPARSE Path changed, restart parsing the path - */ - NTSTATUS STDCALL_FUNC (*Parse)(PVOID ParsedObject, - PVOID *NextObject, - PUNICODE_STRING FullPath, - PWSTR *Path, - ULONG Attributes); - - /* - * PURPOSE: Called to set, query, delete or assign a security-descriptor - * to the object - * RETURNS - * STATUS_SUCCESS NextObject was found - */ - NTSTATUS STDCALL_FUNC (*Security)(PVOID ObjectBody, - SECURITY_OPERATION_CODE OperationCode, - SECURITY_INFORMATION SecurityInformation, - PSECURITY_DESCRIPTOR SecurityDescriptor, - PULONG BufferLength); - - /* - * PURPOSE: Called to query the name of the object - * RETURNS - * STATUS_SUCCESS NextObject was found - */ - NTSTATUS STDCALL_FUNC (*QueryName)(PVOID ObjectBody, - POBJECT_NAME_INFORMATION ObjectNameInfo, - ULONG Length, - PULONG ReturnLength); - - /* - * PURPOSE: Called when a process asks to close the object - */ - VOID STDCALL_FUNC (*OkayToClose)(VOID); - - NTSTATUS STDCALL_FUNC (*Create)(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - struct _OBJECT_ATTRIBUTES* ObjectAttributes); - - VOID STDCALL_FUNC (*DuplicationNotify)(PEPROCESS DuplicateTo, - PEPROCESS DuplicateFrom, - PVOID Object); -} OBJECT_TYPE; - -#ifndef __USE_W32API typedef struct _OBJECT_TYPE *POBJECT_TYPE; -#endif /* __USE_W32API */ - - -typedef struct _OBJECT_HEADER -/* - * PURPOSE: Header for every object managed by the object manager - */ -{ - UNICODE_STRING Name; - LIST_ENTRY Entry; - LONG RefCount; - LONG HandleCount; - BOOLEAN CloseInProcess; - BOOLEAN Permanent; - BOOLEAN Inherit; - struct _DIRECTORY_OBJECT* Parent; - POBJECT_TYPE ObjectType; - PSECURITY_DESCRIPTOR SecurityDescriptor; - - /* - * PURPOSE: Object type - * NOTE: This overlaps the first member of the object body - */ - CSHORT Type; - - /* - * PURPOSE: Object size - * NOTE: This overlaps the second member of the object body - */ - CSHORT Size; - - -} OBJECT_HEADER, *POBJECT_HEADER; - -#ifndef __USE_W32API typedef struct _OBJECT_ATTRIBUTES { @@ -237,8 +83,8 @@ typedef struct _OBJECT_ATTRIBUTES HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; - SECURITY_DESCRIPTOR *SecurityDescriptor; - SECURITY_QUALITY_OF_SERVICE *SecurityQualityOfService; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; #endif /* __USE_W32API */ diff --git a/reactos/include/ntos/ps.h b/reactos/include/ntos/ps.h index 2c225c8c673..9bdfad8e866 100644 --- a/reactos/include/ntos/ps.h +++ b/reactos/include/ntos/ps.h @@ -47,6 +47,7 @@ /* Thread access rights */ #define THREAD_TERMINATE (0x0001L) #define THREAD_SUSPEND_RESUME (0x0002L) +#define THREAD_ALERT (0x0004L) #define THREAD_GET_CONTEXT (0x0008L) #define THREAD_SET_CONTEXT (0x0010L) #define THREAD_SET_INFORMATION (0x0020L) @@ -69,6 +70,7 @@ #define PROCESS_SET_QUOTA (0x0100L) #define PROCESS_SET_INFORMATION (0x0200L) #define PROCESS_QUERY_INFORMATION (0x0400L) +#define PROCESS_SET_PORT (0x0800L) #define PROCESS_ALL_ACCESS (0x1f0fffL) diff --git a/reactos/include/ntos/rtl.h b/reactos/include/ntos/rtl.h index 4d9cea4e5bb..6623ea51f6a 100755 --- a/reactos/include/ntos/rtl.h +++ b/reactos/include/ntos/rtl.h @@ -112,7 +112,7 @@ static __inline VOID InsertHeadList( IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) -{ +{ PLIST_ENTRY OldFlink; OldFlink = ListHead->Flink; Entry->Flink = OldFlink; @@ -140,7 +140,7 @@ static __inline VOID InsertTailList( IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry) -{ +{ PLIST_ENTRY OldBlink; OldBlink = ListHead->Blink; Entry->Flink = ListHead; @@ -458,8 +458,7 @@ RtlZeroMemory (PVOID Destination, ULONG Length); #define RTL_REGISTRY_WINDOWS_NT 3 #define RTL_REGISTRY_DEVICEMAP 4 #define RTL_REGISTRY_USER 5 -#define RTL_REGISTRY_ENUM 6 /* ReactOS specific: Used internally in kernel only */ -#define RTL_REGISTRY_MAXIMUM 7 +#define RTL_REGISTRY_MAXIMUM 6 #define RTL_REGISTRY_HANDLE 0x40000000 #define RTL_REGISTRY_OPTIONAL 0x80000000 @@ -522,7 +521,7 @@ PushEntryList ( NTSTATUS STDCALL RtlAbsoluteToSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, - PSECURITY_DESCRIPTOR RelSD, + PSECURITY_DESCRIPTOR_RELATIVE RelSD, PULONG BufferLength); NTSTATUS STDCALL @@ -853,6 +852,10 @@ NTSTATUS STDCALL RtlCreateSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Revision); +NTSTATUS STDCALL +RtlCreateSecurityDescriptorRelative (PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, + ULONG Revision); + NTSTATUS STDCALL RtlCreateSystemVolumeInformationFolder( @@ -878,6 +881,12 @@ RtlCustomCPToUnicodeN ( ULONG CustomSize ); +BOOLEAN STDCALL +RtlCutoverTimeToSystemTime(IN PTIME_FIELDS CutoverTimeFields, + OUT PLARGE_INTEGER SystemTime, + IN PLARGE_INTEGER CurrentTime, + IN BOOLEAN ThisYearsCutoverOnly); + NTSTATUS STDCALL RtlDecompressBuffer(IN USHORT CompressionFormat, OUT PUCHAR UncompressedBuffer, @@ -1310,6 +1319,12 @@ RtlGetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Group, PBOOLEAN GroupDefaulted); +NTSTATUS STDCALL +RtlGetLastNtStatus(VOID); + +ULONG STDCALL +RtlGetLastWin32Error(VOID); + NTSTATUS STDCALL RtlGetNextRange (IN OUT PRTL_RANGE_LIST_ITERATOR Iterator, OUT PRTL_RANGE *Range, @@ -1332,6 +1347,10 @@ RtlGetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PACL* Sacl, PBOOLEAN SaclDefaulted); +BOOLEAN STDCALL +RtlGetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl); + NTSTATUS STDCALL RtlGetSetBootStatusData( @@ -1990,7 +2009,7 @@ RtlLookupElementGenericTableFullAvl ( NTSTATUS STDCALL RtlMakeSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, - PSECURITY_DESCRIPTOR RelSD, + PSECURITY_DESCRIPTOR_RELATIVE RelSD, PULONG BufferLength); VOID STDCALL @@ -2205,6 +2224,9 @@ RtlReserveChunk ( VOID STDCALL RtlResetRtlTranslations (IN PNLSTABLEINFO NlsTable); +VOID STDCALL +RtlRestoreLastWin32Error(IN ULONG Error); + /* * VOID * RtlRetrieveUlong ( @@ -2213,7 +2235,7 @@ RtlResetRtlTranslations (IN PNLSTABLEINFO NlsTable); * ); */ #define RtlRetrieveUlong(DestAddress,SrcAddress) \ - if ((ULONG)(SrcAddress) & LONG_MASK) \ + if ((ULONG_PTR)(SrcAddress) & LONG_MASK) \ { \ ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \ ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \ @@ -2233,7 +2255,7 @@ RtlResetRtlTranslations (IN PNLSTABLEINFO NlsTable); * ); */ #define RtlRetrieveUshort(DestAddress,SrcAddress) \ - if ((ULONG)(SrcAddress) & SHORT_MASK) \ + if ((ULONG_PTR)(SrcAddress) & SHORT_MASK) \ { \ ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \ ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \ @@ -2252,7 +2274,7 @@ RtlSecondsSince1980ToTime (ULONG SecondsSince1980, PLARGE_INTEGER Time); NTSTATUS STDCALL -RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR RelSD, +RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR_RELATIVE RelSD, PSECURITY_DESCRIPTOR AbsSD, PULONG AbsSDSize, PACL Dacl, @@ -2267,13 +2289,18 @@ RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR RelSD, NTSTATUS STDCALL RtlSelfRelativeToAbsoluteSD2( - PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, + PSECURITY_DESCRIPTOR_RELATIVE SelfRelativeSecurityDescriptor, PULONG BufferSize ); VOID STDCALL RtlSetAllBits (IN PRTL_BITMAP BitMapHeader); +NTSTATUS STDCALL +RtlSetAttributesSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL Control, + OUT PULONG Revision); + VOID STDCALL RtlSetBit ( @@ -2289,6 +2316,11 @@ RtlSetBits ( ULONG NumberToSet ); +NTSTATUS STDCALL +RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); + NTSTATUS STDCALL RtlSetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN DaclPresent, @@ -2300,6 +2332,18 @@ RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Group, BOOLEAN GroupDefaulted); +NTSTATUS STDCALL +RtlSetInformationAcl (PACL Acl, + PVOID Information, + ULONG InformationLength, + ACL_INFORMATION_CLASS InformationClass); + +VOID STDCALL +RtlSetLastWin32Error(IN ULONG Error); + +VOID STDCALL +RtlSetLastWin32ErrorAndNtStatusFromNtStatus(IN NTSTATUS Status); + NTSTATUS STDCALL RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Owner, @@ -2311,11 +2355,9 @@ RtlSetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PACL Sacl, BOOLEAN SaclDefaulted); -NTSTATUS STDCALL -RtlSetInformationAcl (PACL Acl, - PVOID Information, - ULONG InformationLength, - ACL_INFORMATION_CLASS InformationClass); +VOID STDCALL +RtlSetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl); NTSTATUS STDCALL RtlSetTimeZoneInformation (IN OUT PTIME_ZONE_INFORMATION TimeZoneInformation); @@ -2341,10 +2383,10 @@ RtlSplay ( * ); */ #define RtlStoreUlong(Address,Value) \ - if ((ULONG)(Address) & LONG_MASK) \ + if ((ULONG_PTR)(Address) & LONG_MASK) \ { \ ((PUCHAR)(Address))[LONG_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ - ((PUCHAR)(Address))[LONG_3RD_MOST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ + ((PUCHAR)(Address))[LONG_3RD_MOST_SIGNIFICANT_BIT]=(UCHAR)(SECONDBYTE(Value)); \ ((PUCHAR)(Address))[LONG_2ND_MOST_SIGNIFICANT_BIT]=(UCHAR)(THIRDBYTE(Value)); \ ((PUCHAR)(Address))[LONG_MOST_SIGNIFICANT_BIT]=(UCHAR)(FOURTHBYTE(Value)); \ } \ @@ -2361,7 +2403,7 @@ RtlSplay ( * ); */ #define RtlStoreUshort(Address,Value) \ - if ((ULONG)(Address) & SHORT_MASK) \ + if ((ULONG_PTR)(Address) & SHORT_MASK) \ { \ ((PUCHAR)(Address))[SHORT_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ ((PUCHAR)(Address))[SHORT_MOST_SIGNIFICANT_BIT]=(UCHAR)(SECONDBYTE(Value)); \ @@ -2641,7 +2683,7 @@ RtlValidateHeap ( BOOLEAN STDCALL RtlValidRelativeSecurityDescriptor ( - IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, + IN PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptorInput, IN ULONG SecurityDescriptorLength, IN SECURITY_INFORMATION RequiredInformation ); diff --git a/reactos/include/ntos/security.h b/reactos/include/ntos/security.h index 829a96ea308..e4b76e917e2 100644 --- a/reactos/include/ntos/security.h +++ b/reactos/include/ntos/security.h @@ -36,13 +36,14 @@ /* Security descriptor control. */ #define SECURITY_DESCRIPTOR_REVISION (1) #define SECURITY_DESCRIPTOR_MIN_LENGTH (20) -#define SE_OWNER_DEFAULTED (1) -#define SE_GROUP_DEFAULTED (2) -#define SE_DACL_PRESENT (4) -#define SE_DACL_DEFAULTED (8) -#define SE_SACL_PRESENT (16) -#define SE_SACL_DEFAULTED (32) -#define SE_SELF_RELATIVE (32768) +#define SE_OWNER_DEFAULTED (0x0001) +#define SE_GROUP_DEFAULTED (0x0002) +#define SE_DACL_PRESENT (0x0004) +#define SE_DACL_DEFAULTED (0x0008) +#define SE_SACL_PRESENT (0x0010) +#define SE_SACL_DEFAULTED (0x0020) +#define SE_RM_CONTROL_VALID (0x4000) +#define SE_SELF_RELATIVE (0x8000) #endif /* This is defined in the Win 32 API headers as something else: */ @@ -74,6 +75,11 @@ typedef struct _SECURITY_DESCRIPTOR_CONTEXT #ifndef __USE_W32API +#define SYSTEM_LUID { 0x3E7, 0x0 } +#define ANONYMOUS_LOGON_LUID { 0x3e6, 0x0 } +#define LOCALSERVICE_LUID { 0x3e5, 0x0 } +#define NETWORKSERVICE_LUID { 0x3e4, 0x0 } + /* SID Auhority */ #define SECURITY_NULL_SID_AUTHORITY {0,0,0,0,0,0} #define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} @@ -227,7 +233,9 @@ typedef struct _SID UCHAR SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; ULONG SubAuthority[1]; -} SID, *PSID; +} SID, *PISID; + +typedef PVOID PSID; typedef struct _ACL { @@ -275,6 +283,17 @@ typedef struct _SECURITY_DESCRIPTOR PACL Dacl; } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; +typedef struct _SECURITY_DESCRIPTOR_RELATIVE +{ + UCHAR Revision; + UCHAR Sbz1; + SECURITY_DESCRIPTOR_CONTROL Control; + ULONG Owner; + ULONG Group; + ULONG Sacl; + ULONG Dacl; +} SECURITY_DESCRIPTOR_RELATIVE, *PSECURITY_DESCRIPTOR_RELATIVE; + typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; diff --git a/reactos/include/ntos/types.h b/reactos/include/ntos/types.h index f3a0973cc24..0ee104f787c 100644 --- a/reactos/include/ntos/types.h +++ b/reactos/include/ntos/types.h @@ -517,6 +517,9 @@ typedef struct _LOADER_PARAMETER_BLOCK ULONG DrivesAddr; ULONG ConfigTable; ULONG BootLoaderName; + ULONG PageDirectoryStart; + ULONG PageDirectoryEnd; + ULONG KernelBase; } LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK; typedef enum _KAPC_ENVIRONMENT diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index dddce95cf28..476e5822115 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -1485,14 +1485,14 @@ NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle, * IoStatusBlock = Caller should supply storage for * IoControlCode = Contains the File System Control command. This is an * index to the structures in InputBuffer and OutputBuffer. - * FSCTL_GET_RETRIEVAL_POINTERS MAPPING_PAIR - * FSCTL_GET_RETRIEVAL_POINTERS GET_RETRIEVAL_DESCRIPTOR - * FSCTL_GET_VOLUME_BITMAP BITMAP_DESCRIPTOR - * FSCTL_MOVE_FILE MOVEFILE_DESCRIPTOR + * FSCTL_GET_RETRIEVAL_POINTERS [Input/Output] RETRIEVAL_POINTERS_BUFFER + * FSCTL_GET_VOLUME_BITMAP [Input] STARTING_LCN_INPUT_BUFFER + * FSCTL_GET_VOLUME_BITMAP [Output] VOLUME_BITMAP_BUFFER + * FSCTL_MOVE_FILE [Input] MOVE_FILE_DATA * - * InputBuffer = Caller should supply storage for input buffer if FCTL expects one. + * InputBuffer = Caller should supply storage for input buffer if FSCTL expects one. * InputBufferSize = Size of the input bufffer - * OutputBuffer = Caller should supply storage for output buffer if FCTL expects one. + * OutputBuffer = Caller should supply storage for output buffer if FSCTL expects one. * OutputBufferSize = Size of the input bufffer * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES | * STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST ] @@ -1887,10 +1887,10 @@ NtNotifyChangeKey( IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, - OUT PVOID ChangeBuffer, + IN BOOLEAN WatchSubtree, + OUT PVOID Buffer, IN ULONG Length, - IN BOOLEAN WatchSubtree + IN BOOLEAN Asynchronous ); NTSTATUS @@ -1902,10 +1902,10 @@ ZwNotifyChangeKey( IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, - OUT PVOID ChangeBuffer, + IN BOOLEAN WatchSubtree, + OUT PVOID Buffer, IN ULONG Length, - IN BOOLEAN WatchSubtree + IN BOOLEAN Asynchronous ); /* @@ -2205,14 +2205,14 @@ ZwOpenSection( NTSTATUS STDCALL NtOpenSemaphore( - IN HANDLE SemaphoreHandle, + OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAcces, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTSTATUS STDCALL ZwOpenSemaphore( - IN HANDLE SemaphoreHandle, + OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAcces, IN POBJECT_ATTRIBUTES ObjectAttributes ); @@ -2702,7 +2702,7 @@ ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, FileNamesInformation FILE_NAMES_INFORMATION FileDispositionInformation FILE_DISPOSITION_INFORMATION FilePositionInformation FILE_POSITION_INFORMATION - FileFullEaInformation FILE_FULL_EA_INFORMATION + FileFullEaInformation FILE_FULL_EA_INFORMATION FileModeInformation FILE_MODE_INFORMATION FileAlignmentInformation FILE_ALIGNMENT_INFORMATION FileAllInformation FILE_ALL_INFORMATION @@ -2715,7 +2715,7 @@ ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, FilePipeRemoteInformation FileMailslotQueryInformation FileMailslotSetInformation - FileCompressionInformation FILE_COMPRESSION_INFORMATION + FileCompressionInformation FILE_COMPRESSION_INFORMATION FileCopyOnWriteInformation FileCompletionInformation IO_COMPLETION_CONTEXT FileMoveClusterInformation @@ -2728,7 +2728,7 @@ ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, FileContentIndexInformation FileInheritContentIndexInformation FileOleInformation - FileMaximumInformation + FileMaximumInformation * REMARK: * This procedure maps to the win32 GetShortPathName, GetLongPathName, @@ -3014,8 +3014,8 @@ ZwQueryMutant( /* * FUNCTION: Queries the system ( high-resolution ) performance counter. * ARGUMENTS: - * Counter = Performance counter - * Frequency = Performance frequency + * PerformanceCounter = Performance counter + * PerformanceFrequency = Performance frequency * REMARKS: This procedure queries a tick count faster than 10ms ( The resolution for Intel®-based CPUs is about 0.8 microseconds.) This procedure maps to the win32 QueryPerformanceCounter, QueryPerformanceFrequency @@ -3025,15 +3025,15 @@ ZwQueryMutant( NTSTATUS STDCALL NtQueryPerformanceCounter( - IN PLARGE_INTEGER Counter, - IN PLARGE_INTEGER Frequency + OUT PLARGE_INTEGER PerformanceCounter, + OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL ); NTSTATUS STDCALL ZwQueryPerformanceCounter( - IN PLARGE_INTEGER Counter, - IN PLARGE_INTEGER Frequency + OUT PLARGE_INTEGER PerformanceCounter, + OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL ); /* @@ -3107,19 +3107,19 @@ ZwQuerySymbolicLinkObject( NTSTATUS STDCALL NtQuerySystemEnvironmentValue( - IN PUNICODE_STRING Name, - OUT PVOID Value, - ULONG Length, - PULONG ReturnLength + IN PUNICODE_STRING VariableName, + OUT PWCHAR ValueBuffer, + IN ULONG ValueBufferLength, + OUT PULONG ReturnLength OPTIONAL ); NTSTATUS STDCALL ZwQuerySystemEnvironmentValue( - IN PUNICODE_STRING Name, - OUT PVOID Value, - ULONG Length, - PULONG ReturnLength + IN PUNICODE_STRING VariableName, + OUT PWCHAR ValueBuffer, + IN ULONG ValueBufferLength, + OUT PULONG ReturnLength OPTIONAL ); @@ -4929,21 +4929,6 @@ ZwYieldExecution( VOID ); -/* --- PLUG AND PLAY --- */ - -NTSTATUS -STDCALL -NtPlugPlayControl (DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3); - -NTSTATUS -STDCALL -NtGetPlugPlayEvent (ULONG Reserved1, - ULONG Reserved2, - PVOID Buffer, - ULONG BufferLength); - /* --- POWER MANAGEMENT --- */ #ifndef __USE_W32API @@ -5027,12 +5012,6 @@ NtSetLdtEntries (ULONG Selector1, ULONG Selector2, LDT_ENTRY LdtEntry2); -NTSTATUS -STDCALL -NtQueryOleDirectoryFile ( - VOID - ); - /* * FUNCTION: Checks a clients access rights to a object * ARGUMENTS: @@ -5240,8 +5219,8 @@ NtCreateThread( NTSTATUS STDCALL NtDelayExecution( - IN ULONG Alertable, - IN LARGE_INTEGER *Interval + IN BOOLEAN Alertable, + IN PLARGE_INTEGER DelayInterval ); /* @@ -6439,7 +6418,7 @@ NTSTATUS STDCALL ZwDelayExecution( IN BOOLEAN Alertable, - IN TIME *Interval + IN PLARGE_INTEGER DelayInterval ); /* diff --git a/reactos/include/ntos/zwtypes.h b/reactos/include/ntos/zwtypes.h index 9ebd6510a4f..067ed8bb132 100755 --- a/reactos/include/ntos/zwtypes.h +++ b/reactos/include/ntos/zwtypes.h @@ -684,8 +684,8 @@ typedef struct _PROCESS_BASIC_INFORMATION PPEB PebBaseAddress; KAFFINITY AffinityMask; KPRIORITY BasePriority; - ULONG UniqueProcessId; - ULONG InheritedFromUniqueProcessId; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; // Information class 1 @@ -729,10 +729,10 @@ typedef struct _VM_COUNTERS_ // Information class 4 typedef struct _KERNEL_USER_TIMES { - TIME CreateTime; - TIME ExitTime; - TIME KernelTime; - TIME UserTime; + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; } KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; // Information class 9 @@ -1111,28 +1111,17 @@ typedef struct _FILE_NOTIFY_INFORMATION { #define FSCTL_GET_RETRIEVAL_POINTERS 0x90073 #define FSCTL_MOVE_FILE 0x90074 -typedef struct _MAPPING_PAIR -{ - ULONGLONG Vcn; - ULONGLONG Lcn; -} MAPPING_PAIR, *PMAPPING_PAIR; - -typedef struct _GET_RETRIEVAL_DESCRIPTOR -{ - ULONG NumberOfPairs; - ULONGLONG StartVcn; - MAPPING_PAIR Pair[0]; // variable size -} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR; - -typedef struct _MOVEFILE_DESCRIPTOR -{ - HANDLE FileHandle; - ULONG Reserved; - LARGE_INTEGER StartVcn; - LARGE_INTEGER TargetLcn; - ULONG NumVcns; - ULONG Reserved1; -} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR; +/* Structure copied from ntifs.h (Must be in sync!) */ +#include +typedef struct _RETRIEVAL_POINTERS_BUFFER { + ULONG ExtentCount; + LARGE_INTEGER StartingVcn; + struct { + LARGE_INTEGER NextVcn; + LARGE_INTEGER Lcn; + } Extents[1]; +} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; +#include typedef struct _SECTION_BASIC_INFORMATION { @@ -1324,13 +1313,13 @@ typedef struct _SYSTEM_PROCESSES_NT4 SIZE_T NextEntryDelta; ULONG ThreadCount; ULONG Reserved1[6]; - TIME CreateTime; - TIME UserTime; - TIME KernelTime; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; + HANDLE ProcessId; + HANDLE InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; @@ -1342,13 +1331,13 @@ typedef struct _SYSTEM_PROCESSES_NT5 SIZE_T NextEntryDelta; ULONG ThreadCount; ULONG Reserved1[6]; - TIME CreateTime; - TIME UserTime; - TIME KernelTime; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; + HANDLE ProcessId; + HANDLE InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; @@ -1659,11 +1648,27 @@ typedef enum _OBJECT_INFORMATION_CLASS // directory information -typedef struct _DIRECTORY_BASIC_INFORMATION +typedef struct _OBJECT_DIRECTORY_INFORMATION { UNICODE_STRING ObjectName; UNICODE_STRING ObjectTypeName; // Directory, Device ... -} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; + + +/* system battery state */ +typedef struct _SYSTEM_BATTERY_STATE { + BOOLEAN AcOnLine; + BOOLEAN BatteryPresent; + BOOLEAN Charging; + BOOLEAN Discharging; + BOOLEAN Spare1[4]; + ULONG MaxCapacity; + ULONG RemainingCapacity; + ULONG Rate; + ULONG EstimatedTime; + ULONG DefaultAlert1; + ULONG DefaultAlert2; +} SYSTEM_BATTERY_STATE, *PSYSTEM_BATTERY_STATE; // power information levels @@ -1704,14 +1709,6 @@ typedef enum _POWER_INFORMATION_LEVEL { #define FSCTL_READ_MFT_RECORD 0x90068 // NTFS only -typedef struct _BITMAP_DESCRIPTOR -{ - ULONGLONG StartLcn; - ULONGLONG ClustersToEndOfVol; - BYTE Map[0]; // variable size -} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR; - - //typedef enum _TIMER_TYPE //{ // NotificationTimer, diff --git a/reactos/include/pseh/framebased.h b/reactos/include/pseh/framebased.h index 8a913c6435e..51823e0091d 100644 --- a/reactos/include/pseh/framebased.h +++ b/reactos/include/pseh/framebased.h @@ -176,11 +176,11 @@ static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler #define _SEH_TRY_FILTER_FINALLY(FILTER_, FINALLY_) \ { \ - _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_); \ - \ _SEHFrame_t * _SEHFrame; \ volatile _SEHPortableFrame_t * _SEHPortableFrame; \ \ + _SEH_DECLARE_HANDLERS(FILTER_, FINALLY_); \ + \ _SEHFrame = _alloca(sizeof(_SEHFrame_t)); \ _SEHFrame->SEH_Header.SPF_Handlers = &_SEHHandlers; \ _SEHFrame->SEH_Locals = &_SEHLocals; \ diff --git a/reactos/include/pseh/prettybased.h b/reactos/include/pseh/prettybased.h new file mode 100644 index 00000000000..0991a3e40fa --- /dev/null +++ b/reactos/include/pseh/prettybased.h @@ -0,0 +1,299 @@ +/* + Copyright (c) 2004 KJK::Hyperion + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +/* +Pretty PSEH + +Made to be macro compatible with ms seh syntax and to be pretty, having the +finally block inline etc. Being pretty is not cheap. PPSEH has more +overhead than PSEH, thou mostly during exception/unwinding. Normal execution +only add the overhead of one setjmp, and only in the try/finally case. +PPSEH is probably much less portable than PSEH also..... + +ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT!ALERT! +-must always use non-native NLG cause a special version of longjmp (which doesn't +restore esp) is needed + +-compiler must use ebp as stack frame pointer, cause the finally block rely +on this to access external variables + +-all external variables that are used in the except/finally block MUST be volatile +to prevent variables from being optimized into registers. +See: http://alphalinux.org/archives/axp-list/1998/February1998/0330.html + +-you can't use return within a try/except/finally block + +-you can't use __LEAVE within a (for/do/while) loop. it will only leave the loop +and not the try-block itself + + +USAGE: + +__TRY{ + __LEAVE; +} +__EXCEPT(_SEH_STATIC_FILTER(EXCEPTION_EXECUTE_HANDLER)){ +} +__ENDTRY; + + +__TRY{ +} +__FINALLY{ +} +__ENDTRY; + + +_SEH_FILTER(filter){ + return EXCEPTION_EXECUTE_HANDLER; +} +__TRY2{ +} +__EXCEPT2(filter){ +} +__FINALLY2{ +} +__ENDTRY2; + + + +-Gunnar + +*/ + + +#ifndef KJK_PPSEH_FRAMEBASED_H_ +#define KJK_PPSEH_FRAMEBASED_H_ + +#include +#include +#include + +#ifndef offsetof +# include +#endif + +/* +Must always use non-native NLG since we need a special version of longjmp which does +not restore esp +*/ +#include + + +typedef struct __SEHFrame +{ + _SEHPortableFrame_t SEH_Header; + _SEHJmpBuf_t SEH_JmpBuf; + _SEHJmpBuf_t* SEH_JmpRetPtr; +} +_SEHFrame_t; + +/* + Note: just define __inline to an empty symbol if your C compiler doesn't + support it +*/ +#ifdef __cplusplus +# ifndef __inline +# define __inline inline +# endif +#endif + + +/* FILTER FUNCTIONS */ +/* Declares a filter function's prototype */ +#define _SEH_FILTER(NAME_) \ + long __stdcall NAME_ \ + ( \ + struct _EXCEPTION_POINTERS * _SEHExceptionPointers, \ + struct __SEHPortableFrame * _SEHPortableFrame \ + ) + + +/* Declares a static filter */ +#define _SEH_STATIC_FILTER(ACTION_) ((_SEHFilter_t)((ACTION_) + 2)) + + +static __declspec(noreturn) __inline void __stdcall _SEHCompilerSpecificHandler +( + _SEHPortableFrame_t * frame +) +{ + _SEHFrame_t * myframe; + myframe = (_SEHFrame_t *)(((char *)frame) - offsetof(_SEHFrame_t, SEH_Header)); + _SEHLongJmp(myframe->SEH_JmpBuf, 1); +} + + + +void __stdcall _FinallyPretty +( + struct __SEHPortableFrame * frame +) +{ + _SEHFrame_t * myframe; + _SEHJmpBuf_t jmpRetBuf; + + myframe = (_SEHFrame_t *)(((char *)frame) - offsetof(_SEHFrame_t, SEH_Header)); + + if(_SEHSetJmp(jmpRetBuf) == 0) + { + myframe->SEH_JmpRetPtr = &jmpRetBuf; + _SEHLongJmp_KeepEsp(myframe->SEH_JmpBuf, 2); + } +} + + + +#define ___EXCEPT_DUAL(filter) \ + } while(0); \ + \ + _SEHLeave(&_SEHFrame->SEH_Header); \ + } \ + else \ + { \ + _SEHHandlers.SH_Filter = (filter); \ + _SEHHandlers.SH_Finally = _FinallyPretty; \ + \ + if(_loop == 2 || (_ret = _SEHSetJmp(_SEHFrame->SEH_JmpBuf))) \ + { \ + if (_ret == 1) \ + { \ + _SEHLeave(&_SEHFrame->SEH_Header); \ + do \ + { + + + +#define ___FINALLY_DUAL \ + } while (0); \ + } \ + \ + do \ + { + + + +#define ___EXCEPT_SINGLE(filter) \ + } while(0); \ + \ + _SEHLeave(&_SEHFrame->SEH_Header); \ + break; \ + } \ + else \ + { \ + _SEHHandlers.SH_Filter = (filter); \ + _SEHHandlers.SH_Finally = (NULL); \ + \ + if(_SEHSetJmp(_SEHFrame->SEH_JmpBuf)) \ + { \ + _SEHLeave(&_SEHFrame->SEH_Header); \ + do \ + { + + + +#define ___TRY \ + do \ + { \ + int _loop =0; int _ret = 0; \ + static _SEHHandlers_t _SEHHandlers = \ + { \ + (NULL), \ + _SEHCompilerSpecificHandler, \ + (NULL) \ + }; \ + \ + _SEHFrame_t * _SEHFrame; \ + volatile _SEHPortableFrame_t * _SEHPortableFrame; \ + \ + _SEHFrame = _alloca(sizeof(_SEHFrame_t)); \ + _SEHFrame->SEH_Header.SPF_Handlers = &_SEHHandlers; \ + \ + _SEHPortableFrame = &_SEHFrame->SEH_Header; \ + (void)_SEHPortableFrame; \ + \ + for(;;_loop++) \ + if (_loop == 1) \ + { \ + _SEHEnter(&_SEHFrame->SEH_Header); \ + \ + do \ + { + + +#define ___FINALLY_SINGLE \ + } while(0); \ + \ + _SEHLeave(&_SEHFrame->SEH_Header); \ + } \ + else \ + { \ + _SEHHandlers.SH_Filter = _SEH_STATIC_FILTER(_SEH_CONTINUE_SEARCH); \ + _SEHHandlers.SH_Finally = _FinallyPretty; \ + \ + if(_loop == 2 || (_ret = _SEHSetJmp(_SEHFrame->SEH_JmpBuf))) \ + { \ + do \ + { + + + +#define ___ENDTRY \ + } while (0); \ + \ + if (_ret == 2) \ + { \ + _SEHLongJmp(*_SEHFrame->SEH_JmpRetPtr, 1); \ + } \ + break; \ + } \ + } \ + } while (0); + + + +#ifdef _MSC_VER + #define __TRY2 __try{__try + #define __EXCEPT2 __except + #define __FINALLY2 }__finally + #define __ENDTRY2 + #define __TRY __try + #define __EXCEPT __except + #define __FINALLY __finally + #define __ENDTRY + #define _SEH_STATIC_FILTER(ACTION_) (ACTION_) + #define __LEAVE __leave + #define __LEAVE2 __leave +#else + #define __TRY2 ___TRY + #define __EXCEPT2 ___EXCEPT_DUAL + #define __FINALLY2 ___FINALLY_DUAL + #define __ENDTRY2 __ENDTRY + #define __TRY ___TRY + #define __EXCEPT ___EXCEPT_SINGLE + #define __FINALLY ___FINALLY_SINGLE + #define __ENDTRY ___ENDTRY + #define __LEAVE break + #define __LEAVE2 break +#endif + + +#endif diff --git a/reactos/include/pseh/setjmp.h b/reactos/include/pseh/setjmp.h index ef17bc68599..6acf58b8464 100644 --- a/reactos/include/pseh/setjmp.h +++ b/reactos/include/pseh/setjmp.h @@ -37,6 +37,7 @@ _SEHJmpBuf_t[1]; #endif extern __declspec(noreturn) void __stdcall _SEHLongJmp(_SEHJmpBuf_t, int); +extern __declspec(noreturn) void __stdcall _SEHLongJmp_KeepEsp(_SEHJmpBuf_t, int); extern int __stdcall _SEHSetJmp(_SEHJmpBuf_t); #endif diff --git a/reactos/include/reactos/rossym.h b/reactos/include/reactos/rossym.h new file mode 100644 index 00000000000..7219bce77c1 --- /dev/null +++ b/reactos/include/reactos/rossym.h @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/reactos/rossym.h + * PURPOSE: Handling of rossym symbol info + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#ifndef REACTOS_ROSSYM_H_INCLUDED +#define REACTOS_ROSSYM_H_INCLUDED + +#define ROSSYM_SECTION_NAME ".rossym" + +typedef struct _ROSSYM_HEADER { + unsigned long SymbolsOffset; + unsigned long SymbolsLength; + unsigned long StringsOffset; + unsigned long StringsLength; +} ROSSYM_HEADER, *PROSSYM_HEADER; + +typedef struct _ROSSYM_ENTRY { + ULONG_PTR Address; + ULONG FunctionOffset; + ULONG FileOffset; + ULONG SourceLine; +} ROSSYM_ENTRY, *PROSSYM_ENTRY; + +typedef struct _ROSSYM_CALLBACKS { + PVOID (*AllocMemProc)(ULONG_PTR Size); + VOID (*FreeMemProc)(PVOID Area); + BOOLEAN (*ReadFileProc)(PVOID FileContext, PVOID Buffer, ULONG Size); + BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position); +} ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS; + +typedef struct _ROSSYM_INFO *PROSSYM_INFO; + +VOID RosSymInit(PROSSYM_CALLBACKS Callbacks); +VOID RosSymInitKernelMode(VOID); +VOID RosSymInitUserMode(VOID); + +BOOLEAN RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize, + PROSSYM_INFO *RosSymInfo); +BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, + PROSSYM_INFO *RosSymInfo); +BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo); +ULONG RosSymGetRawDataLength(PROSSYM_INFO RosSymInfo); +VOID RosSymGetRawData(PROSSYM_INFO RosSymInfo, PVOID RawData); +BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, + ULONG_PTR RelativeAddress, + ULONG *LineNumber, + char *FileName, + char *FunctionName); +VOID RosSymDelete(PROSSYM_INFO RosSymInfo); + +#endif /* REACTOS_ROSSYM_H_INCLUDED */ + +/* EOF */ + diff --git a/reactos/include/rosrtl/path.h b/reactos/include/rosrtl/path.h new file mode 100644 index 00000000000..4e71704c86f --- /dev/null +++ b/reactos/include/rosrtl/path.h @@ -0,0 +1,21 @@ +/* + */ + +#ifndef ROSRTL_PATH_H__ +#define ROSRTL_PATH_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +BOOL STDCALL MakeSureDirectoryPathExistsExA(LPCSTR DirPath, BOOL FileAtEnd); +BOOL STDCALL MakeSureDirectoryPathExistsExW(LPCWSTR DirPath, BOOL FileAtEnd); + +#ifdef __cplusplus +} +#endif + +#endif + +/* EOF */ diff --git a/reactos/include/services/services.h b/reactos/include/services/services.h new file mode 100644 index 00000000000..95818c026a3 --- /dev/null +++ b/reactos/include/services/services.h @@ -0,0 +1,24 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/services/services.h + * PURPOSE: Private interface between SERVICES.EXE and ADVAPI32.DLL + * PROGRAMMER: Eric Kohl + */ + +#ifndef __SERVICES_SERVICES_H__ +#define __SERVICES_SERVICES_H__ + +#define SCM_START_COMMAND 1 + +typedef struct _SCM_START_PACKET +{ + ULONG Command; + ULONG Size; + WCHAR Arguments[1]; +} SCM_START_PACKET, *PSCM_START_PACKET; + +#endif /* __SERVICES_SERVICES_H__ */ + +/* EOF */ diff --git a/reactos/include/sm/api.h b/reactos/include/sm/api.h new file mode 100644 index 00000000000..797a14dc5ad --- /dev/null +++ b/reactos/include/sm/api.h @@ -0,0 +1,72 @@ +/* $Id$ */ +#ifndef __SM_API_H +#define __SM_API_H + +#define SM_API_PORT_NAME L"\\SmApiPort" +#define SM_DBGSS_PORT_NAME L"\\DbgSsApiPort" +#define SM_DBGUI_PORT_NAME L"\\DbgUiApiPort" + +#pragma pack(push,4) + +/*** 1 ****************************************************************/ + +#define SM_API_COMPLETE_SESSION 1 /* complete a session initialization */ + +typedef struct _SM_PORT_MESSAGE_COMPSES +{ + HANDLE hApiPort; + HANDLE hSbApiPort; + +} SM_PORT_MESSAGE_COMPSES, *PSM_PORT_MESSAGE_COMPSES; + +/*** 2 ****************************************************************/ + +#define SM_API_2 2 + +/* obsolete */ + +/*** 3 ****************************************************************/ + +#define SM_API_3 3 + +/* unknown */ + +/*** 4 ****************************************************************/ + +#define SM_API_EXECUTE_PROGRAMME 4 /* start a subsystem (server) */ + +#define SM_EXEXPGM_MAX_LENGTH 32 /* max count of wide string */ + +typedef struct _SM_PORT_MESSAGE_EXECPGM +{ + ULONG NameLength; + WCHAR Name [SM_EXEXPGM_MAX_LENGTH]; + +} SM_PORT_MESSAGE_EXECPGM, *PSM_PORT_MESSAGE_EXECPGM; + +/*** | ****************************************************************/ + +typedef struct _SM_PORT_MESSAGE +{ + /*** LPC common header ***/ + LPC_MESSAGE Header; + /*** SM common header ***/ + DWORD ApiIndex; + NTSTATUS Status; + /*** SM per API arguments ***/ + union { + SM_PORT_MESSAGE_COMPSES CompSes; + SM_PORT_MESSAGE_EXECPGM ExecPgm; + }; + +} SM_PORT_MESSAGE, * PSM_PORT_MESSAGE; + +#pragma pack(pop) + +/*** MACRO ***********************************************************/ + +#define SM_PORT_DATA_SIZE(c) (sizeof(DWORD)+sizeof(NTSTATUS)+sizeof(c)) +#define SM_PORT_MESSAGE_SIZE (sizeof(SM_PORT_MESSAGE)) + + +#endif /* !def __SM_API_H */ diff --git a/reactos/include/sm/helper.h b/reactos/include/sm/helper.h new file mode 100644 index 00000000000..13ed8829041 --- /dev/null +++ b/reactos/include/sm/helper.h @@ -0,0 +1,46 @@ +#ifndef _SM_HELPER_H + +/*** DATA TYPES ******************************************************/ + +#define SM_SB_NAME_MAX_LENGTH 120 + +#pragma pack(push,4) + +/* SmConnectApiPort */ +typedef struct _SM_CONNECT_DATA +{ + ULONG Subsystem; + WCHAR SbName [SM_SB_NAME_MAX_LENGTH]; + +} SM_CONNECT_DATA, *PSM_CONNECT_DATA; + +/* SmpConnectSbApiPort */ +typedef struct _SB_CONNECT_DATA +{ + ULONG SmApiMax; +} SB_CONNECT_DATA, *PSB_CONNECT_DATA; + +#pragma pack(pop) + + +/*** PROTOTYPES ******************************************************/ + + +/* smdll/connect.c */ +NTSTATUS STDCALL +SmConnectApiPort (IN PUNICODE_STRING pSbApiPortName OPTIONAL, + IN HANDLE hSbApiPort OPTIONAL, + IN DWORD dwSubsystem OPTIONAL, /* pe.h */ + IN OUT PHANDLE phSmApiPort); +/* smdll/compses.c */ +NTSTATUS STDCALL +SmCompleteSession (IN HANDLE hSmApiPort, + IN HANDLE hSbApiPort, + IN HANDLE hApiPort); +/* smdll/execpgm.c */ +NTSTATUS STDCALL +SmExecuteProgram (IN HANDLE hSmApiPort, + IN PUNICODE_STRING Pgm + ); + +#endif /* ndef _SM_HELPER_H */ diff --git a/reactos/include/sockets.h b/reactos/include/sockets.h index 132351f85e1..13f86a3567a 100644 --- a/reactos/include/sockets.h +++ b/reactos/include/sockets.h @@ -828,9 +828,7 @@ struct protoent * PASCAL getprotobyname(const char * name); /* Microsoft Windows Extension function prototypes */ -/* int PASCAL WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData); */ -int PASCAL WSAStartup(int wVersionRequired, LPWSADATA lpWSAData); - +int PASCAL WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData); int PASCAL WSACleanup(void); diff --git a/reactos/include/tchar.h b/reactos/include/tchar.h index 28ead327faf..cf296e3b4f6 100644 --- a/reactos/include/tchar.h +++ b/reactos/include/tchar.h @@ -148,6 +148,7 @@ typedef wchar_t TCHAR; #define _totupper towupper #define _totlower towlower #define _ttoi _wtoi +#define _ttoi64 _wtoi64 #define _tcsftime wcsftime #define _tsplitpath _wsplitpath #define _tmakepath _wmakepath @@ -256,6 +257,7 @@ typedef char TCHAR; #define _totupper toupper #define _totlower tolower #define _ttoi atoi +#define _ttoi64 _atoi64 #define _tcsftime strftime #define _tsplitpath _splitpath #define _tmakepath _makepath diff --git a/reactos/include/win32k/dc.h b/reactos/include/win32k/dc.h index 589aec4d14a..d85424d2c2e 100644 --- a/reactos/include/win32k/dc.h +++ b/reactos/include/win32k/dc.h @@ -124,8 +124,6 @@ typedef struct _GDIPOINTER /* should stay private to ENG */ RECTL Exclude; /* required publicly for SPS_ACCEPT_EXCLUDE */ PGD_MOVEPOINTER MovePointer; ULONG Status; - BOOL SafetySwitch; - UINT SafetyRemoveCount; } GDIPOINTER, *PGDIPOINTER; typedef struct @@ -140,6 +138,11 @@ typedef struct PFILE_OBJECT VideoFileObject; GDIPOINTER Pointer; + + /* Stuff to keep track of software cursors; win32k gdi part */ + UINT SafetyRemoveLevel; /* at what level was the cursor removed? + 0 for not removed */ + UINT SafetyRemoveCount; } GDIDEVICE; /* Internal functions */ diff --git a/reactos/include/win32k/driver.h b/reactos/include/win32k/driver.h index d93effbf172..a18ff7d7648 100644 --- a/reactos/include/win32k/driver.h +++ b/reactos/include/win32k/driver.h @@ -97,6 +97,8 @@ typedef LONG (STDCALL *PGD_QUERYSPOOLTYPE)(DHPDEV, LPWSTR); typedef BOOL (STDCALL *PGD_GRADIENTFILL)(SURFOBJ*, CLIPOBJ*, XLATEOBJ*, TRIVERTEX*, ULONG, PVOID, ULONG, RECTL*, POINTL*, ULONG); +typedef VOID (STDCALL *PGD_SYNCHRONIZESURFACE)(SURFOBJ*, RECTL *, FLONG); + typedef struct _DRIVER_FUNCTIONS { PGD_ENABLEDRIVER EnableDriver; @@ -158,6 +160,7 @@ typedef struct _DRIVER_FUNCTIONS PGD_DISABLEDIRECTDRAW DisableDirectDraw; PGD_QUERYSPOOLTYPE QuerySpoolType; PGD_GRADIENTFILL GradientFill; + PGD_SYNCHRONIZESURFACE SynchronizeSurface; } DRIVER_FUNCTIONS, *PDRIVER_FUNCTIONS; BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver); diff --git a/reactos/include/win32k/gdiobj.h b/reactos/include/win32k/gdiobj.h index 71c699a6e8d..8d94dfa85a2 100644 --- a/reactos/include/win32k/gdiobj.h +++ b/reactos/include/win32k/gdiobj.h @@ -51,6 +51,8 @@ #define GDI_OBJECT_TYPE_MEMDC 0x00750000 #define GDI_OBJECT_TYPE_DCE 0x00770000 #define GDI_OBJECT_TYPE_DONTCARE 0x007f0000 +/** Not really an object type. Forces GDI_FreeObj to be silent. */ +#define GDI_OBJECT_TYPE_SILENT 0x80000000 /*@}*/ typedef PVOID PGDIOBJ; diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index 13983b00a4f..71f39147310 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -1814,7 +1814,7 @@ typedef struct tagKMDDELPARAM typedef struct _GDI_TABLE_ENTRY { PVOID KernelData; /* Points to the kernel mode structure */ - LONG ProcessId; /* process id that created the object, 0 for stock objects */ + HANDLE ProcessId; /* process id that created the object, 0 for stock objects */ LONG Type; /* the first 16 bit is the object type including the stock obj flag, the last 16 bits is just the object type */ PVOID UserData; /* Points to the user mode structure, usually NULL though */ } GDI_TABLE_ENTRY, *PGDI_TABLE_ENTRY; diff --git a/reactos/include/wine/debug.h b/reactos/include/wine/debug.h index 875396bb24d..3af86979922 100644 --- a/reactos/include/wine/debug.h +++ b/reactos/include/wine/debug.h @@ -37,6 +37,7 @@ struct _GUID; extern const char *wine_dbgstr_an( const char * s, int n ); extern const char *wine_dbgstr_wn( const wchar_t *s, int n ); extern const char *wine_dbgstr_guid( const struct _GUID *id ); +extern const char *wine_dbgstr_longlong( unsigned long long ll ); extern const char *wine_dbg_sprintf( const char *format, ... ); inline static const char *debugstr_an( const char * s, int n ) { return wine_dbgstr_an( s, n ); } diff --git a/reactos/include/wine/guiddef.h b/reactos/include/wine/guiddef.h index d107ceaa2db..cc7aaf9dab6 100644 --- a/reactos/include/wine/guiddef.h +++ b/reactos/include/wine/guiddef.h @@ -38,9 +38,6 @@ typedef struct _GUID extern const GUID name; #endif -#define DEFINE_OLEGUID(name, l, w1, w2) \ - DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46) - #ifndef _GUIDDEF_H_ #define _GUIDDEF_H_ @@ -68,8 +65,6 @@ typedef GUID FMTID,*LPFMTID; #else /* defined(__cplusplus) && !defined(CINTERFACE) */ #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID))) #endif /* defined(__cplusplus) && !defined(CINTERFACE) */ -#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) -#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) #if defined(__cplusplus) && !defined(CINTERFACE) #include diff --git a/reactos/include/wine/list.h b/reactos/include/wine/list.h new file mode 100644 index 00000000000..92b84d8303b --- /dev/null +++ b/reactos/include/wine/list.h @@ -0,0 +1,153 @@ +/* + * Linked lists support + * + * Copyright (C) 2002 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SERVER_LIST_H +#define __WINE_SERVER_LIST_H + +struct list +{ + struct list *next; + struct list *prev; +}; + +/* Define a list like so: + * + * struct gadget + * { + * struct list entry; <-- doesn't have to be the first item in the struct + * int a, b; + * }; + * + * static struct list global_gadgets = LIST_INIT( global_gadgets ); + * + * or + * + * struct some_global_thing + * { + * struct list gadgets; + * }; + * + * list_init( &some_global_thing->gadgets ); + * + * Manipulate it like this: + * + * list_add_head( &global_gadgets, &new_gadget->entry ); + * list_remove( &new_gadget->entry ); + * list_add_after( &some_random_gadget->entry, &new_gadget->entry ); + * + * And to iterate over it: + * + * struct list *cursor; + * LIST_FOR_EACH( cursor, &global_gadgets ) + * { + * struct gadget *gadget = LIST_ENTRY( cursor, struct gadget, entry ); + * } + * + */ + +/* add an element after the specified one */ +inline static void list_add_after( struct list *elem, struct list *to_add ) +{ + to_add->next = elem->next; + to_add->prev = elem; + elem->next->prev = to_add; + elem->next = to_add; +} + +/* add an element before the specified one */ +inline static void list_add_before( struct list *elem, struct list *to_add ) +{ + to_add->next = elem; + to_add->prev = elem->prev; + elem->prev->next = to_add; + elem->prev = to_add; +} + +/* add element at the head of the list */ +inline static void list_add_head( struct list *list, struct list *elem ) +{ + list_add_after( list, elem ); +} + +/* add element at the tail of the list */ +inline static void list_add_tail( struct list *list, struct list *elem ) +{ + list_add_before( list, elem ); +} + +/* remove an element from its list */ +inline static void list_remove( struct list *elem ) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + +/* get the next element */ +inline static struct list *list_next( struct list *list, struct list *elem ) +{ + struct list *ret = elem->next; + if (elem->next == list) ret = NULL; + return ret; +} + +/* get the previous element */ +inline static struct list *list_prev( struct list *list, struct list *elem ) +{ + struct list *ret = elem->prev; + if (elem->prev == list) ret = NULL; + return ret; +} + +/* get the first element */ +inline static struct list *list_head( struct list *list ) +{ + return list_next( list, list ); +} + +/* get the last element */ +inline static struct list *list_tail( struct list *list ) +{ + return list_prev( list, list ); +} + +/* check if a list is empty */ +inline static int list_empty( struct list *list ) +{ + return list->next == list; +} + +/* initialize a list */ +inline static void list_init( struct list *list ) +{ + list->next = list->prev = list; +} + +/* iterate through the list */ +#define LIST_FOR_EACH(cursor,list) \ + for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next) + +/* macros for statically initialized lists */ +#define LIST_INIT(list) { &(list), &(list) } + +/* get pointer to object containing list element */ +#define LIST_ENTRY(elem, type, field) \ + ((type *)((char *)(elem) - (unsigned int)(&((type *)0)->field))) + +#endif /* __WINE_SERVER_LIST_H */ diff --git a/reactos/include/wine/msiquery.h b/reactos/include/wine/msiquery.h index cfd07b9a875..9b61ae6acd4 100644 --- a/reactos/include/wine/msiquery.h +++ b/reactos/include/wine/msiquery.h @@ -59,7 +59,30 @@ typedef enum tagMSIMODIFY #define MSIDBOPEN_TRANSACT (LPCTSTR)1 #define MSIDBOPEN_DIRECT (LPCTSTR)2 #define MSIDBOPEN_CREATE (LPCTSTR)3 +#define MSIDBOPEN_CREATEDIRECT (LPCTSTR)4 +typedef enum tagMSIRUNMODE +{ + MSIRUNMODE_ADMIN = 0, + MSIRUNMODE_ADVERTISE = 1, + MSIRUNMODE_MAINTENANCE = 2, + MSIRUNMODE_ROLLBACKENABLED = 3, + MSIRUNMODE_LOGENABLED = 4, + MSIRUNMODE_OPERATIONS = 5, + MSIRUNMODE_REBOOTATEND = 6, + MSIRUNMODE_REBOOTNOW = 7, + MSIRUNMODE_CABINET = 8, + MSIRUNMODE_SOURCESHORTNAMES = 9, + MSIRUNMODE_TARGETSHORTNAMES = 10, + MSIRUNMODE_RESERVED11 = 11, + MSIRUNMODE_WINDOWS9X = 12, + MSIRUNMODE_ZAWENABLED = 13, + MSIRUNMODE_RESERVED14 = 14, + MSIRUNMODE_RESERVED15 = 15, + MSIRUNMODE_SCHEDULED = 16, + MSIRUNMODE_ROLLBACK = 17, + MSIRUNMODE_COMMIT = 18 +} MSIRUNMODE; /* view manipulation */ UINT WINAPI MsiViewFetch(MSIHANDLE,MSIHANDLE*); @@ -123,15 +146,12 @@ MSICONDITION WINAPI MsiEvaluateConditionW(MSIHANDLE,LPCWSTR); #define MsiEvaluateCondition WINELIB_NAME_AW(MsiEvaluateCondition) /* property functions */ -UINT WINAPI MsiGetPropertyA(MSIHANDLE hInstall, LPCSTR szName, - LPSTR szValueBuf, DWORD* pchValueBuf); -UINT WINAPI MsiGetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, - LPWSTR szValueBuf, DWORD* pchValueBuf); +UINT WINAPI MsiGetPropertyA(MSIHANDLE, LPCSTR, LPSTR, DWORD*); +UINT WINAPI MsiGetPropertyW(MSIHANDLE, LPCWSTR, LPWSTR, DWORD*); #define MsiGetProperty WINELIB_NAME_AW(MsiGetProperty) -UINT WINAPI MsiSetPropertyA(MSIHANDLE hInstall, LPCSTR szName, LPCSTR szValue); -UINT WINAPI MsiSetPropertyW(MSIHANDLE hInstall, LPCWSTR szName, - LPCWSTR szValue); +UINT WINAPI MsiSetPropertyA(MSIHANDLE, LPCSTR, LPCSTR); +UINT WINAPI MsiSetPropertyW(MSIHANDLE, LPCWSTR, LPCWSTR); #define MsiSetProperty WINELIB_NAME_AW(MsiSetProperty) UINT WINAPI MsiGetTargetPathA(MSIHANDLE,LPCSTR,LPSTR,DWORD*); @@ -148,11 +168,13 @@ UINT WINAPI MsiGetSourcePathW(MSIHANDLE,LPCWSTR,LPWSTR,DWORD*); MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE); -UINT WINAPI MsiViewGetColumnInfo( MSIHANDLE, MSICOLINFO, MSIHANDLE*); -INT WINAPI MsiProcessMessage( MSIHANDLE, INSTALLMESSAGE, MSIHANDLE); +UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE, MSICOLINFO, MSIHANDLE*); +INT WINAPI MsiProcessMessage(MSIHANDLE, INSTALLMESSAGE, MSIHANDLE); -UINT WINAPI MsiSetFeatureStateA( MSIHANDLE, LPCSTR, INSTALLSTATE); -UINT WINAPI MsiSetFeatureStateW( MSIHANDLE, LPCWSTR, INSTALLSTATE); +UINT WINAPI MsiSetFeatureStateA(MSIHANDLE, LPCSTR, INSTALLSTATE); +UINT WINAPI MsiSetFeatureStateW(MSIHANDLE, LPCWSTR, INSTALLSTATE); #define MsiSetFeatureState WINELIB_NAME_AW(MsiSetFeatureState) +BOOL WINAPI MsiGetMode(MSIHANDLE, MSIRUNMODE); + #endif /* __WINE_MSIQUERY_H */ diff --git a/reactos/include/wine/objidl.h b/reactos/include/wine/objidl.h index d118b9051dc..b9f9eecf0c1 100644 --- a/reactos/include/wine/objidl.h +++ b/reactos/include/wine/objidl.h @@ -1943,4 +1943,67 @@ void __RPC_STUB IGlobalInterfaceTable_GetInterfaceFromGlobal_Stub( #endif /* __IGlobalInterfaceTable_INTERFACE_DEFINED__ */ +#ifndef __IInternalUnknown_FWD_DEFINED__ +#define __IInternalUnknown_FWD_DEFINED__ +typedef struct IInternalUnknown IInternalUnknown; +#endif + +/***************************************************************************** + * IInternalUnknown interface + */ +#ifndef __IInternalUnknown_INTERFACE_DEFINED__ +#define __IInternalUnknown_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IInternalUnknown, 0x00000021, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46); +#if defined(__cplusplus) && !defined(CINTERFACE) +struct IInternalUnknown : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE QueryInternalInterface( + REFIID riid, + void** ppv) = 0; + +}; +#else +typedef struct IInternalUnknownVtbl IInternalUnknownVtbl; +struct IInternalUnknown { + const IInternalUnknownVtbl* lpVtbl; +}; +struct IInternalUnknownVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IInternalUnknown* This, + REFIID riid, + void** ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IInternalUnknown* This); + + ULONG (STDMETHODCALLTYPE *Release)( + IInternalUnknown* This); + + /*** IInternalUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInternalInterface)( + IInternalUnknown* This, + REFIID riid, + void** ppv); + + END_INTERFACE +}; + +#ifdef COBJMACROS +/*** IUnknown methods ***/ +#define IInternalUnknown_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IInternalUnknown_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IInternalUnknown_Release(p) (p)->lpVtbl->Release(p) +/*** IInternalUnknown methods ***/ +#define IInternalUnknown_QueryInternalInterface(p,a,b) (p)->lpVtbl->QueryInternalInterface(p,a,b) +#endif + +#endif + +#endif /* __IInternalUnknown_INTERFACE_DEFINED__ */ + + #endif /* __WINE_OBJIDL_H */ diff --git a/reactos/include/wine/setupapi.h b/reactos/include/wine/setupapi.h index 4b9bf42ff29..cee5f4c02e6 100644 --- a/reactos/include/wine/setupapi.h +++ b/reactos/include/wine/setupapi.h @@ -156,6 +156,59 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_FILE_CALLBACK) #define MAX_SUBTITLE_LEN 256 #define SP_MAX_MACHINENAME_LENGTH (MAX_PATH + 3) +typedef UINT DI_FUNCTION; + +typedef struct _SP_CLASSINSTALL_HEADER +{ + DWORD cbSize; + DI_FUNCTION InstallFunction; +} SP_CLASSINSTALL_HEADER, *PSP_CLASSINSTALL_HEADER; + +typedef struct _SP_PROPCHANGE_PARAMS +{ + SP_CLASSINSTALL_HEADER ClassInstallHeader; + DWORD StateChange; + DWORD Scope; + DWORD HwProfile; +} SP_PROPCHANGE_PARAMS, *PSP_PROPCHANGE_PARAMS; + +#define DICS_ENABLE 0x00000001 +#define DICS_DISABLE 0x00000002 +#define DICS_PROPCHANGE 0x00000003 +#define DICS_START 0x00000004 +#define DICS_STOP 0x00000005 + +typedef struct _SP_DEVINSTALL_PARAMS_A +{ + DWORD cbSize; + DWORD Flags; + DWORD FlagsEx; + HWND hwndParent; + PSP_FILE_CALLBACK_A InstallMsgHandler; + PVOID InstallMsgHandlerContext; + HSPFILEQ FileQueue; + ULONG_PTR ClassInstallReserved; + DWORD Reserved; + CHAR DriverPath[MAX_PATH]; +} SP_DEVINSTALL_PARAMS_A, *PSP_DEVINSTALL_PARAMS_A; + +typedef struct _SP_DEVINSTALL_PARAMS_W +{ + DWORD cbSize; + DWORD Flags; + DWORD FlagsEx; + HWND hwndParent; + PSP_FILE_CALLBACK_W InstallMsgHandler; + PVOID InstallMsgHandlerContext; + HSPFILEQ FileQueue; + ULONG_PTR ClassInstallReserved; + DWORD Reserved; + WCHAR DriverPath[MAX_PATH]; +} SP_DEVINSTALL_PARAMS_W, *PSP_DEVINSTALL_PARAMS_W; + +DECL_WINELIB_SETUPAPI_TYPE_AW(SP_DEVINSTALL_PARAMS) +DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_DEVINSTALL_PARAMS) + /* Device Information structure (references a device instance that is a member of a device information set) */ typedef struct _SP_DEVINFO_DATA @@ -397,7 +450,6 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS) #define FLG_REGSVR_DLLREGISTER 0x00000001 #define FLG_REGSVR_DLLINSTALL 0x00000002 -/* */ #define DI_NOVCP 0x00000008 /* Class installer function codes */ @@ -559,7 +611,7 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS) #define ERROR_NO_SUCH_INTERFACE_DEVICE ERROR_NO_SUCH_DEVICE_INTERFACE #define ERROR_NOT_INSTALLED (APPLICATION_ERROR_MASK|ERROR_SEVERITY_ERROR|0x1000) -/* Flags for SetupDiGetClassDevs */ +/* flags for SetupDiGetClassDevs */ #define DIGCF_DEFAULT 0x00000001 #define DIGCF_PRESENT 0x00000002 #define DIGCF_ALLCLASSES 0x00000004 @@ -613,96 +665,29 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS) #define SPDRP_MAXIMUM_PROPERTY 0x00000023 -VOID WINAPI MyFree( LPVOID lpMem ); -LPVOID WINAPI MyMalloc( DWORD dwSize ); -LPVOID WINAPI MyRealloc( LPVOID lpSrc, DWORD dwSize ); - -LONG WINAPI QueryRegistryValue( HKEY, LPCWSTR, LPBYTE *, LPDWORD, LPDWORD ); - -void WINAPI InstallHinfSectionA( HWND hwnd, HINSTANCE handle, LPCSTR cmdline, INT show ); -void WINAPI InstallHinfSectionW( HWND hwnd, HINSTANCE handle, LPCWSTR cmdline, INT show ); +LONG WINAPI AddTagToGroupOrderList(PCWSTR lpGroupName, DWORD dwUnknown2, DWORD dwUnknown3); +BOOL WINAPI DelayedMove(PCWSTR lpExistingFileName, PCWSTR lpNewFileName); +BOOL WINAPI DoesUserHavePrivilege(PCWSTR lpPrivilegeName); +PWSTR WINAPI DuplicateString(PCWSTR lpSrc); +BOOL WINAPI EnablePrivilege(PCWSTR lpPrivilegeName, BOOL bEnable); +BOOL WINAPI FileExists(PCWSTR lpFileName, PWIN32_FIND_DATAW lpFileFindData); +void WINAPI InstallHinfSectionA( HWND hwnd, HINSTANCE handle, PCSTR cmdline, INT show ); +void WINAPI InstallHinfSectionW( HWND hwnd, HINSTANCE handle, PCWSTR cmdline, INT show ); #define InstallHinfSection WINELIB_NAME_AW(InstallHinfSection) -HINF WINAPI SetupOpenInfFileA( PCSTR name, PCSTR pszclass, DWORD style, UINT *error ); -HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR pszclass, DWORD style, UINT *error ); -#define SetupOpenInfFile WINELIB_NAME_AW(SetupOpenInfFile) -BOOL WINAPI SetupOpenAppendInfFileA( PCSTR, HINF, UINT * ); -BOOL WINAPI SetupOpenAppendInfFileW( PCWSTR, HINF, UINT * ); -#define SetupOpenAppendInfFile WINELIB_NAME_AW(SetupOpenAppendInfFile) -HINF WINAPI SetupOpenMasterInf( VOID ); -void WINAPI SetupCloseInfFile( HINF hinf ); -BOOL WINAPI SetupGetLineByIndexA( HINF, PCSTR, DWORD, INFCONTEXT * ); -BOOL WINAPI SetupGetLineByIndexW( HINF, PCWSTR, DWORD, INFCONTEXT * ); -#define SetupGetLineByIndex WINELIB_NAME_AW(SetupGetLineByIndex) -LONG WINAPI SetupGetLineCountA( HINF hinf, PCSTR section ); -LONG WINAPI SetupGetLineCountW( HINF hinf, PCWSTR section ); -#define SetupGetLineCount WINELIB_NAME_AW(SetupGetLineCount) -BOOL WINAPI SetupFindFirstLineA( HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context ); -BOOL WINAPI SetupFindFirstLineW( HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context ); -#define SetupFindFirstLine WINELIB_NAME_AW(SetupFindFirstLine) -BOOL WINAPI SetupFindNextLine( PINFCONTEXT context_in, PINFCONTEXT context_out ); -BOOL WINAPI SetupFindNextMatchLineA( PINFCONTEXT context_in, PCSTR key, PINFCONTEXT context_out ); -BOOL WINAPI SetupFindNextMatchLineW( PINFCONTEXT context_in, PCWSTR key, PINFCONTEXT context_out ); -#define SetupFindNextMatchLine WINELIB_NAME_AW(SetupFindNextMatchLine) -BOOL WINAPI SetupGetLineTextA( PINFCONTEXT context, HINF hinf, PCSTR section_name,PCSTR key_name, PSTR buffer, DWORD size, PDWORD required ); -BOOL WINAPI SetupGetLineTextW( PINFCONTEXT context, HINF hinf, PCWSTR section_name, PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required ); -#define SetupGetLineText WINELIB_NAME_AW(SetupGetLineText) -DWORD WINAPI SetupGetFieldCount( PINFCONTEXT context ); -BOOL WINAPI SetupGetIntField( PINFCONTEXT context, DWORD index, PINT result ); -BOOL WINAPI SetupGetStringFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required ); -BOOL WINAPI SetupGetStringFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, PDWORD required ); -#define SetupGetStringField WINELIB_NAME_AW(SetupGetStringField) -BOOL WINAPI SetupGetBinaryField( PINFCONTEXT context, DWORD index, BYTE *buffer, DWORD size, LPDWORD required ); -BOOL WINAPI SetupGetMultiSzFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, LPDWORD required ); -BOOL WINAPI SetupGetMultiSzFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, LPDWORD required ); -#define SetupGetMultiSzField WINELIB_NAME_AW(SetupGetMultiSzField) -BOOL WINAPI SetupSetDirectoryIdA( HINF, DWORD, PCSTR ); -BOOL WINAPI SetupSetDirectoryIdW( HINF, DWORD, PCWSTR ); -#define SetupSetDirectoryId WINELIB_NAME_AW(SetupSetDirectoryId) -HSPFILEQ WINAPI SetupOpenFileQueue(void); +BOOL WINAPI IsUserAdmin(VOID); +PWSTR WINAPI MultiByteToUnicode(PCSTR lpMultiByteStr, UINT uCodePage); +VOID WINAPI MyFree(PVOID lpMem); +PVOID WINAPI MyMalloc(DWORD dwSize); +PVOID WINAPI MyRealloc(PVOID lpSrc, DWORD dwSize); +LONG WINAPI QueryRegistryValue(HKEY, PCWSTR, PBYTE *, PDWORD, PDWORD); BOOL WINAPI SetupCloseFileQueue( HSPFILEQ ); -BOOL WINAPI SetupSetFileQueueAlternatePlatformA( HSPFILEQ, PSP_ALTPLATFORM_INFO, PCSTR ); -BOOL WINAPI SetupSetFileQueueAlternatePlatformW( HSPFILEQ, PSP_ALTPLATFORM_INFO, PCWSTR ); -#define SetupSetFileQueueAlternatePlatform WINELIB_NAME_AW(SetupSetFileQueueAlternatePlatform) -BOOL WINAPI SetupQueueCopyA(HSPFILEQ,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,DWORD); -BOOL WINAPI SetupQueueCopyW(HSPFILEQ,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,DWORD); -#define SetupQueueCopy WINELIB_NAME_AW(SetupQueueCopy) -BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A ); -BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W ); -#define SetupQueueCopyIndirect WINELIB_NAME_AW(SetupQueueCopyIndirect) -BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ, HINF, PCSTR, PCSTR, PCSTR, DWORD ); -BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ, HINF, PCWSTR, PCWSTR, PCWSTR, DWORD ); -#define SetupQueueDefaultCopy WINELIB_NAME_AW(SetupQueueDefaultCopy) -BOOL WINAPI SetupQueueDeleteA( HSPFILEQ, PCSTR, PCSTR ); -BOOL WINAPI SetupQueueDeleteW( HSPFILEQ, PCWSTR, PCWSTR ); -#define SetupQueueDelete WINELIB_NAME_AW(SetupQueueDelete) -BOOL WINAPI SetupQueueRenameA( HSPFILEQ, PCSTR, PCSTR, PCSTR, PCSTR ); -BOOL WINAPI SetupQueueRenameW( HSPFILEQ, PCWSTR, PCWSTR, PCWSTR, PCWSTR ); -#define SetupQueueRename WINELIB_NAME_AW(SetupQueueRename) +void WINAPI SetupCloseInfFile( HINF hinf ); BOOL WINAPI SetupCommitFileQueueA( HWND, HSPFILEQ, PSP_FILE_CALLBACK_A, PVOID ); BOOL WINAPI SetupCommitFileQueueW( HWND, HSPFILEQ, PSP_FILE_CALLBACK_W, PVOID ); #define SetupCommitFileQueue WINELIB_NAME_AW(SetupCommitFileQueue) -BOOL WINAPI SetupScanFileQueueA( HSPFILEQ, DWORD, HWND, PSP_FILE_CALLBACK_A, PVOID, PDWORD ); -BOOL WINAPI SetupScanFileQueueW( HSPFILEQ, DWORD, HWND, PSP_FILE_CALLBACK_W, PVOID, PDWORD ); -#define SetupScanFileQueue WINELIB_NAME_AW(SetupScanFileQueue) -BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ, UINT, PUINT ); -BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ, PDWORD ); -BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD ); -BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ, PCSTR, HINF, HINF, PCSTR, DWORD ); -BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ, PCWSTR, HINF, HINF, PCWSTR, DWORD ); -#define SetupQueueCopySection WINELIB_NAME_AW(SetupQueueCopySection) -BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ, HINF, HINF, PCSTR ); -BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ, HINF, HINF, PCWSTR ); -#define SetupQueueDeleteSection WINELIB_NAME_AW(SetupQueueDeleteSection) -BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ, HINF, HINF, PCSTR ); -BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ, HINF, HINF, PCWSTR ); -#define SetupQueueRenameSection WINELIB_NAME_AW(SetupQueueRenameSection) -PVOID WINAPI SetupInitDefaultQueueCallback( HWND ); -PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND, HWND, UINT, DWORD, PVOID ); -void WINAPI SetupTermDefaultQueueCallback( PVOID ); UINT WINAPI SetupDefaultQueueCallbackA( PVOID, UINT, UINT_PTR, UINT_PTR ); UINT WINAPI SetupDefaultQueueCallbackW( PVOID, UINT, UINT_PTR, UINT_PTR ); #define SetupDefaultQueueCallback WINELIB_NAME_AW(SetupDefaultQueueCallback) - BOOL WINAPI SetupDiBuildClassInfoList(DWORD, LPGUID, DWORD, PDWORD); BOOL WINAPI SetupDiBuildClassInfoListExA(DWORD, LPGUID, DWORD, PDWORD, PCSTR, PVOID); BOOL WINAPI SetupDiBuildClassInfoListExW(DWORD, LPGUID, DWORD, PDWORD, PCWSTR, PVOID); @@ -737,7 +722,6 @@ BOOL WINAPI SetupDiGetClassDescriptionExW(const GUID*, PWSTR, DWORD, PDWORD, HDEVINFO WINAPI SetupDiGetClassDevsA(CONST GUID *,LPCSTR,HWND,DWORD); HDEVINFO WINAPI SetupDiGetClassDevsW(CONST GUID *,LPCWSTR,HWND,DWORD); #define SetupDiGetClassDevs WINELIB_NAME_AW(SetupDiGetClassDevs) - BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA); BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, @@ -751,7 +735,35 @@ HKEY WINAPI SetupDiOpenClassRegKey(const GUID*, REGSAM); HKEY WINAPI SetupDiOpenClassRegKeyExA(const GUID*, REGSAM, DWORD, PCSTR, PVOID); HKEY WINAPI SetupDiOpenClassRegKeyExW(const GUID*, REGSAM, DWORD, PCWSTR, PVOID); #define SetupDiOpenClassRegKeyEx WINELIB_NAME_AW(SetupDiOpenClassRegKeyEx) - +BOOL WINAPI SetupFindFirstLineA( HINF hinf, PCSTR section, PCSTR key, INFCONTEXT *context ); +BOOL WINAPI SetupFindFirstLineW( HINF hinf, PCWSTR section, PCWSTR key, INFCONTEXT *context ); +#define SetupFindFirstLine WINELIB_NAME_AW(SetupFindFirstLine) +BOOL WINAPI SetupFindNextLine( PINFCONTEXT context_in, PINFCONTEXT context_out ); +BOOL WINAPI SetupFindNextMatchLineA( PINFCONTEXT context_in, PCSTR key, PINFCONTEXT context_out ); +BOOL WINAPI SetupFindNextMatchLineW( PINFCONTEXT context_in, PCWSTR key, PINFCONTEXT context_out ); +#define SetupFindNextMatchLine WINELIB_NAME_AW(SetupFindNextMatchLine) +BOOL WINAPI SetupGetBinaryField( PINFCONTEXT context, DWORD index, BYTE *buffer, DWORD size, LPDWORD required ); +DWORD WINAPI SetupGetFieldCount( PINFCONTEXT context ); +BOOL WINAPI SetupGetFileQueueCount( HSPFILEQ, UINT, PUINT ); +BOOL WINAPI SetupGetFileQueueFlags( HSPFILEQ, PDWORD ); +BOOL WINAPI SetupGetIntField( PINFCONTEXT context, DWORD index, PINT result ); +BOOL WINAPI SetupGetLineByIndexA( HINF, PCSTR, DWORD, INFCONTEXT * ); +BOOL WINAPI SetupGetLineByIndexW( HINF, PCWSTR, DWORD, INFCONTEXT * ); +#define SetupGetLineByIndex WINELIB_NAME_AW(SetupGetLineByIndex) +LONG WINAPI SetupGetLineCountA( HINF hinf, PCSTR section ); +LONG WINAPI SetupGetLineCountW( HINF hinf, PCWSTR section ); +#define SetupGetLineCount WINELIB_NAME_AW(SetupGetLineCount) +BOOL WINAPI SetupGetLineTextA( PINFCONTEXT context, HINF hinf, PCSTR section_name,PCSTR key_name, PSTR buffer, DWORD size, PDWORD required ); +BOOL WINAPI SetupGetLineTextW( PINFCONTEXT context, HINF hinf, PCWSTR section_name, PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required ); +#define SetupGetLineText WINELIB_NAME_AW(SetupGetLineText) +BOOL WINAPI SetupGetMultiSzFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, LPDWORD required ); +BOOL WINAPI SetupGetMultiSzFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, LPDWORD required ); +#define SetupGetMultiSzField WINELIB_NAME_AW(SetupGetMultiSzField) +BOOL WINAPI SetupGetStringFieldA( PINFCONTEXT context, DWORD index, PSTR buffer, DWORD size, PDWORD required ); +BOOL WINAPI SetupGetStringFieldW( PINFCONTEXT context, DWORD index, PWSTR buffer, DWORD size, PDWORD required ); +#define SetupGetStringField WINELIB_NAME_AW(SetupGetStringField) +PVOID WINAPI SetupInitDefaultQueueCallback( HWND ); +PVOID WINAPI SetupInitDefaultQueueCallbackEx( HWND, HWND, UINT, DWORD, PVOID ); BOOL WINAPI SetupInstallFilesFromInfSectionA( HINF, HINF, HSPFILEQ, PCSTR, PCSTR, UINT ); BOOL WINAPI SetupInstallFilesFromInfSectionW( HINF, HINF, HSPFILEQ, PCWSTR, PCWSTR, UINT ); #define SetupInstallFilesFromInfSection WINELIB_NAME_AW(SetupInstallFilesFromInfSection) @@ -763,6 +775,50 @@ BOOL WINAPI SetupInstallFromInfSectionW(HWND,HINF,PCWSTR,UINT,HKEY,PCWSTR,UI BOOL WINAPI SetupIterateCabinetA(PCSTR, DWORD, PSP_FILE_CALLBACK_A, PVOID); BOOL WINAPI SetupIterateCabinetW(PCWSTR, DWORD, PSP_FILE_CALLBACK_W, PVOID); #define SetupIterateCabinet WINELIB_NAME_AW(SetupIterateCabinet) +BOOL WINAPI SetupOpenAppendInfFileA( PCSTR, HINF, UINT * ); +BOOL WINAPI SetupOpenAppendInfFileW( PCWSTR, HINF, UINT * ); +#define SetupOpenAppendInfFile WINELIB_NAME_AW(SetupOpenAppendInfFile) +HSPFILEQ WINAPI SetupOpenFileQueue(void); +HINF WINAPI SetupOpenInfFileA( PCSTR name, PCSTR pszclass, DWORD style, UINT *error ); +HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR pszclass, DWORD style, UINT *error ); +#define SetupOpenInfFile WINELIB_NAME_AW(SetupOpenInfFile) +HINF WINAPI SetupOpenMasterInf( VOID ); +BOOL WINAPI SetupQueueCopyA(HSPFILEQ,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,PCSTR,DWORD); +BOOL WINAPI SetupQueueCopyW(HSPFILEQ,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,PCWSTR,DWORD); +#define SetupQueueCopy WINELIB_NAME_AW(SetupQueueCopy) +BOOL WINAPI SetupQueueCopyIndirectA( PSP_FILE_COPY_PARAMS_A ); +BOOL WINAPI SetupQueueCopyIndirectW( PSP_FILE_COPY_PARAMS_W ); +#define SetupQueueCopyIndirect WINELIB_NAME_AW(SetupQueueCopyIndirect) +BOOL WINAPI SetupQueueCopySectionA( HSPFILEQ, PCSTR, HINF, HINF, PCSTR, DWORD ); +BOOL WINAPI SetupQueueCopySectionW( HSPFILEQ, PCWSTR, HINF, HINF, PCWSTR, DWORD ); +#define SetupQueueCopySection WINELIB_NAME_AW(SetupQueueCopySection) +BOOL WINAPI SetupQueueDefaultCopyA( HSPFILEQ, HINF, PCSTR, PCSTR, PCSTR, DWORD ); +BOOL WINAPI SetupQueueDefaultCopyW( HSPFILEQ, HINF, PCWSTR, PCWSTR, PCWSTR, DWORD ); +#define SetupQueueDefaultCopy WINELIB_NAME_AW(SetupQueueDefaultCopy) +BOOL WINAPI SetupQueueDeleteA( HSPFILEQ, PCSTR, PCSTR ); +BOOL WINAPI SetupQueueDeleteW( HSPFILEQ, PCWSTR, PCWSTR ); +#define SetupQueueDelete WINELIB_NAME_AW(SetupQueueDelete) +BOOL WINAPI SetupQueueDeleteSectionA( HSPFILEQ, HINF, HINF, PCSTR ); +BOOL WINAPI SetupQueueDeleteSectionW( HSPFILEQ, HINF, HINF, PCWSTR ); +#define SetupQueueDeleteSection WINELIB_NAME_AW(SetupQueueDeleteSection) +BOOL WINAPI SetupQueueRenameA( HSPFILEQ, PCSTR, PCSTR, PCSTR, PCSTR ); +BOOL WINAPI SetupQueueRenameW( HSPFILEQ, PCWSTR, PCWSTR, PCWSTR, PCWSTR ); +#define SetupQueueRename WINELIB_NAME_AW(SetupQueueRename) +BOOL WINAPI SetupQueueRenameSectionA( HSPFILEQ, HINF, HINF, PCSTR ); +BOOL WINAPI SetupQueueRenameSectionW( HSPFILEQ, HINF, HINF, PCWSTR ); +#define SetupQueueRenameSection WINELIB_NAME_AW(SetupQueueRenameSection) +BOOL WINAPI SetupScanFileQueueA( HSPFILEQ, DWORD, HWND, PSP_FILE_CALLBACK_A, PVOID, PDWORD ); +BOOL WINAPI SetupScanFileQueueW( HSPFILEQ, DWORD, HWND, PSP_FILE_CALLBACK_W, PVOID, PDWORD ); +#define SetupScanFileQueue WINELIB_NAME_AW(SetupScanFileQueue) +BOOL WINAPI SetupSetDirectoryIdA( HINF, DWORD, PCSTR ); +BOOL WINAPI SetupSetDirectoryIdW( HINF, DWORD, PCWSTR ); +#define SetupSetDirectoryId WINELIB_NAME_AW(SetupSetDirectoryId) +BOOL WINAPI SetupSetFileQueueAlternatePlatformA( HSPFILEQ, PSP_ALTPLATFORM_INFO, PCSTR ); +BOOL WINAPI SetupSetFileQueueAlternatePlatformW( HSPFILEQ, PSP_ALTPLATFORM_INFO, PCWSTR ); +#define SetupSetFileQueueAlternatePlatform WINELIB_NAME_AW(SetupSetFileQueueAlternatePlatform) +BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD ); +void WINAPI SetupTermDefaultQueueCallback( PVOID ); +PSTR WINAPI UnicodeToMultiByte(PCWSTR lpUnicodeStr, UINT uCodePage); #undef DECL_WINELIB_SETUPAPI_TYPE_AW diff --git a/reactos/lib/advapi32/advapi32.def b/reactos/lib/advapi32/advapi32.def index 147168f6aad..dfbbbb41972 100644 --- a/reactos/lib/advapi32/advapi32.def +++ b/reactos/lib/advapi32/advapi32.def @@ -31,10 +31,10 @@ BackupEventLogA@8 BackupEventLogW@8 ;BuildAccessRequestA ;BuildAccessRequestW -;BuildExplicitAccessWithNameA@20 -;BuildExplicitAccessWithNameW@20 -;BuildImpersonateExplicitAccessWithNameA@24 -;BuildImpersonateExplicitAccessWithNameW@24 +BuildExplicitAccessWithNameA@20 +BuildExplicitAccessWithNameW@20 +BuildImpersonateExplicitAccessWithNameA@24 +BuildImpersonateExplicitAccessWithNameW@24 BuildImpersonateTrusteeA@8 BuildImpersonateTrusteeW@8 ;BuildSecurityDescriptorA@36 @@ -45,6 +45,7 @@ BuildTrusteeWithSidA@8 BuildTrusteeWithSidW@8 ChangeServiceConfigA@44 ChangeServiceConfigW@44 +CheckTokenMembership@12 ClearEventLogA@8 ClearEventLogW@8 CloseEventLog@4 @@ -162,6 +163,7 @@ GetSecurityDescriptorDacl@16 GetSecurityDescriptorGroup@12 GetSecurityDescriptorLength@4 GetSecurityDescriptorOwner@12 +GetSecurityDescriptorRMControl@8 GetSecurityDescriptorSacl@16 GetSecurityInfo@32 GetSecurityInfoExA@36 @@ -235,7 +237,7 @@ LsaClose@4 LsaFreeMemory@4 ;LsaGetQuotasForAccount@8 ;LsaGetSystemAccessAccount@8 -;LsaGetUserName@8 +LsaGetUserName@8 ;LsaICLookupNames@32 ;LsaICLookupSids@32 ;LsaLookupNames@20 @@ -255,7 +257,7 @@ LsaQueryInformationPolicy@12 ;LsaQueryTrustedDomainInfo@16 ;LsaRemoveAccountRights@20 ;LsaRemovePrivilegesFromAccount@12 -;LsaRetrievePrivateData@12 +LsaRetrievePrivateData@12 ;LsaSetInformationPolicy@12 ;LsaSetInformationTrustedDomain@12 ;LsaSetQuotasForAccount@8 @@ -263,7 +265,7 @@ LsaQueryInformationPolicy@12 ;LsaSetSecurityObject@12 ;LsaSetSystemAccessAccount@8 ;LsaSetTrustedDomainInformation@16 -;LsaStorePrivateData@12 +LsaStorePrivateData@12 MakeAbsoluteSD@44 MakeSelfRelativeSD@12 MapGenericMask@8 @@ -359,6 +361,8 @@ RegisterEventSourceA@8 RegisterEventSourceW@8 RegisterServiceCtrlHandlerA@8 RegisterServiceCtrlHandlerW@8 +RegisterServiceCtrlHandlerExA@12 +RegisterServiceCtrlHandlerExW@12 ;ReplaceAllAccessRightsA ;ReplaceAllAccessRightsW ReportEventA@36 @@ -377,9 +381,11 @@ SetKernelObjectSecurity@12 SetNamedSecurityInfoA@28 SetNamedSecurityInfoW@28 ;SetPrivateObjectSecurity@20 +SetSecurityDescriptorControl@12 SetSecurityDescriptorDacl@16 SetSecurityDescriptorGroup@12 SetSecurityDescriptorOwner@12 +SetSecurityDescriptorRMControl@8 SetSecurityDescriptorSacl@16 SetSecurityInfo@28 SetServiceBits@16 diff --git a/reactos/lib/advapi32/misc/logon.c b/reactos/lib/advapi32/misc/logon.c index 316f41ad1c0..97db084b306 100644 --- a/reactos/lib/advapi32/misc/logon.c +++ b/reactos/lib/advapi32/misc/logon.c @@ -30,6 +30,7 @@ CreateProcessAsUserA (HANDLE hToken, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { + PROCESS_ACCESS_TOKEN AccessToken; NTSTATUS Status; /* Create the process with a suspended main thread */ @@ -47,11 +48,14 @@ CreateProcessAsUserA (HANDLE hToken, return FALSE; } + AccessToken.Token = hToken; + AccessToken.Thread = NULL; + /* Set the new process token */ Status = NtSetInformationProcess (lpProcessInformation->hProcess, ProcessAccessToken, - (PVOID)&hToken, - sizeof (HANDLE)); + (PVOID)&AccessToken, + sizeof (AccessToken)); if (!NT_SUCCESS (Status)) { SetLastError (RtlNtStatusToDosError (Status)); @@ -84,6 +88,7 @@ CreateProcessAsUserW (HANDLE hToken, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { + PROCESS_ACCESS_TOKEN AccessToken; NTSTATUS Status; /* Create the process with a suspended main thread */ @@ -101,11 +106,14 @@ CreateProcessAsUserW (HANDLE hToken, return FALSE; } + AccessToken.Token = hToken; + AccessToken.Thread = NULL; + /* Set the new process token */ Status = NtSetInformationProcess (lpProcessInformation->hProcess, ProcessAccessToken, - (PVOID)&hToken, - sizeof (HANDLE)); + (PVOID)&AccessToken, + sizeof (AccessToken)); if (!NT_SUCCESS (Status)) { SetLastError (RtlNtStatusToDosError (Status)); diff --git a/reactos/lib/advapi32/reg/reg.c b/reactos/lib/advapi32/reg/reg.c index 68dba4b0be7..9c6a668a95b 100644 --- a/reactos/lib/advapi32/reg/reg.c +++ b/reactos/lib/advapi32/reg/reg.c @@ -24,7 +24,7 @@ /* GLOBALS ******************************************************************/ -static CRITICAL_SECTION HandleTableCS; +static RTL_CRITICAL_SECTION HandleTableCS; static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]; static HANDLE ProcessHeap; diff --git a/reactos/lib/advapi32/sec/lsa.c b/reactos/lib/advapi32/sec/lsa.c index eaf061034d0..bc915a6d4c8 100644 --- a/reactos/lib/advapi32/sec/lsa.c +++ b/reactos/lib/advapi32/sec/lsa.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/advapi32/sec/lsa.c @@ -493,3 +492,19 @@ LsaStorePrivateData( { return STATUS_NOT_IMPLEMENTED; } + +/* + * @unimplemented + */ +NTSTATUS +STDCALL +LsaGetUserName( + PUNICODE_STRING *UserName, + PUNICODE_STRING *DomainName) +{ + DPRINT1("LsaGetUserName not implemented\n"); + + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/lib/advapi32/sec/sec.c b/reactos/lib/advapi32/sec/sec.c index 00b353eeac1..790a33dc6e3 100644 --- a/reactos/lib/advapi32/sec/sec.c +++ b/reactos/lib/advapi32/sec/sec.c @@ -124,7 +124,7 @@ GetSecurityDescriptorOwner ( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID *pOwner, LPBOOL lpbOwnerDefaulted -) + ) { BOOLEAN OwnerDefaulted; NTSTATUS Status; @@ -144,6 +144,23 @@ GetSecurityDescriptorOwner ( } +/* + * @implemented + */ +DWORD +STDCALL +GetSecurityDescriptorRMControl ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl) +{ + if (!RtlGetSecurityDescriptorRMControl(SecurityDescriptor, + RMControl)) + return ERROR_INVALID_DATA; + + return ERROR_SUCCESS; +} + + /* * @implemented */ @@ -241,7 +258,7 @@ MakeAbsoluteSD ( { NTSTATUS Status; - Status = RtlSelfRelativeToAbsoluteSD (pSelfRelativeSecurityDescriptor, + Status = RtlSelfRelativeToAbsoluteSD ((PSECURITY_DESCRIPTOR_RELATIVE)pSelfRelativeSecurityDescriptor, pAbsoluteSecurityDescriptor, lpdwAbsoluteSecurityDescriptorSize, pDacl, @@ -276,7 +293,7 @@ MakeSelfRelativeSD ( NTSTATUS Status; Status = RtlAbsoluteToSelfRelativeSD (pAbsoluteSecurityDescriptor, - pSelfRelativeSecurityDescriptor, + (PSECURITY_DESCRIPTOR_RELATIVE)pSelfRelativeSecurityDescriptor, (PULONG)lpdwBufferLength); if (!NT_SUCCESS(Status)) { @@ -288,6 +305,31 @@ MakeSelfRelativeSD ( } +/* + * @implemented + */ +BOOL +STDCALL +SetSecurityDescriptorControl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet) +{ + NTSTATUS Status; + + Status = RtlSetControlSecurityDescriptor(pSecurityDescriptor, + ControlBitsOfInterest, + ControlBitsToSet); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + /* * @implemented */ @@ -368,6 +410,22 @@ SetSecurityDescriptorOwner ( } +/* + * @implemented + */ +DWORD +STDCALL +SetSecurityDescriptorRMControl ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl) +{ + RtlSetSecurityDescriptorRMControl(SecurityDescriptor, + RMControl); + + return ERROR_SUCCESS; +} + + /* * @implemented */ diff --git a/reactos/lib/advapi32/sec/trustee.c b/reactos/lib/advapi32/sec/trustee.c index b9ef34fc2aa..a408d7d71b2 100644 --- a/reactos/lib/advapi32/sec/trustee.c +++ b/reactos/lib/advapi32/sec/trustee.c @@ -36,6 +36,96 @@ BuildImpersonateTrusteeW(PTRUSTEE_W pTrustee, } +/****************************************************************************** + * BuildExplicitAccessWithNameA [ADVAPI32.@] + */ +VOID WINAPI +BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess, + LPSTR pTrusteeName, + DWORD AccessPermissions, + ACCESS_MODE AccessMode, + DWORD Inheritance) +{ + pExplicitAccess->grfAccessPermissions = AccessPermissions; + pExplicitAccess->grfAccessMode = AccessMode; + pExplicitAccess->grfInheritance = Inheritance; + + pExplicitAccess->Trustee.pMultipleTrustee = NULL; + pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; + pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + pExplicitAccess->Trustee.ptstrName = pTrusteeName; +} + + +/****************************************************************************** + * BuildExplicitAccessWithNameW [ADVAPI32.@] + */ +VOID WINAPI +BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess, + LPWSTR pTrusteeName, + DWORD AccessPermissions, + ACCESS_MODE AccessMode, + DWORD Inheritance) +{ + pExplicitAccess->grfAccessPermissions = AccessPermissions; + pExplicitAccess->grfAccessMode = AccessMode; + pExplicitAccess->grfInheritance = Inheritance; + + pExplicitAccess->Trustee.pMultipleTrustee = NULL; + pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; + pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + pExplicitAccess->Trustee.ptstrName = pTrusteeName; +} + + +/****************************************************************************** + * BuildImpersonateExplicitAccessWithNameA [ADVAPI32.@] + */ +VOID WINAPI +BuildImpersonateExplicitAccessWithNameA(PEXPLICIT_ACCESS_A pExplicitAccess, + LPSTR pTrusteeName, + PTRUSTEE_A pTrustee, + DWORD AccessPermissions, + ACCESS_MODE AccessMode, + DWORD Inheritance) +{ + pExplicitAccess->grfAccessPermissions = AccessPermissions; + pExplicitAccess->grfAccessMode = AccessMode; + pExplicitAccess->grfInheritance = Inheritance; + + pExplicitAccess->Trustee.pMultipleTrustee = pTrustee; + pExplicitAccess->Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE; + pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; + pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + pExplicitAccess->Trustee.ptstrName = pTrusteeName; +} + + +/****************************************************************************** + * BuildImpersonateExplicitAccessWithNameW [ADVAPI32.@] + */ +VOID WINAPI +BuildImpersonateExplicitAccessWithNameW(PEXPLICIT_ACCESS_W pExplicitAccess, + LPWSTR pTrusteeName, + PTRUSTEE_W pTrustee, + DWORD AccessPermissions, + ACCESS_MODE AccessMode, + DWORD Inheritance) +{ + pExplicitAccess->grfAccessPermissions = AccessPermissions; + pExplicitAccess->grfAccessMode = AccessMode; + pExplicitAccess->grfInheritance = Inheritance; + + pExplicitAccess->Trustee.pMultipleTrustee = pTrustee; + pExplicitAccess->Trustee.MultipleTrusteeOperation = TRUSTEE_IS_IMPERSONATE; + pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; + pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + pExplicitAccess->Trustee.ptstrName = pTrusteeName; +} + + /****************************************************************************** * BuildTrusteeWithSidA [ADVAPI32.@] */ diff --git a/reactos/lib/advapi32/service/sctrl.c b/reactos/lib/advapi32/service/sctrl.c index 08319086856..e6fd2499b58 100644 --- a/reactos/lib/advapi32/service/sctrl.c +++ b/reactos/lib/advapi32/service/sctrl.c @@ -13,46 +13,56 @@ /* INCLUDES ******************************************************************/ #include "advapi32.h" +#include + #define NDEBUG #include /* TYPES *********************************************************************/ -typedef struct +typedef struct _ACTIVE_SERVICE { DWORD ThreadId; UNICODE_STRING ServiceName; - LPSERVICE_MAIN_FUNCTIONW MainFunction; + union + { + LPSERVICE_MAIN_FUNCTIONA lpFuncA; + LPSERVICE_MAIN_FUNCTIONW lpFuncW; + } Main; LPHANDLER_FUNCTION HandlerFunction; + LPHANDLER_FUNCTION_EX HandlerFunctionEx; + LPVOID HandlerContext; SERVICE_STATUS ServiceStatus; + BOOL bUnicode; + LPWSTR Arguments; } ACTIVE_SERVICE, *PACTIVE_SERVICE; + /* GLOBALS *******************************************************************/ -static ULONG ActiveServiceCount; -static PACTIVE_SERVICE ActiveServices; -/* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in use */ +static DWORD dwActiveServiceCount = 0; +static PACTIVE_SERVICE lpActiveServices = NULL; + /* FUNCTIONS *****************************************************************/ - static PACTIVE_SERVICE ScLookupServiceByServiceName(LPWSTR lpServiceName) { DWORD i; - for (i = 0; i < ActiveServiceCount; i++) + for (i = 0; i < dwActiveServiceCount; i++) { - if (_wcsicmp(ActiveServices[i].ServiceName.Buffer, lpServiceName) == 0) + if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0) { - return(&ActiveServices[i]); + return &lpActiveServices[i]; } } SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); - return(NULL); + return NULL; } @@ -61,17 +71,73 @@ ScLookupServiceByThreadId(DWORD ThreadId) { DWORD i; - for (i = 0; i < ActiveServiceCount; i++) + for (i = 0; i < dwActiveServiceCount; i++) { - if (ActiveServices[i].ThreadId == ThreadId) + if (lpActiveServices[i].ThreadId == ThreadId) { - return(&ActiveServices[i]); + return &lpActiveServices[i]; } } SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); - return(NULL); + return NULL; +} + + +static DWORD WINAPI +ScServiceMainStub(LPVOID Context) +{ + PACTIVE_SERVICE lpService; + DWORD dwArgCount = 0; + DWORD dwLength = 0; + + lpService = (PACTIVE_SERVICE)Context; + + DPRINT("ScServiceMainStub() called\n"); + + /* Count arguments */ + while (lpService->Arguments[dwLength]) + { + dwLength += wcslen(&lpService->Arguments[dwLength]) + 1; + dwArgCount++; + } + + /* Build the argument vector and call the main service routine */ + if (lpService->bUnicode) + { + LPWSTR *lpArgVector; + LPWSTR Ptr; + + lpArgVector = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + (dwArgCount + 1) * sizeof(LPWSTR)); + if (lpArgVector == NULL) + return ERROR_OUTOFMEMORY; + + dwArgCount = 0; + Ptr = lpService->Arguments; + while (*Ptr) + { + lpArgVector[dwArgCount] = Ptr; + + dwArgCount++; + Ptr += (wcslen(Ptr) + 1); + } + lpArgVector[dwArgCount] = NULL; + + (lpService->Main.lpFuncW)(dwArgCount, lpArgVector); + + HeapFree(GetProcessHeap(), + 0, + lpArgVector); + } + else + { + (lpService->Main.lpFuncA)(0, NULL); + } + + return ERROR_SUCCESS; } @@ -82,25 +148,31 @@ ScConnectControlPipe(HANDLE *hPipe) DWORD dwProcessId; DWORD dwState; - WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", - 15000); + if (!WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", 15000)) + { + DPRINT1("WaitNamedPipe() failed (Error %lu)\n", GetLastError()); + return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT; + } *hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (*hPipe == INVALID_HANDLE_VALUE) - return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT); + { + DPRINT1("CreateFileW() failed (Error %lu)\n", GetLastError()); + return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT; + } dwState = PIPE_READMODE_MESSAGE; if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL)) { CloseHandle(hPipe); *hPipe = INVALID_HANDLE_VALUE; - return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT); + return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT; } dwProcessId = GetCurrentProcessId(); @@ -110,37 +182,102 @@ ScConnectControlPipe(HANDLE *hPipe) &dwBytesWritten, NULL); - return(ERROR_SUCCESS); + DPRINT("Sent process id %lu\n", dwProcessId); + + return ERROR_SUCCESS; } -static VOID -ScServiceDispatcher(HANDLE hPipe, PVOID p1, PVOID p2) -{ - DPRINT1("ScDispatcherLoop() called\n"); -#if 0 +static DWORD +ScStartService(PSCM_START_PACKET StartPacket) +{ + PACTIVE_SERVICE lpService; + HANDLE ThreadHandle; + + DPRINT("Size: %lu\n", StartPacket->Size); + DPRINT("Service: %S\n", &StartPacket->Arguments[0]); + + lpService = ScLookupServiceByServiceName(&StartPacket->Arguments[0]); + if (lpService == NULL) + return ERROR_SERVICE_DOES_NOT_EXIST; + + lpService->Arguments = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + StartPacket->Size); + if (lpService->Arguments == NULL) + return ERROR_OUTOFMEMORY; + + memcpy(lpService->Arguments, + StartPacket->Arguments, + StartPacket->Size * sizeof(WCHAR)); + + ThreadHandle = CreateThread(NULL, + 0, + ScServiceMainStub, + lpService, + CREATE_SUSPENDED, + &lpService->ThreadId); + if (ThreadHandle == NULL) + return ERROR_SERVICE_NO_THREAD; + + ResumeThread(ThreadHandle); + CloseHandle(ThreadHandle); + + return ERROR_SUCCESS; +} + + +static BOOL +ScServiceDispatcher(HANDLE hPipe, + PUCHAR lpBuffer, + DWORD dwBufferSize) +{ + LPDWORD Buffer; + DWORD Count; + BOOL bResult; + + DPRINT("ScDispatcherLoop() called\n"); + + Buffer = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + 1024); + if (Buffer == NULL) + return FALSE; + while (TRUE) { /* Read command from the control pipe */ + bResult = ReadFile(hPipe, + Buffer, + 1024, + &Count, + NULL); + if (bResult == FALSE) + { + DPRINT1("Pipe read failed\n"); + return FALSE; + } /* Execute command */ + switch (Buffer[0]) + { + case SCM_START_COMMAND: + DPRINT("Start command\n"); + ScStartService((PSCM_START_PACKET)Buffer); + break; + default: + DPRINT1("Unknown command %lu", Buffer[0]); + break; + } } -#endif -} + HeapFree(GetProcessHeap(), + 0, + Buffer); -DWORD WINAPI -ScServiceMainStub(LPVOID Context) -{ - LPSERVICE_MAIN_FUNCTIONW lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)Context; - - /* FIXME: Send argc and argv (from command line) as arguments */ - - (lpServiceProc)(0, NULL); - - return ERROR_SUCCESS; + return TRUE; } @@ -161,7 +298,7 @@ RegisterServiceCtrlHandlerA(LPCSTR lpServiceName, if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE))) { SetLastError(ERROR_OUTOFMEMORY); - return((SERVICE_STATUS_HANDLE)0); + return (SERVICE_STATUS_HANDLE)0; } SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer, @@ -169,7 +306,7 @@ RegisterServiceCtrlHandlerA(LPCSTR lpServiceName, RtlFreeUnicodeString(&ServiceNameU); - return(SHandle); + return SHandle; } @@ -187,12 +324,70 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName); if (Service == NULL) { - return((SERVICE_STATUS_HANDLE)NULL); + return (SERVICE_STATUS_HANDLE)NULL; } Service->HandlerFunction = lpHandlerProc; + Service->HandlerFunctionEx = NULL; - return((SERVICE_STATUS_HANDLE)Service->ThreadId); + return (SERVICE_STATUS_HANDLE)Service->ThreadId; +} + + +/********************************************************************** + * RegisterServiceCtrlHandlerExA + * + * @implemented + */ +SERVICE_STATUS_HANDLE STDCALL +RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName, + LPHANDLER_FUNCTION_EX lpHandlerProc, + LPVOID lpContext) +{ + ANSI_STRING ServiceNameA; + UNICODE_STRING ServiceNameU; + SERVICE_STATUS_HANDLE SHandle; + + RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName); + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE))) + { + SetLastError(ERROR_OUTOFMEMORY); + return (SERVICE_STATUS_HANDLE)0; + } + + SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer, + lpHandlerProc, + lpContext); + + RtlFreeUnicodeString(&ServiceNameU); + + return SHandle; +} + + +/********************************************************************** + * RegisterServiceCtrlHandlerExW + * + * @implemented + */ +SERVICE_STATUS_HANDLE STDCALL +RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, + LPHANDLER_FUNCTION_EX lpHandlerProc, + LPVOID lpContext) +{ + PACTIVE_SERVICE Service; + + Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName); + if (Service == NULL) + { + return (SERVICE_STATUS_HANDLE)NULL; + } + + Service->HandlerFunction = NULL; + Service->HandlerFunctionEx = lpHandlerProc; + Service->HandlerContext = lpContext; + + return (SERVICE_STATUS_HANDLE)Service->ThreadId; } @@ -208,7 +403,7 @@ SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus, BOOL bUpdateImmediately) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return(FALSE); + return FALSE; } @@ -242,14 +437,14 @@ SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, if (!Service) { SetLastError(ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } RtlCopyMemory(&Service->ServiceStatus, lpServiceStatus, sizeof(SERVICE_STATUS)); - return(TRUE); + return TRUE; } @@ -261,65 +456,72 @@ SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, BOOL STDCALL StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable) { - // FIXME how to deal with diffs between ANSI/UNICODE -#if 0 - LPSERVICE_TABLE_ENTRYW ServiceStartTableW; - ANSI_STRING ServiceNameA; - UNICODE_STRING ServiceNameW; - ULONG i, j; - ULONG Count; - BOOL b; + ULONG i; + HANDLE hPipe; + DWORD dwError; + PUCHAR lpMessageBuffer; + + DPRINT("StartServiceCtrlDispatcherA() called\n"); i = 0; while (lpServiceStartTable[i].lpServiceProc != NULL) { i++; } - Count = i; - ServiceStartTableW = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - sizeof(SERVICE_TABLE_ENTRYW) * Count); - for (i = 0; i < Count; i++) - { - RtlInitAnsiString( - &ServiceNameA, - lpServiceStartTable[i].lpServiceName); - if (!NT_SUCCESS(RtlAnsiStringToUnicodeString( - &ServiceNameW, - &ServiceNameA, - TRUE))) + dwActiveServiceCount = i; + lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + dwActiveServiceCount * sizeof(ACTIVE_SERVICE)); + if (lpActiveServices == NULL) { - for (j = 0; j < i; j++) - { - RtlInitUnicodeString( - &ServiceNameW, - ServiceStartTableW[j].lpServiceName); - RtlFreeUnicodeString(&ServiceNameW); - } - RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW); - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - ServiceStartTableW[i].lpServiceName = ServiceNameW.Buffer; - ServiceStartTableW[i].lpServiceProc = - lpServiceStartTable[i].lpServiceProc; - } - - b = StartServiceCtrlDispatcherW(ServiceStartTableW); - - for (i = 0; i < Count; i++) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW[i].lpServiceName); + return FALSE; } - RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW); + /* Copy service names and start procedure */ + for (i = 0; i < dwActiveServiceCount; i++) + { + RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName, + lpServiceStartTable[i].lpServiceName); + lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc; + lpActiveServices[i].bUnicode = FALSE; + } - return b; -#else - UNIMPLEMENTED; - return 0; -#endif + dwError = ScConnectControlPipe(&hPipe); + if (dwError != ERROR_SUCCESS) + { + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; + return FALSE; + } + + lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + 256); + if (lpMessageBuffer == NULL) + { + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; + CloseHandle(hPipe); + return FALSE; + } + + ScServiceDispatcher(hPipe, lpMessageBuffer, 256); + CloseHandle(hPipe); + + /* Free the message buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer); + + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; + + return TRUE; } @@ -334,6 +536,7 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable) ULONG i; HANDLE hPipe; DWORD dwError; + PUCHAR lpMessageBuffer; DPRINT("StartServiceCtrlDispatcherW() called\n"); @@ -343,99 +546,59 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable) i++; } - ActiveServiceCount = i; - ActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - ActiveServiceCount * sizeof(ACTIVE_SERVICE)); - if (ActiveServices == NULL) + dwActiveServiceCount = i; + lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + dwActiveServiceCount * sizeof(ACTIVE_SERVICE)); + if (lpActiveServices == NULL) { - return(FALSE); + return FALSE; } /* Copy service names and start procedure */ - for (i = 0; i < ActiveServiceCount; i++) + for (i = 0; i < dwActiveServiceCount; i++) { - RtlCreateUnicodeString(&ActiveServices[i].ServiceName, + RtlCreateUnicodeString(&lpActiveServices[i].ServiceName, lpServiceStartTable[i].lpServiceName); - ActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc; + lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc; + lpActiveServices[i].bUnicode = TRUE; } dwError = ScConnectControlPipe(&hPipe); - if (dwError == ERROR_SUCCESS) + if (dwError != ERROR_SUCCESS) { - /* FIXME: free the service table */ - return(FALSE); + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; + return FALSE; } - ScServiceDispatcher(hPipe, NULL, NULL); + lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + 256); + if (lpMessageBuffer == NULL) + { + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; + CloseHandle(hPipe); + return FALSE; + } + + ScServiceDispatcher(hPipe, lpMessageBuffer, 256); CloseHandle(hPipe); - /* FIXME: free the service table */ + /* Free the message buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer); - return(TRUE); + /* Free the service table */ + RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices); + lpActiveServices = NULL; + dwActiveServiceCount = 0; -#if 0 - ActiveServicesThreadHandles = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - (ActiveServiceCount + 1) * sizeof(HANDLE)); - if (!ActiveServicesThreadHandles) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices); - ActiveServices = NULL; - return(FALSE); - } - - for (i = 0; i 0) - { - r = WaitForMultipleObjects( - ActiveServiceCount + 1, - ActiveServicesThreadHandles, - FALSE, - INFINITE); - if (r == WAIT_OBJECT_0) - { - /* Received message from the scm */ - } - else if (r > WAIT_OBJECT_0 && r < (WAIT_OBJECT_0 + ActiveServiceCount)) - { - /* A service died */ - - ActiveServiceCount--; - ActiveServicesThreadHandles[r - WAIT_OBJECT_0 - 1] = - ActiveServicesThreadHandles[ActiveServiceCount + 1]; - RtlCopyMemory( - &ActiveServices[r - WAIT_OBJECT_0 - 2], - &ActiveServices[ActiveServiceCount], - sizeof(ACTIVE_SERVICE)); - } - else - { - /* Bail */ - } - } return TRUE; -#endif } /* EOF */ diff --git a/reactos/lib/advapi32/token/token.c b/reactos/lib/advapi32/token/token.c index 9b7a0c51a66..3b42ec8d0d1 100644 --- a/reactos/lib/advapi32/token/token.c +++ b/reactos/lib/advapi32/token/token.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/advapi32/token/token.c @@ -11,6 +10,8 @@ #include "advapi32.h" +#define NDEBUG +#include /* * @implemented @@ -310,4 +311,87 @@ DuplicateToken (HANDLE ExistingTokenHandle, DuplicateTokenHandle); } + +/* + * @implemented + */ +BOOL STDCALL +CheckTokenMembership (HANDLE ExistingTokenHandle, + PSID SidToCheck, + PBOOL IsMember) +{ + HANDLE AccessToken; + BOOL ReleaseToken = FALSE; + BOOL Result = FALSE; + DWORD dwSize; + DWORD i; + PTOKEN_GROUPS lpGroups = NULL; + TOKEN_TYPE TokenInformation; + + if (IsMember == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (ExistingTokenHandle == NULL) + { + /* Get impersonation token of the calling thread */ + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &ExistingTokenHandle)) + return FALSE; + + if (!DuplicateToken(ExistingTokenHandle, SecurityAnonymous, &AccessToken)) + { + CloseHandle(ExistingTokenHandle); + goto ByeBye; + } + CloseHandle(ExistingTokenHandle); + ReleaseToken = TRUE; + } + else + { + if (!GetTokenInformation(ExistingTokenHandle, TokenType, &TokenInformation, sizeof(TokenInformation), &dwSize)) + goto ByeBye; + if (TokenInformation != TokenImpersonation) + { + /* Duplicate token to have a impersonation token */ + if (!DuplicateToken(ExistingTokenHandle, SecurityAnonymous, &AccessToken)) + return FALSE; + ReleaseToken = TRUE; + } + else + AccessToken = ExistingTokenHandle; + } + + *IsMember = FALSE; + /* Search in groups of the token */ + if (!GetTokenInformation(AccessToken, TokenGroups, NULL, 0, &dwSize)) + goto ByeBye; + lpGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 0, dwSize); + if (!lpGroups) + goto ByeBye; + if (!GetTokenInformation(AccessToken, TokenGroups, lpGroups, dwSize, &dwSize)) + goto ByeBye; + for (i = 0; i < lpGroups->GroupCount; i++) + { + if (EqualSid(SidToCheck, &lpGroups->Groups[i].Sid)) + { + Result = TRUE; + *IsMember = TRUE; + goto ByeBye; + } + } + /* FIXME: Search in users of the token? */ + DPRINT1("CheckTokenMembership() partially implemented!\n"); + Result = TRUE; + +ByeBye: + if (lpGroups != NULL) + HeapFree(GetProcessHeap(), 0, lpGroups); + if (ReleaseToken) + CloseHandle(AccessToken); + + return Result; +} + /* EOF */ diff --git a/reactos/lib/cabinet/cabinet_main.c b/reactos/lib/cabinet/cabinet_main.c index 8a46c59f2e9..f5020ac7b3f 100644 --- a/reactos/lib/cabinet/cabinet_main.c +++ b/reactos/lib/cabinet/cabinet_main.c @@ -121,8 +121,10 @@ HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR what) TRACE("extracting to dir: %s\n", debugstr_a(dir)); /* FIXME: what to do on failure? */ - if (!process_cabinet(what, dir, FALSE, FALSE, dest)) + if (!process_cabinet(what, dir, FALSE, FALSE, dest)) { + LocalFree(dir); return E_OUTOFMEMORY; + } LocalFree(dir); diff --git a/reactos/lib/comctl32/animate.c b/reactos/lib/comctl32/animate.c index 66cf7f28b51..ce9b3f3f41a 100644 --- a/reactos/lib/comctl32/animate.c +++ b/reactos/lib/comctl32/animate.c @@ -187,32 +187,20 @@ static void ANIMATE_Free(ANIMATE_INFO *infoPtr) FreeResource(infoPtr->hRes); infoPtr->hRes = 0; } - if (infoPtr->lpIndex) { - HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex); - infoPtr->lpIndex = NULL; - } + HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex); + infoPtr->lpIndex = NULL; if (infoPtr->hic) { fnIC.fnICClose(infoPtr->hic); infoPtr->hic = 0; } - if (infoPtr->inbih) { - HeapFree(GetProcessHeap(), 0, infoPtr->inbih); - infoPtr->inbih = NULL; - } - if (infoPtr->outbih) { - HeapFree(GetProcessHeap(), 0, infoPtr->outbih); - infoPtr->outbih = NULL; - } - if( infoPtr->indata ) - { + HeapFree(GetProcessHeap(), 0, infoPtr->inbih); + infoPtr->inbih = NULL; + HeapFree(GetProcessHeap(), 0, infoPtr->outbih); + infoPtr->outbih = NULL; HeapFree(GetProcessHeap(), 0, infoPtr->indata); - infoPtr->indata = NULL; - } - if( infoPtr->outdata ) - { + infoPtr->indata = NULL; HeapFree(GetProcessHeap(), 0, infoPtr->outdata); - infoPtr->outdata = NULL; - } + infoPtr->outdata = NULL; if( infoPtr->hbmPrevFrame ) { DeleteObject(infoPtr->hbmPrevFrame); diff --git a/reactos/lib/comctl32/comboex.c b/reactos/lib/comctl32/comboex.c index 5551b58d7a8..8cff35a286a 100644 --- a/reactos/lib/comctl32/comboex.c +++ b/reactos/lib/comctl32/comboex.c @@ -1840,7 +1840,6 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return CallWindowProcW (infoPtr->prevEditWndProc, hwnd, uMsg, wParam, lParam); } - return 0; } @@ -2243,7 +2242,6 @@ COMBOEX_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ERR("unknown msg %04x wp=%08x lp=%08lx\n",uMsg,wParam,lParam); return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/comctl32undoc.c b/reactos/lib/comctl32/comctl32undoc.c index fd7cbfab4fd..3eae1aebf57 100644 --- a/reactos/lib/comctl32/comctl32undoc.c +++ b/reactos/lib/comctl32/comctl32undoc.c @@ -106,9 +106,8 @@ typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); * NOTES * No more information available yet! */ - -HRESULT WINAPI -DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam) +HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, + IStream *pStream, LPARAM lParam) { HRESULT errCode; LARGE_INTEGER position; @@ -205,9 +204,8 @@ DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lPar * NOTES * No more information available yet! */ - -HRESULT WINAPI -DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam) +HRESULT WINAPI DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, + IStream *pStream, LPARAM lParam) { FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n", @@ -220,6 +218,8 @@ DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM /************************************************************************** * DPA_Merge [COMCTL32.11] * + * Merge two dynamic pointers arrays. + * * PARAMS * hdpa1 [I] handle to a dynamic pointer array * hdpa2 [I] handle to a dynamic pointer array @@ -235,10 +235,9 @@ DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM * NOTES * No more information available yet! */ - -BOOL WINAPI -DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, - PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam) +BOOL WINAPI DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, + PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, + LPARAM lParam) { INT nCount; LPVOID *pWork1, *pWork2; @@ -373,7 +372,6 @@ DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, * Success: pointer to allocated memory block * Failure: NULL */ - LPVOID WINAPI Alloc (DWORD dwSize) { return LocalAlloc( LMEM_ZEROINIT, dwSize ); @@ -398,7 +396,6 @@ LPVOID WINAPI Alloc (DWORD dwSize) * If lpSrc is a NULL-pointer, then ReAlloc allocates a memory * block like Alloc. */ - LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize) { if (lpSrc) @@ -420,7 +417,6 @@ LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize) * Success: TRUE * Failure: FALSE */ - BOOL WINAPI Free (LPVOID lpMem) { return !LocalFree( lpMem ); @@ -440,7 +436,6 @@ BOOL WINAPI Free (LPVOID lpMem) * Success: size of the specified memory block * Failure: 0 */ - DWORD WINAPI GetSize (LPVOID lpMem) { return LocalSize( lpMem ); @@ -448,33 +443,90 @@ DWORD WINAPI GetSize (LPVOID lpMem) /************************************************************************** - * The MRU-API is a set of functions to manipulate MRU(Most Recently Used) - * lists. + * MRU-Functions {COMCTL32} * - * Stored in the reg. as a set of values under a single key. Each item in the - * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'. - * The order of the list is stored with value name 'MRUList' which is a string - * containing the value names (i.e. 'a', 'b', etc.) in the relevant order. + * NOTES + * The MRU-Api is a set of functions to manipulate lists of M.R.U. (Most Recently + * Used) items. It is an undocumented Api that is used (at least) by the shell + * and explorer to implement their recent documents feature. + * + * Since these functions are undocumented, they are unsupported by MS and + * may change at any time. + * + * Internally, the list is implemented as a last in, last out list of items + * persisted into the system registry under a caller chosen key. Each list + * item is given a one character identifier in the Ascii range from 'a' to + * '}'. A list of the identifiers in order from newest to oldest is stored + * under the same key in a value named "MRUList". + * + * Items are re-ordered by changing the order of the values in the MRUList + * value. When a new item is added, it becomes the new value of the oldest + * identifier, and that identifier is moved to the front of the MRUList value. + * + * Wine stores MRU-lists in the same registry format as Windows, so when + * switching between the builtin and native comctl32.dll no problems or + * incompatibilities should occur. + * + * The following undocumented structure is used to create an MRU-list: + *|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs); + *|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length); + *| + *|typedef struct tagCREATEMRULIST + *|{ + *| DWORD cbSize; + *| DWORD nMaxItems; + *| DWORD dwFlags; + *| HKEY hKey; + *| LPCTSTR lpszSubKey; + *| PROC lpfnCompare; + *|} CREATEMRULIST, *LPCREATEMRULIST; + * + * MEMBERS + * cbSize [I] The size of the CREATEMRULIST structure. This must be set + * to sizeof(CREATEMRULIST) by the caller. + * nMaxItems [I] The maximum number of items allowed in the list. Because + * of the limited number of identifiers, this should be set to + * a value from 1 to 30 by the caller. + * dwFlags [I] If bit 0 is set, the list will be used to store binary + * data, otherwise it is assumed to store strings. If bit 1 + * is set, every change made to the list will be reflected in + * the registry immediately, otherwise changes will only be + * written when the list is closed. + * hKey [I] The registry key that the list should be written under. + * This must be supplied by the caller. + * lpszSubKey [I] A caller supplied name of a subkey under hKey to write + * the list to. This may not be blank. + * lpfnCompare [I] A caller supplied comparison function, which may be either + * an MRUStringCmpFn if dwFlags does not have bit 0 set, or a + * MRUBinaryCmpFn otherwise. + * + * FUNCTIONS + * - Create an MRU-list with CreateMRUList() or CreateMRUListLazy(). + * - Add items to an MRU-list with AddMRUString() or AddMRUData(). + * - Remove items from an MRU-list with DelMRUString(). + * - Find data in an MRU-list with FindMRUString() or FindMRUData(). + * - Iterate through an MRU-list with EnumMRUList(). + * - Free an MRU-list with FreeMRUList(). */ typedef struct tagCREATEMRULISTA { - DWORD cbSize; /* size of struct */ - DWORD nMaxItems; /* max no. of items in list */ - DWORD dwFlags; /* see below */ - HKEY hKey; /* root reg. key under which list is saved */ - LPCSTR lpszSubKey; /* reg. subkey */ - PROC lpfnCompare; /* item compare proc */ + DWORD cbSize; + DWORD nMaxItems; + DWORD dwFlags; + HKEY hKey; + LPCSTR lpszSubKey; + PROC lpfnCompare; } CREATEMRULISTA, *LPCREATEMRULISTA; typedef struct tagCREATEMRULISTW { - DWORD cbSize; /* size of struct */ - DWORD nMaxItems; /* max no. of items in list */ - DWORD dwFlags; /* see below */ - HKEY hKey; /* root reg. key under which list is saved */ - LPCWSTR lpszSubKey; /* reg. subkey */ - PROC lpfnCompare; /* item compare proc */ + DWORD cbSize; + DWORD nMaxItems; + DWORD dwFlags; + HKEY hKey; + LPCWSTR lpszSubKey; + PROC lpfnCompare; } CREATEMRULISTW, *LPCREATEMRULISTW; /* dwFlags */ @@ -517,9 +569,9 @@ typedef struct tagWINEMRULIST /************************************************************************** * MRU_SaveChanged (internal) * - * Localize MRU saving code + * Local MRU saving code */ -VOID MRU_SaveChanged( LPWINEMRULIST mp ) +static void MRU_SaveChanged ( LPWINEMRULIST mp ) { UINT i, err; HKEY newkey; @@ -587,16 +639,17 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp ) * hMRUList [I] Handle to list. * * RETURNS - * Success: TRUE - * Failure: FALSE + * Nothing. */ -BOOL WINAPI -FreeMRUList (HANDLE hMRUList) +void WINAPI FreeMRUList (HANDLE hMRUList) { LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList; UINT i; - TRACE("\n"); + TRACE("(%p)\n", hMRUList); + if (!hMRUList) + return; + if (mp->wineFlags & WMRUF_CHANGED) { /* need to open key and then save the info */ MRU_SaveChanged( mp ); @@ -609,7 +662,7 @@ FreeMRUList (HANDLE hMRUList) Free(mp->realMRU); Free(mp->array); Free((LPWSTR)mp->extview.lpszSubKey); - return Free(mp); + Free(mp); } @@ -629,8 +682,8 @@ FreeMRUList (HANDLE hMRUList) * RETURNS * Position in list 0 -> MRU. -1 if item not found. */ -INT WINAPI -FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum) +INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, + LPINT lpRegNum) { LPWINEMRULIST mp = (LPWINEMRULIST)hList; INT ret; @@ -707,14 +760,22 @@ FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum) * No. corresponding to registry name where value is stored 'a' -> 0 etc. * -1 on error. */ -INT WINAPI -AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) +INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) { LPWINEMRULIST mp = (LPWINEMRULIST)hList; LPWINEMRUITEM witem; - INT i, replace, ret; + INT i, replace; - if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) { + if ((replace = FindMRUData (hList, lpData, cbData, NULL)) >= 0) { + /* Item exists, just move it to the front */ + LPSTR pos = strchr(mp->realMRU, replace + 'a'); + while (pos > mp->realMRU) + { + pos[0] = pos[-1]; + pos--; + } + } + else { /* either add a new entry or replace oldest */ if (mp->cursize < mp->extview.nMaxItems) { /* Add in a new item */ @@ -726,57 +787,73 @@ AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) replace = mp->realMRU[mp->cursize - 1] - 'a'; Free(mp->array[replace]); } - } - else { - /* free up the old data */ - Free(mp->array[replace]); + + /* Allocate space for new item and move in the data */ + mp->array[replace] = witem = Alloc(cbData + sizeof(WINEMRUITEM)); + witem->itemFlag |= WMRUIF_CHANGED; + witem->size = cbData; + memcpy( &witem->datastart, lpData, cbData); + + /* now rotate MRU list */ + for(i=mp->cursize-1; i>=1; i--) + mp->realMRU[i] = mp->realMRU[i-1]; } - /* Allocate space for new item and move in the data */ - mp->array[replace] = witem = Alloc(cbData + sizeof(WINEMRUITEM)); - witem->itemFlag |= WMRUIF_CHANGED; - witem->size = cbData; - memcpy( &witem->datastart, lpData, cbData); - - /* now rotate MRU list */ + /* The new item gets the front spot */ mp->wineFlags |= WMRUF_CHANGED; - for(i=mp->cursize-1; i>=1; i--) { - mp->realMRU[i] = mp->realMRU[i-1]; - } mp->realMRU[0] = replace + 'a'; + TRACE("(%p, %p, %ld) adding data, /%c/ now most current\n", - hList, lpData, cbData, replace+'a'); - ret = replace; + hList, lpData, cbData, replace+'a'); if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) { /* save changed stuff right now */ MRU_SaveChanged( mp ); } - return ret; + return replace; } /************************************************************************** * AddMRUStringW [COMCTL32.401] * - * Add item to MRU string list. If item already exists in list them it is - * simply moved up to the top of the list and not added again. If list is - * full then the least recently used item is removed to make room. + * Add an item to an MRU string list. * * PARAMS - * hList [I] Handle to list. - * lpszString [I] ptr to string to add. + * hList [I] Handle to list. + * lpszString [I] The string to add. * * RETURNS - * No. corresponding to registry name where value is stored 'a' -> 0 etc. - * -1 on error. + * Success: The number corresponding to the registry name where the string + * has been stored (0 maps to 'a', 1 to 'b' and so on). + * Failure: -1, if hList is NULL or memory allocation fails. If lpszString + * is invalid, the function returns 0, and GetLastError() returns + * ERROR_INVALID_PARAMETER. The last error value is set only in + * this case. + * + * NOTES + * -If lpszString exists in the list already, it is moved to the top of the + * MRU list (it is not duplicated). + * -If the list is full the least recently used list entry is replaced with + * lpszString. + * -If this function returns 0 you should check the last error value to + * ensure the call really succeeded. */ -INT WINAPI -AddMRUStringW(HANDLE hList, LPCWSTR lpszString) +INT WINAPI AddMRUStringW(HANDLE hList, LPCWSTR lpszString) { - FIXME("(%p, %s) empty stub!\n", hList, debugstr_w(lpszString)); + TRACE("(%p,%s)\n", hList, debugstr_w(lpszString)); - return 0; + if (!hList) + return -1; + + if (!lpszString || IsBadStringPtrW(lpszString, -1)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + return AddMRUData(hList, lpszString, + (strlenW(lpszString) + 1) * sizeof(WCHAR)); } /************************************************************************** @@ -784,12 +861,32 @@ AddMRUStringW(HANDLE hList, LPCWSTR lpszString) * * See AddMRUStringW. */ -INT WINAPI -AddMRUStringA(HANDLE hList, LPCSTR lpszString) +INT WINAPI AddMRUStringA(HANDLE hList, LPCSTR lpszString) { - FIXME("(%p, %s) empty stub!\n", hList, debugstr_a(lpszString)); + DWORD len; + LPWSTR stringW; + INT ret; - return 0; + TRACE("(%p,%s)\n", hList, debugstr_a(lpszString)); + + if (!hList) + return -1; + + if (IsBadStringPtrA(lpszString, -1)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0) * sizeof(WCHAR); + stringW = Alloc(len); + if (!stringW) + return -1; + + MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len); + ret = AddMRUData(hList, stringW, len); + Free(stringW); + return ret; } /************************************************************************** @@ -804,8 +901,7 @@ AddMRUStringA(HANDLE hList, LPCSTR lpszString) * RETURNS * TRUE if successful, FALSE if nItemPos is out of range. */ -BOOL WINAPI -DelMRUString(HANDLE hList, INT nItemPos) +BOOL WINAPI DelMRUString(HANDLE hList, INT nItemPos) { FIXME("(%p, %d): stub\n", hList, nItemPos); return TRUE; @@ -816,11 +912,10 @@ DelMRUString(HANDLE hList, INT nItemPos) * * See FindMRUStringA. */ -INT WINAPI -FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum) +INT WINAPI FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum) { - FIXME("stub\n"); - return -1; + return FindMRUData(hList, lpszString, + (lstrlenW(lpszString) + 1) * sizeof(WCHAR), lpRegNum); } /************************************************************************** @@ -838,8 +933,7 @@ FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum) * RETURNS * Position in list 0 -> MRU. -1 if item not found. */ -INT WINAPI -FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) +INT WINAPI FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) { DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0); LPWSTR stringW = Alloc(len * sizeof(WCHAR)); @@ -854,7 +948,7 @@ FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) /************************************************************************* * CreateMRUListLazy_common (internal) */ -HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) +static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) { UINT i, err; HKEY newkey; @@ -901,7 +995,7 @@ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) *mp->realMRU = 0; } - TRACE("MRU list = %s\n", mp->realMRU); + TRACE("MRU list = %s, datasize = %ld\n", mp->realMRU, datasize); mp->cursize = datasize - 1; /* datasize now has number of items in the MRUList */ @@ -939,16 +1033,16 @@ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) * * See CreateMRUListLazyA. */ -HANDLE WINAPI -CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) +HANDLE WINAPI CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, + DWORD dwParam3, DWORD dwParam4) { LPWINEMRULIST mp; - if (lpcml == NULL) - return 0; + /* Native does not check for a NULL lpcml */ - if (lpcml->cbSize < sizeof(CREATEMRULISTW)) - return 0; + if (lpcml->cbSize != sizeof(CREATEMRULISTW) || !lpcml->hKey || + IsBadStringPtrW(lpcml->lpszSubKey, -1)) + return NULL; mp = Alloc(sizeof(WINEMRULIST)); memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW)); @@ -973,16 +1067,16 @@ CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWOR * RETURNS * Handle to MRU list. */ -HANDLE WINAPI -CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) +HANDLE WINAPI CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, + DWORD dwParam3, DWORD dwParam4) { LPWINEMRULIST mp; DWORD len; - if (lpcml == NULL) - return 0; + /* Native does not check for a NULL lpcml */ - if (lpcml->cbSize < sizeof(CREATEMRULISTA)) + if (lpcml->cbSize != sizeof(CREATEMRULISTA) || !lpcml->hKey || + IsBadStringPtrA(lpcml->lpszSubKey, -1)) return 0; mp = Alloc(sizeof(WINEMRULIST)); @@ -1000,8 +1094,7 @@ CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWOR * * See CreateMRUListA. */ -HANDLE WINAPI -CreateMRUListW (LPCREATEMRULISTW lpcml) +HANDLE WINAPI CreateMRUListW (LPCREATEMRULISTW lpcml) { return CreateMRUListLazyW(lpcml, 0, 0, 0); } @@ -1017,8 +1110,7 @@ CreateMRUListW (LPCREATEMRULISTW lpcml) * RETURNS * Handle to MRU list. */ -HANDLE WINAPI -CreateMRUListA (LPCREATEMRULISTA lpcml) +HANDLE WINAPI CreateMRUListA (LPCREATEMRULISTA lpcml) { return CreateMRUListLazyA (lpcml, 0, 0, 0); } @@ -1042,8 +1134,8 @@ CreateMRUListA (LPCREATEMRULISTA lpcml) * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in * the list. */ -INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer, -DWORD nBufferSize) +INT WINAPI EnumMRUListW (HANDLE hList, INT nItemPos, LPVOID lpBuffer, + DWORD nBufferSize) { LPWINEMRULIST mp = (LPWINEMRULIST) hList; LPWINEMRUITEM witem; @@ -1067,8 +1159,8 @@ DWORD nBufferSize) * * See EnumMRUListW. */ -INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, -DWORD nBufferSize) +INT WINAPI EnumMRUListA (HANDLE hList, INT nItemPos, LPVOID lpBuffer, + DWORD nBufferSize) { LPWINEMRULIST mp = (LPWINEMRULIST) hList; LPWINEMRUITEM witem; @@ -1110,9 +1202,7 @@ DWORD nBufferSize) * RETURNS * The number of characters copied. */ - -INT WINAPI -Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen) +INT WINAPI Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen) { INT len; @@ -1157,9 +1247,7 @@ Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen) * Set lpSrc to NULL to free the memory allocated by a previous call * to this function. */ - -BOOL WINAPI -Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc) +BOOL WINAPI Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc) { TRACE("(%p %p)\n", lppDest, lpSrc); @@ -1186,9 +1274,7 @@ Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc) * * See Str_GetPtrA. */ - -INT WINAPI -Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen) +INT WINAPI Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen) { INT len; @@ -1221,9 +1307,7 @@ Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen) * * See Str_SetPtrA. */ - -BOOL WINAPI -Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc) +BOOL WINAPI Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc) { TRACE("(%p %p)\n", lppDest, lpSrc); @@ -1260,8 +1344,7 @@ Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc) * Length, in bytes, of the converted string. */ -INT -Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen) +INT Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen) { INT len; @@ -1306,9 +1389,7 @@ Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen) * TRUE: conversion successful * FALSE: error */ - -BOOL -Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) +BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) { TRACE("(%p %s)\n", lppDest, lpSrc); @@ -1350,9 +1431,7 @@ Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) * fixed-size memory blocks. These arrays can store any kind of data * (e.g. strings and icons). */ - -HDSA WINAPI -DSA_Create (INT nSize, INT nGrow) +HDSA WINAPI DSA_Create (INT nSize, INT nGrow) { HDSA hdsa; @@ -1384,9 +1463,7 @@ DSA_Create (INT nSize, INT nGrow) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DSA_Destroy (const HDSA hdsa) +BOOL WINAPI DSA_Destroy (const HDSA hdsa) { TRACE("(%p)\n", hdsa); @@ -1414,9 +1491,7 @@ DSA_Destroy (const HDSA hdsa) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) +BOOL WINAPI DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) { LPVOID pSrc; @@ -1447,9 +1522,7 @@ DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) * Success: pointer to an item * Failure: NULL */ - -LPVOID WINAPI -DSA_GetItemPtr (const HDSA hdsa, INT nIndex) +LPVOID WINAPI DSA_GetItemPtr (const HDSA hdsa, INT nIndex) { LPVOID pSrc; @@ -1482,9 +1555,7 @@ DSA_GetItemPtr (const HDSA hdsa, INT nIndex) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) +BOOL WINAPI DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) { INT nSize, nNewItems; LPVOID pDest, lpTemp; @@ -1540,9 +1611,7 @@ DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) * Success: position of the new item * Failure: -1 */ - -INT WINAPI -DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) +INT WINAPI DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) { INT nNewItems, nSize; LPVOID lpTemp, lpDest; @@ -1603,9 +1672,7 @@ DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) * Success: number of the deleted element * Failure: -1 */ - -INT WINAPI -DSA_DeleteItem (const HDSA hdsa, INT nIndex) +INT WINAPI DSA_DeleteItem (const HDSA hdsa, INT nIndex) { LPVOID lpDest,lpSrc; INT nSize; @@ -1657,9 +1724,7 @@ DSA_DeleteItem (const HDSA hdsa, INT nIndex) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DSA_DeleteAllItems (const HDSA hdsa) +BOOL WINAPI DSA_DeleteAllItems (const HDSA hdsa) { TRACE("(%p)\n", hdsa); @@ -1688,9 +1753,7 @@ DSA_DeleteAllItems (const HDSA hdsa) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DPA_Destroy (const HDPA hdpa) +BOOL WINAPI DPA_Destroy (const HDPA hdpa) { TRACE("(%p)\n", hdpa); @@ -1717,9 +1780,7 @@ DPA_Destroy (const HDPA hdpa) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DPA_Grow (const HDPA hdpa, INT nGrow) +BOOL WINAPI DPA_Grow (const HDPA hdpa, INT nGrow) { TRACE("(%p %d)\n", hdpa, nGrow); @@ -1751,9 +1812,7 @@ DPA_Grow (const HDPA hdpa, INT nGrow) * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, * this implementation just returns NULL. */ - -HDPA WINAPI -DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) +HDPA WINAPI DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) { INT nNewItems, nSize; HDPA hdpaTemp; @@ -1811,9 +1870,7 @@ DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) * Success: pointer * Failure: NULL */ - -LPVOID WINAPI -DPA_GetPtr (const HDPA hdpa, INT nIndex) +LPVOID WINAPI DPA_GetPtr (const HDPA hdpa, INT nIndex) { TRACE("(%p %d)\n", hdpa, nIndex); @@ -1847,9 +1904,7 @@ DPA_GetPtr (const HDPA hdpa, INT nIndex) * Success: index of the specified pointer * Failure: -1 */ - -INT WINAPI -DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) +INT WINAPI DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) { INT i; @@ -1879,9 +1934,7 @@ DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) * Success: index of the inserted pointer * Failure: -1 */ - -INT WINAPI -DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) +INT WINAPI DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) { TRACE("(%p %d %p)\n", hdpa, i, p); @@ -1914,9 +1967,7 @@ DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) +BOOL WINAPI DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) { LPVOID *lpTemp; @@ -1967,9 +2018,7 @@ DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) * Success: deleted pointer * Failure: NULL */ - -LPVOID WINAPI -DPA_DeletePtr (const HDPA hdpa, INT i) +LPVOID WINAPI DPA_DeletePtr (const HDPA hdpa, INT i) { LPVOID *lpDest, *lpSrc, lpTemp = NULL; INT nSize; @@ -2022,9 +2071,7 @@ DPA_DeletePtr (const HDPA hdpa, INT i) * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DPA_DeleteAllPtrs (const HDPA hdpa) +BOOL WINAPI DPA_DeleteAllPtrs (const HDPA hdpa) { TRACE("(%p)\n", hdpa); @@ -2058,10 +2105,8 @@ DPA_DeleteAllPtrs (const HDPA hdpa) * RETURNS * NONE */ - -static VOID -DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, - PFNDPACOMPARE pfnCompare, LPARAM lParam) +static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, + PFNDPACOMPARE pfnCompare, LPARAM lParam) { INT m; LPVOID t; @@ -2109,9 +2154,7 @@ DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, * Success: TRUE * Failure: FALSE */ - -BOOL WINAPI -DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) +BOOL WINAPI DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) { if (!hdpa || !pfnCompare) return FALSE; @@ -2148,10 +2191,8 @@ DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) * Function is NOT tested! * If something goes wrong, blame HIM not ME! (Eric Kohl) */ - -INT WINAPI -DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, - PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) +INT WINAPI DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, + PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) { if (!hdpa || !pfnCompare || !pFind) return -1; @@ -2232,9 +2273,7 @@ DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, * The DPA_ functions can be used to create and manipulate arrays of * pointers. */ - -HDPA WINAPI -DPA_CreateEx (INT nGrow, HANDLE hHeap) +HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap) { HDPA hdpa; @@ -2275,9 +2314,7 @@ DPA_CreateEx (INT nGrow, HANDLE hHeap) * The DPA_ functions can be used to create and manipulate arrays of * pointers. */ - -HDPA WINAPI -DPA_Create (INT nGrow) +HDPA WINAPI DPA_Create (INT nGrow) { return DPA_CreateEx( nGrow, 0 ); } @@ -2302,8 +2339,7 @@ typedef struct tagNOTIFYDATA * DoNotify [Internal] */ -static LRESULT -DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr) +static LRESULT DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr) { NMHDR nmhdr; LPNMHDR lpNmh = NULL; @@ -2355,7 +2391,6 @@ DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr) * message is taken from the NMHDR structure. * If hwndFrom is not -1 then lpHdr can be NULL. */ - LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr) { NOTIFYDATA notify; @@ -2393,7 +2428,6 @@ LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr * message is taken from the NMHDR structure. * If hwndFrom is not -1 then lpHdr can be NULL. */ - LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr, DWORD dwParam5) { @@ -2436,9 +2470,8 @@ LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, * RETURNS * none */ - -VOID WINAPI -DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) +VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, + LPVOID lParam) { INT i; @@ -2471,9 +2504,8 @@ DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) * RETURNS * none */ - -void WINAPI -DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) +void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, + LPVOID lParam) { TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); @@ -2495,9 +2527,8 @@ DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) * RETURNS * none */ - -VOID WINAPI -DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) +VOID WINAPI DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, + LPVOID lParam) { INT i; @@ -2531,9 +2562,8 @@ DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) * RETURNS * none */ - -void WINAPI -DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) +void WINAPI DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, + LPVOID lParam) { TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); diff --git a/reactos/lib/comctl32/commctrl.c b/reactos/lib/comctl32/commctrl.c index cabb51de2ea..0fbbc940710 100644 --- a/reactos/lib/comctl32/commctrl.c +++ b/reactos/lib/comctl32/commctrl.c @@ -336,7 +336,7 @@ MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu, * Handle to the window that contains the menu and controls. * * uFlags - * Identifier of the menu item to receive or loose a check mark. + * Identifier of the menu item to receive or lose a check mark. * * lpInfo * The array of integers contains pairs of values. BOTH values of diff --git a/reactos/lib/comctl32/datetime.c b/reactos/lib/comctl32/datetime.c index 54a33e2958c..daa068591b0 100644 --- a/reactos/lib/comctl32/datetime.c +++ b/reactos/lib/comctl32/datetime.c @@ -487,22 +487,17 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc) int i,prevright; RECT *field; RECT *rcDraw = &infoPtr->rcDraw; - RECT *rcClient = &infoPtr->rcClient; RECT *calbutton = &infoPtr->calbutton; RECT *checkbox = &infoPtr->checkbox; - HBRUSH hbr; SIZE size; - COLORREF oldBk, oldTextColor; + COLORREF oldTextColor; /* draw control edge */ TRACE("\n"); - hbr = CreateSolidBrush(RGB(255, 255, 255)); - FillRect(hdc, rcClient, hbr); - DrawEdge(hdc, rcClient, EDGE_SUNKEN, BF_RECT); - DeleteObject(hbr); if (infoPtr->dateValid) { HFONT oldFont = SelectObject (hdc, infoPtr->hFont); + INT oldBkMode = SetBkMode (hdc, TRANSPARENT); WCHAR txt[80]; DATETIME_ReturnTxt (infoPtr, 0, txt, sizeof(txt)/sizeof(txt[0])); @@ -521,18 +516,23 @@ DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc) field->bottom = rcDraw->bottom; prevright = field->right; - if ((infoPtr->haveFocus) && (i == infoPtr->select)) { - hbr = CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)); + if (infoPtr->dwStyle & WS_DISABLED) + oldTextColor = SetTextColor (hdc, comctl32_color.clrGrayText); + else if ((infoPtr->haveFocus) && (i == infoPtr->select)) { + /* fill if focussed */ + HBRUSH hbr = CreateSolidBrush (comctl32_color.clrActiveCaption); FillRect(hdc, field, hbr); - oldBk = SetBkColor (hdc, GetSysColor(COLOR_ACTIVECAPTION)); - oldTextColor = SetTextColor (hdc, GetSysColor(COLOR_WINDOW)); DeleteObject (hbr); - DrawTextW (hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); - SetBkColor (hdc, oldBk); - SetTextColor (hdc, oldTextColor); - } else - DrawTextW ( hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE ); + oldTextColor = SetTextColor (hdc, comctl32_color.clrWindow); + } + else + oldTextColor = SetTextColor (hdc, comctl32_color.clrWindowText); + + /* draw the date text using the colour set above */ + DrawTextW (hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); + SetTextColor (hdc, oldTextColor); } + SetBkMode (hdc, oldBkMode); SelectObject (hdc, oldFont); } @@ -576,25 +576,29 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, WORD wKey, INT x, INT y) /* FIXME: might be conditions where we don't want to update infoPtr->select */ infoPtr->select = new; - if (infoPtr->select != old) - infoPtr->haveFocus = DTHT_GOTFOCUS; + SetFocus(infoPtr->hwndSelf); if (infoPtr->select == DTHT_MCPOPUP) { + RECT rcMonthCal; + SendMessageW(infoPtr->hMonthCal, MCM_GETMINREQRECT, 0, (LPARAM)&rcMonthCal); + /* FIXME: button actually is only depressed during dropdown of the */ /* calendar control and when the mouse is over the button window */ infoPtr->bCalDepressed = TRUE; /* recalculate the position of the monthcal popup */ if(infoPtr->dwStyle & DTS_RIGHTALIGN) - infoPtr->monthcal_pos.x = infoPtr->rcClient.right - - ((infoPtr->calbutton.right - infoPtr->calbutton.left) + 200); + infoPtr->monthcal_pos.x = infoPtr->calbutton.left - + (rcMonthCal.right - rcMonthCal.left); else - infoPtr->monthcal_pos.x = 8; + /* FIXME: this should be after the area reserved for the checkbox */ + infoPtr->monthcal_pos.x = infoPtr->rcDraw.left; infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom; ClientToScreen (infoPtr->hwndSelf, &(infoPtr->monthcal_pos)); - /* FIXME My Windoze has cx=about 200, but it probably depends on font size etc */ - SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x, infoPtr->monthcal_pos.y, 200, 150, 0); + SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x, + infoPtr->monthcal_pos.y, rcMonthCal.right - rcMonthCal.left, + rcMonthCal.bottom - rcMonthCal.top, 0); if(IsWindowVisible(infoPtr->hMonthCal)) { ShowWindow(infoPtr->hMonthCal, SW_HIDE); @@ -611,7 +615,7 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, WORD wKey, INT x, INT y) DATETIME_SendSimpleNotify (infoPtr, DTN_DROPDOWN); } - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); return 0; } @@ -620,7 +624,7 @@ DATETIME_LButtonDown (DATETIME_INFO *infoPtr, WORD wKey, INT x, INT y) static LRESULT DATETIME_LButtonUp (DATETIME_INFO *infoPtr, WORD wKey) { - if(infoPtr->bCalDepressed == TRUE) { + if(infoPtr->bCalDepressed) { infoPtr->bCalDepressed = FALSE; InvalidateRect(infoPtr->hwndSelf, &(infoPtr->calbutton), TRUE); } @@ -667,6 +671,45 @@ DATETIME_Command (DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam) } +static LRESULT +DATETIME_Enable (DATETIME_INFO *infoPtr, BOOL bEnable) +{ + TRACE("%p %s\n", infoPtr, bEnable ? "TRUE" : "FALSE"); + if (bEnable) + infoPtr->dwStyle &= ~WS_DISABLED; + else + infoPtr->dwStyle |= WS_DISABLED; + return 0; +} + + +static LRESULT +DATETIME_EraseBackground (DATETIME_INFO *infoPtr, HDC hdc) +{ + HBRUSH hBrush, hSolidBrush = NULL; + RECT rc; + + if (infoPtr->dwStyle & WS_DISABLED) + hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace); + else + { + hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT, + (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf); + if (!hBrush) + hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow); + } + + GetClientRect (infoPtr->hwndSelf, &rc); + + FillRect (hdc, &rc, hBrush); + + if (hSolidBrush) + DeleteObject(hSolidBrush); + + return -1; +} + + static LRESULT DATETIME_Notify (DATETIME_INFO *infoPtr, int idCtrl, LPNMHDR lpnmh) { @@ -749,6 +792,8 @@ DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode, LPARAM flags) static LRESULT DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus) { + TRACE("lost focus to %p\n", lostFocus); + if (infoPtr->haveFocus) { DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS); infoPtr->haveFocus = 0; @@ -760,9 +805,23 @@ DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus) } +static LRESULT +DATETIME_NCCreate (HWND hwnd, LPCREATESTRUCTW lpcs) +{ + DWORD dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); + /* force control to have client edge */ + dwExStyle |= WS_EX_CLIENTEDGE; + SetWindowLongW(hwnd, GWL_EXSTYLE, dwExStyle); + + return DefWindowProcW(hwnd, WM_NCCREATE, 0, (LPARAM)lpcs); +} + + static LRESULT DATETIME_SetFocus (DATETIME_INFO *infoPtr, HWND lostFocus) { + TRACE("got focus from %p\n", lostFocus); + if (infoPtr->haveFocus == 0) { DATETIME_SendSimpleNotify (infoPtr, NM_SETFOCUS); infoPtr->haveFocus = DTHT_GOTFOCUS; @@ -814,10 +873,7 @@ DATETIME_Size (DATETIME_INFO *infoPtr, WORD flags, INT width, INT height) TRACE("Height=%ld, Width=%ld\n", infoPtr->rcClient.bottom, infoPtr->rcClient.right); - memcpy((&infoPtr->rcDraw), (&infoPtr->rcClient), sizeof(infoPtr->rcDraw)); - - /* subract the size of the edge drawn by DrawEdge */ - InflateRect(&infoPtr->rcDraw, -2, -2); + infoPtr->rcDraw = infoPtr->rcClient; /* set the size of the button that drops the calendar down */ /* FIXME: account for style that allows button on left side */ @@ -833,17 +889,6 @@ DATETIME_Size (DATETIME_INFO *infoPtr, WORD flags, INT width, INT height) infoPtr->checkbox.left = infoPtr->rcDraw.left; infoPtr->checkbox.right = infoPtr->rcDraw.left + 10; - /* update the position of the monthcal control */ - if(infoPtr->dwStyle & DTS_RIGHTALIGN) - infoPtr->monthcal_pos.x = infoPtr->rcClient.right - ((infoPtr->calbutton.right - - infoPtr->calbutton.left) + 145); - else - infoPtr->monthcal_pos.x = 8; - - infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom; - ClientToScreen (infoPtr->hwndSelf, &(infoPtr->monthcal_pos)); - SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x, infoPtr->monthcal_pos.y, 145, 150, 0); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); return 0; @@ -903,6 +948,7 @@ DATETIME_Create (HWND hwnd, LPCREATESTRUCTW lpcs) infoPtr->fieldRect = (RECT *) Alloc (infoPtr->nrFieldsAllocated * sizeof(RECT)); infoPtr->buflen = (int *) Alloc (infoPtr->nrFieldsAllocated * sizeof(int)); infoPtr->hwndNotify = lpcs->hwndParent; + infoPtr->select = -1; /* initially, nothing is selected */ DATETIME_StyleChanged(infoPtr, GWL_STYLE, &ss); DATETIME_SetFormatW (infoPtr, 0); @@ -946,7 +992,7 @@ DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) TRACE ("%x, %x, %lx\n", uMsg, wParam, lParam); - if (!infoPtr && (uMsg != WM_CREATE)) + if (!infoPtr && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE)) return DefWindowProcW( hwnd, uMsg, wParam, lParam ); switch (uMsg) { @@ -988,6 +1034,12 @@ DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_NOTIFY: return DATETIME_Notify (infoPtr, (int)wParam, (LPNMHDR)lParam); + case WM_ENABLE: + return DATETIME_Enable (infoPtr, (BOOL)wParam); + + case WM_ERASEBKGND: + return DATETIME_EraseBackground (infoPtr, (HDC)wParam); + case WM_GETDLGCODE: return DLGC_WANTARROWS | DLGC_WANTCHARS; @@ -1000,6 +1052,9 @@ DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_KILLFOCUS: return DATETIME_KillFocus (infoPtr, (HWND)wParam); + case WM_NCCREATE: + return DATETIME_NCCreate (hwnd, (LPCREATESTRUCTW)lParam); + case WM_SETFOCUS: return DATETIME_SetFocus (infoPtr, (HWND)wParam); diff --git a/reactos/lib/comctl32/flatsb.c b/reactos/lib/comctl32/flatsb.c index 2980b6b9a6a..1c5fa66236a 100644 --- a/reactos/lib/comctl32/flatsb.c +++ b/reactos/lib/comctl32/flatsb.c @@ -34,9 +34,7 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "wingdi.h" #include "winuser.h" -#include "winnls.h" #include "commctrl.h" #include "wine/debug.h" @@ -263,7 +261,6 @@ FlatSB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcA (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/header.c b/reactos/lib/comctl32/header.c index 892c7dfce0b..03b80845264 100644 --- a/reactos/lib/comctl32/header.c +++ b/reactos/lib/comctl32/header.c @@ -688,29 +688,36 @@ HEADER_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) if (!phdi) return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; TRACE("[nItem=%d]\n", nItem); if (phdi->mask == 0) return TRUE; - lpItem = &infoPtr->items[nItem]; + if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) { + lpItem = NULL; + } + else { + lpItem = &infoPtr->items[nItem]; + } + if (phdi->mask & HDI_BITMAP) - phdi->hbm = lpItem->hbm; + phdi->hbm = (lpItem != NULL) ? lpItem->hbm : 0; if (phdi->mask & HDI_FORMAT) - phdi->fmt = lpItem->fmt; + phdi->fmt = (lpItem != NULL) ? lpItem->fmt : 0; if (phdi->mask & HDI_WIDTH) - phdi->cxy = lpItem->cxy; + phdi->cxy = (lpItem != NULL) ? lpItem->cxy : 0; if (phdi->mask & HDI_LPARAM) - phdi->lParam = lpItem->lParam; + phdi->lParam = (lpItem != NULL) ? lpItem->lParam : 0; if (phdi->mask & HDI_TEXT) { - if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { + if (lpItem == NULL) { + *phdi->pszText = 0; + } + else if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { if (lpItem->pszText) WideCharToMultiByte (CP_ACP, 0, lpItem->pszText, -1, phdi->pszText, phdi->cchTextMax, NULL, NULL); @@ -722,10 +729,10 @@ HEADER_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) } if (phdi->mask & HDI_IMAGE) - phdi->iImage = lpItem->iImage; + phdi->iImage = (lpItem != NULL) ? lpItem->iImage : 0; if (phdi->mask & HDI_ORDER) - phdi->iOrder = lpItem->iOrder; + phdi->iOrder = (lpItem != NULL) ? lpItem->iOrder : 0; return TRUE; } @@ -741,29 +748,36 @@ HEADER_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam) if (!phdi) return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; TRACE("[nItem=%d]\n", nItem); if (phdi->mask == 0) return TRUE; - lpItem = &infoPtr->items[nItem]; + if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) { + lpItem = NULL; + } + else { + lpItem = &infoPtr->items[nItem]; + } + if (phdi->mask & HDI_BITMAP) - phdi->hbm = lpItem->hbm; + phdi->hbm = (lpItem != NULL) ? lpItem->hbm : 0; if (phdi->mask & HDI_FORMAT) - phdi->fmt = lpItem->fmt; + phdi->fmt = (lpItem != NULL) ? lpItem->fmt : 0; if (phdi->mask & HDI_WIDTH) - phdi->cxy = lpItem->cxy; + phdi->cxy = (lpItem != NULL) ? lpItem->cxy : 0; if (phdi->mask & HDI_LPARAM) - phdi->lParam = lpItem->lParam; + phdi->lParam = (lpItem != NULL) ? lpItem->lParam : 0; if (phdi->mask & HDI_TEXT) { - if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { + if (lpItem == NULL) { + *phdi->pszText = 0; + } + else if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { if (lpItem->pszText) lstrcpynW (phdi->pszText, lpItem->pszText, phdi->cchTextMax); else @@ -774,10 +788,10 @@ HEADER_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam) } if (phdi->mask & HDI_IMAGE) - phdi->iImage = lpItem->iImage; + phdi->iImage = (lpItem != NULL) ? lpItem->iImage : 0; if (phdi->mask & HDI_ORDER) - phdi->iOrder = lpItem->iOrder; + phdi->iOrder = (lpItem != NULL) ? lpItem->iOrder : 0; return TRUE; } @@ -1831,7 +1845,6 @@ HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) msg, wParam, lParam ); return DefWindowProcA (hwnd, msg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/imagelist.c b/reactos/lib/comctl32/imagelist.c index 99e1dd11e42..37f7def4b5e 100644 --- a/reactos/lib/comctl32/imagelist.c +++ b/reactos/lib/comctl32/imagelist.c @@ -612,6 +612,8 @@ ImageList_Create (INT cx, INT cy, UINT flags, } SelectObject(himl->hdcMask, himl->hbmMask); } + else + himl->hbmMask = 0; /* create blending brushes */ hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25); @@ -1056,10 +1058,10 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) INT cx, cy, lx, ly, nOvlIdx; DWORD fState, dwRop; UINT fStyle; - COLORREF clrBk, oldImageBk, oldImageFg; + COLORREF oldImageBk, oldImageFg; HDC hImageDC, hImageListDC, hMaskListDC; HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp; - BOOL bIsTransparent, bBlend, bResult = FALSE; + BOOL bIsTransparent, bBlend, bResult = FALSE, bMask; HIMAGELIST himl; if (!pimldp || !(himl = pimldp->himl)) return FALSE; @@ -1073,9 +1075,14 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK; cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx; cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy; - clrBk = (pimldp->rgbBk == CLR_DEFAULT) ? himl->clrBk : pimldp->rgbBk; - bIsTransparent = (fStyle & ILD_TRANSPARENT) || clrBk == CLR_NONE; - bBlend = fStyle & (ILD_BLEND25 | ILD_BLEND50); + + bIsTransparent = (fStyle & ILD_TRANSPARENT); + if( pimldp->rgbBk == CLR_NONE ) + bIsTransparent = TRUE; + if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) ) + bIsTransparent = TRUE; + bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ; + bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask; TRACE("himl(0x%lx) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n", (DWORD)himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy); @@ -1107,24 +1114,43 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) /* * Draw the initial image */ - if (fStyle & ILD_MASK) { + if( bMask ) { if (himl->hbmMask) { - BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCCOPY); + HBRUSH hOldBrush; + hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst))); + PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY ); + BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCPAINT); + DeleteObject (SelectObject (hImageDC, hOldBrush)); + if( bIsTransparent ) + { + BitBlt ( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND); + bResult = TRUE; + goto end; + } } else { HBRUSH hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH)); PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY); SelectObject(hImageDC, hOldBrush); } - } else if (himl->hbmMask && !bIsTransparent) { + } else { /* blend the image with the needed solid background */ - HBRUSH hOldBrush = SelectObject (hImageDC, CreateSolidBrush (clrBk)); + COLORREF colour = RGB(0,0,0); + HBRUSH hOldBrush; + + if( !bIsTransparent ) + { + colour = pimldp->rgbBk; + if( colour == CLR_DEFAULT ) + colour = himl->clrBk; + if( colour == CLR_NONE ) + colour = GetBkColor(pimldp->hdcDst); + } + + hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour)); PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY ); BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCAND ); BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, lx, ly, SRCPAINT ); DeleteObject (SelectObject (hImageDC, hOldBrush)); - } else { - /* start off with the image, if we have a mask, we'll use it later */ - BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, lx, ly, SRCCOPY); } /* Time for blending, if required */ @@ -1179,7 +1205,7 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) /* now copy the image to the screen */ dwRop = SRCCOPY; - if (himl->hbmMask && bIsTransparent && !(fStyle & ILD_MASK)) { + if (himl->hbmMask && bIsTransparent ) { COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) ); COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff )); BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hMaskListDC, lx, ly, SRCAND); @@ -1191,7 +1217,7 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, dwRop); bResult = TRUE; - +end: /* cleanup the mess */ SetBkColor(hImageDC, oldImageBk); SetTextColor(hImageDC, oldImageFg); @@ -1388,14 +1414,18 @@ ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle) /* draw mask*/ ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy); hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask); - PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, WHITENESS); - ImageList_Draw(himl, i, hdcDst, 0, 0, fStyle | ILD_MASK); + if (himl->hbmMask) { + BitBlt (hdcDst, 0, 0, himl->cx, himl->cy, + himl->hdcMask, i * himl->cx, 0, SRCCOPY); + } + else + PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS); /* draw image*/ ii.hbmColor = CreateCompatibleBitmap (himl->hdcImage, himl->cx, himl->cy); SelectObject (hdcDst, ii.hbmColor); - PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS); - ImageList_Draw(himl, i, hdcDst, 0, 0, fStyle | ILD_TRANSPARENT); + BitBlt (hdcDst, 0, 0, himl->cx, himl->cy, + himl->hdcImage, i * himl->cx, 0, SRCCOPY); /* * CreateIconIndirect requires us to deselect the bitmaps from diff --git a/reactos/lib/comctl32/listview.c b/reactos/lib/comctl32/listview.c index 7ae622cefea..b774e853bee 100644 --- a/reactos/lib/comctl32/listview.c +++ b/reactos/lib/comctl32/listview.c @@ -7254,9 +7254,11 @@ static INT WINAPI LISTVIEW_CallBackCompare(LPVOID first, LPVOID second, LPARAM l LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)lParam; ITEM_INFO* lv_first = (ITEM_INFO*) DPA_GetPtr( (HDPA)first, 0 ); ITEM_INFO* lv_second = (ITEM_INFO*) DPA_GetPtr( (HDPA)second, 0 ); + PFNLVCOMPARE CompareFunction = infoPtr->pfnCompare; /* Forward the call to the client defined callback */ - return (infoPtr->pfnCompare)( lv_first->lParam , lv_second->lParam, infoPtr->lParamSort ); + + return (CompareFunction)( lv_first->lParam , lv_second->lParam, infoPtr->lParamSort ); } /*** @@ -8348,6 +8350,36 @@ static LRESULT LISTVIEW_Paint(LISTVIEW_INFO *infoPtr, HDC hdc) return 0; } + +/*** + * DESCRIPTION: + * Paints/Repaints the listview control. + * + * PARAMETER(S): + * [I] infoPtr : valid pointer to the listview structure + * [I] hdc : device context handle + * [I] options : drawing options + * + * RETURN: + * Zero + */ +static LRESULT LISTVIEW_PrintClient(LISTVIEW_INFO *infoPtr, HDC hdc, DWORD options) +{ + FIXME("Partial Stub: (hdc=%p options=0x%08lx)\n", hdc, options); + + if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwndSelf)) + return 0; + + if (options & PRF_ERASEBKGND) + LISTVIEW_EraseBkgnd(infoPtr, hdc); + + if (options & PRF_CLIENT) + LISTVIEW_Paint(infoPtr, hdc); + + return 0; +} + + /*** * DESCRIPTION: * Processes double click messages (right mouse button). @@ -9195,6 +9227,9 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_NOTIFYFORMAT: return LISTVIEW_NotifyFormat(infoPtr, (HWND)wParam, (INT)lParam); + case WM_PRINTCLIENT: + return LISTVIEW_PrintClient(infoPtr, (HDC)wParam, (DWORD)lParam); + case WM_PAINT: return LISTVIEW_Paint(infoPtr, (HDC)wParam); @@ -9262,7 +9297,6 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return DefWindowProcW(hwnd, uMsg, wParam, lParam); } - return 0; } /*** diff --git a/reactos/lib/comctl32/monthcal.c b/reactos/lib/comctl32/monthcal.c index 7c53fcca4dd..961fcae6e69 100644 --- a/reactos/lib/comctl32/monthcal.c +++ b/reactos/lib/comctl32/monthcal.c @@ -337,7 +337,6 @@ static void MONTHCAL_DrawDay(MONTHCAL_INFO *infoPtr, HDC hdc, int day, int month RECT r; static int haveBoldFont, haveSelectedDay = FALSE; HBRUSH hbr; - HPEN hNewPen, hOldPen = 0; COLORREF oldCol = 0; COLORREF oldBk = 0; @@ -394,12 +393,8 @@ static void MONTHCAL_DrawDay(MONTHCAL_INFO *infoPtr, HDC hdc, int day, int month DrawTextA(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); /* draw a rectangle around the currently selected days text */ - if((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) { - hNewPen = CreatePen(PS_ALTERNATE, 0, GetSysColor(COLOR_WINDOWTEXT) ); - hbr = GetSysColorBrush(COLOR_WINDOWTEXT); - FrameRect(hdc, &r, hbr); - SelectObject(hdc, hOldPen); - } + if((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) + DrawFocusRect(hdc, &r); } @@ -2016,7 +2011,6 @@ MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ERR( "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); return DefWindowProcA(hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/nativefont.c b/reactos/lib/comctl32/nativefont.c index 4e6fd78ac6a..4955a8c83b1 100644 --- a/reactos/lib/comctl32/nativefont.c +++ b/reactos/lib/comctl32/nativefont.c @@ -106,7 +106,6 @@ NATIVEFONT_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/pager.c b/reactos/lib/comctl32/pager.c index 74d765e633d..0cd5e67b8a3 100644 --- a/reactos/lib/comctl32/pager.c +++ b/reactos/lib/comctl32/pager.c @@ -1368,8 +1368,6 @@ PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) default: return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - - return 0; } diff --git a/reactos/lib/comctl32/propsheet.c b/reactos/lib/comctl32/propsheet.c index d38dc1f6cd1..2ad24f2a151 100644 --- a/reactos/lib/comctl32/propsheet.c +++ b/reactos/lib/comctl32/propsheet.c @@ -3690,6 +3690,4 @@ PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) default: return FALSE; } - - return FALSE; } diff --git a/reactos/lib/comctl32/rebar.c b/reactos/lib/comctl32/rebar.c index 532e21ea82b..b01295bf0ef 100644 --- a/reactos/lib/comctl32/rebar.c +++ b/reactos/lib/comctl32/rebar.c @@ -4696,7 +4696,6 @@ REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcA (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/smoothscroll.c b/reactos/lib/comctl32/smoothscroll.c index fbed31eb5bc..5c0030fc355 100644 --- a/reactos/lib/comctl32/smoothscroll.c +++ b/reactos/lib/comctl32/smoothscroll.c @@ -27,10 +27,7 @@ #include "winbase.h" #include "winreg.h" #include "winerror.h" -#include "wingdi.h" #include "winuser.h" -#include "winnls.h" -#include "commctrl.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(commctrl); @@ -75,7 +72,6 @@ BOOL WINAPI SmoothScrollWindow( SMOOTHSCROLLSTRUCT *smooth ) { LPRECT lpupdaterect = smooth->lpupdaterect; HRGN hrgnupdate = smooth->hrgnupdate; RECT tmprect; - BOOL ret = TRUE; DWORD flags = smooth->flags; if (smooth->dwSize!=sizeof(SMOOTHSCROLLSTRUCT)) @@ -132,5 +128,4 @@ BOOL WINAPI SmoothScrollWindow( SMOOTHSCROLLSTRUCT *smooth ) { smooth->lpcliprect,hrgnupdate,lpupdaterect, flags & 0xffff ); - return ret; } diff --git a/reactos/lib/comctl32/status.c b/reactos/lib/comctl32/status.c index fd82bb59f23..4ee0b9c44fd 100644 --- a/reactos/lib/comctl32/status.c +++ b/reactos/lib/comctl32/status.c @@ -455,7 +455,7 @@ STATUSBAR_GetTextLength (STATUS_INFO *infoPtr, INT nPart) else part = &infoPtr->parts[nPart]; - if (part->text) + if ((~part->style & SBT_OWNERDRAW) && part->text) result = strlenW(part->text); else result = 0; @@ -650,7 +650,7 @@ STATUSBAR_SetTextT (STATUS_INFO *infoPtr, INT nPart, WORD style, { STATUSWINDOWPART *part=NULL; BOOL changed = FALSE; - WORD oldStyle; + INT oldStyle; if (style & SBT_OWNERDRAW) { TRACE("part %d, text %p\n",nPart,text); @@ -675,9 +675,12 @@ STATUSBAR_SetTextT (STATUS_INFO *infoPtr, INT nPart, WORD style, oldStyle = part->style; part->style = style; if (style & SBT_OWNERDRAW) { - if (part->text == text) - return TRUE; - part->text = (LPWSTR)text; + if (!(oldStyle & SBT_OWNERDRAW)) { + if (part->text) + Free (part->text); + } else if (part->text == text) + return TRUE; + part->text = (LPWSTR)text; } else { LPWSTR ntext; @@ -1252,7 +1255,6 @@ StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) msg, wParam, lParam); return DefWindowProcW (hwnd, msg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/syslink.c b/reactos/lib/comctl32/syslink.c index 4eeff7533a9..3567c96a3a4 100644 --- a/reactos/lib/comctl32/syslink.c +++ b/reactos/lib/comctl32/syslink.c @@ -33,7 +33,6 @@ #include "winuser.h" #include "winnls.h" #include "commctrl.h" -#include "comctl32.h" #include "wine/unicode.h" #include "wine/debug.h" @@ -116,14 +115,8 @@ static VOID SYSLINK_FreeDocItem (PDOC_ITEM DocItem) { if(DocItem->Type == slLink) { - if(DocItem->u.Link.szID != NULL) - { - SYSLINK_Free(DocItem->u.Link.szID); - } - if(DocItem->u.Link.szUrl != NULL) - { - SYSLINK_Free(DocItem->u.Link.szUrl); - } + SYSLINK_Free(DocItem->u.Link.szID); + SYSLINK_Free(DocItem->u.Link.szUrl); } if(DocItem->Type == slLink && DocItem->u.Link.hRgn != NULL) @@ -1637,6 +1630,8 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, case WM_DESTROY: TRACE("SysLink Ctrl destruction, hwnd=%p\n", hwnd); SYSLINK_ClearDoc(infoPtr); + if(infoPtr->Font != 0) DeleteObject(infoPtr->Font); + if(infoPtr->LinkFont != 0) DeleteObject(infoPtr->LinkFont); SYSLINK_Free (infoPtr); SetWindowLongPtrW(hwnd, 0, 0); return 0; diff --git a/reactos/lib/comctl32/tab.c b/reactos/lib/comctl32/tab.c index 6a930398b54..a4b843c5520 100644 --- a/reactos/lib/comctl32/tab.c +++ b/reactos/lib/comctl32/tab.c @@ -201,6 +201,8 @@ TAB_DumpItemInternal(TAB_INFO *infoPtr, UINT iItem) } } +/* RETURNS + * the index of the selected tab, or -1 if no tab is selected. */ static LRESULT TAB_GetCurSel (HWND hwnd) { @@ -209,11 +211,21 @@ TAB_GetCurSel (HWND hwnd) return infoPtr->iSelected; } +/* RETURNS + * the index of the tab item that has the focus + * NOTE + * we have not to return negative value + * TODO + * test for windows */ static LRESULT TAB_GetCurFocus (HWND hwnd) { TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - + if (infoPtr->uFocus<0) + { + FIXME("we have not to return negative value"); + return 0; + } return infoPtr->uFocus; } @@ -255,10 +267,10 @@ TAB_SetCurFocus (HWND hwnd,WPARAM wParam) FIXME("Should set input focus\n"); } else { int oldFocus = infoPtr->uFocus; - if (infoPtr->iSelected != iItem || infoPtr->uFocus == -1 ) { + if (infoPtr->iSelected != iItem || oldFocus == -1 ) { infoPtr->uFocus = iItem; if (oldFocus != -1) { - if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)!=TRUE) { + if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) { infoPtr->iSelected = iItem; TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); } @@ -611,7 +623,7 @@ TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) if ((newItem != -1) && (infoPtr->iSelected != newItem)) { - if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING) != TRUE) + if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) { infoPtr->iSelected = newItem; infoPtr->uFocus = newItem; @@ -3258,8 +3270,6 @@ TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcW(hwnd, uMsg, wParam, lParam); } - - return 0; } diff --git a/reactos/lib/comctl32/toolbar.c b/reactos/lib/comctl32/toolbar.c index 9ca3072b71b..58f8b0e105c 100644 --- a/reactos/lib/comctl32/toolbar.c +++ b/reactos/lib/comctl32/toolbar.c @@ -4269,7 +4269,7 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam; HBITMAP hBitmap; int i = 0, nOldButtons = 0, pos = 0; - int nOldBitmaps, nNewBitmaps; + int nOldBitmaps, nNewBitmaps = 0; HIMAGELIST himlDef = 0; TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n", @@ -4322,6 +4322,7 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) for (i = pos + nOldBitmaps - 1; i >= pos; i--) ImageList_Remove(himlDef, i); + if (hBitmap) { BITMAP bmp; HBITMAP hOldBitmapBitmap, hOldBitmapLoad, hbmLoad; @@ -5522,8 +5523,7 @@ TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) DestroyWindow (infoPtr->hwndToolTip); /* delete temporary buffer for tooltip text */ - if (infoPtr->pszTooltipText) - HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); + HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); /* delete button data */ if (infoPtr->buttons) @@ -6081,23 +6081,25 @@ TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) INT nHit; TBUTTON_INFO *btnPtr; - /* fill in the TRACKMOUSEEVENT struct */ - trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); - trackinfo.dwFlags = TME_QUERY; - trackinfo.hwndTrack = hwnd; - trackinfo.dwHoverTime = HOVER_DEFAULT; + if (infoPtr->dwStyle & TBSTYLE_FLAT) { + /* fill in the TRACKMOUSEEVENT struct */ + trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); + trackinfo.dwFlags = TME_QUERY; + trackinfo.hwndTrack = hwnd; + trackinfo.dwHoverTime = HOVER_DEFAULT; - /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ - _TrackMouseEvent(&trackinfo); - - /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ - if(!(trackinfo.dwFlags & TME_LEAVE)) { - trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ - - /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ - /* and can properly deactivate the hot toolbar button */ + /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ _TrackMouseEvent(&trackinfo); - } + + /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ + if(!(trackinfo.dwFlags & TME_LEAVE)) { + trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ + + /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ + /* and can properly deactivate the hot toolbar button */ + _TrackMouseEvent(&trackinfo); + } + } if (infoPtr->hwndToolTip) TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd, @@ -6108,7 +6110,7 @@ TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - if (!infoPtr->bAnchor || (nHit >= 0)) + if ((infoPtr->dwStyle & TBSTYLE_FLAT) && (!infoPtr->bAnchor || (nHit >= 0))) TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE); if (infoPtr->nOldHit != nHit) @@ -6275,11 +6277,8 @@ static LRESULT TOOLBAR_TTGetDispInfo (TOOLBAR_INFO *infoPtr, NMTTDISPINFOW *lpnm TRACE("button index = %d\n", index); - if (infoPtr->pszTooltipText) - { - HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); - infoPtr->pszTooltipText = NULL; - } + HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); + infoPtr->pszTooltipText = NULL; if (index < 0) return 0; @@ -7101,7 +7100,6 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/tooltips.c b/reactos/lib/comctl32/tooltips.c index 802363a454a..e7499ad7353 100644 --- a/reactos/lib/comctl32/tooltips.c +++ b/reactos/lib/comctl32/tooltips.c @@ -1400,8 +1400,6 @@ TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) } else return (infoPtr->nCurrentTool != -1); - - return FALSE; } @@ -1438,8 +1436,6 @@ TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) } else return (infoPtr->nCurrentTool != -1); - - return FALSE; } @@ -2802,7 +2798,6 @@ TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg, wParam, lParam); return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/trackbar.c b/reactos/lib/comctl32/trackbar.c index fae5a562660..8a364d9a5e4 100644 --- a/reactos/lib/comctl32/trackbar.c +++ b/reactos/lib/comctl32/trackbar.c @@ -1810,7 +1810,6 @@ TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); return DefWindowProcW (hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comctl32/treeview.c b/reactos/lib/comctl32/treeview.c index 52b4fe4c3d1..b7320f14e1b 100644 --- a/reactos/lib/comctl32/treeview.c +++ b/reactos/lib/comctl32/treeview.c @@ -31,7 +31,6 @@ * TVN_SETDISPINFO, TVN_SINGLEEXPAND * * missing styles: TVS_FULLROWSELECT, TVS_INFOTIP, TVS_RTLREADING, - * TVS_TRACKSELECT * * missing item styles: TVIS_CUT, TVIS_EXPANDPARTIAL * @@ -132,6 +131,8 @@ typedef struct tagTREEVIEW_INFO HFONT hFont; HFONT hDefaultFont; HFONT hBoldFont; + HFONT hUnderlineFont; + HCURSOR hcurHand; HWND hwndToolTip; HWND hwndEdit; @@ -263,10 +264,24 @@ TREEVIEW_CreateBoldFont(HFONT hOrigFont) return CreateFontIndirectW(&font); } +static HFONT +TREEVIEW_CreateUnderlineFont(HFONT hOrigFont) +{ + LOGFONTW font; + + GetObjectW(hOrigFont, sizeof(font), &font); + font.lfUnderline = TRUE; + return CreateFontIndirectW(&font); +} + static inline HFONT TREEVIEW_FontForItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) { - return (item->state & TVIS_BOLD) ? infoPtr->hBoldFont : infoPtr->hFont; + if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (item == infoPtr->hotItem)) + return infoPtr->hUnderlineFont; + if (item->state & TVIS_BOLD) + return infoPtr->hBoldFont; + return infoPtr->hFont; } /* for trace/debugging purposes only */ @@ -1814,6 +1829,7 @@ TREEVIEW_SetFont(TREEVIEW_INFO *infoPtr, HFONT hFont, BOOL bRedraw) DeleteObject(infoPtr->hBoldFont); infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont); + infoPtr->hUnderlineFont = TREEVIEW_CreateUnderlineFont(infoPtr->hFont); if (!infoPtr->bHeightSet) infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); @@ -2486,7 +2502,9 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem) } else { - if (infoPtr->clrText == -1) + if ((infoPtr->dwStyle & TVS_TRACKSELECT) && (wineItem == infoPtr->hotItem)) + oldTextColor = SetTextColor(hdc, comctl32_color.clrHighlight); + else if (infoPtr->clrText == -1) oldTextColor = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); else @@ -3177,7 +3195,7 @@ TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, TREEVIEW_UpdateScrollBars(infoPtr); /* Scroll up so that as many children as possible are visible. - * This looses when expanding causes an HScroll bar to appear, but we + * This fails when expanding causes an HScroll bar to appear, but we * don't know that yet, so the last item is obscured. */ if (wineItem->firstChild != NULL) { @@ -4112,9 +4130,6 @@ TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect, case TVGN_CARET: prevSelect = infoPtr->selectedItem; - if (prevSelect == newSelect) - return FALSE; - if (TREEVIEW_SendTreeviewNotify(infoPtr, TVN_SELCHANGINGW, cause, @@ -4701,7 +4716,6 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) infoPtr->hwnd = hwnd; infoPtr->dwStyle = GetWindowLongW(hwnd, GWL_STYLE); - infoPtr->uInternalStatus = 0; infoPtr->Timer = 0; infoPtr->uNumItems = 0; infoPtr->cdmode = 0; @@ -4713,6 +4727,7 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) /* No scroll bars yet. */ infoPtr->clientWidth = rcClient.right; infoPtr->clientHeight = rcClient.bottom; + infoPtr->uInternalStatus = 0; infoPtr->treeWidth = 0; infoPtr->treeHeight = 0; @@ -4754,6 +4769,8 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectW(&lf); infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont); + infoPtr->hUnderlineFont = TREEVIEW_CreateUnderlineFont(infoPtr->hFont); + infoPtr->hcurHand = LoadCursorW(NULL, (LPWSTR)IDC_HAND); infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); @@ -4821,6 +4838,11 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) infoPtr->stateImageWidth = 16; infoPtr->stateImageHeight = 16; } + + /* Make sure actual scrollbar state is consistent with uInternalStatus */ + ShowScrollBar(hwnd, SB_VERT, FALSE); + ShowScrollBar(hwnd, SB_HORZ, FALSE); + return 0; } @@ -4844,6 +4866,7 @@ TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr) DeleteObject(infoPtr->hDefaultFont); DeleteObject(infoPtr->hBoldFont); + DeleteObject(infoPtr->hUnderlineFont); Free(infoPtr); return 0; @@ -5011,6 +5034,63 @@ TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam) return FALSE; } +static LRESULT +TREEVIEW_MouseLeave (TREEVIEW_INFO * infoPtr) +{ + if (infoPtr->hotItem) + { + /* remove hot effect from item */ + InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE); + infoPtr->hotItem = NULL; + } + return 0; +} + +static LRESULT +TREEVIEW_MouseMove (TREEVIEW_INFO * infoPtr, WPARAM wParam, LPARAM lParam) +{ + POINT pt; + TRACKMOUSEEVENT trackinfo; + TREEVIEW_ITEM * item; + + /* fill in the TRACKMOUSEEVENT struct */ + trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); + trackinfo.dwFlags = TME_QUERY; + trackinfo.hwndTrack = infoPtr->hwnd; + trackinfo.dwHoverTime = HOVER_DEFAULT; + + /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ + _TrackMouseEvent(&trackinfo); + + /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ + if(!(trackinfo.dwFlags & TME_LEAVE)) + { + trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ + + /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ + /* and can properly deactivate the hot item */ + _TrackMouseEvent(&trackinfo); + } + + pt.x = (INT)LOWORD(lParam); + pt.y = (INT)HIWORD(lParam); + + item = TREEVIEW_HitTestPoint(infoPtr, pt); + + if (item != infoPtr->hotItem) + { + /* redraw old hot item */ + if (infoPtr->hotItem) + InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE); + infoPtr->hotItem = item; + /* redraw new hot item */ + if (infoPtr->hotItem) + InvalidateRect(infoPtr->hwnd, &infoPtr->hotItem->rect, TRUE); + } + + return 0; +} + static LRESULT TREEVIEW_Notify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) { @@ -5107,6 +5187,28 @@ TREEVIEW_StyleChanged(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) return 0; } +static LRESULT +TREEVIEW_SetCursor(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) +{ + POINT pt; + TREEVIEW_ITEM * item; + + GetCursorPos(&pt); + ScreenToClient(infoPtr->hwnd, &pt); + + item = TREEVIEW_HitTestPoint(infoPtr, pt); + + /* FIXME: send NM_SETCURSOR */ + + if (item && (infoPtr->dwStyle & TVS_TRACKSELECT)) + { + SetCursor(infoPtr->hcurHand); + return 0; + } + else + return DefWindowProcW(infoPtr->hwnd, WM_SETCURSOR, wParam, lParam); +} + static LRESULT TREEVIEW_SetFocus(TREEVIEW_INFO *infoPtr) { @@ -5329,7 +5431,11 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) /* WM_MBUTTONDOWN */ - /* WM_MOUSEMOVE */ + case WM_MOUSELEAVE: + return TREEVIEW_MouseLeave(infoPtr); + + case WM_MOUSEMOVE: + return TREEVIEW_MouseMove(infoPtr, wParam, lParam); case WM_NOTIFY: return TREEVIEW_Notify(infoPtr, wParam, lParam); @@ -5345,6 +5451,9 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_RBUTTONDOWN: return TREEVIEW_RButtonDown(infoPtr, lParam); + case WM_SETCURSOR: + return TREEVIEW_SetCursor(infoPtr, wParam, lParam); + case WM_SETFOCUS: return TREEVIEW_SetFocus(infoPtr); @@ -5388,7 +5497,6 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) def: return DefWindowProcA(hwnd, uMsg, wParam, lParam); } - return 0; } diff --git a/reactos/lib/comdlg32/cdlg.h b/reactos/lib/comdlg32/cdlg.h index 5b8f935cf4b..3e3378e138c 100644 --- a/reactos/lib/comdlg32/cdlg.h +++ b/reactos/lib/comdlg32/cdlg.h @@ -93,7 +93,7 @@ typedef struct { #define PD32_DEFAULT_PRINTER 1582 #define PD32_NR_OF_DOCUMENTS_IN_QUEUE 1583 -#define PD32_PRINT_ALL_X_PAGES 1584 + #define PD32_MARGINS_IN_INCHES 1585 #define PD32_MARGINS_IN_MILIMETERS 1586 #define PD32_MILIMETERS 1587 @@ -145,6 +145,13 @@ typedef struct { #define IDS_COLOR_AQUA 1054 #define IDS_COLOR_WHITE 1055 +#define IDS_FONT_SIZE 1200 +#define IDS_SAVE_BUTTON 1201 +#define IDS_SAVE_IN 1202 +#define IDS_SAVE 1203 +#define IDS_SAVE_AS 1204 +#define IDS_OPEN_FILE 1205 + #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -199,26 +206,25 @@ typedef struct { HWND hWnd1; HWND hWnd2; - LPCHOOSEFONTA lpcf32a; + LPCHOOSEFONTW lpcf32w; int added; } CFn_ENUMSTRUCT, *LPCFn_ENUMSTRUCT; -INT AddFontFamily(const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, - UINT nFontType, LPCHOOSEFONTA lpcf, HWND hwnd, +INT AddFontFamily(const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *lpNTM, + UINT nFontType, LPCHOOSEFONTW lpcf, HWND hwnd, LPCFn_ENUMSTRUCT e); -INT AddFontStyle(const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *metrics, - UINT nFontType, LPCHOOSEFONTA lpcf, HWND hcmb2, HWND hcmb3, +INT AddFontStyle(const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *metrics, + UINT nFontType, LPCHOOSEFONTW lpcf, HWND hcmb2, HWND hcmb3, HWND hDlg, BOOL iswin16); void _dump_cf_flags(DWORD cflags); LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf); + LPCHOOSEFONTW lpcf); LRESULT CFn_WMMeasureItem(HWND hDlg, WPARAM wParam, LPARAM lParam); LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam); LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf); + LPCHOOSEFONTW lpcf); LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf); -LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam); + LPCHOOSEFONTW lpcf); #endif /* _WINE_DLL_CDLG_H */ diff --git a/reactos/lib/comdlg32/cdlg_Cn.rc b/reactos/lib/comdlg32/cdlg_Cn.rc index 4a00be6e78b..f60317423ff 100644 --- a/reactos/lib/comdlg32/cdlg_Cn.rc +++ b/reactos/lib/comdlg32/cdlg_Cn.rc @@ -300,9 +300,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Ò³ÃæÉèÖÃ" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Ö½ÕÅ", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "´óС(&S):", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -408,7 +408,6 @@ supported by your printer.\nPlease enter a value between 1 and %d." PD32_DEFAULT_PRINTER "Default Printer; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "There are %d documents in the queue" - PD32_PRINT_ALL_X_PAGES "&All %d pages" PD32_MARGINS_IN_INCHES "Margins [inches]" PD32_MARGINS_IN_MILIMETERS "Margins [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_De.rc b/reactos/lib/comdlg32/cdlg_De.rc index f7ea0367a68..d7264e24dba 100644 --- a/reactos/lib/comdlg32/cdlg_De.rc +++ b/reactos/lib/comdlg32/cdlg_De.rc @@ -120,9 +120,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Seite einrichten" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papier", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Größe:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -402,7 +402,6 @@ Bitte geben sie einen Wert zwischen %d und %d an." PD32_DEFAULT_PRINTER "Standard Drucker; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Es sind %d Dokumente in der Queue" - PD32_PRINT_ALL_X_PAGES "&Alle %d Seiten" PD32_MARGINS_IN_INCHES "Ränder [inches/zoll]" PD32_MARGINS_IN_MILIMETERS "Ränder [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_En.rc b/reactos/lib/comdlg32/cdlg_En.rc index c70cc38c57f..332eb1090ac 100644 --- a/reactos/lib/comdlg32/cdlg_En.rc +++ b/reactos/lib/comdlg32/cdlg_En.rc @@ -300,9 +300,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Setup Page" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Paper", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Size:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -408,7 +408,6 @@ supported by your printer.\nPlease enter a value between 1 and %d." PD32_DEFAULT_PRINTER "Default Printer; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "There are %d documents in the queue" - PD32_PRINT_ALL_X_PAGES "&All %d pages" PD32_MARGINS_IN_INCHES "Margins [inches]" PD32_MARGINS_IN_MILIMETERS "Margins [mm]" PD32_MILIMETERS "mm" @@ -461,6 +460,15 @@ STRINGTABLE DISCARDABLE /* Color names */ IDS_COLOR_WHITE "White" } +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Select a font size between %d and %d points." + IDS_SAVE_BUTTON "&Save" + IDS_SAVE_IN "Save &in:" + IDS_SAVE "Save" + IDS_SAVE_AS "Save as" + IDS_OPEN_FILE "Open File" +} /****************************************************************/ /* English neutral resources diff --git a/reactos/lib/comdlg32/cdlg_Es.rc b/reactos/lib/comdlg32/cdlg_Es.rc index 1ccbba9eb8c..25798e151c1 100644 --- a/reactos/lib/comdlg32/cdlg_Es.rc +++ b/reactos/lib/comdlg32/cdlg_Es.rc @@ -1,6 +1,6 @@ /* * Copyright 1995 Jon Tombs - * Copyright 2004 José Manuel Ferrer Ortiz + * Copyright 2004, 2005 José Manuel Ferrer Ortiz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -139,7 +139,7 @@ FONT 8, "MS Shell Dlg" CHECKBOX "&Subrayado", chx2, 10,94,50,10, BS_AUTOCHECKBOX LTEXT "&Color:", stc4 ,6,110,30,9 COMBOBOX cmb4,6,120,84,100,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | - CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP + CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP GROUPBOX "Ejemplo",grp2,98,72,120,36,WS_GROUP CTEXT "AaBbYyZzÑñ",stc5,103,80,109,24,SS_NOPREFIX | NOT WS_VISIBLE LTEXT "Codificación:",stc7 ,98,114,80,9 @@ -155,7 +155,7 @@ FONT 8, "MS Shell Dlg" { LTEXT "Colores &básicos:", 1088, 4, 4, 140, 10 LTEXT "Colores person&alizados:", 1089, 4, 106, 140, 10 - LTEXT "Color|Sól&ido", 1090, 150, 151, 48, 10 + LTEXT "Color | Sól&ido", 1090, 150, 151, 48, 10 LTEXT "&Rojo:", 726 /*1094*/,249,126,24,10 EDITTEXT 706, 275,124,21,12, WS_BORDER | WS_GROUP | WS_TABSTOP LTEXT "&Verde:",727/*1095*/,249,140,24,10 @@ -178,7 +178,7 @@ FONT 8, "MS Shell Dlg" PUSHBUTTON "A&yuda", pshHelp,100,166, 44, 14 PUSHBUTTON "Añadir a &colores personalizados", 712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Definir colores personalizados >>", 719/*1025*/, 4, 150, 142, 14, WS_GROUP | WS_TABSTOP - PUSHBUTTON "&i",713,300,200,4,14 /* just a dummy: 'i' is like &i in "sol&id" */ + PUSHBUTTON "&i",713,300,200,4,14 /* just a dummy: 'i' is like &i in "sol&id" */ } @@ -267,7 +267,7 @@ FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "Aceptar",IDOK,180,156,48,14,WS_GROUP PUSHBUTTON "Cancelar",IDCANCEL,232,156,48,14 -/* PUSHBUTTON "Network...", psh5, 284,156,48,14 */ +/* PUSHBUTTON "Red...", psh5, 284,156,48,14 */ GROUPBOX "Impresora", grp4, 8, 4, 272,84, WS_GROUP PUSHBUTTON "&Propiedades", psh2, 212, 17, 60,14, WS_GROUP @@ -299,9 +299,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Página de configuración" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papel", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Tamaño:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -409,7 +409,6 @@ desconocido." PD32_DEFAULT_PRINTER "Impresora por defecto; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Hay %d documentos en la cola" - PD32_PRINT_ALL_X_PAGES "&Todas las %d páginas" PD32_MARGINS_IN_INCHES "Márgenes [pulgadas]" PD32_MARGINS_IN_MILIMETERS "Márgenes [mm]" PD32_MILIMETERS "mm" @@ -418,7 +417,7 @@ desconocido." PD32_PRINTER_STATUS_PAUSED "Pausada; " PD32_PRINTER_STATUS_ERROR "Error; " PD32_PRINTER_STATUS_PENDING_DELETION "Borrado pendiente; " - PD32_PRINTER_STATUS_PAPER_JAM "Paper jam; " + PD32_PRINTER_STATUS_PAPER_JAM "Papel atascado; " PD32_PRINTER_STATUS_PAPER_OUT "Sin papel; " PD32_PRINTER_STATUS_MANUAL_FEED "Ponga papel a mano; " PD32_PRINTER_STATUS_PAPER_PROBLEM "Problema con el papel; " @@ -451,7 +450,7 @@ STRINGTABLE DISCARDABLE /* Color names */ IDS_COLOR_OLIVE "Oliva" IDS_COLOR_NAVY "Azul marino" IDS_COLOR_PURPLE "Morado" - IDS_COLOR_TEAL "Teal" + IDS_COLOR_TEAL "Turquesa" IDS_COLOR_GRAY "Gris" IDS_COLOR_SILVER "Plateado" IDS_COLOR_RED "Rojo" @@ -462,3 +461,8 @@ STRINGTABLE DISCARDABLE /* Color names */ IDS_COLOR_AQUA "Agua" IDS_COLOR_WHITE "Blanco" } + +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Elija un tamaño de fuente entre %d and %d puntos." +} diff --git a/reactos/lib/comdlg32/cdlg_Fr.rc b/reactos/lib/comdlg32/cdlg_Fr.rc index f09d859dfb2..e1e67e085f8 100644 --- a/reactos/lib/comdlg32/cdlg_Fr.rc +++ b/reactos/lib/comdlg32/cdlg_Fr.rc @@ -303,9 +303,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Mise en page" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papier", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Taille:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -411,7 +411,6 @@ Veuillez indiquer un nombre de copies entre 1 et %d." PD32_DEFAULT_PRINTER "Imprimante par défaut; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Il y a %d documents dans la file d'attente" - PD32_PRINT_ALL_X_PAGES "&Toutes les %d pages" PD32_MARGINS_IN_INCHES "Marges [pouces]" PD32_MARGINS_IN_MILIMETERS "Marges [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_It.rc b/reactos/lib/comdlg32/cdlg_It.rc index d8a0e2ed4a9..53e459a1e5b 100644 --- a/reactos/lib/comdlg32/cdlg_It.rc +++ b/reactos/lib/comdlg32/cdlg_It.rc @@ -300,9 +300,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Setup di Pagina" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Carta", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Dimensione:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -407,7 +407,6 @@ supportato dalla stampante.\nInserire un valore compreso tra 1 e %d" PD32_DEFAULT_PRINTER "Stampante predefinita; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Ci sono %d documenti nella coda di stampa" - PD32_PRINT_ALL_X_PAGES "&Tutte le %d pagine" PD32_MARGINS_IN_INCHES "Margini [pollici]" PD32_MARGINS_IN_MILIMETERS "Margini [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_Nl.rc b/reactos/lib/comdlg32/cdlg_Nl.rc index 1de3b2e3f90..5b2b6abf5fb 100644 --- a/reactos/lib/comdlg32/cdlg_Nl.rc +++ b/reactos/lib/comdlg32/cdlg_Nl.rc @@ -251,7 +251,7 @@ FONT 8, "MS Shell Dlg" EDITTEXT edt3, 240,106, 32,12, WS_GROUP | ES_NUMBER GROUPBOX "Afdrukbereik", grp1, 8,92, 144,64, WS_GROUP - CONTROL "&Alle xx", rad1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,106,64,12 + CONTROL "&Alle", rad1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,16,106,64,12 CONTROL "&Pagina's", rad3,"Button",BS_AUTORADIOBUTTON,16,122,36,12 CONTROL "Sele&ctie", rad2,"Button",BS_AUTORADIOBUTTON,16,138,64,12 EDITTEXT edt1, 74,122, 26,12, WS_GROUP | ES_NUMBER @@ -289,7 +289,6 @@ gespecifieerde fout" PD32_DEFAULT_PRINTER "Default Printer, " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Er staan %d documenten in de \ wachtrij" - PD32_PRINT_ALL_X_PAGES "&Alle %d pagina's" PD32_MARGINS_IN_INCHES "Marges [inch]" PD32_MARGINS_IN_MILIMETERS "Marges [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_Pl.rc b/reactos/lib/comdlg32/cdlg_Pl.rc index 81ccdfcdbfc..a456168b8dd 100644 --- a/reactos/lib/comdlg32/cdlg_Pl.rc +++ b/reactos/lib/comdlg32/cdlg_Pl.rc @@ -302,9 +302,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Ustawienia Strony" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papier", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Rozmiar:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -405,7 +405,6 @@ STRINGTABLE DISCARDABLE PD32_DEFAULT_PRINTER "Domyœlna Drukarka; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "W kolejce znajduj¹ siê %d dokumenty" - PD32_PRINT_ALL_X_PAGES "&Wszystkie %d strony" PD32_MARGINS_IN_INCHES "Marginesy [cale]" PD32_MARGINS_IN_MILIMETERS "Marginesy [mm]" PD32_MILIMETERS "mm" @@ -437,6 +436,16 @@ STRINGTABLE DISCARDABLE PD32_PRINTER_STATUS_POWER_SAVE "Tryb oszczêdzania energii; " } +STRINGTABLE DISCARDABLE +{ + IDS_FONT_SIZE "Wybierz czcionkê o rozmiarze pomiêdzy %d a %d punktami." + IDS_SAVE_BUTTON "&Zapisz" + IDS_SAVE_IN "Zapisz &w:" + IDS_SAVE "Zapisz" + IDS_SAVE_AS "Zapisz jako" + IDS_OPEN_FILE "Otwórz Plik" +} + STRINGTABLE DISCARDABLE /* Color names */ { IDS_COLOR_BLACK "Czarny" diff --git a/reactos/lib/comdlg32/cdlg_Pt.rc b/reactos/lib/comdlg32/cdlg_Pt.rc index 26f0382d9af..af0258b9523 100644 --- a/reactos/lib/comdlg32/cdlg_Pt.rc +++ b/reactos/lib/comdlg32/cdlg_Pt.rc @@ -301,9 +301,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Configurações de Página" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papel", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Tamanho:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -407,7 +407,6 @@ pela sua impressora.\nPor favor entre um valor entre 1 e %d." PD32_DEFAULT_PRINTER "Impressora Padrão; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Existem %d documentos na fila" - PD32_PRINT_ALL_X_PAGES "&Todas %d páginas" PD32_MARGINS_IN_INCHES "Margens [polegadas]" PD32_MARGINS_IN_MILIMETERS "Margens [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_Ru.rc b/reactos/lib/comdlg32/cdlg_Ru.rc index e93c7c59ab6..1401f6cbccb 100644 --- a/reactos/lib/comdlg32/cdlg_Ru.rc +++ b/reactos/lib/comdlg32/cdlg_Ru.rc @@ -376,7 +376,6 @@ STRINGTABLE DISCARDABLE PD32_DEFAULT_PRINTER "Ïðèíòåð ïî óìîë÷àíèþ; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "%d äîêóìåíòîâ â î÷åðåäè" - PD32_PRINT_ALL_X_PAGES "&Âñå %d ñòðàíèö" PD32_MARGINS_IN_INCHES "Ãðàíèöû [äþéìû)" PD32_MARGINS_IN_MILIMETERS "Ãðàíèöû [ìì]" PD32_MILIMETERS "ìì" diff --git a/reactos/lib/comdlg32/cdlg_Si.rc b/reactos/lib/comdlg32/cdlg_Si.rc index 16208e78341..85afa8aa65f 100644 --- a/reactos/lib/comdlg32/cdlg_Si.rc +++ b/reactos/lib/comdlg32/cdlg_Si.rc @@ -300,9 +300,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Priprava strani" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papir", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "Veli&kost:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -405,7 +405,6 @@ Vnesite PD32_DEFAULT_PRINTER "Privzeti tiskalnik; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "%d èakajoèih dok." - PD32_PRINT_ALL_X_PAGES "&Vse strani -- %d" PD32_MARGINS_IN_INCHES "Robovi [palci]" PD32_MARGINS_IN_MILIMETERS "Robovi [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_Sk.rc b/reactos/lib/comdlg32/cdlg_Sk.rc index 25b3bd7f750..c402e1f7339 100644 --- a/reactos/lib/comdlg32/cdlg_Sk.rc +++ b/reactos/lib/comdlg32/cdlg_Sk.rc @@ -378,7 +378,6 @@ supported by your printer.\nPlease enter a value between 1 and %d" PD32_DEFAULT_PRINTER "Implicitná tlaèiareò; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "There are %d documents in queue" - PD32_PRINT_ALL_X_PAGES "&Všetky %d strany" PD32_MARGINS_IN_INCHES "Okraje [palce]" PD32_MARGINS_IN_MILIMETERS "Okraje [mm]" PD32_MILIMETERS "mm" diff --git a/reactos/lib/comdlg32/cdlg_Sv.rc b/reactos/lib/comdlg32/cdlg_Sv.rc index 57b45aed659..fba9fd44901 100644 --- a/reactos/lib/comdlg32/cdlg_Sv.rc +++ b/reactos/lib/comdlg32/cdlg_Sv.rc @@ -293,9 +293,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Utskriftsformat" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "Papper", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "&Storlek:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160,CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -398,7 +398,6 @@ pappersgr PD32_DEFAULT_PRINTER "Standardskrivare; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "Det är %d dokument i kön" - PD32_PRINT_ALL_X_PAGES "&Alla %d sidor" PD32_MARGINS_IN_INCHES "Marginaler [inches]" PD32_MARGINS_IN_MILIMETERS "Marginaler [millimeter]" PD32_MILIMETERS "millimeter" diff --git a/reactos/lib/comdlg32/cdlg_Th.rc b/reactos/lib/comdlg32/cdlg_Th.rc index 9a1e8c3ec66..1c6aef7edb8 100644 --- a/reactos/lib/comdlg32/cdlg_Th.rc +++ b/reactos/lib/comdlg32/cdlg_Th.rc @@ -297,9 +297,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "»ÃѺáµè§" FONT 8, "MS Shell Dlg" BEGIN - CONTROL "", rct1, 130, 0x00020006, 80, 8, 80, 80, SS_WHITERECT - CONTROL "", rct2, 130, 0x00020005, 160, 12, 4, 80, SS_GRAYRECT - CONTROL "", rct3, 130, 0x00020005, 84, 88, 80, 4, SS_GRAYRECT + CONTROL "", rct1, "Static", SS_WHITERECT, 80, 8, 80, 80 + CONTROL "", rct2, "Static", SS_GRAYRECT, 160, 12, 4, 80 + CONTROL "", rct3, "Static", SS_GRAYRECT, 84, 88, 80, 4 GROUPBOX "¡ÃдÒÉ", grp2, 8, 96, 224, 56, BS_GROUPBOX LTEXT "¢¹Ò´:", stc2, 16, 112, 36, 8 COMBOBOX cmb2, 64, 110, 160, 160, CBS_SIMPLE|CBS_DROPDOWN|CBS_SORT|WS_GROUP|WS_TABSTOP|WS_VSCROLL @@ -402,7 +402,6 @@ supported by your printer.\nPlease enter a value between 1 and %d." PD32_DEFAULT_PRINTER "à¤Ã×èͧ¾ÔÁ¾ì»¡µÔ; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "ÁÕ %d á¿éÁÃÍÍÂÙè" - PD32_PRINT_ALL_X_PAGES "·Ø¡ %d ˹éÒ" PD32_MARGINS_IN_INCHES "¢Íº¡ÃдÒÉ [¹ÔéÇ]" PD32_MARGINS_IN_MILIMETERS "¢Íº¡ÃдÒÉ [ÁÁ.]" PD32_MILIMETERS "ÁÁ." diff --git a/reactos/lib/comdlg32/cdlg_Uk.rc b/reactos/lib/comdlg32/cdlg_Uk.rc index 6b5dc878f3d..c746f90a5a6 100644 --- a/reactos/lib/comdlg32/cdlg_Uk.rc +++ b/reactos/lib/comdlg32/cdlg_Uk.rc @@ -376,7 +376,6 @@ STRINGTABLE DISCARDABLE PD32_DEFAULT_PRINTER "Ïðèíòåð çà îáóìîâëåííÿì; " PD32_NR_OF_DOCUMENTS_IN_QUEUE "%d äîêóìåíò³â ó ÷åðç³" - PD32_PRINT_ALL_X_PAGES "&Âñ³ %d ñòîð³íîê" PD32_MARGINS_IN_INCHES "Ìåæ³ [äþéìè]" PD32_MARGINS_IN_MILIMETERS "Ìåæ³ [ìì]" PD32_MILIMETERS "ìì" diff --git a/reactos/lib/comdlg32/colordlg.c b/reactos/lib/comdlg32/colordlg.c index fd6ad256cdb..9898f0d6819 100644 --- a/reactos/lib/comdlg32/colordlg.c +++ b/reactos/lib/comdlg32/colordlg.c @@ -1057,11 +1057,10 @@ LRESULT CC_WMCommand( HWND hDlg, WPARAM wParam, LPARAM lParam, WORD notifyCode, */ LRESULT CC_WMPaint( HWND hDlg, WPARAM wParam, LPARAM lParam ) { - HDC hdc; PAINTSTRUCT ps; LCCPRIV lpp = (LCCPRIV)GetWindowLongA(hDlg, DWL_USER); - hdc = BeginPaint(hDlg, &ps); + BeginPaint(hDlg, &ps); /* we have to paint dialog children except text and buttons */ CC_PaintPredefColorArray(hDlg, 6, 8); CC_PaintUserColorArray(hDlg, 2, 8, lpp->lpcc->lpCustColors); @@ -1072,7 +1071,7 @@ LRESULT CC_WMPaint( HWND hDlg, WPARAM wParam, LPARAM lParam ) CC_PaintColorGraph(hDlg); EndPaint(hDlg, &ps); - return TRUE; + return TRUE; } /*********************************************************************** @@ -1289,7 +1288,8 @@ BOOL WINAPI ChooseColorW( LPCHOOSECOLORW lpChCol ) { HRSRC hResInfo; HGLOBAL hDlgTmpl; - if (!(hResInfo = FindResourceA(COMDLG32_hInstance, "CHOOSE_COLOR", (LPSTR)RT_DIALOG))) + static const WCHAR wszCHOOSE_COLOR[] = {'C','H','O','O','S','E','_','C','O','L','O','R',0}; + if (!(hResInfo = FindResourceW(COMDLG32_hInstance, wszCHOOSE_COLOR, (LPWSTR)RT_DIALOG))) { COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE); return FALSE; diff --git a/reactos/lib/comdlg32/filedlg.c b/reactos/lib/comdlg32/filedlg.c index 4cc0868054a..232b3273a09 100644 --- a/reactos/lib/comdlg32/filedlg.c +++ b/reactos/lib/comdlg32/filedlg.c @@ -314,7 +314,7 @@ BOOL WINAPI GetFileDialog95A(LPOPENFILENAMEA ofn,UINT iDlgType) ZeroMemory(&fodInfos, sizeof(FileOpenDlgInfos)); /* Pass in the original ofn */ - fodInfos.ofnInfos = ofn; + fodInfos.ofnInfos = (LPOPENFILENAMEW)ofn; /* save current directory */ if (ofn->Flags & OFN_NOCHANGEDIR) @@ -445,13 +445,13 @@ BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType) { BOOL ret; FileOpenDlgInfos fodInfos; - LPSTR lpstrSavDir = NULL; + LPWSTR lpstrSavDir = NULL; /* Initialize FileOpenDlgInfos structure */ ZeroMemory(&fodInfos, sizeof(FileOpenDlgInfos)); /* Pass in the original ofn */ - fodInfos.ofnInfos = (LPOPENFILENAMEA) ofn; + fodInfos.ofnInfos = ofn; fodInfos.title = ofn->lpstrTitle; fodInfos.defext = ofn->lpstrDefExt; @@ -479,8 +479,8 @@ BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType) /* save current directory */ if (ofn->Flags & OFN_NOCHANGEDIR) { - lpstrSavDir = MemAlloc(MAX_PATH); - GetCurrentDirectoryA(MAX_PATH, lpstrSavDir); + lpstrSavDir = MemAlloc(MAX_PATH*sizeof(WCHAR)); + GetCurrentDirectoryW(MAX_PATH, lpstrSavDir); } fodInfos.unicode = TRUE; @@ -500,7 +500,7 @@ BOOL WINAPI GetFileDialog95W(LPOPENFILENAMEW ofn,UINT iDlgType) if (lpstrSavDir) { - SetCurrentDirectoryA(lpstrSavDir); + SetCurrentDirectoryW(lpstrSavDir); MemFree(lpstrSavDir); } @@ -729,12 +729,12 @@ HWND CreateTemplateDialog(FileOpenDlgInfos *fodInfos, HWND hwnd) hinst = fodInfos->ofnInfos->hInstance; if(fodInfos->unicode) { - LPOPENFILENAMEW ofn = (LPOPENFILENAMEW) fodInfos->ofnInfos; + LPOPENFILENAMEW ofn = fodInfos->ofnInfos; hRes = FindResourceW( hinst, ofn->lpTemplateName, (LPWSTR)RT_DIALOG); } else { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA)fodInfos->ofnInfos; hRes = FindResourceA( hinst, ofn->lpTemplateName, (LPSTR)RT_DIALOG); } if (!hRes) @@ -807,7 +807,7 @@ HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode) ofnNotify.hdr.hwndFrom=hwndParentDlg; ofnNotify.hdr.idFrom=0; ofnNotify.hdr.code = uCode; - ofnNotify.lpOFN = (LPOPENFILENAMEW) fodInfos->ofnInfos; + ofnNotify.lpOFN = fodInfos->ofnInfos; ofnNotify.pszFile = NULL; ret = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify); } @@ -817,7 +817,7 @@ HRESULT SendCustomDlgNotificationMessage(HWND hwndParentDlg, UINT uCode) ofnNotify.hdr.hwndFrom=hwndParentDlg; ofnNotify.hdr.idFrom=0; ofnNotify.hdr.code = uCode; - ofnNotify.lpOFN = fodInfos->ofnInfos; + ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos; ofnNotify.pszFile = NULL; ret = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg,WM_NOTIFY,0,(LPARAM)&ofnNotify); } @@ -1164,7 +1164,9 @@ static LRESULT FILEDLG95_InitControls(HWND hwnd) } else if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) { - SetWindowTextA(hwnd,"Save"); + WCHAR buf[16]; + LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, sizeof(buf)/sizeof(WCHAR)); + SetWindowTextW(hwnd, buf); } /* Initialise the file name edit control */ @@ -1388,11 +1390,14 @@ static LRESULT FILEDLG95_InitControls(HWND hwnd) (rectDlg.bottom-rectDlg.top) - (rectHelp.bottom - rectCancel.bottom), SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER); } - /* change Open to Save FIXME: use resources */ + /* change Open to Save */ if (fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG) { - SetDlgItemTextA(hwnd,IDOK,"&Save"); - SetDlgItemTextA(hwnd,IDC_LOOKINSTATIC,"Save &in"); + WCHAR buf[16]; + LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, buf, sizeof(buf)/sizeof(WCHAR)); + SetDlgItemTextW(hwnd, IDOK, buf); + LoadStringW(COMDLG32_hInstance, IDS_SAVE_IN, buf, sizeof(buf)/sizeof(WCHAR)); + SetDlgItemTextW(hwnd, IDC_LOOKINSTATIC, buf); } return 0; } @@ -1582,12 +1587,12 @@ BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPWSTR lpstrFileList, UINT nFileCo if(fodInfos->unicode) { - LPOPENFILENAMEW ofn = (LPOPENFILENAMEW) fodInfos->ofnInfos; + LPOPENFILENAMEW ofn = fodInfos->ofnInfos; ofn->lpstrFile[0] = '\0'; } else { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA) fodInfos->ofnInfos; ofn->lpstrFile[0] = '\0'; } @@ -1640,13 +1645,13 @@ BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPWSTR lpstrFileList, UINT nFileCo } if(fodInfos->unicode) { - LPOPENFILENAMEW ofn = (LPOPENFILENAMEW) fodInfos->ofnInfos; + LPOPENFILENAMEW ofn = fodInfos->ofnInfos; strcpyW( ofn->lpstrFile, lpstrPathSpec); memcpy( ofn->lpstrFile + nSizePath, lpstrFileList, sizeUsed*sizeof(WCHAR) ); } else { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA)fodInfos->ofnInfos; if (ofn->lpstrFile != NULL) { @@ -1684,14 +1689,14 @@ BOOL FILEDLG95_OnOpenMultipleFiles(HWND hwnd, LPWSTR lpstrFileList, UINT nFileCo #define ONOPEN_SEARCH 3 static void FILEDLG95_OnOpenMessage(HWND hwnd, int idCaption, int idText) { - char strMsgTitle[MAX_PATH]; - char strMsgText [MAX_PATH]; + WCHAR strMsgTitle[MAX_PATH]; + WCHAR strMsgText [MAX_PATH]; if (idCaption) - LoadStringA(COMDLG32_hInstance, idCaption, strMsgTitle, sizeof(strMsgTitle)); + LoadStringW(COMDLG32_hInstance, idCaption, strMsgTitle, sizeof(strMsgTitle)/sizeof(WCHAR)); else strMsgTitle[0] = '\0'; - LoadStringA(COMDLG32_hInstance, idText, strMsgText, sizeof(strMsgText)); - MessageBoxA(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND); + LoadStringW(COMDLG32_hInstance, idText, strMsgText, sizeof(strMsgText)/sizeof(WCHAR)); + MessageBoxW(hwnd,strMsgText, strMsgTitle, MB_OK | MB_ICONHAND); } BOOL FILEDLG95_OnOpen(HWND hwnd) @@ -2027,7 +2032,7 @@ BOOL FILEDLG95_OnOpen(HWND hwnd) { if(fodInfos->unicode) { - LPOPENFILENAMEW ofn = (LPOPENFILENAMEW) fodInfos->ofnInfos; + LPOPENFILENAMEW ofn = fodInfos->ofnInfos; strncpyW(ofn->lpstrFile, lpstrPathAndFile, ofn->nMaxFile); if (ofn->Flags & OFN_ALLOWMULTISELECT) @@ -2035,7 +2040,7 @@ BOOL FILEDLG95_OnOpen(HWND hwnd) } else { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA)fodInfos->ofnInfos; WideCharToMultiByte(CP_ACP, 0, lpstrPathAndFile, -1, ofn->lpstrFile, ofn->nMaxFile, NULL, NULL); @@ -2058,12 +2063,12 @@ BOOL FILEDLG95_OnOpen(HWND hwnd) LPWSTR lpstrFileTitle = PathFindFileNameW(lpstrPathAndFile); if(fodInfos->unicode) { - LPOPENFILENAMEW ofn = (LPOPENFILENAMEW) fodInfos->ofnInfos; + LPOPENFILENAMEW ofn = fodInfos->ofnInfos; strncpyW(ofn->lpstrFileTitle, lpstrFileTitle, ofn->nMaxFileTitle); } else { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA)fodInfos->ofnInfos; WideCharToMultiByte(CP_ACP, 0, lpstrFileTitle, -1, ofn->lpstrFileTitle, ofn->nMaxFileTitle, NULL, NULL); } @@ -2072,7 +2077,7 @@ BOOL FILEDLG95_OnOpen(HWND hwnd) /* copy currently selected filter to lpstrCustomFilter */ if (fodInfos->ofnInfos->lpstrCustomFilter) { - LPOPENFILENAMEA ofn = fodInfos->ofnInfos; + LPOPENFILENAMEA ofn = (LPOPENFILENAMEA)fodInfos->ofnInfos; int len = WideCharToMultiByte(CP_ACP, 0, fodInfos->ShellInfos.lpstrCurrentFilter, -1, NULL, 0, NULL, NULL); if (len + strlen(ofn->lpstrCustomFilter) + 1 <= ofn->nMaxCustFilter) @@ -3208,7 +3213,6 @@ HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrF if(!lpsf) { - HRESULT hRes; SHGetDesktopFolder(&lpsf); hRes = GetName(lpsf,pidl,dwFlags,lpstrFileName); IShellFolder_Release(lpsf); @@ -3358,10 +3362,7 @@ static void *MemAlloc(UINT size) static void MemFree(void *mem) { - if(mem) - { - HeapFree(GetProcessHeap(),0,mem); - } + HeapFree(GetProcessHeap(),0,mem); } /* diff --git a/reactos/lib/comdlg32/filedlg31.c b/reactos/lib/comdlg32/filedlg31.c index 1dab681c1e9..9f26997c4ef 100644 --- a/reactos/lib/comdlg32/filedlg31.c +++ b/reactos/lib/comdlg32/filedlg31.c @@ -586,11 +586,8 @@ static LRESULT FD31_DiskChange( PFD31_DATA lfs ) static LRESULT FD31_FileTypeChange( PFD31_DATA lfs ) { LONG lRet; - WCHAR diskname[BUFFILE]; LPWSTR pstr; - diskname[0] = 0; - lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0); if (lRet == LB_ERR) return TRUE; @@ -705,7 +702,6 @@ static LPWSTR FD31_DupToW(LPCSTR str, DWORD size) */ void FD31_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open) { - LPCSTR str; UNICODE_STRING usBuffer; ofnW->lStructSize = sizeof(OPENFILENAMEW); @@ -727,13 +723,18 @@ void FD31_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open) RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpstrInitialDir); ofnW->lpstrInitialDir = usBuffer.Buffer; } - if (ofnA->lpstrTitle) - str = ofnA->lpstrTitle; - else - /* Allocates default title (FIXME : get it from resource) */ - str = open ? "Open File" : "Save as"; - RtlCreateUnicodeStringFromAsciiz (&usBuffer,str); - ofnW->lpstrTitle = usBuffer.Buffer; + if (ofnA->lpstrTitle) { + RtlCreateUnicodeStringFromAsciiz (&usBuffer, ofnA->lpstrTitle); + ofnW->lpstrTitle = usBuffer.Buffer; + } else { + WCHAR buf[16]; + int len; + LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS, + buf, sizeof(buf)/sizeof(WCHAR)); + len = lstrlenW(buf)+1; + ofnW->lpstrTitle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + memcpy((void*)ofnW->lpstrTitle, buf, len*sizeof(WCHAR)); + } ofnW->Flags = ofnA->Flags; ofnW->nFileOffset = ofnA->nFileOffset; ofnW->nFileExtension = ofnA->nFileExtension; @@ -757,12 +758,12 @@ void FD31_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open) */ void FD31_FreeOfnW(LPOPENFILENAMEW ofnW) { - if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter); - if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter); - if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile); - if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle); - if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir); - if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle); + HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter); + HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter); + HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile); + HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle); + HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir); + HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle); if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName))) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName); } diff --git a/reactos/lib/comdlg32/filedlgbrowser.c b/reactos/lib/comdlg32/filedlgbrowser.c index 4a8a88f08a9..787b52ac2ad 100644 --- a/reactos/lib/comdlg32/filedlgbrowser.c +++ b/reactos/lib/comdlg32/filedlgbrowser.c @@ -216,10 +216,11 @@ HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface, ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface) { IShellBrowserImpl *This = (IShellBrowserImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p,%lu)\n", This, This->ref); + TRACE("(%p,%lu)\n", This, ref - 1); - return ++(This->ref); + return ref; } /************************************************************************** @@ -228,16 +229,17 @@ ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface) ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface) { IShellBrowserImpl *This = (IShellBrowserImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p,%lu)\n", This, This->ref); + TRACE("(%p,%lu)\n", This, ref + 1); - if (!--(This->ref)) + if (!ref) { COMDLG32_SHFree(This); TRACE("-- destroyed\n"); return 0; } - return This->ref; + return ref; } /* diff --git a/reactos/lib/comdlg32/filedlgbrowser.h b/reactos/lib/comdlg32/filedlgbrowser.h index b09fe0533ce..93543cf4f50 100644 --- a/reactos/lib/comdlg32/filedlgbrowser.h +++ b/reactos/lib/comdlg32/filedlgbrowser.h @@ -56,7 +56,7 @@ typedef struct { - LPOPENFILENAMEA ofnInfos; + LPOPENFILENAMEW ofnInfos; BOOL unicode; LPWSTR initdir; LPWSTR filename; diff --git a/reactos/lib/comdlg32/fontdlg.c b/reactos/lib/comdlg32/fontdlg.c index 4f2f413abfe..37acc272b71 100644 --- a/reactos/lib/comdlg32/fontdlg.c +++ b/reactos/lib/comdlg32/fontdlg.c @@ -36,7 +36,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(commdlg); -#define WINE_FONTDATA "__WINE_FONTDLGDATA" +static const WCHAR strWineFontData[] = {'_','_','W','I','N','E','_','F','O','N','T','D','L','G','D','A','T','A',0}; +static const WCHAR strWineFontData_a[] = + {'_','_','W','I','N','E','_','F','O','N','T','D','L','G','D','A','T','A','_','A',0}; +static const WCHAR chooseFontW[] = {'C','H','O','O','S','E','_','F','O','N','T',0}; #include "cdlg.h" @@ -44,11 +47,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(commdlg); static HIMAGELIST himlTT = 0; #define TTBITMAP_XSIZE 20 /* x-size of the bitmaps */ - -INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, - LPARAM lParam); -INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, - LPARAM lParam); +INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); /* There is a table here of all charsets, and the sample text for each. * There is a second table that translates a charset into an index into @@ -168,8 +168,7 @@ BOOL WINAPI ChooseFontW(LPCHOOSEFONTW lpChFont) HINSTANCE hDlginst; HGLOBAL hDlgTmpl; - static const WCHAR chooseFontW[] = {'C','H','O','O','S','E','_', - 'F','O','N','T',0}; + TRACE("(%p)\n", lpChFont); if ( (lpChFont->Flags&CF_ENABLETEMPLATEHANDLE)!=0 ) { @@ -221,6 +220,8 @@ BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont) HINSTANCE hDlginst; HGLOBAL hDlgTmpl; + TRACE("(%p)\n", lpChFont); + if ( (lpChFont->Flags&CF_ENABLETEMPLATEHANDLE)!=0 ) { template=(LPCVOID)lpChFont->hInstance; @@ -238,7 +239,7 @@ BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont) } else { hDlginst=COMDLG32_hInstance; - if (!(hResInfo = FindResourceA(hDlginst, "CHOOSE_FONT", (LPSTR)RT_DIALOG))) + if (!(hResInfo = FindResourceW(hDlginst, chooseFontW, (LPWSTR)RT_DIALOG))) { COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE); return FALSE; @@ -253,7 +254,6 @@ BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont) } if (TRACE_ON(commdlg)) _dump_cf_flags(lpChFont->Flags); - if (lpChFont->Flags & (CF_SELECTSCRIPT | CF_NOVERTFONTS )) FIXME(": unimplemented flag (ignored)\n"); @@ -261,7 +261,6 @@ BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont) lpChFont->hwndOwner, FormatCharDlgProcA, (LPARAM)lpChFont ); } - #define TEXT_EXTRAS 4 #define TEXT_COLORS 16 @@ -276,7 +275,7 @@ static const COLORREF textcolors[TEXT_COLORS]= /*********************************************************************** * CFn_HookCallChk32 [internal] */ -static BOOL CFn_HookCallChk32(LPCHOOSEFONTA lpcf) +static BOOL CFn_HookCallChk32(LPCHOOSEFONTW lpcf) { if (lpcf) if(lpcf->Flags & CF_ENABLEHOOK) @@ -288,14 +287,14 @@ static BOOL CFn_HookCallChk32(LPCHOOSEFONTA lpcf) /************************************************************************* * AddFontFamily [internal] */ -INT AddFontFamily(const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, - UINT nFontType, LPCHOOSEFONTA lpcf, HWND hwnd, LPCFn_ENUMSTRUCT e) +INT AddFontFamily(const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *lpNTM, + UINT nFontType, LPCHOOSEFONTW lpcf, HWND hwnd, LPCFn_ENUMSTRUCT e) { int i; WORD w; - const LOGFONTA *lplf = &(lpElfex->elfLogFont); + const LOGFONTW *lplf = &(lpElfex->elfLogFont); - TRACE("font=%s (nFontType=%d)\n", lplf->lfFaceName,nFontType); + TRACE("font=%s (nFontType=%d)\n", debugstr_w(lplf->lfFaceName), nFontType); if (lpcf->Flags & CF_FIXEDPITCHONLY) if (!(lplf->lfPitchAndFamily & FIXED_PITCH)) @@ -309,14 +308,14 @@ INT AddFontFamily(const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, if (e) e->added++; - i=SendMessageA(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)lplf->lfFaceName); + i=SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)lplf->lfFaceName); if (i == CB_ERR) { - i = SendMessageA(hwnd, CB_ADDSTRING, 0, (LPARAM)lplf->lfFaceName); + i = SendMessageW(hwnd, CB_ADDSTRING, 0, (LPARAM)lplf->lfFaceName); if( i != CB_ERR) { /* store some important font information */ w = (lplf->lfPitchAndFamily) << 8 | (HIWORD(lpNTM->ntmTm.ntmFlags) & 0xff); - SendMessageA(hwnd, CB_SETITEMDATA, i, MAKELONG(nFontType,w)); + SendMessageW(hwnd, CB_SETITEMDATA, i, MAKELONG(nFontType,w)); } } return 1; @@ -325,13 +324,13 @@ INT AddFontFamily(const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, /************************************************************************* * FontFamilyEnumProc32 [internal] */ -static INT WINAPI FontFamilyEnumProc(const ENUMLOGFONTEXA *lpElfex, - const TEXTMETRICA *metrics, DWORD dwFontType, LPARAM lParam) +static INT WINAPI FontFamilyEnumProc(const ENUMLOGFONTEXW *lpElfex, + const TEXTMETRICW *metrics, DWORD dwFontType, LPARAM lParam) { LPCFn_ENUMSTRUCT e; e=(LPCFn_ENUMSTRUCT)lParam; - return AddFontFamily( lpElfex, (NEWTEXTMETRICEXA *) metrics, - dwFontType, e->lpcf32a, e->hWnd1, e); + return AddFontFamily( lpElfex, (NEWTEXTMETRICEXW *) metrics, + dwFontType, e->lpcf32w, e->hWnd1, e); } /************************************************************************* @@ -339,42 +338,48 @@ static INT WINAPI FontFamilyEnumProc(const ENUMLOGFONTEXA *lpElfex, * * Fill font style information into combobox (without using font.c directly) */ -static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, const LOGFONTA *lplf) +static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, const LOGFONTW *lplf) { #define FSTYLES 4 struct FONTSTYLE { int italic; int weight; - const char *stname; + const WCHAR *stname; }; + static const WCHAR strRegular[] = {'R','e','g','u','l','a','r',0}; + static const WCHAR strItalic[] = {'I','t','a','l','i','c',0}; + static const WCHAR strBold[] = {'B','o','l','d',0}; + static const WCHAR strBoldItalic[] = {'B','o','l','d',' ','I','t','a','l','i','c',0}; static const struct FONTSTYLE fontstyles[FSTYLES]={ - { 0,FW_NORMAL,"Regular"}, { 1,FW_NORMAL,"Italic"}, - { 0,FW_BOLD,"Bold"}, { 1,FW_BOLD,"Bold Italic"} + { 0, FW_NORMAL, strRegular }, + { 1, FW_NORMAL, strItalic }, + { 0, FW_BOLD, strBold }, + { 1, FW_BOLD, strBoldItalic } }; HFONT hf; - TEXTMETRICA tm; + TEXTMETRICW tm; int i,j; - LOGFONTA lf; + LOGFONTW lf; - memcpy(&lf, lplf, sizeof(LOGFONTA)); + memcpy(&lf, lplf, sizeof(LOGFONTW)); for (i=0;iFlags & CF_LIMITSIZE)) || ((lpcf->Flags & CF_LIMITSIZE) && (h >= lpcf->nSizeMin) && (h <= lpcf->nSizeMax))) { - sprintf(buffer, "%2d", h); - j=SendMessageA(hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)buffer); + wsprintfW(buffer, strFormat, h); + j=SendMessageW(hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)buffer); if (j==CB_ERR) { - j=SendMessageA(hwnd, CB_ADDSTRING, 0, (LPARAM)buffer); - if (j!=CB_ERR) j = SendMessageA(hwnd, CB_SETITEMDATA, j, h); + j=SendMessageW(hwnd, CB_ADDSTRING, 0, (LPARAM)buffer); + if (j!=CB_ERR) j = SendMessageW(hwnd, CB_SETITEMDATA, j, h); if (j==CB_ERR) return 1; } } @@ -408,9 +414,9 @@ static int AddFontSizeToCombo3(HWND hwnd, UINT h, LPCHOOSEFONTA lpcf) /************************************************************************* * SetFontSizesToCombo3 [internal] */ -static int SetFontSizesToCombo3(HWND hwnd, LPCHOOSEFONTA lpcf) +static int SetFontSizesToCombo3(HWND hwnd, LPCHOOSEFONTW lpcf) { - static const char sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72}; + static const BYTE sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72}; int i; for (i = 0; i < sizeof(sizes)/sizeof(sizes[0]); i++) @@ -421,7 +427,7 @@ static int SetFontSizesToCombo3(HWND hwnd, LPCHOOSEFONTA lpcf) /************************************************************************* * CFn_GetDC [internal] */ -inline HDC CFn_GetDC(LPCHOOSEFONTA lpcf) +inline HDC CFn_GetDC(LPCHOOSEFONTW lpcf) { HDC ret = ((lpcf->Flags & CF_PRINTERFONTS) && lpcf->hDC) ? lpcf->hDC : @@ -433,7 +439,7 @@ inline HDC CFn_GetDC(LPCHOOSEFONTA lpcf) /************************************************************************* * CFn_ReleaseDC [internal] */ -inline void CFn_ReleaseDC(LPCHOOSEFONTA lpcf, HDC hdc) +inline void CFn_ReleaseDC(LPCHOOSEFONTW lpcf, HDC hdc) { if(!((lpcf->Flags & CF_PRINTERFONTS) && lpcf->hDC)) ReleaseDC(0, hdc); @@ -442,19 +448,19 @@ inline void CFn_ReleaseDC(LPCHOOSEFONTA lpcf, HDC hdc) /*********************************************************************** * AddFontStyle [internal] */ -INT AddFontStyle( const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, - UINT nFontType, LPCHOOSEFONTA lpcf, HWND hcmb2, HWND hcmb3, +INT AddFontStyle( const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *lpNTM, + UINT nFontType, LPCHOOSEFONTW lpcf, HWND hcmb2, HWND hcmb3, HWND hDlg, BOOL iswin16) { int i; - const LOGFONTA *lplf = &(lpElfex->elfLogFont); + const LOGFONTW *lplf = &(lpElfex->elfLogFont); HWND hcmb5; HDC hdc; TRACE("(nFontType=%d)\n",nFontType); TRACE(" %s h=%ld w=%ld e=%ld o=%ld wg=%ld i=%d u=%d s=%d" " ch=%d op=%d cp=%d q=%d pf=%xh\n", - lplf->lfFaceName,lplf->lfHeight,lplf->lfWidth, + debugstr_w(lplf->lfFaceName),lplf->lfHeight,lplf->lfWidth, lplf->lfEscapement,lplf->lfOrientation, lplf->lfWeight,lplf->lfItalic,lplf->lfUnderline, lplf->lfStrikeOut,lplf->lfCharSet, lplf->lfOutPrecision, @@ -467,10 +473,10 @@ INT AddFontStyle( const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, 72, GetDeviceCaps(hdc, LOGPIXELSY)); CFn_ReleaseDC(lpcf, hdc); i = AddFontSizeToCombo3(hcmb3, points, lpcf); - if( i) return 0; + if(i) return 0; } else if (SetFontSizesToCombo3(hcmb3, lpcf)) return 0; - if (!SendMessageA(hcmb2, CB_GETCOUNT, 0, 0)) + if (!SendMessageW(hcmb2, CB_GETCOUNT, 0, 0)) { if(!(hdc = CFn_GetDC(lpcf))) return 0; i=SetFontStylesToCombo2(hcmb2,hdc,lplf); @@ -479,13 +485,13 @@ INT AddFontStyle( const ENUMLOGFONTEXA *lpElfex, const NEWTEXTMETRICEXA *lpNTM, return 0; } if( iswin16 || !( hcmb5 = GetDlgItem(hDlg, cmb5))) return 1; - i = SendMessageA( hcmb5, CB_FINDSTRINGEXACT, 0, + i = SendMessageW( hcmb5, CB_FINDSTRINGEXACT, 0, (LPARAM)lpElfex->elfScript); if( i == CB_ERR) { - i = SendMessageA( hcmb5, CB_ADDSTRING, 0, + i = SendMessageW( hcmb5, CB_ADDSTRING, 0, (LPARAM)lpElfex->elfScript); if( i != CB_ERR) - SendMessageA( hcmb5, CB_SETITEMDATA, i, lplf->lfCharSet); + SendMessageW( hcmb5, CB_SETITEMDATA, i, lplf->lfCharSet); } return 1 ; } @@ -495,14 +501,14 @@ static INT CFn_FitFontSize( HWND hDlg, int points) int i,n; int ret = 0; /* look for fitting font size in combobox3 */ - n=SendDlgItemMessageA(hDlg, cmb3, CB_GETCOUNT, 0, 0); + n=SendDlgItemMessageW(hDlg, cmb3, CB_GETCOUNT, 0, 0); for (i=0;ihWnd1; HWND hcmb3=s->hWnd2; HWND hDlg=GetParent(hcmb3); - return AddFontStyle( lpElfex, (const NEWTEXTMETRICEXA *) metrics, - dwFontType, s->lpcf32a, hcmb2, hcmb3, hDlg, FALSE); + return AddFontStyle( lpElfex, (const NEWTEXTMETRICEXW *) metrics, + dwFontType, s->lpcf32w, hcmb2, hcmb3, hDlg, FALSE); } /*********************************************************************** * CFn_WMInitDialog [internal] */ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf) + LPCHOOSEFONTW lpcf) { HDC hdc; int i,j,init=0; long pstyle; CFn_ENUMSTRUCT s; - LPLOGFONTA lpxx; - HCURSOR hcursor=SetCursor(LoadCursorA(0,(LPSTR)IDC_WAIT)); + LPLOGFONTW lpxx; + HCURSOR hcursor=SetCursor(LoadCursorW(0,(LPWSTR)IDC_WAIT)); + static const WCHAR strColorName[] = {'[','c','o','l','o','r',' ','n','a','m','e',']',0}; - SetPropA(hDlg, WINE_FONTDATA, (HANDLE)lParam); + SetPropW(hDlg, strWineFontData, (HANDLE)lParam); lpxx=lpcf->lpLogFont; TRACE("WM_INITDIALOG lParam=%08lX\n", lParam); - if (lpcf->lStructSize != sizeof(CHOOSEFONTA)) + if (lpcf->lStructSize != sizeof(CHOOSEFONTW)) { ERR("structure size failure !!!\n"); EndDialog (hDlg, 0); return FALSE; } if (!himlTT) - himlTT = ImageList_LoadImageA( COMDLG32_hInstance, MAKEINTRESOURCEA(38), + himlTT = ImageList_LoadImageW( COMDLG32_hInstance, MAKEINTRESOURCEW(38), TTBITMAP_XSIZE, 0, CLR_DEFAULT, IMAGE_BITMAP, 0); if (!(lpcf->Flags & CF_SHOWHELP) || !IsWindow(lpcf->hwndOwner)) @@ -605,18 +612,18 @@ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, { for (i=0;irgbColors) - SendDlgItemMessageA(hDlg,cmb4, CB_SETCURSEL,j,0); + SendDlgItemMessageW(hDlg,cmb4, CB_SETCURSEL,j,0); } } else @@ -633,14 +640,14 @@ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, return FALSE; } s.hWnd1=GetDlgItem(hDlg,cmb1); - s.lpcf32a=lpcf; + s.lpcf32w=lpcf; do { - LOGFONTA elf; + LOGFONTW elf; s.added = 0; elf.lfCharSet = DEFAULT_CHARSET; /* enum all charsets */ elf.lfPitchAndFamily = 0; elf.lfFaceName[0] = '\0'; /* enum all fonts */ - if (!EnumFontFamiliesExA(hdc, &elf, (FONTENUMPROCA)FontFamilyEnumProc, (LPARAM)&s, 0)) + if (!EnumFontFamiliesExW(hdc, &elf, (FONTENUMPROCW)FontFamilyEnumProc, (LPARAM)&s, 0)) { TRACE("EnumFontFamiliesEx returns 0\n"); break; @@ -663,7 +670,7 @@ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, if (lpcf->Flags & CF_INITTOLOGFONTSTRUCT) { /* look for fitting font name in combobox1 */ - j=SendDlgItemMessageA(hDlg,cmb1,CB_FINDSTRING,-1,(LONG)lpxx->lfFaceName); + j=SendDlgItemMessageW(hDlg,cmb1,CB_FINDSTRING,-1,(LONG)lpxx->lfFaceName); if (j!=CB_ERR) { INT height = lpxx->lfHeight < 0 ? -lpxx->lfHeight : @@ -673,8 +680,8 @@ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, points = MulDiv( height, 72, GetDeviceCaps(hdc, LOGPIXELSY)); pstyle = MAKELONG(lpxx->lfWeight > FW_MEDIUM ? FW_BOLD: FW_NORMAL,lpxx->lfItalic !=0); - SendDlgItemMessageA(hDlg, cmb1, CB_SETCURSEL, j, 0); - SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE), + SendDlgItemMessageW(hDlg, cmb1, CB_SETCURSEL, j, 0); + SendMessageW(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE), (LPARAM)GetDlgItem(hDlg,cmb1)); init=1; /* look for fitting font style in combobox2 */ @@ -686,17 +693,17 @@ LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam, } if (!init) { - SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0); - SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE), + SendDlgItemMessageW(hDlg,cmb1,CB_SETCURSEL,0,0); + SendMessageW(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE), (LPARAM)GetDlgItem(hDlg,cmb1)); } if (lpcf->Flags & CF_USESTYLE && lpcf->lpszStyle) { - j=SendDlgItemMessageA(hDlg,cmb2,CB_FINDSTRING,-1,(LONG)lpcf->lpszStyle); + j=SendDlgItemMessageW(hDlg,cmb2,CB_FINDSTRING,-1,(LONG)lpcf->lpszStyle); if (j!=CB_ERR) { - j=SendDlgItemMessageA(hDlg,cmb2,CB_SETCURSEL,j,0); - SendMessageA(hDlg,WM_COMMAND,cmb2, + j=SendDlgItemMessageW(hDlg,cmb2,CB_SETCURSEL,j,0); + SendMessageW(hDlg,WM_COMMAND,cmb2, MAKELONG(HWND_16(GetDlgItem(hDlg,cmb2)),CBN_SELCHANGE)); } } @@ -716,18 +723,18 @@ LRESULT CFn_WMMeasureItem(HWND hDlg, WPARAM wParam, LPARAM lParam) TEXTMETRICW tm; LPMEASUREITEMSTRUCT lpmi=(LPMEASUREITEMSTRUCT)lParam; if (!himlTT) - himlTT = ImageList_LoadImageA( COMDLG32_hInstance, MAKEINTRESOURCEA(38), + himlTT = ImageList_LoadImageW( COMDLG32_hInstance, MAKEINTRESOURCEW(38), TTBITMAP_XSIZE, 0, CLR_DEFAULT, IMAGE_BITMAP, 0); ImageList_GetIconSize( himlTT, 0, &lpmi->itemHeight); lpmi->itemHeight += 2; /* use MAX of bitmap height and tm.tmHeight .*/ - hdc=GetDC( hDlg); + hdc=GetDC(hDlg); if(!hdc) return 0; hfontprev = SelectObject( hdc, GetStockObject( SYSTEM_FONT)); - GetTextMetricsW( hdc, &tm); + GetTextMetricsW(hdc, &tm); if( tm.tmHeight > lpmi->itemHeight) lpmi->itemHeight = tm.tmHeight; - SelectObject( hdc, hfontprev); - ReleaseDC( hDlg, hdc); + SelectObject(hdc, hfontprev); + ReleaseDC(hDlg, hdc); return 0; } @@ -738,7 +745,7 @@ LRESULT CFn_WMMeasureItem(HWND hDlg, WPARAM wParam, LPARAM lParam) LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam) { HBRUSH hBrush; - char buffer[40]; + WCHAR buffer[40]; COLORREF cr, oldText=0, oldBk=0; RECT rect; int nFontType; @@ -771,11 +778,11 @@ LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam) { case cmb1: /* TRACE(commdlg,"WM_Drawitem cmb1\n"); */ - SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, + SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, (LPARAM)buffer); - TextOutA(lpdi->hDC, lpdi->rcItem.left + TTBITMAP_XSIZE + 10, - lpdi->rcItem.top, buffer, strlen(buffer)); - nFontType = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L); + TextOutW(lpdi->hDC, lpdi->rcItem.left + TTBITMAP_XSIZE + 10, + lpdi->rcItem.top, buffer, lstrlenW(buffer)); + nFontType = SendMessageW(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L); idx = -1; if (nFontType & TRUETYPE_FONTTYPE) { idx = 0; /* picture: TT */ @@ -795,19 +802,19 @@ LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam) case cmb3: /* TRACE(commdlg,"WM_DRAWITEN cmb2,cmb3\n"); */ case cmb5: - SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, + SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, (LPARAM)buffer); - TextOutA(lpdi->hDC, lpdi->rcItem.left, - lpdi->rcItem.top, buffer, strlen(buffer)); + TextOutW(lpdi->hDC, lpdi->rcItem.left, + lpdi->rcItem.top, buffer, lstrlenW(buffer)); break; case cmb4: /* TRACE(commdlg,"WM_DRAWITEM cmb4 (=COLOR)\n"); */ - SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, - (LPARAM)buffer); - TextOutA(lpdi->hDC, lpdi->rcItem.left + 25+5, - lpdi->rcItem.top, buffer, strlen(buffer)); - cr = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L); + SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID, + (LPARAM)buffer); + TextOutW(lpdi->hDC, lpdi->rcItem.left + 25+5, + lpdi->rcItem.top, buffer, lstrlenW(buffer)); + cr = SendMessageW(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L); hBrush = CreateSolidBrush(cr); if (hBrush) { @@ -840,12 +847,12 @@ LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam) * CFn_WMCommand [internal] */ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf) + LPCHOOSEFONTW lpcf) { int i; long l; HDC hdc; - LPLOGFONTA lpxx=lpcf->lpLogFont; + LPLOGFONTW lpxx=lpcf->lpLogFont; TRACE("WM_COMMAND wParam=%08lX lParam=%08lX\n", (LONG)wParam, lParam); switch (LOWORD(wParam)) @@ -862,33 +869,33 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, EndDialog (hDlg, 0); return TRUE; } - idx = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0); - pointsize = (int)SendDlgItemMessageA( hDlg, cmb3, CB_GETITEMDATA, + idx = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0); + pointsize = (int)SendDlgItemMessageW( hDlg, cmb3, CB_GETITEMDATA, idx, 0); - idx = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0); - pstyle = SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, idx, 0); - idx = SendDlgItemMessageA(hDlg, cmb5, CB_GETCURSEL, 0, 0); - charset = SendDlgItemMessageA(hDlg, cmb5, CB_GETITEMDATA, idx, 0); + idx = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0); + pstyle = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, idx, 0); + idx = SendDlgItemMessageW(hDlg, cmb5, CB_GETCURSEL, 0, 0); + charset = SendDlgItemMessageW(hDlg, cmb5, CB_GETITEMDATA, idx, 0); - SendDlgItemMessageA(hDlg, cmb2, CB_RESETCONTENT, 0, 0); - SendDlgItemMessageA(hDlg, cmb3, CB_RESETCONTENT, 0, 0); - SendDlgItemMessageA(hDlg, cmb5, CB_RESETCONTENT, 0, 0); - i=SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL, 0, 0); + SendDlgItemMessageW(hDlg, cmb2, CB_RESETCONTENT, 0, 0); + SendDlgItemMessageW(hDlg, cmb3, CB_RESETCONTENT, 0, 0); + SendDlgItemMessageW(hDlg, cmb5, CB_RESETCONTENT, 0, 0); + i=SendDlgItemMessageW(hDlg, cmb1, CB_GETCURSEL, 0, 0); if (i!=CB_ERR) { - HCURSOR hcursor=SetCursor(LoadCursorA(0,(LPSTR)IDC_WAIT)); + HCURSOR hcursor=SetCursor(LoadCursorW(0,(LPWSTR)IDC_WAIT)); CFn_ENUMSTRUCT s; - LOGFONTA enumlf; - SendDlgItemMessageA(hDlg, cmb1, CB_GETLBTEXT, i, + LOGFONTW enumlf; + SendDlgItemMessageW(hDlg, cmb1, CB_GETLBTEXT, i, (LPARAM)enumlf.lfFaceName); - TRACE("WM_COMMAND/cmb1 =>%s\n",enumlf.lfFaceName); + TRACE("WM_COMMAND/cmb1 =>%s\n", debugstr_w(enumlf.lfFaceName)); s.hWnd1=GetDlgItem(hDlg, cmb2); s.hWnd2=GetDlgItem(hDlg, cmb3); - s.lpcf32a=lpcf; + s.lpcf32w=lpcf; enumlf.lfCharSet = DEFAULT_CHARSET; /* enum all charsets */ enumlf.lfPitchAndFamily = 0; - EnumFontFamiliesExA(hdc, &enumlf, - (FONTENUMPROCA)FontStyleEnumProc, (LPARAM)&s, 0); + EnumFontFamiliesExW(hdc, &enumlf, + (FONTENUMPROCW)FontStyleEnumProc, (LPARAM)&s, 0); CFn_FitFontStyle(hDlg, pstyle); if( pointsize != CB_ERR) CFn_FitFontSize(hDlg, pointsize); if( charset != CB_ERR) CFn_FitCharSet( hDlg, charset ); @@ -903,37 +910,37 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, case cmb5: if (HIWORD(wParam)==CBN_SELCHANGE || HIWORD(wParam)== BN_CLICKED ) { - char str[256]; + WCHAR str[256]; WINDOWINFO wininfo; TRACE("WM_COMMAND/cmb2,3 =%08lX\n", lParam); - i=SendDlgItemMessageA(hDlg,cmb1,CB_GETCURSEL,0,0); + i=SendDlgItemMessageW(hDlg,cmb1,CB_GETCURSEL,0,0); if (i==CB_ERR) - i=GetDlgItemTextA( hDlg, cmb1, str, 256 ); + i=GetDlgItemTextW( hDlg, cmb1, str, 256 ); else { - SendDlgItemMessageA(hDlg,cmb1,CB_GETLBTEXT,i, + SendDlgItemMessageW(hDlg,cmb1,CB_GETLBTEXT,i, (LPARAM)str); - l=SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,i,0); + l=SendDlgItemMessageW(hDlg,cmb1,CB_GETITEMDATA,i,0); lpcf->nFontType = LOWORD(l); /* FIXME: lpcf->nFontType |= .... SIMULATED_FONTTYPE and so */ /* same value reported to the EnumFonts call back with the extra FONTTYPE_... bits added */ lpxx->lfPitchAndFamily = HIWORD(l) >> 8; } - strcpy(lpxx->lfFaceName,str); - i=SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0); + lstrcpyW(lpxx->lfFaceName,str); + i=SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0); if (i!=CB_ERR) { - l=SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0); + l=SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0); if (0!=(lpxx->lfItalic=HIWORD(l))) lpcf->nFontType |= ITALIC_FONTTYPE; if ((lpxx->lfWeight=LOWORD(l)) > FW_MEDIUM) lpcf->nFontType |= BOLD_FONTTYPE; } - i=SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0); + i=SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0); if( i != CB_ERR) - lpcf->iPointSize = 10 * LOWORD(SendDlgItemMessageA(hDlg, cmb3, + lpcf->iPointSize = 10 * LOWORD(SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA , i, 0)); else lpcf->iPointSize = 100; @@ -945,9 +952,9 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, CFn_ReleaseDC(lpcf, hdc); } else lpxx->lfHeight = -lpcf->iPointSize / 10; - i=SendDlgItemMessageA(hDlg, cmb5, CB_GETCURSEL, 0, 0); + i=SendDlgItemMessageW(hDlg, cmb5, CB_GETCURSEL, 0, 0); if (i!=CB_ERR) - lpxx->lfCharSet=SendDlgItemMessageA(hDlg, cmb5, CB_GETITEMDATA, i, 0); + lpxx->lfCharSet=SendDlgItemMessageW(hDlg, cmb5, CB_GETITEMDATA, i, 0); else lpxx->lfCharSet = DEFAULT_CHARSET; lpxx->lfStrikeOut=IsDlgButtonChecked(hDlg,chx1); @@ -968,7 +975,7 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, break; case cmb4: - i=SendDlgItemMessageA(hDlg, cmb4, CB_GETCURSEL, 0, 0); + i=SendDlgItemMessageW(hDlg, cmb4, CB_GETCURSEL, 0, 0); if (i!=CB_ERR) { WINDOWINFO wininfo; @@ -985,9 +992,9 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, break; case psh15: - i=RegisterWindowMessageA( HELPMSGSTRINGA ); + i=RegisterWindowMessageW( HELPMSGSTRINGW ); if (lpcf->hwndOwner) - SendMessageA(lpcf->hwndOwner, i, 0, (LPARAM)GetPropA(hDlg, WINE_FONTDATA)); + SendMessageW(lpcf->hwndOwner, i, 0, (LPARAM)GetPropW(hDlg, strWineFontData)); /* if (CFn_HookCallChk(lpcf)) CallWindowProc16(lpcf->lpfnHook,hDlg,WM_COMMAND,psh15,(LPARAM)lpcf);*/ break; @@ -1000,10 +1007,11 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, EndDialog(hDlg, TRUE); else { - char buffer[80]; - sprintf(buffer,"Select a font size between %d and %d points.", - lpcf->nSizeMin,lpcf->nSizeMax); - MessageBoxA(hDlg, buffer, NULL, MB_OK); + WCHAR buffer[80]; + WCHAR format[80]; + LoadStringW(COMDLG32_hInstance, IDS_FONT_SIZE, format, sizeof(format)/sizeof(WCHAR)); + wsprintfW(buffer, format, lpcf->nSizeMin,lpcf->nSizeMax); + MessageBoxW(hDlg, buffer, NULL, MB_OK); } return(TRUE); case IDCANCEL: @@ -1013,18 +1021,44 @@ LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, return(FALSE); } -LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam) +LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam, LPCHOOSEFONTW lpcfw) { + LPCHOOSEFONTA lpcfa; + LPCSTR lpTemplateName; + LPSTR lpszStyle; + LPLOGFONTA lpLogFonta; + int len; + + lpcfa = GetPropW(hwnd, strWineFontData_a); + lpLogFonta = lpcfa->lpLogFont; + lpTemplateName = lpcfa->lpTemplateName; + lpszStyle = lpcfa->lpszStyle; + memcpy(lpcfa, lpcfw, sizeof(CHOOSEFONTA)); + lpcfa->lpLogFont = lpLogFonta; + lpcfa->lpTemplateName = lpTemplateName; + lpcfa->lpszStyle = lpszStyle; + memcpy(lpcfa->lpLogFont, lpcfw->lpLogFont, sizeof(LOGFONTA)); + WideCharToMultiByte(CP_ACP, 0, lpcfw->lpLogFont->lfFaceName, + LF_FACESIZE, lpcfa->lpLogFont->lfFaceName, LF_FACESIZE, 0, 0); + + if(lpcfw->lpszStyle) { + len = WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, NULL, -1, 0, 0); + WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, lpcfa->lpszStyle, len, 0, 0); + HeapFree(GetProcessHeap(), 0, lpcfw->lpszStyle); + } + + HeapFree(GetProcessHeap(), 0, (LPBYTE)lpcfw->lpTemplateName); + HeapFree(GetProcessHeap(), 0, lpcfw->lpLogFont); + HeapFree(GetProcessHeap(), 0, lpcfw); + return TRUE; } -LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, - LPCHOOSEFONTA lpcf ) +LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, LPCHOOSEFONTW lpcf) { WINDOWINFO info; info.cbSize=sizeof(info); - if( GetWindowInfo( GetDlgItem( hDlg, stc5), &info ) ) { PAINTSTRUCT ps; @@ -1032,7 +1066,7 @@ LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, HPEN hOrigPen; HFONT hOrigFont; COLORREF rgbPrev; - LOGFONTA lf = *(lpcf->lpLogFont); + LOGFONTW lf = *(lpcf->lpLogFont); MapWindowPoints( 0, hDlg, (LPPOINT) &info.rcWindow, 2); hdc = BeginPaint( hDlg, &ps ); @@ -1058,7 +1092,7 @@ LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, info.rcWindow.bottom--; info.rcWindow.top++; info.rcWindow.left++; - hOrigFont = SelectObject( hdc, CreateFontIndirectA( &lf ) ); + hOrigFont = SelectObject( hdc, CreateFontIndirectW( &lf ) ); rgbPrev=SetTextColor( hdc, lpcf->rgbColors ); DrawTextW( hdc, @@ -1077,29 +1111,50 @@ LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - LPCHOOSEFONTA lpcf; + LPCHOOSEFONTW lpcfw; + LPCHOOSEFONTA lpcfa; INT_PTR res = FALSE; + int len; - if (uMsg!=WM_INITDIALOG) - { - lpcf=(LPCHOOSEFONTA)GetPropA(hDlg, WINE_FONTDATA); - if (!lpcf && uMsg != WM_MEASUREITEM) + if (uMsg!=WM_INITDIALOG) { + lpcfw = (LPCHOOSEFONTW)GetPropW(hDlg, strWineFontData); + if (!lpcfw) return FALSE; - if (CFn_HookCallChk32(lpcf)) - res=CallWindowProcA((WNDPROC)lpcf->lpfnHook, hDlg, uMsg, wParam, lParam); + if (CFn_HookCallChk32(lpcfw)) + res=CallWindowProcA((WNDPROC)lpcfw->lpfnHook, hDlg, uMsg, wParam, lParam); if (res) return res; - } - else - { - lpcf=(LPCHOOSEFONTA)lParam; - if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf)) + } else { + lpcfa=(LPCHOOSEFONTA)lParam; + SetPropW(hDlg, strWineFontData_a, (HANDLE)lParam); + + lpcfw = HeapAlloc(GetProcessHeap(), 0, sizeof(CHOOSEFONTW)); + memcpy(lpcfw, lpcfa, sizeof(CHOOSEFONTA)); + lpcfw->lpLogFont = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGFONTW)); + memcpy(lpcfw->lpLogFont, lpcfa->lpLogFont, sizeof(LOGFONTA)); + MultiByteToWideChar(CP_ACP, 0, lpcfa->lpLogFont->lfFaceName, + LF_FACESIZE, lpcfw->lpLogFont->lfFaceName, LF_FACESIZE); + + if(lpcfa->lpszStyle) { + len = MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, NULL, 0); + lpcfw->lpszStyle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, lpcfw->lpszStyle, len); + } + + if(lpcfa->lpTemplateName) { + len = MultiByteToWideChar(CP_ACP, 0, lpcfa->lpTemplateName, -1, NULL, 0); + lpcfw->lpTemplateName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpcfa->lpTemplateName, + -1, (LPWSTR)lpcfw->lpTemplateName, len); + } + + if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcfw)) { TRACE("CFn_WMInitDialog returned FALSE\n"); return FALSE; } - if (CFn_HookCallChk32(lpcf)) - return CallWindowProcA((WNDPROC)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam); + if (CFn_HookCallChk32(lpcfw)) + return CallWindowProcA((WNDPROC)lpcfa->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam); } switch (uMsg) { @@ -1108,16 +1163,15 @@ INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, case WM_DRAWITEM: return CFn_WMDrawItem(hDlg, wParam, lParam); case WM_COMMAND: - return CFn_WMCommand(hDlg, wParam, lParam, lpcf); + return CFn_WMCommand(hDlg, wParam, lParam, lpcfw); case WM_DESTROY: - return CFn_WMDestroy(hDlg, wParam, lParam); + return CFn_WMDestroy(hDlg, wParam, lParam, lpcfw); case WM_CHOOSEFONT_GETLOGFONT: - TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", - lParam); + TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam); FIXME("current logfont back to caller\n"); break; case WM_PAINT: - return CFn_WMPaint(hDlg, wParam, lParam, lpcf); + return CFn_WMPaint(hDlg, wParam, lParam, lpcfw); } return res; } @@ -1128,29 +1182,29 @@ INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - LPCHOOSEFONTW lpcf32w; + LPCHOOSEFONTW lpcf; INT_PTR res = FALSE; if (uMsg!=WM_INITDIALOG) { - lpcf32w=(LPCHOOSEFONTW)GetPropA(hDlg, WINE_FONTDATA); - if (!lpcf32w) + lpcf=(LPCHOOSEFONTW)GetPropW(hDlg, strWineFontData); + if (!lpcf) return FALSE; - if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w)) - res=CallWindowProcW((WNDPROC)lpcf32w->lpfnHook, hDlg, uMsg, wParam, lParam); + if (CFn_HookCallChk32(lpcf)) + res=CallWindowProcW((WNDPROC)lpcf->lpfnHook, hDlg, uMsg, wParam, lParam); if (res) return res; } else { - lpcf32w=(LPCHOOSEFONTW)lParam; - if (!CFn_WMInitDialog(hDlg, wParam, lParam, (LPCHOOSEFONTA)lpcf32w)) + lpcf=(LPCHOOSEFONTW)lParam; + if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf)) { TRACE("CFn_WMInitDialog returned FALSE\n"); return FALSE; } - if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w)) - return CallWindowProcW((WNDPROC)lpcf32w->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam); + if (CFn_HookCallChk32(lpcf)) + return CallWindowProcW((WNDPROC)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam); } switch (uMsg) { @@ -1159,14 +1213,15 @@ INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, case WM_DRAWITEM: return CFn_WMDrawItem(hDlg, wParam, lParam); case WM_COMMAND: - return CFn_WMCommand(hDlg, wParam, lParam, (LPCHOOSEFONTW)lpcf32w); + return CFn_WMCommand(hDlg, wParam, lParam, lpcf); case WM_DESTROY: - return CFn_WMDestroy(hDlg, wParam, lParam); + return TRUE; case WM_CHOOSEFONT_GETLOGFONT: - TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", - lParam); + TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam); FIXME("current logfont back to caller\n"); break; + case WM_PAINT: + return CFn_WMPaint(hDlg, wParam, lParam, lpcf); } return res; } diff --git a/reactos/lib/comdlg32/fontdlg16.c b/reactos/lib/comdlg32/fontdlg16.c index 7ab9ea7fb77..5a04ccd9436 100644 --- a/reactos/lib/comdlg32/fontdlg16.c +++ b/reactos/lib/comdlg32/fontdlg16.c @@ -41,7 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(commdlg); #include "cdlg.h" #include "cdlg16.h" -static void FONT_LogFont16To32A( const LPLOGFONT16 font16, LPLOGFONTA font32 ) +static void FONT_LogFont16To32W( const LPLOGFONT16 font16, LPLOGFONTW font32 ) { font32->lfHeight = font16->lfHeight; font32->lfWidth = font16->lfWidth; @@ -56,35 +56,50 @@ static void FONT_LogFont16To32A( const LPLOGFONT16 font16, LPLOGFONTA font32 ) font32->lfClipPrecision = font16->lfClipPrecision; font32->lfQuality = font16->lfQuality; font32->lfPitchAndFamily = font16->lfPitchAndFamily; - lstrcpynA( font32->lfFaceName, font16->lfFaceName, LF_FACESIZE ); + MultiByteToWideChar(CP_ACP, 0, font16->lfFaceName, + LF_FACESIZE, font32->lfFaceName, LF_FACESIZE); }; -static void FONT_Metrics16To32A( const TEXTMETRIC16 *pm16, - NEWTEXTMETRICEXA *pnm32a) +static void FONT_Metrics16To32W( const TEXTMETRIC16 *pm16, + NEWTEXTMETRICEXW *pnm32w) { - ZeroMemory( pnm32a, sizeof(NEWTEXTMETRICEXA)); + ZeroMemory( pnm32w, sizeof(NEWTEXTMETRICEXW)); /* NOTE: only the fields used by AddFontStyle() are filled in */ - pnm32a->ntmTm.tmHeight = pm16->tmHeight; - pnm32a->ntmTm.tmExternalLeading = pm16->tmExternalLeading; + pnm32w->ntmTm.tmHeight = pm16->tmHeight; + pnm32w->ntmTm.tmExternalLeading = pm16->tmExternalLeading; }; -static void CFn_CHOOSEFONT16to32A(LPCHOOSEFONT16 chf16, LPCHOOSEFONTA chf32a) +static void CFn_CHOOSEFONT16to32W(LPCHOOSEFONT16 chf16, LPCHOOSEFONTW chf32w) { - chf32a->lStructSize=sizeof(CHOOSEFONTA); - chf32a->hwndOwner=HWND_32(chf16->hwndOwner); - chf32a->hDC=HDC_32(chf16->hDC); - chf32a->iPointSize=chf16->iPointSize; - chf32a->Flags=chf16->Flags; - chf32a->rgbColors=chf16->rgbColors; - chf32a->lCustData=chf16->lCustData; - chf32a->lpfnHook=NULL; - chf32a->lpTemplateName=MapSL(chf16->lpTemplateName); - chf32a->hInstance=HINSTANCE_32(chf16->hInstance); - chf32a->lpszStyle=MapSL(chf16->lpszStyle); - chf32a->nFontType=chf16->nFontType; - chf32a->nSizeMax=chf16->nSizeMax; - chf32a->nSizeMin=chf16->nSizeMin; - FONT_LogFont16To32A(MapSL(chf16->lpLogFont), chf32a->lpLogFont); + int len; + if(chf16->lpTemplateName) + { + len = MultiByteToWideChar(CP_ACP, 0, (LPBYTE)chf16->lpTemplateName, -1, NULL, 0); + chf32w->lpTemplateName = HeapAlloc(GetProcessHeap(), 0,len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, (LPSTR)MapSL(chf16->lpTemplateName), + -1, (LPWSTR)chf32w->lpTemplateName, len); + } + if(chf16->lpszStyle) + { + len = MultiByteToWideChar(CP_ACP, 0, (LPBYTE)chf16->lpszStyle, -1, NULL, 0); + chf32w->lpszStyle = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, (LPSTR)MapSL(chf16->lpTemplateName), + -1, chf32w->lpszStyle, len); + } + chf32w->lStructSize=sizeof(CHOOSEFONTW); + chf32w->hwndOwner=HWND_32(chf16->hwndOwner); + chf32w->hDC=HDC_32(chf16->hDC); + chf32w->iPointSize=chf16->iPointSize; + chf32w->Flags=chf16->Flags; + chf32w->rgbColors=chf16->rgbColors; + chf32w->lCustData=chf16->lCustData; + chf32w->lpfnHook=NULL; + chf32w->hInstance=HINSTANCE_32(chf16->hInstance); + chf32w->lpszStyle=MapSL(chf16->lpszStyle); + chf32w->nFontType=chf16->nFontType; + chf32w->nSizeMax=chf16->nSizeMax; + chf32w->nSizeMin=chf16->nSizeMin; + FONT_LogFont16To32W(MapSL(chf16->lpLogFont), chf32w->lpLogFont); }; /*********************************************************************** @@ -110,12 +125,12 @@ INT16 WINAPI FontFamilyEnumProc16( SEGPTR logfont, SEGPTR metrics, LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); LOGFONT16 *lplf = MapSL( logfont ); TEXTMETRIC16 *lpmtrx16 = MapSL(metrics); - ENUMLOGFONTEXA elf32a; - NEWTEXTMETRICEXA nmtrx32a; - FONT_LogFont16To32A(lplf, &(elf32a.elfLogFont)); - FONT_Metrics16To32A(lpmtrx16, &nmtrx32a); - return AddFontFamily(&elf32a, &nmtrx32a, nFontType, - (LPCHOOSEFONTA)lpcf->lpTemplateName, hwnd,NULL); + ENUMLOGFONTEXW elf32w; + NEWTEXTMETRICEXW nmtrx32w; + FONT_LogFont16To32W(lplf, &(elf32w.elfLogFont)); + FONT_Metrics16To32W(lpmtrx16, &nmtrx32w); + return AddFontFamily(&elf32w, &nmtrx32w, nFontType, + (LPCHOOSEFONTW)lpcf->lpTemplateName, hwnd,NULL); } /*********************************************************************** @@ -130,12 +145,12 @@ INT16 WINAPI FontStyleEnumProc16( SEGPTR logfont, SEGPTR metrics, LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); LOGFONT16 *lplf = MapSL(logfont); TEXTMETRIC16 *lpmtrx16 = MapSL(metrics); - ENUMLOGFONTEXA elf32a; - NEWTEXTMETRICEXA nmtrx32a; - FONT_LogFont16To32A(lplf, &(elf32a.elfLogFont)); - FONT_Metrics16To32A(lpmtrx16, &nmtrx32a); - return AddFontStyle(&elf32a, &nmtrx32a, nFontType, - (LPCHOOSEFONTA)lpcf->lpTemplateName, hcmb2, hcmb3, hDlg, TRUE); + ENUMLOGFONTEXW elf32w; + NEWTEXTMETRICEXW nmtrx32w; + FONT_LogFont16To32W(lplf, &(elf32w.elfLogFont)); + FONT_Metrics16To32W(lpmtrx16, &nmtrx32w); + return AddFontStyle(&elf32w, &nmtrx32w, nFontType, + (LPCHOOSEFONTW)lpcf->lpTemplateName, hcmb2, hcmb3, hDlg, TRUE); } /*********************************************************************** @@ -149,13 +164,13 @@ BOOL16 WINAPI ChooseFont16(LPCHOOSEFONT16 lpChFont) BOOL16 bRet = FALSE; LPCVOID template; FARPROC16 ptr; - CHOOSEFONTA cf32a; - LOGFONTA lf32a; + CHOOSEFONTW cf32w; + LOGFONTW lf32w; LOGFONT16 *font16; SEGPTR lpTemplateName; - cf32a.lpLogFont=&lf32a; - CFn_CHOOSEFONT16to32A(lpChFont, &cf32a); + cf32w.lpLogFont=&lf32w; + CFn_CHOOSEFONT16to32W(lpChFont, &cf32w); TRACE("ChooseFont\n"); if (!lpChFont) return FALSE; @@ -228,7 +243,7 @@ BOOL16 WINAPI ChooseFont16(LPCHOOSEFONT16 lpChFont) /* lpTemplateName is not used in the dialog */ lpTemplateName=lpChFont->lpTemplateName; - lpChFont->lpTemplateName=(SEGPTR)&cf32a; + lpChFont->lpTemplateName=(SEGPTR)&cf32w; ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 16); hInst = GetWindowLongPtrA(HWND_32(lpChFont->hwndOwner), GWLP_HINSTANCE); @@ -242,27 +257,32 @@ BOOL16 WINAPI ChooseFont16(LPCHOOSEFONT16 lpChFont) } lpChFont->lpTemplateName=lpTemplateName; - lpChFont->iPointSize = cf32a.iPointSize; - lpChFont->Flags = cf32a.Flags; - lpChFont->rgbColors = cf32a.rgbColors; - lpChFont->lCustData = cf32a.lCustData; - lpChFont->nFontType = cf32a.nFontType; + lpChFont->iPointSize = cf32w.iPointSize; + lpChFont->Flags = cf32w.Flags; + lpChFont->rgbColors = cf32w.rgbColors; + lpChFont->lCustData = cf32w.lCustData; + lpChFont->nFontType = cf32w.nFontType; font16 = MapSL(lpChFont->lpLogFont); - font16->lfHeight = cf32a.lpLogFont->lfHeight; - font16->lfWidth = cf32a.lpLogFont->lfWidth; - font16->lfEscapement = cf32a.lpLogFont->lfEscapement; - font16->lfOrientation = cf32a.lpLogFont->lfOrientation; - font16->lfWeight = cf32a.lpLogFont->lfWeight; - font16->lfItalic = cf32a.lpLogFont->lfItalic; - font16->lfUnderline = cf32a.lpLogFont->lfUnderline; - font16->lfStrikeOut = cf32a.lpLogFont->lfStrikeOut; - font16->lfCharSet = cf32a.lpLogFont->lfCharSet; - font16->lfOutPrecision = cf32a.lpLogFont->lfOutPrecision; - font16->lfClipPrecision = cf32a.lpLogFont->lfClipPrecision; - font16->lfQuality = cf32a.lpLogFont->lfQuality; - font16->lfPitchAndFamily = cf32a.lpLogFont->lfPitchAndFamily; - lstrcpynA( font16->lfFaceName, cf32a.lpLogFont->lfFaceName, LF_FACESIZE ); + font16->lfHeight = cf32w.lpLogFont->lfHeight; + font16->lfWidth = cf32w.lpLogFont->lfWidth; + font16->lfEscapement = cf32w.lpLogFont->lfEscapement; + font16->lfOrientation = cf32w.lpLogFont->lfOrientation; + font16->lfWeight = cf32w.lpLogFont->lfWeight; + font16->lfItalic = cf32w.lpLogFont->lfItalic; + font16->lfUnderline = cf32w.lpLogFont->lfUnderline; + font16->lfStrikeOut = cf32w.lpLogFont->lfStrikeOut; + font16->lfCharSet = cf32w.lpLogFont->lfCharSet; + font16->lfOutPrecision = cf32w.lpLogFont->lfOutPrecision; + font16->lfClipPrecision = cf32w.lpLogFont->lfClipPrecision; + font16->lfQuality = cf32w.lpLogFont->lfQuality; + font16->lfPitchAndFamily = cf32w.lpLogFont->lfPitchAndFamily; + WideCharToMultiByte(CP_ACP, 0, cf32w.lpLogFont->lfFaceName, + LF_FACESIZE, font16->lfFaceName, LF_FACESIZE, 0, 0); + + HeapFree(GetProcessHeap(), 0, (LPBYTE)cf32w.lpTemplateName); + HeapFree(GetProcessHeap(), 0, cf32w.lpszStyle); + return bRet; } @@ -291,7 +311,7 @@ BOOL16 CALLBACK FormatCharDlgProc16(HWND16 hDlg16, UINT16 message, else { lpcf=(LPCHOOSEFONT16)lParam; - if (!CFn_WMInitDialog(hDlg, wParam, lParam, (LPCHOOSEFONTA)lpcf->lpTemplateName)) + if (!CFn_WMInitDialog(hDlg, wParam, lParam, (LPCHOOSEFONTW)lpcf->lpTemplateName)) { TRACE("CFn_WMInitDialog returned FALSE\n"); return FALSE; @@ -337,17 +357,16 @@ BOOL16 CALLBACK FormatCharDlgProc16(HWND16 hDlg16, UINT16 message, break; case WM_COMMAND: res=CFn_WMCommand(hDlg, MAKEWPARAM( wParam, HIWORD(lParam) ), LOWORD(lParam), - (LPCHOOSEFONTA)lpcf->lpTemplateName); + (LPCHOOSEFONTW)lpcf->lpTemplateName); break; case WM_DESTROY: - res=CFn_WMDestroy(hDlg, wParam, lParam); - break; + return TRUE; case WM_CHOOSEFONT_GETLOGFONT: TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam); FIXME("current logfont back to caller\n"); break; case WM_PAINT: - res= CFn_WMPaint(hDlg, wParam, lParam, (LPCHOOSEFONTA)lpcf->lpTemplateName); + res= CFn_WMPaint(hDlg, wParam, lParam, (LPCHOOSEFONTW)lpcf->lpTemplateName); break; } return res; diff --git a/reactos/lib/comdlg32/printdlg.c b/reactos/lib/comdlg32/printdlg.c index 454b854235c..159169a829e 100644 --- a/reactos/lib/comdlg32/printdlg.c +++ b/reactos/lib/comdlg32/printdlg.c @@ -479,8 +479,8 @@ static BOOL PRINTDLG_PaperSizeA( out: GlobalUnlock(pdlga->hDevNames); GlobalUnlock(pdlga->hDevMode); - if (Names) HeapFree(GetProcessHeap(),0,Names); - if (points) HeapFree(GetProcessHeap(),0,points); + HeapFree(GetProcessHeap(),0,Names); + HeapFree(GetProcessHeap(),0,points); return retval; } @@ -537,8 +537,8 @@ static BOOL PRINTDLG_PaperSizeW( out: GlobalUnlock(pdlga->hDevNames); GlobalUnlock(pdlga->hDevMode); - if (Names) HeapFree(GetProcessHeap(),0,Names); - if (points) HeapFree(GetProcessHeap(),0,points); + HeapFree(GetProcessHeap(),0,Names); + HeapFree(GetProcessHeap(),0,points); return retval; } @@ -860,10 +860,8 @@ BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, DWORD needed; HANDLE hprn; - if(PrintStructures->lpPrinterInfo) - HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo); - if(PrintStructures->lpDriverInfo) - HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo); + HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo); + HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo); if(!OpenPrinterA(name, &hprn, NULL)) { ERR("Can't open printer %s\n", name); return FALSE; @@ -883,10 +881,8 @@ BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo); - if(PrintStructures->lpDevMode) { - HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); - PrintStructures->lpDevMode = NULL; - } + HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); + PrintStructures->lpDevMode = NULL; dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0); if(dmSize == -1) { @@ -928,15 +924,6 @@ BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, if (lppd->Flags & PD_PAGENUMS) CheckRadioButton(hDlg, rad1, rad3, rad3); } - /* "All xxx pages"... */ - { - char resourcestr[64]; - char result[64]; - LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, - resourcestr, 49); - sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1); - SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result); - } /* Collate pages * @@ -1022,10 +1009,8 @@ static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name, DWORD needed; HANDLE hprn; - if(PrintStructures->lpPrinterInfo) - HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo); - if(PrintStructures->lpDriverInfo) - HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo); + HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo); + HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo); if(!OpenPrinterW(name, &hprn, NULL)) { ERR("Can't open printer %s\n", debugstr_w(name)); return FALSE; @@ -1045,10 +1030,8 @@ static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name, PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo); - if(PrintStructures->lpDevMode) { - HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); - PrintStructures->lpDevMode = NULL; - } + HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode); + PrintStructures->lpDevMode = NULL; dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0); if(dmSize == -1) { @@ -1090,15 +1073,6 @@ static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name, if (lppd->Flags & PD_PAGENUMS) CheckRadioButton(hDlg, rad1, rad3, rad3); } - /* "All xxx pages"... */ - { - WCHAR resourcestr[64]; - WCHAR result[64]; - LoadStringW(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, - resourcestr, 49); - wsprintfW(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1); - SendDlgItemMessageW(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result); - } /* Collate pages * @@ -1412,7 +1386,7 @@ LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam, switch (LOWORD(wParam)) { case IDOK: TRACE(" OK button was hit\n"); - if (PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)!=TRUE) { + if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) { FIXME("Update printdlg was not successful!\n"); return(FALSE); } @@ -1589,7 +1563,7 @@ static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam, switch (LOWORD(wParam)) { case IDOK: TRACE(" OK button was hit\n"); - if (PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)!=TRUE) { + if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) { FIXME("Update printdlg was not successful!\n"); return(FALSE); } diff --git a/reactos/lib/cpl/access/access.rc b/reactos/lib/cpl/access/access.rc index 788e95b572a..dae44aee125 100644 --- a/reactos/lib/cpl/access/access.rc +++ b/reactos/lib/cpl/access/access.rc @@ -79,7 +79,7 @@ CAPTION "General" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN GROUPBOX "Automatic Reset",-1,PROPSHEETPADDING,LABELLINE(1),PROPSHEETWIDTH-(2*PROPSHEETPADDING),LABELLINE(5) - CHECKBOX "&Turn off accessbility features after idle for:",IDC_RESET_BOX,(2*PROPSHEETPADDING),LABELLINE(2)-2,PROPSHEETWIDTH-(6*PROPSHEETPADDING)-ICONSIZE,LABELLINE(2) + CHECKBOX "&Turn off accessibility features after idle for:",IDC_RESET_BOX,(2*PROPSHEETPADDING),LABELLINE(2)-2,PROPSHEETWIDTH-(6*PROPSHEETPADDING)-ICONSIZE,LABELLINE(2) //POPUP IDC_RESET_POPUP, GRAYED //{ @@ -112,5 +112,5 @@ END STRINGTABLE BEGIN IDS_CPLSYSTEMNAME "Accessibility" - IDS_CPLSYSTEMDESCRIPTION "Customizes accessbility features for your computer." + IDS_CPLSYSTEMDESCRIPTION "Customizes accessibility features for your computer." END diff --git a/reactos/lib/cpl/desk/Makefile b/reactos/lib/cpl/desk/Makefile index ae5df7f5ea7..6ee30dc9069 100644 --- a/reactos/lib/cpl/desk/Makefile +++ b/reactos/lib/cpl/desk/Makefile @@ -13,20 +13,20 @@ TARGET_INSTALLDIR = system32 TARGET_BASE = $(TARGET_BASE_LIB_CPL_DESK) TARGET_CFLAGS = \ - -I./include \ + -I./include \ -D_WIN32_IE=0x0600 \ -D_WIN32_WINNT=0x0501 \ -D__USE_W32API \ -DUNICODE \ -D_UNICODE \ - -D__REACTOS__ \ + -D__USE_W32API \ -Wall \ -Werror \ -fno-builtin TARGET_LFLAGS = -nostartfiles -TARGET_SDKLIBS = kernel32.a user32.a comctl32.a +TARGET_SDKLIBS = kernel32.a user32.a comctl32.a comdlg32.a advapi32.a gdi32.a TARGET_GCCLIBS = gcc @@ -34,7 +34,12 @@ TARGET_PCH = TARGET_CLEAN = -TARGET_OBJECTS = desk.o +TARGET_OBJECTS = desk.o \ + background.o \ + screensaver.o \ + appearance.o \ + settings.o \ + dibitmap.o DEP_OBJECTS = $(TARGET_OBJECTS) diff --git a/reactos/lib/cpl/desk/appearance.c b/reactos/lib/cpl/desk/appearance.c new file mode 100644 index 00000000000..ca0d7613413 --- /dev/null +++ b/reactos/lib/cpl/desk/appearance.c @@ -0,0 +1,34 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/appearance.c + * PURPOSE: Appearance property page + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) + */ + +#include +#include + +#include "resource.h" + +INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + { + } break; + + case WM_COMMAND: + { + } break; + } + + return FALSE; +} + diff --git a/reactos/lib/cpl/desk/background.c b/reactos/lib/cpl/desk/background.c new file mode 100644 index 00000000000..6898823cd2f --- /dev/null +++ b/reactos/lib/cpl/desk/background.c @@ -0,0 +1,611 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/background.c + * PURPOSE: Background property page + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) + */ + +#include +#include +#include +#include +#include + +#include "resource.h" + +#include "desk.h" +#include "dibitmap.h" + +#define MAX_BACKGROUNDS 100 + +#define PLACEMENT_CENTER 0 +#define PLACEMENT_STRETCH 1 +#define PLACEMENT_TILE 2 + +typedef struct +{ + BOOL bWallpaper; /* Is this background a wallpaper */ + + TCHAR szFilename[MAX_PATH]; + TCHAR szDisplayName[256]; + +} BackgroundItem; + +BackgroundItem g_backgroundItems[MAX_BACKGROUNDS]; + +DIBitmap *g_pWallpaperBitmap = NULL; + +int g_placementSelection = 0; +int g_backgroundSelection = 0; + +int g_listViewItemCount = 0; + +HWND g_hBackgroundPage = NULL; +HWND g_hBackgroundList = NULL; +HWND g_hBackgroundPreview = NULL; + +HWND g_hPlacementCombo = NULL; +HWND g_hColorButton = NULL; + +HIMAGELIST g_hShellImageList = NULL; + +/* Add the bitmaps in the C:\ReactOS directory and the current wallpaper if any */ +void AddListViewItems() +{ + WIN32_FIND_DATA fd; + HANDLE hFind; + TCHAR szSearchPath[MAX_PATH]; + LV_ITEM listItem; + LV_COLUMN dummy; + RECT clientRect; + HKEY regKey; + SHFILEINFO sfi; + HIMAGELIST himl; + TCHAR wallpaperFilename[MAX_PATH]; + DWORD bufferSize = sizeof(wallpaperFilename); + DWORD varType = REG_SZ; + LONG result; + UINT i = 0; + BackgroundItem *backgroundItem = NULL; + + GetClientRect(g_hBackgroundList, &clientRect); + + ZeroMemory(&dummy, sizeof(LV_COLUMN)); + dummy.mask = LVCF_SUBITEM | LVCF_WIDTH; + dummy.iSubItem = 0; + dummy.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL); + + ListView_InsertColumn(g_hBackgroundList, 0, &dummy); + + /* Add the "None" item */ + + backgroundItem = &g_backgroundItems[g_listViewItemCount]; + + backgroundItem->bWallpaper = FALSE; + + LoadString(hApplet, + IDS_NONE, + backgroundItem->szDisplayName, + sizeof(backgroundItem->szDisplayName) / sizeof(TCHAR)); + + ZeroMemory(&listItem, sizeof(LV_ITEM)); + listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; + listItem.state = LVIS_SELECTED; + listItem.pszText = backgroundItem->szDisplayName; + listItem.iImage = -1; + listItem.iItem = g_listViewItemCount; + listItem.lParam = g_listViewItemCount; + + ListView_InsertItem(g_hBackgroundList, &listItem); + ListView_SetItemState(g_hBackgroundList, g_listViewItemCount, LVIS_SELECTED, LVIS_SELECTED); + + g_listViewItemCount++; + + /* Add current wallpaper if any */ + + RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, ®Key); + + result = RegQueryValueEx(regKey, TEXT("Wallpaper"), 0, &varType, (LPBYTE)wallpaperFilename, &bufferSize); + + if((result == ERROR_SUCCESS) && (_tcslen(wallpaperFilename) > 0)) + { + himl = (HIMAGELIST)SHGetFileInfo(wallpaperFilename, + 0, + &sfi, + sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_SMALLICON | + SHGFI_DISPLAYNAME); + + if(himl != NULL) + { + if(i++ == 0) + { + g_hShellImageList = himl; + ListView_SetImageList(g_hBackgroundList, himl, LVSIL_SMALL); + } + + backgroundItem = &g_backgroundItems[g_listViewItemCount]; + + backgroundItem->bWallpaper = TRUE; + + _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName); + _tcscpy(backgroundItem->szFilename, wallpaperFilename); + + ZeroMemory(&listItem, sizeof(LV_ITEM)); + listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; + listItem.state = LVIS_SELECTED; + listItem.pszText = backgroundItem->szDisplayName; + listItem.iImage = sfi.iIcon; + listItem.iItem = g_listViewItemCount; + listItem.lParam = g_listViewItemCount; + + ListView_InsertItem(g_hBackgroundList, &listItem); + ListView_SetItemState(g_hBackgroundList, g_listViewItemCount, LVIS_SELECTED, LVIS_SELECTED); + + g_listViewItemCount++; + } + } + + RegCloseKey(regKey); + + /* Add all the bitmaps in the C:\ReactOS directory. */ + + GetWindowsDirectory(szSearchPath, MAX_PATH); + _tcscat(szSearchPath, TEXT("\\*.bmp")); + + hFind = FindFirstFile(szSearchPath, &fd); + while(hFind != INVALID_HANDLE_VALUE) + { + /* Don't add any hidden bitmaps */ + if((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) + { + TCHAR filename[MAX_PATH]; + + GetWindowsDirectory(filename, MAX_PATH); + + _tcscat(filename, TEXT("\\")); + _tcscat(filename, fd.cFileName); + + himl = (HIMAGELIST)SHGetFileInfo(filename, + 0, + &sfi, + sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_SMALLICON | + SHGFI_DISPLAYNAME); + + if(himl == NULL) + { + break; + } + + if(i++ == 0) + { + g_hShellImageList = himl; + ListView_SetImageList(g_hBackgroundList, himl, LVSIL_SMALL); + } + + backgroundItem = &g_backgroundItems[g_listViewItemCount]; + + backgroundItem->bWallpaper = TRUE; + + _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName); + _tcscpy(backgroundItem->szFilename, filename); + + ZeroMemory(&listItem, sizeof(LV_ITEM)); + listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; + listItem.pszText = backgroundItem->szDisplayName; + listItem.state = 0; + listItem.iImage = sfi.iIcon; + listItem.iItem = g_listViewItemCount; + listItem.lParam = g_listViewItemCount; + + ListView_InsertItem(g_hBackgroundList, &listItem); + + g_listViewItemCount++; + } + + if(!FindNextFile(hFind, &fd)) + hFind = INVALID_HANDLE_VALUE; + } +} + +void InitBackgroundDialog() +{ + g_hBackgroundList = GetDlgItem(g_hBackgroundPage, IDC_BACKGROUND_LIST); + g_hBackgroundPreview = GetDlgItem(g_hBackgroundPage, IDC_BACKGROUND_PREVIEW); + g_hPlacementCombo = GetDlgItem(g_hBackgroundPage, IDC_PLACEMENT_COMBO); + g_hColorButton = GetDlgItem(g_hBackgroundPage, IDC_COLOR_BUTTON); + + AddListViewItems(); + + TCHAR szString[256]; + + LoadString(hApplet, IDS_CENTER, szString, sizeof(szString) / sizeof(TCHAR)); + SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_CENTER, (LPARAM)szString); + + LoadString(hApplet, IDS_STRETCH, szString, sizeof(szString) / sizeof(TCHAR)); + SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_STRETCH, (LPARAM)szString); + + LoadString(hApplet, IDS_TILE, szString, sizeof(szString) / sizeof(TCHAR)); + SendMessage(g_hPlacementCombo, CB_INSERTSTRING, PLACEMENT_TILE, (LPARAM)szString); + + /* Load the default settings from the registry */ + HKEY regKey; + + TCHAR szBuffer[2]; + DWORD bufferSize = sizeof(szBuffer); + DWORD varType = REG_SZ; + LONG result; + + RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, ®Key); + + result = RegQueryValueEx(regKey, TEXT("WallpaperStyle"), 0, &varType, (LPBYTE)szBuffer, &bufferSize); + + if(result == ERROR_SUCCESS) + { + if(_ttoi(szBuffer) == 0) + { + SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_CENTER, 0); + g_placementSelection = PLACEMENT_CENTER; + } + + if(_ttoi(szBuffer) == 2) + { + SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_STRETCH, 0); + g_placementSelection = PLACEMENT_STRETCH; + } + } + else + { + SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_CENTER, 0); + g_placementSelection = PLACEMENT_CENTER; + } + + result = RegQueryValueEx(regKey, TEXT("TileWallpaper"), 0, &varType, (LPBYTE)szBuffer, &bufferSize); + + if(result == ERROR_SUCCESS) + { + if(_ttoi(szBuffer) == 1) + { + SendMessage(g_hPlacementCombo, CB_SETCURSEL, PLACEMENT_TILE, 0); + g_placementSelection = PLACEMENT_TILE; + } + } + + RegCloseKey(regKey); +} + +void OnColorButton() +{ + MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK); +} + +BOOL CheckListBoxFilename(HWND list, TCHAR *filename) +{ + return FALSE; +} + +void OnBrowseButton() +{ + OPENFILENAME ofn; + TCHAR filename[MAX_PATH]; + TCHAR fileTitle[256]; + BackgroundItem *backgroundItem = NULL; + + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = g_hBackgroundPage; + ofn.lpstrFile = filename; + + /* Set lpstrFile[0] to '\0' so that GetOpenFileName does not + * use the contents of szFile to initialize itself */ + ofn.lpstrFile[0] = TEXT('\0'); + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFilter = TEXT("Bitmap Files (*.bmp)\0*.bmp\0"); + ofn.nFilterIndex = 0; + ofn.lpstrFileTitle = fileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + if(GetOpenFileName(&ofn) == TRUE) + { + /* Check if there is already a entry that holds this filename */ + if(CheckListBoxFilename(g_hBackgroundList, filename) == TRUE) + return; + + SHFILEINFO sfi; + LV_ITEM listItem; + + if(g_listViewItemCount > (MAX_BACKGROUNDS - 1)) + return; + + SHGetFileInfo(filename, + 0, + &sfi, + sizeof(sfi), + SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_DISPLAYNAME); + + backgroundItem = &g_backgroundItems[g_listViewItemCount]; + + backgroundItem->bWallpaper = TRUE; + + _tcscpy(backgroundItem->szDisplayName, sfi.szDisplayName); + _tcscpy(backgroundItem->szFilename, filename); + + ZeroMemory(&listItem, sizeof(LV_ITEM)); + listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE; + listItem.state = 0; + listItem.pszText = backgroundItem->szDisplayName; + listItem.iImage = sfi.iIcon; + listItem.iItem = g_listViewItemCount; + listItem.lParam = g_listViewItemCount; + + ListView_InsertItem(g_hBackgroundList, &listItem); + + g_listViewItemCount++; + } +} + +void ListViewItemChanged(int itemIndex) +{ + BackgroundItem *backgroundItem = NULL; + + g_backgroundSelection = itemIndex; + backgroundItem = &g_backgroundItems[g_backgroundSelection]; + + if(g_pWallpaperBitmap != NULL) + { + DibFreeImage(g_pWallpaperBitmap); + g_pWallpaperBitmap = NULL; + } + + if(backgroundItem->bWallpaper == TRUE) + { + g_pWallpaperBitmap = DibLoadImage(backgroundItem->szFilename); + + if(g_pWallpaperBitmap == NULL) + { + return; + } + } + + InvalidateRect(g_hBackgroundPreview, NULL, TRUE); + + EnableWindow(g_hColorButton, (backgroundItem->bWallpaper == FALSE ? TRUE : FALSE)); + EnableWindow(g_hPlacementCombo, backgroundItem->bWallpaper); + + PropSheet_Changed(GetParent(g_hBackgroundPage), g_hBackgroundPage); +} + +void DrawBackgroundPreview(LPDRAWITEMSTRUCT draw) +{ + if(g_backgroundItems[g_backgroundSelection].bWallpaper == FALSE) + { + FillRect(draw->hDC, &draw->rcItem, GetSysColorBrush(COLOR_BACKGROUND)); + return; + } + + if(g_pWallpaperBitmap == NULL) + return; + + float scaleX = ((float)GetSystemMetrics(SM_CXSCREEN) - 1) / (float)draw->rcItem.right; + float scaleY = ((float)GetSystemMetrics(SM_CYSCREEN) - 1) / (float)draw->rcItem.bottom; + + int scaledWidth = g_pWallpaperBitmap->width / scaleX; + int scaledHeight = g_pWallpaperBitmap->height / scaleY; + + int posX = (draw->rcItem.right / 2) - (scaledWidth / 2); + int posY = (draw->rcItem.bottom / 2) - (scaledHeight / 2); + + FillRect(draw->hDC, &draw->rcItem, GetSysColorBrush(COLOR_BACKGROUND)); + + SetStretchBltMode(draw->hDC, COLORONCOLOR); + + if(g_placementSelection == PLACEMENT_CENTER) + { + StretchDIBits(draw->hDC, + posX, + posY, + scaledWidth, + scaledHeight, + 0, + 0, + g_pWallpaperBitmap->width, + g_pWallpaperBitmap->height, + g_pWallpaperBitmap->bits, + g_pWallpaperBitmap->info, + DIB_RGB_COLORS, + SRCCOPY); + } + + if(g_placementSelection == PLACEMENT_STRETCH) + { + StretchDIBits(draw->hDC, + 0, + 0, + draw->rcItem.right, + draw->rcItem.bottom, + 0, + 0, + g_pWallpaperBitmap->width, + g_pWallpaperBitmap->height, + g_pWallpaperBitmap->bits, + g_pWallpaperBitmap->info, + DIB_RGB_COLORS, + SRCCOPY); + } + + if(g_placementSelection == PLACEMENT_TILE) + { + int x; + int y; + + for(y = 0; y < draw->rcItem.bottom; y += scaledHeight) + { + for(x = 0; x < draw->rcItem.right; x += scaledWidth) + { + StretchDIBits(draw->hDC, + x, + y, + scaledWidth, + scaledHeight, + 0, + 0, + g_pWallpaperBitmap->width, + g_pWallpaperBitmap->height, + g_pWallpaperBitmap->bits, + g_pWallpaperBitmap->info, + DIB_RGB_COLORS, + SRCCOPY); + } + } + } +} + +void SetWallpaper() +{ + HKEY regKey; + + RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, ®Key); + + if(g_placementSelection == PLACEMENT_TILE) + { + RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("1"), sizeof(TCHAR) * 2); + RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2); + } + + if(g_placementSelection == PLACEMENT_CENTER) + { + RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2); + RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2); + } + + if(g_placementSelection == PLACEMENT_STRETCH) + { + RegSetValueEx(regKey, TEXT("TileWallpaper"), 0, REG_SZ, (BYTE *)TEXT("0"), sizeof(TCHAR) * 2); + RegSetValueEx(regKey, TEXT("WallpaperStyle"), 0, REG_SZ, (BYTE *)TEXT("2"), sizeof(TCHAR) * 2); + } + + RegCloseKey(regKey); + + if(g_backgroundItems[g_backgroundSelection].bWallpaper == TRUE) + { + SystemParametersInfo(SPI_SETDESKWALLPAPER, + 0, + g_backgroundItems[g_backgroundSelection].szFilename, + SPIF_UPDATEINIFILE); + } + else + { + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, TEXT(""), SPIF_UPDATEINIFILE); + } +} + +INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + g_hBackgroundPage = hwndDlg; + + switch(uMsg) + { + case WM_INITDIALOG: + { + InitBackgroundDialog(); + } break; + + case WM_COMMAND: + { + DWORD controlId = LOWORD(wParam); + DWORD command = HIWORD(wParam); + + switch(controlId) + { + case IDC_COLOR_BUTTON: + { + if(command == BN_CLICKED) + OnColorButton(); + + } break; + + case IDC_BROWSE_BUTTON: + { + if(command == BN_CLICKED) + OnBrowseButton(); + + } break; + + case IDC_PLACEMENT_COMBO: + { + if(command == CBN_SELCHANGE) + { + g_placementSelection = SendMessage(g_hPlacementCombo, CB_GETCURSEL, 0, 0); + + InvalidateRect(g_hBackgroundPreview, NULL, TRUE); + + PropSheet_Changed(GetParent(g_hBackgroundPage), g_hBackgroundPage); + } + + } break; + } + } break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT drawItem; + drawItem = (LPDRAWITEMSTRUCT)lParam; + + if(drawItem->CtlID == IDC_BACKGROUND_PREVIEW) + { + DrawBackgroundPreview(drawItem); + } + + } break; + + case WM_NOTIFY: + { + LPNMHDR lpnm = (LPNMHDR)lParam; + + switch(lpnm->code) + { + case PSN_APPLY: + { + SetWallpaper(); + + return TRUE; + } break; + + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam; + + if((nm->uNewState & LVIS_SELECTED) == 0) + return FALSE; + + ListViewItemChanged(nm->iItem); + + } break; + + default: + break; + } + + } break; + + case WM_DESTROY: + { + if(g_pWallpaperBitmap != NULL) + DibFreeImage(g_pWallpaperBitmap); + + } break; + } + + return FALSE; +} + diff --git a/reactos/lib/cpl/desk/desk.c b/reactos/lib/cpl/desk/desk.c index 1c45c41e09e..d64825ce450 100644 --- a/reactos/lib/cpl/desk/desk.c +++ b/reactos/lib/cpl/desk/desk.c @@ -1,214 +1,128 @@ -/* - * ReactOS - * Copyright (C) 2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Display Control Panel * FILE: lib/cpl/desk/desk.c * PURPOSE: ReactOS Display Control Panel - * PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com) - * UPDATE HISTORY: - * 06-17-2004 Created - * 08-07-2004 Initial Checkin + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) */ -#include -#include -#include -#include #include - #include #include -#include - #include "resource.h" #include "desk.h" #define NUM_APPLETS (1) -LONG CALLBACK DisplayApplet(VOID); -INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam); +extern INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); HINSTANCE hApplet = 0; /* Applets */ APPLET Applets[NUM_APPLETS] = { - {IDI_CPLSYSTEM, IDS_CPLSYSTEMNAME, IDS_CPLSYSTEMDESCRIPTION, DisplayApplet} + { + IDC_DESK_ICON, + IDS_CPLNAME, + IDS_CPLDESCRIPTION, + DisplayApplet + } }; - - -/* Property page dialog callback */ -INT_PTR CALLBACK -BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +static VOID InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc) { - switch(uMsg) - { - case WM_INITDIALOG: - break; - case WM_COMMAND: - break; - } - return FALSE; + ZeroMemory(psp, sizeof(PROPSHEETPAGE)); + psp->dwSize = sizeof(PROPSHEETPAGE); + psp->dwFlags = PSP_DEFAULT; + psp->hInstance = hApplet; + psp->pszTemplate = MAKEINTRESOURCE(idDlg); + psp->pfnDlgProc = DlgProc; } - -/* Property page dialog callback */ -INT_PTR CALLBACK -ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +/* Display Applet */ +LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LONG wParam, LONG lParam) { - switch(uMsg) - { - case WM_INITDIALOG: - break; - case WM_COMMAND: - break; - } - return FALSE; -} - - -/* Property page dialog callback */ -INT_PTR CALLBACK -AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_INITDIALOG: - break; - case WM_COMMAND: - break; - } - return FALSE; -} - - -/* Property page dialog callback */ -INT_PTR CALLBACK -SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_INITDIALOG: - break; - case WM_COMMAND: - break; - } - return FALSE; -} - - -static VOID -InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc) -{ - ZeroMemory(psp, sizeof(PROPSHEETPAGE)); - psp->dwSize = sizeof(PROPSHEETPAGE); - psp->dwFlags = PSP_DEFAULT; - psp->hInstance = hApplet; - psp->pszTemplate = MAKEINTRESOURCE(idDlg); - psp->pfnDlgProc = DlgProc; -} - - -/* First Applet */ - -LONG CALLBACK -DisplayApplet(VOID) -{ - PROPSHEETPAGE psp[4]; - PROPSHEETHEADER psh; - TCHAR Caption[1024]; - - LoadString(hApplet, IDS_CPLSYSTEMNAME, Caption, sizeof(Caption) / sizeof(TCHAR)); - - ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); - psh.dwSize = sizeof(PROPSHEETHEADER); - psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE; - psh.hwndParent = NULL; - psh.hInstance = hApplet; - psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM)); - psh.pszCaption = Caption; - psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); - psh.nStartPage = 0; - psh.ppsp = psp; - psh.pfnCallback = NULL; - - InitPropSheetPage(&psp[0], IDD_PROPPAGEBACKGROUND, BackgroundPageProc); - InitPropSheetPage(&psp[1], IDD_PROPPAGESCREENSAVER, ScreenSaverPageProc); - InitPropSheetPage(&psp[2], IDD_PROPPAGEAPPEARANCE, AppearancePageProc); - InitPropSheetPage(&psp[3], IDD_PROPPAGESETTINGS, SettingsPageProc); - - return (LONG)(PropertySheet(&psh) != -1); + PROPSHEETPAGE psp[4]; + PROPSHEETHEADER psh; + TCHAR Caption[1024]; + + LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR)); + + ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_PROPTITLE; + psh.hwndParent = NULL; + psh.hInstance = hApplet; + psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON)); + psh.pszCaption = Caption; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.nStartPage = 0; + psh.ppsp = psp; + + InitPropSheetPage(&psp[0], IDD_BACKGROUND, BackgroundPageProc); + InitPropSheetPage(&psp[1], IDD_SCREENSAVER, ScreenSaverPageProc); + InitPropSheetPage(&psp[2], IDD_APPEARANCE, AppearancePageProc); + InitPropSheetPage(&psp[3], IDD_SETTINGS, SettingsPageProc); + + return (LONG)(PropertySheet(&psh) != -1); } /* Control Panel Callback */ -LONG CALLBACK -CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2) +LONG CALLBACK CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { - int i = (int)lParam1; - - switch(uMsg) - { - case CPL_INIT: - { - return TRUE; - } - case CPL_GETCOUNT: - { - return NUM_APPLETS; - } - case CPL_INQUIRE: - { - CPLINFO *CPlInfo = (CPLINFO*)lParam2; - CPlInfo->lData = 0; - CPlInfo->idIcon = Applets[i].idIcon; - CPlInfo->idName = Applets[i].idName; - CPlInfo->idInfo = Applets[i].idDescription; - break; - } - case CPL_DBLCLK: - { - Applets[i].AppletProc(); - break; - } - } - return FALSE; + int i = (int)lParam1; + + switch(uMsg) + { + case CPL_INIT: + { + return TRUE; + } + + case CPL_GETCOUNT: + { + return NUM_APPLETS; + } + + case CPL_INQUIRE: + { + CPLINFO *CPlInfo = (CPLINFO*)lParam2; + CPlInfo->lData = 0; + CPlInfo->idIcon = Applets[i].idIcon; + CPlInfo->idName = Applets[i].idName; + CPlInfo->idInfo = Applets[i].idDescription; + } break; + + case CPL_DBLCLK: + { + Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); + } break; + } + + return FALSE; } -BOOL WINAPI -DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) { - switch(dwReason) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - hApplet = hinstDLL; - break; - } - return TRUE; + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + { + hApplet = hinstDLL; + } break; + } + + return TRUE; } diff --git a/reactos/lib/cpl/desk/desk.dsp b/reactos/lib/cpl/desk/desk.dsp deleted file mode 100644 index ff57b0a2ce9..00000000000 --- a/reactos/lib/cpl/desk/desk.dsp +++ /dev/null @@ -1,124 +0,0 @@ -# Microsoft Developer Studio Project File - Name="desk" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=desk - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "desk.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "desk.mak" CFG="desk - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "desk - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "desk - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "desk - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "desk_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "desk_EXPORTS" /D "_UNICODE" /D "UNICODE" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" /d "_MSC_VER" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /machine:I386 /out:"Release/desk.cpl" - -!ELSEIF "$(CFG)" == "desk - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "desk_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "desk_EXPORTS" /D "_UNICODE" /D "UNICODE" /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" /d "_MSC_VER" -# SUBTRACT RSC /x -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /debug /machine:I386 /out:"Debug/desk.cpl" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "desk - Win32 Release" -# Name "desk - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\desk.c -# End Source File -# Begin Source File - -SOURCE=.\desk.h -# End Source File -# Begin Source File - -SOURCE=.\resource.h -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\desk.def -# End Source File -# Begin Source File - -SOURCE=.\desk.rc -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/reactos/lib/cpl/desk/desk.h b/reactos/lib/cpl/desk/desk.h index c4bb7b71243..eb600d83f9b 100644 --- a/reactos/lib/cpl/desk/desk.h +++ b/reactos/lib/cpl/desk/desk.h @@ -1,20 +1,17 @@ -#ifndef __CPL_APPWIZ_H -#define __CPL_APPWIZ_H - -typedef LONG (CALLBACK *CPLAPPLET_PROC)(VOID); +#ifndef __CPL_DESK_H__ +#define __CPL_DESK_H__ typedef struct { - int idIcon; - int idName; - int idDescription; - CPLAPPLET_PROC AppletProc; + int idIcon; + int idName; + int idDescription; + + APPLET_PROC AppletProc; + } APPLET, *PAPPLET; extern HINSTANCE hApplet; -void ShowLastWin32Error(HWND hWndOwner); +#endif /* __CPL_DESK_H__ */ -#endif /* __CPL_APPWIZ_H */ - -/* EOF */ diff --git a/reactos/lib/cpl/desk/desk.rc b/reactos/lib/cpl/desk/desk.rc index 532fd994b6f..426e4a01382 100644 --- a/reactos/lib/cpl/desk/desk.rc +++ b/reactos/lib/cpl/desk/desk.rc @@ -1,119 +1,16 @@ +#include #include "resource.h" -#ifdef _MSC_VER -#include <../../../include/defines.h> -#else -#include -#endif +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Display Panel\0" -#define REACTOS_STR_INTERNAL_NAME "desk\0" -#define REACTOS_STR_ORIGINAL_FILENAME "desk.cpl\0" -#ifdef _MSC_VER -#include <../../../include/reactos/version.rc> -#else +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Display Panel\0" +#define REACTOS_STR_INTERNAL_NAME "desk\0" +#define REACTOS_STR_ORIGINAL_FILENAME "desk.cpl\0" + #include -#endif -IDD_PROPPAGEBACKGROUND DIALOGEX 0, 0, 246, 228 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Background" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - GROUPBOX "&Pattern",1001,5,118,115,92 - LISTBOX 1002,11,130,103,42,LBS_SORT | LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "&Edit Pattern...",1003,53,175,61,14 - GROUPBOX "&Wallpaper",1004,127,118,115,92 - LISTBOX 1005,133,130,103,42,LBS_SORT | LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "&Browse...",1006,174,175,61,14 - LTEXT "&Position:",1007,134,196,28,8 - COMBOBOX 1008,169,193,67,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | - WS_TABSTOP -END +IDC_DESK_ICON ICON "resources/applet.ico" -IDD_PROPPAGESCREENSAVER DIALOGEX 0, 0, 246, 228 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Screen Saver" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - GROUPBOX "&Screen Saver",200,4,129,238,48 - COMBOBOX 1000,10,140,115,200,CBS_DROPDOWNLIST | CBS_SORT | - WS_VSCROLL | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Se&ttings...",1003,130,139,50,14,WS_GROUP - PUSHBUTTON "Pre&view",1004,183,139,50,14 - CONTROL "&Lock desktop on resume",1020,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,157,112,9 - LTEXT "&Wait:",1016,151,160,17,9 - EDITTEXT 1006,170,158,30,12,ES_RIGHT | WS_GROUP - CONTROL "",1007,"msctls_updown32",UDS_SETBUDDYINT | - UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | - UDS_NOTHOUSANDS | WS_BORDER | WS_GROUP,203,158,11,12 - LTEXT "minutes",1022,204,160,28,9 - GROUPBOX "Energy saving features of monitor",1017,4,179,238,33 - PUSHBUTTON "P&ower...",1014,175,190,50,14 - LTEXT "To adjust the power settings for your monitor, click Power.", - 1018,19,190,155,16 - CONTROL "",1002,"Static",SS_BITMAP | SS_CENTERIMAGE,60,11,125, - 107 -END +#include "en.rc" -IDD_PROPPAGEAPPEARANCE DIALOGEX 0, 0, 246, 228 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Appearance" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - LTEXT "&Color Scheme:",-1,3,130,30,9 - COMBOBOX 1400,3,140,131,200,CBS_DROPDOWNLIST | CBS_SORT | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Sa&ve As...",1401,138,140,50,14 - PUSHBUTTON "&Delete",1402,191,140,50,14 - LTEXT "&Item:",-1,3,159,26,9 - COMBOBOX 1403,3,169,131,200,CBS_DROPDOWNLIST | CBS_SORT | - WS_VSCROLL | WS_TABSTOP - LTEXT "Si&ze:",1450,138,159,16,9 - EDITTEXT 1404,138,169,38,13,ES_RIGHT | WS_GROUP - CONTROL "",1411,"msctls_updown32",UDS_SETBUDDYINT | - UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | - WS_BORDER | WS_GROUP,168,169,10,13 - LTEXT "Co&lor:",1451,180,159,20,9 - LTEXT "Color &2:",1455,212,159,28,9 - LTEXT "&Font:",1452,3,188,20,9 - COMBOBOX 1407,3,198,131,200,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | - WS_TABSTOP - LTEXT "Siz&e:",1454,138,188,17,8 - COMBOBOX 1408,138,198,38,200,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | - WS_TABSTOP - LTEXT "Colo&r:",1453,180,188,20,9 - CHECKBOX "B",1409,212,198,14,13,BS_PUSHLIKE - CHECKBOX "I",1410,226,198,14,13,BS_PUSHLIKE -END - -IDD_PROPPAGESETTINGS DIALOGEX 0, 0, 246, 228 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Settings" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - LTEXT "&Display:",1820,3,140,30,8 - GROUPBOX "&Colors",1817,3,160,115,43 - COMBOBOX 1807,9,170,103,80,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | - CBS_SORT | WS_VSCROLL | WS_TABSTOP - CONTROL "",1813,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_SUNKEN, - 9,188,103,9 - GROUPBOX "&Screen area",1818,125,160,115,43 - CONTROL "",1808,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP, - 152,170,58,17 - LTEXT "Less",1815,131,170,15,8,NOT WS_GROUP - LTEXT "More",1816,215,170,21,8,NOT WS_GROUP - CTEXT "640 X 480 pixels",1814,132,190,100,10,NOT WS_GROUP - PUSHBUTTON "Ad&vanced...",1802,184,205,56,14 - LTEXT "",1050,19,149,224,8 -END - -STRINGTABLE -BEGIN - IDS_CPLSYSTEMNAME "Display" - IDS_CPLSYSTEMDESCRIPTION "Customizes your desktop display and screen saver." -END diff --git a/reactos/lib/cpl/desk/desk.xml b/reactos/lib/cpl/desk/desk.xml index a984a82009a..bf3faf4bc26 100644 --- a/reactos/lib/cpl/desk/desk.xml +++ b/reactos/lib/cpl/desk/desk.xml @@ -9,7 +9,14 @@ 0x501 kernel32 user32 + advapi32 + gdi32 comctl32 + comdlg32 desk.c - desk.rc + background.c + screensaver.c + appearance.c + settings.c + dibitmap.c diff --git a/reactos/lib/cpl/desk/dibitmap.c b/reactos/lib/cpl/desk/dibitmap.c new file mode 100644 index 00000000000..661c58ea1e2 --- /dev/null +++ b/reactos/lib/cpl/desk/dibitmap.c @@ -0,0 +1,92 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/dibitmap.c + * PURPOSE: DIB loading + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) + */ + +#include "dibitmap.h" + +DIBitmap *DibLoadImage(TCHAR *filename) +{ + BOOL bSuccess; + DWORD dwFileSize, dwHighSize, dwBytesRead; + HANDLE hFile; + DIBitmap *bitmap; + + hFile = CreateFile(filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) + return NULL; + + dwFileSize = GetFileSize(hFile, &dwHighSize); + + if(dwHighSize) + { + CloseHandle(hFile); + return NULL; + } + + bitmap = malloc(sizeof(DIBitmap)); + if(!bitmap) + return NULL; + + bitmap->header = malloc(dwFileSize); + if(!bitmap->header) + { + CloseHandle(hFile); + return NULL; + } + + bSuccess = ReadFile(hFile, bitmap->header, dwFileSize, &dwBytesRead, NULL); + CloseHandle(hFile); + + if(!bSuccess || (dwBytesRead != dwFileSize) + || (bitmap->header->bfType != * (WORD *) "BM") + || (bitmap->header->bfSize != dwFileSize)) + { + free(bitmap->header); + return NULL; + } + + bitmap->info = (BITMAPINFO *)(bitmap->header + 1); + bitmap->bits = (BYTE *)bitmap->header + bitmap->header->bfOffBits; + + /* Get the DIB width and height */ + if(bitmap->info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + bitmap->width = ((BITMAPCOREHEADER *)bitmap->info)->bcWidth; + bitmap->height = ((BITMAPCOREHEADER *)bitmap->info)->bcHeight; + } + else + { + bitmap->width = bitmap->info->bmiHeader.biWidth; + bitmap->height = abs(bitmap->info->bmiHeader.biHeight); + } + + return bitmap; +} + +void DibFreeImage(DIBitmap *bitmap) +{ + if(bitmap == NULL) + return; + + /* Free the header */ + if(bitmap->header != NULL) + free(bitmap->header); + + /* Free the bitmap structure */ + if(bitmap != NULL) + free(bitmap); +} + diff --git a/reactos/lib/cpl/desk/dibitmap.h b/reactos/lib/cpl/desk/dibitmap.h new file mode 100644 index 00000000000..cb5b0ab0909 --- /dev/null +++ b/reactos/lib/cpl/desk/dibitmap.h @@ -0,0 +1,22 @@ + +#ifndef __DIBITMAP_H__ +#define __DIBITMAP_H__ + +#include + +typedef struct +{ + BITMAPFILEHEADER *header; + BITMAPINFO *info; + BYTE *bits; + + int width; + int height; + +} DIBitmap; + +extern DIBitmap *DibLoadImage(TCHAR *filename); +extern void DibFreeImage(DIBitmap *bitmap); + +#endif /* __DIBITMAP_H__ */ + diff --git a/reactos/lib/cpl/desk/en.rc b/reactos/lib/cpl/desk/en.rc new file mode 100644 index 00000000000..88614bfa290 --- /dev/null +++ b/reactos/lib/cpl/desk/en.rc @@ -0,0 +1,59 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +IDD_BACKGROUND DIALOGEX DISCARDABLE 0, 0, 246, 228 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Background" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_BACKGROUND_PREVIEW,"Static",SS_OWNERDRAW,48,10, + 150,105,WS_EX_STATICEDGE + CONTROL "",IDC_BACKGROUND_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_NOCOLUMNHEADER | LVS_SHAREIMAGELISTS | + WS_BORDER | WS_TABSTOP,7,139,173,71 + LTEXT "Select an image to use as your desktop wallpaper:", + IDC_STATIC,8,127,180,8 + PUSHBUTTON "&Browse...",IDC_BROWSE_BUTTON,187,175,50,14 + PUSHBUTTON "&Color...",IDC_COLOR_BUTTON,187,195,50,14 + LTEXT "Placement:",IDC_STATIC,187,138,36,8 + COMBOBOX IDC_PLACEMENT_COMBO,187,148,50,90,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_SCREENSAVER DIALOGEX DISCARDABLE 0, 0, 246, 228 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Screen Saver" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "This space is intentionally left blank",IDC_STATIC,66, + 110,112,8 +END + +IDD_APPEARANCE DIALOGEX DISCARDABLE 0, 0, 246, 228 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Appearance" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "This space is intentionally left blank",IDC_STATIC,66, + 110,112,8 +END + +IDD_SETTINGS DIALOGEX DISCARDABLE 0, 0, 246, 228 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Settings" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "This space is intentionally left blank",IDC_STATIC,66, + 110,112,8 +END + +STRINGTABLE +BEGIN + IDS_CPLNAME "Display" + IDS_CPLDESCRIPTION "Customizes the desktop display and screen saver." + + IDS_NONE "(None)" + IDS_CENTER "Center" + IDS_STRETCH "Stretch" + IDS_TILE "Tile" +END + diff --git a/reactos/lib/cpl/desk/resource.h b/reactos/lib/cpl/desk/resource.h index 82fc09e75ba..c1fc9bce05a 100644 --- a/reactos/lib/cpl/desk/resource.h +++ b/reactos/lib/cpl/desk/resource.h @@ -1,33 +1,40 @@ -#ifndef __CPL_RESOURCE_H -#define __CPL_RESOURCE_H +#ifndef __CPL_DESK_RESOURCE_H__ +#define __CPL_DESK_RESOURCE_H__ /* metrics */ -#define PROPSHEETWIDTH 246 -#define PROPSHEETHEIGHT 228 -#define PROPSHEETPADDING 6 -#define SYSTEM_COLUMN (0 * PROPSHEETPADDING) -// this is not supported by the MS Resource compiler: -//#define LABELLINE(x) 0 //(((PROPSHEETPADDING + 2) * x) + (x + 2)) +#define PROPSHEETWIDTH 246 +#define PROPSHEETHEIGHT 228 +#define PROPSHEETPADDING 6 -#define ICONSIZE 16 +#define SYSTEM_COLUMN (18 * PROPSHEETPADDING) +#define LABELLINE(x) (((PROPSHEETPADDING + 2) * x) + (x + 2)) + +#define ICONSIZE 16 /* ids */ +#define IDC_DESK_ICON 1 -#define IDI_CPLSYSTEM 100 +#define IDC_STATIC -1 -#define IDD_PROPPAGEBACKGROUND 100 -#define IDD_PROPPAGESCREENSAVER 101 -#define IDD_PROPPAGEAPPEARANCE 102 -#define IDD_PROPPAGESETTINGS 103 +#define IDD_BACKGROUND 100 +#define IDD_SCREENSAVER 101 +#define IDD_APPEARANCE 102 +#define IDD_SETTINGS 103 -#define IDS_CPLSYSTEMNAME 1001 -#define IDS_CPLSYSTEMDESCRIPTION 2001 +/* Background Page */ +#define IDC_BACKGROUND_LIST 1000 +#define IDC_BACKGROUND_PREVIEW 1001 +#define IDC_BROWSE_BUTTON 1002 +#define IDC_COLOR_BUTTON 1003 +#define IDC_PLACEMENT_COMBO 1004 -/* controls */ -#define IDC_INSTALL 101 -#define IDC_SOFTWARELIST 102 -#define IDC_ADDREMOVE 103 +#define IDS_CPLNAME 2000 +#define IDS_CPLDESCRIPTION 2001 -#endif /* __CPL_RESOURCE_H */ +#define IDS_NONE 2002 +#define IDS_CENTER 2003 +#define IDS_STRETCH 2004 +#define IDS_TILE 2005 + +#endif /* __CPL_DESK_RESOURCE_H__ */ -/* EOF */ diff --git a/reactos/lib/cpl/desk/screensaver.c b/reactos/lib/cpl/desk/screensaver.c new file mode 100644 index 00000000000..c80337b2145 --- /dev/null +++ b/reactos/lib/cpl/desk/screensaver.c @@ -0,0 +1,34 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/screensaver.c + * PURPOSE: Screen saver property page + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) + */ + +#include +#include + +#include "resource.h" + +INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + { + } break; + + case WM_COMMAND: + { + } break; + } + + return FALSE; +} + diff --git a/reactos/lib/cpl/desk/settings.c b/reactos/lib/cpl/desk/settings.c new file mode 100644 index 00000000000..7c2b0d2695d --- /dev/null +++ b/reactos/lib/cpl/desk/settings.c @@ -0,0 +1,34 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Display Control Panel + * FILE: lib/cpl/desk/settings.c + * PURPOSE: Settings property page + * + * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) + */ + +#include +#include + +#include "resource.h" + +INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + { + } break; + + case WM_COMMAND: + { + } break; + } + + return FALSE; +} + diff --git a/reactos/lib/cpl/timedate/De.rc b/reactos/lib/cpl/timedate/De.rc index 715f3b68227..9a135150e10 100644 --- a/reactos/lib/cpl/timedate/De.rc +++ b/reactos/lib/cpl/timedate/De.rc @@ -37,4 +37,7 @@ STRINGTABLE BEGIN IDS_CPLNAME "Datum/Zeit" IDS_CPLDESCRIPTION "Ändert die Uhrzeit, Datum und Zeitzone." + IDS_TIMEZONETEXT "Aktuelle Zeitzone: %s" + IDS_TIMEZONEINVALID "Ungültig" + IDS_TIMEZONEUNKNOWN "Unbekannt" END diff --git a/reactos/lib/cpl/timedate/En.rc b/reactos/lib/cpl/timedate/En.rc index 01a2e4dac67..257d610093d 100644 --- a/reactos/lib/cpl/timedate/En.rc +++ b/reactos/lib/cpl/timedate/En.rc @@ -16,7 +16,7 @@ BEGIN CONTROL "", IDC_TIMEPICKER, "SysDateTimePick32", DTS_TIMEFORMAT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 144, 17, 90, 12 - LTEXT "Current time zone: %s", IDC_TIMEZONE, 4, 136, 241, 8 + LTEXT "", IDC_TIMEZONE, 4, 136, 241, 8 END @@ -36,4 +36,7 @@ STRINGTABLE BEGIN IDS_CPLNAME "Date/Time" IDS_CPLDESCRIPTION "Changes date, time and time zone information." + IDS_TIMEZONETEXT "Current time zone: %s" + IDS_TIMEZONEINVALID "Invalid" + IDS_TIMEZONEUNKNOWN "Unknown" END diff --git a/reactos/lib/cpl/timedate/Es.rc b/reactos/lib/cpl/timedate/Es.rc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/reactos/lib/cpl/timedate/Fr.rc b/reactos/lib/cpl/timedate/Fr.rc new file mode 100644 index 00000000000..4daa1df32af --- /dev/null +++ b/reactos/lib/cpl/timedate/Fr.rc @@ -0,0 +1,42 @@ +LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT + +IDD_DATETIMEPAGE DIALOGEX 0, 0, 252, 146 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Date && Heure" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "&Date", -1, 4, 2, 122, 125 + CONTROL "", IDC_DATEPICKER, "SysDateTimePick32", + DTS_SHORTDATEFORMAT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, + 11, 17, 108, 12 + CONTROL "", IDC_MONTHCALENDAR, "SysMonthCal32", + WS_CHILD | WS_VISIBLE | WS_TABSTOP, + 11, 37, 108, 80 + GROUPBOX "&Heure", -1, 132, 2, 113, 125 + CONTROL "", IDC_TIMEPICKER, "SysDateTimePick32", + DTS_TIMEFORMAT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, + 144, 17, 90, 12 + LTEXT "", IDC_TIMEZONE, 4, 136, 241, 8 +END + + +IDD_TIMEZONEPAGE DIALOGEX 0, 0, 252, 146 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Fuseau horaire" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + COMBOBOX IDC_TIMEZONELIST, 5, 4, 241, 136, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP + AUTOCHECKBOX "Ajuster automatiquement l'heure lors du &passage à l'heure d'été" + IDC_AUTODAYLIGHT, 5, 136, 241, 10, WS_VISIBLE | WS_GROUP | WS_TABSTOP +END + + +STRINGTABLE +BEGIN + IDS_CPLNAME "Date/Heure" + IDS_CPLDESCRIPTION "Change la date, l'heure et le fuseau horaire." + IDS_TIMEZONETEXT "Fuseau horaire actuel: %s" + IDS_TIMEZONEINVALID "Invalide" + IDS_TIMEZONEUNKNOWN "Inconnu" +END diff --git a/reactos/lib/cpl/timedate/resource.h b/reactos/lib/cpl/timedate/resource.h index 6a399911816..bca49b99325 100644 --- a/reactos/lib/cpl/timedate/resource.h +++ b/reactos/lib/cpl/timedate/resource.h @@ -15,7 +15,10 @@ #define IDC_AUTODAYLIGHT 113 #define IDS_CPLNAME 1001 -#define IDS_CPLDESCRIPTION 2001 +#define IDS_CPLDESCRIPTION 1002 +#define IDS_TIMEZONETEXT 1003 +#define IDS_TIMEZONEINVALID 1004 +#define IDS_TIMEZONEUNKNOWN 1005 #endif /* __CPL_RESOURCE_H */ diff --git a/reactos/lib/cpl/timedate/timedate.c b/reactos/lib/cpl/timedate/timedate.c index a7c4d7880f8..5822a039af4 100644 --- a/reactos/lib/cpl/timedate/timedate.c +++ b/reactos/lib/cpl/timedate/timedate.c @@ -102,14 +102,35 @@ SetTimeZoneName(HWND hwnd) { TIME_ZONE_INFORMATION TimeZoneInfo; WCHAR TimeZoneString[128]; + WCHAR TimeZoneText[128]; + WCHAR TimeZoneName[128]; DWORD TimeZoneId; TimeZoneId = GetTimeZoneInformation(&TimeZoneInfo); - wsprintf(TimeZoneString, - L"Current time zone: %s\n", - (TimeZoneId == TIME_ZONE_ID_DAYLIGHT) ? TimeZoneInfo.DaylightName : TimeZoneInfo.StandardName); + LoadString(hApplet, IDS_TIMEZONETEXT, TimeZoneText, 128); + switch (TimeZoneId) + { + case TIME_ZONE_ID_STANDARD: + wcscpy(TimeZoneName, TimeZoneInfo.StandardName); + break; + + case TIME_ZONE_ID_DAYLIGHT: + wcscpy(TimeZoneName, TimeZoneInfo.DaylightName); + break; + + case TIME_ZONE_ID_UNKNOWN: + LoadString(hApplet, IDS_TIMEZONEUNKNOWN, TimeZoneName, 128); + break; + + case TIME_ZONE_ID_INVALID: + default: + LoadString(hApplet, IDS_TIMEZONEINVALID, TimeZoneName, 128); + break; + } + + wsprintf(TimeZoneString, TimeZoneText, TimeZoneName); SendDlgItemMessageW(hwnd, IDC_TIMEZONE, WM_SETTEXT, 0, (LPARAM)TimeZoneString); } diff --git a/reactos/lib/cpl/timedate/timedate.rc b/reactos/lib/cpl/timedate/timedate.rc index 1f0aa9c85ce..cc27842ec32 100644 --- a/reactos/lib/cpl/timedate/timedate.rc +++ b/reactos/lib/cpl/timedate/timedate.rc @@ -19,4 +19,5 @@ IDC_CPLICON ICON "resources/applet.ico" #include "En.rc" #include "De.rc" - +#include "Es.rc" +#include "Fr.rc" diff --git a/reactos/lib/msvcrt/README.txt b/reactos/lib/crt/README.txt similarity index 100% rename from reactos/lib/msvcrt/README.txt rename to reactos/lib/crt/README.txt diff --git a/reactos/lib/msvcrt/conio/cgets.c b/reactos/lib/crt/conio/cgets.c similarity index 85% rename from reactos/lib/msvcrt/conio/cgets.c rename to reactos/lib/crt/conio/cgets.c index cf06ddfc527..dfdb99bf1b0 100644 --- a/reactos/lib/msvcrt/conio/cgets.c +++ b/reactos/lib/crt/conio/cgets.c @@ -1,7 +1,14 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/conio/cgets.c + * PURPOSE: C Runtime + * PROGRAMMER: Eric Kohl (Imported from DJGPP) + */ + #include #include - /* * @implemented */ diff --git a/reactos/lib/crtdll/conio/cprintf.c b/reactos/lib/crt/conio/cprintf.c similarity index 58% rename from reactos/lib/crtdll/conio/cprintf.c rename to reactos/lib/crt/conio/cprintf.c index b668157a39d..b8e487edca3 100644 --- a/reactos/lib/crtdll/conio/cprintf.c +++ b/reactos/lib/crt/conio/cprintf.c @@ -1,3 +1,11 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/conio/cprintf.c + * PURPOSE: C Runtime + * PROGRAMMER: Eric Kohl (Imported from DJGPP) + */ + #include #include diff --git a/reactos/lib/msvcrt/conio/cputs.c b/reactos/lib/crt/conio/cputs.c similarity index 100% rename from reactos/lib/msvcrt/conio/cputs.c rename to reactos/lib/crt/conio/cputs.c diff --git a/reactos/lib/crtdll/conio/cscanf.c b/reactos/lib/crt/conio/cscanf.c similarity index 59% rename from reactos/lib/crtdll/conio/cscanf.c rename to reactos/lib/crt/conio/cscanf.c index 4839931aef7..f508c18d212 100644 --- a/reactos/lib/crtdll/conio/cscanf.c +++ b/reactos/lib/crt/conio/cscanf.c @@ -1,3 +1,11 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/conio/cscanf.c + * PURPOSE: C Runtime + * PROGRAMMER: Eric Kohl (Imported from DJGPP) + */ + #include #include #include diff --git a/reactos/lib/msvcrt/conio/getch.c b/reactos/lib/crt/conio/getch.c similarity index 100% rename from reactos/lib/msvcrt/conio/getch.c rename to reactos/lib/crt/conio/getch.c diff --git a/reactos/lib/msvcrt/conio/getche.c b/reactos/lib/crt/conio/getche.c similarity index 100% rename from reactos/lib/msvcrt/conio/getche.c rename to reactos/lib/crt/conio/getche.c diff --git a/reactos/lib/msvcrt/conio/kbhit.c b/reactos/lib/crt/conio/kbhit.c similarity index 100% rename from reactos/lib/msvcrt/conio/kbhit.c rename to reactos/lib/crt/conio/kbhit.c diff --git a/reactos/lib/msvcrt/conio/putch.c b/reactos/lib/crt/conio/putch.c similarity index 100% rename from reactos/lib/msvcrt/conio/putch.c rename to reactos/lib/crt/conio/putch.c diff --git a/reactos/lib/msvcrt/conio/ungetch.c b/reactos/lib/crt/conio/ungetch.c similarity index 100% rename from reactos/lib/msvcrt/conio/ungetch.c rename to reactos/lib/crt/conio/ungetch.c diff --git a/reactos/lib/msvcrt/crt.xml b/reactos/lib/crt/crt.xml similarity index 62% rename from reactos/lib/msvcrt/crt.xml rename to reactos/lib/crt/crt.xml index efe19db0c76..672e3e823fb 100644 --- a/reactos/lib/msvcrt/crt.xml +++ b/reactos/lib/crt/crt.xml @@ -8,15 +8,26 @@ + + cgets.c + cprintf.c + cputs.c + cscanf.c + getch.c + getche.c + kbhit.c + putch.c + ungetch.c + ctype.c - isalnum.c isascii.c iscntrl.c isgraph.c isprint.c ispunct.c isupper.c + isctype.c chdir.c @@ -27,6 +38,17 @@ getdrive.c mkdir.c rmdir.c + wchdir.c + wgetcwd.c + wgetdcwd.c + wmkdir.c + wrmdir.c + + + abnorter.c + exhand2.c + matherr.c + unwind.c chgsign.c @@ -48,47 +70,64 @@ chsize.c close.c commit.c + create.c + dup.c dup2.c + eof.c filelen.c + fileleni.c + find.c + fmode.c isatty.c locking.c + lseek.c + lseeki64.c mktemp.c + open.c + pipe.c + read.c setmode.c sopen.c + stubs.c tell.c + telli64.c umask.c + unlink.c utime.c + waccess.c + wchmod.c + wcreate.c + wfind.c + wmktemp.c + wopen.c write.c + wunlink.c + wutime.c locale.c acos.c + adjust.c asin.c atan2.c - atan.c cabs.c - cos.c cosh.c exp.c - fabs.c fmod.c frexp.c + huge_val.c hypot.c j0_y0.c j1_y1.c jn_yn.c ldexp.c log10.c - log.c modf.c pow.c - sin.c sinh.c - sqrt.c stubs.c - tan.c tanh.c @@ -151,13 +190,24 @@ amsg.c assert.c + crtmain.c environ.c + getargs.c initterm.c + lock.c + purecall.c + stubs.c + tls.c + _cwait.c + _system.c dll.c + process.c procid.c + thread.c threadid.c + threadx.c lfind.c @@ -170,6 +220,7 @@ signal.c + xcptinfo.c allocfil.c @@ -177,16 +228,42 @@ fclose.c fdopen.c feof.c + ferror.c + fflush.c fgetc.c + fgetchar.c fgetpos.c + fgets.c + fgetws.c + filbuf.c + fileno.c flsbuf.c + fopen.c fprintf.c fputc.c + fputchar.c + fputs.c + fread.c + freopen.c + fscanf.c fseek.c fsetpos.c + fsopen.c + ftell.c fwalk.c + fwrite.c + getc.c + getchar.c + gets.c getw.c + perror.c + popen.c + printf.c + putc.c + putchar.c + puts.c putw.c + remove.c rename.c rewind.c rmtmp.c @@ -207,62 +284,103 @@ vscanf.c vsprintf.c vsscanf.c + wfdopen.c + wrename.c + wtempnam.c + wtmpnam.c _exit.c abort.c - abs.c atexit.c atof.c - atoi.c - atol.c - bsearch.c div.c ecvt.c ecvtbuf.c + errno.c fcvt.c fcvtbuf.c + fullpath.c gcvt.c - itoa.c - labs.c + getenv.c ldiv.c makepath.c + malloc.c + mbtowc.c obsol.c + putenv.c + rand.c rot.c senv.c - splitp.c strtod.c - strtol.c strtoul.c swab.c wcstod.c + wcstombs.c + wctomb.c + wfulpath.c + wputenv.c + wsenv.c + wsplitp.c + wmakpath.c lasttok.c strcoll.c strdup.c + strerror.c + strncoll.c + strpbrk.c strrev.c strset.c + strstr.c strtok.c + strupr.c strxfrm.c + fstat.c + fstati64.c futime.c + stat.c + wstat.c + systime.c clock.c ctime.c difftime.c + ftime.c strdate.c strftime.c strtime.c time.c + tz_vars.c + wctime.c + wstrdate.c + wstrtime.c + wcscoll.c + wcscspn.c wcsdup.c + wcsicmp.c + wcslwr.c + wcsnicmp.c + wcspbrk.c wcsrev.c wcsset.c + wcsspn.c + wcsstr.c wcstok.c + wcsupr.c wcsxfrm.c + wlasttok.c + + + cpp.c + cppexcept.c + heap.c + thread.c diff --git a/reactos/lib/msvcrt/ctype/ctype.c b/reactos/lib/crt/ctype/ctype.c similarity index 96% rename from reactos/lib/msvcrt/ctype/ctype.c rename to reactos/lib/crt/ctype/ctype.c index 5861d6d6494..3c88c06e704 100644 --- a/reactos/lib/msvcrt/ctype/ctype.c +++ b/reactos/lib/crt/ctype/ctype.c @@ -1,4 +1,11 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/ctype.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + #include unsigned short _ctype[] = { diff --git a/reactos/lib/msvcrt/ctype/isalnum.c b/reactos/lib/crt/ctype/isalnum.c similarity index 99% rename from reactos/lib/msvcrt/ctype/isalnum.c rename to reactos/lib/crt/ctype/isalnum.c index 6450ec50bf0..57130bc90c3 100644 --- a/reactos/lib/msvcrt/ctype/isalnum.c +++ b/reactos/lib/crt/ctype/isalnum.c @@ -9,6 +9,7 @@ */ #include + #undef iswalnum /* * @implemented diff --git a/reactos/lib/msvcrt/ctype/isalpha.c b/reactos/lib/crt/ctype/isalpha.c similarity index 100% rename from reactos/lib/msvcrt/ctype/isalpha.c rename to reactos/lib/crt/ctype/isalpha.c diff --git a/reactos/lib/msvcrt/ctype/isascii.c b/reactos/lib/crt/ctype/isascii.c similarity index 100% rename from reactos/lib/msvcrt/ctype/isascii.c rename to reactos/lib/crt/ctype/isascii.c diff --git a/reactos/lib/crt/ctype/iscntrl.c b/reactos/lib/crt/ctype/iscntrl.c new file mode 100644 index 00000000000..59d75f76eac --- /dev/null +++ b/reactos/lib/crt/ctype/iscntrl.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/iscntrl.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + + +#undef iswcntrl +/* + * @implemented + */ +int iswcntrl(wint_t c) +{ + return iswctype(c, _CONTROL); +} diff --git a/reactos/lib/msvcrt/ctype/iscsym.c b/reactos/lib/crt/ctype/iscsym.c similarity index 100% rename from reactos/lib/msvcrt/ctype/iscsym.c rename to reactos/lib/crt/ctype/iscsym.c diff --git a/reactos/lib/msvcrt/ctype/isctype.c b/reactos/lib/crt/ctype/isctype.c similarity index 73% rename from reactos/lib/msvcrt/ctype/isctype.c rename to reactos/lib/crt/ctype/isctype.c index 15fb758a2af..9b0c668e653 100644 --- a/reactos/lib/msvcrt/ctype/isctype.c +++ b/reactos/lib/crt/ctype/isctype.c @@ -1,4 +1,11 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isctype.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + #include @@ -32,14 +39,6 @@ int _isctype(unsigned int c, int ctypeFlags) return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); } -/* - * @implemented - */ -int iswctype(wint_t wc, wctype_t wctypeFlags) -{ - return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); -} - /* * obsolete * diff --git a/reactos/lib/crt/ctype/isdigit.c b/reactos/lib/crt/ctype/isdigit.c new file mode 100644 index 00000000000..36783d43587 --- /dev/null +++ b/reactos/lib/crt/ctype/isdigit.c @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isdigit.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + + +#undef isdigit +/* + * @implemented + */ +int isdigit(int c) +{ + return _isctype(c, _DIGIT); +} + +#undef iswdigit +/* + * @implemented + */ +int iswdigit(wint_t c) +{ + return iswctype(c, _DIGIT); +} diff --git a/reactos/lib/crt/ctype/isgraph.c b/reactos/lib/crt/ctype/isgraph.c new file mode 100644 index 00000000000..a62ef348888 --- /dev/null +++ b/reactos/lib/crt/ctype/isgraph.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isgraph.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +#undef iswgraph +/* + * @implemented + */ +int iswgraph(wint_t c) +{ + return iswctype(c,_PUNCT | _ALPHA | _DIGIT); +} diff --git a/reactos/lib/crt/ctype/islower.c b/reactos/lib/crt/ctype/islower.c new file mode 100644 index 00000000000..c91e5dde091 --- /dev/null +++ b/reactos/lib/crt/ctype/islower.c @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/islower.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + + +#undef islower +/* + * @implemented + */ +int islower(int c) +{ + return _isctype(c, _LOWER); +} + +/* + * @implemented + */ +int iswlower(wint_t c) +{ + return iswctype(c, _LOWER); +} diff --git a/reactos/lib/crt/ctype/isprint.c b/reactos/lib/crt/ctype/isprint.c new file mode 100644 index 00000000000..8eca3b574ac --- /dev/null +++ b/reactos/lib/crt/ctype/isprint.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isprint.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +/* + * @implemented + */ +int iswprint(wint_t c) +{ + return iswctype((unsigned short)c,_BLANK | _PUNCT | _ALPHA | _DIGIT); +} diff --git a/reactos/lib/crt/ctype/ispunct.c b/reactos/lib/crt/ctype/ispunct.c new file mode 100644 index 00000000000..ae55fb0bc88 --- /dev/null +++ b/reactos/lib/crt/ctype/ispunct.c @@ -0,0 +1,18 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/ispunct.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +#undef iswpunct +/* + * @implemented + */ +int iswpunct(wint_t c) +{ + return iswctype(c, _PUNCT); +} diff --git a/reactos/lib/msvcrt/ctype/isspace.c b/reactos/lib/crt/ctype/isspace.c similarity index 100% rename from reactos/lib/msvcrt/ctype/isspace.c rename to reactos/lib/crt/ctype/isspace.c diff --git a/reactos/lib/crt/ctype/isupper.c b/reactos/lib/crt/ctype/isupper.c new file mode 100644 index 00000000000..187956c2414 --- /dev/null +++ b/reactos/lib/crt/ctype/isupper.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isupper.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +/* + * @implemented + */ +int iswupper(wint_t c) +{ + return iswctype(c, _UPPER); +} diff --git a/reactos/lib/crt/ctype/isxdigit.c b/reactos/lib/crt/ctype/isxdigit.c new file mode 100644 index 00000000000..3490c07924f --- /dev/null +++ b/reactos/lib/crt/ctype/isxdigit.c @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/isxdigit.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +#undef isxdigit +/* + * @implemented + */ +int isxdigit(int c) +{ + return _isctype(c, _HEX); +} + +#undef iswxdigit +/* + * @implemented + */ +int iswxdigit(wint_t c) +{ + return iswctype(c, _HEX); +} + diff --git a/reactos/lib/crt/ctype/toascii.c b/reactos/lib/crt/ctype/toascii.c new file mode 100644 index 00000000000..8ad09e23c83 --- /dev/null +++ b/reactos/lib/crt/ctype/toascii.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/toascii.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + +#include + +/* + * @implemented + */ +int __toascii(int c) +{ + return((unsigned)(c) & 0x7F); +} diff --git a/reactos/lib/msvcrt/ctype/tolower.c b/reactos/lib/crt/ctype/tolower.c similarity index 68% rename from reactos/lib/msvcrt/ctype/tolower.c rename to reactos/lib/crt/ctype/tolower.c index 34ceb9785fc..48c8788020f 100644 --- a/reactos/lib/msvcrt/ctype/tolower.c +++ b/reactos/lib/crt/ctype/tolower.c @@ -1,4 +1,11 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/tolower.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ + #include #undef tolower diff --git a/reactos/lib/msvcrt/ctype/toupper.c b/reactos/lib/crt/ctype/toupper.c similarity index 66% rename from reactos/lib/msvcrt/ctype/toupper.c rename to reactos/lib/crt/ctype/toupper.c index 52c10c6f2a1..7e21e65e226 100644 --- a/reactos/lib/msvcrt/ctype/toupper.c +++ b/reactos/lib/crt/ctype/toupper.c @@ -1,6 +1,12 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: msvcrt/ctype/toupper.c + * PURPOSE: C Runtime + * PROGRAMMER: Copyright (C) 1995 DJ Delorie + */ +#include #undef toupper /* diff --git a/reactos/lib/msvcrt/direct/chdir.c b/reactos/lib/crt/direct/chdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/chdir.c rename to reactos/lib/crt/direct/chdir.c diff --git a/reactos/lib/msvcrt/direct/chdrive.c b/reactos/lib/crt/direct/chdrive.c similarity index 100% rename from reactos/lib/msvcrt/direct/chdrive.c rename to reactos/lib/crt/direct/chdrive.c diff --git a/reactos/lib/msvcrt/direct/getcwd.c b/reactos/lib/crt/direct/getcwd.c similarity index 100% rename from reactos/lib/msvcrt/direct/getcwd.c rename to reactos/lib/crt/direct/getcwd.c diff --git a/reactos/lib/msvcrt/direct/getdcwd.c b/reactos/lib/crt/direct/getdcwd.c similarity index 100% rename from reactos/lib/msvcrt/direct/getdcwd.c rename to reactos/lib/crt/direct/getdcwd.c diff --git a/reactos/lib/crtdll/direct/getdfree.c b/reactos/lib/crt/direct/getdfree.c similarity index 100% rename from reactos/lib/crtdll/direct/getdfree.c rename to reactos/lib/crt/direct/getdfree.c diff --git a/reactos/lib/crtdll/direct/getdrive.c b/reactos/lib/crt/direct/getdrive.c similarity index 100% rename from reactos/lib/crtdll/direct/getdrive.c rename to reactos/lib/crt/direct/getdrive.c diff --git a/reactos/lib/msvcrt/direct/mkdir.c b/reactos/lib/crt/direct/mkdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/mkdir.c rename to reactos/lib/crt/direct/mkdir.c diff --git a/reactos/lib/msvcrt/direct/rmdir.c b/reactos/lib/crt/direct/rmdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/rmdir.c rename to reactos/lib/crt/direct/rmdir.c diff --git a/reactos/lib/msvcrt/direct/wchdir.c b/reactos/lib/crt/direct/wchdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/wchdir.c rename to reactos/lib/crt/direct/wchdir.c diff --git a/reactos/lib/msvcrt/direct/wgetcwd.c b/reactos/lib/crt/direct/wgetcwd.c similarity index 100% rename from reactos/lib/msvcrt/direct/wgetcwd.c rename to reactos/lib/crt/direct/wgetcwd.c diff --git a/reactos/lib/msvcrt/direct/wgetdcwd.c b/reactos/lib/crt/direct/wgetdcwd.c similarity index 100% rename from reactos/lib/msvcrt/direct/wgetdcwd.c rename to reactos/lib/crt/direct/wgetdcwd.c diff --git a/reactos/lib/msvcrt/direct/wmkdir.c b/reactos/lib/crt/direct/wmkdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/wmkdir.c rename to reactos/lib/crt/direct/wmkdir.c diff --git a/reactos/lib/msvcrt/direct/wrmdir.c b/reactos/lib/crt/direct/wrmdir.c similarity index 100% rename from reactos/lib/msvcrt/direct/wrmdir.c rename to reactos/lib/crt/direct/wrmdir.c diff --git a/reactos/lib/msvcrt/except/abnorter.c b/reactos/lib/crt/except/abnorter.c similarity index 100% rename from reactos/lib/msvcrt/except/abnorter.c rename to reactos/lib/crt/except/abnorter.c diff --git a/reactos/lib/msvcrt/except/exhand2.c b/reactos/lib/crt/except/exhand2.c similarity index 100% rename from reactos/lib/msvcrt/except/exhand2.c rename to reactos/lib/crt/except/exhand2.c diff --git a/reactos/lib/msvcrt/except/matherr.c b/reactos/lib/crt/except/matherr.c similarity index 100% rename from reactos/lib/msvcrt/except/matherr.c rename to reactos/lib/crt/except/matherr.c diff --git a/reactos/lib/msvcrt/except/seh.s b/reactos/lib/crt/except/seh.s similarity index 100% rename from reactos/lib/msvcrt/except/seh.s rename to reactos/lib/crt/except/seh.s diff --git a/reactos/lib/msvcrt/except/unwind.c b/reactos/lib/crt/except/unwind.c similarity index 100% rename from reactos/lib/msvcrt/except/unwind.c rename to reactos/lib/crt/except/unwind.c diff --git a/reactos/lib/msvcrt/except/xcptfil.c b/reactos/lib/crt/except/xcptfil.c similarity index 100% rename from reactos/lib/msvcrt/except/xcptfil.c rename to reactos/lib/crt/except/xcptfil.c diff --git a/reactos/lib/msvcrt/float/chgsign.c b/reactos/lib/crt/float/chgsign.c similarity index 100% rename from reactos/lib/msvcrt/float/chgsign.c rename to reactos/lib/crt/float/chgsign.c diff --git a/reactos/lib/msvcrt/float/clearfp.c b/reactos/lib/crt/float/clearfp.c similarity index 100% rename from reactos/lib/msvcrt/float/clearfp.c rename to reactos/lib/crt/float/clearfp.c diff --git a/reactos/lib/crtdll/float/cntrlfp.c b/reactos/lib/crt/float/cntrlfp.c similarity index 100% rename from reactos/lib/crtdll/float/cntrlfp.c rename to reactos/lib/crt/float/cntrlfp.c diff --git a/reactos/lib/msvcrt/float/copysign.c b/reactos/lib/crt/float/copysign.c similarity index 100% rename from reactos/lib/msvcrt/float/copysign.c rename to reactos/lib/crt/float/copysign.c diff --git a/reactos/lib/msvcrt/float/fpclass.c b/reactos/lib/crt/float/fpclass.c similarity index 100% rename from reactos/lib/msvcrt/float/fpclass.c rename to reactos/lib/crt/float/fpclass.c diff --git a/reactos/lib/msvcrt/float/fpecode.c b/reactos/lib/crt/float/fpecode.c similarity index 100% rename from reactos/lib/msvcrt/float/fpecode.c rename to reactos/lib/crt/float/fpecode.c diff --git a/reactos/lib/msvcrt/float/fpreset.c b/reactos/lib/crt/float/fpreset.c similarity index 100% rename from reactos/lib/msvcrt/float/fpreset.c rename to reactos/lib/crt/float/fpreset.c diff --git a/reactos/lib/msvcrt/float/isnan.c b/reactos/lib/crt/float/isnan.c similarity index 100% rename from reactos/lib/msvcrt/float/isnan.c rename to reactos/lib/crt/float/isnan.c diff --git a/reactos/lib/crtdll/float/logb.c b/reactos/lib/crt/float/logb.c similarity index 100% rename from reactos/lib/crtdll/float/logb.c rename to reactos/lib/crt/float/logb.c diff --git a/reactos/lib/msvcrt/float/nafter.c b/reactos/lib/crt/float/nafter.c similarity index 100% rename from reactos/lib/msvcrt/float/nafter.c rename to reactos/lib/crt/float/nafter.c diff --git a/reactos/lib/msvcrt/float/scalb.c b/reactos/lib/crt/float/scalb.c similarity index 100% rename from reactos/lib/msvcrt/float/scalb.c rename to reactos/lib/crt/float/scalb.c diff --git a/reactos/lib/crtdll/float/statfp.c b/reactos/lib/crt/float/statfp.c similarity index 100% rename from reactos/lib/crtdll/float/statfp.c rename to reactos/lib/crt/float/statfp.c diff --git a/reactos/lib/msvcrt/io/access.c b/reactos/lib/crt/io/access.c similarity index 100% rename from reactos/lib/msvcrt/io/access.c rename to reactos/lib/crt/io/access.c diff --git a/reactos/lib/msvcrt/io/chmod.c b/reactos/lib/crt/io/chmod.c similarity index 100% rename from reactos/lib/msvcrt/io/chmod.c rename to reactos/lib/crt/io/chmod.c diff --git a/reactos/lib/crtdll/io/chsize.c b/reactos/lib/crt/io/chsize.c similarity index 100% rename from reactos/lib/crtdll/io/chsize.c rename to reactos/lib/crt/io/chsize.c diff --git a/reactos/lib/crtdll/io/close.c b/reactos/lib/crt/io/close.c similarity index 100% rename from reactos/lib/crtdll/io/close.c rename to reactos/lib/crt/io/close.c diff --git a/reactos/lib/msvcrt/io/commit.c b/reactos/lib/crt/io/commit.c similarity index 100% rename from reactos/lib/msvcrt/io/commit.c rename to reactos/lib/crt/io/commit.c diff --git a/reactos/lib/msvcrt/io/create.c b/reactos/lib/crt/io/create.c similarity index 100% rename from reactos/lib/msvcrt/io/create.c rename to reactos/lib/crt/io/create.c diff --git a/reactos/lib/msvcrt/io/dup.c b/reactos/lib/crt/io/dup.c similarity index 100% rename from reactos/lib/msvcrt/io/dup.c rename to reactos/lib/crt/io/dup.c diff --git a/reactos/lib/msvcrt/io/dup2.c b/reactos/lib/crt/io/dup2.c similarity index 100% rename from reactos/lib/msvcrt/io/dup2.c rename to reactos/lib/crt/io/dup2.c diff --git a/reactos/lib/msvcrt/io/eof.c b/reactos/lib/crt/io/eof.c similarity index 100% rename from reactos/lib/msvcrt/io/eof.c rename to reactos/lib/crt/io/eof.c diff --git a/reactos/lib/msvcrt/io/filelen.c b/reactos/lib/crt/io/filelen.c similarity index 100% rename from reactos/lib/msvcrt/io/filelen.c rename to reactos/lib/crt/io/filelen.c diff --git a/reactos/lib/msvcrt/io/fileleni.c b/reactos/lib/crt/io/fileleni.c similarity index 100% rename from reactos/lib/msvcrt/io/fileleni.c rename to reactos/lib/crt/io/fileleni.c diff --git a/reactos/lib/msvcrt/io/find.c b/reactos/lib/crt/io/find.c similarity index 100% rename from reactos/lib/msvcrt/io/find.c rename to reactos/lib/crt/io/find.c diff --git a/reactos/lib/msvcrt/io/fmode.c b/reactos/lib/crt/io/fmode.c similarity index 60% rename from reactos/lib/msvcrt/io/fmode.c rename to reactos/lib/crt/io/fmode.c index 811f361b184..2306d60a40f 100644 --- a/reactos/lib/msvcrt/io/fmode.c +++ b/reactos/lib/crt/io/fmode.c @@ -2,13 +2,13 @@ #include #include -#undef _fmode -unsigned int _fmode = O_TEXT; + +int __fmode = O_TEXT; /* * @implemented */ -unsigned int *__p__fmode(void) +int *__p__fmode(void) { - return &_fmode; + return &__fmode; } diff --git a/reactos/lib/crtdll/io/isatty.c b/reactos/lib/crt/io/isatty.c similarity index 100% rename from reactos/lib/crtdll/io/isatty.c rename to reactos/lib/crt/io/isatty.c diff --git a/reactos/lib/msvcrt/io/locking.c b/reactos/lib/crt/io/locking.c similarity index 100% rename from reactos/lib/msvcrt/io/locking.c rename to reactos/lib/crt/io/locking.c diff --git a/reactos/lib/msvcrt/io/lseek.c b/reactos/lib/crt/io/lseek.c similarity index 100% rename from reactos/lib/msvcrt/io/lseek.c rename to reactos/lib/crt/io/lseek.c diff --git a/reactos/lib/msvcrt/io/lseeki64.c b/reactos/lib/crt/io/lseeki64.c similarity index 100% rename from reactos/lib/msvcrt/io/lseeki64.c rename to reactos/lib/crt/io/lseeki64.c diff --git a/reactos/lib/msvcrt/io/mktemp.c b/reactos/lib/crt/io/mktemp.c similarity index 100% rename from reactos/lib/msvcrt/io/mktemp.c rename to reactos/lib/crt/io/mktemp.c diff --git a/reactos/lib/msvcrt/io/open.c b/reactos/lib/crt/io/open.c similarity index 99% rename from reactos/lib/msvcrt/io/open.c rename to reactos/lib/crt/io/open.c index 96f784e0bfb..1921fa4ef06 100644 --- a/reactos/lib/msvcrt/io/open.c +++ b/reactos/lib/crt/io/open.c @@ -21,10 +21,10 @@ #include #include #include -#include #include #include #include +#include #define NDEBUG #include @@ -192,7 +192,7 @@ int _open(const char* _path, int _oflag,...) } DPRINT("OK\n"); if (!(_oflag & (_O_TEXT|_O_BINARY))) { - _oflag |= _fmode; + _oflag |= __fmode; } return __fileno_alloc(hFile,_oflag); } diff --git a/reactos/lib/msvcrt/io/pipe.c b/reactos/lib/crt/io/pipe.c similarity index 100% rename from reactos/lib/msvcrt/io/pipe.c rename to reactos/lib/crt/io/pipe.c diff --git a/reactos/lib/msvcrt/io/read.c b/reactos/lib/crt/io/read.c similarity index 99% rename from reactos/lib/msvcrt/io/read.c rename to reactos/lib/crt/io/read.c index c996ae88f07..6e9229df1e8 100644 --- a/reactos/lib/msvcrt/io/read.c +++ b/reactos/lib/crt/io/read.c @@ -12,7 +12,7 @@ * behavior for line-buffered streams (KJK::Hyperion) */ -#include "precomp.h" +#include #include #include diff --git a/reactos/lib/msvcrt/io/setmode.c b/reactos/lib/crt/io/setmode.c similarity index 100% rename from reactos/lib/msvcrt/io/setmode.c rename to reactos/lib/crt/io/setmode.c diff --git a/reactos/lib/msvcrt/io/sopen.c b/reactos/lib/crt/io/sopen.c similarity index 100% rename from reactos/lib/msvcrt/io/sopen.c rename to reactos/lib/crt/io/sopen.c diff --git a/reactos/lib/msvcrt/io/stubs.c b/reactos/lib/crt/io/stubs.c similarity index 100% rename from reactos/lib/msvcrt/io/stubs.c rename to reactos/lib/crt/io/stubs.c diff --git a/reactos/lib/msvcrt/io/tell.c b/reactos/lib/crt/io/tell.c similarity index 100% rename from reactos/lib/msvcrt/io/tell.c rename to reactos/lib/crt/io/tell.c diff --git a/reactos/lib/msvcrt/io/telli64.c b/reactos/lib/crt/io/telli64.c similarity index 100% rename from reactos/lib/msvcrt/io/telli64.c rename to reactos/lib/crt/io/telli64.c diff --git a/reactos/lib/msvcrt/io/umask.c b/reactos/lib/crt/io/umask.c similarity index 100% rename from reactos/lib/msvcrt/io/umask.c rename to reactos/lib/crt/io/umask.c diff --git a/reactos/lib/msvcrt/io/unlink.c b/reactos/lib/crt/io/unlink.c similarity index 100% rename from reactos/lib/msvcrt/io/unlink.c rename to reactos/lib/crt/io/unlink.c diff --git a/reactos/lib/msvcrt/io/utime.c b/reactos/lib/crt/io/utime.c similarity index 100% rename from reactos/lib/msvcrt/io/utime.c rename to reactos/lib/crt/io/utime.c diff --git a/reactos/lib/msvcrt/io/waccess.c b/reactos/lib/crt/io/waccess.c similarity index 100% rename from reactos/lib/msvcrt/io/waccess.c rename to reactos/lib/crt/io/waccess.c diff --git a/reactos/lib/msvcrt/io/wchmod.c b/reactos/lib/crt/io/wchmod.c similarity index 100% rename from reactos/lib/msvcrt/io/wchmod.c rename to reactos/lib/crt/io/wchmod.c diff --git a/reactos/lib/msvcrt/io/wcreate.c b/reactos/lib/crt/io/wcreate.c similarity index 100% rename from reactos/lib/msvcrt/io/wcreate.c rename to reactos/lib/crt/io/wcreate.c diff --git a/reactos/lib/msvcrt/io/wfind.c b/reactos/lib/crt/io/wfind.c similarity index 100% rename from reactos/lib/msvcrt/io/wfind.c rename to reactos/lib/crt/io/wfind.c diff --git a/reactos/lib/msvcrt/io/wmktemp.c b/reactos/lib/crt/io/wmktemp.c similarity index 100% rename from reactos/lib/msvcrt/io/wmktemp.c rename to reactos/lib/crt/io/wmktemp.c diff --git a/reactos/lib/msvcrt/io/wopen.c b/reactos/lib/crt/io/wopen.c similarity index 100% rename from reactos/lib/msvcrt/io/wopen.c rename to reactos/lib/crt/io/wopen.c diff --git a/reactos/lib/msvcrt/io/write.c b/reactos/lib/crt/io/write.c similarity index 100% rename from reactos/lib/msvcrt/io/write.c rename to reactos/lib/crt/io/write.c diff --git a/reactos/lib/msvcrt/io/wunlink.c b/reactos/lib/crt/io/wunlink.c similarity index 100% rename from reactos/lib/msvcrt/io/wunlink.c rename to reactos/lib/crt/io/wunlink.c diff --git a/reactos/lib/msvcrt/io/wutime.c b/reactos/lib/crt/io/wutime.c similarity index 100% rename from reactos/lib/msvcrt/io/wutime.c rename to reactos/lib/crt/io/wutime.c diff --git a/reactos/lib/msvcrt/locale/locale.c b/reactos/lib/crt/locale/locale.c similarity index 63% rename from reactos/lib/msvcrt/locale/locale.c rename to reactos/lib/crt/locale/locale.c index 642f22011fd..3486b70eb98 100644 --- a/reactos/lib/msvcrt/locale/locale.c +++ b/reactos/lib/crt/locale/locale.c @@ -1,3 +1,9 @@ +/* + * Some stuff takem from wine msvcrt\locale.c + * + * Copyright 2000 Jon Griffiths + */ + #include "precomp.h" #include #include @@ -201,3 +207,74 @@ void __lc_codepage(void) DPRINT1("__lc_codepage - stub\n"); return; } + + +/********************************************************************* + * _Gettnames (MSVCRT.@) + */ +void *_Gettnames(void) +{ + DPRINT1("(void), stub!\n"); + return NULL; +} + +/********************************************************************* + * __lconv_init (MSVCRT.@) + */ +void __lconv_init(void) +{ + DPRINT1(" stub\n"); +} + + +/********************************************************************* + * _Strftime (MSVCRT.@) + */ +const char* _Strftime(char *out, unsigned int len, const char *fmt, + const void *tm, void *foo) +{ + /* FIXME: */ + DPRINT1("(%p %d %s %p %p) stub\n", out, len, fmt, tm, foo); + return ""; +} + + +/********************************************************************* + * _Getdays (MSVCRT.@) + */ +const char* _Getdays(void) +{ + static const char *MSVCRT_days = ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:" + "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday"; + /* FIXME: Use locale */ + DPRINT1("(void) semi-stub\n"); + return MSVCRT_days; +} + +/********************************************************************* + * _Getmonths (MSVCRT.@) + */ +const char* _Getmonths(void) +{ + static const char *MSVCRT_months = ":Jan:January:Feb:February:Mar:March:Apr:" + "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:" + "October:Nov:November:Dec:December"; + /* FIXME: Use locale */ + DPRINT1("(void) semi-stub\n"); + return MSVCRT_months; +} + +/********************************************************************* + * __crtLCMapStringA (MSVCRT.@) + */ +int __crtLCMapStringA( + LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst, + int dstlen, unsigned int codepage, int xflag +) { + DPRINT1("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n", + lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag); + /* FIXME: A bit incorrect. But msvcrt itself just converts its + * arguments to wide strings and then calls LCMapStringW + */ + return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen); +} diff --git a/reactos/lib/crt/makefile b/reactos/lib/crt/makefile new file mode 100644 index 00000000000..053fc66731a --- /dev/null +++ b/reactos/lib/crt/makefile @@ -0,0 +1,475 @@ +# $Id: Makefile 12852 2005-01-06 13:58:04Z mf $ + +PATH_TO_TOP = ../.. + +TARGET_DEFONLY = yes + +TARGET_TYPE = library + +TARGET_NAME = crt + +TARGET_PCH = precomp.h + +TARGET_CFLAGS = -D_MSVCRT_LIB_ -Wall -Werror + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += \ + -D_DISABLE_TIDENTS \ + -D__USE_W32API \ + -D__REACTOS__ \ + -D_WIN32_IE=0x600 \ + -D_WIN32_WINNT=0x501 \ + -DUSE_MSVCRT_PREFIX \ + -D_MT + +CONIO_OBJECTS = \ + conio/cgets.o \ + conio/cprintf.o \ + conio/cputs.o \ + conio/cscanf.o \ + conio/getch.o \ + conio/getche.o \ + conio/kbhit.o \ + conio/putch.o \ + conio/ungetch.o + +CTYPE_OBJECTS = \ + ctype/ctype.o \ + ctype/isalnum.o \ + ctype/isalpha.o \ + ctype/isascii.o \ + ctype/iscntrl.o \ + ctype/isdigit.o \ + ctype/isgraph.o \ + ctype/islower.o \ + ctype/isprint.o \ + ctype/ispunct.o \ + ctype/isspace.o \ + ctype/isupper.o \ + ctype/isxdigit.o \ + ctype/toascii.o \ + ctype/tolower.o \ + ctype/toupper.o \ + ctype/iscsym.o \ + ctype/isctype.o + +DIRECT_OBJECTS = \ + direct/chdir.o \ + direct/chdrive.o \ + direct/getcwd.o \ + direct/getdcwd.o \ + direct/getdfree.o \ + direct/getdrive.o \ + direct/mkdir.o \ + direct/rmdir.o \ + direct/wchdir.o \ + direct/wgetcwd.o \ + direct/wgetdcwd.o \ + direct/wmkdir.o \ + direct/wrmdir.o + +EXCEPT_OBJECTS = \ + except/seh.o \ + except/abnorter.o \ + except/exhand2.o \ + except/matherr.o \ + except/unwind.o \ + except/xcptfil.o + +FLOAT_OBJECTS = \ + float/chgsign.o \ + float/clearfp.o \ + float/cntrlfp.o \ + float/copysign.o \ + float/fpclass.o \ + float/fpecode.o \ + float/fpreset.o \ + float/isnan.o \ + float/logb.o \ + float/nafter.o \ + float/scalb.o \ + float/statfp.o + +IO_OBJECTS = \ + io/access.o \ + io/chmod.o \ + io/chsize.o \ + io/close.o \ + io/commit.o \ + io/create.o \ + io/dup.o \ + io/dup2.o \ + io/eof.o \ + io/filelen.o \ + io/fileleni.o \ + io/find.o \ + io/fmode.o \ + io/isatty.o \ + io/locking.o \ + io/lseek.o \ + io/lseeki64.o \ + io/mktemp.o \ + io/open.o \ + io/pipe.o \ + io/read.o \ + io/setmode.o \ + io/sopen.o \ + io/stubs.o \ + io/tell.o \ + io/telli64.o \ + io/umask.o \ + io/unlink.o \ + io/utime.o \ + io/waccess.o \ + io/wchmod.o \ + io/wcreate.o \ + io/wfind.o \ + io/wmktemp.o \ + io/wopen.o \ + io/write.o \ + io/wunlink.o \ + io/wutime.o + +LOCALE_OBJECTS = \ + locale/locale.o + +MATH_OBJECTS = \ + math/acos.o \ + math/adjust.o \ + math/asin.o \ + math/atan.o \ + math/atan2.o \ + math/cabs.o \ + math/ceil.o \ + math/cos.o \ + math/cosh.o \ + math/exp.o \ + math/fabs.o \ + math/floor.o \ + math/fmod.o \ + math/frexp.o \ + math/huge_val.o \ + math/hypot.o \ + math/j0_y0.o \ + math/j1_y1.o \ + math/jn_yn.o \ + math/ldexp.o \ + math/log.o \ + math/log10.o \ + math/modf.o \ + math/pow.o \ + math/sin.o \ + math/sinh.o \ + math/sqrt.o \ + math/stubs.o \ + math/tan.o \ + math/tanh.o + +MBSTRING_OBJECTS = \ + mbstring/hanzen.o \ + mbstring/ischira.o \ + mbstring/iskana.o \ + mbstring/iskpun.o \ + mbstring/islead.o \ + mbstring/islwr.o \ + mbstring/ismbal.o \ + mbstring/ismbaln.o \ + mbstring/ismbc.o \ + mbstring/ismbgra.o \ + mbstring/ismbkaln.o \ + mbstring/ismblead.o \ + mbstring/ismbpri.o \ + mbstring/ismbpun.o \ + mbstring/ismbtrl.o \ + mbstring/isuppr.o \ + mbstring/jistojms.o \ + mbstring/jmstojis.o \ + mbstring/mbbtype.o \ + mbstring/mbccpy.o \ + mbstring/mbclen.o \ + mbstring/mbscat.o \ + mbstring/mbschr.o \ + mbstring/mbscmp.o \ + mbstring/mbscoll.o \ + mbstring/mbscpy.o \ + mbstring/mbscspn.o \ + mbstring/mbsdec.o \ + mbstring/mbsdup.o \ + mbstring/mbsicmp.o \ + mbstring/mbsicoll.o \ + mbstring/mbsinc.o \ + mbstring/mbslen.o \ + mbstring/mbslwr.o \ + mbstring/mbsncat.o \ + mbstring/mbsnccnt.o \ + mbstring/mbsncmp.o \ + mbstring/mbsncoll.o \ + mbstring/mbsncpy.o \ + mbstring/mbsnextc.o \ + mbstring/mbsnicmp.o \ + mbstring/mbsnicoll.o \ + mbstring/mbsninc.o \ + mbstring/mbsnset.o \ + mbstring/mbspbrk.o \ + mbstring/mbsrchr.o \ + mbstring/mbsrev.o \ + mbstring/mbsset.o \ + mbstring/mbsspn.o \ + mbstring/mbsspnp.o \ + mbstring/mbsstr.o \ + mbstring/mbstok.o \ + mbstring/mbstrlen.o \ + mbstring/mbsupr.o + +MISC_OBJECTS = \ + misc/amsg.o \ + misc/assert.o \ + misc/crtmain.o \ + misc/environ.o \ + misc/getargs.o \ + misc/initterm.o \ + misc/lock.o \ + misc/purecall.o \ + misc/stubs.o \ + misc/tls.o + +PROCESS_OBJECTS = \ + process/_cwait.o \ + process/_system.o \ + process/dll.o \ + process/process.o \ + process/procid.o \ + process/thread.o \ + process/threadid.o \ + process/threadx.o + +SEARCH_OBJECTS = \ + search/lfind.o \ + search/lsearch.o + +SETJMP_OBJECTS = \ + setjmp/i386/setjmp.o + +SIGNAL_OBJECTS = \ + signal/signal.o \ + signal/xcptinfo.o + +STDIO_OBJECTS = \ + stdio/allocfil.o \ + stdio/clearerr.o \ + stdio/fclose.o \ + stdio/fdopen.o \ + stdio/feof.o \ + stdio/ferror.o \ + stdio/fflush.o \ + stdio/fgetc.o \ + stdio/fgetchar.o \ + stdio/fgetpos.o \ + stdio/fgets.o \ + stdio/fgetws.o \ + stdio/filbuf.o \ + stdio/fileno.o \ + stdio/flsbuf.o \ + stdio/fopen.o \ + stdio/fprintf.o \ + stdio/fputc.o \ + stdio/fputchar.o \ + stdio/fputs.o \ + stdio/fread.o \ + stdio/freopen.o \ + stdio/fscanf.o \ + stdio/fseek.o \ + stdio/fsetpos.o \ + stdio/fsopen.o \ + stdio/ftell.o \ + stdio/fwalk.o \ + stdio/fwrite.o \ + stdio/getc.o \ + stdio/getchar.o \ + stdio/gets.o \ + stdio/getw.o \ + stdio/perror.o \ + stdio/popen.o \ + stdio/printf.o \ + stdio/putc.o \ + stdio/putchar.o \ + stdio/puts.o \ + stdio/putw.o \ + stdio/remove.o \ + stdio/rename.o \ + stdio/rewind.o \ + stdio/rmtmp.o \ + stdio/scanf.o \ + stdio/setbuf.o \ + stdio/setvbuf.o \ + stdio/sprintf.o \ + stdio/sscanf.o \ + stdio/stdhnd.o \ + stdio/tempnam.o \ + stdio/tmpfile.o \ + stdio/tmpnam.o \ + stdio/ungetc.o \ + stdio/vfprintf.o \ + stdio/vfscanf.o \ + stdio/vfwprint.o \ + stdio/vprintf.o \ + stdio/vscanf.o \ + stdio/vsprintf.o \ + stdio/vsscanf.o \ + stdio/wfdopen.o \ + stdio/wrename.o \ + stdio/wtempnam.o \ + stdio/wtmpnam.o + +STDLIB_OBJECTS = \ + stdlib/_exit.o \ + stdlib/abort.o \ + stdlib/abs.o \ + stdlib/atexit.o \ + stdlib/atof.o \ + stdlib/atoi.o \ + stdlib/atoi64.o \ + stdlib/atol.o \ + stdlib/bsearch.o \ + stdlib/div.o \ + stdlib/ecvt.o \ + stdlib/ecvtbuf.o \ + stdlib/errno.o \ + stdlib/fcvt.o \ + stdlib/fcvtbuf.o \ + stdlib/fullpath.o \ + stdlib/gcvt.o \ + stdlib/getenv.o \ + stdlib/itoa.o \ + stdlib/itow.o \ + stdlib/labs.o \ + stdlib/ldiv.o \ + stdlib/makepath.o \ + stdlib/malloc.o \ + stdlib/mbstowcs.o \ + stdlib/mbtowc.o \ + stdlib/obsol.o \ + stdlib/putenv.o \ + stdlib/qsort.o \ + stdlib/rand.o \ + stdlib/rot.o \ + stdlib/senv.o \ + stdlib/splitp.o \ + stdlib/strtod.o \ + stdlib/strtol.o \ + stdlib/strtoul.o \ + stdlib/swab.o \ + stdlib/wcstod.o \ + stdlib/wcstol.o \ + stdlib/wcstombs.o \ + stdlib/wcstoul.o \ + stdlib/wctomb.o \ + stdlib/wfulpath.o \ + stdlib/witoa.o \ + stdlib/witow.o \ + stdlib/wputenv.o \ + stdlib/wsenv.o \ + stdlib/wsplitp.o \ + stdlib/wmakpath.o \ + stdlib/wtoi.o \ + stdlib/wtoi64.o + +STRING_OBJECTS = \ + string/lasttok.o \ + string/memicmp.o \ + string/strcoll.o \ + string/strdup.o \ + string/strerror.o \ + string/stricmp.o \ + string/strlwr.o \ + string/strncoll.o \ + string/strnicmp.o \ + string/strpbrk.o \ + string/strrev.o\ + string/strset.o \ + string/strstr.o \ + string/strtok.o \ + string/strupr.o \ + string/strxfrm.o + +SYS_STAT_OBJECTS = \ + sys_stat/fstat.o \ + sys_stat/fstati64.o \ + sys_stat/futime.o \ + sys_stat/stat.o \ + sys_stat/wstat.o \ + sys_stat/systime.o + +TIME_OBJECTS = \ + time/clock.o \ + time/ctime.o \ + time/difftime.o \ + time/ftime.o \ + time/strdate.o \ + time/strftime.o \ + time/strtime.o \ + time/time.o \ + time/tz_vars.o \ + time/wctime.o \ + time/wstrdate.o \ + time/wstrtime.o + + + +WSTRING_OBJECTS = \ + wstring/wcscoll.o \ + wstring/wcscspn.o \ + wstring/wcsdup.o \ + wstring/wcsicmp.o \ + wstring/wcslwr.o \ + wstring/wcsnicmp.o \ + wstring/wcspbrk.o \ + wstring/wcsrev.o \ + wstring/wcsset.o \ + wstring/wcsspn.o \ + wstring/wcsstr.o \ + wstring/wcstok.o \ + wstring/wcsupr.o \ + wstring/wcsxfrm.o \ + wstring/wlasttok.o + +WINE_OBJECTS = \ + wine/cpp.o \ + wine/cppexcept.o \ + wine/heap.o \ + wine/thread.o + +TARGET_OBJECTS = \ + $(CONIO_OBJECTS) \ + $(CTYPE_OBJECTS) \ + $(DIRECT_OBJECTS) \ + $(EXCEPT_OBJECTS) \ + $(FLOAT_OBJECTS) \ + $(IO_OBJECTS) \ + $(LOCALE_OBJECTS) \ + $(MATH_OBJECTS) \ + $(MBSTRING_OBJECTS) \ + $(MISC_OBJECTS) \ + $(PROCESS_OBJECTS) \ + $(SEARCH_OBJECTS) \ + $(SETJMP_OBJECTS) \ + $(SIGNAL_OBJECTS) \ + $(STDIO_OBJECTS) \ + $(STDLIB_OBJECTS) \ + $(STRING_OBJECTS) \ + $(SYS_STAT_OBJECTS) \ + $(TIME_OBJECTS) \ + $(WSTRING_OBJECTS) \ + $(WINE_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +DEP_OBJECTS := $(TARGET_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) + +include $(PATH_TO_TOP)/tools/depend.mk + +# EOF diff --git a/reactos/lib/crtdll/math/acos.c b/reactos/lib/crt/math/acos.c similarity index 100% rename from reactos/lib/crtdll/math/acos.c rename to reactos/lib/crt/math/acos.c diff --git a/reactos/lib/msvcrt/math/adjust.c b/reactos/lib/crt/math/adjust.c similarity index 100% rename from reactos/lib/msvcrt/math/adjust.c rename to reactos/lib/crt/math/adjust.c diff --git a/reactos/lib/crtdll/math/asin.c b/reactos/lib/crt/math/asin.c similarity index 100% rename from reactos/lib/crtdll/math/asin.c rename to reactos/lib/crt/math/asin.c diff --git a/reactos/lib/crtdll/math/atan.c b/reactos/lib/crt/math/atan.c similarity index 100% rename from reactos/lib/crtdll/math/atan.c rename to reactos/lib/crt/math/atan.c diff --git a/reactos/lib/crtdll/math/atan2.c b/reactos/lib/crt/math/atan2.c similarity index 100% rename from reactos/lib/crtdll/math/atan2.c rename to reactos/lib/crt/math/atan2.c diff --git a/reactos/lib/crtdll/math/cabs.c b/reactos/lib/crt/math/cabs.c similarity index 100% rename from reactos/lib/crtdll/math/cabs.c rename to reactos/lib/crt/math/cabs.c diff --git a/reactos/lib/msvcrt/math/ceil.c b/reactos/lib/crt/math/ceil.c similarity index 100% rename from reactos/lib/msvcrt/math/ceil.c rename to reactos/lib/crt/math/ceil.c diff --git a/reactos/lib/crtdll/math/cos.c b/reactos/lib/crt/math/cos.c similarity index 100% rename from reactos/lib/crtdll/math/cos.c rename to reactos/lib/crt/math/cos.c diff --git a/reactos/lib/crtdll/math/cosh.c b/reactos/lib/crt/math/cosh.c similarity index 100% rename from reactos/lib/crtdll/math/cosh.c rename to reactos/lib/crt/math/cosh.c diff --git a/reactos/lib/crtdll/math/exp.c b/reactos/lib/crt/math/exp.c similarity index 100% rename from reactos/lib/crtdll/math/exp.c rename to reactos/lib/crt/math/exp.c diff --git a/reactos/lib/crtdll/math/fabs.c b/reactos/lib/crt/math/fabs.c similarity index 100% rename from reactos/lib/crtdll/math/fabs.c rename to reactos/lib/crt/math/fabs.c diff --git a/reactos/lib/msvcrt/math/floor.c b/reactos/lib/crt/math/floor.c similarity index 100% rename from reactos/lib/msvcrt/math/floor.c rename to reactos/lib/crt/math/floor.c diff --git a/reactos/lib/crtdll/math/fmod.c b/reactos/lib/crt/math/fmod.c similarity index 100% rename from reactos/lib/crtdll/math/fmod.c rename to reactos/lib/crt/math/fmod.c diff --git a/reactos/lib/msvcrt/math/frexp.c b/reactos/lib/crt/math/frexp.c similarity index 100% rename from reactos/lib/msvcrt/math/frexp.c rename to reactos/lib/crt/math/frexp.c diff --git a/reactos/lib/msvcrt/math/huge_val.c b/reactos/lib/crt/math/huge_val.c similarity index 100% rename from reactos/lib/msvcrt/math/huge_val.c rename to reactos/lib/crt/math/huge_val.c diff --git a/reactos/lib/crtdll/math/hypot.c b/reactos/lib/crt/math/hypot.c similarity index 100% rename from reactos/lib/crtdll/math/hypot.c rename to reactos/lib/crt/math/hypot.c diff --git a/reactos/lib/crtdll/math/j0_y0.c b/reactos/lib/crt/math/j0_y0.c similarity index 100% rename from reactos/lib/crtdll/math/j0_y0.c rename to reactos/lib/crt/math/j0_y0.c diff --git a/reactos/lib/crtdll/math/j1_y1.c b/reactos/lib/crt/math/j1_y1.c similarity index 100% rename from reactos/lib/crtdll/math/j1_y1.c rename to reactos/lib/crt/math/j1_y1.c diff --git a/reactos/lib/crtdll/math/jn_yn.c b/reactos/lib/crt/math/jn_yn.c similarity index 100% rename from reactos/lib/crtdll/math/jn_yn.c rename to reactos/lib/crt/math/jn_yn.c diff --git a/reactos/lib/crtdll/math/ldexp.c b/reactos/lib/crt/math/ldexp.c similarity index 100% rename from reactos/lib/crtdll/math/ldexp.c rename to reactos/lib/crt/math/ldexp.c diff --git a/reactos/lib/crtdll/math/log.c b/reactos/lib/crt/math/log.c similarity index 100% rename from reactos/lib/crtdll/math/log.c rename to reactos/lib/crt/math/log.c diff --git a/reactos/lib/crtdll/math/log10.c b/reactos/lib/crt/math/log10.c similarity index 100% rename from reactos/lib/crtdll/math/log10.c rename to reactos/lib/crt/math/log10.c diff --git a/reactos/lib/msvcrt/math/math.c b/reactos/lib/crt/math/math.c similarity index 100% rename from reactos/lib/msvcrt/math/math.c rename to reactos/lib/crt/math/math.c diff --git a/reactos/lib/msvcrt/math/modf.c b/reactos/lib/crt/math/modf.c similarity index 100% rename from reactos/lib/msvcrt/math/modf.c rename to reactos/lib/crt/math/modf.c diff --git a/reactos/lib/crtdll/math/pow.c b/reactos/lib/crt/math/pow.c similarity index 100% rename from reactos/lib/crtdll/math/pow.c rename to reactos/lib/crt/math/pow.c diff --git a/reactos/lib/crtdll/math/sin.c b/reactos/lib/crt/math/sin.c similarity index 100% rename from reactos/lib/crtdll/math/sin.c rename to reactos/lib/crt/math/sin.c diff --git a/reactos/lib/crtdll/math/sinh.c b/reactos/lib/crt/math/sinh.c similarity index 100% rename from reactos/lib/crtdll/math/sinh.c rename to reactos/lib/crt/math/sinh.c diff --git a/reactos/lib/crtdll/math/sqrt.c b/reactos/lib/crt/math/sqrt.c similarity index 100% rename from reactos/lib/crtdll/math/sqrt.c rename to reactos/lib/crt/math/sqrt.c diff --git a/reactos/lib/crtdll/math/stubs.c b/reactos/lib/crt/math/stubs.c similarity index 100% rename from reactos/lib/crtdll/math/stubs.c rename to reactos/lib/crt/math/stubs.c diff --git a/reactos/lib/crtdll/math/tan.c b/reactos/lib/crt/math/tan.c similarity index 100% rename from reactos/lib/crtdll/math/tan.c rename to reactos/lib/crt/math/tan.c diff --git a/reactos/lib/crtdll/math/tanh.c b/reactos/lib/crt/math/tanh.c similarity index 100% rename from reactos/lib/crtdll/math/tanh.c rename to reactos/lib/crt/math/tanh.c diff --git a/reactos/lib/msvcrt/mbstring/hanzen.c b/reactos/lib/crt/mbstring/hanzen.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/hanzen.c rename to reactos/lib/crt/mbstring/hanzen.c diff --git a/reactos/lib/msvcrt/mbstring/ischira.c b/reactos/lib/crt/mbstring/ischira.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ischira.c rename to reactos/lib/crt/mbstring/ischira.c diff --git a/reactos/lib/msvcrt/mbstring/iskana.c b/reactos/lib/crt/mbstring/iskana.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/iskana.c rename to reactos/lib/crt/mbstring/iskana.c diff --git a/reactos/lib/msvcrt/mbstring/iskmoji.c b/reactos/lib/crt/mbstring/iskmoji.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/iskmoji.c rename to reactos/lib/crt/mbstring/iskmoji.c diff --git a/reactos/lib/msvcrt/mbstring/iskpun.c b/reactos/lib/crt/mbstring/iskpun.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/iskpun.c rename to reactos/lib/crt/mbstring/iskpun.c diff --git a/reactos/lib/msvcrt/mbstring/islead.c b/reactos/lib/crt/mbstring/islead.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/islead.c rename to reactos/lib/crt/mbstring/islead.c diff --git a/reactos/lib/msvcrt/mbstring/islwr.c b/reactos/lib/crt/mbstring/islwr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/islwr.c rename to reactos/lib/crt/mbstring/islwr.c diff --git a/reactos/lib/msvcrt/mbstring/ismbal.c b/reactos/lib/crt/mbstring/ismbal.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbal.c rename to reactos/lib/crt/mbstring/ismbal.c diff --git a/reactos/lib/msvcrt/mbstring/ismbaln.c b/reactos/lib/crt/mbstring/ismbaln.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbaln.c rename to reactos/lib/crt/mbstring/ismbaln.c diff --git a/reactos/lib/msvcrt/mbstring/ismbc.c b/reactos/lib/crt/mbstring/ismbc.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbc.c rename to reactos/lib/crt/mbstring/ismbc.c diff --git a/reactos/lib/msvcrt/mbstring/ismbgra.c b/reactos/lib/crt/mbstring/ismbgra.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbgra.c rename to reactos/lib/crt/mbstring/ismbgra.c diff --git a/reactos/lib/msvcrt/mbstring/ismbkaln.c b/reactos/lib/crt/mbstring/ismbkaln.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbkaln.c rename to reactos/lib/crt/mbstring/ismbkaln.c diff --git a/reactos/lib/msvcrt/mbstring/ismblead.c b/reactos/lib/crt/mbstring/ismblead.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismblead.c rename to reactos/lib/crt/mbstring/ismblead.c diff --git a/reactos/lib/msvcrt/mbstring/ismbpri.c b/reactos/lib/crt/mbstring/ismbpri.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbpri.c rename to reactos/lib/crt/mbstring/ismbpri.c diff --git a/reactos/lib/msvcrt/mbstring/ismbpun.c b/reactos/lib/crt/mbstring/ismbpun.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbpun.c rename to reactos/lib/crt/mbstring/ismbpun.c diff --git a/reactos/lib/msvcrt/mbstring/ismbtrl.c b/reactos/lib/crt/mbstring/ismbtrl.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/ismbtrl.c rename to reactos/lib/crt/mbstring/ismbtrl.c diff --git a/reactos/lib/msvcrt/mbstring/isuppr.c b/reactos/lib/crt/mbstring/isuppr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/isuppr.c rename to reactos/lib/crt/mbstring/isuppr.c diff --git a/reactos/lib/crtdll/mbstring/jistojms.c b/reactos/lib/crt/mbstring/jistojms.c similarity index 100% rename from reactos/lib/crtdll/mbstring/jistojms.c rename to reactos/lib/crt/mbstring/jistojms.c diff --git a/reactos/lib/crtdll/mbstring/jmstojis.c b/reactos/lib/crt/mbstring/jmstojis.c similarity index 100% rename from reactos/lib/crtdll/mbstring/jmstojis.c rename to reactos/lib/crt/mbstring/jmstojis.c diff --git a/reactos/lib/msvcrt/mbstring/mbbtype.c b/reactos/lib/crt/mbstring/mbbtype.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbbtype.c rename to reactos/lib/crt/mbstring/mbbtype.c diff --git a/reactos/lib/msvcrt/mbstring/mbccpy.c b/reactos/lib/crt/mbstring/mbccpy.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbccpy.c rename to reactos/lib/crt/mbstring/mbccpy.c diff --git a/reactos/lib/msvcrt/mbstring/mbclen.c b/reactos/lib/crt/mbstring/mbclen.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbclen.c rename to reactos/lib/crt/mbstring/mbclen.c diff --git a/reactos/lib/msvcrt/mbstring/mbscat.c b/reactos/lib/crt/mbstring/mbscat.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbscat.c rename to reactos/lib/crt/mbstring/mbscat.c diff --git a/reactos/lib/msvcrt/mbstring/mbschr.c b/reactos/lib/crt/mbstring/mbschr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbschr.c rename to reactos/lib/crt/mbstring/mbschr.c diff --git a/reactos/lib/msvcrt/mbstring/mbscmp.c b/reactos/lib/crt/mbstring/mbscmp.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbscmp.c rename to reactos/lib/crt/mbstring/mbscmp.c diff --git a/reactos/lib/msvcrt/mbstring/mbscoll.c b/reactos/lib/crt/mbstring/mbscoll.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbscoll.c rename to reactos/lib/crt/mbstring/mbscoll.c diff --git a/reactos/lib/msvcrt/mbstring/mbscpy.c b/reactos/lib/crt/mbstring/mbscpy.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbscpy.c rename to reactos/lib/crt/mbstring/mbscpy.c diff --git a/reactos/lib/msvcrt/mbstring/mbscspn.c b/reactos/lib/crt/mbstring/mbscspn.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbscspn.c rename to reactos/lib/crt/mbstring/mbscspn.c diff --git a/reactos/lib/crtdll/mbstring/mbsdec.c b/reactos/lib/crt/mbstring/mbsdec.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbsdec.c rename to reactos/lib/crt/mbstring/mbsdec.c diff --git a/reactos/lib/msvcrt/mbstring/mbsdup.c b/reactos/lib/crt/mbstring/mbsdup.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsdup.c rename to reactos/lib/crt/mbstring/mbsdup.c diff --git a/reactos/lib/msvcrt/mbstring/mbsicmp.c b/reactos/lib/crt/mbstring/mbsicmp.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsicmp.c rename to reactos/lib/crt/mbstring/mbsicmp.c diff --git a/reactos/lib/msvcrt/mbstring/mbsicoll.c b/reactos/lib/crt/mbstring/mbsicoll.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsicoll.c rename to reactos/lib/crt/mbstring/mbsicoll.c diff --git a/reactos/lib/crtdll/mbstring/mbsinc.c b/reactos/lib/crt/mbstring/mbsinc.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbsinc.c rename to reactos/lib/crt/mbstring/mbsinc.c diff --git a/reactos/lib/crtdll/mbstring/mbslen.c b/reactos/lib/crt/mbstring/mbslen.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbslen.c rename to reactos/lib/crt/mbstring/mbslen.c diff --git a/reactos/lib/crtdll/mbstring/mbslwr.c b/reactos/lib/crt/mbstring/mbslwr.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbslwr.c rename to reactos/lib/crt/mbstring/mbslwr.c diff --git a/reactos/lib/msvcrt/mbstring/mbsncat.c b/reactos/lib/crt/mbstring/mbsncat.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsncat.c rename to reactos/lib/crt/mbstring/mbsncat.c diff --git a/reactos/lib/crtdll/mbstring/mbsnccnt.c b/reactos/lib/crt/mbstring/mbsnccnt.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbsnccnt.c rename to reactos/lib/crt/mbstring/mbsnccnt.c diff --git a/reactos/lib/msvcrt/mbstring/mbsncmp.c b/reactos/lib/crt/mbstring/mbsncmp.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsncmp.c rename to reactos/lib/crt/mbstring/mbsncmp.c diff --git a/reactos/lib/msvcrt/mbstring/mbsncoll.c b/reactos/lib/crt/mbstring/mbsncoll.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsncoll.c rename to reactos/lib/crt/mbstring/mbsncoll.c diff --git a/reactos/lib/msvcrt/mbstring/mbsncpy.c b/reactos/lib/crt/mbstring/mbsncpy.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsncpy.c rename to reactos/lib/crt/mbstring/mbsncpy.c diff --git a/reactos/lib/msvcrt/mbstring/mbsnextc.c b/reactos/lib/crt/mbstring/mbsnextc.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsnextc.c rename to reactos/lib/crt/mbstring/mbsnextc.c diff --git a/reactos/lib/msvcrt/mbstring/mbsnicmp.c b/reactos/lib/crt/mbstring/mbsnicmp.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsnicmp.c rename to reactos/lib/crt/mbstring/mbsnicmp.c diff --git a/reactos/lib/msvcrt/mbstring/mbsnicoll.c b/reactos/lib/crt/mbstring/mbsnicoll.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsnicoll.c rename to reactos/lib/crt/mbstring/mbsnicoll.c diff --git a/reactos/lib/msvcrt/mbstring/mbsninc.c b/reactos/lib/crt/mbstring/mbsninc.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsninc.c rename to reactos/lib/crt/mbstring/mbsninc.c diff --git a/reactos/lib/msvcrt/mbstring/mbsnset.c b/reactos/lib/crt/mbstring/mbsnset.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsnset.c rename to reactos/lib/crt/mbstring/mbsnset.c diff --git a/reactos/lib/msvcrt/mbstring/mbspbrk.c b/reactos/lib/crt/mbstring/mbspbrk.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbspbrk.c rename to reactos/lib/crt/mbstring/mbspbrk.c diff --git a/reactos/lib/msvcrt/mbstring/mbsrchr.c b/reactos/lib/crt/mbstring/mbsrchr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsrchr.c rename to reactos/lib/crt/mbstring/mbsrchr.c diff --git a/reactos/lib/msvcrt/mbstring/mbsrev.c b/reactos/lib/crt/mbstring/mbsrev.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsrev.c rename to reactos/lib/crt/mbstring/mbsrev.c diff --git a/reactos/lib/msvcrt/mbstring/mbsset.c b/reactos/lib/crt/mbstring/mbsset.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsset.c rename to reactos/lib/crt/mbstring/mbsset.c diff --git a/reactos/lib/msvcrt/mbstring/mbsspn.c b/reactos/lib/crt/mbstring/mbsspn.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsspn.c rename to reactos/lib/crt/mbstring/mbsspn.c diff --git a/reactos/lib/msvcrt/mbstring/mbsspnp.c b/reactos/lib/crt/mbstring/mbsspnp.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsspnp.c rename to reactos/lib/crt/mbstring/mbsspnp.c diff --git a/reactos/lib/msvcrt/mbstring/mbsstr.c b/reactos/lib/crt/mbstring/mbsstr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsstr.c rename to reactos/lib/crt/mbstring/mbsstr.c diff --git a/reactos/lib/msvcrt/mbstring/mbstok.c b/reactos/lib/crt/mbstring/mbstok.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbstok.c rename to reactos/lib/crt/mbstring/mbstok.c diff --git a/reactos/lib/crtdll/mbstring/mbstrlen.c b/reactos/lib/crt/mbstring/mbstrlen.c similarity index 100% rename from reactos/lib/crtdll/mbstring/mbstrlen.c rename to reactos/lib/crt/mbstring/mbstrlen.c diff --git a/reactos/lib/msvcrt/mbstring/mbsupr.c b/reactos/lib/crt/mbstring/mbsupr.c similarity index 100% rename from reactos/lib/msvcrt/mbstring/mbsupr.c rename to reactos/lib/crt/mbstring/mbsupr.c diff --git a/reactos/lib/msvcrt/misc/amsg.c b/reactos/lib/crt/misc/amsg.c similarity index 100% rename from reactos/lib/msvcrt/misc/amsg.c rename to reactos/lib/crt/misc/amsg.c diff --git a/reactos/lib/msvcrt/misc/assert.c b/reactos/lib/crt/misc/assert.c similarity index 100% rename from reactos/lib/msvcrt/misc/assert.c rename to reactos/lib/crt/misc/assert.c diff --git a/reactos/lib/msvcrt/misc/crtmain.c b/reactos/lib/crt/misc/crtmain.c similarity index 100% rename from reactos/lib/msvcrt/misc/crtmain.c rename to reactos/lib/crt/misc/crtmain.c diff --git a/reactos/lib/msvcrt/misc/environ.c b/reactos/lib/crt/misc/environ.c similarity index 99% rename from reactos/lib/msvcrt/misc/environ.c rename to reactos/lib/crt/misc/environ.c index 93d5f31534c..7847d2aa3bf 100644 --- a/reactos/lib/msvcrt/misc/environ.c +++ b/reactos/lib/crt/misc/environ.c @@ -9,7 +9,7 @@ #include #include #include - + #define NDEBUG #include @@ -18,6 +18,7 @@ unsigned int _osver = 0; unsigned int _winminor = 0; unsigned int _winmajor = 0; unsigned int _winver = 0; + char *_acmdln = NULL; /* pointer to ascii command line */ wchar_t *_wcmdln = NULL; /* pointer to wide character command line */ diff --git a/reactos/lib/msvcrt/misc/getargs.c b/reactos/lib/crt/misc/getargs.c similarity index 97% rename from reactos/lib/msvcrt/misc/getargs.c rename to reactos/lib/crt/misc/getargs.c index 3a57cea4e74..b68db68d6dc 100644 --- a/reactos/lib/msvcrt/misc/getargs.c +++ b/reactos/lib/crt/misc/getargs.c @@ -68,7 +68,7 @@ int expand(char* name, int flag) do { if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { strcpy(&buffer[pos], fd.cFileName); - if (add(strdup(buffer)) < 0) { + if (add(_strdup(buffer)) < 0) { FindClose(hFile); return -1; } @@ -136,7 +136,7 @@ int __getmainargs(int* argc, char*** argv, char*** env, int flag) *argc = __argc; *argv = __argv; *env = _environ; - _pgmptr = strdup((char*)argv[0]); + _pgmptr = _strdup((char*)argv[0]); return 0; } diff --git a/reactos/lib/msvcrt/misc/initterm.c b/reactos/lib/crt/misc/initterm.c similarity index 100% rename from reactos/lib/msvcrt/misc/initterm.c rename to reactos/lib/crt/misc/initterm.c diff --git a/reactos/lib/msvcrt/misc/lock.c b/reactos/lib/crt/misc/lock.c similarity index 100% rename from reactos/lib/msvcrt/misc/lock.c rename to reactos/lib/crt/misc/lock.c diff --git a/reactos/lib/msvcrt/misc/purecall.c b/reactos/lib/crt/misc/purecall.c similarity index 100% rename from reactos/lib/msvcrt/misc/purecall.c rename to reactos/lib/crt/misc/purecall.c diff --git a/reactos/lib/msvcrt/misc/stubs.c b/reactos/lib/crt/misc/stubs.c similarity index 100% rename from reactos/lib/msvcrt/misc/stubs.c rename to reactos/lib/crt/misc/stubs.c diff --git a/reactos/lib/msvcrt/misc/tls.c b/reactos/lib/crt/misc/tls.c similarity index 100% rename from reactos/lib/msvcrt/misc/tls.c rename to reactos/lib/crt/misc/tls.c diff --git a/reactos/lib/crt/precomp.h b/reactos/lib/crt/precomp.h new file mode 100644 index 00000000000..f6d254553a6 --- /dev/null +++ b/reactos/lib/crt/precomp.h @@ -0,0 +1 @@ +#include diff --git a/reactos/lib/msvcrt/process/_cwait.c b/reactos/lib/crt/process/_cwait.c similarity index 100% rename from reactos/lib/msvcrt/process/_cwait.c rename to reactos/lib/crt/process/_cwait.c diff --git a/reactos/lib/msvcrt/process/_system.c b/reactos/lib/crt/process/_system.c similarity index 98% rename from reactos/lib/msvcrt/process/_system.c rename to reactos/lib/crt/process/_system.c index ddea6879a00..9041e41bfc6 100644 --- a/reactos/lib/msvcrt/process/_system.c +++ b/reactos/lib/crt/process/_system.c @@ -47,7 +47,7 @@ int system(const char *command) if (szComSpec == NULL) { - szComSpec = strdup("cmd.exe"); + szComSpec = _strdup("cmd.exe"); if (szComSpec == NULL) { __set_errno(ENOMEM); diff --git a/reactos/lib/msvcrt/process/dll.c b/reactos/lib/crt/process/dll.c similarity index 100% rename from reactos/lib/msvcrt/process/dll.c rename to reactos/lib/crt/process/dll.c diff --git a/reactos/lib/msvcrt/process/process.c b/reactos/lib/crt/process/process.c similarity index 100% rename from reactos/lib/msvcrt/process/process.c rename to reactos/lib/crt/process/process.c diff --git a/reactos/lib/crtdll/process/procid.c b/reactos/lib/crt/process/procid.c similarity index 100% rename from reactos/lib/crtdll/process/procid.c rename to reactos/lib/crt/process/procid.c diff --git a/reactos/lib/msvcrt/process/thread.c b/reactos/lib/crt/process/thread.c similarity index 100% rename from reactos/lib/msvcrt/process/thread.c rename to reactos/lib/crt/process/thread.c diff --git a/reactos/lib/msvcrt/process/threadid.c b/reactos/lib/crt/process/threadid.c similarity index 100% rename from reactos/lib/msvcrt/process/threadid.c rename to reactos/lib/crt/process/threadid.c diff --git a/reactos/lib/msvcrt/process/threadx.c b/reactos/lib/crt/process/threadx.c similarity index 100% rename from reactos/lib/msvcrt/process/threadx.c rename to reactos/lib/crt/process/threadx.c diff --git a/reactos/lib/crtdll/search/lfind.c b/reactos/lib/crt/search/lfind.c similarity index 100% rename from reactos/lib/crtdll/search/lfind.c rename to reactos/lib/crt/search/lfind.c diff --git a/reactos/lib/crtdll/search/lsearch.c b/reactos/lib/crt/search/lsearch.c similarity index 100% rename from reactos/lib/crtdll/search/lsearch.c rename to reactos/lib/crt/search/lsearch.c diff --git a/reactos/lib/msvcrt/setjmp/i386/setjmp.s b/reactos/lib/crt/setjmp/i386/setjmp.s similarity index 100% rename from reactos/lib/msvcrt/setjmp/i386/setjmp.s rename to reactos/lib/crt/setjmp/i386/setjmp.s diff --git a/reactos/lib/crtdll/signal/signal.c b/reactos/lib/crt/signal/signal.c similarity index 100% rename from reactos/lib/crtdll/signal/signal.c rename to reactos/lib/crt/signal/signal.c diff --git a/reactos/lib/crtdll/signal/xcptinfo.c b/reactos/lib/crt/signal/xcptinfo.c similarity index 92% rename from reactos/lib/crtdll/signal/xcptinfo.c rename to reactos/lib/crt/signal/xcptinfo.c index a9ae5497846..9a9ce6237be 100644 --- a/reactos/lib/crtdll/signal/xcptinfo.c +++ b/reactos/lib/crt/signal/xcptinfo.c @@ -1,9 +1,9 @@ -#include - -/* - * @unimplemented - */ -void **__pxcptinfoptrs (void) -{ - return NULL; -} +#include + +/* + * @unimplemented + */ +void **__pxcptinfoptrs (void) +{ + return NULL; +} diff --git a/reactos/lib/msvcrt/stdio/allocfil.c b/reactos/lib/crt/stdio/allocfil.c similarity index 100% rename from reactos/lib/msvcrt/stdio/allocfil.c rename to reactos/lib/crt/stdio/allocfil.c diff --git a/reactos/lib/crtdll/stdio/clearerr.c b/reactos/lib/crt/stdio/clearerr.c similarity index 100% rename from reactos/lib/crtdll/stdio/clearerr.c rename to reactos/lib/crt/stdio/clearerr.c diff --git a/reactos/lib/crtdll/stdio/fclose.c b/reactos/lib/crt/stdio/fclose.c similarity index 100% rename from reactos/lib/crtdll/stdio/fclose.c rename to reactos/lib/crt/stdio/fclose.c diff --git a/reactos/lib/msvcrt/stdio/fdopen.c b/reactos/lib/crt/stdio/fdopen.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fdopen.c rename to reactos/lib/crt/stdio/fdopen.c diff --git a/reactos/lib/crtdll/stdio/feof.c b/reactos/lib/crt/stdio/feof.c similarity index 100% rename from reactos/lib/crtdll/stdio/feof.c rename to reactos/lib/crt/stdio/feof.c diff --git a/reactos/lib/msvcrt/stdio/ferror.c b/reactos/lib/crt/stdio/ferror.c similarity index 100% rename from reactos/lib/msvcrt/stdio/ferror.c rename to reactos/lib/crt/stdio/ferror.c diff --git a/reactos/lib/msvcrt/stdio/fflush.c b/reactos/lib/crt/stdio/fflush.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fflush.c rename to reactos/lib/crt/stdio/fflush.c diff --git a/reactos/lib/msvcrt/stdio/fgetc.c b/reactos/lib/crt/stdio/fgetc.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fgetc.c rename to reactos/lib/crt/stdio/fgetc.c diff --git a/reactos/lib/msvcrt/stdio/fgetchar.c b/reactos/lib/crt/stdio/fgetchar.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fgetchar.c rename to reactos/lib/crt/stdio/fgetchar.c diff --git a/reactos/lib/msvcrt/stdio/fgetpos.c b/reactos/lib/crt/stdio/fgetpos.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fgetpos.c rename to reactos/lib/crt/stdio/fgetpos.c diff --git a/reactos/lib/msvcrt/stdio/fgets.c b/reactos/lib/crt/stdio/fgets.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fgets.c rename to reactos/lib/crt/stdio/fgets.c diff --git a/reactos/lib/msvcrt/stdio/fgetws.c b/reactos/lib/crt/stdio/fgetws.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fgetws.c rename to reactos/lib/crt/stdio/fgetws.c diff --git a/reactos/lib/msvcrt/stdio/filbuf.c b/reactos/lib/crt/stdio/filbuf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/filbuf.c rename to reactos/lib/crt/stdio/filbuf.c diff --git a/reactos/lib/msvcrt/stdio/fileno.c b/reactos/lib/crt/stdio/fileno.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fileno.c rename to reactos/lib/crt/stdio/fileno.c diff --git a/reactos/lib/msvcrt/stdio/flsbuf.c b/reactos/lib/crt/stdio/flsbuf.c similarity index 99% rename from reactos/lib/msvcrt/stdio/flsbuf.c rename to reactos/lib/crt/stdio/flsbuf.c index e0b4154b902..2ca113c15be 100644 --- a/reactos/lib/msvcrt/stdio/flsbuf.c +++ b/reactos/lib/crt/stdio/flsbuf.c @@ -93,6 +93,7 @@ int _flsbuf(int c, FILE* f) if ((f->_flag & (_IO_LBF|_IONBF)) == 0) { f->_cnt--; *f->_ptr++ = c; + f->_flag |= _IODIRTY; } return c; } diff --git a/reactos/lib/msvcrt/stdio/fopen.c b/reactos/lib/crt/stdio/fopen.c similarity index 93% rename from reactos/lib/msvcrt/stdio/fopen.c rename to reactos/lib/crt/stdio/fopen.c index 176ed6eff3b..eb309c9f798 100644 --- a/reactos/lib/msvcrt/stdio/fopen.c +++ b/reactos/lib/crt/stdio/fopen.c @@ -30,17 +30,12 @@ #include #include #include -//#include +#include //might change fopen(file,mode) -> fsopen(file,mode,_SH_DENYNO); -#undef _fmode -extern unsigned int _fmode; - FILE* __alloc_file(void); -//extern int _fmode; - FILE* fopen(const char *file, const char *mode) { @@ -68,7 +63,7 @@ FILE* fopen(const char *file, const char *mode) else if (strchr(mode, 'b')) oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); fd = _open(file, oflags, 0); if (fd < 0) @@ -94,7 +89,7 @@ FILE* fopen(const char *file, const char *mode) f->_flag |= _IOTEXT; else if (strchr(mode, 'b')) f->_flag |= _IOBINARY; - else if (_fmode & O_BINARY) + else if (__fmode & O_BINARY) f->_flag |= _IOBINARY; f->_base = f->_ptr = NULL; @@ -130,7 +125,7 @@ FILE* _wfopen(const wchar_t *file, const wchar_t *mode) else if (wcschr(mode, L'b')) oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); fd = _wopen(file, oflags, 0); if (fd < 0) @@ -155,7 +150,7 @@ FILE* _wfopen(const wchar_t *file, const wchar_t *mode) f->_flag |= _IOTEXT; else if (wcschr(mode, L'b')) f->_flag |= _IOBINARY; - else if (_fmode & O_BINARY) + else if (__fmode & O_BINARY) f->_flag |= _IOBINARY; f->_base = f->_ptr = NULL; diff --git a/reactos/lib/crtdll/stdio/fprintf.c b/reactos/lib/crt/stdio/fprintf.c similarity index 100% rename from reactos/lib/crtdll/stdio/fprintf.c rename to reactos/lib/crt/stdio/fprintf.c diff --git a/reactos/lib/msvcrt/stdio/fputc.c b/reactos/lib/crt/stdio/fputc.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fputc.c rename to reactos/lib/crt/stdio/fputc.c diff --git a/reactos/lib/msvcrt/stdio/fputchar.c b/reactos/lib/crt/stdio/fputchar.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fputchar.c rename to reactos/lib/crt/stdio/fputchar.c diff --git a/reactos/lib/msvcrt/stdio/fputs.c b/reactos/lib/crt/stdio/fputs.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fputs.c rename to reactos/lib/crt/stdio/fputs.c diff --git a/reactos/lib/msvcrt/stdio/fread.c b/reactos/lib/crt/stdio/fread.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fread.c rename to reactos/lib/crt/stdio/fread.c diff --git a/reactos/lib/msvcrt/stdio/freopen.c b/reactos/lib/crt/stdio/freopen.c similarity index 96% rename from reactos/lib/msvcrt/stdio/freopen.c rename to reactos/lib/crt/stdio/freopen.c index 06f003f47a0..881e765e889 100644 --- a/reactos/lib/msvcrt/stdio/freopen.c +++ b/reactos/lib/crt/stdio/freopen.c @@ -44,7 +44,7 @@ FILE *freopen(const char *file, const char *mode, FILE *f) else if (tbchar == 'b') oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); fd = _open(file, oflags, 0666); if (fd < 0) @@ -104,7 +104,7 @@ FILE *_wfreopen(const wchar_t *file, const wchar_t *mode, FILE *f) else if (tbchar == L'b') oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); fd = _wopen(file, oflags, 0666); if (fd < 0) diff --git a/reactos/lib/msvcrt/stdio/fscanf.c b/reactos/lib/crt/stdio/fscanf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fscanf.c rename to reactos/lib/crt/stdio/fscanf.c diff --git a/reactos/lib/msvcrt/stdio/fseek.c b/reactos/lib/crt/stdio/fseek.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fseek.c rename to reactos/lib/crt/stdio/fseek.c diff --git a/reactos/lib/msvcrt/stdio/fsetpos.c b/reactos/lib/crt/stdio/fsetpos.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fsetpos.c rename to reactos/lib/crt/stdio/fsetpos.c diff --git a/reactos/lib/msvcrt/stdio/fsopen.c b/reactos/lib/crt/stdio/fsopen.c similarity index 97% rename from reactos/lib/msvcrt/stdio/fsopen.c rename to reactos/lib/crt/stdio/fsopen.c index 7d7268f7d11..94d39aa1c90 100644 --- a/reactos/lib/msvcrt/stdio/fsopen.c +++ b/reactos/lib/crt/stdio/fsopen.c @@ -65,7 +65,7 @@ FILE* _fsopen(const char *file, const char *mode, int shflag) else if (tbchar == 'b') oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); if ( shflag == _SH_DENYNO ) shf = _S_IREAD | _S_IWRITE; @@ -146,7 +146,7 @@ FILE* _wfsopen(const wchar_t *file, const wchar_t *mode, int shflag) else if (tbchar == L'b') oflags |= O_BINARY; else - oflags |= (_fmode & (O_TEXT|O_BINARY)); + oflags |= (__fmode & (O_TEXT|O_BINARY)); if ( shflag == _SH_DENYNO ) shf = _S_IREAD | _S_IWRITE; diff --git a/reactos/lib/msvcrt/stdio/ftell.c b/reactos/lib/crt/stdio/ftell.c similarity index 100% rename from reactos/lib/msvcrt/stdio/ftell.c rename to reactos/lib/crt/stdio/ftell.c diff --git a/reactos/lib/msvcrt/stdio/fwalk.c b/reactos/lib/crt/stdio/fwalk.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fwalk.c rename to reactos/lib/crt/stdio/fwalk.c diff --git a/reactos/lib/msvcrt/stdio/fwrite.c b/reactos/lib/crt/stdio/fwrite.c similarity index 100% rename from reactos/lib/msvcrt/stdio/fwrite.c rename to reactos/lib/crt/stdio/fwrite.c diff --git a/reactos/lib/msvcrt/stdio/getc.c b/reactos/lib/crt/stdio/getc.c similarity index 100% rename from reactos/lib/msvcrt/stdio/getc.c rename to reactos/lib/crt/stdio/getc.c diff --git a/reactos/lib/msvcrt/stdio/getchar.c b/reactos/lib/crt/stdio/getchar.c similarity index 100% rename from reactos/lib/msvcrt/stdio/getchar.c rename to reactos/lib/crt/stdio/getchar.c diff --git a/reactos/lib/msvcrt/stdio/gets.c b/reactos/lib/crt/stdio/gets.c similarity index 100% rename from reactos/lib/msvcrt/stdio/gets.c rename to reactos/lib/crt/stdio/gets.c diff --git a/reactos/lib/msvcrt/stdio/getw.c b/reactos/lib/crt/stdio/getw.c similarity index 100% rename from reactos/lib/msvcrt/stdio/getw.c rename to reactos/lib/crt/stdio/getw.c diff --git a/reactos/lib/msvcrt/stdio/perror.c b/reactos/lib/crt/stdio/perror.c similarity index 100% rename from reactos/lib/msvcrt/stdio/perror.c rename to reactos/lib/crt/stdio/perror.c diff --git a/reactos/lib/msvcrt/stdio/popen.c b/reactos/lib/crt/stdio/popen.c similarity index 94% rename from reactos/lib/msvcrt/stdio/popen.c rename to reactos/lib/crt/stdio/popen.c index 5c9b5583877..2959fb439d9 100644 --- a/reactos/lib/msvcrt/stdio/popen.c +++ b/reactos/lib/crt/stdio/popen.c @@ -95,12 +95,12 @@ FILE *_popen (const char *cm, const char *md) /* program name, pipe mode */ if ( *md == 'r' ) { - pf = _fdopen(__fileno_alloc(hReadPipe, _fmode) , "r"); + pf = _fdopen(__fileno_alloc(hReadPipe, __fmode) , "r"); CloseHandle(hWritePipe); } else { - pf = _fdopen( __fileno_alloc(hWritePipe, _fmode) , "w"); + pf = _fdopen( __fileno_alloc(hWritePipe, __fmode) , "w"); CloseHandle(hReadPipe); } @@ -209,12 +209,12 @@ FILE *_wpopen (const wchar_t *cm, const wchar_t *md) /* program name, pipe mode if ( *md == L'r' ) { - pf = _wfdopen(__fileno_alloc(hReadPipe, _fmode) , L"r"); + pf = _wfdopen(__fileno_alloc(hReadPipe, __fmode) , L"r"); CloseHandle(hWritePipe); } else { - pf = _wfdopen( __fileno_alloc(hWritePipe, _fmode) , L"w"); + pf = _wfdopen( __fileno_alloc(hWritePipe, __fmode) , L"w"); CloseHandle(hReadPipe); } diff --git a/reactos/lib/msvcrt/stdio/printf.c b/reactos/lib/crt/stdio/printf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/printf.c rename to reactos/lib/crt/stdio/printf.c diff --git a/reactos/lib/msvcrt/stdio/putc.c b/reactos/lib/crt/stdio/putc.c similarity index 100% rename from reactos/lib/msvcrt/stdio/putc.c rename to reactos/lib/crt/stdio/putc.c diff --git a/reactos/lib/msvcrt/stdio/putchar.c b/reactos/lib/crt/stdio/putchar.c similarity index 100% rename from reactos/lib/msvcrt/stdio/putchar.c rename to reactos/lib/crt/stdio/putchar.c diff --git a/reactos/lib/msvcrt/stdio/puts.c b/reactos/lib/crt/stdio/puts.c similarity index 100% rename from reactos/lib/msvcrt/stdio/puts.c rename to reactos/lib/crt/stdio/puts.c diff --git a/reactos/lib/crtdll/stdio/putw.c b/reactos/lib/crt/stdio/putw.c similarity index 100% rename from reactos/lib/crtdll/stdio/putw.c rename to reactos/lib/crt/stdio/putw.c diff --git a/reactos/lib/msvcrt/stdio/remove.c b/reactos/lib/crt/stdio/remove.c similarity index 100% rename from reactos/lib/msvcrt/stdio/remove.c rename to reactos/lib/crt/stdio/remove.c diff --git a/reactos/lib/msvcrt/stdio/rename.c b/reactos/lib/crt/stdio/rename.c similarity index 100% rename from reactos/lib/msvcrt/stdio/rename.c rename to reactos/lib/crt/stdio/rename.c diff --git a/reactos/lib/crtdll/stdio/rewind.c b/reactos/lib/crt/stdio/rewind.c similarity index 100% rename from reactos/lib/crtdll/stdio/rewind.c rename to reactos/lib/crt/stdio/rewind.c diff --git a/reactos/lib/msvcrt/stdio/rmtmp.c b/reactos/lib/crt/stdio/rmtmp.c similarity index 100% rename from reactos/lib/msvcrt/stdio/rmtmp.c rename to reactos/lib/crt/stdio/rmtmp.c diff --git a/reactos/lib/msvcrt/stdio/scanf.c b/reactos/lib/crt/stdio/scanf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/scanf.c rename to reactos/lib/crt/stdio/scanf.c diff --git a/reactos/lib/crtdll/stdio/setbuf.c b/reactos/lib/crt/stdio/setbuf.c similarity index 100% rename from reactos/lib/crtdll/stdio/setbuf.c rename to reactos/lib/crt/stdio/setbuf.c diff --git a/reactos/lib/msvcrt/stdio/setvbuf.c b/reactos/lib/crt/stdio/setvbuf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/setvbuf.c rename to reactos/lib/crt/stdio/setvbuf.c diff --git a/reactos/lib/crtdll/stdio/sprintf.c b/reactos/lib/crt/stdio/sprintf.c similarity index 88% rename from reactos/lib/crtdll/stdio/sprintf.c rename to reactos/lib/crt/stdio/sprintf.c index 6a020ae06d8..944b3aa4dc8 100644 --- a/reactos/lib/crtdll/stdio/sprintf.c +++ b/reactos/lib/crt/stdio/sprintf.c @@ -30,7 +30,7 @@ Cambridge, MA 02139, USA. */ * @implemented */ int -sprintf(char *str, const char *fmt, ...) +crt_sprintf(char *str, const char *fmt, ...) { va_list arg; int done; @@ -45,7 +45,7 @@ sprintf(char *str, const char *fmt, ...) * @implemented */ int -swprintf(wchar_t *str, const wchar_t *fmt, ...) +crt_swprintf(wchar_t *str, const wchar_t *fmt, ...) { va_list arg; int done; @@ -65,7 +65,7 @@ swprintf(wchar_t *str, const wchar_t *fmt, ...) * @implemented */ int -_snprintf (char *s, size_t maxlen,const char *format, ...) +crt__snprintf (char *s, size_t maxlen,const char *format, ...) { va_list arg; int done; @@ -81,7 +81,7 @@ _snprintf (char *s, size_t maxlen,const char *format, ...) * @implemented */ int -_snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) +crt__snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) { va_list arg; int done; diff --git a/reactos/lib/msvcrt/stdio/sscanf.c b/reactos/lib/crt/stdio/sscanf.c similarity index 93% rename from reactos/lib/msvcrt/stdio/sscanf.c rename to reactos/lib/crt/stdio/sscanf.c index cb2180351f9..408f0c3b467 100644 --- a/reactos/lib/msvcrt/stdio/sscanf.c +++ b/reactos/lib/crt/stdio/sscanf.c @@ -25,7 +25,8 @@ /* Read formatted input from S, according to the format string FORMAT. */ /* VARARGS2 */ -int msvcrt_sscanf (const char *s,const char *format, ...) +int +crt_sscanf (const char *s,const char *format, ...) { va_list arg; int done; @@ -40,7 +41,8 @@ int msvcrt_sscanf (const char *s,const char *format, ...) /* * @implemented */ -int swscanf(const wchar_t *str, const wchar_t *fmt, ...) +int +swscanf(const wchar_t *str, const wchar_t *fmt, ...) { va_list arg; int done; diff --git a/reactos/lib/msvcrt/stdio/stdhnd.c b/reactos/lib/crt/stdio/stdhnd.c similarity index 100% rename from reactos/lib/msvcrt/stdio/stdhnd.c rename to reactos/lib/crt/stdio/stdhnd.c diff --git a/reactos/lib/msvcrt/stdio/tempnam.c b/reactos/lib/crt/stdio/tempnam.c similarity index 100% rename from reactos/lib/msvcrt/stdio/tempnam.c rename to reactos/lib/crt/stdio/tempnam.c diff --git a/reactos/lib/msvcrt/stdio/tmpfile.c b/reactos/lib/crt/stdio/tmpfile.c similarity index 100% rename from reactos/lib/msvcrt/stdio/tmpfile.c rename to reactos/lib/crt/stdio/tmpfile.c diff --git a/reactos/lib/msvcrt/stdio/tmpnam.c b/reactos/lib/crt/stdio/tmpnam.c similarity index 100% rename from reactos/lib/msvcrt/stdio/tmpnam.c rename to reactos/lib/crt/stdio/tmpnam.c diff --git a/reactos/lib/msvcrt/stdio/ungetc.c b/reactos/lib/crt/stdio/ungetc.c similarity index 100% rename from reactos/lib/msvcrt/stdio/ungetc.c rename to reactos/lib/crt/stdio/ungetc.c diff --git a/reactos/lib/msvcrt/stdio/vfprintf.c b/reactos/lib/crt/stdio/vfprintf.c similarity index 74% rename from reactos/lib/msvcrt/stdio/vfprintf.c rename to reactos/lib/crt/stdio/vfprintf.c index a6a060134ed..8d2c0f3d510 100644 --- a/reactos/lib/msvcrt/stdio/vfprintf.c +++ b/reactos/lib/crt/stdio/vfprintf.c @@ -408,213 +408,7 @@ static int numberf(FILE * f, double __n, char exp_sign, int size, int precision } -static int numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type) -{ - long double exponent = 0.0; - long double e; - long ie; - //int x; - char *buf, *tmp; - int i = 0; - int j = 0; - //int k = 0; - - long double frac, intr; - long double p; - char sign; - char c; - char ro = 0; - - int result, done = 0; - - union - { - long double* __n; - long_double_t* n; - } n; - - n.__n = &__n; - - if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { - ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); - exponent = ie/3.321928; - } - - if ( exp_sign == 'g' || exp_sign == 'G' ) { - type |= ZEROTRUNC; - if ( exponent < -4 || fabs(exponent) >= precision ) - exp_sign -= 2; // g -> e and G -> E - } - - if ( exp_sign == 'e' || exp_sign == 'E' ) { - frac = modfl(exponent,&e); - if ( frac > 0.5 ) - e++; - else if ( frac < -0.5 ) - e--; - - result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); - if (result < 0) - return -1; - done += result; - if (putc( exp_sign,f) == EOF) - return -1; - done++; - size--; - ie = (long)e; - type = LEFT | PLUS; - if ( ie < 0 ) - type |= SIGN; - - result = number(f,ie, 10,2, 2,type ); - if (result < 0) - return -1; - done += result; - return done; - } - - if ( exp_sign == 'f' ) { - - buf = alloca(4096); - if (type & LEFT) { - type &= ~ZEROPAD; - } - - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) { - if (__n < 0) { - sign = '-'; - __n = fabs(__n); - size--; - } else if (type & PLUS) { - sign = '+'; - size--; - } else if (type & SPACE) { - sign = ' '; - size--; - } - } - - frac = modfl(__n,&intr); - - // # flags forces a . and prevents trucation of trailing zero's - if ( precision > 0 ) { - //frac = modfl(__n,&intr); - - i = precision-1; - while ( i >= 0 ) { - frac*=10.0L; - frac = modfl((long double)frac, &p); - buf[i] = (int)p + '0'; - i--; - } - i = precision; - size -= precision; - - ro = 0; - if ( frac > 0.5 ) { - ro = 1; - } - - if ( precision >= 1 || type & SPECIAL) { - buf[i++] = '.'; - size--; - } - } - - if ( intr == 0.0 ) { - buf[i++] = '0'; - size--; - } - else { - while ( intr > 0.0 ) { - p=intr; - intr/=10.0L; - modfl(intr, &intr); - - p -= 10.0L*intr; - - buf[i++] = (int)p + '0'; - size--; - } - } - - j = 0; - while ( j < i && ro == 1) { - if ( buf[j] >= '0' && buf[j] <= '8' ) { - buf[j]++; - ro = 0; - } - else if ( buf[j] == '9' ) { - buf[j] = '0'; - } - j++; - } - if ( ro == 1 ) - buf[i++] = '1'; - - buf[i] = 0; - - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - { - if (putc(' ',f) == EOF) - return -1; - done++; - } - if (sign) - { - if (putc(sign,f) == EOF) - return -1; - done++; - } - - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - { - if (putc(' ',f) == EOF) - return -1; - done++; - } - if (type & SPECIAL) { - } - - if (!(type & LEFT)) - while (size-- > 0) - { - if (putc(c,f) == EOF) - return -1; - done++; - } - tmp = buf; - if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { - j = 0; - while ( j < i && ( *tmp == '0' || *tmp == '.' )) { - tmp++; - i--; - } - } -// else -// while (i < precision--) -// putc( '0', f); - while (i-- > 0) - { - if ( putc(tmp[i],f) == EOF) - return -1; - done++; - } - while (size-- > 0) - { - if (putc(' ', f) == EOF) - return -1; - done++; - } - } - return done; -} static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags) { @@ -720,7 +514,6 @@ int __vfprintf(FILE *f, const char *fmt, va_list args) int len; ULONGLONG num; int base; - long double _ldouble; double _double; const char *s; const wchar_t *sw; @@ -938,85 +731,43 @@ int __vfprintf(FILE *f, const char *fmt, va_list args) case 'f': case 'g': case 'G': - if (qualifier == 'l' || qualifier == 'L' ) { - _ldouble = va_arg(args, long double); - - if ( _isnanl(_ldouble) ) { - s = "Nan"; - len = 3; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } - else if ( _isinfl(_ldouble) < 0 ) { - s = "-Inf"; - len = 4; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } - else if ( _isinfl(_ldouble) > 0 ) { - s = "+Inf"; - len = 4; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } else { - if ( precision == -1 ) - precision = 6; - result = numberfl(f,_ldouble,*fmt,field_width,precision,flags); - if (result < 0) - return -1; - done += result; - } - } else { - _double = (double)va_arg(args, double); + _double = (double)va_arg(args, double); - if ( _isnan(_double) ) { - s = "Nan"; - len = 3; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } else if ( _isinf(_double) < 0 ) { - s = "-Inf"; - len = 4; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } else if ( _isinf(_double) > 0 ) { - s = "+Inf"; - len = 4; - while ( len > 0 ) { - if (putc(*s++,f) == EOF) - return -1; - done++; - len --; - } - } else { - if ( precision == -1 ) - precision = 6; - result = numberf(f,_double,*fmt,field_width,precision,flags); - if (result < 0) - return -1; - done += result; - } - } + if ( _isnan(_double) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } continue; case 'p': diff --git a/reactos/lib/crt/stdio/vfscanf.c b/reactos/lib/crt/stdio/vfscanf.c new file mode 100644 index 00000000000..d4e7de6cb5d --- /dev/null +++ b/reactos/lib/crt/stdio/vfscanf.c @@ -0,0 +1,1229 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "precomp.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __USE_W32API +int __set_errno(int err); +#else +#include +#endif + +/* The internal entry points for `strtoX' take an extra flag argument + saying whether or not to parse locale-dependent number grouping. */ + +double __strtod_internal (const char *__nptr,char **__endptr, int __group); +float __strtof_internal (const char *__nptr, char **__endptr,int __group); +long double __strtold_internal (const char *__nptr,char **__endptr, int __group); +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group); +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group); + + +#include // robd +//#ifdef __GNUC__ +//#define HAVE_LONGLONG +//#define LONGLONG LONGLONG +//#else +//#define LONGLONG long +//#endif + +/* Those are flags in the conversion format. */ +# define LONG 0x001 /* l: long or double */ +# define LONGDBL 0x002 /* L: LONGLONG or long double */ +# define SHORT 0x004 /* h: short */ +# define SUPPRESS 0x008 /* *: suppress assignment */ +# define POINTER 0x010 /* weird %p pointer (`fake hex') */ +# define NOSKIP 0x020 /* do not skip blanks */ +# define WIDTH 0x040 /* width was given */ +# define GROUP 0x080 /* ': group numbers */ +# define MALLOC 0x100 /* a: malloc strings */ + +# define TYPEMOD (LONG|LONGDBL|SHORT) + + +# define UNGETC(c, s) ((void) (((wint_t)c) != ((wint_t)EOF) && --read_in), ungetc (c, s)) +# define inchar() ((c = getc (s)), (void) (c != EOF && ++read_in), c) +# define encode_error() do { \ + funlockfile (s); \ + __set_errno (EILSEQ); \ + return done; \ + } while (0) +# define conv_error() do { \ + funlockfile (s); \ + return done; \ + } while (0) +# define input_error() do { \ + funlockfile (s); \ + return done ? 0 : EOF; \ + } while (0) +# define memory_error() do { \ + funlockfile (s); \ + __set_errno (ENOMEM); \ + return EOF; \ + } while (0) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + __set_errno (EINVAL); \ + return EOF; \ + } \ + } while (0) + +# define flockfile(S) /* nothing */ +# define funlockfile(S) /* nothing */ + +# define ADDW(Ch) \ +do{ \ + if (wpsize == wpmax) \ + { \ + char *old = wp; \ + wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \ + wp = (char *) malloc (wpmax); \ + if (old != NULL) \ + { \ + memcpy (wp, old, wpsize); \ + free(old); \ + } \ + } \ + wp[wpsize++] = (Ch); \ +}while(0) + + +int __vfscanf (FILE *s, const char *format, va_list argptr) +{ + va_list arg; + register const char *f = format; + register unsigned char fc; /* Current character of the format. */ + register size_t done = 0; /* Assignments done. */ + register size_t read_in = 0; /* Chars read in. */ + register int c = 0; /* Last char read. */ + register int width; /* Maximum field width. */ + register int flags; /* Modifiers for current format element. */ + + /* Status for reading F-P nums. */ + char got_dot, got_e, negative; + /* If a [...] is a [^...]. */ + char not_in; + /* Base for integral numbers. */ + int base; + /* Signedness for integral numbers. */ + int number_signed; + /* Decimal point character. */ + wchar_t decimal = '.'; + /* The thousands character of the current locale. */ + wchar_t thousands = ','; + /* Integral holding variables. */ + union + { + LONGLONG q; + ULONGLONG uq; + long int l; + unsigned long int ul; + } num; + /* Character-buffer pointer. */ + char *str = NULL; + wchar_t *wstr = NULL; + char **strptr = NULL; + size_t strsize = 0; + /* We must not react on white spaces immediately because they can + possibly be matched even if in the input stream no character is + available anymore. */ + int skip_space = 0; + /* Workspace. */ + char *wp = NULL; /* Workspace. */ + size_t wpmax = 0; /* Maximal size of workspace. */ + size_t wpsize = 0; /* Currently used bytes in workspace. */ + char *tw; /* Temporary pointer. */ + +#ifdef __va_copy + + __va_copy (arg, argptr); +#else + + arg = (va_list) argptr; +#endif + + + + /* Run through the format string. */ + while (*f != '\0') + { + unsigned int argpos; + /* Extract the next argument, which is of type TYPE. + For a %N$... spec, this is the Nth argument from the beginning; + otherwise it is the next argument after the state now in ARG. */ +#define ARG(type) va_arg(argptr,type) + + if (!isascii (*f)) + { + /* Non-ASCII, may be a multibyte. */ + // int len = mblen (f, strlen (f)); + int len =1; + if (len > 0) + { + do + { + c = inchar (); + if (c == EOF) + input_error (); + else if (c != *f++) + { + UNGETC (c, s); + conv_error (); + } + } + while (--len > 0); + continue; + } + } + + fc = *f++; + if (fc != '%') + { + /* Remember to skip spaces. */ + if (isspace (fc)) + { + skip_space = 1; + continue; + } + + /* Read a character. */ + c = inchar (); + + /* Characters other than format specs must just match. */ + if (c == EOF) + input_error (); + + /* We saw white space char as the last character in the format + string. Now it's time to skip all leading white space. */ + if (skip_space) + { + while (isspace (c)) + if (inchar () == EOF && *_errno() == EINTR) + conv_error (); + skip_space = 0; + } + + if (c != fc) + { + UNGETC (c, s); + conv_error (); + } + + continue; + } + + /* This is the start of the conversion string. */ + flags = 0; + + /* Initialize state of modifiers. */ + argpos = 0; + + /* Prepare temporary buffer. */ + wpsize = 0; + + /* Check for a positional parameter specification. */ + if (isdigit (*f)) + { + argpos = *f++ - '0'; + while (isdigit (*f)) + argpos = argpos * 10 + (*f++ - '0'); + if (*f == '$') + ++f; + else + { + /* Oops; that was actually the field width. */ + width = argpos; + flags |= WIDTH; + argpos = 0; + goto got_width; + } + } + + /* Check for the assignment-suppressing and the number grouping flag. */ + while (*f == '*' || *f == '\'') + switch (*f++) + { + case '*': + flags |= SUPPRESS; + break; + case '\'': + flags |= GROUP; + break; + } + + /* We have seen width. */ + if (isdigit (*f)) + flags |= WIDTH; + + /* Find the maximum field width. */ + width = 0; + while (isdigit (*f)) + { + width *= 10; + width += *f++ - '0'; + } +got_width: + if (width == 0) + width = -1; + + /* Check for type modifiers. */ + while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q') + switch (*f++) + { + case 'h': + /* int's are short int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= SHORT; + break; + case 'l': + if (flags & (SHORT|LONGDBL)) + conv_error (); + else if (flags & LONG) + { + /* A double `l' is equivalent to an `L'. */ + flags &= ~LONG; + flags |= LONGDBL; + } + else + /* int's are long int's. */ + flags |= LONG; + break; + case 'q': + case 'L': + /* double's are long double's, and int's are LONGLONG int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= LONGDBL; + break; + case 'a': + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + /* String conversions (%s, %[) take a `char **' + arg and fill it in with a malloc'd pointer. */ + flags |= MALLOC; + break; + } + + /* End of the format string? */ + if (*f == '\0') + conv_error (); + + /* We must take care for EINTR errors. */ + if (c == EOF && *_errno() == EINTR) + input_error (); + + /* Find the conversion specifier. */ + fc = *f++; + if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) + { + /* Eat whitespace. */ + do + if (inchar () == EOF && *_errno() == EINTR) + input_error (); + while (isspace (c)) + ; + UNGETC (c, s); + skip_space = 0; + } + + switch (fc) + { + case '%': /* Must match a literal '%'. */ + c = inchar (); + if (c != fc) + { + UNGETC (c, s); + conv_error (); + } + break; + + case 'n': /* Answer number of assignments done. */ + /* Corrigendum 1 to ISO C 1990 describes the allowed flags + with the 'n' conversion specifier. */ + if (!(flags & SUPPRESS)) + { + /* Don't count the read-ahead. */ + if (flags & LONGDBL) + *ARG (long int *) = read_in; + else if (flags & LONG) + *ARG (long int *) = read_in; + else if (flags & SHORT) + *ARG (short int *) = read_in; + else + *ARG (int *) = read_in; + +#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1 + /* We have a severe problem here. The ISO C standard + contradicts itself in explaining the effect of the %n + format in `scanf'. While in ISO C:1990 and the ISO C + Amendement 1:1995 the result is described as + + Execution of a %n directive does not effect the + assignment count returned at the completion of + execution of the f(w)scanf function. + + in ISO C Corrigendum 1:1994 the following was added: + + Subclause 7.9.6.2 + Add the following fourth example: + In: + #include + int d1, d2, n1, n2, i; + i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2); + the value 123 is assigned to d1 and the value3 to n1. + Because %n can never get an input failure the value + of 3 is also assigned to n2. The value of d2 is not + affected. The value 3 is assigned to i. + + We go for now with the historically correct code fro ISO C, + i.e., we don't count the %n assignments. When it ever + should proof to be wrong just remove the #ifdef above. */ + ++done; +#endif + + } + break; + + case 'c': /* Match characters. */ + if ((flags & LONG) == 0) + { + if (!(flags & SUPPRESS)) + { + str = ARG (char *); + if (str == NULL) + conv_error (); + } + + c = inchar (); + if (c == EOF) + input_error (); + + if (width == -1) + width = 1; + + if (!(flags & SUPPRESS)) + { + do + *str++ = c; + while (--width > 0 && inchar () != EOF); + } + else + while (--width > 0 && inchar () != EOF) + ; + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + + break; + } + /* FALLTHROUGH */ + case 'C': + /* Get UTF-8 encoded wide character. Here we assume (as in + other parts of the libc) that we only have to handle + UTF-8. */ + { + wint_t val; + size_t cnt = 0; + int first = 1; + + if (!(flags & SUPPRESS)) + { + wstr = ARG (wchar_t *); + if (str == NULL) + conv_error (); + } + + do + { +#define NEXT_WIDE_CHAR(First) \ + c = inchar (); \ + if (c == EOF) { \ + /* EOF is only an error for the first character. */ \ + if (First) { \ + input_error (); \ + } \ + else \ + { \ + --read_in; \ + break; \ + } \ + } \ + val = c; \ + if (val >= 0x80) \ + { \ + if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + if ((c & 0xe0) == 0xc0) \ + { \ + /* We expect two bytes. */ \ + cnt = 1; \ + val &= 0x1f; \ + } \ + else if ((c & 0xf0) == 0xe0) \ + { \ + /* We expect three bytes. */ \ + cnt = 2; \ + val &= 0x0f; \ + } \ + else if ((c & 0xf8) == 0xf0) \ + { \ + /* We expect four bytes. */ \ + cnt = 3; \ + val &= 0x07; \ + } \ + else if ((c & 0xfc) == 0xf8) \ + { \ + /* We expect five bytes. */ \ + cnt = 4; \ + val &= 0x03; \ + } \ + else \ + { \ + /* We expect six bytes. */ \ + cnt = 5; \ + val &= 0x01; \ + } \ + \ + do \ + { \ + c = inchar (); \ + if (c == EOF \ + || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + val <<= 6; \ + val |= c & 0x3f; \ + } \ + while (--cnt > 0); \ + } \ + \ + if (!(flags & SUPPRESS)) \ + *wstr++ = val; \ + first = 0 + + NEXT_WIDE_CHAR (first); + } + while (--width > 0); + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + } + break; + + case 's': /* Read a string. */ + if (flags & LONG) + /* We have to process a wide character string. */ + goto wide_char_string; + +#define STRING_ARG(Str, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + if (flags & MALLOC) \ + { \ + /* The string is to be stored in a malloc'd buffer. */ \ + strptr = ARG (char **); \ + if (strptr == NULL) \ + conv_error (); \ + /* Allocate an initial buffer. */ \ + strsize = 100; \ + *strptr = malloc (strsize * sizeof (Type)); \ + Str = (Type *) *strptr; \ + } \ + else \ + Str = ARG (Type *); \ + if (Str == NULL) \ + conv_error (); \ + } + + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + + do + { + if (isspace (c)) + { + UNGETC (c, s); + break; + } +#define STRING_ADD_CHAR(Str, c, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + *Str++ = c; \ + if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \ + { \ + /* Enlarge the buffer. */ \ + Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* Can't allocate that much. Last-ditch effort. */\ + Str = realloc (*strptr, \ + (strsize + 1) * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* We lose. Oh well. \ + Terminate the string and stop converting, \ + so at least we don't skip any input. */ \ + ((Type *) (*strptr))[strsize] = '\0'; \ + ++done; \ + conv_error (); \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + ++strsize; \ + } \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + strsize *= 2; \ + } \ + } \ + } + + STRING_ADD_CHAR (str, c, char); + } + while ((width <= 0 || --width > 0) && inchar () != EOF); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + break; + + case 'S': + /* Wide character string. */ +wide_char_string: + { + wint_t val; + int first = 1; + STRING_ARG (wstr, wchar_t); + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + + if (iswspace (val)) + { + /* XXX We would have to push back the whole wide char + with possibly many bytes. But since scanf does + not make a difference for white space characters + we can simply push back a simple which is + guaranteed to be in the [:space:] class. */ + UNGETC (' ', s); + break; + } + + STRING_ADD_CHAR (wstr, val, wchar_t); + first = 0; + } + while (width <= 0 || --width > 0); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + break; + + case 'x': /* Hexadecimal integer. */ + case 'X': /* Ditto. */ + base = 16; + number_signed = 0; + goto number; + + case 'o': /* Octal integer. */ + base = 8; + number_signed = 0; + goto number; + + case 'u': /* Unsigned decimal integer. */ + base = 10; + number_signed = 0; + goto number; + + case 'd': /* Signed decimal integer. */ + base = 10; + number_signed = 1; + goto number; + + case 'i': /* Generic number. */ + base = 0; + number_signed = 1; + +number: + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + ADDW (c); + if (width > 0) + --width; + c = inchar (); + } + + /* Look for a leading indication of base. */ + if (width != 0 && c == '0') + { + if (width > 0) + --width; + + ADDW (c); + c = inchar (); + + if (width != 0 && tolower (c) == 'x') + { + if (base == 0) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = inchar (); + } + } + else if (base == 0) + base = 8; + } + + if (base == 0) + base = 10; + + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + if (base == 16 ? !isxdigit (c) : + ((!isdigit (c) || c - '0' >= base) && + !((flags & GROUP) && base == 10 && c == thousands))) + break; + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } + + /* The just read character is not part of the number anymore. */ + UNGETC (c, s); + + if (wpsize == 0 || + (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) + /* There was no number. */ + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); + if (flags & LONGDBL) + { + // if (number_signed) + // num.q = __strtoq_internal (wp, &tw, base, flags & GROUP); + // else + // num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP); + } + else + { + if (number_signed) + num.l = __strtol_internal (wp, &tw, base, flags & GROUP); + else + num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); + } + if (wp == tw) + conv_error (); + + if (!(flags & SUPPRESS)) + { + if (! number_signed) + { + if (flags & LONGDBL) + { + *ARG (ULONGLONG*) = num.uq; + } + else if (flags & LONG) + *ARG (unsigned long int*) = num.ul; + else if (flags & SHORT) + *ARG (unsigned short int*) = (unsigned short int) num.ul; + else + *ARG (unsigned int*) = (unsigned int) num.ul; + } + else + { + if (flags & LONGDBL) + { + *ARG (LONGLONG*) = num.q; + } + else if (flags & LONG) + *ARG (long int *) = num.l; + else if (flags & SHORT) + *ARG (short int *) = (short int) num.l; + else + *ARG (int *) = (int) num.l; + } + ++done; + } + break; + + case 'e': /* Floating-point numbers. */ + case 'E': + case 'f': + case 'g': + case 'G': + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + negative = c == '-'; + if (inchar () == EOF) + /* EOF is only an input error before we read any chars. */ + conv_error (); + if (width > 0) + --width; + } + else + negative = 0; + + got_dot = got_e = 0; + do + { + if (isdigit (c)) + ADDW (c); + else if (got_e && wp[wpsize - 1] == 'e' + && (c == '-' || c == '+')) + ADDW (c); + else if (wpsize > 0 && !got_e && tolower (c) == 'e') + { + ADDW ('e'); + got_e = got_dot = 1; + } + else if (c == decimal && !got_dot) + { + ADDW (c); + got_dot = 1; + } + else if ((flags & GROUP) && c == thousands && !got_dot) + ADDW (c); + else + { + /* The last read character is not part of the number + anymore. */ + UNGETC (c, s); + break; + } + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (wpsize == 0) + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); +#if 0 + + if (flags & LONGDBL) + { + long double d = __strtold_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (long double *) = negative ? -d : d; + } +#endif + /* + double = long double in windows world. -Gunnar + */ + if (flags & (LONG|LONGDBL)) + { + double d = __strtod_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp){ + *ARG (double *) = negative ? -d : d; + } + } + else + { + float d = __strtof_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp){ + *ARG (float *) = negative ? -d : d; + } + } + + if (tw == wp) + conv_error (); + + if (!(flags & SUPPRESS)) + ++done; + break; + + case '[': /* Character class. */ + if (flags & LONG) + { + STRING_ARG (wstr, wchar_t); + c = '\0'; /* This is to keep gcc quiet. */ + } + else + { + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + } + + if (*f == '^') + { + ++f; + not_in = 1; + } + else + not_in = 0; + + /* Fill WP with byte flags indexed by character. + We will use this flag map for matching input characters. */ + if (wpmax < UCHAR_MAX) + { + wpmax = UCHAR_MAX; + wp = (char *) alloca (wpmax); + } + memset (wp, 0, UCHAR_MAX); + + fc = *f; + if (fc == ']' || fc == '-') + { + /* If ] or - appears before any char in the set, it is not + the terminator or separator, but the first char in the + set. */ + wp[fc] = 1; + ++f; + } + + while ((fc = *f++) != '\0' && fc != ']') + { + if (fc == '-' && *f != '\0' && *f != ']' && + (unsigned char) f[-2] <= (unsigned char) *f) + { + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ + for (fc = f[-2]; fc < *f; ++fc) + wp[fc] = 1; + } + else + /* Add the character to the flag map. */ + wp[fc] = 1; + } + if (fc == '\0') + { + if (!(flags & LONG)) + UNGETC (c, s); + conv_error(); + } + + if (flags & LONG) + { + wint_t val; + int first = 1; + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + if (val > 255 || wp[val] == not_in) + { + /* XXX We have a problem here. We read a wide + character and this possibly took several + bytes. But we can only push back one single + character. To be sure we don't create wrong + input we push it back only in case it is + representable within one byte. */ + if (val < 0x80) + UNGETC (val, s); + break; + } + STRING_ADD_CHAR (wstr, val, wchar_t); + if (width > 0) + --width; + first = 0; + } + while (width != 0); + + if (first) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + else + { + num.ul = read_in - 1; /* -1 because we already read one char. */ + do + { + if (wp[c] == not_in) + { + UNGETC (c, s); + break; + } + STRING_ADD_CHAR (str, c, char); + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (read_in == num.ul) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + } + break; + + case 'p': /* Generic pointer. */ + base = 16; + /* A PTR must be the same size as a `long int'. */ + flags &= ~(SHORT|LONGDBL); + flags |= LONG; + number_signed = 0; + goto number; + } + } + + /* The last thing we saw int the format string was a white space. + Consume the last white spaces. */ + if (skip_space) + { + do + c = inchar (); + while (isspace (c)); + UNGETC (c, s); + } + + + return done; +} + + + +int +xfscanf(FILE *f, const char *fmt, ...) +{ + int r; + va_list a=0; + va_start(a, fmt); + r = __vfscanf(f, fmt, a); + va_end(a); + return r; +} + + +double __strtod_internal (const char *__nptr,char **__endptr, int __group) +{ + return strtod(__nptr,__endptr); +} +float __strtof_internal (const char *__nptr, char **__endptr,int __group) +{ + return (float)strtod(__nptr,__endptr); +} +static double powten[] = + { + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, +#ifdef __GNUC__ + 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L +#else + 1e256L, 1e256L, 1e256L, 1e256L +#endif + }; + +long double __strtold_internal (const char *s,char **sret, int __group) +{ + + long double r; /* result */ + int e, ne; /* exponent */ + int sign; /* +- 1.0 */ + int esign; + int flags=0; + int l2powm1; + + r = 0.0L; + sign = 1; + e = ne = 0; + esign = 1; + + while(*s && isspace(*s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0L; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r *= 10.0L; + r += *s - '0'; + s++; + ne++; + } + } + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0.0L; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + if (esign < 0) + { + esign = -esign; + e = -e; + } + e = e - ne; + if (e < -4096) + { + /* possibly subnormal number, 10^e would overflow */ + r *= 1.0e-2048L; + e += 2048; + } + if (e < 0) + { + e = -e; + esign = -esign; + } + if (e >= 8192) + e = 8191; + if (e) + { + double d = 1.0L; + l2powm1 = 0; + while (e) + { + if (e & 1) + d *= powten[l2powm1]; + e >>= 1; + l2powm1++; + } + if (esign > 0) + r *= d; + else + r /= d; + } + if (sret) + *sret = (char *)s; + return r * sign; + + return 0; +} +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtol(__nptr,__endptr, __base); +} +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtoul(__nptr,__endptr, __base); +} + + + + + + + + + diff --git a/reactos/lib/msvcrt/stdio/vfwprint.c b/reactos/lib/crt/stdio/vfwprint.c similarity index 74% rename from reactos/lib/msvcrt/stdio/vfwprint.c rename to reactos/lib/crt/stdio/vfwprint.c index ad5261c5c88..4e58b29bf95 100644 --- a/reactos/lib/msvcrt/stdio/vfwprint.c +++ b/reactos/lib/crt/stdio/vfwprint.c @@ -415,197 +415,6 @@ static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precis } -static int numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type) -{ - long double exponent = 0.0; - long double e; - long ie; - - //int x; - wchar_t *buf, *tmp; - int i = 0; - int j = 0; - //int k = 0; - - long double frac, intr; - long double p; - wchar_t sign; - wchar_t c; - char ro = 0; - - int result, done = 0; - - union - { - long double* __n; - long_double_t* n; - } n; - - n.__n = &__n; - - if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { - ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); - exponent = ie/3.321928; - } - - if ( exp_sign == L'g' || exp_sign == L'G' ) { - type |= ZEROTRUNC; - if ( exponent < -4 || fabs(exponent) >= precision ) - exp_sign -= 2; // g -> e and G -> E - } - - if ( exp_sign == L'e' || exp_sign == L'E' ) { - frac = modfl(exponent,&e); - if ( frac > 0.5 ) - e++; - else if ( frac < -0.5 ) - e--; - - result = numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); - if (result < 0) - return -1; - done += result; - if (putwc( exp_sign,f) == WEOF) - return -1; - done++; - size--; - ie = (long)e; - type = LEFT | PLUS; - if ( ie < 0 ) - type |= SIGN; - - result = number(f,ie, 10,2, 2,type ); - if (result < 0) - return -1; - done += result; - return done; - } - - if ( exp_sign == L'f' ) { - buf = alloca(4096); - if (type & LEFT) { - type &= ~ZEROPAD; - } - - c = (type & ZEROPAD) ? L'0' : L' '; - sign = 0; - if (type & SIGN) { - if (__n < 0) { - sign = L'-'; - __n = fabs(__n); - size--; - } else if (type & PLUS) { - sign = L'+'; - size--; - } else if (type & SPACE) { - sign = L' '; - size--; - } - } - - frac = modfl(__n,&intr); - - // # flags forces a . and prevents trucation of trailing zero's - if ( precision > 0 ) { - //frac = modfl(__n,&intr); - - i = precision-1; - while ( i >= 0 ) { - frac*=10.0L; - frac = modfl((long double)frac, &p); - buf[i] = (int)p + L'0'; - i--; - } - i = precision; - size -= precision; - - ro = 0; - if ( frac > 0.5 ) { - ro = 1; - } - - if ( precision >= 1 || type & SPECIAL) { - buf[i++] = L'.'; - size--; - } - } - - if ( intr == 0.0 ) { - buf[i++] = L'0'; - size--; - } - else { - while ( intr > 0.0 ) { - p = intr; - intr/=10.0L; - modfl(intr, &intr); - - p -=10.0*intr; - - buf[i++] = (int)p + L'0'; - size--; - } - } - - j = 0; - while ( j < i && ro == 1) { - if ( buf[j] >= L'0' && buf[j] <= L'8' ) { - buf[j]++; - ro = 0; - } - else if ( buf[j] == L'9' ) { - buf[j] = L'0'; - } - j++; - } - if ( ro == 1 ) - buf[i++] = L'1'; - - buf[i] = 0; - - size -= precision; - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - putwc(L' ',f); - if (sign) - putwc(sign,f); - - if (!(type&(ZEROPAD+LEFT))) - while(size-->0) - putwc(L' ',f); - if (type & SPECIAL) { - } - - if (!(type & LEFT)) - while (size-- > 0) - putwc(c,f); - - tmp = buf; - if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { - j = 0; - while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { - tmp++; - i--; - } - } -// else -// while (i < precision--) -// putc( '0', f); - while (i-- > 0) - { - if (putwc(tmp[i],f) == WEOF) - return -1; - done++; - } - while (size-- > 0) - { - if (putwc(L' ', f) == WEOF) - return -1; - done++; - } - } - return done; -} static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags) { @@ -700,7 +509,6 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) int len = 0; ULONGLONG num; int base; - long double _ldouble; double _double; const char *s; const wchar_t* sw; @@ -915,85 +723,43 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) case L'f': case L'g': case L'G': - if (qualifier == L'l' || qualifier == L'L' ) { - _ldouble = va_arg(args, long double); - - if ( _isnanl(_ldouble) ) { - sw = L"Nan"; - len = 3; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } - else if ( _isinfl(_ldouble) < 0 ) { - sw = L"-Inf"; - len = 4; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } - else if ( _isinfl(_ldouble) > 0 ) { - sw = L"+Inf"; - len = 4; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } else { - if ( precision == -1 ) - precision = 6; - result = numberfl(f,_ldouble,*fmt,field_width,precision,flags); - if (result < 0) - return -1; - done += result; - } - } else { - _double = (double)va_arg(args, double); + _double = (double)va_arg(args, double); - if ( _isnan(_double) ) { - sw = L"Nan"; - len = 3; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } else if ( _isinf(_double) < 0 ) { - sw = L"-Inf"; - len = 4; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } else if ( _isinf(_double) > 0 ) { - sw = L"+Inf"; - len = 4; - while ( len > 0 ) { - if (putwc(*sw++,f) == WEOF) - return -1; - done++; - len --; - } - } else { - if ( precision == -1 ) - precision = 6; - result = numberf(f,_double,*fmt,field_width,precision,flags); - if (result < 0) - return -1; - done += result; - } - } + if ( _isnan(_double) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } continue; case L'p': diff --git a/reactos/lib/msvcrt/stdio/vprintf.c b/reactos/lib/crt/stdio/vprintf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/vprintf.c rename to reactos/lib/crt/stdio/vprintf.c diff --git a/reactos/lib/crtdll/stdio/vscanf.c b/reactos/lib/crt/stdio/vscanf.c similarity index 100% rename from reactos/lib/crtdll/stdio/vscanf.c rename to reactos/lib/crt/stdio/vscanf.c diff --git a/reactos/lib/msvcrt/stdio/vsprintf.c b/reactos/lib/crt/stdio/vsprintf.c similarity index 83% rename from reactos/lib/msvcrt/stdio/vsprintf.c rename to reactos/lib/crt/stdio/vsprintf.c index 1ff90e477fe..628761e96aa 100644 --- a/reactos/lib/msvcrt/stdio/vsprintf.c +++ b/reactos/lib/crt/stdio/vsprintf.c @@ -5,7 +5,7 @@ #include int -msvcrt_vsprintf(char *str, const char *fmt, va_list ap) +crt_vsprintf(char *str, const char *fmt, va_list ap) { FILE f; int len; @@ -39,7 +39,7 @@ vswprintf(wchar_t *str, const wchar_t *fmt, va_list ap) int -msvcrt__vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) +crt__vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) { FILE f; int len; @@ -54,7 +54,7 @@ msvcrt__vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) } int -msvcrt__vsnwprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap) +crt__vsnwprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap) { FILE f; int len; diff --git a/reactos/lib/msvcrt/stdio/vsscanf.c b/reactos/lib/crt/stdio/vsscanf.c similarity index 100% rename from reactos/lib/msvcrt/stdio/vsscanf.c rename to reactos/lib/crt/stdio/vsscanf.c diff --git a/reactos/lib/msvcrt/stdio/wfdopen.c b/reactos/lib/crt/stdio/wfdopen.c similarity index 100% rename from reactos/lib/msvcrt/stdio/wfdopen.c rename to reactos/lib/crt/stdio/wfdopen.c diff --git a/reactos/lib/msvcrt/stdio/wrename.c b/reactos/lib/crt/stdio/wrename.c similarity index 100% rename from reactos/lib/msvcrt/stdio/wrename.c rename to reactos/lib/crt/stdio/wrename.c diff --git a/reactos/lib/msvcrt/stdio/wtempnam.c b/reactos/lib/crt/stdio/wtempnam.c similarity index 100% rename from reactos/lib/msvcrt/stdio/wtempnam.c rename to reactos/lib/crt/stdio/wtempnam.c diff --git a/reactos/lib/msvcrt/stdio/wtmpnam.c b/reactos/lib/crt/stdio/wtmpnam.c similarity index 100% rename from reactos/lib/msvcrt/stdio/wtmpnam.c rename to reactos/lib/crt/stdio/wtmpnam.c diff --git a/reactos/lib/crtdll/stdlib/_exit.c b/reactos/lib/crt/stdlib/_exit.c similarity index 100% rename from reactos/lib/crtdll/stdlib/_exit.c rename to reactos/lib/crt/stdlib/_exit.c diff --git a/reactos/lib/crtdll/stdlib/abort.c b/reactos/lib/crt/stdlib/abort.c similarity index 100% rename from reactos/lib/crtdll/stdlib/abort.c rename to reactos/lib/crt/stdlib/abort.c diff --git a/reactos/lib/crtdll/stdlib/abs.c b/reactos/lib/crt/stdlib/abs.c similarity index 100% rename from reactos/lib/crtdll/stdlib/abs.c rename to reactos/lib/crt/stdlib/abs.c diff --git a/reactos/lib/msvcrt/stdlib/atexit.c b/reactos/lib/crt/stdlib/atexit.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/atexit.c rename to reactos/lib/crt/stdlib/atexit.c diff --git a/reactos/lib/crtdll/stdlib/atof.c b/reactos/lib/crt/stdlib/atof.c similarity index 100% rename from reactos/lib/crtdll/stdlib/atof.c rename to reactos/lib/crt/stdlib/atof.c diff --git a/reactos/lib/crtdll/stdlib/atoi.c b/reactos/lib/crt/stdlib/atoi.c similarity index 100% rename from reactos/lib/crtdll/stdlib/atoi.c rename to reactos/lib/crt/stdlib/atoi.c diff --git a/reactos/lib/msvcrt/stdlib/atoi64.c b/reactos/lib/crt/stdlib/atoi64.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/atoi64.c rename to reactos/lib/crt/stdlib/atoi64.c diff --git a/reactos/lib/crtdll/stdlib/atol.c b/reactos/lib/crt/stdlib/atol.c similarity index 100% rename from reactos/lib/crtdll/stdlib/atol.c rename to reactos/lib/crt/stdlib/atol.c diff --git a/reactos/lib/crtdll/stdlib/atold.c b/reactos/lib/crt/stdlib/atold.c similarity index 100% rename from reactos/lib/crtdll/stdlib/atold.c rename to reactos/lib/crt/stdlib/atold.c diff --git a/reactos/lib/crtdll/stdlib/bsearch.c b/reactos/lib/crt/stdlib/bsearch.c similarity index 100% rename from reactos/lib/crtdll/stdlib/bsearch.c rename to reactos/lib/crt/stdlib/bsearch.c diff --git a/reactos/lib/crtdll/stdlib/div.c b/reactos/lib/crt/stdlib/div.c similarity index 100% rename from reactos/lib/crtdll/stdlib/div.c rename to reactos/lib/crt/stdlib/div.c diff --git a/reactos/lib/msvcrt/stdlib/doserrmap.h b/reactos/lib/crt/stdlib/doserrmap.h similarity index 100% rename from reactos/lib/msvcrt/stdlib/doserrmap.h rename to reactos/lib/crt/stdlib/doserrmap.h diff --git a/reactos/lib/crtdll/stdlib/ecvt.c b/reactos/lib/crt/stdlib/ecvt.c similarity index 100% rename from reactos/lib/crtdll/stdlib/ecvt.c rename to reactos/lib/crt/stdlib/ecvt.c diff --git a/reactos/lib/crtdll/stdlib/ecvtbuf.c b/reactos/lib/crt/stdlib/ecvtbuf.c similarity index 100% rename from reactos/lib/crtdll/stdlib/ecvtbuf.c rename to reactos/lib/crt/stdlib/ecvtbuf.c diff --git a/reactos/lib/msvcrt/stdlib/errno.c b/reactos/lib/crt/stdlib/errno.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/errno.c rename to reactos/lib/crt/stdlib/errno.c diff --git a/reactos/lib/crtdll/stdlib/fcvt.c b/reactos/lib/crt/stdlib/fcvt.c similarity index 100% rename from reactos/lib/crtdll/stdlib/fcvt.c rename to reactos/lib/crt/stdlib/fcvt.c diff --git a/reactos/lib/crtdll/stdlib/fcvtbuf.c b/reactos/lib/crt/stdlib/fcvtbuf.c similarity index 100% rename from reactos/lib/crtdll/stdlib/fcvtbuf.c rename to reactos/lib/crt/stdlib/fcvtbuf.c diff --git a/reactos/lib/msvcrt/stdlib/fullpath.c b/reactos/lib/crt/stdlib/fullpath.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/fullpath.c rename to reactos/lib/crt/stdlib/fullpath.c diff --git a/reactos/lib/crtdll/stdlib/gcvt.c b/reactos/lib/crt/stdlib/gcvt.c similarity index 100% rename from reactos/lib/crtdll/stdlib/gcvt.c rename to reactos/lib/crt/stdlib/gcvt.c diff --git a/reactos/lib/msvcrt/stdlib/getenv.c b/reactos/lib/crt/stdlib/getenv.c similarity index 82% rename from reactos/lib/msvcrt/stdlib/getenv.c rename to reactos/lib/crt/stdlib/getenv.c index ba704782643..71d91b18afc 100644 --- a/reactos/lib/msvcrt/stdlib/getenv.c +++ b/reactos/lib/crt/stdlib/getenv.c @@ -18,7 +18,7 @@ char *getenv(const char *name) { char *str = *environ; char *pos = strchr(str,'='); - if (pos && ((pos - str) == length) && !strnicmp(str, name, length)) + if (pos && ((pos - str) == length) && !_strnicmp(str, name, length)) return pos + 1; } return NULL; @@ -36,7 +36,7 @@ wchar_t *_wgetenv(const wchar_t *name) { wchar_t *str = *environ; wchar_t *pos = wcschr(str, L'='); - if (pos && ((pos - str) == length) && !wcsnicmp(str, name, length)) + if (pos && ((pos - str) == length) && !_wcsnicmp(str, name, length)) return pos + 1; } return NULL; diff --git a/reactos/lib/msvcrt/stdlib/itoa.c b/reactos/lib/crt/stdlib/itoa.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/itoa.c rename to reactos/lib/crt/stdlib/itoa.c diff --git a/reactos/lib/msvcrt/stdlib/itow.c b/reactos/lib/crt/stdlib/itow.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/itow.c rename to reactos/lib/crt/stdlib/itow.c diff --git a/reactos/lib/crtdll/stdlib/labs.c b/reactos/lib/crt/stdlib/labs.c similarity index 100% rename from reactos/lib/crtdll/stdlib/labs.c rename to reactos/lib/crt/stdlib/labs.c diff --git a/reactos/lib/crtdll/stdlib/ldiv.c b/reactos/lib/crt/stdlib/ldiv.c similarity index 100% rename from reactos/lib/crtdll/stdlib/ldiv.c rename to reactos/lib/crt/stdlib/ldiv.c diff --git a/reactos/lib/msvcrt/stdlib/makepath.c b/reactos/lib/crt/stdlib/makepath.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/makepath.c rename to reactos/lib/crt/stdlib/makepath.c diff --git a/reactos/lib/msvcrt/stdlib/malloc.c b/reactos/lib/crt/stdlib/malloc.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/malloc.c rename to reactos/lib/crt/stdlib/malloc.c diff --git a/reactos/lib/msvcrt/stdlib/mbstowcs.c b/reactos/lib/crt/stdlib/mbstowcs.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/mbstowcs.c rename to reactos/lib/crt/stdlib/mbstowcs.c diff --git a/reactos/lib/msvcrt/stdlib/mbtowc.c b/reactos/lib/crt/stdlib/mbtowc.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/mbtowc.c rename to reactos/lib/crt/stdlib/mbtowc.c diff --git a/reactos/lib/crtdll/stdlib/obsol.c b/reactos/lib/crt/stdlib/obsol.c similarity index 100% rename from reactos/lib/crtdll/stdlib/obsol.c rename to reactos/lib/crt/stdlib/obsol.c diff --git a/reactos/lib/msvcrt/stdlib/putenv.c b/reactos/lib/crt/stdlib/putenv.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/putenv.c rename to reactos/lib/crt/stdlib/putenv.c diff --git a/reactos/lib/msvcrt/stdlib/qsort.c b/reactos/lib/crt/stdlib/qsort.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/qsort.c rename to reactos/lib/crt/stdlib/qsort.c diff --git a/reactos/lib/msvcrt/stdlib/rand.c b/reactos/lib/crt/stdlib/rand.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/rand.c rename to reactos/lib/crt/stdlib/rand.c diff --git a/reactos/lib/msvcrt/stdlib/rot.c b/reactos/lib/crt/stdlib/rot.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/rot.c rename to reactos/lib/crt/stdlib/rot.c diff --git a/reactos/lib/msvcrt/stdlib/senv.c b/reactos/lib/crt/stdlib/senv.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/senv.c rename to reactos/lib/crt/stdlib/senv.c diff --git a/reactos/lib/msvcrt/stdlib/splitp.c b/reactos/lib/crt/stdlib/splitp.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/splitp.c rename to reactos/lib/crt/stdlib/splitp.c diff --git a/reactos/lib/crtdll/stdlib/strtod.c b/reactos/lib/crt/stdlib/strtod.c similarity index 100% rename from reactos/lib/crtdll/stdlib/strtod.c rename to reactos/lib/crt/stdlib/strtod.c diff --git a/reactos/lib/msvcrt/stdlib/strtol.c b/reactos/lib/crt/stdlib/strtol.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/strtol.c rename to reactos/lib/crt/stdlib/strtol.c diff --git a/reactos/lib/msvcrt/stdlib/strtold.c b/reactos/lib/crt/stdlib/strtold.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/strtold.c rename to reactos/lib/crt/stdlib/strtold.c diff --git a/reactos/lib/msvcrt/stdlib/strtoll.c b/reactos/lib/crt/stdlib/strtoll.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/strtoll.c rename to reactos/lib/crt/stdlib/strtoll.c diff --git a/reactos/lib/msvcrt/stdlib/strtoul.c b/reactos/lib/crt/stdlib/strtoul.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/strtoul.c rename to reactos/lib/crt/stdlib/strtoul.c diff --git a/reactos/lib/msvcrt/stdlib/strtoull.c b/reactos/lib/crt/stdlib/strtoull.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/strtoull.c rename to reactos/lib/crt/stdlib/strtoull.c diff --git a/reactos/lib/msvcrt/stdlib/swab.c b/reactos/lib/crt/stdlib/swab.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/swab.c rename to reactos/lib/crt/stdlib/swab.c diff --git a/reactos/lib/msvcrt/stdlib/wcstod.c b/reactos/lib/crt/stdlib/wcstod.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wcstod.c rename to reactos/lib/crt/stdlib/wcstod.c diff --git a/reactos/lib/msvcrt/stdlib/wcstol.c b/reactos/lib/crt/stdlib/wcstol.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wcstol.c rename to reactos/lib/crt/stdlib/wcstol.c diff --git a/reactos/lib/msvcrt/stdlib/wcstom.c b/reactos/lib/crt/stdlib/wcstom.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wcstom.c rename to reactos/lib/crt/stdlib/wcstom.c diff --git a/reactos/lib/msvcrt/stdlib/wcstomb.c b/reactos/lib/crt/stdlib/wcstomb.c similarity index 72% rename from reactos/lib/msvcrt/stdlib/wcstomb.c rename to reactos/lib/crt/stdlib/wcstomb.c index 32a3a43cff0..c0b5d997b18 100644 --- a/reactos/lib/msvcrt/stdlib/wcstomb.c +++ b/reactos/lib/crt/stdlib/wcstomb.c @@ -46,6 +46,32 @@ static const unsigned char encoding_byte[] = size_t __wcrtomb (char *s, wchar_t wc); +/* + * Convert WCHAR into its multibyte character representation, + * putting this in S and returning its length. + * + * Attention: this function should NEVER be intentionally used. + * The interface is completely stupid. The state is shared between + * all conversion functions. You should use instead the restartable + * version `wcrtomb'. + * + * @implemented + */ +int +wctomb (char *s, wchar_t wchar) +{ + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. This is nonsense because any multibyte encoding has a + state. The ISO C amendment 1 corrects this while introducing the + restartable functions. We simply say here all encodings have a + state. */ + if (s == NULL) + return 1; + + return __wcrtomb (s, wchar); +} + size_t __wcrtomb (char *s, wchar_t wc) diff --git a/reactos/lib/msvcrt/stdlib/wcstombs.c b/reactos/lib/crt/stdlib/wcstombs.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wcstombs.c rename to reactos/lib/crt/stdlib/wcstombs.c diff --git a/reactos/lib/msvcrt/stdlib/wcstoul.c b/reactos/lib/crt/stdlib/wcstoul.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wcstoul.c rename to reactos/lib/crt/stdlib/wcstoul.c diff --git a/reactos/lib/msvcrt/stdlib/wctomb.c b/reactos/lib/crt/stdlib/wctomb.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wctomb.c rename to reactos/lib/crt/stdlib/wctomb.c diff --git a/reactos/lib/msvcrt/stdlib/wfulpath.c b/reactos/lib/crt/stdlib/wfulpath.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wfulpath.c rename to reactos/lib/crt/stdlib/wfulpath.c diff --git a/reactos/lib/msvcrt/stdlib/witoa.c b/reactos/lib/crt/stdlib/witoa.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/witoa.c rename to reactos/lib/crt/stdlib/witoa.c diff --git a/reactos/lib/msvcrt/stdlib/witow.c b/reactos/lib/crt/stdlib/witow.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/witow.c rename to reactos/lib/crt/stdlib/witow.c diff --git a/reactos/lib/msvcrt/stdlib/wmakpath.c b/reactos/lib/crt/stdlib/wmakpath.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wmakpath.c rename to reactos/lib/crt/stdlib/wmakpath.c diff --git a/reactos/lib/msvcrt/stdlib/wputenv.c b/reactos/lib/crt/stdlib/wputenv.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wputenv.c rename to reactos/lib/crt/stdlib/wputenv.c diff --git a/reactos/lib/msvcrt/stdlib/wsenv.c b/reactos/lib/crt/stdlib/wsenv.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wsenv.c rename to reactos/lib/crt/stdlib/wsenv.c diff --git a/reactos/lib/msvcrt/stdlib/wsplitp.c b/reactos/lib/crt/stdlib/wsplitp.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wsplitp.c rename to reactos/lib/crt/stdlib/wsplitp.c diff --git a/reactos/lib/msvcrt/stdlib/wtoi.c b/reactos/lib/crt/stdlib/wtoi.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wtoi.c rename to reactos/lib/crt/stdlib/wtoi.c diff --git a/reactos/lib/msvcrt/stdlib/wtoi64.c b/reactos/lib/crt/stdlib/wtoi64.c similarity index 100% rename from reactos/lib/msvcrt/stdlib/wtoi64.c rename to reactos/lib/crt/stdlib/wtoi64.c diff --git a/reactos/lib/msvcrt/string/lasttok.c b/reactos/lib/crt/string/lasttok.c similarity index 100% rename from reactos/lib/msvcrt/string/lasttok.c rename to reactos/lib/crt/string/lasttok.c diff --git a/reactos/lib/msvcrt/string/memicmp.c b/reactos/lib/crt/string/memicmp.c similarity index 100% rename from reactos/lib/msvcrt/string/memicmp.c rename to reactos/lib/crt/string/memicmp.c diff --git a/reactos/lib/msvcrt/string/strcoll.c b/reactos/lib/crt/string/strcoll.c similarity index 100% rename from reactos/lib/msvcrt/string/strcoll.c rename to reactos/lib/crt/string/strcoll.c diff --git a/reactos/lib/msvcrt/string/strdup.c b/reactos/lib/crt/string/strdup.c similarity index 100% rename from reactos/lib/msvcrt/string/strdup.c rename to reactos/lib/crt/string/strdup.c diff --git a/reactos/lib/msvcrt/string/strerror.c b/reactos/lib/crt/string/strerror.c similarity index 100% rename from reactos/lib/msvcrt/string/strerror.c rename to reactos/lib/crt/string/strerror.c diff --git a/reactos/lib/msvcrt/string/stricmp.c b/reactos/lib/crt/string/stricmp.c similarity index 100% rename from reactos/lib/msvcrt/string/stricmp.c rename to reactos/lib/crt/string/stricmp.c diff --git a/reactos/lib/msvcrt/string/strlwr.c b/reactos/lib/crt/string/strlwr.c similarity index 100% rename from reactos/lib/msvcrt/string/strlwr.c rename to reactos/lib/crt/string/strlwr.c diff --git a/reactos/lib/msvcrt/string/strncoll.c b/reactos/lib/crt/string/strncoll.c similarity index 100% rename from reactos/lib/msvcrt/string/strncoll.c rename to reactos/lib/crt/string/strncoll.c diff --git a/reactos/lib/msvcrt/string/strnicmp.c b/reactos/lib/crt/string/strnicmp.c similarity index 100% rename from reactos/lib/msvcrt/string/strnicmp.c rename to reactos/lib/crt/string/strnicmp.c diff --git a/reactos/lib/msvcrt/string/strpbrk.c b/reactos/lib/crt/string/strpbrk.c similarity index 100% rename from reactos/lib/msvcrt/string/strpbrk.c rename to reactos/lib/crt/string/strpbrk.c diff --git a/reactos/lib/msvcrt/string/strrev.c b/reactos/lib/crt/string/strrev.c similarity index 100% rename from reactos/lib/msvcrt/string/strrev.c rename to reactos/lib/crt/string/strrev.c diff --git a/reactos/lib/msvcrt/string/strset.c b/reactos/lib/crt/string/strset.c similarity index 100% rename from reactos/lib/msvcrt/string/strset.c rename to reactos/lib/crt/string/strset.c diff --git a/reactos/lib/msvcrt/string/strstr.c b/reactos/lib/crt/string/strstr.c similarity index 100% rename from reactos/lib/msvcrt/string/strstr.c rename to reactos/lib/crt/string/strstr.c diff --git a/reactos/lib/msvcrt/string/strtok.c b/reactos/lib/crt/string/strtok.c similarity index 100% rename from reactos/lib/msvcrt/string/strtok.c rename to reactos/lib/crt/string/strtok.c diff --git a/reactos/lib/msvcrt/string/strupr.c b/reactos/lib/crt/string/strupr.c similarity index 100% rename from reactos/lib/msvcrt/string/strupr.c rename to reactos/lib/crt/string/strupr.c diff --git a/reactos/lib/msvcrt/string/strxfrm.c b/reactos/lib/crt/string/strxfrm.c similarity index 100% rename from reactos/lib/msvcrt/string/strxfrm.c rename to reactos/lib/crt/string/strxfrm.c diff --git a/reactos/lib/msvcrt/sys_stat/fstat.c b/reactos/lib/crt/sys_stat/fstat.c similarity index 100% rename from reactos/lib/msvcrt/sys_stat/fstat.c rename to reactos/lib/crt/sys_stat/fstat.c diff --git a/reactos/lib/msvcrt/sys_stat/fstati64.c b/reactos/lib/crt/sys_stat/fstati64.c similarity index 100% rename from reactos/lib/msvcrt/sys_stat/fstati64.c rename to reactos/lib/crt/sys_stat/fstati64.c diff --git a/reactos/lib/msvcrt/sys_stat/futime.c b/reactos/lib/crt/sys_stat/futime.c similarity index 100% rename from reactos/lib/msvcrt/sys_stat/futime.c rename to reactos/lib/crt/sys_stat/futime.c diff --git a/reactos/lib/msvcrt/sys_stat/stat.c b/reactos/lib/crt/sys_stat/stat.c similarity index 100% rename from reactos/lib/msvcrt/sys_stat/stat.c rename to reactos/lib/crt/sys_stat/stat.c diff --git a/reactos/lib/crtdll/sys_stat/systime.c b/reactos/lib/crt/sys_stat/systime.c similarity index 95% rename from reactos/lib/crtdll/sys_stat/systime.c rename to reactos/lib/crt/sys_stat/systime.c index 0fa73435a99..59ecdc9d9ac 100644 --- a/reactos/lib/crtdll/sys_stat/systime.c +++ b/reactos/lib/crt/sys_stat/systime.c @@ -1,70 +1,70 @@ -#include "precomp.h" -#include - - -int month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31}; - -/* - * @unimplemented - */ -unsigned int _getsystime(struct tm* tp) -{ - SYSTEMTIME Time; - int i; - - GetLocalTime(&Time); - - tp->tm_year = Time.wYear - 1900; - tp->tm_mon = Time.wMonth - 1; - tp->tm_wday = Time.wDayOfWeek; - tp->tm_mday = Time.wDay; - tp->tm_hour = Time.wHour; - tp->tm_min = Time.wMinute; - tp->tm_sec = Time.wSecond; - - tp->tm_isdst = -1; - - //FIXME GetTimeZoneInformation currently not in kernel32 - - //TimeZoneId = GetTimeZoneInformation(&TimeZoneInformation ); - //if ( TimeZoneId == TIME_ZONE_ID_DAYLIGHT ) { - // tp->tm_isdst = 1; - //} - //else - // tp->tm_isdst = 0; - - if (tp->tm_year % 4 == 0) { - if (tp->tm_year % 100 != 0) - tp->tm_yday = 1; - else if ((tp->tm_year-100) % 1000 == 0) - tp->tm_yday = 1; - } - - for (i = 0; i <= tp->tm_mon; i++) - tp->tm_yday += month[i]; - - return Time.wMilliseconds; -} - - -/* - * @implemented - */ -unsigned int _setsystime(struct tm* tp, unsigned int ms) -{ - SYSTEMTIME Time; - - Time.wYear = tp->tm_year + 1900; - Time.wMonth = tp->tm_mon + 1; - Time.wDayOfWeek = tp->tm_wday; - Time.wDay = tp->tm_mday; - Time.wHour = tp->tm_hour; - Time.wMinute = tp->tm_min; - Time.wSecond = tp->tm_sec; - Time.wMilliseconds = ms; - - if (!SetLocalTime(&Time)) - return -1; - - return 0; -} +#include "precomp.h" +#include + + +int month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31}; + +/* + * @unimplemented + */ +unsigned int _getsystime(struct tm* tp) +{ + SYSTEMTIME Time; + int i; + + GetLocalTime(&Time); + + tp->tm_year = Time.wYear - 1900; + tp->tm_mon = Time.wMonth - 1; + tp->tm_wday = Time.wDayOfWeek; + tp->tm_mday = Time.wDay; + tp->tm_hour = Time.wHour; + tp->tm_min = Time.wMinute; + tp->tm_sec = Time.wSecond; + + tp->tm_isdst = -1; + + //FIXME GetTimeZoneInformation currently not in kernel32 + + //TimeZoneId = GetTimeZoneInformation(&TimeZoneInformation ); + //if ( TimeZoneId == TIME_ZONE_ID_DAYLIGHT ) { + // tp->tm_isdst = 1; + //} + //else + // tp->tm_isdst = 0; + + if (tp->tm_year % 4 == 0) { + if (tp->tm_year % 100 != 0) + tp->tm_yday = 1; + else if ((tp->tm_year-100) % 1000 == 0) + tp->tm_yday = 1; + } + + for (i = 0; i <= tp->tm_mon; i++) + tp->tm_yday += month[i]; + + return Time.wMilliseconds; +} + + +/* + * @implemented + */ +unsigned int _setsystime(struct tm* tp, unsigned int ms) +{ + SYSTEMTIME Time; + + Time.wYear = tp->tm_year + 1900; + Time.wMonth = tp->tm_mon + 1; + Time.wDayOfWeek = tp->tm_wday; + Time.wDay = tp->tm_mday; + Time.wHour = tp->tm_hour; + Time.wMinute = tp->tm_min; + Time.wSecond = tp->tm_sec; + Time.wMilliseconds = ms; + + if (!SetLocalTime(&Time)) + return -1; + + return 0; +} diff --git a/reactos/lib/msvcrt/sys_stat/wstat.c b/reactos/lib/crt/sys_stat/wstat.c similarity index 100% rename from reactos/lib/msvcrt/sys_stat/wstat.c rename to reactos/lib/crt/sys_stat/wstat.c diff --git a/reactos/lib/msvcrt/time/clock.c b/reactos/lib/crt/time/clock.c similarity index 100% rename from reactos/lib/msvcrt/time/clock.c rename to reactos/lib/crt/time/clock.c diff --git a/reactos/lib/msvcrt/time/ctime.c b/reactos/lib/crt/time/ctime.c similarity index 100% rename from reactos/lib/msvcrt/time/ctime.c rename to reactos/lib/crt/time/ctime.c diff --git a/reactos/lib/crtdll/time/difftime.c b/reactos/lib/crt/time/difftime.c similarity index 100% rename from reactos/lib/crtdll/time/difftime.c rename to reactos/lib/crt/time/difftime.c diff --git a/reactos/lib/msvcrt/time/ftime.c b/reactos/lib/crt/time/ftime.c similarity index 100% rename from reactos/lib/msvcrt/time/ftime.c rename to reactos/lib/crt/time/ftime.c diff --git a/reactos/lib/crtdll/time/posixrul.h b/reactos/lib/crt/time/posixrul.h similarity index 100% rename from reactos/lib/crtdll/time/posixrul.h rename to reactos/lib/crt/time/posixrul.h diff --git a/reactos/lib/msvcrt/time/strdate.c b/reactos/lib/crt/time/strdate.c similarity index 100% rename from reactos/lib/msvcrt/time/strdate.c rename to reactos/lib/crt/time/strdate.c diff --git a/reactos/lib/msvcrt/time/strftime.c b/reactos/lib/crt/time/strftime.c similarity index 100% rename from reactos/lib/msvcrt/time/strftime.c rename to reactos/lib/crt/time/strftime.c diff --git a/reactos/lib/msvcrt/time/strtime.c b/reactos/lib/crt/time/strtime.c similarity index 100% rename from reactos/lib/msvcrt/time/strtime.c rename to reactos/lib/crt/time/strtime.c diff --git a/reactos/lib/msvcrt/time/time.c b/reactos/lib/crt/time/time.c similarity index 100% rename from reactos/lib/msvcrt/time/time.c rename to reactos/lib/crt/time/time.c diff --git a/reactos/lib/msvcrt/time/tz_vars.c b/reactos/lib/crt/time/tz_vars.c similarity index 100% rename from reactos/lib/msvcrt/time/tz_vars.c rename to reactos/lib/crt/time/tz_vars.c diff --git a/reactos/lib/crtdll/time/tzfile.h b/reactos/lib/crt/time/tzfile.h similarity index 100% rename from reactos/lib/crtdll/time/tzfile.h rename to reactos/lib/crt/time/tzfile.h diff --git a/reactos/lib/msvcrt/time/wctime.c b/reactos/lib/crt/time/wctime.c similarity index 100% rename from reactos/lib/msvcrt/time/wctime.c rename to reactos/lib/crt/time/wctime.c diff --git a/reactos/lib/msvcrt/time/wstrdate.c b/reactos/lib/crt/time/wstrdate.c similarity index 100% rename from reactos/lib/msvcrt/time/wstrdate.c rename to reactos/lib/crt/time/wstrdate.c diff --git a/reactos/lib/msvcrt/time/wstrtime.c b/reactos/lib/crt/time/wstrtime.c similarity index 100% rename from reactos/lib/msvcrt/time/wstrtime.c rename to reactos/lib/crt/time/wstrtime.c diff --git a/reactos/lib/msvcrt/wine/cpp.c b/reactos/lib/crt/wine/cpp.c similarity index 99% rename from reactos/lib/msvcrt/wine/cpp.c rename to reactos/lib/crt/wine/cpp.c index 1f6ea81d37a..1065cdc7c61 100644 --- a/reactos/lib/msvcrt/wine/cpp.c +++ b/reactos/lib/crt/wine/cpp.c @@ -35,8 +35,8 @@ #include "msvcrt/malloc.h" #include "msvcrt/stdlib.h" -#include "msvcrt.h" -#include "cppexcept.h" +#include +#include #include WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); diff --git a/reactos/lib/msvcrt/wine/cppexcept.c b/reactos/lib/crt/wine/cppexcept.c similarity index 99% rename from reactos/lib/msvcrt/wine/cppexcept.c rename to reactos/lib/crt/wine/cppexcept.c index e8bb106fe29..98c4bcf7660 100644 --- a/reactos/lib/msvcrt/wine/cppexcept.c +++ b/reactos/lib/crt/wine/cppexcept.c @@ -32,12 +32,12 @@ #include "winbase.h" #include "winreg.h" #include "wine/winternl.h" -#include "msvcrt.h" +#include #include "wine/exception.h" #include "excpt.h" #include "wine/debug.h" -#include "cppexcept.h" +#include WINE_DEFAULT_DEBUG_CHANNEL(seh); diff --git a/reactos/lib/msvcrt/wine/heap.c b/reactos/lib/crt/wine/heap.c similarity index 93% rename from reactos/lib/msvcrt/wine/heap.c rename to reactos/lib/crt/wine/heap.c index 77217e23127..54f7a762ae7 100644 --- a/reactos/lib/msvcrt/wine/heap.c +++ b/reactos/lib/crt/wine/heap.c @@ -119,3 +119,13 @@ int MSVCRT__set_new_mode(int mode) UNLOCK_HEAP; return old_mode; } + +/********************************************************************* + * _heapadd (MSVCRT.@) + */ +int _heapadd(void* mem, size_t size) +{ + TRACE("(%p,%d) unsupported in Win32\n", mem,size); + *_errno() = ENOSYS; + return -1; +} diff --git a/reactos/lib/msvcrt/wine/thread.c b/reactos/lib/crt/wine/thread.c similarity index 99% rename from reactos/lib/msvcrt/wine/thread.c rename to reactos/lib/crt/wine/thread.c index 92ee285e591..f8b9a579574 100644 --- a/reactos/lib/msvcrt/wine/thread.c +++ b/reactos/lib/crt/wine/thread.c @@ -19,7 +19,7 @@ */ #include "precomp.h" -#include "msvcrt.h" +#include #include "msvcrt/malloc.h" #include "msvcrt/process.h" diff --git a/reactos/lib/msvcrt/wstring/wcscoll.c b/reactos/lib/crt/wstring/wcscoll.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcscoll.c rename to reactos/lib/crt/wstring/wcscoll.c diff --git a/reactos/lib/msvcrt/wstring/wcscspn.c b/reactos/lib/crt/wstring/wcscspn.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcscspn.c rename to reactos/lib/crt/wstring/wcscspn.c diff --git a/reactos/lib/msvcrt/wstring/wcsdup.c b/reactos/lib/crt/wstring/wcsdup.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsdup.c rename to reactos/lib/crt/wstring/wcsdup.c diff --git a/reactos/lib/msvcrt/wstring/wcsicmp.c b/reactos/lib/crt/wstring/wcsicmp.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsicmp.c rename to reactos/lib/crt/wstring/wcsicmp.c diff --git a/reactos/lib/msvcrt/wstring/wcslwr.c b/reactos/lib/crt/wstring/wcslwr.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcslwr.c rename to reactos/lib/crt/wstring/wcslwr.c diff --git a/reactos/lib/msvcrt/wstring/wcsnicmp.c b/reactos/lib/crt/wstring/wcsnicmp.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsnicmp.c rename to reactos/lib/crt/wstring/wcsnicmp.c diff --git a/reactos/lib/msvcrt/wstring/wcspbrk.c b/reactos/lib/crt/wstring/wcspbrk.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcspbrk.c rename to reactos/lib/crt/wstring/wcspbrk.c diff --git a/reactos/lib/msvcrt/wstring/wcsrev.c b/reactos/lib/crt/wstring/wcsrev.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsrev.c rename to reactos/lib/crt/wstring/wcsrev.c diff --git a/reactos/lib/msvcrt/wstring/wcsset.c b/reactos/lib/crt/wstring/wcsset.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsset.c rename to reactos/lib/crt/wstring/wcsset.c diff --git a/reactos/lib/msvcrt/wstring/wcsspn.c b/reactos/lib/crt/wstring/wcsspn.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsspn.c rename to reactos/lib/crt/wstring/wcsspn.c diff --git a/reactos/lib/msvcrt/wstring/wcsstr.c b/reactos/lib/crt/wstring/wcsstr.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsstr.c rename to reactos/lib/crt/wstring/wcsstr.c diff --git a/reactos/lib/msvcrt/wstring/wcstok.c b/reactos/lib/crt/wstring/wcstok.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcstok.c rename to reactos/lib/crt/wstring/wcstok.c diff --git a/reactos/lib/msvcrt/wstring/wcsupr.c b/reactos/lib/crt/wstring/wcsupr.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsupr.c rename to reactos/lib/crt/wstring/wcsupr.c diff --git a/reactos/lib/msvcrt/wstring/wcsxfrm.c b/reactos/lib/crt/wstring/wcsxfrm.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wcsxfrm.c rename to reactos/lib/crt/wstring/wcsxfrm.c diff --git a/reactos/lib/msvcrt/wstring/wlasttok.c b/reactos/lib/crt/wstring/wlasttok.c similarity index 100% rename from reactos/lib/msvcrt/wstring/wlasttok.c rename to reactos/lib/crt/wstring/wlasttok.c diff --git a/reactos/lib/crtdll/conio/cgets.c b/reactos/lib/crtdll/conio/cgets.c deleted file mode 100644 index fed3024a259..00000000000 --- a/reactos/lib/crtdll/conio/cgets.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include - - -/* - * @implemented - */ -char* _cgets(char *string) -{ - unsigned len = 0; - unsigned int maxlen_wanted; - char *sp; - int c; - /* - * Be smart and check for NULL pointer. - * Don't know wether TURBOC does this. - */ - if (!string) - return(NULL); - maxlen_wanted = (unsigned int)((unsigned char)string[0]); - sp = &(string[2]); - /* - * Should the string be shorter maxlen_wanted including or excluding - * the trailing '\0' ? We don't take any risk. - */ - while(len < maxlen_wanted-1) - { - c=_getch(); - /* - * shold we check for backspace here? - * TURBOC does (just checked) but doesn't in cscanf (thats harder - * or even impossible). We do the same. - */ - if (c == '\b') - { - if (len > 0) - { - _cputs("\b \b"); /* go back, clear char on screen with space - and go back again */ - len--; - sp[len] = '\0'; /* clear the character in the string */ - } - } - else if (c == '\r') - { - sp[len] = '\0'; - break; - } - else if (c == 0) - { - /* special character ends input */ - sp[len] = '\0'; - _ungetch(c); /* keep the char for later processing */ - break; - } - else - { - sp[len] = _putch(c); - len++; - } - } - sp[maxlen_wanted-1] = '\0'; - string[1] = (char)((unsigned char)len); - return(sp); -} - - diff --git a/reactos/lib/crtdll/conio/cputs.c b/reactos/lib/crtdll/conio/cputs.c deleted file mode 100644 index 4f7ad5558c1..00000000000 --- a/reactos/lib/crtdll/conio/cputs.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/cputs.c - * PURPOSE: Writes a character to stdout - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -#include "precomp.h" -#include -#include -#include -#include - -/* - * @implemented - */ -int _cputs(const char *_str) -{ - int len = strlen(_str); - DWORD written = 0; - if (!WriteFile(filehnd(stdout->_file),_str,len,&written,NULL)) - return -1; - return 0; -} diff --git a/reactos/lib/crtdll/conio/getch.c b/reactos/lib/crtdll/conio/getch.c deleted file mode 100644 index 02b2906ae3c..00000000000 --- a/reactos/lib/crtdll/conio/getch.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/getch.c - * PURPOSE: Writes a character to stdout - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -#include "precomp.h" -#include -#include -#include -#include - - -/* - * @implemented - */ -int _getch(void) -{ - DWORD NumberOfCharsRead = 0; - char c; - if (char_avail) { - c = ungot_char; - char_avail = 0; - } else { - ReadConsoleA(_get_osfhandle(stdin->_file), - &c, - 1, - &NumberOfCharsRead, - NULL); - } - if (c == 10) - c = 13; - putchar(c); - return c; -} - -#if 0 -/* - * @unimplemented - */ -int _getche(void) -{ - int c; - - c = _getch(); - _putch(c); - - return c; -} -#endif diff --git a/reactos/lib/crtdll/conio/getche.c b/reactos/lib/crtdll/conio/getche.c deleted file mode 100644 index f994649e73d..00000000000 --- a/reactos/lib/crtdll/conio/getche.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/getche.c - * PURPOSE: Reads a character from stdin - * PROGRAMER: DJ Delorie - Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include -#include - - -int getche(void) -{ - if (char_avail) - /* - * We don't know, wether the ungot char was already echoed - * we assume yes (for example in cscanf, probably the only - * place where ungetch is ever called. - * There is no way to check for this really, because - * ungetch could have been called with a character that - * hasn't been got by a conio function. - * We don't echo again. - */ - return(getch()); - return (_putch(getch())); -} diff --git a/reactos/lib/crtdll/conio/kbhit.c b/reactos/lib/crtdll/conio/kbhit.c deleted file mode 100644 index 4c28e4b61f4..00000000000 --- a/reactos/lib/crtdll/conio/kbhit.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/kbhit.c - * PURPOSE: Checks for keyboard hits - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include "precomp.h" -#include -#include - - -// FIXME PeekCosoleInput returns more than keyboard hits - -/* - * @unimplemented - */ -int _kbhit(void) -{ - //INPUT_RECORD InputRecord; - DWORD NumberRead=0; - if (char_avail) - return(1); - else { - //FIXME PeekConsoleInput might do DeviceIo - //PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead); - return NumberRead; - } - return 0; -} diff --git a/reactos/lib/crtdll/conio/putch.c b/reactos/lib/crtdll/conio/putch.c deleted file mode 100644 index 5cf65255a96..00000000000 --- a/reactos/lib/crtdll/conio/putch.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/putch.c - * PURPOSE: Writes a character to stdout - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include "precomp.h" -#include - -/* - * @implemented - */ -int _putch( int c ) -{ - DWORD NumberOfCharsWritten; - - if ( WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),&c,1,&NumberOfCharsWritten,NULL) ) { - return -1; - } - return NumberOfCharsWritten; -} diff --git a/reactos/lib/crtdll/conio/ungetch.c b/reactos/lib/crtdll/conio/ungetch.c deleted file mode 100644 index 6439f9e505a..00000000000 --- a/reactos/lib/crtdll/conio/ungetch.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/ungetch.c - * PURPOSE: Ungets a character from stdin - * PROGRAMER: DJ Delorie - Boudewijn Dekker [ Adapted from djgpp libc ] - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include -#include - -#define EOF -1 - -int char_avail = 0; -int ungot_char = 0; - - -/* - * @implemented - */ -int _ungetch(int c) -{ - if (char_avail) - return(EOF); - ungot_char = c; - char_avail = 1; - return(c); -} diff --git a/reactos/lib/crtdll/crtdll.def b/reactos/lib/crtdll/crtdll.def index 785391ce8cc..a3d8fc6512e 100644 --- a/reactos/lib/crtdll/crtdll.def +++ b/reactos/lib/crtdll/crtdll.def @@ -35,16 +35,16 @@ ; __builtin_new ; __builtin_delete ; _set_new_handler__FPFUi_i -; +; I commented out these, cause i dont get why they were added. -Gunnar ; LIBRARY CRTDLL.DLL EXPORTS -__builtin_new -__builtin_delete -??2@YAPAXI@Z=malloc -??3@YAXPAX@Z=free -?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z=_set_new_handler__FPFUi_i -_set_new_handler__FPFUi_i +;__builtin_new +;__builtin_delete +??2@YAPAXI@Z=MSVCRT_operator_new +??3@YAXPAX@Z=MSVCRT_operator_delete +?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z=MSVCRT__set_new_handler +;_set_new_handler__FPFUi_i _CIacos _CIasin _CIatan @@ -61,31 +61,31 @@ _CIsinh _CIsqrt _CItan _CItanh -_HUGE_dll +_HUGE_dll=_HUGE DATA _XcptFilter __GetMainArgs -__argc_dll -__argv_dll +__argc_dll=__argc DATA +__argv_dll=__argv DATA __dllonexit __doserrno __fpecode -__isascii +__isascii=NTDLL.__isascii __iscsym=NTDLL.__iscsym __iscsymf=NTDLL.__iscsymf -__mb_cur_max_dll +__mb_cur_max_dll=__mb_cur_max DATA __pxcptinfoptrs __threadhandle __threadid __toascii=NTDLL.__toascii _abnormal_termination _access -_acmdln_dll -_aexit_rtn_dll +_acmdln_dll=_acmdln DATA +_aexit_rtn_dll=_aexit_rtn DATA _amsg_exit _assert -_basemajor_dll -_baseminor_dll -_baseversion_dll +_basemajor_dll=CRTDLL__basemajor_dll DATA +_baseminor_dll=CRTDLL__baseminor_dll DATA +_baseversion_dll=CRTDLL__baseversion_dll DATA _beep _beginthread _c_exit @@ -100,23 +100,23 @@ _chsize _clearfp _close _commit -_commode_dll +_commode_dll=_commode DATA _control87 _controlfp _copysign _cprintf -_cpumode_dll +_cpumode_dll=_cpumode DATA ;fixme: wine has CRTDLL__cpumode_dll _cputs _creat _cscanf -_ctype +_ctype DATA _cwait -_daylight_dll +_daylight_dll=_daylight DATA _dup _dup2 _ecvt _endthread -_environ_dll +_environ_dll=_environ DATA _eof _errno _except_handler2 @@ -136,23 +136,23 @@ _fdopen _fgetchar _fgetwchar _filbuf -_fileinfo_dll +;_fileinfo_dll=_fileinfo DATA _filelength -_fileno +_fileno DATA _findclose _findfirst _findnext _finite _flsbuf _flushall -_fmode_dll +_fmode_dll=__fmode DATA _fpclass _fpieee_flt _fpreset _fputchar _fputwchar _fsopen -_fstat +_fstat=CRTDLL__fstat _ftime _ftol=NTDLL._ftol _fullpath @@ -177,7 +177,7 @@ _heapset _heapwalk _hypot _initterm -_iob +_iob DATA _isatty _isctype _ismbbalnum @@ -236,7 +236,7 @@ _mbctokata _mbctolower _mbctombb _mbctoupper -_mbctype +_mbctype DATA _mbsbtype _mbscat _mbschr @@ -282,21 +282,21 @@ _nextafter _onexit _open _open_osfhandle -_osmajor_dll -_osminor_dll -_osmode_dll -_osver_dll -_osversion_dll +_osmajor_dll=CRTDLL__osmajor_dll DATA +_osminor_dll=CRTDLL__osminor_dll DATA +_osmode_dll=CRTDLL__osmode_dll DATA +_osver_dll=_osver DATA +_osversion_dll=CRTDLL__osversion_dll DATA _pclose -_pctype_dll -_pgmptr_dll +_pctype_dll=_pctype DATA +_pgmptr_dll=_pgmptr DATA _pipe _popen _purecall _putch _putenv _putw -_pwctype_dll +_pwctype_dll=_pwctype DATA _read _rmdir _rmtmp @@ -309,8 +309,8 @@ _setjmp _setmode _setsystime _sleep -_snprintf -_snwprintf +_snprintf=crt__snprintf +_snwprintf=crt__snwprintf _sopen _spawnl _spawnle @@ -320,8 +320,8 @@ _spawnv _spawnve _spawnvp _spawnvpe -_splitpath -_stat +_splitpath=NTDLL._splitpath +_stat=CRTDLL__stat _statusfp _strcmpi=NTDLL._strcmpi _strdate @@ -343,14 +343,14 @@ _strspnp _strtime _strupr=NTDLL._strupr _swab -_sys_errlist -_sys_nerr_dll +_sys_errlist DATA +_sys_nerr_dll=_sys_nerr DATA _tell _tempnam -_timezone_dll +_timezone_dll=_timezone _tolower=NTDLL._tolower _toupper=NTDLL._toupper -_tzname +_tzname DATA _tzset _ultoa=NTDLL._ultoa _ultow=NTDLL._ultow @@ -359,8 +359,8 @@ _ungetch _unlink _unloaddll _utime -_vsnprintf -_vsnwprintf +_vsnprintf=crt__vsnprintf +_vsnwprintf=crt__vsnwprintf _wcsdup _wcsicmp _wcsicoll @@ -370,9 +370,9 @@ _wcsnset _wcsrev _wcsset _wcsupr -_winmajor_dll -_winminor_dll -_winver_dll +_winmajor_dll=_winmajor DATA +_winminor_dll=_winminor DATA +_winver_dll=_winver DATA _write _wtoi=NTDLL._wtoi _wtol=NTDLL._wtol @@ -380,29 +380,29 @@ _y0 _y1 _yn abort -abs +abs=NTDLL.abs acos asctime asin -atan +atan=NTDLL.atan atan2 atexit atof -atoi -atol -bsearch +atoi=NTDLL.atoi +atol=NTDLL.atol +bsearch=NTDLL.bsearch calloc -ceil +ceil=NTDLL.ceil clearerr clock -cos +cos=NTDLL.cos cosh ctime difftime div exit exp -fabs +fabs=NTDLL.fabs fclose feof ferror @@ -411,7 +411,7 @@ fgetc fgetpos fgets fgetwc -floor +floor=NTDLL.floor fmod fopen fprintf @@ -435,42 +435,42 @@ getenv gets gmtime is_wctype -isalnum +isalnum=NTDLL.isalnum isalpha=NTDLL.isalpha -iscntrl +iscntrl=NTDLL.iscntrl isdigit=NTDLL.isdigit -isgraph +isgraph=NTDLL.isgraph isleadbyte islower=NTDLL.islower -isprint -ispunct +isprint=NTDLL.isprint +ispunct=NTDLL.ispunct isspace=NTDLL.isspace -isupper +isupper=NTDLL.isupper iswalnum iswalpha=NTDLL.iswalpha iswascii iswcntrl -iswctype -iswdigit +iswctype=NTDLL.iswctype +iswdigit=NTDLL.iswdigit iswgraph -iswlower +iswlower=NTDLL.iswlower iswprint iswpunct iswspace=NTDLL.iswspace iswupper -iswxdigit +iswxdigit=NTDLL.iswxdigit isxdigit=NTDLL.isxdigit -labs +labs=NTDLL.labs ldexp ldiv localeconv localtime -log +log=NTDLL.log log10 longjmp malloc mblen -mbstowcs +mbstowcs=NTDLL.mbstowcs mbtowc memchr=NTDLL.memchr memcmp=NTDLL.memcmp @@ -485,7 +485,7 @@ printf putc putchar puts -qsort +qsort=NTDLL.qsort raise rand realloc @@ -497,15 +497,15 @@ setbuf setlocale setvbuf signal -sin +sin=NTDLL.sin sinh -sprintf -sqrt +sprintf=crt_sprintf +sqrt=NTDLL.sqrt srand -sscanf +sscanf=crt_sscanf strcat strchr -strcmp +strcmp=NTDLL.strcmp strcoll strcpy strcspn @@ -521,27 +521,27 @@ strspn strstr=NTDLL.strstr strtod strtok -strtol +strtol=NTDLL.strtol strtoul strxfrm -swprintf +swprintf=crt_swprintf swscanf system -tan +tan=NTDLL.tan tanh time tmpfile tmpnam tolower=NTDLL.tolower toupper=NTDLL.toupper -towlower -towupper +towlower=NTDLL.towlower +towupper=NTDLL.towupper ungetc ungetwc vfprintf vfwprintf vprintf -vsprintf +vsprintf=crt_vsprintf vswprintf vwprintf wcscat @@ -561,9 +561,9 @@ wcsspn wcsstr wcstod wcstok -wcstol +wcstol=NTDLL.wcstol wcstombs -wcstoul +wcstoul=NTDLL.wcstoul wcsxfrm wctomb wprintf diff --git a/reactos/lib/crtdll/crtdll.xml b/reactos/lib/crtdll/crtdll.xml index ff573f5c8a3..31accdf9221 100644 --- a/reactos/lib/crtdll/crtdll.xml +++ b/reactos/lib/crtdll/crtdll.xml @@ -14,138 +14,6 @@ kernel32 ntdll crt - - isctype.c - - - abnorter.c - exhand2.c - matherr.c - unwind.c - - - create.c - dup.c - eof.c - find.c - fmode.c - lseek.c - open.c - pipe.c - read.c - unlink.c - write.c - - - acosh.c - asinh.c - atanh.c - ceil.c - floor.c - huge_val.c - - - expand.c - heap.c - - - amsg.c - debug.c - dllmain.c - GetArgs.c - purecall.c - setnew.c - - - _cwait.c - _system.c - spawnl.c - spawnlp.c - spawnlpe.c - spawnvp.c - spawnv.c - spawnve.c - spawnle.c - execl.c - execlp.c - execlpe.c - execvpe.c - execvp.c - execv.c - execle.c - execve.c - thread.c - - - xcptfil.c - xcptinfo.c - - - getenv.c - ferror.c - fflush.c - fgetchar.c - fgets.c - filbuf.c - fileno.c - fopen.c - fputchar.c - fputs.c - fread.c - freopen.c - fscanf.c - frlist.c - fsopen.c - ftell.c - fwrite.c - getc.c - getchar.c - gets.c - getw.c - popen.c - printf.c - putc.c - putchar.c - puts.c - remove.c - setbuffe.c - setlineb.c - stdiohk.c - - - errno.c - fullpath.c - itow.c - malloc.c - mbstowcs.c - putenv.c - rand.c - wcstomb.c - - - lasttok.c - strerror.c - - - fstat.c - ftime.c - systime.c - stat.c - - - strdec.c - strinc.c - strninc.c - strncnt.c - strnextc.c - strspnp.c - - - tz_vars.c - - - wlasttok.c - wcscoll.c - + dllmain.c crtdll.rc diff --git a/reactos/lib/crtdll/ctype/isctype.c b/reactos/lib/crtdll/ctype/isctype.c deleted file mode 100644 index 2629ccfb9b0..00000000000 --- a/reactos/lib/crtdll/ctype/isctype.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - -extern unsigned short _ctype[]; - -unsigned short *_pctype_dll = _ctype + 1; -unsigned short *_pwctype_dll = _ctype + 1; - - -/* - * @implemented - */ -int _isctype(unsigned int c, int ctypeFlags) -{ - return (_pctype_dll[(unsigned char)(c & 0xFF)] & ctypeFlags); -} - -/* - * @implemented - */ -int iswctype(wint_t wc, wctype_t wctypeFlags) -{ - return (_pwctype_dll[(unsigned char)(wc & 0xFF)] & wctypeFlags); -} - -/* - * @implemented - */ -int is_wctype(wint_t wc, wctype_t wctypeFlags) -{ - return (_pwctype_dll[(unsigned char)(wc & 0xFF)] & wctypeFlags); -} - -/* EOF */ diff --git a/reactos/lib/crtdll/direct/mkdir.c b/reactos/lib/crtdll/direct/mkdir.c deleted file mode 100644 index 15e85d3f197..00000000000 --- a/reactos/lib/crtdll/direct/mkdir.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "precomp.h" -#include - - -/* - * @implemented - */ -int _mkdir(const char* _path) -{ - if (!CreateDirectoryA(_path, NULL)) - return -1; - return 0; -} diff --git a/reactos/lib/crtdll/dllmain.c b/reactos/lib/crtdll/dllmain.c new file mode 100644 index 00000000000..3607c4b9fb1 --- /dev/null +++ b/reactos/lib/crtdll/dllmain.c @@ -0,0 +1,296 @@ +/* $Id: dllmain.c 12852 2005-01-06 13:58:04Z mf $ + * + * dllmain.c + * + * ReactOS MSVCRT.DLL Compatibility Library + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision: 1.24 $ + * $Author: mf $ + * $Date: 2005-01-06 14:58:04 +0100 (Thu, 06 Jan 2005) $ + * + */ + +#include "precomp.h" +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* EXTERNAL PROTOTYPES ********************************************************/ + +//void __fileno_init(void); +extern BOOL __fileno_init(void); +extern int BlockEnvToEnvironA(void); +extern int BlockEnvToEnvironW(void); +extern void FreeEnvironment(char **environment); + +extern unsigned int _osver; +extern unsigned int _winminor; +extern unsigned int _winmajor; +extern unsigned int _winver; + +unsigned int CRTDLL__basemajor_dll; +unsigned int CRTDLL__baseminor_dll; +unsigned int CRTDLL__baseversion_dll; +unsigned int CRTDLL__cpumode_dll; +unsigned int CRTDLL__osmajor_dll; +unsigned int CRTDLL__osminor_dll; +unsigned int CRTDLL__osmode_dll; +unsigned int CRTDLL__osversion_dll; + +extern char* _acmdln; /* pointer to ascii command line */ +extern wchar_t* _wcmdln; /* pointer to wide character command line */ +#undef _environ +extern char** _environ; /* pointer to environment block */ +extern char** __initenv; /* pointer to initial environment block */ +extern wchar_t** _wenviron; /* pointer to environment block */ +extern wchar_t** __winitenv; /* pointer to initial environment block */ + + + +/* dev_t is a short in crtdll but an unsigned int in msvcrt */ +typedef short crtdll_dev_t; + +struct crtdll_stat +{ + crtdll_dev_t st_dev; + _ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + crtdll_dev_t st_rdev; + _off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +/* convert struct _stat from crtdll format to msvcrt format */ +static void convert_struct_stat( struct crtdll_stat *dst, const struct _stat *src ) +{ + dst->st_dev = src->st_dev; + dst->st_ino = src->st_ino; + dst->st_mode = src->st_mode; + dst->st_nlink = src->st_nlink; + dst->st_uid = src->st_uid; + dst->st_gid = src->st_gid; + dst->st_rdev = src->st_rdev; + dst->st_size = src->st_size; + dst->st_atime = src->st_atime; + dst->st_mtime = src->st_mtime; + dst->st_ctime = src->st_ctime; +} + +/* from msvcrt */ +extern void __getmainargs( int *argc, char ***argv, char ***envp, + int expand_wildcards, int *new_mode ); + +/* LIBRARY GLOBAL VARIABLES ***************************************************/ + +HANDLE hHeap = NULL; /* handle for heap */ + + +/* LIBRARY ENTRY POINT ********************************************************/ + +BOOL +STDCALL +DllMain(PVOID hinstDll, ULONG dwReason, PVOID reserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH://1 + /* initialize version info */ + DPRINT("Attach %d\n", nAttachCount); + + _osver = GetVersion(); + + CRTDLL__basemajor_dll = (_osver >> 24) & 0xFF; + CRTDLL__baseminor_dll = (_osver >> 16) & 0xFF; + CRTDLL__baseversion_dll = (_osver >> 16); + CRTDLL__cpumode_dll = 1; /* FIXME */ + CRTDLL__osmajor_dll = (_osver >>8) & 0xFF; + CRTDLL__osminor_dll = (_osver & 0xFF); + CRTDLL__osmode_dll = 1; /* FIXME */ + CRTDLL__osversion_dll = (_osver & 0xFFFF); + + _winmajor = (_osver >> 8) & 0xFF; + _winminor = _osver & 0xFF; + _winver = (_winmajor << 8) + _winminor; + _osver = (_osver >> 16) & 0xFFFF; + hHeap = HeapCreate(0, 100000, 0); + if (hHeap == NULL) + return FALSE; + if (!__fileno_init()) + return FALSE; + + /* create tls stuff */ + if (!CreateThreadData()) + return FALSE; + + if (BlockEnvToEnvironA() < 0) + return FALSE; + + if (BlockEnvToEnvironW() < 0) + { + FreeEnvironment((char**)_wenviron); + return FALSE; + } + + _acmdln = _strdup(GetCommandLineA()); + _wcmdln = _wcsdup(GetCommandLineW()); + + /* FIXME: more initializations... */ + + /* FIXME: Initialization of the WINE code */ + msvcrt_init_mt_locks(); + + DPRINT("Attach done\n"); + break; + + case DLL_THREAD_ATTACH://2 + break; + + case DLL_THREAD_DETACH://4 + FreeThreadData(NULL); + break; + + case DLL_PROCESS_DETACH://0 + DPRINT("Detach %d\n", nAttachCount); + /* FIXME: more cleanup... */ + _fcloseall(); + + /* destroy tls stuff */ + DestroyThreadData(); + + if (__winitenv && __winitenv != _wenviron) + FreeEnvironment((char**)__winitenv); + if (_wenviron) + FreeEnvironment((char**)_wenviron); + + if (__initenv && __initenv != _environ) + FreeEnvironment(__initenv); + if (_environ) + FreeEnvironment(_environ); + + /* destroy heap */ + HeapDestroy(hHeap); + + DPRINT("Detach done\n"); + break; + } + + return TRUE; +} + + + + +/********************************************************************* + * __GetMainArgs (CRTDLL.@) + */ +void __GetMainArgs( int *argc, char ***argv, char ***envp, int expand_wildcards ) +{ + int new_mode = 0; + __getmainargs( argc, argv, envp, expand_wildcards, &new_mode ); +} + + +/********************************************************************* + * _fstat (CRTDLL.@) + */ +int CRTDLL__fstat(int fd, struct crtdll_stat* buf) +{ + extern int _fstat(int,struct _stat*); + struct _stat st; + int ret; + + if (!(ret = _fstat( fd, &st ))) convert_struct_stat( buf, &st ); + return ret; +} + + +/********************************************************************* + * _stat (CRTDLL.@) + */ +int CRTDLL__stat(const char* path, struct crtdll_stat * buf) +{ + extern int _stat(const char*,struct _stat*); + struct _stat st; + int ret; + + if (!(ret = _stat( path, &st ))) convert_struct_stat( buf, &st ); + return ret; +} + + +/********************************************************************* + * _strdec (CRTDLL.@) + */ +char *_strdec(const char *str1, const char *str2) +{ + return (char *)(str2 - 1); +} + + +/********************************************************************* + * _strinc (CRTDLL.@) + */ +char *_strinc(const char *str) +{ + return (char *)(str + 1); +} + + +/********************************************************************* + * _strncnt (CRTDLL.@) + */ +size_t _strncnt(const char *str, size_t maxlen) +{ + size_t len = strlen(str); + return (len > maxlen) ? maxlen : len; +} + + +/********************************************************************* + * _strnextc (CRTDLL.@) + */ +unsigned int _strnextc(const char *str) +{ + return (unsigned int)str[0]; +} + + +/********************************************************************* + * _strninc (CRTDLL.@) + */ +char *_strninc(const char *str, size_t len) +{ + return (char *)(str + len); +} + + +/********************************************************************* + * _strspnp (CRTDLL.@) + */ +char *_strspnp( const char *str1, const char *str2) +{ + str1 += strspn( str1, str2 ); + return *str1 ? (char*)str1 : NULL; +} + +/* EOF */ diff --git a/reactos/lib/crtdll/except/abnorter.c b/reactos/lib/crtdll/except/abnorter.c deleted file mode 100644 index 3f27a81208c..00000000000 --- a/reactos/lib/crtdll/except/abnorter.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "precomp.h" -#include - -#ifdef __GNUC__ - -/* - * @unimplemented - */ -int _abnormal_termination(void) -{ - printf("Abnormal Termination\n"); -// return AbnormalTermination(); - return 0; -} - -#else -#endif diff --git a/reactos/lib/crtdll/except/exhand2.c b/reactos/lib/crtdll/except/exhand2.c deleted file mode 100644 index 49001483225..00000000000 --- a/reactos/lib/crtdll/except/exhand2.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "precomp.h" -#include - - -#ifdef __GNUC__ -#else -#endif - -ULONG DbgPrint(PCH Format, ...) -{ - return 0; -} - -VOID STDCALL -MsvcrtDebug(ULONG Value) -{ - //DbgPrint("MsvcrtDebug 0x%.08x\n", Value); -} - -struct _EXCEPTION_RECORD; -struct _CONTEXT; - -/* - * @unimplemented - */ -EXCEPTION_DISPOSITION -_except_handler2( - struct _EXCEPTION_RECORD* ExceptionRecord, void* Frame, - struct _CONTEXT *ContextRecord, void* DispatcherContext) -{ - //printf("_except_handler2()\n"); - return 0; -} diff --git a/reactos/lib/crtdll/except/matherr.c b/reactos/lib/crtdll/except/matherr.c deleted file mode 100644 index c800b2c920c..00000000000 --- a/reactos/lib/crtdll/except/matherr.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "precomp.h" -#include - - -struct _exception { - int type; - char* name; - double arg1; - double arg2; - double retval; -} ; - - -/* - * @unimplemented - */ -int _matherr(struct _exception* e) -{ - return 0; -} - - -// not exported by NTDLL -void __setusermatherr(int (*handler)(struct _exception*)) -{ - -} - - -#define _FPIEEE_RECORD void - -/* - * @unimplemented - */ -int _fpieee_flt( - unsigned long exception_code, - struct _EXCEPTION_POINTERS* ExceptionPointer, - int (*handler)(_FPIEEE_RECORD*) - ) -{ - return 0; -} diff --git a/reactos/lib/crtdll/except/unwind.c b/reactos/lib/crtdll/except/unwind.c deleted file mode 100644 index de846f957fe..00000000000 --- a/reactos/lib/crtdll/except/unwind.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "precomp.h" -#define PEXCEPTION_FRAME void* - -/* - * @unimplemented - */ -void _global_unwind2( PEXCEPTION_FRAME frame ) -{ - //RtlUnwind( frame, 0, NULL, 0 ); -} - - -/* - * @unimplemented - */ -void _local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr ) -{ - //TRACE(crtdll,"(%p,%ld)\n",endframe,nr); - return; -} diff --git a/reactos/lib/crtdll/float/clearfp.c b/reactos/lib/crtdll/float/clearfp.c deleted file mode 100644 index 9e65bd29285..00000000000 --- a/reactos/lib/crtdll/float/clearfp.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned int _clearfp (void) -{ -unsigned short __res = _statusfp(); -#ifdef __GNUC__ -__asm__ __volatile__ ( - "fclex \n\t" - ); -#else -#endif /*__GNUC__*/ - return __res; -} - diff --git a/reactos/lib/crtdll/float/fpreset.c b/reactos/lib/crtdll/float/fpreset.c deleted file mode 100644 index 1a4efe4f31c..00000000000 --- a/reactos/lib/crtdll/float/fpreset.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - - -/* - * @unimplemented - */ -void _fpreset(void) -{ - /* FIXME: This causes an exception */ -// __asm__ __volatile__("fninit\n\t"); - return; -} diff --git a/reactos/lib/crtdll/float/nafter.c b/reactos/lib/crtdll/float/nafter.c deleted file mode 100644 index dd007322e4b..00000000000 --- a/reactos/lib/crtdll/float/nafter.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - - -/* - * @implemented - */ -double _nextafter(double x, double y) -{ - if (x == y) - return x; - - if (isnan(x) || isnan(y)) - return x; - - return x; -} diff --git a/reactos/lib/crtdll/io/commit.c b/reactos/lib/crtdll/io/commit.c deleted file mode 100644 index d4024a6cd0c..00000000000 --- a/reactos/lib/crtdll/io/commit.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "precomp.h" -#include -#include -#include - - -/* - * @implemented - */ -int _commit(int _fd) -{ - if (! FlushFileBuffers(_get_osfhandle(_fd)) ) { - __set_errno(EBADF); - return -1; - } - - return 0; -} diff --git a/reactos/lib/crtdll/io/dup2.c b/reactos/lib/crtdll/io/dup2.c deleted file mode 100644 index 995e48b00cd..00000000000 --- a/reactos/lib/crtdll/io/dup2.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -/* - * @implemented - */ -int _dup2( int handle1, int handle2 ) -{ - return __fileno_dup2( handle1, handle2 ); -} diff --git a/reactos/lib/crtdll/io/mktemp.c b/reactos/lib/crtdll/io/mktemp.c deleted file mode 100644 index a47f8d09b61..00000000000 --- a/reactos/lib/crtdll/io/mktemp.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/io/mktemp.c - * PURPOSE: Makes a temp file based on a template - * PROGRAMER: DJ Delorie - Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Appropriated for the Reactos Kernel - */ - -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include - -#define NDEBUG -#include - - -/* - * @implemented - */ -char* _mktemp (char *_template) -{ - static int count = 0; - char *cp, *dp; - int i, len, xcount, loopcnt; - - DPRINT("_mktemp('%s')\n", _template); - len = strlen (_template); - cp = _template + len; - - xcount = 0; - while (xcount < 6 && cp > _template && cp[-1] == 'X') - xcount++, cp--; - - if (xcount) { - dp = cp; - while (dp > _template && dp[-1] != '/' && dp[-1] != '\\' && dp[-1] != ':') - dp--; - - /* Keep the first characters of the template, but turn the rest into - Xs. */ - while (cp > dp + 8 - xcount) { - *--cp = 'X'; - xcount = (xcount >= 6) ? 6 : 1 + xcount; - } - - /* If dots occur too early -- squash them. */ - while (dp < cp) { - if (*dp == '.') *dp = 'a'; - dp++; - } - - /* Try to add ".tmp" to the filename. Truncate unused Xs. */ - if (cp + xcount + 3 < _template + len) - strcpy (cp + xcount, ".tmp"); - else - cp[xcount] = 0; - - /* This loop can run up to 2<<(5*6) times, or about 10^9 times. */ - for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) { - int c = count++; - for (i = 0; i < xcount; i++, c >>= 5) - cp[i] = "abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f]; - if (_access(_template,0) == -1) - return _template; - } - } - - /* Failure: truncate the template and return NULL. */ - *_template = 0; - return 0; -} diff --git a/reactos/lib/crtdll/io/setmode.c b/reactos/lib/crtdll/io/setmode.c deleted file mode 100644 index 0fe6ac54dfb..00000000000 --- a/reactos/lib/crtdll/io/setmode.c +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/io/setmode.c - * PURPOSE: Sets the file translation mode - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include -#include -#include - -#define NDEBUG -#include - - -/* - * @implemented - */ -int _setmode(int _fd, int _newmode) -{ - DPRINT("_setmod(fd %d, newmode %x)\n", _fd, _newmode); - return __fileno_setmode(_fd, _newmode); -} diff --git a/reactos/lib/crtdll/io/sopen.c b/reactos/lib/crtdll/io/sopen.c deleted file mode 100644 index 8ebadea6a83..00000000000 --- a/reactos/lib/crtdll/io/sopen.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - - -/* - * @implemented - */ -int _sopen(char *path,int access,int shflag,int mode) -{ - return _open((path), (access)|(shflag), (mode)); -} diff --git a/reactos/lib/crtdll/io/tell.c b/reactos/lib/crtdll/io/tell.c deleted file mode 100644 index 4f81bc83e1e..00000000000 --- a/reactos/lib/crtdll/io/tell.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include -#include - - -/* - * @implemented - */ -off_t _tell(int _file) -{ - return _lseek(_file, 0, SEEK_CUR); -} diff --git a/reactos/lib/crtdll/io/umask.c b/reactos/lib/crtdll/io/umask.c deleted file mode 100644 index b5419310899..00000000000 --- a/reactos/lib/crtdll/io/umask.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -unsigned _unMode_dll = 022; - -/* - * @implemented - */ -unsigned _umask (unsigned unMode) -{ - unsigned old_mask = _unMode_dll; - _unMode_dll = unMode; - return old_mask; -} diff --git a/reactos/lib/crtdll/io/utime.c b/reactos/lib/crtdll/io/utime.c deleted file mode 100644 index 593ca7e1538..00000000000 --- a/reactos/lib/crtdll/io/utime.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include -#include -#include - - -/* - * @implemented - */ -int _utime(const char* filename, struct _utimbuf* buf) -{ - int fn; - int ret; - - fn = _open(filename, _O_RDWR); - if ( fn == -1 ) { - __set_errno(EBADF); - return -1; - } - ret = _futime(fn,buf); - if ( _close(fn) < 0 ) - return -1; - return ret; -} diff --git a/reactos/lib/crtdll/makefile b/reactos/lib/crtdll/makefile index da7fd6874cb..1145c2aba1a 100644 --- a/reactos/lib/crtdll/makefile +++ b/reactos/lib/crtdll/makefile @@ -2,7 +2,7 @@ PATH_TO_TOP = ../.. -PATH_TO_MSVCRT = ../msvcrt +TARGET_DEFONLY = yes TARGET_TYPE = dynlink @@ -17,487 +17,26 @@ RM_AT_FROM_SYMBOLS = no TARGET_LFLAGS = -nostartfiles -nostdlib -TARGET_CFLAGS = -D_MSVCRT_LIB_ -Werror -Wall - -# require os code to explicitly request A/W version of structs/functions -TARGET_CFLAGS += -D_DISABLE_TIDENTS - -TARGET_SDKLIBS = string.a kernel32.a ntdll.a +TARGET_SDKLIBS = crt.a string.a kernel32.a ntdll.a wine.a TARGET_GCCLIBS = gcc -TARGET_OBJECTS = $(TARGET_NAME).o +TARGET_CFLAGS = -D__USE_W32API -Wall -Werror -TARGET_CLEAN = \ - conio/*.o \ - ctype/*.o \ - direct/*.o \ - dirent/*.o \ - except/*.o \ - float/*.o \ - io/*.o \ - libc/*.o \ - malloc/*.o \ - math/*.o \ - mbstring/*.o \ - misc/*.o \ - process/*.o \ - quad/*.o \ - search/*.o \ - setjmp/*.o \ - signal/*.o \ - stdio/*.o \ - stdlib/*.o \ - string/*.o \ - sys_stat/*.o \ - tchar/*.o \ - time/*.o \ - wchar/*.o +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += \ + -D_DISABLE_TIDENTS \ + -D__USE_W32API \ + -D__REACTOS__ \ + -D_WIN32_IE=0x600 \ + -D_WIN32_WINNT=0x501 \ + -DUSE_MSVCRT_PREFIX \ + -D_MT +TARGET_OBJECTS = dllmain.o include $(PATH_TO_TOP)/rules.mak include $(TOOLS_PATH)/helper.mk - -CONIO_OBJECTS = \ - $(PATH_TO_MSVCRT)/conio/cgets.o \ - $(PATH_TO_MSVCRT)/conio/cprintf.o \ - $(PATH_TO_MSVCRT)/conio/cputs.o \ - $(PATH_TO_MSVCRT)/conio/cscanf.o \ - $(PATH_TO_MSVCRT)/conio/getch.o \ - $(PATH_TO_MSVCRT)/conio/getche.o \ - $(PATH_TO_MSVCRT)/conio/kbhit.o \ - $(PATH_TO_MSVCRT)/conio/putch.o \ - $(PATH_TO_MSVCRT)/conio/ungetch.o - -CTYPE_OBJECTS = \ - $(PATH_TO_MSVCRT)/ctype/ctype.o \ - $(PATH_TO_MSVCRT)/ctype/isalnum.o \ - $(PATH_TO_MSVCRT)/ctype/isascii.o \ - $(PATH_TO_MSVCRT)/ctype/iscntrl.o \ - ctype/isctype.o \ - $(PATH_TO_MSVCRT)/ctype/isgraph.o \ - $(PATH_TO_MSVCRT)/ctype/isprint.o \ - $(PATH_TO_MSVCRT)/ctype/ispunct.o \ - $(PATH_TO_MSVCRT)/ctype/isupper.o - -# REMOVED CTYPE ENTRIES: -# $(PATH_TO_MSVCRT)/ctype/isalpha.o \ -# $(PATH_TO_MSVCRT)/ctype/iscsym.o \ -# $(PATH_TO_MSVCRT)/ctype/isdigit.o \ -# $(PATH_TO_MSVCRT)/ctype/islower.o \ -# $(PATH_TO_MSVCRT)/ctype/isspace.o \ -# $(PATH_TO_MSVCRT)/ctype/isxdigit.o \ -# $(PATH_TO_MSVCRT)/ctype/toascii.o \ -# $(PATH_TO_MSVCRT)/ctype/tolower.o \ -# $(PATH_TO_MSVCRT)/ctype/toupper.o \ - -DIRECT_OBJECTS = \ - $(PATH_TO_MSVCRT)/direct/chdir.o \ - $(PATH_TO_MSVCRT)/direct/chdrive.o \ - $(PATH_TO_MSVCRT)/direct/getcwd.o \ - $(PATH_TO_MSVCRT)/direct/getdcwd.o \ - $(PATH_TO_MSVCRT)/direct/getdfree.o \ - $(PATH_TO_MSVCRT)/direct/getdrive.o \ - $(PATH_TO_MSVCRT)/direct/mkdir.o \ - $(PATH_TO_MSVCRT)/direct/rmdir.o - -EXCEPT_OBJECTS = \ - except/abnorter.o \ - except/exhand2.o \ - except/matherr.o \ - except/unwind.o - -FLOAT_OBJECTS = \ - $(PATH_TO_MSVCRT)/float/chgsign.o \ - $(PATH_TO_MSVCRT)/float/clearfp.o \ - $(PATH_TO_MSVCRT)/float/cntrlfp.o \ - $(PATH_TO_MSVCRT)/float/copysign.o \ - $(PATH_TO_MSVCRT)/float/fpclass.o \ - $(PATH_TO_MSVCRT)/float/fpreset.o \ - $(PATH_TO_MSVCRT)/float/isnan.o \ - $(PATH_TO_MSVCRT)/float/logb.o \ - $(PATH_TO_MSVCRT)/float/nafter.o \ - $(PATH_TO_MSVCRT)/float/scalb.o \ - $(PATH_TO_MSVCRT)/float/statfp.o - -IO_OBJECTS = \ - $(PATH_TO_MSVCRT)/io/access.o \ - $(PATH_TO_MSVCRT)/io/chmod.o \ - $(PATH_TO_MSVCRT)/io/chsize.o \ - $(PATH_TO_MSVCRT)/io/close.o \ - $(PATH_TO_MSVCRT)/io/commit.o \ - io/create.o \ - io/dup.o \ - $(PATH_TO_MSVCRT)/io/dup2.o \ - io/eof.o \ - $(PATH_TO_MSVCRT)/io/filelen.o \ - io/find.o \ - io/fmode.o \ - $(PATH_TO_MSVCRT)/io/isatty.o \ - $(PATH_TO_MSVCRT)/io/locking.o \ - io/lseek.o \ - $(PATH_TO_MSVCRT)/io/mktemp.o \ - io/open.o \ - io/pipe.o \ - io/read.o \ - $(PATH_TO_MSVCRT)/io/setmode.o \ - $(PATH_TO_MSVCRT)/io/sopen.o \ - $(PATH_TO_MSVCRT)/io/tell.o \ - $(PATH_TO_MSVCRT)/io/umask.o \ - io/unlink.o \ - $(PATH_TO_MSVCRT)/io/utime.o \ - io/write.o - -LOCALE_OBJECTS = \ - $(PATH_TO_MSVCRT)/locale/locale.o - -MATH_OBJECTS = \ - $(PATH_TO_MSVCRT)/math/acos.o \ - math/acosh.o \ - $(PATH_TO_MSVCRT)/math/asin.o \ - math/asinh.o \ - $(PATH_TO_MSVCRT)/math/atan.o \ - $(PATH_TO_MSVCRT)/math/atan2.o\ - math/atanh.o \ - $(PATH_TO_MSVCRT)/math/cabs.o \ - math/ceil.o \ - $(PATH_TO_MSVCRT)/math/cos.o \ - $(PATH_TO_MSVCRT)/math/cosh.o \ - $(PATH_TO_MSVCRT)/math/exp.o \ - $(PATH_TO_MSVCRT)/math/fabs.o\ - math/floor.o \ - $(PATH_TO_MSVCRT)/math/fmod.o \ - $(PATH_TO_MSVCRT)/math/frexp.o \ - math/huge_val.o \ - $(PATH_TO_MSVCRT)/math/hypot.o \ - $(PATH_TO_MSVCRT)/math/j0_y0.o \ - $(PATH_TO_MSVCRT)/math/j1_y1.o \ - $(PATH_TO_MSVCRT)/math/jn_yn.o \ - $(PATH_TO_MSVCRT)/math/ldexp.o \ - $(PATH_TO_MSVCRT)/math/log.o \ - $(PATH_TO_MSVCRT)/math/log10.o \ - $(PATH_TO_MSVCRT)/math/modf.o \ - $(PATH_TO_MSVCRT)/math/pow.o \ - $(PATH_TO_MSVCRT)/math/sin.o \ - $(PATH_TO_MSVCRT)/math/sinh.o \ - $(PATH_TO_MSVCRT)/math/sqrt.o \ - $(PATH_TO_MSVCRT)/math/stubs.o \ - $(PATH_TO_MSVCRT)/math/tan.o \ - $(PATH_TO_MSVCRT)/math/tanh.o - -MALLOC_OBJECTS = \ - malloc/expand.o \ - malloc/heap.o - -MBSTRING_OBJECTS = \ - $(PATH_TO_MSVCRT)/mbstring/hanzen.o \ - $(PATH_TO_MSVCRT)/mbstring/ischira.o \ - $(PATH_TO_MSVCRT)/mbstring/iskana.o \ - $(PATH_TO_MSVCRT)/mbstring/iskpun.o \ - $(PATH_TO_MSVCRT)/mbstring/islead.o \ - $(PATH_TO_MSVCRT)/mbstring/islwr.o \ - $(PATH_TO_MSVCRT)/mbstring/iskmoji.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbal.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbaln.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbc.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbgra.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbkaln.o \ - $(PATH_TO_MSVCRT)/mbstring/ismblead.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbpri.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbpun.o \ - $(PATH_TO_MSVCRT)/mbstring/ismbtrl.o \ - $(PATH_TO_MSVCRT)/mbstring/isuppr.o \ - $(PATH_TO_MSVCRT)/mbstring/jistojms.o \ - $(PATH_TO_MSVCRT)/mbstring/jmstojis.o \ - $(PATH_TO_MSVCRT)/mbstring/mbbtype.o \ - $(PATH_TO_MSVCRT)/mbstring/mbccpy.o \ - $(PATH_TO_MSVCRT)/mbstring/mbclen.o \ - $(PATH_TO_MSVCRT)/mbstring/mbscat.o \ - $(PATH_TO_MSVCRT)/mbstring/mbschr.o \ - $(PATH_TO_MSVCRT)/mbstring/mbscmp.o \ - $(PATH_TO_MSVCRT)/mbstring/mbscoll.o \ - $(PATH_TO_MSVCRT)/mbstring/mbscpy.o \ - $(PATH_TO_MSVCRT)/mbstring/mbscspn.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsdec.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsdup.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsicmp.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsicoll.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsinc.o \ - $(PATH_TO_MSVCRT)/mbstring/mbslen.o \ - $(PATH_TO_MSVCRT)/mbstring/mbslwr.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsncat.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsnccnt.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsncmp.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsncoll.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsncpy.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsnextc.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsnicmp.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsnicoll.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsninc.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsnset.o \ - $(PATH_TO_MSVCRT)/mbstring/mbspbrk.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsrchr.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsrev.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsset.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsspn.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsspnp.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsstr.o \ - $(PATH_TO_MSVCRT)/mbstring/mbstok.o \ - $(PATH_TO_MSVCRT)/mbstring/mbstrlen.o \ - $(PATH_TO_MSVCRT)/mbstring/mbsupr.o - -MISC_OBJECTS = \ - misc/amsg.o \ - $(PATH_TO_MSVCRT)/misc/assert.o \ - misc/debug.o \ - misc/dllmain.o \ - misc/GetArgs.o \ - $(PATH_TO_MSVCRT)/misc/initterm.o \ - misc/purecall.o \ - misc/setnew.o - -PROCESS_OBJECTS = \ - process/_cwait.o \ - process/_system.o\ - $(PATH_TO_MSVCRT)/process/dll.o \ - process/spawnl.o \ - process/spawnlp.o \ - process/spawnlpe.o \ - process/spawnvp.o \ - process/spawnv.o \ - process/spawnve.o \ - process/spawnle.o \ - process/execl.o \ - process/execlp.o \ - process/execlpe.o \ - process/execvpe.o \ - process/execvp.o \ - process/execv.o \ - process/execle.o \ - process/execve.o \ - $(PATH_TO_MSVCRT)/process/procid.o \ - process/thread.o \ - $(PATH_TO_MSVCRT)/process/threadid.o - -QUAD_OBJECTS = \ - quad/qdivrem.o \ - quad/divdi3.o \ - quad/moddi3.o \ - quad/udivdi3.o \ - quad/umoddi3.o - -SEARCH_OBJECTS = \ - $(PATH_TO_MSVCRT)/search/lfind.o \ - $(PATH_TO_MSVCRT)/search/lsearch.o - -SETJMP_OBJECTS = \ - $(PATH_TO_MSVCRT)/setjmp/i386/setjmp.o - -SIGNAL_OBJECTS = \ - signal/xcptfil.o \ - signal/xcptinfo.o \ - $(PATH_TO_MSVCRT)/signal/signal.o - -STDIO_OBJECTS = \ - $(PATH_TO_MSVCRT)/stdio/allocfil.o \ - stdio/getenv.o \ - $(PATH_TO_MSVCRT)/stdio/clearerr.o \ - $(PATH_TO_MSVCRT)/stdio/fclose.o \ - $(PATH_TO_MSVCRT)/stdio/fdopen.o \ - $(PATH_TO_MSVCRT)/stdio/feof.o \ - stdio/ferror.o \ - stdio/fflush.o \ - $(PATH_TO_MSVCRT)/stdio/fgetc.o \ - stdio/fgetchar.o \ - $(PATH_TO_MSVCRT)/stdio/fgetpos.o \ - stdio/fgets.o \ - stdio/filbuf.o \ - stdio/fileno.o \ - $(PATH_TO_MSVCRT)/stdio/flsbuf.o \ - stdio/fopen.o \ - $(PATH_TO_MSVCRT)/stdio/fprintf.o \ - $(PATH_TO_MSVCRT)/stdio/fputc.o \ - stdio/fputchar.o\ - stdio/fputs.o \ - stdio/fread.o \ - stdio/freopen.o \ - stdio/fscanf.o \ - $(PATH_TO_MSVCRT)/stdio/fseek.o \ - $(PATH_TO_MSVCRT)/stdio/fsetpos.o \ - stdio/frlist.o \ - stdio/fsopen.o \ - stdio/ftell.o \ - $(PATH_TO_MSVCRT)/stdio/fwalk.o \ - stdio/fwrite.o \ - stdio/getc.o \ - stdio/getchar.o \ - stdio/gets.o \ - $(PATH_TO_MSVCRT)/stdio/getw.o \ - stdio/perror.o \ - stdio/popen.o \ - stdio/printf.o \ - stdio/putc.o \ - stdio/putchar.o \ - stdio/puts.o \ - $(PATH_TO_MSVCRT)/stdio/putw.o \ - stdio/remove.o \ - $(PATH_TO_MSVCRT)/stdio/rename.o \ - $(PATH_TO_MSVCRT)/stdio/rewind.o \ - $(PATH_TO_MSVCRT)/stdio/rmtmp.o \ - $(PATH_TO_MSVCRT)/stdio/scanf.o \ - $(PATH_TO_MSVCRT)/stdio/setbuf.o \ - stdio/setbuffe.o \ - stdio/setlineb.o \ - $(PATH_TO_MSVCRT)/stdio/setvbuf.o \ - $(PATH_TO_MSVCRT)/stdio/sprintf.o \ - $(PATH_TO_MSVCRT)/stdio/sscanf.o \ - $(PATH_TO_MSVCRT)/stdio/stdhnd.o \ - stdio/stdiohk.o \ - $(PATH_TO_MSVCRT)/stdio/tempnam.o \ - $(PATH_TO_MSVCRT)/stdio/tmpfile.o \ - $(PATH_TO_MSVCRT)/stdio/tmpnam.o \ - $(PATH_TO_MSVCRT)/stdio/ungetc.o \ - $(PATH_TO_MSVCRT)/stdio/vfprintf.o \ - $(PATH_TO_MSVCRT)/stdio/vfscanf.o \ - $(PATH_TO_MSVCRT)/stdio/vfwprint.o \ - $(PATH_TO_MSVCRT)/stdio/vprintf.o \ - $(PATH_TO_MSVCRT)/stdio/vscanf.o \ - $(PATH_TO_MSVCRT)/stdio/vsprintf.o \ - $(PATH_TO_MSVCRT)/stdio/vsscanf.o - -STDLIB_OBJECTS = \ - $(PATH_TO_MSVCRT)/stdlib/_exit.o \ - $(PATH_TO_MSVCRT)/stdlib/abort.o \ - $(PATH_TO_MSVCRT)/stdlib/abs.o \ - $(PATH_TO_MSVCRT)/stdlib/atexit.o \ - $(PATH_TO_MSVCRT)/stdlib/atof.o \ - $(PATH_TO_MSVCRT)/stdlib/atoi.o \ - $(PATH_TO_MSVCRT)/stdlib/atol.o \ - $(PATH_TO_MSVCRT)/stdlib/bsearch.o \ - $(PATH_TO_MSVCRT)/stdlib/div.o \ - $(PATH_TO_MSVCRT)/stdlib/ecvt.o \ - $(PATH_TO_MSVCRT)/stdlib/ecvtbuf.o \ - stdlib/errno.o \ - $(PATH_TO_MSVCRT)/stdlib/fcvt.o \ - $(PATH_TO_MSVCRT)/stdlib/fcvtbuf.o \ - stdlib/fullpath.o \ - $(PATH_TO_MSVCRT)/stdlib/gcvt.o \ - $(PATH_TO_MSVCRT)/stdlib/itoa.o \ - stdlib/itow.o \ - $(PATH_TO_MSVCRT)/stdlib/labs.o \ - $(PATH_TO_MSVCRT)/stdlib/ldiv.o \ - $(PATH_TO_MSVCRT)/stdlib/makepath.o \ - stdlib/malloc.o \ - stdlib/mbstowcs.o \ - $(PATH_TO_MSVCRT)/stdlib/obsol.o \ - stdlib/putenv.o \ - stdlib/qsort.o \ - stdlib/rand.o \ - $(PATH_TO_MSVCRT)/stdlib/rot.o \ - $(PATH_TO_MSVCRT)/stdlib/senv.o \ - $(PATH_TO_MSVCRT)/stdlib/splitp.o \ - $(PATH_TO_MSVCRT)/stdlib/strtod.o \ - $(PATH_TO_MSVCRT)/stdlib/strtol.o \ - $(PATH_TO_MSVCRT)/stdlib/strtoul.o \ - $(PATH_TO_MSVCRT)/stdlib/swab.o \ - $(PATH_TO_MSVCRT)/stdlib/wcstod.o \ - stdlib/wcstomb.o - -STRING_OBJECTS = \ - string/lasttok.o \ - $(PATH_TO_MSVCRT)/string/strcoll.o \ - $(PATH_TO_MSVCRT)/string/strdup.o \ - string/strerror.o \ - $(PATH_TO_MSVCRT)/string/strrev.o \ - $(PATH_TO_MSVCRT)/string/strset.o \ - $(PATH_TO_MSVCRT)/string/strtok.o \ - $(PATH_TO_MSVCRT)/string/strxfrm.o - -# string/str_old.o \ -# $(PATH_TO_MSVCRT)/string/memicmp.o \ -# $(PATH_TO_MSVCRT)/string/stricmp.o \ -# $(PATH_TO_MSVCRT)/string/strlwr.o \ -# $(PATH_TO_MSVCRT)/string/strnicmp.o \ -# $(PATH_TO_MSVCRT)/string/strpbrk.o \ -# $(PATH_TO_MSVCRT)/string/strstr.o \ -# $(PATH_TO_MSVCRT)/string/strupr.o \ - -SYS_STAT_OBJECTS = \ - sys_stat/fstat.o \ - $(PATH_TO_MSVCRT)/sys_stat/futime.o \ - sys_stat/ftime.o \ - sys_stat/systime.o \ - sys_stat/stat.o - -TCHAR_OBJECTS = \ - tchar/strdec.o \ - tchar/strinc.o \ - tchar/strninc.o \ - tchar/strncnt.o \ - tchar/strnextc.o \ - tchar/strspnp.o - -TIME_OBJECTS = \ - $(PATH_TO_MSVCRT)/time/time.o \ - $(PATH_TO_MSVCRT)/time/clock.o \ - $(PATH_TO_MSVCRT)/time/ctime.o \ - $(PATH_TO_MSVCRT)/time/difftime.o \ - $(PATH_TO_MSVCRT)/time/strdate.o \ - $(PATH_TO_MSVCRT)/time/strftime.o \ - $(PATH_TO_MSVCRT)/time/strtime.o \ - time/tz_vars.o - -WSTRING_OBJECTS = \ - wchar/wlasttok.o \ - wchar/wcscoll.o \ - $(PATH_TO_MSVCRT)/wstring/wcsdup.o \ - $(PATH_TO_MSVCRT)/wstring/wcsrev.o \ - $(PATH_TO_MSVCRT)/wstring/wcsset.o \ - $(PATH_TO_MSVCRT)/wstring/wcstok.o \ - $(PATH_TO_MSVCRT)/wstring/wcsxfrm.o - -# wchar/wcstod.o \ -# wchar/wcstok.o \ -# wchar/wcstol.o \ -# wchar/wtoi.o \ -# $(PATH_TO_MSVCRT)/wstring/wcscspn.o \ -# $(PATH_TO_MSVCRT)/wstring/wcsicmp.o \ -# $(PATH_TO_MSVCRT)/wstring/wcslwr.o \ -# $(PATH_TO_MSVCRT)/wstring/wcspbrk.o \ -# $(PATH_TO_MSVCRT)/wstring/wcsspn.o \ -# $(PATH_TO_MSVCRT)/wstring/wcsstr.o \ -# $(PATH_TO_MSVCRT)/wstring/wcsupr.o \ -# wchar/wcstombs.o \ -# $(PATH_TO_MSVCRT)/wstring/wcsnicmp.o - - -OBJECTS = \ - $(CONIO_OBJECTS) \ - $(CTYPE_OBJECTS) \ - $(DIRECT_OBJECTS) \ - $(EXCEPT_OBJECTS) \ - $(FLOAT_OBJECTS) \ - $(IO_OBJECTS) \ - $(LOCALE_OBJECTS) \ - $(MALLOC_OBJECTS) \ - $(MATH_OBJECTS) \ - $(MBSTRING_OBJECTS)\ - $(MISC_OBJECTS) \ - $(PROCESS_OBJECTS) \ - $(SEARCH_OBJECTS) \ - $(SETJMP_OBJECTS) \ - $(SIGNAL_OBJECTS) \ - $(STDIO_OBJECTS) \ - $(STDLIB_OBJECTS) \ - $(STRING_OBJECTS) \ - $(SYS_STAT_OBJECTS) \ - $(TCHAR_OBJECTS) \ - $(TIME_OBJECTS) \ - $(WSTRING_OBJECTS) - -$(TARGET_NAME).o: $(OBJECTS) - $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o - # EOF diff --git a/reactos/lib/crtdll/mbstring/hanzen.c b/reactos/lib/crtdll/mbstring/hanzen.c deleted file mode 100644 index 60853efead4..00000000000 --- a/reactos/lib/crtdll/mbstring/hanzen.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/hanzen.c - * PURPOSE: Multibyte conversion routines formerly called hantozen and zentohan - * PROGRAMER: Boudewijn Dekker, Taiji Yamada - * UPDATE HISTORY: - Modified from Taiji Yamada japanese code system utilities - * 12/04/99: Created - */ - -#include - -static unsigned short han_to_zen_ascii_table[0x5f] = { - 0x8140, 0x8149, 0x8168, 0x8194, 0x8190, 0x8193, 0x8195, 0x8166, - 0x8169, 0x816a, 0x8196, 0x817b, 0x8143, 0x817c, 0x8144, 0x815e, - 0x824f, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, - 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, 0x8184, 0x8148, - 0x8197, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, - 0x8267, 0x8268, 0x8269, 0x826a, 0x826b, 0x826c, 0x826d, 0x826e, - 0x826f, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, 0x8275, 0x8276, - 0x8277, 0x8278, 0x8279, 0x816d, 0x818f, 0x816e, 0x814f, 0x8151, - 0x8165, 0x8281, 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, - 0x8288, 0x8289, 0x828a, 0x828b, 0x828c, 0x828d, 0x828e, 0x828f, - 0x8290, 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, - 0x8298, 0x8299, 0x829a, 0x816f, 0x8162, 0x8170, 0x8150 -}; -static unsigned short han_to_zen_kana_table[0x40] = { - 0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, - 0x8342, 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362, - 0x815b, 0x8341, 0x8343, 0x8345, 0x8347, 0x8349, 0x834a, 0x834c, - 0x834e, 0x8350, 0x8352, 0x8354, 0x8356, 0x8358, 0x835a, 0x835c, - 0x835e, 0x8360, 0x8363, 0x8365, 0x8367, 0x8369, 0x836a, 0x836b, - 0x836c, 0x836d, 0x836e, 0x8371, 0x8374, 0x8377, 0x837a, 0x837d, - 0x837e, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, 0x8388, 0x8389, - 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8393, 0x814a, 0x814b -}; -static unsigned char zen_to_han_kana_table[0x8396-0x8340+1] = { - 0xa7, 0xb1, 0xa8, 0xb2, 0xa9, 0xb3, 0xaa, 0xb4, - 0xab, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, - 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, - 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0xc0, 0xc0, - 0xc1, 0xc1, 0xaf, 0xc2, 0xc2, 0xc3, 0xc3, 0xc4, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xca, - 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, - 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xcf, 0xd0, 0, - 0xd1, 0xd2, 0xd3, 0xac, 0xd4, 0xad, 0xd5, 0xae, - 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdc, - 0xb2, 0xb4, 0xa6, 0xdd, 0xb3, 0xb6, 0xb9 -}; -#define ZTOH_SYMBOLS 9 -static unsigned short zen_to_han_symbol_table_1[ZTOH_SYMBOLS] = { - 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x815b, 0x814a, 0x814b -}; -static unsigned char zen_to_han_symbol_table_2[ZTOH_SYMBOLS] = { - 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xb0, 0xde, 0xdf -}; -#define ISKANA(c) ((c) >= 0xa1 && (c) <= 0xdf) -#define JISHIRA(c) ((c) >= 0x829f && (c) <= 0x82f1) -#define JISKANA(c) ((c) >= 0x8340 && (c) <= 0x8396 && (c) != 0x837f) -#define JTOKANA(c) ((c) <= 0x82dd ? (c) + 0xa1 : (c) + 0xa2) - - -/* - * @implemented - */ -unsigned short _mbbtombc(unsigned short c) -{ - if (c >= 0x20 && c <= 0x7e) { - return han_to_zen_ascii_table[c - 0x20]; - } else if (ISKANA(c)) { - return han_to_zen_kana_table[c - 0xa0]; - } - return c; -} - - -/* - * @implemented - */ -unsigned short _mbctombb(unsigned short c) -{ - int i; - unsigned short *p; - - if (JISKANA(c)) { - return zen_to_han_kana_table[c - 0x8340]; - } else if (JISHIRA(c)) { - c = JTOKANA(c); - return zen_to_han_kana_table[c - 0x8340]; - } else if (c <= 0x8396) { - for (i = 0x20, p = han_to_zen_ascii_table; i <= 0x7e; i++, p++) { - if (*p == c) { - return i; - } - } - for (i = 0; i < ZTOH_SYMBOLS; i++) { - if (zen_to_han_symbol_table_1[i] == c) { - return zen_to_han_symbol_table_2[i]; - } - } - } - return c; -} - - - diff --git a/reactos/lib/crtdll/mbstring/ischira.c b/reactos/lib/crtdll/mbstring/ischira.c deleted file mode 100644 index 9fa4426b3e6..00000000000 --- a/reactos/lib/crtdll/mbstring/ischira.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/ischira.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include -#include - - -/* - * @implemented - */ -int _ismbchira(unsigned int c) -{ - return ((c>=0x829F) && (c<=0x82F1)); -} - -/* - * @implemented - */ -int _ismbckata(unsigned int c) -{ - return ((c>=0x8340) && (c<=0x8396)); -} - -/* - * @implemented - */ -unsigned int _mbctohira(unsigned int c) -{ - return c; -} - -/* - * @implemented - */ -unsigned int _mbctokata(unsigned int c) -{ - return c; -} - diff --git a/reactos/lib/crtdll/mbstring/iskana.c b/reactos/lib/crtdll/mbstring/iskana.c deleted file mode 100644 index fdf57960522..00000000000 --- a/reactos/lib/crtdll/mbstring/iskana.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/hanzen.c - * PURPOSE: Checks for kana character - * PROGRAMER: Boudewijn Dekker, Taiji Yamada - * UPDATE HISTORY: - Modified from Taiji Yamada japanese code system utilities - * 12/04/99: Created - */ -#include -#include - -/* - * @implemented - */ -int _ismbbkana(unsigned char c) -{ - return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_M|_KNJ_P)); -} diff --git a/reactos/lib/crtdll/mbstring/iskmoji.c b/reactos/lib/crtdll/mbstring/iskmoji.c deleted file mode 100644 index e2f1d48c840..00000000000 --- a/reactos/lib/crtdll/mbstring/iskmoji.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int _ismbbkalpha(unsigned char c) -{ - return (0xA7 <= c && c <= 0xDF); -} diff --git a/reactos/lib/crtdll/mbstring/iskpun.c b/reactos/lib/crtdll/mbstring/iskpun.c deleted file mode 100644 index 935c850cb0d..00000000000 --- a/reactos/lib/crtdll/mbstring/iskpun.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/iskpun.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include - -/* - * @implemented - */ -int _ismbbkpunct( unsigned int c ) -{ - return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); -} diff --git a/reactos/lib/crtdll/mbstring/islwr.c b/reactos/lib/crtdll/mbstring/islwr.c deleted file mode 100644 index 44167a836f3..00000000000 --- a/reactos/lib/crtdll/mbstring/islwr.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncmp.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include -#include - -/* - * code page 952 only - * - * @implemented - */ -int _ismbclower( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - if ( c >= 0x829A && c<= 0x829A ) - return 1; - } - - return islower(c); -} diff --git a/reactos/lib/crtdll/mbstring/ismbal.c b/reactos/lib/crtdll/mbstring/ismbal.c deleted file mode 100644 index 398d22df624..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbal.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/hanzen.c - * PURPOSE: Checks for alphabetic multibyte character - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include -#include - -/* - * @implemented - */ -int _ismbbalpha(unsigned char c) -{ - return (isalpha(c) ||_ismbbkalnum(c)); -} - diff --git a/reactos/lib/crtdll/mbstring/ismbaln.c b/reactos/lib/crtdll/mbstring/ismbaln.c deleted file mode 100644 index 109a2f5ef76..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbaln.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - - -/* - * @implemented - */ -int _ismbbalnum(unsigned char c) -{ - return (isalnum(c) || _ismbbkalnum(c)); -} - diff --git a/reactos/lib/crtdll/mbstring/ismbc.c b/reactos/lib/crtdll/mbstring/ismbc.c deleted file mode 100644 index f4bcc7a1a25..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbc.c +++ /dev/null @@ -1,132 +0,0 @@ -#include - -int _ismbbalpha(unsigned char c); -int _ismbbalnum(unsigned char c); - -int _ismbcalnum( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return _ismbbalnum(c); - - return 0; -} - -/* - * @implemented - */ -int _ismbcalpha( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return _ismbbalpha(c); - - return 0; -} - -/* - * @implemented - */ -int _ismbcdigit( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return 0; -// return _ismbbdigit(c); - - return 0; -} - -/* - * @implemented - */ -int _ismbcprint( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return 0; -// return _ismbbdigit(c); - - return 0; -} - -/* - * @implemented - */ -int _ismbcsymbol( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return 0; -// return _ismbbdigit(c); - - return 0; -} - -/* - * @implemented - */ -int _ismbcspace( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - // true multibyte character - return 0; - } - else - return 0; -// return _ismbbdigit(c); - - return 0; -} -/* - * @implemented - */ -int _ismbclegal(unsigned int c) -{ - if ((c & 0xFF00) != 0) { - return _ismbblead(c>>8) && _ismbbtrail(c&0xFF); - } - else - return _ismbbtrail(c&0xFF); - - return 0; -} - -/* - * @unimplemented - */ -int _ismbcl0(unsigned int c) -{ - return 0; -} - -/* - * @unimplemented - */ -int _ismbcl1(unsigned int c) -{ - return 0; -} - -/* - * @unimplemented - */ -int _ismbcl2(unsigned int c) -{ - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/ismbgra.c b/reactos/lib/crtdll/mbstring/ismbgra.c deleted file mode 100644 index f38499b0b80..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbgra.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -/* - * @implemented - */ -int _ismbbgraph(unsigned char c) -{ - return (isgraph(c) || _ismbbkana(c)); -} diff --git a/reactos/lib/crtdll/mbstring/ismbkaln.c b/reactos/lib/crtdll/mbstring/ismbkaln.c deleted file mode 100644 index 44f764ad0c4..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbkaln.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/iskpun.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include -#include - -/* - * @implemented - */ -int _ismbbkalnum( unsigned int c ) -{ - return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); -} diff --git a/reactos/lib/crtdll/mbstring/ismblead.c b/reactos/lib/crtdll/mbstring/ismblead.c deleted file mode 100644 index ba65a2c7a61..00000000000 --- a/reactos/lib/crtdll/mbstring/ismblead.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/ismblead.c - * PURPOSE: Checks for a lead byte - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * Modified from Taiji Yamada japanese code system utilities - * 12/04/99: Created - */ - -#include -#include -#include - -size_t _mbclen2(const unsigned int s); - -char _jctype[257] = { -/*-1*/ ___, -/*0x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, -/*1x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, -/*2x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, -/*3x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, -/*4x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, -/*5x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, -/*6x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, -/*7x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,___, -/*8x*/ __2,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, -/*9x*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, -/*Ax*/ __2,_P2,_P2,_P2,_P2,_P2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, -/*Bx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, -/*Cx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, -/*Dx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, -/*Ex*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, -/*Fx*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,___,___,___ -}; - -char *_mbctype = _jctype; -/* - * @implemented - */ -int _ismbblead(unsigned int c) -{ - return ((_jctype+1)[(unsigned char)(c)] & _KNJ_1); -} -//int _ismbblead(unsigned int byte) -//{ -// -// return (int)IsDBCSLeadByte(byte) -//} - -/* - * @implemented - */ -int _ismbslead( const unsigned char *str, const unsigned char *t) -{ - unsigned char *s = (unsigned char *)str; - while(*s != 0 && s != t) - { - - s+= _mbclen2(*s); - } - return _ismbblead( *s); -} - diff --git a/reactos/lib/crtdll/mbstring/ismbpri.c b/reactos/lib/crtdll/mbstring/ismbpri.c deleted file mode 100644 index e6d5ebc9881..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbpri.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -/* - * @implemented - */ -int _ismbbprint(unsigned char c) -{ - return (isprint(c) || _ismbbkana(c)); -} diff --git a/reactos/lib/crtdll/mbstring/ismbpun.c b/reactos/lib/crtdll/mbstring/ismbpun.c deleted file mode 100644 index 2ccd434c37d..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbpun.c +++ /dev/null @@ -1,18 +0,0 @@ - -#include -#include -#include - - -/* - * @implemented - */ -int _ismbbpunct(unsigned char c) -{ -// (0xA1 <= c <= 0xA6) - return (ispunct(c) || _ismbbkana(c)); -} - - //iskana() :(0xA1 <= c <= 0xDF) - //iskpun() :(0xA1 <= c <= 0xA6) - //iskmoji() :(0xA7 <= c <= 0xDF) diff --git a/reactos/lib/crtdll/mbstring/ismbtrl.c b/reactos/lib/crtdll/mbstring/ismbtrl.c deleted file mode 100644 index c68eca45bb6..00000000000 --- a/reactos/lib/crtdll/mbstring/ismbtrl.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/ismbtrail.c - * PURPOSE: Checks for a trailing byte - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include -#include - -size_t _mbclen2(const unsigned int s); - -// iskanji2() : (0x40 <= c <= 0x7E 0x80 <= c <= 0xFC) - -/* - * @implemented - */ -int _ismbbtrail(unsigned int c) -{ - return ((_jctype+1)[(unsigned char)(c)] & _KNJ_2); -} - -//int _ismbbtrail( unsigned int b) -//{ -// return ((b >= 0x40 && b <= 0x7e ) || (b >= 0x80 && b <= 0xfc ) ); -//} - - -/* - * @implemented - */ -int _ismbstrail( const unsigned char *str, const unsigned char *t) -{ - unsigned char *s = (unsigned char *)str; - while(*s != 0 && s != t) - { - - s+= _mbclen2(*s); - } - - return _ismbbtrail(*s); -} diff --git a/reactos/lib/crtdll/mbstring/isuppr.c b/reactos/lib/crtdll/mbstring/isuppr.c deleted file mode 100644 index 00638379b62..00000000000 --- a/reactos/lib/crtdll/mbstring/isuppr.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncmp.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include -#include - -/* - * code page 952 only - * - * @implemented - */ -int _ismbcupper( unsigned int c ) -{ - if ((c & 0xFF00) != 0) { - if ( c >= 0x8260 && c<= 0x8279 ) - return 1; - } - - return isupper(c); -} diff --git a/reactos/lib/crtdll/mbstring/mbbtype.c b/reactos/lib/crtdll/mbstring/mbbtype.c deleted file mode 100644 index 0f67c57bb38..00000000000 --- a/reactos/lib/crtdll/mbstring/mbbtype.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbbtype.c - * PURPOSE: Determines the type of a multibyte character - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include -#include - -/* - * @implemented - */ -int _mbbtype(unsigned char c , int type) -{ - if ( type == 1 ) { - if ((c >= 0x40 && c <= 0x7e ) || (c >= 0x80 && c <= 0xfc ) ) - { - return _MBC_TRAIL; - } - else if (( c >= 0x20 && c >= 0x7E ) || ( c >= 0xA1 && c <= 0xDF ) || - ( c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC ) ) - return _MBC_ILLEGAL; - else - return 0; - - } - else { - if (( c >= 0x20 && c <= 0x7E ) || ( c >= 0xA1 && c <= 0xDF )) { - return _MBC_SINGLE; - } - else if ( (c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC) ) - return _MBC_LEAD; - else if (( c >= 0x20 && c >= 0x7E ) || ( c >= 0xA1 && c <= 0xDF ) || - ( c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC ) ) - return _MBC_ILLEGAL; - else - return 0; - - } - - - return 0; -} - -/* - * @implemented - */ -int _mbsbtype( const unsigned char *str, size_t n ) -{ - if ( str == NULL ) - return -1; - return _mbbtype(*(str+n),1); -} diff --git a/reactos/lib/crtdll/mbstring/mbccpy.c b/reactos/lib/crtdll/mbstring/mbccpy.c deleted file mode 100644 index 94ea4fda4d4..00000000000 --- a/reactos/lib/crtdll/mbstring/mbccpy.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -size_t _mbclen2(const unsigned int s); - -/* - * @implemented - */ -void _mbccpy(unsigned char *dst, const unsigned char *src) -{ - if (!_ismbblead(*src) ) - return; - - memcpy(dst,src,_mbclen2(*src)); -} diff --git a/reactos/lib/crtdll/mbstring/mbscoll.c b/reactos/lib/crtdll/mbstring/mbscoll.c deleted file mode 100644 index dad12be050b..00000000000 --- a/reactos/lib/crtdll/mbstring/mbscoll.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbscoll.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include - -int colldif(unsigned short c1, unsigned short c2); - -int _mbscoll(const unsigned char *str1, const unsigned char *str2) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - while ( *s1 != 0 ) { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return colldif(*s1, *s2); - else { - s1 += 1; - s2 += 1; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return colldif(*short_s1, *short_s2); - else { - s1 += 2; - s2 += 2; - - } - } - else - return colldif(*s1, *s2); - } ; - return 0; -} - -#if 0 -int _mbsbcoll(const unsigned char *str1, const unsigned char *str2) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - - while ( *s1 != 0 ) { - - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return colldif(*s1, *s2); - else { - s1 += 1; - s2 += 1; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return colldif(*short_s1, *short_s2); - else { - s1 += 2; - s2 += 2; - } - } - else - return colldif(*s1, *s2); - } ; - return 0; -} -#endif diff --git a/reactos/lib/crtdll/mbstring/mbsicmp.c b/reactos/lib/crtdll/mbstring/mbsicmp.c deleted file mode 100644 index b1b7c41e096..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsicmp.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsicmp.c - * PURPOSE: Duplicates a multi byte string - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include -#include -#include - -/* - * @implemented - */ -int _mbsicmp(const unsigned char *str1, const unsigned char *str2) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - do { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (toupper(*s1) != toupper(*s2)) - return toupper(*s1) - toupper(*s2); - else { - s1 += 1; - s2 += 1; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) - return _mbctoupper(*short_s1) - _mbctoupper(*short_s2); - else { - s1 += 2; - s2 += 2; - } - } - else - return *s1 - *s2; - } while (*s1 != 0); - return 0; - - while (toupper(*s1) == toupper(*s2)) - { - if (*s1 == 0) - return 0; - s1++; - s2++; - } - return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); -} diff --git a/reactos/lib/crtdll/mbstring/mbsicoll.c b/reactos/lib/crtdll/mbstring/mbsicoll.c deleted file mode 100644 index 32020cc8348..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsicoll.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/iskpun.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include -#include -#include - -int colldif(unsigned short c1, unsigned short c2); -int _mbsicoll(const unsigned char *str1, const unsigned char *str2) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - while ( *s1 != 0 ) { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (toupper(*s1) != toupper(*s2)) - return colldif(*s1, *s2); - else { - s1 += 1; - s2 += 1; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) - return colldif(*short_s1, *short_s2); - else { - s1 += 2; - s2 += 2; - - } - } - else - return colldif(*s1, *s2); - } ; - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/mbsncmp.c b/reactos/lib/crtdll/mbstring/mbsncmp.c deleted file mode 100644 index 94c349d97a5..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsncmp.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncmp.c - * PURPOSE: Compares two strings to a maximum of n bytes or characters - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include - -/* - * @implemented - */ -int _mbsncmp(const unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - if (n == 0) - return 0; - do { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return *s1 - *s2; - else { - s1 += 1; - s2 += 1; - n--; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return *short_s1 - *short_s2; - else { - s1 += 2; - s2 += 2; - n--; - - } - } - else - return *s1 - *s2; - } while (n > 0); - return 0; -} - -/* - * @implemented - */ -int _mbsnbcmp(const unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - if (n == 0) - return 0; - do { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return *s1 - *s2; - else { - s1 += 1; - s2 += 1; - n--; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return *short_s1 - *short_s2; - else { - s1 += 2; - s2 += 2; - n-=2; - - } - } - else - return *s1 - *s2; - } while (n > 0); - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/mbsncoll.c b/reactos/lib/crtdll/mbstring/mbsncoll.c deleted file mode 100644 index 1a35922dd32..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsncoll.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncoll.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include - -int colldif(unsigned short c1, unsigned short c2); - -int _mbsncoll(const unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - if (n == 0) - return 0; - do { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return colldif(*s1, *s2); - else { - s1 += 1; - s2 += 1; - n--; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return colldif(*short_s1, *short_s2); - else { - s1 += 2; - s2 += 2; - n--; - - } - } - else - return colldif(*s1, *s2); - } while (n > 0); - return 0; -} - -int _mbsnbcoll(const unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - int l1, l2; - - if (n == 0) - return 0; - do { - - if (*s1 == 0) - break; - - l1 = _ismbblead(*s1); - l2 = _ismbblead(*s2); - if ( !l1 && !l2 ) { - - if (*s1 != *s2) - return colldif(*s1, *s2); - else { - s1 += 1; - s2 += 1; - n--; - } - } - else if ( l1 && l2 ){ - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - if ( *short_s1 != *short_s2 ) - return colldif(*short_s1, *short_s2); - else { - s1 += 2; - s2 += 2; - n-=2; - - } - } - else - return colldif(*s1, *s2); - } while (n > 0); - return 0; -} - -int colldif(unsigned short c1, unsigned short c2) -{ - return c1 - c2; -} diff --git a/reactos/lib/crtdll/mbstring/mbsncpy.c b/reactos/lib/crtdll/mbstring/mbsncpy.c deleted file mode 100644 index 112c7513785..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsncpy.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncpy.c - * PURPOSE: Copies a string to a maximum of n bytes or characters - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include - - -/* - * @implemented - */ -unsigned char *_mbsncpy(unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - if (n == 0) - return 0; - do { - - if (*s2 == 0) - break; - - if ( !_ismbblead(*s2) ) { - - *s1 = *s2; - s1 += 1; - s2 += 1; - n--; - } - else { - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - *short_s1 = *short_s2; - s1 += 2; - s2 += 2; - n--; - } - } while (n > 0); - return str1; -} - - - -/* - * The _mbsnbcpy function copies count bytes from src to dest. If src is shorter - * than dest, the string is padded with null characters. If dest is less than or - * equal to count it is not terminated with a null character. - * - * @implemented - */ -unsigned char * _mbsnbcpy(unsigned char *str1, const unsigned char *str2, size_t n) -{ - unsigned char *s1 = (unsigned char *)str1; - unsigned char *s2 = (unsigned char *)str2; - - unsigned short *short_s1, *short_s2; - - if (n == 0) - return 0; - do { - - if (*s2 == 0) { - *s1 = *s2; - break; - } - - if ( !_ismbblead(*s2) ) { - - *s1 = *s2; - s1 += 1; - s2 += 1; - n--; - } - else { - short_s1 = (unsigned short *)s1; - short_s2 = (unsigned short *)s2; - *short_s1 = *short_s2; - s1 += 2; - s2 += 2; - n-=2; - } - } while (n > 0); - return str1; -} diff --git a/reactos/lib/crtdll/mbstring/mbsnextc.c b/reactos/lib/crtdll/mbstring/mbsnextc.c deleted file mode 100644 index 44ad9502994..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsnextc.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned int _mbsnextc (const unsigned char *src) -{ - unsigned char *char_src = (unsigned char *)src; - unsigned short *short_src = (unsigned short *)src; - - if ( src == NULL ) - return 0; - - if ( !_ismbblead(*src) ) - return *char_src; - else - return *short_src; - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/mbsnicmp.c b/reactos/lib/crtdll/mbstring/mbsnicmp.c deleted file mode 100644 index cb5c2555f8d..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsnicmp.c +++ /dev/null @@ -1,47 +0,0 @@ -#include - - -size_t _mbclen2(const unsigned int s); -unsigned int _mbbtoupper(unsigned int c); - - -/* - * @implemented - */ -int _mbsnicmp(const unsigned char* s1, const unsigned char* s2, size_t n) -{ - if (n == 0) - return 0; - do { - if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) - return _mbbtoupper(*(unsigned const char*)s1) - _mbbtoupper(*(unsigned const char*)s2); - s1 += _mbclen2(*s1); - s2 += _mbclen2(*s2); - - if (*s1 == 0) - break; - if (!_ismbblead(*s1) ) - n--; - } while (n > 0); - return 0; -} - -/* - * @implemented - */ -int _mbsnbicmp(const unsigned char* s1, const unsigned char* s2, size_t n) -{ - if (n == 0) - return 0; - do { - if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) - return _mbbtoupper(*(unsigned const char*)s1) - _mbbtoupper(*(unsigned const char*)s2); - s1 += _mbclen2(*s1); - s2 += _mbclen2(*s2); - - if (*s1 == 0) - break; - n--; - } while (n > 0); - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/mbsnicoll.c b/reactos/lib/crtdll/mbstring/mbsnicoll.c deleted file mode 100644 index 3fead6d6a7b..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsnicoll.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -int _mbsnicoll(const unsigned char *s1, const unsigned char *s2, size_t n) -{ - return 0; -} - -int _mbsnbicoll(const unsigned char *s1, const unsigned char *s2, size_t n) -{ - return 0; -} diff --git a/reactos/lib/crtdll/mbstring/mbsninc.c b/reactos/lib/crtdll/mbstring/mbsninc.c deleted file mode 100644 index 419ee3a3ac1..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsninc.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned char * _mbsninc(const unsigned char *str, size_t n) -{ - unsigned char *s = (unsigned char *)str; - while(*s != 0 && n > 0) { - if (!_ismbblead(*s) ) - n--; - s++; - } - - return s; -} diff --git a/reactos/lib/crtdll/mbstring/mbsnset.c b/reactos/lib/crtdll/mbstring/mbsnset.c deleted file mode 100644 index af367ee9949..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsnset.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsset.c - * PURPOSE: Fills a string with a multibyte character - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include - -size_t _mbclen2(const unsigned int s); - -/* - * @implemented - */ -unsigned char * _mbsnset(unsigned char *src, unsigned int val, size_t count) -{ - unsigned char *char_src = (unsigned char *)src; - unsigned short *short_src = (unsigned short *)src; - - if ( _mbclen2(val) == 1 ) { - - while(count > 0) { - *char_src = val; - char_src++; - count--; - } - *char_src = 0; - } - else { - while(count > 0) { - *short_src = val; - short_src++; - count-=2; - } - *short_src = 0; - } - - return src; -} - -/* - * @implemented - */ -unsigned char * _mbsnbset(unsigned char *src, unsigned int val, size_t count) -{ - unsigned char *char_src = (unsigned char *)src; - unsigned short *short_src = (unsigned short *)src; - - if ( _mbclen2(val) == 1 ) { - - while(count > 0) { - *char_src = val; - char_src++; - count--; - } - *char_src = 0; - } - else { - while(count > 0) { - *short_src = val; - short_src++; - count-=2; - } - *short_src = 0; - } - - return src; -} diff --git a/reactos/lib/crtdll/mbstring/mbsset.c b/reactos/lib/crtdll/mbstring/mbsset.c deleted file mode 100644 index f6067f2b8a9..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsset.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsset.c - * PURPOSE: Fills a string with a multibyte character - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ - -#include - -size_t _mbclen2(const unsigned int s); - -/* - * @implemented - */ -unsigned char * _mbsset(unsigned char *src, unsigned int c) -{ - unsigned char *char_src = src; - unsigned short *short_src = (unsigned short *)src; - - if ( _mbclen2(c) == 1 ) { - - while(*char_src != 0) { - *char_src = c; - char_src++; - } - *char_src = 0; - } - else { - while(*short_src != 0) { - *short_src = c; - short_src++; - } - *short_src = 0; - } - - return src; -} diff --git a/reactos/lib/crtdll/mbstring/mbsupr.c b/reactos/lib/crtdll/mbstring/mbsupr.c deleted file mode 100644 index 3ac3e61fe54..00000000000 --- a/reactos/lib/crtdll/mbstring/mbsupr.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/mbstring/mbsncmp.c - * PURPOSE: - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 12/04/99: Created - */ -#include -#include - -unsigned int _mbbtoupper(unsigned int c) -{ - if (!_ismbblead(c) ) - return toupper(c); - - return c; -} - -// codepage 952 -#define CASE_DIFF (0x8281 - 0x8260) - -/* - * @implemented - */ -unsigned int _mbctoupper(unsigned int c) -{ - - if ((c & 0xFF00) != 0) { -// true multibyte case conversion needed - if ( _ismbcupper(c) ) - return c + CASE_DIFF; - - } else - return _mbbtoupper(c); - - return 0; -} - -/* - * @implemented - */ -unsigned char * _mbsupr(unsigned char *x) -{ - unsigned char *y=x; - while (*y) { - if (!_ismbblead(*y) ) - *y = toupper(*y); - else { - *y=_mbctoupper(*(unsigned short *)y); - y++; - } - } - return x; -} diff --git a/reactos/lib/crtdll/process/dll.c b/reactos/lib/crtdll/process/dll.c deleted file mode 100644 index 771732dd590..00000000000 --- a/reactos/lib/crtdll/process/dll.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/process/dll.c - * PURPOSE: Dll support routines - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 04/03/99: Created - */ - -#include "precomp.h" -#include - - -/* - * @implemented - */ -void* _loaddll(char* name) -{ - return LoadLibraryA(name); -} - -/* - * @implemented - */ -int _unloaddll(void* handle) -{ - return FreeLibrary(handle); -} - -/* - * @implemented - */ -FARPROC _getdllprocaddr(void* hModule, char* lpProcName, int iOrdinal) -{ - if (lpProcName != NULL) - return GetProcAddress(hModule, lpProcName); - else - return GetProcAddress(hModule, (LPSTR)iOrdinal); - return (NULL); -} diff --git a/reactos/lib/crtdll/process/threadid.c b/reactos/lib/crtdll/process/threadid.c deleted file mode 100644 index 2b17a83c7fc..00000000000 --- a/reactos/lib/crtdll/process/threadid.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "precomp.h" -#include - -/* - * @implemented - */ -unsigned long __threadid (void) -{ - return GetCurrentThreadId(); -} - -/* - * @implemented - */ -void *__threadhandle(void) -{ - return GetCurrentThread(); -} diff --git a/reactos/lib/crtdll/signal/xcptfil.c b/reactos/lib/crtdll/signal/xcptfil.c deleted file mode 100644 index 9bf6d92ecfa..00000000000 --- a/reactos/lib/crtdll/signal/xcptfil.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "precomp.h" - - -/* - * @unimplemented - */ -int _XcptFilter ( - DWORD ExceptionCode, - struct _EXCEPTION_POINTERS * ExceptionInfo - ) -{ - //fixme XcptFilter -// return UnhandledExceptionFilter(ExceptionInfo); - return 0; -} diff --git a/reactos/lib/crtdll/stdio/allocfil.c b/reactos/lib/crtdll/stdio/allocfil.c deleted file mode 100644 index 139cf0efa42..00000000000 --- a/reactos/lib/crtdll/stdio/allocfil.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include - - -FILE * __alloc_file(void); - -char __validfp (FILE *f) -{ - if ( (unsigned int)f < 256) - return FALSE; - - if( f == NULL || (int)f== -1 ) - return FALSE; - - return TRUE; -} - -/* A FILE* is considered "free" if its flag is zero. */ - -FILE *__alloc_file(void) -{ - __file_rec *fr = __file_rec_list; - __file_rec **last_fr = &__file_rec_list; - FILE *rv=0; - int i; - - /* Try to find an empty slot */ - while (fr) - { - last_fr = &(fr->next); - - /* If one of the existing slots is available, return it */ - for (i=0; icount; i++) - { - if (fr->files[i]->_flag == 0) - { - return fr->files[i]; - } - } - - /* If this one is full, go to the next */ - if (fr->count == __FILE_REC_MAX) - fr = fr->next; - else - /* it isn't full, we can add to it */ - break; - } - if (!fr) - { - /* add another one to the end, make it empty */ - fr = *last_fr = (__file_rec *)malloc(sizeof(__file_rec)); - if (fr == 0) - return 0; - fr->next = 0; - fr->count = 0; - } - /* fr is a pointer to a rec with empty slots in it */ - rv = fr->files[fr->count] = (FILE *)malloc(sizeof(FILE)); - if (rv == 0) - return 0; - memset(rv, 0, sizeof(FILE)); - fr->count ++; - return rv; -} - - -/* - * @implemented - */ -int _fcloseall( void ) -{ - __file_rec *fr = __file_rec_list; - __file_rec **last_fr = &__file_rec_list; - - int total_closed = 0; - int i = 0; - - /* Try to find an empty slot */ - while (fr) - { - last_fr = &(fr->next); - - /* If one of the existing slots is available, return it */ - for (i=0; icount; i++) - if (fr->files[i]->_flag != 0) { - fclose(fr->files[i]); - total_closed++; - } - - /* If this one is full, go to the next */ - if (fr->count == __FILE_REC_MAX) - fr = fr->next; - else - /* it isn't full, we can add to it */ - break; - } - return total_closed; -} diff --git a/reactos/lib/crtdll/stdio/fdopen.c b/reactos/lib/crtdll/stdio/fdopen.c deleted file mode 100644 index 1bdb627b220..00000000000 --- a/reactos/lib/crtdll/stdio/fdopen.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include - -FILE * __alloc_file(void); - - -/* - * @implemented - */ -FILE *_fdopen(int handle, char *mode) -{ - FILE *file; - int rw; - - if ( handle == 0 ) - return stdin; - - if ( handle == 1 ) - return stdout; - - if ( handle == 2 ) - return stderr; - - if ( handle == 3 ) - return stdaux; - - if ( handle == 4 ) - return stdprn; - - file = __alloc_file(); - if (file == NULL) - return NULL; - file->_file = handle; - - rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); - - if (*mode == 'a') - _lseek(handle, 0, SEEK_END); - - file->_cnt = 0; - file->_file = handle; - file->_bufsiz = 0; - -// The mode of the stream must be compatible with the mode of the file descriptor. -// this should be checked. - - if (rw) - file->_flag = _IOREAD | _IOWRT; - else if (*mode == 'r') - file->_flag = _IOREAD; - else - file->_flag = _IOWRT; - - file->_base = file->_ptr = NULL; - - return file; -} diff --git a/reactos/lib/crtdll/stdio/ferror.c b/reactos/lib/crtdll/stdio/ferror.c deleted file mode 100644 index 8192ee0bd62..00000000000 --- a/reactos/lib/crtdll/stdio/ferror.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -#ifdef ferror -#undef ferror -int ferror(FILE *stream); -#endif - -/* - * @implemented - */ -int ferror(FILE *stream) -{ - return stream->_flag & _IOERR; -} diff --git a/reactos/lib/crtdll/stdio/fflush.c b/reactos/lib/crtdll/stdio/fflush.c deleted file mode 100644 index 83852e65747..00000000000 --- a/reactos/lib/crtdll/stdio/fflush.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/kbhit.c - * PURPOSE: Checks for keyboard hits - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include -#include -#include - - -/* - * @implemented - */ -int fflush(FILE *f) -{ - char *base; - int n, rn; - - - - if (f == NULL) - { - int e = errno; - - __set_errno(0); - _fwalk((void (*)(FILE *))fflush); - if (*_errno()) - return EOF; - __set_errno(e); - return 0; - } - - -// nothing to do if stream can not be written to - - if ( !OPEN4WRITING(f) ) { - __set_errno (EINVAL); - return 0; - } - -// discard any unget characters - - f->_flag &= ~_IOUNGETC; - - -// check for buffered dirty block - - if ( (f->_flag&(_IODIRTY|_IONBF)) ==_IODIRTY && f->_base != NULL) - { - - base = f->_base; - - -// if the buffer is read ahead and dirty we will flush it entirely -// else the buffer is appended to the file to the extend it has valid bytes - - if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) - rn = n = f->_ptr - base + f->_cnt; - else - rn = n = f->_ptr - base; - - f->_ptr = base; - - if ((f->_flag & _IOFBF) == _IOFBF) { - if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) - _lseek(fileno(f),-rn, SEEK_CUR); - } - - f->_flag &= ~_IOAHEAD; - - - f->_cnt = (f->_flag&(_IOLBF|_IONBF)) ? 0 : f->_bufsiz; - -// how can write return less than rn without being on error ??? - -// possibly commit the flushed data -// better open the file in write through mode - - do { - n = _write(fileno(f), base, rn); - if (n <= 0) { - f->_flag |= _IOERR; - return EOF; - } - rn -= n; - base += n; - } while (rn > 0); - f->_flag &= ~_IODIRTY; - -// commit flushed data -// _commit(fileno(f)); - } - if (OPEN4READING(f) && OPEN4WRITING(f) ) - { - f->_cnt = 0; - f->_ptr = f->_base; - } - return 0; -} - -/* - * @implemented - */ -int _flushall( void ) -{ - return fflush(NULL); -} diff --git a/reactos/lib/crtdll/stdio/fgetc.c b/reactos/lib/crtdll/stdio/fgetc.c deleted file mode 100644 index 0852a71f5ad..00000000000 --- a/reactos/lib/crtdll/stdio/fgetc.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/stdio/fgetc.c - * PURPOSE: Get a character string from stdin - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Appropriated for Reactos - 25/02/99: Added fgetwc - */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -/* - * @implemented - */ -int fgetc(FILE *f) -{ - return getc(f); -} - -/* - * @implemented - */ -wint_t fgetwc(FILE *f) -{ - return getwc(f); -} diff --git a/reactos/lib/crtdll/stdio/fgetpos.c b/reactos/lib/crtdll/stdio/fgetpos.c deleted file mode 100644 index 94b03b74843..00000000000 --- a/reactos/lib/crtdll/stdio/fgetpos.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -/* - * @implemented - */ -int fgetpos(FILE *stream, fpos_t *pos) -{ - if (stream && pos) - { - *pos = (fpos_t)ftell(stream); - return 0; - } - //errno = EFAULT; - return 1; -} diff --git a/reactos/lib/crtdll/stdio/fileno.c b/reactos/lib/crtdll/stdio/fileno.c deleted file mode 100644 index f10681dca5e..00000000000 --- a/reactos/lib/crtdll/stdio/fileno.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -#undef fileno -int fileno(FILE *f) -{ - return f->_file; -} - - -/* - * @implemented - */ -int _fileno(FILE *f) -{ - return f->_file; -} diff --git a/reactos/lib/crtdll/stdio/fopen.c b/reactos/lib/crtdll/stdio/fopen.c deleted file mode 100644 index 485764190c5..00000000000 --- a/reactos/lib/crtdll/stdio/fopen.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include - -//might change fopen(file,mode) -> fsopen(file,mode,_SH_DENYNO); - -FILE * __alloc_file(void); - - -/* - * @implemented - */ -FILE* fopen(const char *file, const char *mode) -{ - FILE *f; - int fd, rw, oflags = 0; - char tbchar; - - if (file == 0) - return 0; - if (mode == 0) - return 0; - - f = __alloc_file(); - if (f == NULL) - return NULL; - - rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); - - switch (*mode) - { - case 'a': - oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - case 'r': - oflags = rw ? O_RDWR : O_RDONLY; - break; - case 'w': - oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - default: - return (NULL); - } - if (mode[1] == '+') - tbchar = mode[2]; - else - tbchar = mode[1]; - if (tbchar == 't') - oflags |= O_TEXT; - else if (tbchar == 'b') - oflags |= O_BINARY; - else - oflags |= (_fmode & (O_TEXT|O_BINARY)); - - fd = _open(file, oflags, 0666); - if (fd < 0) - return NULL; - -// ms crtdll ensures that writes will end up at the end of file in append mode -// we just move the file pointer to the end of file initially - if (*mode == 'a') - lseek(fd, 0, SEEK_END); - - f->_cnt = 0; - f->_file = fd; - f->_bufsiz = 0; - if (rw) - f->_flag = _IOREAD | _IOWRT; - else if (*mode == 'r') - f->_flag = _IOREAD; - else - f->_flag = _IOWRT; - - f->_base = f->_ptr = NULL; - return f; -} diff --git a/reactos/lib/crtdll/stdio/fputc.c b/reactos/lib/crtdll/stdio/fputc.c deleted file mode 100644 index f4cd15ef24a..00000000000 --- a/reactos/lib/crtdll/stdio/fputc.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -/* - * @implemented - */ -int -fputc(int c, FILE *fp) -{ - return putc(c, fp); -} - -/* - * @implemented - */ -wint_t -fputwc(wchar_t c, FILE *fp) -{ - return putwc(c,fp); -} - diff --git a/reactos/lib/crtdll/stdio/fputs.c b/reactos/lib/crtdll/stdio/fputs.c deleted file mode 100644 index e88b5c612d2..00000000000 --- a/reactos/lib/crtdll/stdio/fputs.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -#include "precomp.h" -#include -#include -#include - - -/* - * @implemented - */ -int -fputs(const char *s, FILE *f) -{ - - int r = 0; - int c; - int unbuffered; - char localbuf[BUFSIZ]; - - unbuffered = f->_flag & _IONBF; - if (unbuffered) - { - f->_flag &= ~_IONBF; - f->_ptr = f->_base = localbuf; - f->_bufsiz = BUFSIZ; - } - - while ((c = *s++)) - r = putc(c, f); - - if (unbuffered) - { - fflush(f); - f->_flag |= _IONBF; - f->_base = NULL; - f->_bufsiz = 0; - f->_cnt = 0; - } - - return(r); - -} diff --git a/reactos/lib/crtdll/stdio/freopen.c b/reactos/lib/crtdll/stdio/freopen.c deleted file mode 100644 index 09b97d4a544..00000000000 --- a/reactos/lib/crtdll/stdio/freopen.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include - - -/* - * @implemented - */ -FILE *freopen(const char *file, const char *mode, FILE *f) -{ - int fd, rw, oflags=0; - char tbchar; - - if (file == 0 || mode == 0 || f == 0) - return 0; - - rw = (mode[1] == '+'); - - fclose(f); - - switch (*mode) { - case 'a': - oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - case 'r': - oflags = rw ? O_RDWR : O_RDONLY; - break; - case 'w': - oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - default: - return NULL; - } - if (mode[1] == '+') - tbchar = mode[2]; - else - tbchar = mode[1]; - if (tbchar == 't') - oflags |= O_TEXT; - else if (tbchar == 'b') - oflags |= O_BINARY; - else - oflags |= (_fmode & (O_TEXT|O_BINARY)); - - fd = _open(file, oflags, 0666); - if (fd < 0) - return NULL; - - if (*mode == 'a') - lseek(fd, 0, SEEK_END); - - f->_cnt = 0; - f->_file = fd; - f->_bufsiz = 0; - if (rw) - f->_flag = _IOREAD | _IOWRT; - else if (*mode == 'r') - f->_flag = _IOREAD; - else - f->_flag = _IOWRT; - - f->_base = f->_ptr = NULL; - return f; -} diff --git a/reactos/lib/crtdll/stdio/fscanf.c b/reactos/lib/crtdll/stdio/fscanf.c deleted file mode 100644 index fefde0ce436..00000000000 --- a/reactos/lib/crtdll/stdio/fscanf.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - - -#include -#include -#include -#include -#include - - -/* Read formatted input from STREAM according to the format string FORMAT. */ -/* VARARGS2 */ -/* - * @implemented - */ -int fscanf(FILE *stream,const char *format, ...) -{ - va_list arg; - int done; - - va_start(arg, format); - done = __vfscanf(stream, format, arg); - va_end(arg); - - return done; -} - -/* - * @implemented - */ -int -fwscanf(FILE *stream, const wchar_t *fmt, ...) -{ - va_list arg; - int done; - char *cf; - int i,len = wcslen(fmt); - - cf = malloc(len+1); - for(i=0;i -#include -#include -#include -#include - - -/* - * @implemented - */ -int fseek(FILE *f, long offset, int ptrname) -{ - long p = -1; /* can't happen? */ - if ( f == NULL ) { - __set_errno (EINVAL); - return -1; - } - - f->_flag &= ~_IOEOF; - if (!OPEN4WRITING(f)) - { - if (f->_base && !(f->_flag & _IONBF)) - { - p = ftell(f); - if (ptrname == SEEK_CUR) - { - offset += p; - ptrname = SEEK_SET; - } - /* check if the target position is in the buffer and - optimize seek by moving inside the buffer */ - if (ptrname == SEEK_SET && (f->_flag & (_IOUNGETC|_IOREAD|_IOWRT )) == 0 - && p-offset <= f->_ptr-f->_base && offset-p <= f->_cnt) - { - f->_ptr+=offset-p; - f->_cnt+=p-offset; - return 0; - } - } - - p = lseek(fileno(f), offset, ptrname); - f->_cnt = 0; - f->_ptr = f->_base; - f->_flag &= ~_IOUNGETC; - } - else - { - p = fflush(f); - return lseek(fileno(f), offset, ptrname) == -1 || p == EOF ? - -1 : 0; - } - return p==-1 ? -1 : 0; -} diff --git a/reactos/lib/crtdll/stdio/fsetpos.c b/reactos/lib/crtdll/stdio/fsetpos.c deleted file mode 100644 index 9c66fb9a17d..00000000000 --- a/reactos/lib/crtdll/stdio/fsetpos.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -/* - * @implemented - */ -int fsetpos(FILE *stream,const fpos_t *pos) -{ - if (stream && pos) - { - fseek(stream, (long)(*pos), SEEK_SET); - return 0; - } - __set_errno(EFAULT); - return -1; -} diff --git a/reactos/lib/crtdll/stdio/fsopen.c b/reactos/lib/crtdll/stdio/fsopen.c deleted file mode 100644 index e216c7a0a34..00000000000 --- a/reactos/lib/crtdll/stdio/fsopen.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/conio/kbhit.c - * PURPOSE: Checks for keyboard hits - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include -#include - - -FILE* __alloc_file(void); - - -/* - * @implemented - */ -FILE* _fsopen(const char* file, const char* mode, int shflag) -{ - FILE* f; - int fd, rw, oflags = 0; - char tbchar; - - int shf; - - if (file == 0) - return 0; - if (mode == 0) - return 0; - - f = __alloc_file(); - if (f == NULL) - return NULL; - - rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); - - switch (*mode) - { - case 'a': - oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - case 'r': - oflags = rw ? O_RDWR : O_RDONLY; - break; - case 'w': - oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); - break; - default: - return (NULL); - } - if (mode[1] == '+') - tbchar = mode[2]; - else - tbchar = mode[1]; - if (tbchar == 't') - oflags |= O_TEXT; - else if (tbchar == 'b') - oflags |= O_BINARY; - else - oflags |= (_fmode & (O_TEXT|O_BINARY)); - - if ( shflag == _SH_DENYNO ) - shf = _S_IREAD | _S_IWRITE; - else if( shflag == _SH_DENYRD ) - shf = _S_IWRITE; - else if( shflag == _SH_DENYRW ) - shf = 0; - else if( shflag == _SH_DENYWR ) - shf = _S_IREAD; - else - shf = _S_IREAD | _S_IWRITE; - - fd = _open(file, oflags, shf); - if (fd < 0) - return NULL; - -// ms crtdll ensures that writes will end up at the end of file in append mode -// we just move the file pointer to the end of file initially - if (*mode == 'a') - lseek(fd, 0, SEEK_END); - - f->_cnt = 0; - f->_file = fd; - f->_bufsiz = 0; - if (rw) - f->_flag = _IOREAD | _IOWRT; - else if (*mode == 'r') - f->_flag = _IOREAD; - else - f->_flag = _IOWRT; - - f->_base = f->_ptr = NULL; - return f; -} diff --git a/reactos/lib/crtdll/stdio/ftell.c b/reactos/lib/crtdll/stdio/ftell.c deleted file mode 100644 index 25109101fee..00000000000 --- a/reactos/lib/crtdll/stdio/ftell.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include - - -/* - * @implemented - */ -long ftell(FILE *f) -{ - long tres; - int adjust=0; - - if (!f) - { - __set_errno(EBADF); - return -1; - } - - if (f->_cnt < 0) - f->_cnt = 0; - else if (f->_flag&_IOREAD) - { - adjust = - f->_cnt; - } - else if (f->_flag&(_IOWRT)) - { - if (f->_base && (f->_flag&_IONBF)==0) - adjust = f->_ptr - f->_base; - } - else - return -1; - - tres = lseek(fileno(f), 0L, SEEK_CUR); - if (tres<0) - return tres; - tres += adjust; - - //f->_cnt = f->_bufsiz - tres; - //f->_ptr = f->_base + tres; - - return tres; -} diff --git a/reactos/lib/crtdll/stdio/fwalk.c b/reactos/lib/crtdll/stdio/fwalk.c deleted file mode 100644 index ef747c1f166..00000000000 --- a/reactos/lib/crtdll/stdio/fwalk.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - - -// not exported by msvcrt or crtdll -__file_rec* __file_rec_list; - -void _fwalk(void (*func)(FILE*)) -{ - __file_rec* fr; - int i; - - for (fr=__file_rec_list; fr; fr=fr->next) - for (i=0; icount; i++) - if (fr->files[i]->_flag) - func(fr->files[i]); -} diff --git a/reactos/lib/crtdll/stdio/getc.c b/reactos/lib/crtdll/stdio/getc.c deleted file mode 100644 index 0b0a1c1c88f..00000000000 --- a/reactos/lib/crtdll/stdio/getc.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "precomp.h" -#include -#include -#include -#include - -//getc can be a macro -#undef getc - -/* - * @implemented - */ -int getc(FILE *fp) -{ - int c = -1; -// check for invalid stream - - if ( !__validfp (fp) ) { - __set_errno(EINVAL); - return EOF; - } -// check for read access on stream - - if ( !OPEN4READING(fp) ) { - __set_errno(EINVAL); - return -1; - } - - if(fp->_cnt > 0) { - fp->_cnt--; - c = (int)(*fp->_ptr++ & 0377); - } - else { - c = _filbuf(fp); - } - return c; -} - -// not exported - -wint_t getwc(FILE *fp) -{ - wint_t c; - - // might check on multi bytes if text mode - - if(fp->_cnt > 0) { - fp->_cnt -= sizeof(wchar_t); - c = *((wchar_t *)(fp->_ptr)); - fp->_ptr += sizeof(wchar_t); - } - else { - c = _filwbuf(fp); - } - - return c; -} - - - - diff --git a/reactos/lib/crtdll/stdio/gets.c b/reactos/lib/crtdll/stdio/gets.c deleted file mode 100644 index c0319655a1e..00000000000 --- a/reactos/lib/crtdll/stdio/gets.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/stdio/gets.c - * PURPOSE: Get a character string from stdin - * PROGRAMER: DJ Delorie - * UPDATE HISTORY: - * 28/12/98: Appropriated for Reactos - */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -char* gets(char* s) -{ - int c; - char *cs; - - cs = s; - while ((c = getchar()) != '\n' && c != EOF) - *cs++ = c; - if (c == EOF && cs==s) - return NULL; - *cs++ = '\0'; - return s; -} - -#if 0 -/* Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include -#include -#include - -link_warning (gets, "the `gets' function is dangerous and should not be used.") - - -/* Read a newline-terminated multibyte string from stdin into S, - removing the trailing newline. Return S or NULL. */ - -char * -gets (s) - char *s; -{ - register char *p = s; - register int c; - FILE *stream = stdin; - int l; - - if (!__validfp (stream) || p == NULL) - { - __set_errno (EINVAL); - return NULL; - } - - if (feof (stream) || ferror (stream)) - return NULL; - - while ((c = getc(stdin)) != EOF) { - if (c == '\n') - break; - if ( isascii(c) ) - *cs++ = c; -#ifdef _MULTIBYTE - else if ( isleadbyte(c) ) { - l = mblen(c); - while(l > 0 ) { - c = getchar(); - if ( isleadbyte(c) || c == EOF ) - return NULL; // encoding error - *cs++ = c; - l--; - } - } -#endif - else - return NULL; // suspicious input - } - - *p = '\0'; - - /* Return null if we had an error, or if we got EOF - before writing any characters. */ - - if (ferror (stream) || (feof (stream) && p == s)) - return NULL; - - return s; -} - -#endif diff --git a/reactos/lib/crtdll/stdio/getw.c b/reactos/lib/crtdll/stdio/getw.c deleted file mode 100644 index bbba2d10263..00000000000 --- a/reactos/lib/crtdll/stdio/getw.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include - - -/* - * Read a word (int) from STREAM. - * - * @implemented - */ -int _getw(FILE *stream) -{ - int w; - - /* Is there a better way? */ - if (fread( &w, sizeof(w), 1, stream) != 1) { - // EOF is a legitimate integer value so users must - // check feof or ferror to verify an EOF return. - return(EOF); - } - return(w); -} - diff --git a/reactos/lib/crtdll/stdio/perror.c b/reactos/lib/crtdll/stdio/perror.c deleted file mode 100644 index 0ad0d792428..00000000000 --- a/reactos/lib/crtdll/stdio/perror.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - - -#ifdef perror -#undef perror -void perror(const char *s); -#endif - -/* - * @implemented - */ -void perror(const char *s) -{ - - fprintf(stderr, "%s: %s\n", s, _strerror(NULL)); -} diff --git a/reactos/lib/crtdll/stdio/printf.c b/reactos/lib/crtdll/stdio/printf.c deleted file mode 100644 index 7c39a058739..00000000000 --- a/reactos/lib/crtdll/stdio/printf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include - -/* Write formatted output to stdout from the format string FORMAT. */ -/* VARARGS1 */ -/* - * @implemented - */ -int -printf (const char *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = vprintf (format, arg); - va_end (arg); - return done; -} - -/* - * @implemented - */ -int -wprintf (const wchar_t *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = vwprintf (format, arg); - va_end (arg); - return done; -} - -#ifdef USE_IN_LIBIO -# undef _IO_printf -/* This is for libg++. */ -strong_alias (printf, _IO_printf); -#endif - diff --git a/reactos/lib/crtdll/stdio/puts.c b/reactos/lib/crtdll/stdio/puts.c deleted file mode 100644 index aaf26b19eea..00000000000 --- a/reactos/lib/crtdll/stdio/puts.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include "precomp.h" -#include -#include -#include - -#undef putchar - - -/* - * @implemented - */ -int puts(const char *s) -{ - int c; - - while ((c = *s++)) - putchar(c); - return putchar('\n'); - -} diff --git a/reactos/lib/crtdll/stdio/remove.c b/reactos/lib/crtdll/stdio/remove.c deleted file mode 100644 index c29670089e6..00000000000 --- a/reactos/lib/crtdll/stdio/remove.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "precomp.h" - - -/* - * @implemented - */ -int remove(const char *fn) -{ - if (!DeleteFileA(fn)) - return -1; - return 0; -} diff --git a/reactos/lib/crtdll/stdio/rename.c b/reactos/lib/crtdll/stdio/rename.c deleted file mode 100644 index cb71b6ae788..00000000000 --- a/reactos/lib/crtdll/stdio/rename.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "precomp.h" -#include -#include - - -/* - * @implemented - */ -int rename(const char *old_, const char *new_) -{ - if ( old_ == NULL || new_ == NULL ) - return -1; - - if ( !MoveFileA(old_,new_) ) - return -1; - - return 0; -} diff --git a/reactos/lib/crtdll/stdio/rmtmp.c b/reactos/lib/crtdll/stdio/rmtmp.c deleted file mode 100644 index 69894475007..00000000000 --- a/reactos/lib/crtdll/stdio/rmtmp.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/stdio/rmtmp.c - * PURPOSE: remove temporary files in current directory - * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) - * UPDATE HISTORY: - * Created 19/01/99 - * NOTE Not tested. - */ - -#include -#include -#include - -#ifndef F_OK - #define F_OK 0x01 -#endif -#ifndef R_OK - #define R_OK 0x02 -#endif -#ifndef W_OK - #define W_OK 0x04 -#endif -#ifndef X_OK - #define X_OK 0x08 -#endif -#ifndef D_OK - #define D_OK 0x10 -#endif - -// should be replace by a closure of the tmp files -extern __file_rec *__file_rec_list; - -int _rmtmp( void ) -{ -/* -loop files and check for name_to_remove -*/ - __file_rec *fr = __file_rec_list; - __file_rec **last_fr = &__file_rec_list; - - int total_closed = 0; - int i = 0; - char temp_name[260]; - - /* Try to find an empty slot */ - while (fr) - { - last_fr = &(fr->next); - - /* If one of the existing slots is available, return it */ - for (i=0; icount; i++) { - if (fr->files[i]->_name_to_remove != NULL) { - if ( _access(fr->files[i]->_name_to_remove,W_OK) ) { - strcpy(temp_name,fr->files[i]->_name_to_remove); - fclose(fr->files[i]); - remove(temp_name); - total_closed++; - } - } - } - - /* If this one is full, go to the next */ - if (fr->count == __FILE_REC_MAX) - fr = fr->next; - else - /* it isn't full, we can add to it */ - break; - } - return total_closed; -} diff --git a/reactos/lib/crtdll/stdio/sscanf.c b/reactos/lib/crtdll/stdio/sscanf.c deleted file mode 100644 index 381f91c47fe..00000000000 --- a/reactos/lib/crtdll/stdio/sscanf.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include -#include - - -/* Read formatted input from S, according to the format string FORMAT. */ -/* VARARGS2 */ -/* - * @implemented - */ -int sscanf (const char *s,const char *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = __vsscanf (s, format, arg); - va_end (arg); - - return done; -} - -/* - * @implemented - */ -int swscanf(const wchar_t *str, const wchar_t *fmt, ...) -{ - va_list arg; - int done; - char *f , *s; - int i,len = wcslen(fmt); - - f = malloc(len+1); - for(i=0;i -#include - - -/* - * @unimplemented - */ -char *_tempnam(const char *dir,const char *prefix ) -{ - char *TempFileName = malloc(MAX_PATH); - char *d; - - if ( dir == NULL ) - d = getenv("TMP"); - else - d = (char *)dir; - -#ifdef _MSVCRT_LIB_ // TODO: check on difference? - if (GetTempFileNameA(d, prefix, 1, TempFileName) == 0) { -#else// TODO: FIXME: review which is correct - if (GetTempFileNameA(d, prefix, 0, TempFileName) == 0) { -#endif /*_MSVCRT_LIB_*/ - - free(TempFileName); - return NULL; - } - - return TempFileName; -} diff --git a/reactos/lib/crtdll/stdio/tmpfile.c b/reactos/lib/crtdll/stdio/tmpfile.c deleted file mode 100644 index 76d890d1d08..00000000000 --- a/reactos/lib/crtdll/stdio/tmpfile.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include -//#include -#include -#include -#include - - -FILE * __alloc_file(void); - -/* - * @implemented - */ -FILE * -tmpfile(void) -{ - int temp_fd; - FILE *f; - char *temp_name = tmpnam(0); - char *n_t_r = (char *)malloc(L_tmpnam); - - if (!n_t_r) - return 0; - - /* We could have a race condition, whereby another program - (in another virtual machine, or if the temporary file is - in a directory which is shared via a network) opens the - file returned by `tmpnam' between the call above and the - moment when we actually open the file below. This loop - retries the call to `tmpnam' until we actually succeed - to create the file which didn't exist before. */ - do { - // errno = 0; - temp_fd = _open(temp_name, 0, SH_DENYRW); - // if ( errno == ENOENT ) -// break; - } while (temp_fd == -1 && (temp_name = tmpnam(0)) != 0); - - if (temp_name == 0) - return 0; - - /* This should have been fdopen(temp_fd, "wb+"), but `fdopen' - is non-ANSI. So we need to dump some of its guts here. Sigh... */ - f = __alloc_file(); - if (f) - { - f->_file = temp_fd; - f->_cnt = 0; - f->_bufsiz = 0; - f->_flag = _IORMONCL | _IOREAD | _IOWRT; - f->_name_to_remove = n_t_r; - strcpy(f->_name_to_remove, temp_name); - f->_base = f->_ptr = NULL; - } - else - { - close(temp_fd); - remove(temp_name); - free(n_t_r); - } - return f; -} diff --git a/reactos/lib/crtdll/stdio/tmpnam.c b/reactos/lib/crtdll/stdio/tmpnam.c deleted file mode 100644 index e54217192d9..00000000000 --- a/reactos/lib/crtdll/stdio/tmpnam.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "precomp.h" -#include -#include - - -/* - * @implemented - */ -char * tmpnam(char *s) -{ - char PathName[MAX_PATH]; - static char static_buf[MAX_PATH]; - - GetTempPathA(MAX_PATH, PathName); - GetTempFileNameA(PathName, "ARI",007,static_buf); - strcpy(s,static_buf); - - return s; -} diff --git a/reactos/lib/crtdll/stdio/ungetc.c b/reactos/lib/crtdll/stdio/ungetc.c deleted file mode 100644 index 00cc274bc42..00000000000 --- a/reactos/lib/crtdll/stdio/ungetc.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include - - -/* - * @implemented - */ -int ungetc(int c, FILE *f) -{ - if (!__validfp (f) || !OPEN4READING(f)) { - __set_errno (EINVAL); - return EOF; - } - - if (c == EOF ) - return EOF; - - if ( f->_ptr == NULL || f->_base == NULL) - return EOF; - - if (f->_ptr == f->_base) - { - if (f->_cnt == 0) - f->_ptr++; - else - return EOF; - } - - f->_cnt++; - f->_ptr--; - if(*f->_ptr != c) - { - f->_flag |= _IOUNGETC; - *f->_ptr = c; - } - return c; -} - - -/* - * @implemented - */ -wint_t -ungetwc(wchar_t c, FILE *f) -{ - if (!__validfp (f) || !OPEN4READING(f)) { - __set_errno (EINVAL); - return EOF; - } - - if (c == (wchar_t)EOF ) - return EOF; - - if ( f->_ptr == NULL || f->_base == NULL) - return EOF; - - if (f->_ptr == f->_base) - { - if (f->_cnt == 0) - f->_ptr+=sizeof(wchar_t); - else - return EOF; - } - - f->_cnt+=sizeof(wchar_t); - f->_ptr-=sizeof(wchar_t); - - f->_flag |= _IOUNGETC; - *((wchar_t *)(f->_ptr)) = c; - - return c; -} diff --git a/reactos/lib/crtdll/stdlib/rot.c b/reactos/lib/crtdll/stdlib/rot.c deleted file mode 100644 index a5b46543e47..00000000000 --- a/reactos/lib/crtdll/stdlib/rot.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/stdlib/rot.c - * PURPOSE: Performs a bit wise rotation - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 03/04/99: Created - */ - -#include -#include - -/* - * @implemented - */ -unsigned int _rotl( unsigned int value, int shift ) -{ - int max_bits = sizeof(unsigned int)<<3; - if ( shift < 0 ) - return _rotr(value,-shift); - - if ( shift > max_bits ) - shift = shift % max_bits; - return (value << shift) | (value >> (max_bits-shift)); -} - -/* - * @implemented - */ -unsigned int _rotr( unsigned int value, int shift ) -{ - int max_bits = sizeof(unsigned int)<<3; - if ( shift < 0 ) - return _rotl(value,-shift); - - if ( shift > max_bits<<3 ) - shift = shift % max_bits; - return (value >> shift) | (value << (max_bits-shift)); -} - - -/* - * @implemented - */ -unsigned long _lrotl( unsigned long value, int shift ) -{ - int max_bits = sizeof(unsigned long)<<3; - if ( shift < 0 ) - return _lrotr(value,-shift); - - if ( shift > max_bits ) - shift = shift % max_bits; - return (value << shift) | (value >> (max_bits-shift)); -} - -/* - * @implemented - */ -unsigned long _lrotr( unsigned long value, int shift ) -{ - int max_bits = sizeof(unsigned long)<<3; - if ( shift < 0 ) - return _lrotl(value,-shift); - - if ( shift > max_bits ) - shift = shift % max_bits; - return (value >> shift) | (value << (max_bits-shift)); -} diff --git a/reactos/lib/crtdll/stdlib/senv.c b/reactos/lib/crtdll/stdlib/senv.c deleted file mode 100644 index 918c9ce107f..00000000000 --- a/reactos/lib/crtdll/stdlib/senv.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "precomp.h" -#include -#include - -#define NDEBUG -#include - - -/* - * @implemented - */ -void _searchenv(const char *file,const char *var,char *path ) -{ - char *env = getenv(var); - char *x; - char *y; - char *FilePart; - - DPRINT("_searchenv()\n"); - - x = strchr(env,'='); - if ( x != NULL ) { - *x = 0; - x++; - } - y = strchr(env,';'); - while ( y != NULL ) { - *y = 0; - if ( SearchPathA(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) { - return; - } - x = y+1; - y = strchr(env,';'); - } - return; -} diff --git a/reactos/lib/crtdll/stdlib/strtol.c b/reactos/lib/crtdll/stdlib/strtol.c deleted file mode 100644 index 0ae10c9b6e3..00000000000 --- a/reactos/lib/crtdll/stdlib/strtol.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include - - -/* - * @implemented - */ -long -strtol(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') - { - neg = 1; - c = *s++; - } - else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) - { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, or equal but the next digit is > 7 (or 8), - * the number is too big, and we will return a range error. - * - * Set any if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; - cutlim = cutoff % (unsigned long)base; - cutoff /= (unsigned long)base; - for (acc = 0, any = 0;; c = *s++) - { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else - { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) - { - acc = neg ? LONG_MIN : LONG_MAX; - __set_errno(ERANGE); - } - else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = any ? (char *)s - 1 : (char *)nptr; - return acc; -} diff --git a/reactos/lib/crtdll/stdlib/strtold.c b/reactos/lib/crtdll/stdlib/strtold.c deleted file mode 100644 index 2cdc6ec3c71..00000000000 --- a/reactos/lib/crtdll/stdlib/strtold.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -//#include - -static double powten[] = -{ - 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, -#ifdef __GNUC__ - 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L -#else - 1e256L, 1e256L, 1e256L, 1e256L -#endif -}; - -long double -_strtold(const char *s, char **sret) -{ - double r; /* result */ - int e, ne; /* exponent */ - int sign; /* +- 1.0 */ - int esign; - int flags=0; - int l2powm1; - - r = 0.0L; - sign = 1; - e = ne = 0; - esign = 1; - - while(*s && isspace(*s)) - s++; - - if (*s == '+') - s++; - else if (*s == '-') - { - sign = -1; - s++; - } - - while ((*s >= '0') && (*s <= '9')) - { - flags |= 1; - r *= 10.0L; - r += *s - '0'; - s++; - } - - if (*s == '.') - { - s++; - while ((*s >= '0') && (*s <= '9')) - { - flags |= 2; - r *= 10.0L; - r += *s - '0'; - s++; - ne++; - } - } - if (flags == 0) - { - if (sret) - *sret = (char *)s; - return 0.0L; - } - - if ((*s == 'e') || (*s == 'E')) - { - s++; - if (*s == '+') - s++; - else if (*s == '-') - { - s++; - esign = -1; - } - while ((*s >= '0') && (*s <= '9')) - { - e *= 10; - e += *s - '0'; - s++; - } - } - if (esign < 0) - { - esign = -esign; - e = -e; - } - e = e - ne; - if (e < -4096) - { - /* possibly subnormal number, 10^e would overflow */ - r *= 1.0e-2048L; - e += 2048; - } - if (e < 0) - { - e = -e; - esign = -esign; - } - if (e >= 8192) - e = 8191; - if (e) - { - double d = 1.0L; - l2powm1 = 0; - while (e) - { - if (e & 1) - d *= powten[l2powm1]; - e >>= 1; - l2powm1++; - } - if (esign > 0) - r *= d; - else - r /= d; - } - if (sret) - *sret = (char *)s; - return r * sign; - - return 0; -} diff --git a/reactos/lib/crtdll/stdlib/strtoll.c b/reactos/lib/crtdll/stdlib/strtoll.c deleted file mode 100644 index b609e79d233..00000000000 --- a/reactos/lib/crtdll/stdlib/strtoll.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include -//#include - -/* constants used in Solaris */ -#define LLONG_MIN -9223372036854775807L-1L -#define LLONG_MAX 9223372036854775807L -#define ULLONG_MAX 18446744073709551615UL - -long -strtoll(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') - { - neg = 1; - c = *s++; - } - else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) - { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - -/* to prevent overflow, we take max-1 and add 1 after division */ - cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1; - cutlim = cutoff % base; - cutoff /= base; - if (++cutlim == base) - { - cutlim = 0; - cutoff++; - } - for (acc = 0, any = 0;; c = *s++) - { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else - { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) - { - acc = neg ? LLONG_MIN : LLONG_MAX; - errno = ERANGE; - } - else if (neg) - acc *= -1; - if (endptr != 0) - *endptr = any ? (char *)s - 1 : (char *)nptr; - return acc; -} diff --git a/reactos/lib/crtdll/stdlib/strtoul.c b/reactos/lib/crtdll/stdlib/strtoul.c deleted file mode 100644 index 63ee96adcc1..00000000000 --- a/reactos/lib/crtdll/stdlib/strtoul.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include - -/* - * Convert a string to an unsigned long integer. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. - * - * @implemented - */ -unsigned long -strtoul(const char *nptr, char **endptr, int base) -{ - const char *s = nptr; - unsigned long acc; - int c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') - { - neg = 1; - c = *s++; - } - else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) - { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; - for (acc = 0, any = 0;; c = *s++) - { - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) - { - acc = ULONG_MAX; - __set_errno(ERANGE); - } - else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = any ? (char *)s - 1 : (char *)nptr; - return acc; -} diff --git a/reactos/lib/crtdll/sys_stat/futime.c b/reactos/lib/crtdll/sys_stat/futime.c deleted file mode 100644 index 4fe2137bb88..00000000000 --- a/reactos/lib/crtdll/sys_stat/futime.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -/* - * @implemented - */ -int _futime(int nHandle, struct _utimbuf* pTimes) -{ - FILETIME LastAccessTime; - FILETIME LastWriteTime; - - // check for stdin / stdout handles ?? - if (nHandle == -1) { - __set_errno(EBADF); - return -1; - } - - if (pTimes == NULL) { - pTimes = alloca(sizeof(struct _utimbuf)); - time(&pTimes->actime); - time(&pTimes->modtime); - } - - if (pTimes->actime < pTimes->modtime) { - __set_errno(EINVAL); - return -1; - } - - UnixTimeToFileTime(pTimes->actime, &LastAccessTime, 0); - UnixTimeToFileTime(pTimes->modtime, &LastWriteTime, 0); - if (!SetFileTime(_get_osfhandle(nHandle), NULL, &LastAccessTime, &LastWriteTime)) { - __set_errno(EBADF); - return -1; - } - - return 0; -} diff --git a/reactos/lib/crtdll/time/clock.c b/reactos/lib/crtdll/time/clock.c deleted file mode 100644 index 4ad606c8ffc..00000000000 --- a/reactos/lib/crtdll/time/clock.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/time/clock.c - * PURPOSE: Get elapsed time - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -#include "precomp.h" -#include -#include - -VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); - -/* - * @implemented - */ -clock_t clock ( void ) -{ - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - DWORD Remainder; - - if (!GetProcessTimes(GetCurrentProcess(),&CreationTime,&ExitTime,&KernelTime,&UserTime)) - return -1; - - return FileTimeToUnixTime(&KernelTime,&Remainder) + FileTimeToUnixTime(&UserTime,&Remainder); -} diff --git a/reactos/lib/crtdll/time/strdate.c b/reactos/lib/crtdll/time/strdate.c deleted file mode 100644 index 17df993483a..00000000000 --- a/reactos/lib/crtdll/time/strdate.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/time/strtime.c - * PURPOSE: Fills a buffer with a formatted date representation - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -#include -#include -#include -#include - - -/* - * @implemented - */ -char *_strdate( const char *datestr ) -{ - time_t t; - struct tm *d; - char *dt = (char *)datestr; - - if ( datestr == NULL ){ - __set_errno(EINVAL); - return NULL; - } - t = time(NULL); - d = localtime(&t); - sprintf(dt,"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year); - return dt; -} diff --git a/reactos/lib/crtdll/time/strftime.c b/reactos/lib/crtdll/time/strftime.c deleted file mode 100644 index 0f5c3b61b3c..00000000000 --- a/reactos/lib/crtdll/time/strftime.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include - - -#define TM_YEAR_BASE 1900 - -static const char* afmt[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", -}; -static const char* Afmt[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", - "Saturday", -}; -static const char* bfmt[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", - "Oct", "Nov", "Dec", -}; -static const char* Bfmt[] = { - "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December", -}; - -static size_t gsize; -static char* pt; - - -static int _add(const char* str) -{ - for (;; ++pt, --gsize) - { - if (!gsize) - return 0; - if (!(*pt = *str++)) - return 1; - } -} - -static int _conv(int n, int digits, char pad) -{ - static char buf[10]; - char* p; - - for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) - *p-- = n % 10 + '0'; - while (p > buf && digits-- > 0) - *p-- = pad; - return _add(++p); -} - -static size_t _fmt(const char* format, const struct tm* t) -{ - for (; *format; ++format) - { - if (*format == '%') { - if (*(format+1) == '#') {format++;} - - switch(*++format) { - case '\0': - --format; - break; - case 'A': - if (t->tm_wday < 0 || t->tm_wday > 6) - return 0; - if (!_add(Afmt[t->tm_wday])) - return 0; - continue; - case 'a': - if (t->tm_wday < 0 || t->tm_wday > 6) - return 0; - if (!_add(afmt[t->tm_wday])) - return 0; - continue; - case 'B': - if (t->tm_mon < 0 || t->tm_mon > 11) - return 0; - if (!_add(Bfmt[t->tm_mon])) - return 0; - continue; - case 'b': - case 'h': - if (t->tm_mon < 0 || t->tm_mon > 11) - return 0; - if (!_add(bfmt[t->tm_mon])) - return 0; - continue; - case 'C': - if (!_fmt("%a %b %e %H:%M:%S %Y", t)) - return 0; - continue; - case 'c': - if (!_fmt("%m/%d/%y %H:%M:%S", t)) - return 0; - continue; - case 'e': - if (!_conv(t->tm_mday, 2, ' ')) - return 0; - continue; - case 'D': - if (!_fmt("%m/%d/%y", t)) - return 0; - continue; - case 'd': - if (!_conv(t->tm_mday, 2, '0')) - return 0; - continue; - case 'H': - if (!_conv(t->tm_hour, 2, '0')) - return 0; - continue; - case 'I': - if (!_conv(t->tm_hour % 12 ? t->tm_hour % 12 : 12, 2, '0')) - return 0; - continue; - case 'j': - if (!_conv(t->tm_yday + 1, 3, '0')) - return 0; - continue; - case 'k': - if (!_conv(t->tm_hour, 2, ' ')) - return 0; - continue; - case 'l': - if (!_conv(t->tm_hour % 12 ? t->tm_hour % 12 : 12, 2, ' ')) - return 0; - continue; - case 'M': - if (!_conv(t->tm_min, 2, '0')) - return 0; - continue; - case 'm': - if (!_conv(t->tm_mon + 1, 2, '0')) - return 0; - continue; - case 'n': - if (!_add("\n")) - return 0; - continue; - case 'p': - if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) - return 0; - continue; - case 'R': - if (!_fmt("%H:%M", t)) - return 0; - continue; - case 'r': - if (!_fmt("%I:%M:%S %p", t)) - return 0; - continue; - case 'S': - if (!_conv(t->tm_sec, 2, '0')) - return 0; - continue; - case 'T': - case 'X': - if (!_fmt("%H:%M:%S", t)) - return 0; - continue; - case 't': - if (!_add("\t")) - return 0; - continue; - case 'U': - if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, 2, '0')) - return 0; - continue; - case 'W': - if (!_conv((t->tm_yday + 7 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7, 2, '0')) - return 0; - continue; - case 'w': - if (!_conv(t->tm_wday, 1, '0')) - return 0; - continue; - case 'x': - if (!_fmt("%m/%d/%y", t)) - return 0; - continue; - case 'y': - if (!_conv((t->tm_year + TM_YEAR_BASE) % 100, 2, '0')) - return 0; - continue; - case 'Y': - if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) - return 0; - continue; - case 'Z': - if (!t->tm_zone || !_add(t->tm_zone)) - return 0; - continue; - case '%': - /* - * X311J/88-090 (4.12.3.5): if conversion char is - * undefined, behavior is undefined. Print out the - * character itself as printf(3) does. - */ - default: - break; - } - } - if (!gsize--) - return 0; - *pt++ = *format; - } - return gsize; -} - -/* - * @implemented - */ -size_t -strftime(char *s, size_t maxsize, const char *format, const struct tm *t) -{ - pt = s; - if ((gsize = maxsize) < 1) - return 0; - if (_fmt(format, t)) - { - *pt = '\0'; - return maxsize - gsize; - } - return 0; -} - -/* - * @implemented - */ -size_t wcsftime(wchar_t* s, size_t maxsize, const wchar_t* format, const struct tm* t) -{ - char* x; - char* f; - int i,j; - x = malloc(maxsize); - j = wcslen(format); - f = malloc(j+1); - for (i = 0; i < j; i++) - f[i] = (char)*format; - f[i] = 0; - pt = x; - if ((gsize = maxsize) < 1) - return 0; - if (_fmt(f, t)) { - *pt = '\0'; - free(f); - for (i = 0; i < maxsize;i ++) - s[i] = (wchar_t)x[i]; - s[i] = 0; - free(x); - return maxsize - gsize; - } - for (i = 0; i < maxsize; i++) - s[i] = (wchar_t)x[i]; - s[i] = 0; - free(f); - free(x); - return 0; -} diff --git a/reactos/lib/crtdll/time/strtime.c b/reactos/lib/crtdll/time/strtime.c deleted file mode 100644 index a6a26230a1e..00000000000 --- a/reactos/lib/crtdll/time/strtime.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/time/strtime.c - * PURPOSE: Fills a buffer with a formatted time representation - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ -#include -#include -#include -#include - - -/* - * @implemented - */ -char *_strtime(char* buf) -{ - time_t t; - struct tm *d; - char *dt = (char *)buf; - - if ( buf == NULL ) { - __set_errno(EINVAL); - return NULL; - } - t = time(NULL); - d = localtime(&t); - sprintf(dt,"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec); - return dt; -} diff --git a/reactos/lib/crtdll/time/time.c b/reactos/lib/crtdll/time/time.c deleted file mode 100644 index 905083e503a..00000000000 --- a/reactos/lib/crtdll/time/time.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/crtdll/time/time.c - * PURPOSE: Get system time - * PROGRAMER: Boudewijn Dekker - * UPDATE HISTORY: - * 28/12/98: Created - */ - -/* - * DOS file system functions - * - * Copyright 1993 Erik Bos - * Copyright 1996 Alexandre Julliard - */ - -#include "precomp.h" -#include -#include - - -VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); - -/* - * @implemented - */ -time_t time(time_t* t) -{ - FILETIME SystemTime; - DWORD Remainder; - time_t tt; - GetSystemTimeAsFileTime(&SystemTime); - tt = FileTimeToUnixTime( &SystemTime,&Remainder ); - if (t) - *t = tt; - return tt; -} - -/*********************************************************************** - * DOSFS_UnixTimeToFileTime - * - * Convert a Unix time to FILETIME format. - * The FILETIME structure is a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601, 0:00. - * 'remainder' is the nonnegative number of 100-ns intervals - * corresponding to the time fraction smaller than 1 second that - * couldn't be stored in the time_t value. - */ -void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, - DWORD remainder ) -{ - /* NOTES: - - CONSTANTS: - The time difference between 1 January 1601, 00:00:00 and - 1 January 1970, 00:00:00 is 369 years, plus the leap years - from 1604 to 1968, excluding 1700, 1800, 1900. - This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total - of 134774 days. - - Any day in that period had 24 * 60 * 60 = 86400 seconds. - - The time difference is 134774 * 86400 * 10000000, which can be written - 116444736000000000 - 27111902 * 2^32 + 3577643008 - 413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768 - - If you find that these constants are buggy, please change them in all - instances in both conversion functions. - - VERSIONS: - There are two versions, one of them uses long long variables and - is presumably faster but not ISO C. The other one uses standard C - data types and operations but relies on the assumption that negative - numbers are stored as 2's complement (-1 is 0xffff....). If this - assumption is violated, dates before 1970 will not convert correctly. - This should however work on any reasonable architecture where WINE - will run. - - DETAILS: - - Take care not to remove the casts. I have tested these functions - (in both versions) for a lot of numbers. I would be interested in - results on other compilers than GCC. - - The operations have been designed to account for the possibility - of 64-bit time_t in future UNICES. Even the versions without - internal long long numbers will work if time_t only is 64 bit. - A 32-bit shift, which was necessary for that operation, turned out - not to work correctly in GCC, besides giving the warning. So I - used a double 16-bit shift instead. Numbers are in the ISO version - represented by three limbs, the most significant with 32 bit, the - other two with 16 bit each. - - As the modulo-operator % is not well-defined for negative numbers, - negative divisors have been avoided in DOSFS_FileTimeToUnixTime. - - There might be quicker ways to do this in C. Certainly so in - assembler. - - Claus Fischer, fischer@iue.tuwien.ac.at - */ - - - - - unsigned long a0; /* 16 bit, low bits */ - unsigned long a1; /* 16 bit, medium bits */ - unsigned long a2; /* 32 bit, high bits */ - - /* Copy the unix time to a2/a1/a0 */ - a0 = unix_time & 0xffff; - a1 = (unix_time >> 16) & 0xffff; - /* This is obsolete if unix_time is only 32 bits, but it does not hurt. - Do not replace this by >> 32, it gives a compiler warning and it does - not work. */ - a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 : - ~((~unix_time >> 16) >> 16)); - - /* Multiply a by 10000000 (a = a2/a1/a0) - Split the factor into 10000 * 1000 which are both less than 0xffff. */ - a0 *= 10000; - a1 = a1 * 10000 + (a0 >> 16); - a2 = a2 * 10000 + (a1 >> 16); - a0 &= 0xffff; - a1 &= 0xffff; - - a0 *= 1000; - a1 = a1 * 1000 + (a0 >> 16); - a2 = a2 * 1000 + (a1 >> 16); - a0 &= 0xffff; - a1 &= 0xffff; - - /* Add the time difference and the remainder */ - a0 += 32768 + (remainder & 0xffff); - a1 += 54590 + (remainder >> 16 ) + (a0 >> 16); - a2 += 27111902 + (a1 >> 16); - a0 &= 0xffff; - a1 &= 0xffff; - - /* Set filetime */ - filetime->dwLowDateTime = (a1 << 16) + a0; - filetime->dwHighDateTime = a2; -} - - -/*********************************************************************** - * DOSFS_FileTimeToUnixTime - * - * Convert a FILETIME format to Unix time. - * If not NULL, 'remainder' contains the fractional part of the filetime, - * in the range of [0..9999999] (even if time_t is negative). - */ -time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) -{ - /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ - - unsigned long a0; /* 16 bit, low bits */ - unsigned long a1; /* 16 bit, medium bits */ - unsigned long a2; /* 32 bit, high bits */ - unsigned long r; /* remainder of division */ - unsigned int carry; /* carry bit for subtraction */ - int negative; /* whether a represents a negative value */ - - /* Copy the time values to a2/a1/a0 */ - a2 = (unsigned long)filetime->dwHighDateTime; - a1 = ((unsigned long)filetime->dwLowDateTime ) >> 16; - a0 = ((unsigned long)filetime->dwLowDateTime ) & 0xffff; - - /* Subtract the time difference */ - if (a0 >= 32768 ) a0 -= 32768 , carry = 0; - else a0 += (1 << 16) - 32768 , carry = 1; - - if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0; - else a1 += (1 << 16) - 54590 - carry, carry = 1; - - a2 -= 27111902 + carry; - - /* If a is negative, replace a by (-1-a) */ - negative = (a2 >= ((unsigned long)1) << 31); - if (negative) - { - /* Set a to -a - 1 (a is a2/a1/a0) */ - a0 = 0xffff - a0; - a1 = 0xffff - a1; - a2 = ~a2; - } - - /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. - Split the divisor into 10000 * 1000 which are both less than 0xffff. */ - a1 += (a2 % 10000) << 16; - a2 /= 10000; - a0 += (a1 % 10000) << 16; - a1 /= 10000; - r = a0 % 10000; - a0 /= 10000; - - a1 += (a2 % 1000) << 16; - a2 /= 1000; - a0 += (a1 % 1000) << 16; - a1 /= 1000; - r += (a0 % 1000) * 10000; - a0 /= 1000; - - /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ - if (negative) - { - /* Set a to -a - 1 (a is a2/a1/a0) */ - a0 = 0xffff - a0; - a1 = 0xffff - a1; - a2 = ~a2; - - r = 9999999 - r; - } - - if (remainder) *remainder = r; - - /* Do not replace this by << 32, it gives a compiler warning and it does - not work. */ - return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; - -} - - - diff --git a/reactos/lib/crtdll/time/tz_vars.c b/reactos/lib/crtdll/time/tz_vars.c deleted file mode 100644 index 3ccf17709b5..00000000000 --- a/reactos/lib/crtdll/time/tz_vars.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - - -int _daylight_dll; -int _timezone_dll; - - -void _set_daylight_export(int value) -{ - _daylight_dll = value; -} - -void _set_timezone_export(int value) -{ - _timezone_dll = value; -} - - - diff --git a/reactos/lib/crtdll/wchar/wcscoll.c b/reactos/lib/crtdll/wchar/wcscoll.c deleted file mode 100644 index f79ed9da607..00000000000 --- a/reactos/lib/crtdll/wchar/wcscoll.c +++ /dev/null @@ -1,22 +0,0 @@ - -#include - -/* - * @unimplemented - */ -int wcscoll(const wchar_t *a1,const wchar_t *a2) -{ - /* FIXME: handle collates */ - return wcscmp(a1,a2); -} - - -/* - * @unimplemented - */ -int _wcsicoll(const wchar_t *a1,const wchar_t *a2) -{ - /* FIXME: handle collates */ - return _wcsicmp(a1,a2); -} - diff --git a/reactos/lib/d3d8thk/win32k.S b/reactos/lib/d3d8thk/win32k.S new file mode 100644 index 00000000000..3d91e68c619 --- /dev/null +++ b/reactos/lib/d3d8thk/win32k.S @@ -0,0 +1 @@ +#include "../gdi32/misc/win32k.S" diff --git a/reactos/lib/d3d8thk/win32k.c b/reactos/lib/d3d8thk/win32k.c deleted file mode 100644 index f6b4d9078db..00000000000 --- a/reactos/lib/d3d8thk/win32k.c +++ /dev/null @@ -1 +0,0 @@ -#include "../gdi32/misc/win32k.c" diff --git a/reactos/lib/dbghelp/dbghelp.c b/reactos/lib/dbghelp/dbghelp.c index 982956e5aed..287f5198926 100644 --- a/reactos/lib/dbghelp/dbghelp.c +++ b/reactos/lib/dbghelp/dbghelp.c @@ -230,14 +230,17 @@ BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProc if (fInvadeProcess) { +#ifndef __REACTOS__ if (!elf_read_wine_loader_dbg_info(pcs)) { SymCleanup(hProcess); return FALSE; } +#endif process_invade(hProcess); elf_synchronize_module_list(pcs); } + DbgPrint("SymInitialize - Success\n"); return TRUE; } diff --git a/reactos/lib/dbghelp/regex.c b/reactos/lib/dbghelp/regex.c index f8c878e715f..0410e3ebf35 100644 --- a/reactos/lib/dbghelp/regex.c +++ b/reactos/lib/dbghelp/regex.c @@ -121,7 +121,7 @@ even if config.h says that we can. */ # undef REL_ALLOC -# if defined STDC_HEADERS || defined _LIBC +# if defined STDC_HEADERS || defined _LIBC || defined _WIN32 # include # else char *malloc (); diff --git a/reactos/lib/dbghelp/stack.c b/reactos/lib/dbghelp/stack.c index 516467c5ec3..5d7e2ec2dcf 100644 --- a/reactos/lib/dbghelp/stack.c +++ b/reactos/lib/dbghelp/stack.c @@ -33,9 +33,7 @@ #include "thread.h" /* FIXME: must be included before winternl.h */ #include "winternl.h" #include "wine/debug.h" -#ifndef __REACTOS__ #include "stackframe.h" -#endif WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); @@ -78,7 +76,6 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread, PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr) { -#ifndef __REACTOS__ STACK32FRAME frame32; STACK16FRAME frame16; char ch; @@ -388,8 +385,4 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread, done_err: curr_mode = stm_done; return FALSE; -#else - /* FIXME */ - return FALSE; -#endif } diff --git a/reactos/lib/dbghelp/stackframe.h b/reactos/lib/dbghelp/stackframe.h new file mode 100644 index 00000000000..c0e3e663a9e --- /dev/null +++ b/reactos/lib/dbghelp/stackframe.h @@ -0,0 +1,94 @@ +/* + * 16-bit and 32-bit mode stack frame layout + * + * Copyright 1995, 1998 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_STACKFRAME_H +#define __WINE_STACKFRAME_H + +#include +#include +#include + +#define SELECTOROF(ptr) (HIWORD(ptr)) +#define OFFSETOF(ptr) (LOWORD(ptr)) + +#include + + /* 32-bit stack layout after CallTo16() */ +typedef struct _STACK32FRAME +{ + DWORD restore_addr; /* 00 return address for restoring code selector */ + DWORD codeselector; /* 04 code selector to restore */ + EXCEPTION_REGISTRATION_RECORD frame; /* 08 Exception frame */ + SEGPTR frame16; /* 10 16-bit frame from last CallFrom16() */ + DWORD edi; /* 14 saved registers */ + DWORD esi; /* 18 */ + DWORD ebx; /* 1c */ + DWORD ebp; /* 20 saved 32-bit frame pointer */ + DWORD retaddr; /* 24 return address */ + DWORD target; /* 28 target address / CONTEXT86 pointer */ + DWORD nb_args; /* 2c number of 16-bit argument bytes */ +} STACK32FRAME; + + /* 16-bit stack layout after CallFrom16() */ +typedef struct _STACK16FRAME +{ + STACK32FRAME *frame32; /* 00 32-bit frame from last CallTo16() */ + DWORD edx; /* 04 saved registers */ + DWORD ecx; /* 08 */ + DWORD ebp; /* 0c */ + WORD ds; /* 10 */ + WORD es; /* 12 */ + WORD fs; /* 14 */ + WORD gs; /* 16 */ + DWORD callfrom_ip; /* 18 callfrom tail IP */ + DWORD module_cs; /* 1c module code segment */ + DWORD relay; /* 20 relay function address */ + WORD entry_ip; /* 22 entry point IP */ + DWORD entry_point; /* 26 API entry point to call, reused as mutex count */ + WORD bp; /* 2a 16-bit stack frame chain */ + WORD ip; /* 2c return address */ + WORD cs; /* 2e */ +} STACK16FRAME; + +#include + +#define CURRENT_STACK16 ((STACK16FRAME*)MapSL(NtCurrentTeb()->cur_stack)) +#define CURRENT_DS (CURRENT_STACK16->ds) + +/* Push bytes on the 16-bit stack of a thread; + * return a segptr to the first pushed byte + */ +static inline SEGPTR stack16_push( int size ) +{ + STACK16FRAME *frame = CURRENT_STACK16; + memmove( (char*)frame - size, frame, sizeof(*frame) ); + NtCurrentTeb()->cur_stack -= size; + return (SEGPTR)(NtCurrentTeb()->cur_stack + sizeof(*frame)); +} + +/* Pop bytes from the 16-bit stack of a thread */ +static inline void stack16_pop( int size ) +{ + STACK16FRAME *frame = CURRENT_STACK16; + memmove( (char*)frame + size, frame, sizeof(*frame) ); + NtCurrentTeb()->cur_stack += size; +} + +#endif /* __WINE_STACKFRAME_H */ diff --git a/reactos/lib/dbghelp/type.c b/reactos/lib/dbghelp/type.c index bad1540a6ae..6c9fd2ed48f 100644 --- a/reactos/lib/dbghelp/type.c +++ b/reactos/lib/dbghelp/type.c @@ -755,9 +755,7 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase, module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN); if (!(module = module_get_debug(pcs, module))) { -#ifndef __REACTOS__ FIXME("Someone didn't properly set ModBase (%s)\n", wine_dbgstr_longlong(ModBase)); -#endif return FALSE; } diff --git a/reactos/lib/dinput/dinput_main.c b/reactos/lib/dinput/dinput_main.c index 3bfcba05e70..900b7c820a3 100644 --- a/reactos/lib/dinput/dinput_main.c +++ b/reactos/lib/dinput/dinput_main.c @@ -744,13 +744,13 @@ HRESULT WINAPI DINPUT_DllCanUnloadNow(void) HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) { *ppv = (LPVOID)&DINPUT_CF; IClassFactory_AddRef((IClassFactory*)*ppv); return S_OK; } - FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + FIXME("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/reactos/lib/dinput/joystick_linux.c b/reactos/lib/dinput/joystick_linux.c index 8b75fb06288..101d900e953 100644 --- a/reactos/lib/dinput/joystick_linux.c +++ b/reactos/lib/dinput/joystick_linux.c @@ -157,7 +157,9 @@ static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN return FALSE; } - if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) { + if ((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 8))) { /* check whether we have a joystick */ sprintf(dev, "%s%d", JOYDEV, id); if ((fd = open(dev,O_RDONLY)) < 0) { @@ -205,7 +207,9 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN return FALSE; } - if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) { + if ((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 8))) { /* check whether we have a joystick */ sprintf(dev, "%s%d", JOYDEV, id); if ((fd = open(dev,O_RDONLY)) < 0) { @@ -552,7 +556,10 @@ static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, newDevice->devcaps.dwSize = sizeof(newDevice->devcaps); newDevice->devcaps.dwFlags = DIDC_ATTACHED; - newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK; + if (newDevice->dinput->version >= 8) + newDevice->devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + else + newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); newDevice->devcaps.dwFFSamplePeriod = 0; newDevice->devcaps.dwFFMinTimeResolution = 0; newDevice->devcaps.dwFirmwareRevision = 0; @@ -573,18 +580,12 @@ static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, FAILED: hr = DIERR_OUTOFMEMORY; FAILED1: - if (newDevice->axis_map) - HeapFree(GetProcessHeap(),0,newDevice->axis_map); - if (newDevice->name) - HeapFree(GetProcessHeap(),0,newDevice->name); - if (newDevice->props) - HeapFree(GetProcessHeap(),0,newDevice->props); - if (newDevice->user_df->rgodf) - HeapFree(GetProcessHeap(),0,newDevice->user_df->rgodf); - if (newDevice->user_df) - HeapFree(GetProcessHeap(),0,newDevice->user_df); - if (newDevice) - HeapFree(GetProcessHeap(),0,newDevice); + HeapFree(GetProcessHeap(),0,newDevice->axis_map); + HeapFree(GetProcessHeap(),0,newDevice->name); + HeapFree(GetProcessHeap(),0,newDevice->props); + HeapFree(GetProcessHeap(),0,newDevice->user_df->rgodf); + HeapFree(GetProcessHeap(),0,newDevice->user_df); + HeapFree(GetProcessHeap(),0,newDevice); *pdev = 0; return hr; @@ -671,16 +672,13 @@ static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface) return ref; /* Free the device name */ - if (This->name) - HeapFree(GetProcessHeap(),0,This->name); + HeapFree(GetProcessHeap(),0,This->name); /* Free the axis map */ - if (This->axis_map) - HeapFree(GetProcessHeap(),0,This->axis_map); + HeapFree(GetProcessHeap(),0,This->axis_map); /* Free the data queue */ - if (This->data_queue != NULL) - HeapFree(GetProcessHeap(),0,This->data_queue); + HeapFree(GetProcessHeap(),0,This->data_queue); /* Free the DataFormat */ HeapFree(GetProcessHeap(), 0, This->user_df->rgodf); @@ -764,12 +762,9 @@ static HRESULT WINAPI JoystickAImpl_SetDataFormat( FAILED: WARN("out of memory\n"); - if (new_props) - HeapFree(GetProcessHeap(),0,new_props); - if (new_rgodf) - HeapFree(GetProcessHeap(),0,new_rgodf); - if (new_df) - HeapFree(GetProcessHeap(),0,new_df); + HeapFree(GetProcessHeap(),0,new_props); + HeapFree(GetProcessHeap(),0,new_rgodf); + HeapFree(GetProcessHeap(),0,new_df); return DIERR_OUTOFMEMORY; } @@ -1580,10 +1575,7 @@ HRESULT WINAPI JoystickAImpl_GetDeviceInfo( pdidi->guidInstance = GUID_Joystick; pdidi->guidProduct = DInput_Wine_Joystick_GUID; /* we only support traditional joysticks for now */ - if (This->dinput->version >= 8) - pdidi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - pdidi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + pdidi->dwDevType = This->devcaps.dwDevType; strcpy(pdidi->tszInstanceName, "Joystick"); strcpy(pdidi->tszProductName, This->name); if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) { @@ -1618,10 +1610,7 @@ HRESULT WINAPI JoystickWImpl_GetDeviceInfo( pdidi->guidInstance = GUID_Joystick; pdidi->guidProduct = DInput_Wine_Joystick_GUID; /* we only support traditional joysticks for now */ - if (This->dinput->version >= 8) - pdidi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - pdidi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + pdidi->dwDevType = This->devcaps.dwDevType; MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, pdidi->tszInstanceName, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, This->name, -1, pdidi->tszProductName, MAX_PATH); if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3W)) { diff --git a/reactos/lib/dinput/joystick_linuxinput.c b/reactos/lib/dinput/joystick_linuxinput.c index 514715b578b..673cc3852fc 100644 --- a/reactos/lib/dinput/joystick_linuxinput.c +++ b/reactos/lib/dinput/joystick_linuxinput.c @@ -175,8 +175,10 @@ static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN if (id != 0) return FALSE; - if ((dwDevType != 0) && (GET_DIDEVICE_TYPE(dwDevType) != DIDEVTYPE_JOYSTICK)) - return FALSE; + if (!((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 8)))) + return FALSE; if (dwFlags & DIEDFL_FORCEFEEDBACK) return FALSE; @@ -211,8 +213,10 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN if (id != 0) return FALSE; - if ((dwDevType != 0) && (GET_DIDEVICE_TYPE(dwDevType) != DIDEVTYPE_JOYSTICK)) - return FALSE; + if (!((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_JOYSTICK) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 8)))) + return FALSE; if (dwFlags & DIEDFL_FORCEFEEDBACK) return FALSE; @@ -229,7 +233,10 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN lpddi->guidProduct = DInput_Wine_Joystick_GUID; lpddi->guidFFDriver = GUID_NULL; - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL<<8); + if (version >= 8) + lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + else + lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, lpddi->tszInstanceName, MAX_PATH); /* ioctl JSIOCGNAME(len) */ @@ -339,8 +346,7 @@ static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface) return ref; /* Free the data queue */ - if (This->data_queue != NULL) - HeapFree(GetProcessHeap(),0,This->data_queue); + HeapFree(GetProcessHeap(),0,This->data_queue); /* Free the DataFormat */ HeapFree(GetProcessHeap(), 0, This->df); @@ -756,7 +762,10 @@ static HRESULT WINAPI JoystickAImpl_GetCapabilities( wasacquired = 0; } lpDIDevCaps->dwFlags = DIDC_ATTACHED; - lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK; + if (This->dinput->version >= 8) + lpDIDevCaps->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + else + lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); axes=0; for (i=0;iabsbits,i)) axes++; diff --git a/reactos/lib/dinput/keyboard.c b/reactos/lib/dinput/keyboard.c index 7110679d172..41630d0e8dc 100644 --- a/reactos/lib/dinput/keyboard.c +++ b/reactos/lib/dinput/keyboard.c @@ -266,7 +266,7 @@ static BOOL keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) || - ((dwDevType == DI8DEVTYPE_KEYBOARD) && (version >= 8))) { + (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 8))) { TRACE("Enumerating the Keyboard device\n"); fill_keyboard_dideviceinstanceA(lpddi, version); @@ -284,7 +284,7 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) || - ((dwDevType == DI8DEVTYPE_KEYBOARD) && (version >= 8))) { + (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 8))) { TRACE("Enumerating the Keyboard device\n"); fill_keyboard_dideviceinstanceW(lpddi, version); @@ -387,8 +387,7 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface) #endif /* Free the data queue */ - if (This->buffer != NULL) - HeapFree(GetProcessHeap(),0,This->buffer); + HeapFree(GetProcessHeap(),0,This->buffer); DeleteCriticalSection(&(This->crit)); @@ -649,36 +648,34 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps) { - SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + DIDEVCAPS devcaps; - TRACE("(this=%p,%p)\n",This,lpDIDevCaps); + TRACE("(this=%p,%p)\n",This,lpDIDevCaps); - if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) { - lpDIDevCaps->dwFlags = DIDC_ATTACHED; + if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) { + WARN("invalid parameter\n"); + return DIERR_INVALIDPARAM; + } + + devcaps.dwSize = lpDIDevCaps->dwSize; + devcaps.dwFlags = DIDC_ATTACHED; if (This->dinput->version >= 8) - lpDIDevCaps->dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); + devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); else - lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); - lpDIDevCaps->dwAxes = 0; - lpDIDevCaps->dwButtons = 256; - lpDIDevCaps->dwPOVs = 0; - lpDIDevCaps->dwFFSamplePeriod = 0; - lpDIDevCaps->dwFFMinTimeResolution = 0; - lpDIDevCaps->dwFirmwareRevision = 100; - lpDIDevCaps->dwHardwareRevision = 100; - lpDIDevCaps->dwFFDriverVersion = 0; - } else if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS_DX3)) { - lpDIDevCaps->dwFlags = DIDC_ATTACHED; - lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); - lpDIDevCaps->dwAxes = 0; - lpDIDevCaps->dwButtons = 256; - lpDIDevCaps->dwPOVs = 0; - } else { - WARN("invalid parameter\n"); - return DIERR_INVALIDPARAM; - } + devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); + devcaps.dwAxes = 0; + devcaps.dwButtons = 256; + devcaps.dwPOVs = 0; + devcaps.dwFFSamplePeriod = 0; + devcaps.dwFFMinTimeResolution = 0; + devcaps.dwFirmwareRevision = 100; + devcaps.dwHardwareRevision = 100; + devcaps.dwFFDriverVersion = 0; - return DI_OK; + memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize); + + return DI_OK; } /****************************************************************************** diff --git a/reactos/lib/dinput/mouse.c b/reactos/lib/dinput/mouse.c index e0602f0a77a..96e849bf186 100644 --- a/reactos/lib/dinput/mouse.c +++ b/reactos/lib/dinput/mouse.c @@ -220,7 +220,7 @@ static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINST if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) || - ((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) { + (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 8))) { TRACE("Enumerating the mouse device\n"); fill_mouse_dideviceinstanceA(lpddi, version); @@ -238,7 +238,7 @@ static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINST if ((dwDevType == 0) || ((dwDevType == DIDEVTYPE_MOUSE) && (version < 8)) || - ((dwDevType == DI8DEVTYPE_MOUSE) && (version >= 8))) { + (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 8))) { TRACE("Enumerating the mouse device\n"); fill_mouse_dideviceinstanceW(lpddi, version); @@ -351,8 +351,7 @@ static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface) return ref; /* Free the data queue */ - if (This->data_queue != NULL) - HeapFree(GetProcessHeap(),0,This->data_queue); + HeapFree(GetProcessHeap(),0,This->data_queue); #ifndef __REACTOS__ if (This->hook) { @@ -458,7 +457,7 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara /* Only allow mouse events every 10 ms. * This is to allow the cursor to start acceleration before * the warps happen. But if it involves a mouse button event we - * allow it since we don't want to loose the clicks. + * allow it since we don't want to lose the clicks. */ if (((GetCurrentTime() - last_event) < 10) && wparam == WM_MOUSEMOVE) @@ -527,9 +526,9 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara switch(wparam) { case WM_LBUTTONDOWN: - GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0xFF, + GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x80, hook->time, This->dinput->evsequence++); - This->m_state.rgbButtons[0] = 0xFF; + This->m_state.rgbButtons[0] = 0x80; break; case WM_LBUTTONUP: GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00, @@ -537,9 +536,9 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara This->m_state.rgbButtons[0] = 0x00; break; case WM_RBUTTONDOWN: - GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0xFF, + GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x80, hook->time, This->dinput->evsequence++); - This->m_state.rgbButtons[1] = 0xFF; + This->m_state.rgbButtons[1] = 0x80; break; case WM_RBUTTONUP: GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00, @@ -547,9 +546,9 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara This->m_state.rgbButtons[1] = 0x00; break; case WM_MBUTTONDOWN: - GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0xFF, + GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x80, hook->time, This->dinput->evsequence++); - This->m_state.rgbButtons[2] = 0xFF; + This->m_state.rgbButtons[2] = 0x80; break; case WM_MBUTTONUP: GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00, @@ -1115,33 +1114,31 @@ static HRESULT WINAPI SysMouseAImpl_GetCapabilities( LPDIDEVCAPS lpDIDevCaps) { SysMouseImpl *This = (SysMouseImpl *)iface; - + DIDEVCAPS devcaps; + TRACE("(this=%p,%p)\n",This,lpDIDevCaps); - - if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) { - lpDIDevCaps->dwFlags = DIDC_ATTACHED; - if (This->dinput->version >= 8) - lpDIDevCaps->dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8); - else - lpDIDevCaps->dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); - lpDIDevCaps->dwAxes = 3; - lpDIDevCaps->dwButtons = 3; - lpDIDevCaps->dwPOVs = 0; - lpDIDevCaps->dwFFSamplePeriod = 0; - lpDIDevCaps->dwFFMinTimeResolution = 0; - lpDIDevCaps->dwFirmwareRevision = 100; - lpDIDevCaps->dwHardwareRevision = 100; - lpDIDevCaps->dwFFDriverVersion = 0; - } else if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS_DX3)) { - lpDIDevCaps->dwFlags = DIDC_ATTACHED; - lpDIDevCaps->dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); - lpDIDevCaps->dwAxes = 3; - lpDIDevCaps->dwButtons = 3; - lpDIDevCaps->dwPOVs = 0; - } else { + + if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) { WARN("invalid parameter\n"); return DIERR_INVALIDPARAM; } + + devcaps.dwSize = lpDIDevCaps->dwSize; + devcaps.dwFlags = DIDC_ATTACHED; + if (This->dinput->version >= 8) + devcaps.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8); + else + devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); + devcaps.dwAxes = 3; + devcaps.dwButtons = 3; + devcaps.dwPOVs = 0; + devcaps.dwFFSamplePeriod = 0; + devcaps.dwFFMinTimeResolution = 0; + devcaps.dwFirmwareRevision = 100; + devcaps.dwHardwareRevision = 100; + devcaps.dwFFDriverVersion = 0; + + memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize); return DI_OK; } diff --git a/reactos/lib/directory.xml b/reactos/lib/directory.xml index 89e3be5c736..c082b1200f3 100644 --- a/reactos/lib/directory.xml +++ b/reactos/lib/directory.xml @@ -28,6 +28,9 @@ + + + @@ -94,6 +97,9 @@ + + + @@ -143,7 +149,6 @@ - @@ -179,6 +184,9 @@ + + + @@ -206,6 +214,9 @@ + + + diff --git a/reactos/lib/epsapi/enum/drivers.c b/reactos/lib/epsapi/enum/drivers.c index 5e6bc6d0b72..5142efdce58 100644 --- a/reactos/lib/epsapi/enum/drivers.c +++ b/reactos/lib/epsapi/enum/drivers.c @@ -67,7 +67,7 @@ NTSTATUS NTAPI PsaCaptureSystemModules(OUT PSYSTEM_MODULE_INFORMATION *SystemModules) { SIZE_T nSize = 0; - PSYSTEM_MODULE_INFORMATION psmModules; + PSYSTEM_MODULE_INFORMATION psmModules = NULL; NTSTATUS Status; #if 0 @@ -94,7 +94,7 @@ PsaCaptureSystemModules(OUT PSYSTEM_MODULE_INFORMATION *SystemModules) pool/heap, we try to determine the buffer size in advance, knowing that the number of elements is unlikely to change */ nSize = sizeof(SYSTEM_MODULE_INFORMATION) + - ((psmModules->Count - 1) * sizeof(SYSTEM_MODULE_INFORMATION)); + (nSize * sizeof(SYSTEM_MODULE_INFORMATION)); psmModules = NULL; diff --git a/reactos/lib/fslib/Makefile b/reactos/lib/fslib/Makefile new file mode 100644 index 00000000000..1251fc55a31 --- /dev/null +++ b/reactos/lib/fslib/Makefile @@ -0,0 +1,48 @@ +# +# ReactOS Driver Support Libraries +# + +PATH_TO_TOP = ../.. + +include $(PATH_TO_TOP)/rules.mak + +FSLIBS = vfatlib + +all: $(FSLIBS) + +depends: + +implib: $(FSLIBS:%=%_implib) + +clean: $(FSLIBS:%=%_clean) + +install: $(FSLIBS:%=%_install) + +bootcd: $(FSLIBS:%=%_bootcd) + +.PHONY: all depends implib clean install bootcd + + +# +# FILE SYSTEM LIBRARIES +# +$(FSLIBS): %: + $(MAKE) -C $* + +$(FSLIBS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(FSLIBS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(FSLIBS:%=%_install): %_install: + $(MAKE) -C $* install + +$(FSLIBS:%=%_bootcd): %_bootcd: + $(MAKE) -C $* bootcd + +.PHONY: $(FSLIBS) $(FSLIBS:%=%_implib) $(FSLIBS:%=%_clean) $(FSLIBS:%=%_install) $(FSLIBS:%=%_bootcd) + +etags: + find . -name "*.[ch]" -print | etags --language=c - +# EOF diff --git a/reactos/lib/fslib/vfatxlib/Makefile b/reactos/lib/fslib/vfatxlib/Makefile new file mode 100644 index 00000000000..bbf47a91027 --- /dev/null +++ b/reactos/lib/fslib/vfatxlib/Makefile @@ -0,0 +1,18 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = library + +TARGET_NAME = vfatxlib + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS -Wall -Werror + +TARGET_OBJECTS = \ + fatx.o \ + vfatxlib.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/lib/fslib/vfatxlib/fatx.c b/reactos/lib/fslib/vfatxlib/fatx.c new file mode 100644 index 00000000000..2948fa22d78 --- /dev/null +++ b/reactos/lib/fslib/vfatxlib/fatx.c @@ -0,0 +1,431 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFATX filesystem library + * FILE: fatx.c + * PURPOSE: Fatx support + * PROGRAMMERS: Hartmut Birr + * REVISIONS: + */ +#define NDEBUG +#include +#define NTOS_MODE_USER +#include +#include +#include +#include "vfatxlib.h" + + +static ULONG +GetShiftCount(ULONG Value) +{ + ULONG i = 1; + while (Value > 0) + { + i++; + Value /= 2; + } + return i - 2; +} + + +static ULONG +CalcVolumeSerialNumber(VOID) +{ + LARGE_INTEGER SystemTime; + TIME_FIELDS TimeFields; + ULONG Serial; + PUCHAR Buffer; + + NtQuerySystemTime (&SystemTime); + RtlTimeToTimeFields (&SystemTime, &TimeFields); + + Buffer = (PUCHAR)&Serial; + Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF); + Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF); + Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF); + Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF); + + return Serial; +} + + +static NTSTATUS +FatxWriteBootSector (IN HANDLE FileHandle, + IN PFATX_BOOT_SECTOR BootSector, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR NewBootSector; + LARGE_INTEGER FileOffset; + + /* Allocate buffer for new bootsector */ + NewBootSector = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(FATX_BOOT_SECTOR)); + if (NewBootSector == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the new bootsector */ + memset(NewBootSector, 0, sizeof(FATX_BOOT_SECTOR)); + + /* Copy FAT16 BPB to new bootsector */ + memcpy(NewBootSector, BootSector, 18); /* FAT16 BPB length (up to (not including) Res2) */ + + /* Write sector 0 */ + FileOffset.QuadPart = 0ULL; + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + NewBootSector, + sizeof(FATX_BOOT_SECTOR), + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector); + return Status; + } + + VfatxUpdateProgress (Context, 1); + + /* Free the new boot sector */ + RtlFreeHeap(RtlGetProcessHeap(), 0, NewBootSector); + + return Status; +} + + +static NTSTATUS +Fatx16WriteFAT (IN HANDLE FileHandle, + IN ULONG SectorOffset, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG i; + ULONG Sectors; + + /* Allocate buffer */ + Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + 32 * 1024); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the buffer */ + memset(Buffer, 0, 32 * 1024); + + /* FAT cluster 0 */ + Buffer[0] = 0xf8; /* Media type */ + Buffer[1] = 0xff; + + /* FAT cluster 1 */ + Buffer[2] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */ + Buffer[3] = 0xff; + + /* Write first sector of the FAT */ + FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + VfatxUpdateProgress (Context, 1); + + /* Zero the begin of the buffer */ + memset(Buffer, 0, 4); + + /* Zero the rest of the FAT */ + Sectors = 32 * 1024 / 512; + for (i = 1; i < FATSectors; i += Sectors) + { + /* Zero some sectors of the FAT */ + FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR) ; + if ((FATSectors - i) <= Sectors) + { + Sectors = FATSectors - i; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + Sectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + VfatxUpdateProgress (Context, Sectors); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + +static NTSTATUS +Fatx32WriteFAT (IN HANDLE FileHandle, + IN ULONG SectorOffset, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG i; + ULONG Sectors; + + /* Allocate buffer */ + Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + 64 * 1024); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the buffer */ + memset(Buffer, 0, 64 * 1024); + + /* FAT cluster 0 */ + Buffer[0] = 0xf8; /* Media type */ + Buffer[1] = 0xff; + Buffer[2] = 0xff; + Buffer[3] = 0x0f; + /* FAT cluster 1 */ + Buffer[4] = 0xff; /* Clean shutdown, no disk read/write errors, end-of-cluster (EOC) mark */ + Buffer[5] = 0xff; + Buffer[6] = 0xff; + Buffer[7] = 0x0f; + + /* Write first sector of the FAT */ + FileOffset.QuadPart = (SectorOffset * 512) + sizeof(FATX_BOOT_SECTOR); + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + VfatxUpdateProgress (Context, 1); + + /* Zero the begin of the buffer */ + memset(Buffer, 0, 8); + + /* Zero the rest of the FAT */ + Sectors = 64 * 1024 / 512; + for (i = 1; i < FATSectors; i += Sectors) + { + /* Zero some sectors of the FAT */ + FileOffset.QuadPart = (SectorOffset + i) * 512 + sizeof(FATX_BOOT_SECTOR); + + if ((FATSectors - i) <= Sectors) + { + Sectors = FATSectors - i; + } + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + Sectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + return(Status); + } + + VfatxUpdateProgress (Context, Sectors); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + +static NTSTATUS +FatxWriteRootDirectory (IN HANDLE FileHandle, + IN ULONG FATSectors, + IN OUT PFORMAT_CONTEXT Context) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status = STATUS_SUCCESS; + PUCHAR Buffer; + LARGE_INTEGER FileOffset; + ULONG FirstRootDirSector; + ULONG RootDirSectors; + + /* Write cluster */ + RootDirSectors = 256 * 64 / 512; + FirstRootDirSector = sizeof(FATX_BOOT_SECTOR) / 512 + FATSectors; + + DPRINT("RootDirSectors = %lu\n", RootDirSectors); + DPRINT("FirstRootDirSector = %lu\n", FirstRootDirSector); + + /* Allocate buffer for the cluster */ + Buffer = (PUCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + 0, + RootDirSectors * 512); + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + /* Zero the buffer */ + memset(Buffer, 0xff, RootDirSectors * 512); + + /* Zero some sectors of the root directory */ + FileOffset.QuadPart = FirstRootDirSector * 512; + + Status = NtWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + RootDirSectors * 512, + &FileOffset, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtWriteFile() failed (Status %lx)\n", Status); + } + + /* Free the buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); + + return(Status); +} + + +NTSTATUS +FatxFormat (HANDLE FileHandle, + PPARTITION_INFORMATION PartitionInfo, + PDISK_GEOMETRY DiskGeometry, + BOOLEAN QuickFormat, + PFORMAT_CONTEXT Context) +{ + FATX_BOOT_SECTOR BootSector; + ULONGLONG SectorCount; + ULONG ClusterCount; + ULONG RootDirSectors; + ULONG FATSectors; + + NTSTATUS Status; + + SectorCount = PartitionInfo->PartitionLength.QuadPart >> GetShiftCount(512); /* Use shifting to avoid 64-bit division */ + + memset(&BootSector, 0, sizeof(FATX_BOOT_SECTOR)); + memcpy(&BootSector.SysType[0], "FATX", 4); + BootSector.SectorsPerCluster = 32; + BootSector.FATCount = 1; + BootSector.VolumeID = CalcVolumeSerialNumber(); + RootDirSectors = 256 * 64 / 512; + + /* Calculate number of FAT sectors */ + ClusterCount = SectorCount >> GetShiftCount(32); + + if (ClusterCount > 65525) + { + FATSectors = (((ClusterCount * 4) + 4095) & ~4095) >> GetShiftCount(512); + } + else + { + FATSectors = (((ClusterCount * 2) + 4095) & ~4095) >> GetShiftCount(512); + } + DPRINT("FATSectors = %hu\n", FATSectors); + + /* Init context data */ + if (QuickFormat) + { + Context->TotalSectorCount = + 1 + FATSectors + RootDirSectors; + } + else + { + Context->TotalSectorCount = SectorCount; + } + + Status = FatxWriteBootSector (FileHandle, + &BootSector, + Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteBootSector() failed with status 0x%.08x\n", Status); + return Status; + } + + /* Write first FAT copy */ + if (ClusterCount > 65525) + { + Status = Fatx32WriteFAT (FileHandle, + 0, + FATSectors, + Context); + } + else + { + Status = Fatx16WriteFAT (FileHandle, + 0, + FATSectors, + Context); + } + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteFAT() failed with status 0x%.08x\n", Status); + return Status; + } + + Status = FatxWriteRootDirectory (FileHandle, + FATSectors, + Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("FatxWriteRootDirectory() failed with status 0x%.08x\n", Status); + } + + if (!QuickFormat) + { + /* FIXME: Fill remaining sectors */ + } + + return Status; +} diff --git a/reactos/lib/fslib/vfatxlib/vfatxlib.c b/reactos/lib/fslib/vfatxlib/vfatxlib.c new file mode 100644 index 00000000000..38e4a77d300 --- /dev/null +++ b/reactos/lib/fslib/vfatxlib/vfatxlib.c @@ -0,0 +1,198 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFATx filesystem library + * FILE: vfatxlib.c + * PURPOSE: Main API + * PROGRAMMERS: Hartmut Birr + * REVISIONS: + * CSH 05/04-2003 Created + */ +#define NTOS_MODE_USER +#include +#include +#include +#include "vfatxlib.h" + +#define NDEBUG +#include + + +NTSTATUS +VfatxInitialize(VOID) +{ + DPRINT("VfatxInitialize()\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +VfatxFormat (PUNICODE_STRING DriveRoot, + ULONG MediaFlag, + BOOLEAN QuickFormat, + PFMIFSCALLBACK Callback) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + DISK_GEOMETRY DiskGeometry; + IO_STATUS_BLOCK Iosb; + HANDLE FileHandle; + PARTITION_INFORMATION PartitionInfo; + FORMAT_CONTEXT Context; + NTSTATUS Status; + + DPRINT("VfatxFormat(DriveRoot '%wZ')\n", DriveRoot); + + Context.TotalSectorCount = 0; + Context.CurrentSectorCount = 0; + Context.Callback = Callback; + Context.Success = FALSE; + Context.Percent = 0; + + InitializeObjectAttributes(&ObjectAttributes, + DriveRoot, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES, + &ObjectAttributes, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtOpenFile() failed with status 0x%.08x\n", Status); + return Status; + } + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY)); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with status 0x%.08x\n", Status); + NtClose(FileHandle); + return Status; + } + + if (DiskGeometry.MediaType == FixedMedia) + { + DPRINT("Cylinders %I64d\n", DiskGeometry.Cylinders.QuadPart); + DPRINT("TracksPerCylinder %ld\n", DiskGeometry.TracksPerCylinder); + DPRINT("SectorsPerTrack %ld\n", DiskGeometry.SectorsPerTrack); + DPRINT("BytesPerSector %ld\n", DiskGeometry.BytesPerSector); + DPRINT("DiskSize %I64d\n", + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector); + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_PARTITION_INFO, + NULL, + 0, + &PartitionInfo, + sizeof(PARTITION_INFORMATION)); + if (!NT_SUCCESS(Status)) + { + DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%.08x\n", Status); + NtClose(FileHandle); + return Status; + } + + /* + * FIXME: This is a hack! + * Partitioning software MUST set the correct number of hidden sectors! + */ + PartitionInfo.HiddenSectors = DiskGeometry.SectorsPerTrack; + } + else + { + PartitionInfo.PartitionType = 0; + PartitionInfo.StartingOffset.QuadPart = 0ULL; + PartitionInfo.PartitionLength.QuadPart = + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + PartitionInfo.HiddenSectors = 0; + PartitionInfo.PartitionNumber = 0; + PartitionInfo.BootIndicator = FALSE; + PartitionInfo.RewritePartition = FALSE; + PartitionInfo.RecognizedPartition = FALSE; + } + + DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType); + DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); + DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); + DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors); + DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); + DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator); + DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); + DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition); + + if (Callback != NULL) + { + Context.Percent = 0; + Callback (PROGRESS, 0, (PVOID)&Context.Percent); + } + + Status = FatxFormat (FileHandle, + &PartitionInfo, + &DiskGeometry, + QuickFormat, + &Context); + NtClose(FileHandle); + + if (Callback != NULL) + { + Context.Success = (BOOLEAN)(NT_SUCCESS(Status)); + Callback (DONE, 0, (PVOID)&Context.Success); + } + + DPRINT("VfatFormat() done. Status 0x%.08x\n", Status); + + return Status; +} + + +NTSTATUS +VfatxCleanup(VOID) +{ + DPRINT("VfatxCleanup()\n"); + + return STATUS_SUCCESS; +} + + +VOID +VfatxUpdateProgress (PFORMAT_CONTEXT Context, + ULONG Increment) +{ + ULONG NewPercent; + + Context->CurrentSectorCount += (ULONGLONG)Increment; + + + NewPercent = (Context->CurrentSectorCount * 100ULL) / Context->TotalSectorCount; + + if (NewPercent > Context->Percent) + { + Context->Percent = NewPercent; + Context->Callback (PROGRESS, 0, &Context->Percent); + } +} + +/* EOF */ diff --git a/reactos/lib/fslib/vfatxlib/vfatxlib.h b/reactos/lib/fslib/vfatxlib/vfatxlib.h new file mode 100644 index 00000000000..3ac90c7c800 --- /dev/null +++ b/reactos/lib/fslib/vfatxlib/vfatxlib.h @@ -0,0 +1,45 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS VFAT filesystem library + * FILE: vfatxlib.h + */ +#define NDEBUG +#include +#define NTOS_MODE_USER +#include +#include + +typedef struct _FATX_BOOT_SECTOR +{ + unsigned char SysType[4]; // 0 + unsigned long VolumeID; // 4 + unsigned long SectorsPerCluster; // 8 + unsigned short FATCount; // 12 + unsigned long Unknown; // 14 + unsigned char Unused[4078]; // 18 +} __attribute__((packed)) FATX_BOOT_SECTOR, *PFATX_BOOT_SECTOR; + + +typedef struct _FORMAT_CONTEXT +{ + PFMIFSCALLBACK Callback; + ULONG TotalSectorCount; + ULONG CurrentSectorCount; + BOOLEAN Success; + ULONG Percent; +} FORMAT_CONTEXT, *PFORMAT_CONTEXT; + + + +NTSTATUS +FatxFormat (HANDLE FileHandle, + PPARTITION_INFORMATION PartitionInfo, + PDISK_GEOMETRY DiskGeometry, + BOOLEAN QuickFormat, + PFORMAT_CONTEXT Context); + +VOID +VfatxUpdateProgress (PFORMAT_CONTEXT Context, + ULONG Increment); + +/* EOF */ diff --git a/reactos/lib/gdi32/gdi32.xml b/reactos/lib/gdi32/gdi32.xml index 9c030790991..fd058e785c3 100644 --- a/reactos/lib/gdi32/gdi32.xml +++ b/reactos/lib/gdi32/gdi32.xml @@ -1,5 +1,4 @@ - addsys include @@ -20,7 +19,7 @@ stubs.c stubsa.c stubsw.c - win32k.c + win32k.S wingl.c diff --git a/reactos/lib/gdi32/misc/stubs.c b/reactos/lib/gdi32/misc/stubs.c index aa0114d7d40..9689b8592d2 100644 --- a/reactos/lib/gdi32/misc/stubs.c +++ b/reactos/lib/gdi32/misc/stubs.c @@ -150,26 +150,16 @@ EnumObjects( return 0; } - /* * @unimplemented */ int STDCALL -Escape( - HDC a0, - int a1, - int a2, - LPCSTR a3, - LPVOID a4 - ) +Escape(HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + return NtGdiEscape(hdc,escape,in_count,in_data,out_data); } - /* * @unimplemented */ @@ -273,13 +263,9 @@ GetRasterizerCaps( */ UINT STDCALL -GetSystemPaletteUse( - HDC hDc - ) +GetSystemPaletteUse(HDC hDc) { - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + return NtGdiGetSystemPaletteUse(hDc); } diff --git a/reactos/lib/gdi32/objects/font.c b/reactos/lib/gdi32/objects/font.c index 1704e068b42..7ac049fde3c 100644 --- a/reactos/lib/gdi32/objects/font.c +++ b/reactos/lib/gdi32/objects/font.c @@ -716,7 +716,7 @@ AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved ) { rc = AddFontResourceExW ( FilenameW, fl, pvReserved ); - HEAP_free ( &FilenameW ); + HEAP_free ( FilenameW ); } return rc; } diff --git a/reactos/lib/icmp/icmp_main.c b/reactos/lib/icmp/icmp_main.c index 50532df2d8a..4f68446f24a 100644 --- a/reactos/lib/icmp/icmp_main.c +++ b/reactos/lib/icmp/icmp_main.c @@ -95,6 +95,7 @@ #include "ip.h" #include "ip_icmp.h" + WINE_DEFAULT_DEBUG_CHANNEL(icmp); @@ -135,6 +136,8 @@ static int in_cksum(u_short *addr, int len) return(answer); } + + /* * Exported Routines. */ diff --git a/reactos/lib/kbdes/kbdes.c b/reactos/lib/kbdes/kbdes.c new file mode 100644 index 00000000000..5b59dae55e4 --- /dev/null +++ b/reactos/lib/kbdes/kbdes.c @@ -0,0 +1,586 @@ +/* + * ReactOS ESASCII Keyboard layout + * Copyright (C) 2003 ReactOS + * License: LGPL, see: LGPL.txt + * Created by HUMA2000 from kbdus, kbdgr, kbdda and kbdfr + * huma2000@terra.es + * Thanks to arty for the kbtest utility and help + * Thanks to carraca from reactos.com forum for his fixes + * Thanks Elrond for help + * + * Thanks to: http://www.barcodeman.com/altek/mule/scandoc.php + * and http://win.tue.nl/~aeb/linux/kbd/scancodes-1.html + */ + + +#include +#include + + +#ifdef _M_IA64 +#define ROSDATA static __declspec(allocate(".data")) +#else +#pragma data_seg(".data") +#define ROSDATA static +#endif + + +#define VK_EMPTY 0xff /* The non-existent VK */ +#define KSHIFT 0x001 /* Shift modifier */ +#define KCTRL 0x002 /* Ctrl modifier */ +#define KALT 0x004 /* Alt modifier */ +#define KEXT 0x100 /* Extended key code */ +#define KMULTI 0x200 /* Multi-key */ +#define KSPEC 0x400 /* Special key */ +#define KNUMP 0x800 /* Number-pad */ +#define KNUMS 0xc00 /* Special + number pad */ +#define KMEXT 0x300 /* Multi + ext */ + +#define SHFT_INVALID 0x0F + +/* Thanks to http://asp.flaaten.dk/pforum/keycode/keycode.htm */ + + +#ifndef VK_OEM_1 +#define VK_OEM_1 0xba /* Tecla `^[ */ +#endif +#ifndef VK_OEM_PLUS +#define VK_OEM_PLUS 0xbb /* Tecla +*] */ +#endif +#ifndef VK_OEM_COMMA +#define VK_OEM_COMMA 0xbc /* Tecla ,; */ +#endif +#ifndef VK_OEM_MINUS +#define VK_OEM_MINUS 0xbd /* Tecla -_ */ +#endif +#ifndef VK_OEM_PERIOD +#define VK_OEM_PERIOD 0xbe /* Tecla .: */ +#endif +#ifndef VK_OEM_2 +#define VK_OEM_2 0xbf /* Tecla çÇ} */ +#endif +#ifndef VK_OEM_3 +#define VK_OEM_3 0xc0 /* Tecla ñÑ */ +#endif +#ifndef VK_OEM_4 +#define VK_OEM_4 0xdb /* Tecla '? */ +#endif +#ifndef VK_OEM_5 +#define VK_OEM_5 0xdc /* Tecla ºª\ */ +#endif +#ifndef VK_OEM_6 +#define VK_OEM_6 0xdd /* Tecla ¡¿ */ +#endif +#ifndef VK_OEM_7 +#define VK_OEM_7 0xde /* Tecla ´¨{ */ +#endif +#ifndef VK_OEM_8 +#define VK_OEM_8 0xdf +#endif +#ifndef VK_OEM_102 +#define VK_OEM_102 0xe2 /* Tecla < > */ +#endif + + +ROSDATA USHORT scancode_to_vk[] = { +/* 00 */ VK_EMPTY, +/* 01 */ VK_ESCAPE, +/* 02 */ '1', +/* 03 */ '2', +/* 04 */ '3', +/* 05 */ '4', +/* 06 */ '5', +/* 07 */ '6', +/* 08 */ '7', +/* 09 */ '8', +/* 0a */ '9', +/* 0b */ '0', +/* 0c */ VK_OEM_4, +/* 0d */ VK_OEM_6, +/* 0e */ VK_BACK, +/* 0f */ VK_TAB, +/* 10 */ 'Q', +/* 11 */ 'W', +/* 12 */ 'E', +/* 13 */ 'R', +/* 14 */ 'T', +/* 15 */ 'Y', +/* 16 */ 'U', +/* 17 */ 'I', +/* 18 */ 'O', +/* 19 */ 'P', +/* 1a */ VK_OEM_1, +/* 1b */ VK_OEM_PLUS, +/* 1c */ VK_RETURN, +/* 1d */ VK_LCONTROL, +/* 1e */ 'A', +/* 1f */ 'S', +/* 20 */ 'D', +/* 21 */ 'F', +/* 22 */ 'G', +/* 23 */ 'H', +/* 24 */ 'J', +/* 25 */ 'K', +/* 26 */ 'L', +/* 27 */ VK_OEM_3, +/* 28 */ VK_OEM_7, +/* 29 */ VK_OEM_5, +/* 2a */ VK_LSHIFT, +/* 2b */ VK_OEM_2, +/* 2c */ 'Z', +/* 2d */ 'X', +/* 2e */ 'C', +/* 2f */ 'V', +/* 30 */ 'B', +/* 31 */ 'N', +/* 32 */ 'M', +/* 33 */ VK_OEM_COMMA, +/* 34 */ VK_OEM_PERIOD, +/* 35 */ VK_OEM_MINUS, +/* 36 */ VK_RSHIFT, +/* 37 */ VK_MULTIPLY, +/* 38 */ VK_LMENU, +/* 39 */ VK_SPACE, +/* 3a */ VK_CAPITAL, +/* 3b */ VK_F1, +/* 3c */ VK_F2, +/* 3d */ VK_F3, +/* 3e */ VK_F4, +/* 3f */ VK_F5, +/* 40 */ VK_F6, +/* 41 */ VK_F7, +/* 42 */ VK_F8, +/* 43 */ VK_F9, +/* 44 */ VK_F10, +/* 45 */ VK_NUMLOCK | KMEXT, +/* 46 */ VK_SCROLL | KMULTI, +/* 47 */ VK_HOME | KNUMS, +/* 48 */ VK_UP | KNUMS, +/* 49 */ VK_PRIOR | KNUMS, +/* 4a */ VK_SUBTRACT, +/* 4b */ VK_LEFT | KNUMS, +/* 4c */ VK_CLEAR | KNUMS, +/* 4d */ VK_RIGHT | KNUMS, +/* 4e */ VK_ADD, +/* 4f */ VK_END | KNUMS, +/* 50 */ VK_DOWN | KNUMS, +/* 51 */ VK_NEXT | KNUMS, +/* 52 */ VK_INSERT | KNUMS, +/* 53 */ VK_DELETE | KNUMS, +/* 54 */ VK_SNAPSHOT, +/* 55 */ VK_EMPTY, +/* 56 */ VK_OEM_102, +/* 57 */ VK_F11, +/* 58 */ VK_F12, +/* 59 */ VK_EMPTY, +/* 5a */ VK_CLEAR, +/* 5b */ VK_EMPTY, +/* 5c */ VK_EMPTY, +/* 5d */ VK_EMPTY, +/* 5e */ VK_EMPTY, /* EREOF */ +/* 5f */ VK_EMPTY, +/* 60 */ VK_EMPTY, +/* 61 */ VK_EMPTY, +/* 62 */ VK_EMPTY, +/* 63 */ VK_EMPTY, /* ZOOM */ +/* 64 */ VK_HELP, +/* 65 */ VK_F13, +/* 66 */ VK_F14, +/* 67 */ VK_F15, +/* 68 */ VK_F16, +/* 69 */ VK_F17, +/* 6a */ VK_F18, +/* 6b */ VK_F19, +/* 6c */ VK_F20, +/* 6d */ VK_F21, +/* 6e */ VK_F22, +/* 6f */ VK_F23, +/* 70 */ VK_EMPTY, +/* 71 */ VK_EMPTY, +/* 72 */ VK_EMPTY, +/* 73 */ VK_EMPTY, +/* 74 */ VK_EMPTY, +/* 75 */ VK_EMPTY, +/* 76 */ VK_EMPTY, +/* 77 */ VK_F24, +/* 78 */ VK_EMPTY, +/* 79 */ VK_EMPTY, +/* 7a */ VK_EMPTY, +/* 7b */ VK_EMPTY, +/* 7c */ VK_EMPTY, +/* 7d */ VK_EMPTY, +/* 7e */ VK_EMPTY, +/* 7f */ VK_EMPTY, +/* 80 */ VK_EMPTY, +/* 00 */ 0 +}; + +ROSDATA VSC_VK extcode0_to_vk[] = { + { 0x10, VK_MEDIA_PREV_TRACK | KEXT }, // Pista anterior, no puedo probarlo hasta que no se implemente el sonido + { 0x19, VK_MEDIA_NEXT_TRACK | KEXT }, // Pista siguiente, + { 0x1D, VK_RCONTROL | KEXT }, // Tecla control + { 0x20, VK_VOLUME_MUTE | KEXT }, // Silenciar volumen + { 0x21, VK_LAUNCH_APP2 | KEXT }, // Tecla calculadora + { 0x22, VK_MEDIA_PLAY_PAUSE | KEXT }, // Play/pause + { 0x24, VK_MEDIA_STOP | KEXT }, // Stop + { 0x2E, VK_VOLUME_DOWN | KEXT }, // Bajar volumen + { 0x30, VK_VOLUME_UP | KEXT }, // Subir volumen + { 0x32, VK_BROWSER_HOME | KEXT }, // Pagina de inicio del navegador de internet o abrirlo si no esta activolo + { 0x35, VK_DIVIDE | KEXT }, // Tecla + { 0x37, VK_SNAPSHOT | KEXT }, // La tecla de imprimir pantalla + { 0x38, VK_RMENU | KEXT }, // Tecla alt + { 0x47, VK_HOME | KEXT }, // Tecla inicio + { 0x48, VK_UP | KEXT }, // Cursor arriba + { 0x49, VK_PRIOR | KEXT }, // Tecla Re pag + { 0x4B, VK_LEFT | KEXT }, // Cursor izquierda + { 0x4D, VK_RIGHT | KEXT }, // Cursor derecha + { 0x4F, VK_END | KEXT }, // Tecla Fin + { 0x50, VK_DOWN | KEXT }, // Cursor abajo + { 0x51, VK_NEXT | KEXT }, // Tecla Av pag + { 0x52, VK_INSERT | KEXT }, // Tecla insertar + { 0x53, VK_DELETE | KEXT }, // Tecla deletear + { 0x5B, VK_LWIN | KEXT }, // Tecla windows izquierda + { 0x5C, VK_RWIN | KEXT }, // Tecla windows derecha + { 0x5D, VK_APPS | KEXT }, // Tecla menu aplicacion derecha + { 0x5F, VK_SLEEP | KEXT }, // Tecla Sleep + { 0x65, VK_BROWSER_SEARCH | KEXT }, // Pagina de búsqueda en el navegador de internet + { 0x66, VK_BROWSER_FAVORITES | KEXT }, // Favoritos, tengo que esperar a que el tcp/ip + { 0x67, VK_BROWSER_REFRESH | KEXT }, // Refrescar el navegador de internet + { 0x68, VK_BROWSER_STOP | KEXT }, // Stop en el navegador de internet + { 0x69, VK_BROWSER_FORWARD | KEXT }, // Adelante en el navegador de internet + { 0x6A, VK_BROWSER_BACK | KEXT }, // Atrás en el navegador de internet + { 0x6B, VK_LAUNCH_APP1 | KEXT }, // Tecla Mi pc + { 0x6C, VK_LAUNCH_MAIL | KEXT }, // Abrir programa de e-mail + { 0x6D, VK_LAUNCH_MEDIA_SELECT | KEXT }, // Abrir reproductor multimedia + { 0x1C, VK_RETURN | KEXT }, // La tecla de intro + { 0x46, VK_CANCEL | KEXT }, // Tecla escape + { 0, 0 }, +}; + + +ROSDATA VSC_VK extcode1_to_vk[] = { + { 0, 0 }, +}; + +ROSDATA VK_TO_BIT modifier_keys[] = { + { VK_SHIFT, KSHIFT }, + { VK_CONTROL, KCTRL }, + { VK_MENU, KALT }, + { 0, 0 } +}; + +typedef struct _mymod { + PVOID mod_keys; + WORD maxmod; + BYTE mod_max[7]; +} INTERNAL_KBD_MODIFIERS; + +ROSDATA INTERNAL_KBD_MODIFIERS modifier_bits[] = { + modifier_keys, + 6, + { 0, 1, 2, 4, SHFT_INVALID, SHFT_INVALID, 3 } +/* NONE, SHIFT, CTRL, CTRL+SHIFT, ALT */ +}; + +#define NOCAPS 0 +#define CAPS KSHIFT /* Caps -> shift */ + +ROSDATA VK_TO_WCHARS2 key_to_chars_2mod[] = { + /* Normal vs Shifted */ + /* The numbers */ + //Del 1 al 5 tienen tres estados + { '4', NOCAPS, '4', '$' }, + { '5', NOCAPS, '5', '%' }, + //El 6 tiene 3 estados + { '7', NOCAPS, '7', '/' }, + { '8', NOCAPS, '8', '(' }, + { '9', NOCAPS, '9', ')' }, + { '0', NOCAPS, '0', '=' }, + /* First letter row */ + { 'Q', CAPS, 'q', 'Q' }, + { 'W', CAPS, 'w', 'W' }, + //La E tiene 3 estados + { 'R', CAPS, 'r', 'R' }, + { 'T', CAPS, 't', 'T' }, + { 'Y', CAPS, 'y', 'Y' }, + { 'U', CAPS, 'u', 'U' }, + { 'I', CAPS, 'i', 'I' }, + { 'O', CAPS, 'o', 'O' }, + { 'P', CAPS, 'p', 'P' }, + /* Second letter row */ + { 'A', CAPS, 'a', 'A' }, + { 'S', CAPS, 's', 'S' }, + { 'D', CAPS, 'd', 'D' }, + { 'F', CAPS, 'f', 'F' }, + { 'G', CAPS, 'g', 'G' }, + { 'H', CAPS, 'h', 'H' }, + { 'J', CAPS, 'j', 'J' }, + { 'K', CAPS, 'k', 'K' }, + { 'L', CAPS, 'l', 'L' }, + { VK_OEM_3, CAPS, 0x00F1, 0x00D1 }, // ñÑ + /* Third letter row */ + { 'Z', CAPS, 'z', 'Z' }, + { 'X', CAPS, 'x', 'X' }, + { 'C', CAPS, 'c', 'C' }, + { 'V', CAPS, 'v', 'V' }, + { 'B', CAPS, 'b', 'B' }, + { 'N', CAPS, 'n', 'N' }, + { 'M', CAPS, 'm', 'M' }, + + /* Specials */ + /* Ctrl-_ generates ES */ + { VK_OEM_6 ,NOCAPS, 0x00a1, 0x00bf }, // ¡¿ + { VK_OEM_4 ,NOCAPS, 0x0027, '?' }, //'? + { VK_OEM_COMMA ,NOCAPS, ',', ';' }, + { VK_OEM_PERIOD ,NOCAPS, '.', ':' }, + { VK_OEM_MINUS ,NOCAPS, '-', '_' }, + { VK_OEM_102 ,NOCAPS, '<', '>' }, + + /* Keys that do not have shift states */ + { VK_TAB, NOCAPS, '\t', '\t' }, + { VK_ADD, NOCAPS, '+', '+' }, + { VK_SUBTRACT, NOCAPS, '-', '-' }, + { VK_MULTIPLY, NOCAPS, '*', '*'}, + { VK_DIVIDE, NOCAPS, '/', '/' }, + { VK_ESCAPE, NOCAPS, '\x1b', '\x1b' }, + { VK_SPACE, NOCAPS, ' ', ' ' }, + { 0, 0 } +}; + + +ROSDATA VK_TO_WCHARS3 key_to_chars_3mod[] = { + /* Normal, Shifted, Ctrl */ + /* Legacy (telnet-style) ascii escapes */ + { VK_RETURN, NOCAPS, '\r', '\r', '\n' }, + { 0,0 } +}; + + +ROSDATA VK_TO_WCHARS4 key_to_chars_4mod[] = { +/* Normal, shifted, control, Alt+Gr */ + { '1', NOCAPS, '1', '!', WCH_NONE, 0x00a6 }, // 1!| + { '2', NOCAPS, '2', '"', WCH_NONE, '@' }, // 2"@ + { '3', NOCAPS, '3', 0x00B7, WCH_NONE, '#' }, // 3·# + { '6', NOCAPS, '6', '&', WCH_NONE, 0x00AC }, // 6&¬ + { 'E', CAPS, 'e', 'E', WCH_NONE, 0x20AC }, // eE€ + { VK_OEM_PLUS, NOCAPS, '+', '*', WCH_NONE, 0x005d }, // +*] + { VK_OEM_2, NOCAPS, 0x00e7, 0x00c7, WCH_NONE, '}' }, // çÇ} + + { VK_OEM_7, NOCAPS, WCH_DEAD, WCH_DEAD, WCH_NONE, '{' }, // ´¨{ + { VK_EMPTY, NOCAPS, 0xB4, 0xA8, WCH_NONE, WCH_NONE }, // ´¨{ + + { VK_OEM_1, NOCAPS, WCH_DEAD, WCH_DEAD, WCH_NONE, 0x5B }, // `^[ + { VK_EMPTY, NOCAPS, 0x60, 0x5e, WCH_NONE, WCH_NONE }, // `^[ + + { VK_OEM_5, NOCAPS, 0x00BA, 0x00AA, WCH_NONE, 0x005c }, // çÇ} + { 0, 0 } +}; + + + +ROSDATA VK_TO_WCHARS1 keypad_numbers[] = { + { VK_NUMPAD0, 0, '0' }, + { VK_NUMPAD1, 0, '1' }, + { VK_NUMPAD2, 0, '2' }, + { VK_NUMPAD3, 0, '3' }, + { VK_NUMPAD4, 0, '4' }, + { VK_NUMPAD5, 0, '5' }, + { VK_NUMPAD6, 0, '6' }, + { VK_NUMPAD7, 0, '7' }, + { VK_NUMPAD8, 0, '8' }, + { VK_NUMPAD9, 0, '9' }, + { VK_DECIMAL, 0, '.' }, + { VK_BACK, 0, '\010' }, + { 0,0 } +}; + + +#define vk_master(n,x) { (PVK_TO_WCHARS1)x, n, sizeof(x[0]) } + + +ROSDATA VK_TO_WCHAR_TABLE vk_to_wchar_master_table[] = { + vk_master(1,keypad_numbers), + vk_master(2,key_to_chars_2mod), + vk_master(3,key_to_chars_3mod), + vk_master(4,key_to_chars_4mod), + { 0,0,0 } +}; + +#define DEADTRANS(ch, accent, comp, flags) MAKELONG(ch, accent), comp, flags //no funciona +ROSDATA DEADKEY deadkey[] = +{ + //*´* + { DEADTRANS(L'a', 0xb4, 0xE1, 0x00) }, // letra a con ´ + { DEADTRANS(L'A', 0xb4, 0xC1, 0x00) }, // letra A con ´ + { DEADTRANS(L'e', 0xb4, 0xE9, 0x00) }, // letra e con ´ + { DEADTRANS(L'E', 0xb4, 0xC9, 0x00) }, // letra E con ´ + { DEADTRANS(L'i', 0xb4, 0xED, 0x00) }, // letra i con ´ + { DEADTRANS(L'I', 0xb4, 0xCD, 0x00) }, // letra I con ´ + { DEADTRANS(L'o', 0xb4, 0xF3, 0x00) }, // letra o con ´ + { DEADTRANS(L'O', 0xb4, 0xD3, 0x00) }, // letra O con ´ + { DEADTRANS(L'u', 0xb4, 0xFA, 0x00) }, // letra u con ´ + { DEADTRANS(L'U', 0xb4, 0xDA, 0x00) }, // letra U con ´ + //*`* + { DEADTRANS(L'a', 0x60, 0xE0, 0x00) }, // letra a con ` + { DEADTRANS(L'A', 0x60, 0xC0, 0x00) }, // letra A con ` + { DEADTRANS(L'e', 0x60, 0xE8, 0x00) }, // letra e con ` + { DEADTRANS(L'E', 0x60, 0xC8, 0x00) }, // letra E con ` + { DEADTRANS(L'i', 0x60, 0xEC, 0x00) }, // letra i con ` + { DEADTRANS(L'I', 0x60, 0xCC, 0x00) }, // letra I con ` + { DEADTRANS(L'o', 0x60, 0xF2, 0x00) }, // letra o con ` + { DEADTRANS(L'O', 0x60, 0xD2, 0x00) }, // letra O con ` + { DEADTRANS(L'u', 0x60, 0xF9, 0x00) }, // letra u con ` + { DEADTRANS(L'U', 0x60, 0xD9, 0x00) }, // letra U con ` + //*^* + { DEADTRANS(L'a', 0x5E, 0xE2, 0x00) }, // letra a con ^ + { DEADTRANS(L'A', 0x5E, 0xC2, 0x00) }, // letra A con ^ + { DEADTRANS(L'e', 0x5E, 0xEA, 0x00) }, // letra e con ^ + { DEADTRANS(L'E', 0x5E, 0xCA, 0x00) }, // letra E con ^ + { DEADTRANS(L'i', 0x5E, 0xEE, 0x00) }, // letra i con ^ + { DEADTRANS(L'I', 0x5E, 0xCE, 0x00) }, // letra I con ^ + { DEADTRANS(L'o', 0x5E, 0xF4, 0x00) }, // letra o con ^ + { DEADTRANS(L'O', 0x5E, 0xD4, 0x00) }, // letra O con ^ + { DEADTRANS(L'u', 0x5E, 0xFB, 0x00) }, // letra u con ^ + { DEADTRANS(L'U', 0x5E, 0xDB, 0x00) }, // letra U con ^ + //*¨* + { DEADTRANS(L'a', 0xA8, 0xE4, 0x00) }, // letra a con ¨ + { DEADTRANS(L'A', 0xA8, 0xC4, 0x00) }, // letra A con ¨ + { DEADTRANS(L'e', 0xA8, 0xEB, 0x00) }, // letra e con ¨ + { DEADTRANS(L'E', 0xA8, 0xCB, 0x00) }, // letra E con ¨ + { DEADTRANS(L'i', 0xA8, 0xEF, 0x00) }, // letra i con ¨ + { DEADTRANS(L'I', 0xA8, 0xCF, 0x00) }, // letra I con ¨ + { DEADTRANS(L'o', 0xA8, 0xF6, 0x00) }, // letra o con ¨ + { DEADTRANS(L'O', 0xA8, 0xD6, 0x00) }, // letra O con ¨ + { DEADTRANS(L'u', 0xA8, 0xFC, 0x00) }, // letra u con ¨ + { DEADTRANS(L'U', 0xA8, 0xDC, 0x00) }, // letra U con ¨ + { 0, 0, 0} +}; + +ROSDATA VSC_LPWSTR key_names[] = { + { 0x00, L"" }, + { 0x01, L"Escape" }, + { 0x0e, L"Borrar" }, + { 0x0f, L"Tabulador" }, + { 0x1c, L"Intro" }, + { 0x1d, L"Ctrl" }, + { 0x2a, L"Shift" }, + { 0x36, L"Shift derecho" }, + { 0x37, L"* numerico" }, + { 0x38, L"Alt" }, + { 0x39, L"Espacio" }, + { 0x3a, L"Bloqueo mayusculas" }, + { 0x3b, L"F1" }, + { 0x3c, L"F2" }, + { 0x3d, L"F3" }, + { 0x3e, L"F4" }, + { 0x3f, L"F5" }, + { 0x40, L"F6" }, + { 0x41, L"F7" }, + { 0x42, L"F8" }, + { 0x43, L"F9" }, + { 0x44, L"F10" }, + { 0x45, L"Pausa" }, + { 0x46, L"Bloqueo de scroll" }, + { 0x47, L"Num 7" }, + { 0x48, L"Num 8" }, + { 0x49, L"Num 9" }, + { 0x4a, L"Num -" }, + { 0x4b, L"Num 4" }, + { 0x4c, L"Num 5" }, + { 0x4d, L"Num 6" }, + { 0x4e, L"Num +" }, + { 0x4f, L"Num 1" }, + { 0x50, L"Num 2" }, + { 0x51, L"Num 3" }, + { 0x52, L"Num 0" }, + { 0x53, L"Borrardo numerico" }, + { 0x54, L"Peticion de sistema" }, + { 0x57, L"F11" }, + { 0x58, L"F12" }, + { 0x7c, L"F13" }, + { 0x7d, L"F14" }, + { 0x7e, L"F15" }, + { 0x7f, L"F16" }, + { 0x80, L"F17" }, + { 0x81, L"F18" }, + { 0x82, L"F19" }, + { 0x83, L"F20" }, + { 0x84, L"F21" }, + { 0x85, L"F22" }, + { 0x86, L"F23" }, + { 0x87, L"F24" }, + { 0, NULL }, +}; + +ROSDATA VSC_LPWSTR extended_key_names[] = { + { 0x1c, L"Intro numerico" }, + { 0x1d, L"Ctrl derecho" }, + { 0x35, L"/ numerica" }, + { 0x37, L"Imprimir pantalla" }, + { 0x38, L"Alt derecho" }, + { 0x45, L"Bloqueo numerico" }, + { 0x46, L"Interrumpir" }, + { 0x47, L"Inicio" }, + { 0x48, L"Arriba" }, + { 0x49, L"Subir pagina" }, + { 0x4b, L"Izquierda" }, + { 0x4c, L"Centrar" }, + { 0x4d, L"Derecha" }, + { 0x4f, L"Fin" }, + { 0x50, L"Abajo" }, + { 0x51, L"Bajar pagina" }, + { 0x52, L"Insertar" }, + { 0x53, L"Borrar" }, + { 0x54, L"" }, + { 0x55, L"Ayuda" }, + { 0x5b, L"Windows izquierda" }, + { 0x5c, L"Windows derecha" }, + { 0, NULL }, +}; + +ROSDATA DEADKEY_LPWSTR dead_key_names[] = { + L"\x00b4" L"Agudo", + L"\x0060" L"Grave", + L"\x005e" L"Circunflejo", + L"\x00A8" L"Dieresis", + NULL +}; + + +/* Finally, the master table */ +ROSDATA KBDTABLES keyboard_layout_table = { + + /* modifier assignments */ + (PMODIFIERS)&modifier_bits, + + /* character from vk tables */ + vk_to_wchar_master_table, + + /* diacritical marks -- currently implemented by wine code */ + /* Spanish have severals */ + deadkey, + + /* Key names */ + (VSC_LPWSTR *)key_names, + (VSC_LPWSTR *)extended_key_names, + NULL, + /* Dead key names */ + + /* scan code to virtual key maps */ + scancode_to_vk, + sizeof(scancode_to_vk) / sizeof(scancode_to_vk[0]), + extcode0_to_vk, + extcode1_to_vk, + + MAKELONG(0,1), /* Version 1.0 */ + + /* Ligatures -- Spanish doesn't have any */ + 0, + 0, + NULL +}; + + +PKBDTABLES STDCALL KbdLayerDescriptor() { + return &keyboard_layout_table; +} diff --git a/reactos/lib/kbdes/kbdes.def b/reactos/lib/kbdes/kbdes.def new file mode 100644 index 00000000000..27d0cf710c0 --- /dev/null +++ b/reactos/lib/kbdes/kbdes.def @@ -0,0 +1,3 @@ +LIBRARY kbdda.dll +EXPORTS +KbdLayerDescriptor@0 diff --git a/reactos/lib/kbdes/kbdes.rc b/reactos/lib/kbdes/kbdes.rc new file mode 100644 index 00000000000..04db5518ee1 --- /dev/null +++ b/reactos/lib/kbdes/kbdes.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Spanish Keyboard Layout\0" +#define REACTOS_STR_INTERNAL_NAME "kbdes\0" +#define REACTOS_STR_ORIGINAL_FILENAME "kbdes.dll\0" +#include diff --git a/reactos/lib/kbdes/kbdes.xml b/reactos/lib/kbdes/kbdes.xml new file mode 100644 index 00000000000..fe5f463bb2f --- /dev/null +++ b/reactos/lib/kbdes/kbdes.xml @@ -0,0 +1,7 @@ + + + include + + kbdes.c + kbdes.rc + diff --git a/reactos/lib/kbdes/makefile b/reactos/lib/kbdes/makefile new file mode 100644 index 00000000000..2ecbddb8534 --- /dev/null +++ b/reactos/lib/kbdes/makefile @@ -0,0 +1,22 @@ +PATH_TO_TOP = ../.. + +TARGET_TYPE = kmdll + +TARGET_NAME = kbdes + +TARGET_BASE = 0x5500000 + +TARGET_CFLAGS = -I$(PATH_TO_TOP)/ntoskrnl/include + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS + +TARGET_OBJECTS = kbdes.o + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/kernel32/debug/debugger.c b/reactos/lib/kernel32/debug/debugger.c index 3513555049d..0f190b993fb 100644 --- a/reactos/lib/kernel32/debug/debugger.c +++ b/reactos/lib/kernel32/debug/debugger.c @@ -24,24 +24,24 @@ CheckRemoteDebuggerPresent ( { HANDLE DebugPort; NTSTATUS Status; - - if(pbDebuggerPresent == NULL) + + if (pbDebuggerPresent == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - + Status = NtQueryInformationProcess(hProcess, ProcessDebugPort, (PVOID)&DebugPort, sizeof(HANDLE), NULL); - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { *pbDebuggerPresent = ((DebugPort != NULL) ? TRUE : FALSE); return TRUE; } - + SetLastErrorByStatus(Status); return FALSE; } @@ -64,8 +64,7 @@ ContinueDebugEvent ( ClientId.UniqueThread = (HANDLE)dwThreadId; Status = DbgUiContinue(&ClientId, dwContinueStatus); - - if(!NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); return FALSE; @@ -76,11 +75,13 @@ ContinueDebugEvent ( /* - * @unimplemented + * NOTE: I'm not sure if the function is complete. + * + * @unmplemented */ BOOL WINAPI -DebugActiveProcess ( +DebugActiveProcess( DWORD dwProcessId ) { diff --git a/reactos/lib/kernel32/except/except.c b/reactos/lib/kernel32/except/except.c index c63d06ab3aa..a02b159ab40 100644 --- a/reactos/lib/kernel32/except/except.c +++ b/reactos/lib/kernel32/except/except.c @@ -15,25 +15,52 @@ #define NDEBUG #include "../include/debug.h" -UINT GlobalErrMode = 0; LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = UnhandledExceptionFilter; -UINT GetErrorMode(void) +UINT +STDCALL +GetErrorMode(VOID) { - return GlobalErrMode; + NTSTATUS Status; + UINT ErrMode; + + Status = NtQueryInformationProcess(NtCurrentProcess(), + ProcessDefaultHardErrorMode, + (PVOID)&ErrMode, + sizeof(ErrMode), + NULL); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return 0; + } + + return ErrMode; } - /* * @implemented */ UINT STDCALL -SetErrorMode( UINT uMode ) +SetErrorMode(UINT uMode) { - UINT OldErrMode = GetErrorMode(); - GlobalErrMode = uMode; - return OldErrMode; + UINT PrevErrMode; + NTSTATUS Status; + + PrevErrMode = GetErrorMode(); + + Status = NtSetInformationProcess(NtCurrentProcess(), + ProcessDefaultHardErrorMode, + (PVOID)&uMode, + sizeof(uMode)); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return 0; + } + + return PrevErrMode; } diff --git a/reactos/lib/kernel32/file/curdir.c b/reactos/lib/kernel32/file/curdir.c index f0e4c6b525f..1084bd4359c 100644 --- a/reactos/lib/kernel32/file/curdir.c +++ b/reactos/lib/kernel32/file/curdir.c @@ -37,33 +37,61 @@ GetCurrentDirectoryA ( { ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; - - /* initialize ansi string */ - AnsiString.Length = 0; - AnsiString.MaximumLength = nBufferLength; - AnsiString.Buffer = lpBuffer; + ULONG Length; /* allocate buffer for unicode string */ UnicodeString.Length = 0; UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR); - UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), - 0, - UnicodeString.MaximumLength); + if (nBufferLength > 0) + { + UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + UnicodeString.MaximumLength); + + /* initialize ansi string */ + AnsiString.Length = 0; + AnsiString.MaximumLength = nBufferLength; + AnsiString.Buffer = lpBuffer; + } + else + { + UnicodeString.Buffer = NULL; + } /* get current directory */ UnicodeString.Length = RtlGetCurrentDirectory_U (UnicodeString.MaximumLength, UnicodeString.Buffer); - DPRINT("UnicodeString.Buffer %S\n", UnicodeString.Buffer); + DPRINT("UnicodeString.Buffer %wZ\n", &UnicodeString); /* convert unicode string to ansi (or oem) */ if (bIsFileApiAnsi) + { + Length = RtlUnicodeStringToAnsiSize (&UnicodeString); + if (Length > nBufferLength) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + UnicodeString.Buffer); + return Length-1; + } RtlUnicodeStringToAnsiString (&AnsiString, &UnicodeString, FALSE); + } else + { + Length = RtlUnicodeStringToOemSize (&UnicodeString); + if (Length > nBufferLength) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + UnicodeString.Buffer); + return Length-1; + } RtlUnicodeStringToOemString (&AnsiString, &UnicodeString, FALSE); + } DPRINT("AnsiString.Buffer %s\n", AnsiString.Buffer); /* free unicode string */ @@ -172,6 +200,7 @@ GetTempPathA ( { UNICODE_STRING UnicodeString; ANSI_STRING AnsiString; + DWORD Length; AnsiString.Length = 0; AnsiString.MaximumLength = nBufferLength; @@ -179,30 +208,50 @@ GetTempPathA ( /* initialize allocate unicode string */ UnicodeString.Length = 0; - UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR); - UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), - 0, - UnicodeString.MaximumLength); - - UnicodeString.Length = GetTempPathW (nBufferLength, - UnicodeString.Buffer) * sizeof(WCHAR); - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - RtlUnicodeStringToAnsiString (&AnsiString, - &UnicodeString, - FALSE); + if(nBufferLength > 0) + { + UnicodeString.MaximumLength = (nBufferLength + 1) * sizeof(WCHAR); + UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + UnicodeString.MaximumLength); + if (UnicodeString.Buffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } else - RtlUnicodeStringToOemString (&AnsiString, - &UnicodeString, - FALSE); + { + UnicodeString.MaximumLength = 0; + UnicodeString.Buffer = NULL; + } + + Length = GetTempPathW (nBufferLength, + UnicodeString.Buffer); + + if (nBufferLength >= Length) + { + /* only touch the buffer if the supplied buffer length is at least + the length that GetTempPathW returned! */ + UnicodeString.Length = Length * sizeof(WCHAR); + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&AnsiString, + &UnicodeString, + FALSE); + else + RtlUnicodeStringToOemString (&AnsiString, + &UnicodeString, + FALSE); + } /* free unicode string buffer */ RtlFreeHeap (RtlGetProcessHeap (), 0, UnicodeString.Buffer); - return AnsiString.Length; + return Length; } @@ -217,42 +266,70 @@ GetTempPathW ( ) { UNICODE_STRING Name; - UNICODE_STRING Value; + PUNICODE_STRING Value; + PTEB Teb; + DWORD Length; NTSTATUS Status; - Value.Length = 0; - Value.MaximumLength = (nBufferLength - 1) * sizeof(WCHAR); - Value.Buffer = lpBuffer; + Teb = NtCurrentTeb(); + Teb->StaticUnicodeString.Length = 0; + Teb->StaticUnicodeString.MaximumLength = MAX_PATH * sizeof(WCHAR); + Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer; + Value = &Teb->StaticUnicodeString; RtlRosInitUnicodeStringFromLiteral (&Name, - L"TMP"); + L"TMP"); Status = RtlQueryEnvironmentVariable_U (NULL, &Name, - &Value); + Value); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { RtlRosInitUnicodeStringFromLiteral (&Name, - L"TEMP"); + L"TEMP"); Status = RtlQueryEnvironmentVariable_U (NULL, &Name, - &Value); - + Value); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { - Value.Length = RtlGetCurrentDirectory_U (Value.MaximumLength, - Value.Buffer); + Value->Length = RtlGetCurrentDirectory_U(Value->MaximumLength, + Value->Buffer); } } - if (NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { - lpBuffer[Value.Length / sizeof(WCHAR)] = L'\\'; - lpBuffer[Value.Length / sizeof(WCHAR) + 1] = 0; + SetLastError(RtlNtStatusToDosError(Status)); + return 0; } - return Value.Length / sizeof(WCHAR) + 1; + Length = Value->Length / sizeof(WCHAR) + 1; + if (nBufferLength < Value->Length / sizeof(WCHAR) + 2) + Length++; + + if (nBufferLength >= Value->Length /sizeof(WCHAR) + 1) + { + if (nBufferLength < Value->Length / sizeof(WCHAR) + 2) + { + memcpy (lpBuffer, + Value->Buffer, + nBufferLength * sizeof(WCHAR)); + } + else + { + memcpy (lpBuffer, + Value->Buffer, + Value->Length); + lpBuffer[Value->Length / sizeof(WCHAR)] = L'\\'; + lpBuffer[Value->Length / sizeof(WCHAR) + 1] = 0; + } + } else if (nBufferLength > 0) + { + lpBuffer[0] = L'\0'; + } + + return Length; } diff --git a/reactos/lib/kernel32/file/dosdev.c b/reactos/lib/kernel32/file/dosdev.c index 6a5f07e5b99..c5e50bb5054 100644 --- a/reactos/lib/kernel32/file/dosdev.c +++ b/reactos/lib/kernel32/file/dosdev.c @@ -156,7 +156,7 @@ QueryDosDeviceW( DWORD ucchMax ) { - PDIRECTORY_BASIC_INFORMATION DirInfo; + POBJECT_DIRECTORY_INFORMATION DirInfo; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; HANDLE DirectoryHandle; @@ -252,7 +252,7 @@ QueryDosDeviceW( RestartScan = TRUE; Context = 0; Ptr = lpTargetPath; - DirInfo = (PDIRECTORY_BASIC_INFORMATION)Buffer; + DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; while (TRUE) { diff --git a/reactos/lib/kernel32/file/file.c b/reactos/lib/kernel32/file/file.c index 6d5be102491..5922ac6d99f 100644 --- a/reactos/lib/kernel32/file/file.c +++ b/reactos/lib/kernel32/file/file.c @@ -694,7 +694,7 @@ GetFileAttributesExW(LPCWSTR lpFileName, NTSTATUS Status; WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData; - DPRINT ("GetFileAttributesExW(%S) called\n", lpFileName); + DPRINT("GetFileAttributesExW(%S) called\n", lpFileName); if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL) @@ -709,7 +709,7 @@ GetFileAttributesExW(LPCWSTR lpFileName, NULL, NULL)) { - DPRINT ("Invalid path\n"); + DPRINT1 ("Invalid path\n"); SetLastError (ERROR_BAD_PATHNAME); return FALSE; } @@ -731,7 +731,7 @@ GetFileAttributesExW(LPCWSTR lpFileName, RtlFreeUnicodeString (&FileName); if (!NT_SUCCESS (Status)) { - DPRINT ("NtOpenFile() failed (Status %lx)\n", Status); + DPRINT1 ("NtOpenFile() failed %x (Status %lx)\n", &ObjectAttributes, Status); SetLastErrorByStatus (Status); return FALSE; } @@ -746,7 +746,7 @@ GetFileAttributesExW(LPCWSTR lpFileName, if (!NT_SUCCESS (Status)) { - DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status); + DPRINT1 ("NtQueryInformationFile() failed (Status %lx)\n", Status); SetLastErrorByStatus (Status); return FALSE; } diff --git a/reactos/lib/kernel32/file/npipe.c b/reactos/lib/kernel32/file/npipe.c index b2bb35f2341..32a8e7d8cb9 100644 --- a/reactos/lib/kernel32/file/npipe.c +++ b/reactos/lib/kernel32/file/npipe.c @@ -123,14 +123,17 @@ CreateNamedPipeW(LPCWSTR lpName, if (dwOpenMode & PIPE_ACCESS_DUPLEX) { CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX; + DesiredAccess |= (FILE_GENERIC_READ | FILE_GENERIC_WRITE); } else if (dwOpenMode & PIPE_ACCESS_INBOUND) { CreateOptions = CreateOptions | FILE_PIPE_INBOUND; + DesiredAccess |= FILE_GENERIC_READ; } else if (dwOpenMode & PIPE_ACCESS_OUTBOUND) { CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND; + DesiredAccess |= FILE_GENERIC_WRITE; } if (dwPipeMode & PIPE_TYPE_BYTE) diff --git a/reactos/lib/kernel32/include/kernel32.h b/reactos/lib/kernel32/include/kernel32.h index 26e3784c743..b4515c0ebc3 100755 --- a/reactos/lib/kernel32/include/kernel32.h +++ b/reactos/lib/kernel32/include/kernel32.h @@ -39,7 +39,7 @@ extern HANDLE hProcessHeap; extern HANDLE hBaseDir; extern HMODULE hCurrentModule; -extern CRITICAL_SECTION DllLock; +extern RTL_CRITICAL_SECTION DllLock; extern UNICODE_STRING DllDirectory; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index 43bc2e4e643..4033316d6cf 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -21,7 +21,7 @@ extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); -extern CRITICAL_SECTION ConsoleLock; +extern RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI IsDebuggerPresent(VOID); @@ -206,7 +206,7 @@ DuplicateConsoleHandle (HANDLE hConsole, Request.Type = CSRSS_DUPLICATE_HANDLE; Request.Data.DuplicateHandleRequest.Handle = hConsole; - Request.Data.DuplicateHandleRequest.ProcessId = GetCurrentProcessId(); + Request.Data.DuplicateHandleRequest.ProcessId = GetTeb()->Cid.UniqueProcess; Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), @@ -1356,7 +1356,7 @@ BOOL STDCALL AllocConsole(VOID) return FALSE; } - Request.Data.AllocConsoleRequest.CtrlDispatcher = (PCONTROLDISPATCHER) &ConsoleControlDispatcher; + Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher; Request.Type = CSRSS_ALLOC_CONSOLE; Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); @@ -1569,7 +1569,7 @@ IntPeekConsoleInput(HANDLE hConsoleInput, Size = nLength * sizeof(INPUT_RECORD); - Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase); + Status = CsrCaptureParameterBuffer(NULL, Size, &BufferBase, &BufferTargetBase); if(!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); @@ -1884,7 +1884,7 @@ IntReadConsoleOutput(HANDLE hConsoleOutput, Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); - Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase); + Status = CsrCaptureParameterBuffer(NULL, Size, &BufferBase, &BufferTargetBase); if(!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); @@ -3327,15 +3327,63 @@ SetConsoleOutputCP( /*-------------------------------------------------------------- * GetConsoleProcessList * - * @unimplemented + * @implemented */ DWORD STDCALL GetConsoleProcessList(LPDWORD lpdwProcessList, - DWORD dwProcessCount) + DWORD dwProcessCount) { - DPRINT1("GetConsoleProcessList(0x%x, 0x%x) UNIMPLEMENTED!\n", lpdwProcessList, dwProcessCount); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + CSRSS_API_REQUEST Request; + PCSRSS_API_REPLY Reply; + ULONG BufferSize, nProcesses; + NTSTATUS Status; + + if(lpdwProcessList == NULL || dwProcessCount == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + BufferSize = sizeof(CSRSS_API_REQUEST) + + (dwProcessCount * sizeof(Reply->Data.GetProcessListReply.ProcessId[0])); + + Reply = RtlAllocateHeap(GetProcessHeap(), 0, BufferSize); + if(Reply == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + Reply->Status = STATUS_SUCCESS; + + Request.Type = CSRSS_GET_PROCESS_LIST; + Request.Data.GetProcessListRequest.nMaxIds = dwProcessCount; + + Status = CsrClientCallServer(&Request, Reply, sizeof(CSRSS_API_REQUEST), + BufferSize); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply->Status)) + { + SetLastErrorByStatus (Status); + nProcesses = 0; + } + else + { + if(dwProcessCount >= Reply->Data.GetProcessListReply.nProcessIdsTotal) + { + nProcesses = Reply->Data.GetProcessListReply.nProcessIdsCopied; + for(nProcesses = 0; nProcesses < Reply->Data.GetProcessListReply.nProcessIdsCopied; nProcesses++) + { + *(lpdwProcessList++) = (DWORD)Reply->Data.GetProcessListReply.ProcessId[nProcesses]; + } + } + else + { + nProcesses = Reply->Data.GetProcessListReply.nProcessIdsTotal; + } + } + + RtlFreeHeap(GetProcessHeap(), 0, Reply); + return nProcesses; } diff --git a/reactos/lib/kernel32/misc/dllmain.c b/reactos/lib/kernel32/misc/dllmain.c index 95fd91cb64d..17e1bbc6818 100644 --- a/reactos/lib/kernel32/misc/dllmain.c +++ b/reactos/lib/kernel32/misc/dllmain.c @@ -33,8 +33,8 @@ DllMain(HANDLE hInst, LPVOID lpReserved); /* Critical section for various kernel32 data structures */ -CRITICAL_SECTION DllLock; -CRITICAL_SECTION ConsoleLock; +RTL_CRITICAL_SECTION DllLock; +RTL_CRITICAL_SECTION ConsoleLock; extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); diff --git a/reactos/lib/kernel32/misc/lcformat.c b/reactos/lib/kernel32/misc/lcformat.c index 043447a0142..c07b95890d4 100644 --- a/reactos/lib/kernel32/misc/lcformat.c +++ b/reactos/lib/kernel32/misc/lcformat.c @@ -82,15 +82,15 @@ typedef struct _NLS_FORMAT_NODE #define GetShortMonth(fmt,mth) fmt->lppszStrings[30 + mth] /* Write access to the cache is protected by this critical section */ -static CRITICAL_SECTION NLS_FormatsCS; -static CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = +static RTL_CRITICAL_SECTION NLS_FormatsCS; +static RTL_CRITICAL_SECTION_DEBUG NLS_FormatsCS_debug = { 0, 0, &NLS_FormatsCS, { &NLS_FormatsCS_debug.ProcessLocksList, &NLS_FormatsCS_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": NLS_Formats") } }; -static CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION NLS_FormatsCS = { &NLS_FormatsCS_debug, -1, 0, 0, 0, 0 }; /************************************************************************** * NLS_GetLocaleNumber diff --git a/reactos/lib/kernel32/misc/nls.c b/reactos/lib/kernel32/misc/nls.c index 259d3134231..8ecee401051 100755 --- a/reactos/lib/kernel32/misc/nls.c +++ b/reactos/lib/kernel32/misc/nls.c @@ -58,7 +58,7 @@ static const unsigned char UTF8Mask[6] = {0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; static LIST_ENTRY CodePageListHead; static CODEPAGE_ENTRY AnsiCodePage; static CODEPAGE_ENTRY OemCodePage; -static CRITICAL_SECTION CodePageListLock; +static RTL_CRITICAL_SECTION CodePageListLock; /* FORWARD DECLARATIONS *******************************************************/ diff --git a/reactos/lib/kernel32/misc/profile.c b/reactos/lib/kernel32/misc/profile.c index 406b90fd92b..fdb9ac4276f 100644 --- a/reactos/lib/kernel32/misc/profile.c +++ b/reactos/lib/kernel32/misc/profile.c @@ -72,14 +72,14 @@ static PROFILE *MRUProfile[N_CACHED_PROFILES]={NULL}; static const WCHAR emptystringW[] = {0}; -static CRITICAL_SECTION PROFILE_CritSect; -static CRITICAL_SECTION_DEBUG critsect_debug = +static RTL_CRITICAL_SECTION PROFILE_CritSect; +static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { 0, 0, &PROFILE_CritSect, { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 0, 0, { 0, (DWORD)(__FILE__ ": PROFILE_CritSect") } }; -static CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; +static RTL_CRITICAL_SECTION PROFILE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 }; static const char hex[16] = "0123456789ABCDEF"; diff --git a/reactos/lib/kernel32/misc/toolhelp.c b/reactos/lib/kernel32/misc/toolhelp.c index 9d2bb1a0df8..0ccb5f67da5 100644 --- a/reactos/lib/kernel32/misc/toolhelp.c +++ b/reactos/lib/kernel32/misc/toolhelp.c @@ -550,7 +550,7 @@ Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl) { BOOL Ret; - if(Snapshot->ModuleListCount > 0) + if(Snapshot->HeapListCount > 0) { LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); Snapshot->HeapListIndex = 1; diff --git a/reactos/lib/kernel32/process/create.c b/reactos/lib/kernel32/process/create.c index 6589c974f35..8aacef2fda9 100644 --- a/reactos/lib/kernel32/process/create.c +++ b/reactos/lib/kernel32/process/create.c @@ -1011,6 +1011,40 @@ CreateProcessW lpProcessInformation); } ///////////////////////////////////////// + + /* + * Get some information about the executable + */ + Status = ZwQuerySection(hSection, + SectionImageInformation, + &Sii, + sizeof(Sii), + &i); + if (! NT_SUCCESS(Status)) + { + NtClose(hSection); + DPRINT("Unable to get SectionImageInformation, status 0x%x\n", Status); + SetLastErrorByStatus(Status); + return FALSE; + } + + if (0 != (Sii.Characteristics & IMAGE_FILE_DLL)) + { + NtClose(hSection); + DPRINT("Can't execute a DLL\n"); + SetLastError(ERROR_BAD_EXE_FORMAT); + return FALSE; + } + + if (IMAGE_SUBSYSTEM_WINDOWS_GUI != Sii.Subsystem + && IMAGE_SUBSYSTEM_WINDOWS_CUI != Sii.Subsystem) + { + NtClose(hSection); + DPRINT("Invalid subsystem %d\n", Sii.Subsystem); + SetLastError(ERROR_CHILD_NOT_COMPLETE); + return FALSE; + } + /* * Initialize the process object attributes */ @@ -1133,16 +1167,6 @@ CreateProcessW DUPLICATE_SAME_ACCESS); /* FIXME - handle failure!!!!! */ } - - /* - * Get some information about the executable - */ - Status = ZwQuerySection(hSection, - SectionImageInformation, - &Sii, - sizeof(Sii), - &i); - /* FIXME - handle failure!!!!! */ /* * Close the section @@ -1157,9 +1181,9 @@ CreateProcessW &ProcessBasicInfo, sizeof(ProcessBasicInfo), &retlen); - DPRINT("ProcessBasicInfo.UniqueProcessId %d\n", + DPRINT("ProcessBasicInfo.UniqueProcessId 0x%x\n", ProcessBasicInfo.UniqueProcessId); - lpProcessInformation->dwProcessId = ProcessBasicInfo.UniqueProcessId; + lpProcessInformation->dwProcessId = (DWORD)ProcessBasicInfo.UniqueProcessId; /* * Tell the csrss server we are creating a new process diff --git a/reactos/lib/kernel32/process/proc.c b/reactos/lib/kernel32/process/proc.c index d90490dffca..83cf6788544 100644 --- a/reactos/lib/kernel32/process/proc.c +++ b/reactos/lib/kernel32/process/proc.c @@ -37,7 +37,18 @@ GetProcessAffinityMask (HANDLE hProcess, LPDWORD lpSystemAffinityMask) { PROCESS_BASIC_INFORMATION ProcessInfo; + SYSTEM_BASIC_INFORMATION SystemInfo; NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemBasicInformation, + &SystemInfo, + sizeof(SystemInfo), + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } Status = NtQueryInformationProcess (hProcess, ProcessBasicInformation, @@ -51,9 +62,7 @@ GetProcessAffinityMask (HANDLE hProcess, } *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask; - - /* FIXME */ - *lpSystemAffinityMask = 0x00000001; + *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessors; return TRUE; } @@ -315,7 +324,7 @@ GetProcessId(HANDLE Process) return 0; } - return ProcessBasic.UniqueProcessId; + return (DWORD)ProcessBasic.UniqueProcessId; } @@ -429,51 +438,6 @@ WaitForInputIdle ( } -/* - * @implemented - */ -VOID STDCALL -Sleep(DWORD dwMilliseconds) -{ - SleepEx(dwMilliseconds, FALSE); - return; -} - - -/* - * @implemented - */ -DWORD STDCALL -SleepEx(DWORD dwMilliseconds, - BOOL bAlertable) -{ - LARGE_INTEGER Interval; - NTSTATUS errCode; - - if (dwMilliseconds != INFINITE) - { - /* - * System time units are 100 nanoseconds (a nanosecond is a billionth of - * a second). - */ - Interval.QuadPart = -((ULONGLONG)dwMilliseconds * 10000); - } - else - { - /* Approximately 292000 years hence */ - Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL; - } - - errCode = NtDelayExecution (bAlertable, &Interval); - if (!NT_SUCCESS(errCode)) - { - SetLastErrorByStatus (errCode); - return -1; - } - return 0; -} - - /* * @implemented */ @@ -872,12 +836,12 @@ GetProcessPriorityBoost(HANDLE hProcess, PBOOL pDisablePriorityBoost) { NTSTATUS Status; - BOOL PriorityBoost; + ULONG PriorityBoost; Status = NtQueryInformationProcess(hProcess, ProcessPriorityBoost, &PriorityBoost, - sizeof(BOOL), + sizeof(ULONG), NULL); if (NT_SUCCESS(Status)) { @@ -899,12 +863,12 @@ SetProcessPriorityBoost(HANDLE hProcess, BOOL bDisablePriorityBoost) { NTSTATUS Status; - BOOL PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */ + ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */ Status = NtSetInformationProcess(hProcess, ProcessPriorityBoost, &PriorityBoost, - sizeof(BOOL)); + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); diff --git a/reactos/lib/kernel32/synch/critical.c b/reactos/lib/kernel32/synch/critical.c index 2409a44fb97..87810c8e021 100644 --- a/reactos/lib/kernel32/synch/critical.c +++ b/reactos/lib/kernel32/synch/critical.c @@ -26,7 +26,7 @@ InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { NTSTATUS Status; - Status = RtlInitializeCriticalSection(lpCriticalSection); + Status = RtlInitializeCriticalSection((PRTL_CRITICAL_SECTION)lpCriticalSection); if (!NT_SUCCESS(Status)) { RtlRaiseStatus(Status); @@ -45,7 +45,7 @@ InitializeCriticalSectionAndSpinCount( { NTSTATUS Status; - Status = RtlInitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount); + Status = RtlInitializeCriticalSectionAndSpinCount((PRTL_CRITICAL_SECTION)lpCriticalSection, dwSpinCount); if (Status) { RtlRaiseStatus(Status); diff --git a/reactos/lib/kernel32/thread/thread.c b/reactos/lib/kernel32/thread/thread.c index 57124e35117..c273c65fd84 100644 --- a/reactos/lib/kernel32/thread/thread.c +++ b/reactos/lib/kernel32/thread/thread.c @@ -852,4 +852,49 @@ GetThreadIOPendingFlag(HANDLE hThread, return FALSE; } + +/* + * @implemented + */ +VOID STDCALL +Sleep(DWORD dwMilliseconds) +{ + SleepEx(dwMilliseconds, FALSE); + return; +} + + +/* + * @implemented + */ +DWORD STDCALL +SleepEx(DWORD dwMilliseconds, + BOOL bAlertable) +{ + LARGE_INTEGER Interval; + NTSTATUS errCode; + + if (dwMilliseconds != INFINITE) + { + /* + * System time units are 100 nanoseconds (a nanosecond is a billionth of + * a second). + */ + Interval.QuadPart = -((ULONGLONG)dwMilliseconds * 10000); + } + else + { + /* Approximately 292000 years hence */ + Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL; + } + + errCode = NtDelayExecution ((bAlertable ? TRUE : FALSE), &Interval); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return -1; + } + return 0; +} + /* EOF */ diff --git a/reactos/lib/kjs/ksrc/ejumps.h b/reactos/lib/kjs/ksrc/ejumps.h index d5c0183790a..4717d66fddc 100644 --- a/reactos/lib/kjs/ksrc/ejumps.h +++ b/reactos/lib/kjs/ksrc/ejumps.h @@ -1175,6 +1175,7 @@ op_div: case JS_NAN: default: nan = 1; + l = 0.0; break; } @@ -1202,6 +1203,7 @@ op_div: case JS_NAN: default: nan = 1; + r = 0.0; break; } diff --git a/reactos/lib/kjs/ksrc/eswitch.h b/reactos/lib/kjs/ksrc/eswitch.h index 2836a8f84d5..41c6634b35b 100644 --- a/reactos/lib/kjs/ksrc/eswitch.h +++ b/reactos/lib/kjs/ksrc/eswitch.h @@ -1135,6 +1135,7 @@ case 41: case JS_NAN: default: nan = 1; + l = 0.0; break; } @@ -1162,6 +1163,7 @@ case 41: case JS_NAN: default: nan = 1; + r = 0.0; break; } diff --git a/reactos/lib/kjs/ksrc/eswt0.h b/reactos/lib/kjs/ksrc/eswt0.h index d0dc1acc68c..60b593ec3ed 100644 --- a/reactos/lib/kjs/ksrc/eswt0.h +++ b/reactos/lib/kjs/ksrc/eswt0.h @@ -1133,6 +1133,7 @@ case 41: case JS_NAN: default: nan = 1; + l = 0.0; break; } @@ -1160,6 +1161,7 @@ case 41: case JS_NAN: default: nan = 1; + r = 0.0; break; } diff --git a/reactos/lib/kjs/makefile b/reactos/lib/kjs/makefile index 8568accd506..7a0295ca8d9 100644 --- a/reactos/lib/kjs/makefile +++ b/reactos/lib/kjs/makefile @@ -18,7 +18,7 @@ TARGET_TYPE = library TARGET_NAME = kjs -TARGET_CFLAGS = -g -D__NTKJS__ -Werror -Wall -I. -Isrc -Iinclude +TARGET_CFLAGS = -g -D__NTKJS__ -D__NO_INLINE__ -Werror -Wall -I. -Isrc -Iinclude # require os code to explicitly request A/W version of structs/functions TARGET_CFLAGS += -D_DISABLE_TIDENTS diff --git a/reactos/lib/libwine/debug.c b/reactos/lib/libwine/debug.c index 9fb3e02ffe4..a72838eb114 100644 --- a/reactos/lib/libwine/debug.c +++ b/reactos/lib/libwine/debug.c @@ -25,6 +25,7 @@ #include #include +#include /* ---------------------------------------------------------------------- */ @@ -203,6 +204,12 @@ const char *wine_dbgstr_guid(const GUID *id) return str; } +const char *wine_dbgstr_longlong( unsigned long long ll ) +{ + if (ll >> 32) return wine_dbg_sprintf( "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll ); + else return wine_dbg_sprintf( "%lx", (unsigned long)ll ); +} + /* varargs wrapper for __wine_dbg_vsprintf */ const char *wine_dbg_sprintf( const char *format, ... ) { @@ -215,3 +222,8 @@ const char *wine_dbg_sprintf( const char *format, ... ) return buffer; } + +const char *wine_dbgstr_w( const WCHAR *s ) +{ + return wine_dbgstr_wn( s, -1 ); +} diff --git a/reactos/lib/mesa32/src/drivers/windows/gdi/wmesa.c b/reactos/lib/mesa32/src/drivers/windows/gdi/wmesa.c index 338a57714c6..09040c519ea 100644 --- a/reactos/lib/mesa32/src/drivers/windows/gdi/wmesa.c +++ b/reactos/lib/mesa32/src/drivers/windows/gdi/wmesa.c @@ -472,7 +472,7 @@ static void clear(GLcontext* ctx, GLbitfield mask, mask &= ~DD_BACK_LEFT_BIT; #endif // DDRAW #else - DWORD dwColor; + DWORD dwColor = 0; WORD wColor; BYTE bColor; LPDWORD lpdw = (LPDWORD)Current->pbPixels; @@ -523,8 +523,6 @@ static void clear(GLcontext* ctx, GLbitfield mask, GetGValue(Current->clearpixel), GetBValue(Current->clearpixel)); } - else - dwColor = 0; if (nBypp != 3) { diff --git a/reactos/lib/mmdrv/Makefile b/reactos/lib/mmdrv/Makefile index cff30e3f81e..fc7a55b3d14 100644 --- a/reactos/lib/mmdrv/Makefile +++ b/reactos/lib/mmdrv/Makefile @@ -14,7 +14,7 @@ TARGET_CFLAGS += -DUNICODE -D_UNICODE -Wall -Werror TARGET_LFLAGS = -TARGET_SDKLIBS = winmm.a +TARGET_SDKLIBS = winmm.a ntdll.a TARGET_BASE = $(TARGET_BASE_LIB_MMDRV) diff --git a/reactos/lib/mmdrv/auxil.c b/reactos/lib/mmdrv/auxil.c index 4d1ea8b4f05..4bbcc522eef 100644 --- a/reactos/lib/mmdrv/auxil.c +++ b/reactos/lib/mmdrv/auxil.c @@ -12,6 +12,8 @@ #include "mmdrv.h" +#define NDEBUG +#include APIENTRY DWORD auxMessage(UINT uDevice, UINT uMessage, @@ -20,7 +22,7 @@ APIENTRY DWORD auxMessage(UINT uDevice, DWORD dwParam2) { - printf("auxMessage\n"); + DPRINT("auxMessage\n"); // the following cases are documented by DDK switch (uMessage) diff --git a/reactos/lib/mmdrv/entry.c b/reactos/lib/mmdrv/entry.c index 09428ed81c3..d2beefe0e89 100644 --- a/reactos/lib/mmdrv/entry.c +++ b/reactos/lib/mmdrv/entry.c @@ -14,6 +14,8 @@ #include "mmdrv.h" +#define NDEBUG +#include #define EXPORT __declspec(dllexport) @@ -22,14 +24,14 @@ CRITICAL_SECTION DriverSection; APIENTRY LONG DriverProc(DWORD DriverID, HANDLE DriverHandle, UINT Message, LONG Param1, LONG Param2) { - printf("DriverProc\n"); + DPRINT("DriverProc\n"); // HINSTANCE Module; switch(Message) { case DRV_LOAD : - printf("DRV_LOAD\n"); + DPRINT("DRV_LOAD\n"); return TRUE; // dont need to do any more /* Module = GetDriverModuleHandle(DriverHandle); @@ -56,7 +58,7 @@ APIENTRY LONG DriverProc(DWORD DriverID, HANDLE DriverHandle, UINT Message, // return 1L; case DRV_FREE : - printf("DRV_FREE\n"); + DPRINT("DRV_FREE\n"); // TerminateMidi(); // TerminateWave(); @@ -65,35 +67,35 @@ APIENTRY LONG DriverProc(DWORD DriverID, HANDLE DriverHandle, UINT Message, return 1L; case DRV_OPEN : - printf("DRV_OPEN\n"); + DPRINT("DRV_OPEN\n"); return 1L; case DRV_CLOSE : - printf("DRV_CLOSE\n"); + DPRINT("DRV_CLOSE\n"); return 1L; case DRV_ENABLE : - printf("DRV_ENABLE\n"); + DPRINT("DRV_ENABLE\n"); return 1L; case DRV_DISABLE : - printf("DRV_DISABLE\n"); + DPRINT("DRV_DISABLE\n"); return 1L; case DRV_QUERYCONFIGURE : - printf("DRV_QUERYCONFIGURE\n"); + DPRINT("DRV_QUERYCONFIGURE\n"); return 0L; case DRV_CONFIGURE : - printf("DRV_CONFIGURE\n"); + DPRINT("DRV_CONFIGURE\n"); return 0L; case DRV_INSTALL : - printf("DRV_INSTALL\n"); + DPRINT("DRV_INSTALL\n"); return DRVCNF_RESTART; default : - printf("?\n"); + DPRINT("?\n"); return DefDriverProc(DriverID, DriverHandle, Message, Param1, Param2); }; } @@ -101,7 +103,7 @@ APIENTRY LONG DriverProc(DWORD DriverID, HANDLE DriverHandle, UINT Message, BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved) { - printf("DllMain called!\n"); + DPRINT("DllMain called!\n"); if (Reason == DLL_PROCESS_ATTACH) { diff --git a/reactos/lib/mmdrv/midi.c b/reactos/lib/mmdrv/midi.c index 083c38c12e2..c4e22bb65c8 100644 --- a/reactos/lib/mmdrv/midi.c +++ b/reactos/lib/mmdrv/midi.c @@ -11,6 +11,8 @@ #include "mmdrv.h" +#define NDEBUG +#include // MIDI device instance information // @@ -66,7 +68,7 @@ static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1, MMRESULT Result = MMSYSERR_NOERROR; // Check ID? - printf("OpenMidiDevice()\n"); + DPRINT("OpenMidiDevice()\n"); switch(DeviceType) { @@ -119,7 +121,7 @@ static DWORD WriteMidi(PBYTE pData, ULONG Length, PMIDIALLOC pClient) { DWORD BytesReturned; - printf("IOCTL_MIDI_PLAY == %d [%x]\n", IOCTL_MIDI_PLAY, IOCTL_MIDI_PLAY); + DPRINT("IOCTL_MIDI_PLAY == %d [%x]\n", IOCTL_MIDI_PLAY, IOCTL_MIDI_PLAY); if ( !DeviceIoControl(pClient->DeviceHandle, IOCTL_MIDI_PLAY, (PVOID)pData, Length, NULL, 0, &BytesReturned, NULL)) @@ -174,40 +176,40 @@ static int GetMidiLength(PMIDIALLOC pClient, BYTE b) APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { - printf("midMessage\n"); + DPRINT("midMessage\n"); return MMSYSERR_NOERROR; switch (dwMessage) { case MIDM_GETNUMDEVS: - printf("MIDM_GETNUMDEVS"); + DPRINT("MIDM_GETNUMDEVS"); return 0; case MIDM_GETDEVCAPS: - printf("MIDM_GETDEVCAPS"); + DPRINT("MIDM_GETDEVCAPS"); return MMSYSERR_NOERROR; case MIDM_OPEN: - printf("MIDM_OPEN"); + DPRINT("MIDM_OPEN"); return MMSYSERR_NOERROR; case MIDM_CLOSE: - printf("MIDM_CLOSE"); + DPRINT("MIDM_CLOSE"); return MMSYSERR_NOERROR; case MIDM_ADDBUFFER: - printf("MIDM_ADDBUFFER"); + DPRINT("MIDM_ADDBUFFER"); return MMSYSERR_NOERROR; case MIDM_STOP: - printf("MIDM_PAUSE"); + DPRINT("MIDM_PAUSE"); return MMSYSERR_NOERROR; case MIDM_START: - printf("MIDM_RESTART"); + DPRINT("MIDM_RESTART"); return MMSYSERR_NOERROR; case MIDM_RESET: - printf("MIDM_RESET"); + DPRINT("MIDM_RESET"); return MMSYSERR_NOERROR; default: @@ -221,27 +223,27 @@ APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar APIENTRY DWORD modMessage(DWORD ID, DWORD Message, DWORD User, DWORD Param1, DWORD Param2) { - printf("modMessage\n"); + DPRINT("modMessage\n"); switch(Message) { case MODM_GETNUMDEVS: - printf("MODM_GETNUMDEVS == %d\n", (int)GetDeviceCount(MidiOutDevice)); + DPRINT("MODM_GETNUMDEVS == %d\n", (int)GetDeviceCount(MidiOutDevice)); return GetDeviceCount(MidiOutDevice); case MODM_GETDEVCAPS: - printf("MODM_GETDEVCAPS"); + DPRINT("MODM_GETDEVCAPS"); return MMSYSERR_NOTSUPPORTED; case MODM_OPEN : return OpenMidiDevice(MidiOutDevice, ID, User, Param1, Param2); case MODM_CLOSE: - printf("MODM_CLOSE"); + DPRINT("MODM_CLOSE"); return MMSYSERR_NOTSUPPORTED; case MODM_DATA: - printf("MODM_DATA"); + DPRINT("MODM_DATA"); int i; BYTE b[4]; @@ -253,27 +255,27 @@ APIENTRY DWORD modMessage(DWORD ID, DWORD Message, DWORD User, DWORD Param1, DWO (PMIDIALLOC)User); case MODM_LONGDATA: - printf("MODM_LONGDATA"); + DPRINT("MODM_LONGDATA"); return MMSYSERR_NOTSUPPORTED; case MODM_RESET: - printf("MODM_RESET"); + DPRINT("MODM_RESET"); return MMSYSERR_NOTSUPPORTED; case MODM_SETVOLUME: - printf("MODM_SETVOLUME"); + DPRINT("MODM_SETVOLUME"); return MMSYSERR_NOTSUPPORTED; case MODM_GETVOLUME: - printf("MODM_GETVOLUME"); + DPRINT("MODM_GETVOLUME"); return MMSYSERR_NOTSUPPORTED; case MODM_CACHEPATCHES: - printf("MODM_CACHEPATCHES"); + DPRINT("MODM_CACHEPATCHES"); return MMSYSERR_NOTSUPPORTED; case MODM_CACHEDRUMPATCHES: - printf("MODM_CACHEDRUMPATCHES"); + DPRINT("MODM_CACHEDRUMPATCHES"); return MMSYSERR_NOTSUPPORTED; }; diff --git a/reactos/lib/mmdrv/mmdrv.h b/reactos/lib/mmdrv/mmdrv.h index 6891333fadb..f9211d362a4 100644 --- a/reactos/lib/mmdrv/mmdrv.h +++ b/reactos/lib/mmdrv/mmdrv.h @@ -31,6 +31,8 @@ #include "mmdef.h" +ULONG DbgPrint(PCH Format, ...); + /* #define SOUND_MAX_DEVICE_NAME 1024 // GUESSWORK #define SOUND_MAX_DEVICES 256 // GUESSWORK diff --git a/reactos/lib/mmdrv/utils.c b/reactos/lib/mmdrv/utils.c index e335d53b581..e97fc004a10 100644 --- a/reactos/lib/mmdrv/utils.c +++ b/reactos/lib/mmdrv/utils.c @@ -11,6 +11,8 @@ #include "mmdrv.h" +#define NDEBUG +#include typedef struct _DEVICE_LIST { @@ -59,7 +61,7 @@ DWORD TranslateStatus(void) MMRESULT OpenDevice(UINT DeviceType, DWORD ID, PHANDLE pDeviceHandle, DWORD Access) { - printf("OpenDevice()\n"); + DPRINT("OpenDevice()\n"); WCHAR DeviceName[SOUND_MAX_DEVICE_NAME]; *pDeviceHandle = INVALID_HANDLE_VALUE; @@ -84,13 +86,13 @@ MMRESULT OpenDevice(UINT DeviceType, DWORD ID, PHANDLE pDeviceHandle, wsprintf(DeviceName, L"\\\\.%ls%d", AUX_DEVICE_NAME_U + strlen("\\Device"), ID); }; - printf("Attempting to open %S\n", DeviceName); + DPRINT("Attempting to open %S\n", DeviceName); *pDeviceHandle = CreateFile(DeviceName, Access, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, Access != GENERIC_READ ? FILE_FLAG_OVERLAPPED : 0, NULL); - printf("DeviceHandle == 0x%x\n", (int)*pDeviceHandle); + DPRINT("DeviceHandle == 0x%x\n", (int)*pDeviceHandle); if (pDeviceHandle == INVALID_HANDLE_VALUE) return TranslateStatus(); @@ -107,7 +109,7 @@ BOOL AddDeviceToList(PDEVICE_LIST* pList, DWORD DeviceType, DWORD CardIndex, { PDEVICE_LIST pNewDevice; - printf("AddDeviceToList()\n"); + DPRINT("AddDeviceToList()\n"); pNewDevice = (PDEVICE_LIST) HeapAlloc(Heap, 0, sizeof(DEVICE_LIST) + lstrlen(Name) * sizeof(WCHAR)); @@ -125,7 +127,7 @@ BOOL AddDeviceToList(PDEVICE_LIST* pList, DWORD DeviceType, DWORD CardIndex, pNewDevice->Next = *pList; *pList = pNewDevice; - printf("Success!\n"); + DPRINT("Success!\n"); return TRUE; } @@ -135,7 +137,7 @@ VOID FreeDeviceList() { PDEVICE_LIST pDevice; - printf("FreeDeviceList()\n"); + DPRINT("FreeDeviceList()\n"); while (DeviceList) { @@ -155,7 +157,7 @@ MMRESULT FindDevices() // DWORD Index; // HKEY DriverKey; - printf("Finding devices\n"); + DPRINT("Finding devices\n"); // DriverKey = OpenParametersKey(); // see drvutil.c of MS DDK for how this SHOULD be done... diff --git a/reactos/lib/mmdrv/wave.c b/reactos/lib/mmdrv/wave.c index d3f3d1cbc38..5816d245cc8 100644 --- a/reactos/lib/mmdrv/wave.c +++ b/reactos/lib/mmdrv/wave.c @@ -14,6 +14,9 @@ #include "mmdrv.h" #include "wave.h" +#define NDEBUG +#include + /* ============================ * INTERNAL * functions start here @@ -144,23 +147,23 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar { switch (dwMessage) { case WODM_GETNUMDEVS: - printf("WODM_GETNUMDEVS"); + DPRINT("WODM_GETNUMDEVS"); return GetDeviceCount(WaveOutDevice); case WODM_GETDEVCAPS: - printf("WODM_GETDEVCAPS"); + DPRINT("WODM_GETDEVCAPS"); return GetDeviceCapabilities(dwId, WaveOutDevice, (LPBYTE)dwParam1, (DWORD)dwParam2); case WODM_OPEN: - printf("WODM_OPEN"); + DPRINT("WODM_OPEN"); return OpenWaveDevice(WaveOutDevice, dwId, dwUser, dwParam1, dwParam2); case WODM_CLOSE: { MMRESULT Result; PWAVEALLOC pTask = (PWAVEALLOC)dwUser; - printf("WODM_CLOSE"); + DPRINT("WODM_CLOSE"); // 1. Check if the task is ready to complete Result = ThreadCallWaveDevice(WaveThreadClose, pTask); @@ -186,7 +189,7 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar { LPWAVEHDR pWaveHdr = (LPWAVEHDR)dwParam1; - printf("WODM_WRITE"); + DPRINT("WODM_WRITE"); if (dwParam1 != 0) return MMSYSERR_INVALPARAM; @@ -215,37 +218,37 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar case WODM_PAUSE: - printf("WODM_PAUSE"); + DPRINT("WODM_PAUSE"); ((PWAVEALLOC)dwUser)->AuxParam.State = WAVE_DD_STOP; return ThreadCallWaveDevice(WaveThreadSetState, (PWAVEALLOC)dwUser); case WODM_RESTART: - printf("WODM_RESTART"); + DPRINT("WODM_RESTART"); ((PWAVEALLOC)dwUser)->AuxParam.State = WAVE_DD_PLAY; return ThreadCallWaveDevice(WaveThreadSetState, (PWAVEALLOC)dwUser); case WODM_RESET: - printf("WODM_RESET"); + DPRINT("WODM_RESET"); ((PWAVEALLOC)dwUser)->AuxParam.State = WAVE_DD_RESET; return ThreadCallWaveDevice(WaveThreadSetState, (PWAVEALLOC)dwUser); case WODM_BREAKLOOP: - printf("WODM_BREAKLOOP"); + DPRINT("WODM_BREAKLOOP"); return ThreadCallWaveDevice(WaveThreadBreakLoop, (PWAVEALLOC)dwUser); case WODM_GETPOS: - printf("WODM_GETPOS"); + DPRINT("WODM_GETPOS"); return GetPositionWaveDevice(((PWAVEALLOC)dwUser), (LPMMTIME)dwParam1, dwParam2); case WODM_SETPITCH: - printf("WODM_SETPITCH"); + DPRINT("WODM_SETPITCH"); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.pData = (PBYTE)&dwParam1; ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.DataLen = sizeof(DWORD); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.Function = IOCTL_WAVE_SET_PITCH; return ThreadCallWaveDevice(WaveThreadSetData, ((PWAVEALLOC)dwUser)); case WODM_SETVOLUME: - printf("WODM_SETVOLUME"); + DPRINT("WODM_SETVOLUME"); { WAVE_DD_VOLUME Vol; Vol.Left = LOWORD(dwParam1) << 16; @@ -256,21 +259,21 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar } case WODM_SETPLAYBACKRATE: - printf("WODM_SETPLAYBACKRATE"); + DPRINT("WODM_SETPLAYBACKRATE"); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.pData = (PBYTE)&dwParam1; ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.DataLen = sizeof(DWORD); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.Function = IOCTL_WAVE_SET_PLAYBACK_RATE; return ThreadCallWaveDevice(WaveThreadSetData, (PWAVEALLOC)dwUser); case WODM_GETPITCH: - printf("WODM_GETPITCH"); + DPRINT("WODM_GETPITCH"); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.pData = (PBYTE)dwParam1; ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.DataLen = sizeof(DWORD); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.Function = IOCTL_WAVE_GET_PITCH; return ThreadCallWaveDevice(WaveThreadGetData, (PWAVEALLOC)dwUser); case WODM_GETVOLUME: - printf("WODM_GETVOLUME"); + DPRINT("WODM_GETVOLUME"); { WAVE_DD_VOLUME Vol; DWORD res; @@ -285,7 +288,7 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar } case WODM_GETPLAYBACKRATE: - printf("WODM_GETPLAYBACKRATE"); + DPRINT("WODM_GETPLAYBACKRATE"); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.pData = (PBYTE)dwParam1; ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.DataLen = sizeof(DWORD); ((PWAVEALLOC)dwUser)->AuxParam.GetSetData.Function = IOCTL_WAVE_GET_PLAYBACK_RATE; @@ -305,7 +308,7 @@ APIENTRY DWORD wodMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwPar */ APIENTRY DWORD widMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { - printf("widMessage\n"); + DPRINT("widMessage\n"); switch (dwMessage) { case WIDM_GETNUMDEVS: diff --git a/reactos/lib/mpr/mpr.rc b/reactos/lib/mpr/mpr.rc index d6fdfe7be7d..3c399678f4f 100644 --- a/reactos/lib/mpr/mpr.rc +++ b/reactos/lib/mpr/mpr.rc @@ -19,6 +19,7 @@ */ #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mprres.h" #include "version.rc" diff --git a/reactos/lib/mpr/mpr_En.rc b/reactos/lib/mpr/mpr_En.rc index 31f4e928845..b6f9d807d06 100644 --- a/reactos/lib/mpr/mpr_En.rc +++ b/reactos/lib/mpr/mpr_En.rc @@ -24,3 +24,23 @@ STRINGTABLE DISCARDABLE { IDS_ENTIRENETWORK "Entire Network" } + +IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Enter Network Password" +FONT 8, "Helv" +{ + LTEXT "Please enter your username and password:", IDC_EXPLAIN, 40, 6, 150, 15 + LTEXT "Proxy", -1, 40, 26, 50, 10 +/* LTEXT "Realm", -1, 40, 46, 50, 10 */ + LTEXT "User", -1, 40, 66, 50, 10 + LTEXT "Password", -1, 40, 86, 50, 10 + LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 + LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 + EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD + CHECKBOX "&Save this password (Insecure)", IDC_SAVEPASSWORD, + 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON + PUSHBUTTON "Cancel", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} diff --git a/reactos/lib/mpr/mprres.h b/reactos/lib/mpr/mprres.h index cc8f0108758..bfaa59a242c 100644 --- a/reactos/lib/mpr/mprres.h +++ b/reactos/lib/mpr/mprres.h @@ -20,4 +20,13 @@ #define IDS_ENTIRENETWORK 1 +#define IDD_PROXYDLG 0x400 + +#define IDC_PROXY 0x401 +#define IDC_REALM 0x402 +#define IDC_USERNAME 0x403 +#define IDC_PASSWORD 0x404 +#define IDC_SAVEPASSWORD 0x405 +#define IDC_EXPLAIN 0x406 + #endif /* ndef __WINE_MPRRES_H__ */ diff --git a/reactos/lib/mpr/nps.c b/reactos/lib/mpr/nps.c index 6a65b74001c..c791b23317e 100644 --- a/reactos/lib/mpr/nps.c +++ b/reactos/lib/mpr/nps.c @@ -2,6 +2,7 @@ * MPR Network Provider Services functions * * Copyright 1999 Ulrich Weigand + * Copyright 2004 Mike McCormack for CodeWeavers Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,24 +19,109 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" + #include #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "winnetwk.h" #include "netspi.h" #include "wine/debug.h" +#include "winerror.h" WINE_DEFAULT_DEBUG_CHANNEL(mpr); +#include "wine/unicode.h" + +#include "mprres.h" + +/*********************************************************************** + * NPS_ProxyPasswordDialog + */ +static INT_PTR WINAPI NPS_ProxyPasswordDialog( + HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + HWND hitem; + LPAUTHDLGSTRUCTA lpAuthDlgStruct; + + if( uMsg == WM_INITDIALOG ) + { + TRACE("WM_INITDIALOG (%08lx)\n", lParam); + + /* save the parameter list */ + lpAuthDlgStruct = (LPAUTHDLGSTRUCTA) lParam; + SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam ); + + if( lpAuthDlgStruct->lpExplainText ) + { + hitem = GetDlgItem( hdlg, IDC_EXPLAIN ); + SetWindowTextA( hitem, lpAuthDlgStruct->lpExplainText ); + } + + /* extract the Realm from the proxy response and show it */ + if( lpAuthDlgStruct->lpResource ) + { + hitem = GetDlgItem( hdlg, IDC_REALM ); + SetWindowTextA( hitem, lpAuthDlgStruct->lpResource ); + } + + return TRUE; + } + + lpAuthDlgStruct = (LPAUTHDLGSTRUCTA) GetWindowLongPtrW( hdlg, GWLP_USERDATA ); + + switch( uMsg ) + { + case WM_COMMAND: + if( wParam == IDOK ) + { + WCHAR username[0x20], password[0x20]; + + username[0] = 0; + hitem = GetDlgItem( hdlg, IDC_USERNAME ); + if( hitem ) + GetWindowTextA( hitem, lpAuthDlgStruct->lpUsername, lpAuthDlgStruct->cbUsername ); + + password[0] = 0; + hitem = GetDlgItem( hdlg, IDC_PASSWORD ); + if( hitem ) + GetWindowTextA( hitem, lpAuthDlgStruct->lpPassword, lpAuthDlgStruct->cbPassword ); + + EndDialog( hdlg, WN_SUCCESS ); + return TRUE; + } + if( wParam == IDCANCEL ) + { + EndDialog( hdlg, WN_CANCEL ); + return TRUE; + } + break; + } + return FALSE; +} /***************************************************************** * NPSAuthenticationDialogA [MPR.@] */ DWORD WINAPI NPSAuthenticationDialogA( LPAUTHDLGSTRUCTA lpAuthDlgStruct ) { - FIXME( "(%p): stub\n", lpAuthDlgStruct ); - return WN_NOT_SUPPORTED; + HMODULE hwininet = GetModuleHandleA( "mpr.dll" ); + + TRACE("%p\n", lpAuthDlgStruct); + + if( !lpAuthDlgStruct ) + return WN_BAD_POINTER; + if( lpAuthDlgStruct->cbStructure < sizeof *lpAuthDlgStruct ) + return WN_BAD_POINTER; + + TRACE("%s %s %s\n",lpAuthDlgStruct->lpResource, + lpAuthDlgStruct->lpOUTitle, lpAuthDlgStruct->lpExplainText); + + return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ), + lpAuthDlgStruct->hwndOwner, NPS_ProxyPasswordDialog, + (LPARAM) lpAuthDlgStruct ); } /***************************************************************** diff --git a/reactos/lib/mpr/wnet.c b/reactos/lib/mpr/wnet.c index 67f723c1a23..19caab35da1 100644 --- a/reactos/lib/mpr/wnet.c +++ b/reactos/lib/mpr/wnet.c @@ -198,8 +198,7 @@ static void _tryLoadProvider(PCWSTR provider) { WARN("Provider %s didn't export NPGetCaps\n", debugstr_w(provider)); - if (name) - HeapFree(GetProcessHeap(), 0, name); + HeapFree(GetProcessHeap(), 0, name); FreeLibrary(hLib); } } @@ -312,8 +311,7 @@ void wnetFree(void) HeapFree(GetProcessHeap(), 0, providerTable->table[i].name); FreeModule(providerTable->table[i].hLib); } - if (providerTable->entireNetwork) - HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork); + HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork); HeapFree(GetProcessHeap(), 0, providerTable); providerTable = NULL; } @@ -372,8 +370,7 @@ static void _freeEnumNetResource(LPNETRESOURCEW lpNet) { if (lpNet) { - if (lpNet->lpRemoteName) - HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName); + HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName); HeapFree(GetProcessHeap(), 0, lpNet); } } diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c index 3509949bddc..749dcef4743 100644 --- a/reactos/lib/msafd/misc/dllmain.c +++ b/reactos/lib/msafd/misc/dllmain.c @@ -16,8 +16,8 @@ #include #ifdef DBG -//DWORD DebugTraceLevel = DEBUG_ULTRA; -DWORD DebugTraceLevel = 0; +DWORD DebugTraceLevel = DEBUG_ULTRA; +//DWORD DebugTraceLevel = 0; #endif /* DBG */ HANDLE GlobalHeap; @@ -66,7 +66,7 @@ WSPSocket( PHELPER_DATA HelperData; PVOID HelperDLLContext; DWORD HelperEvents; - DWORD IOOptions; + DWORD IOOptions = 0; UNICODE_STRING TransportName; UNICODE_STRING DevName; LARGE_INTEGER GroupData; @@ -123,8 +123,11 @@ WSPSocket( Socket->SanData = NULL; /* Ask alex about this */ - if( Socket->SharedData.SocketType == SOCK_DGRAM ) + if( Socket->SharedData.SocketType == SOCK_DGRAM || + Socket->SharedData.SocketType == SOCK_RAW ) { + AFD_DbgPrint(MID_TRACE,("Connectionless socket\n")); Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS; + } /* Packet Size */ SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR); @@ -133,7 +136,7 @@ WSPSocket( SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH; /* Set up EA Buffer */ - EABuffer = HeapAlloc(GlobalHeap, 0, (SIZE_T)&SizeOfEA); + EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA); EABuffer->NextEntryOffset = 0; EABuffer->Flags = 0; EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH; @@ -248,10 +251,11 @@ WSPSocket( Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno); /* Return Socket Handle */ + AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock)); return (SOCKET)Sock; error: - AFD_DbgPrint(MID_TRACE,("Ending\n")); + AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status)); if( lpErrno ) *lpErrno = Status; @@ -565,7 +569,6 @@ WSPSelect( NTSTATUS Status; ULONG HandleCount, OutCount = 0; ULONG PollBufferSize; - LARGE_INTEGER uSec; PVOID PollBuffer; ULONG i, j = 0, x; HANDLE SockEvent; @@ -598,7 +601,6 @@ WSPSelect( } else { PollInfo->Timeout = RtlEnlargedIntegerMultiply ((timeout->tv_sec * 1000) + timeout->tv_usec, -10000); - PollInfo->Timeout.QuadPart += uSec.QuadPart; } /* Number of handles for AFD to Check */ @@ -727,8 +729,8 @@ WSPAccept( NTSTATUS Status; struct fd_set ReadSet; struct timeval Timeout; - PVOID PendingData; - ULONG PendingDataLength; + PVOID PendingData = NULL; + ULONG PendingDataLength = 0; PVOID CalleeDataBuffer; WSABUF CallerData, CalleeID, CallerID, CalleeData; PSOCKADDR RemoteAddress = NULL; @@ -972,19 +974,26 @@ WSPAccept( } /* Return Address in SOCKADDR FORMAT */ - RtlCopyMemory (SocketAddress, - &ListenReceiveData->Address.Address[0].AddressType, - sizeof(RemoteAddress)); + if( SocketAddress ) { + RtlCopyMemory (SocketAddress, + &ListenReceiveData->Address.Address[0].AddressType, + sizeof(RemoteAddress)); + if( *SocketAddressLength ) + *SocketAddressLength = + ListenReceiveData->Address.Address[0].AddressLength; + } NtClose( SockEvent ); /* Re-enable Async Event */ SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); - - /* Return Socket */ - return AcceptSocket; + AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); + + *lpErrno = 0; + + /* Return Socket */ + return AcceptSocket; } int @@ -1286,12 +1295,77 @@ INT WSPAPI WSPGetPeerName( IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT LPINT namelen, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, OUT LPINT lpErrno) { - - return 0; + IO_STATUS_BLOCK IOSB; + ULONG TdiAddressSize; + PTDI_ADDRESS_INFO TdiAddress; + PTRANSPORT_ADDRESS SocketAddress; + PSOCKET_INFORMATION Socket = NULL; + NTSTATUS Status; + HANDLE SockEvent; + + Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, + NULL, 1, FALSE ); + + if( !NT_SUCCESS(Status) ) return SOCKET_ERROR; + + /* Get the Socket Structure associate to this Socket*/ + Socket = GetSocketStructure(s); + + /* Allocate a buffer for the address */ + TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, + Address.Address[0].Address) + + Socket->SharedData.SizeOfLocalAddress; + TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); + + if ( TdiAddress == NULL ) { + NtClose( SockEvent ); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + SocketAddress = &TdiAddress->Address; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle, + SockEvent, + NULL, + NULL, + &IOSB, + IOCTL_AFD_GET_PEER_NAME, + NULL, + 0, + TdiAddress, + TdiAddressSize); + + /* Wait for return */ + if (Status == STATUS_PENDING) { + WaitForSingleObject(SockEvent, INFINITE); + Status = IOSB.Status; + } + + NtClose( SockEvent ); + + if (NT_SUCCESS(Status)) { + if (*NameLength >= SocketAddress->Address[0].AddressLength) { + Name->sa_family = SocketAddress->Address[0].AddressType; + RtlCopyMemory (Name->sa_data, + SocketAddress->Address[0].Address, + SocketAddress->Address[0].AddressLength); + HeapFree(GlobalHeap, 0, TdiAddress); + return 0; + } else { + HeapFree(GlobalHeap, 0, TdiAddress); + *lpErrno = WSAEFAULT; + return SOCKET_ERROR; + } + } + + return MsafdReturnWithErrno + ( IOSB.Status, lpErrno, 0, NULL ); } INT diff --git a/reactos/lib/msafd/misc/sndrcv.c b/reactos/lib/msafd/misc/sndrcv.c index 8ef096ff07a..7c28b66f212 100644 --- a/reactos/lib/msafd/misc/sndrcv.c +++ b/reactos/lib/msafd/misc/sndrcv.c @@ -103,7 +103,7 @@ WSPRecv( HANDLE SockEvent; PSOCKET_INFORMATION Socket; - AFD_DbgPrint(MID_TRACE,("Called\n")); + AFD_DbgPrint(MID_TRACE,("Called (%x)\n", Handle)); /* Get the Socket Structure associate to this Socket*/ Socket = GetSocketStructure(Handle); diff --git a/reactos/lib/msi/Makefile.in b/reactos/lib/msi/Makefile.in index 95f3ecd5b4f..df2489801a5 100644 --- a/reactos/lib/msi/Makefile.in +++ b/reactos/lib/msi/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = msi.dll -IMPORTS = shell32 cabinet oleaut32 ole32 version user32 advapi32 kernel32 +IMPORTS = shell32 cabinet oleaut32 ole32 version user32 gdi32 advapi32 kernel32 EXTRALIBS = -luuid $(LIBUNICODE) C_SRCS = \ @@ -31,6 +31,8 @@ RC_SRCS = version.rc EXTRA_SRCS = sql.y cond.y EXTRA_OBJS = sql.tab.o cond.tab.o +SUBDIRS = tests + @MAKE_DLL_RULES@ sql.tab.c sql.tab.h: sql.y diff --git a/reactos/lib/msi/action.c b/reactos/lib/msi/action.c index e32e1f9b6dd..ec066ac054b 100644 --- a/reactos/lib/msi/action.c +++ b/reactos/lib/msi/action.c @@ -51,6 +51,8 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/stand #include "ver.h" #define CUSTOM_ACTION_TYPE_MASK 0x3F +#define REG_PROGRESS_VALUE 13200 +#define COMPONENT_PROGRESS_VALUE 24000 WINE_DEFAULT_DEBUG_CHANNEL(msi); @@ -65,8 +67,10 @@ typedef struct tagMSIFEATURE WCHAR Directory[96]; INT Attributes; - INSTALLSTATE State; - BOOL Enabled; + INSTALLSTATE Installed; + INSTALLSTATE ActionRequest; + INSTALLSTATE Action; + INT ComponentCount; INT Components[1024]; /* yes hardcoded limit.... I am bad */ INT Cost; @@ -81,21 +85,23 @@ typedef struct tagMSICOMPONENT WCHAR Condition[0x100]; WCHAR KeyPath[96]; - INSTALLSTATE State; - BOOL FeatureState; + INSTALLSTATE Installed; + INSTALLSTATE ActionRequest; + INSTALLSTATE Action; + BOOL Enabled; INT Cost; } MSICOMPONENT; typedef struct tagMSIFOLDER { - WCHAR Directory[96]; - WCHAR TargetDefault[96]; - WCHAR SourceDefault[96]; + LPWSTR Directory; + LPWSTR TargetDefault; + LPWSTR SourceDefault; - WCHAR ResolvedTarget[MAX_PATH]; - WCHAR ResolvedSource[MAX_PATH]; - WCHAR Property[MAX_PATH]; /* initially set property */ + LPWSTR ResolvedTarget; + LPWSTR ResolvedSource; + LPWSTR Property; /* initially set property */ INT ParentIndex; INT State; /* 0 = uninitialized */ @@ -108,12 +114,12 @@ typedef struct tagMSIFOLDER typedef struct tagMSIFILE { - WCHAR File[72]; + LPWSTR File; INT ComponentIndex; - WCHAR FileName[MAX_PATH]; + LPWSTR FileName; INT FileSize; - WCHAR Version[72]; - WCHAR Language[20]; + LPWSTR Version; + LPWSTR Language; INT Attributes; INT Sequence; @@ -123,8 +129,8 @@ typedef struct tagMSIFILE /* 2 = present but replace */ /* 3 = present do not replace */ /* 4 = Installed */ - WCHAR SourcePath[MAX_PATH]; - WCHAR TargetPath[MAX_PATH]; + LPWSTR SourcePath; + LPWSTR TargetPath; BOOL Temporary; }MSIFILE; @@ -134,6 +140,7 @@ typedef struct tagMSIFILE static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran); static UINT ACTION_ProcessUISequence(MSIPACKAGE *package); +static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq); UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action); static UINT ACTION_LaunchConditions(MSIPACKAGE *package); @@ -158,15 +165,15 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); -static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, +static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); -static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, +static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); -static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, +static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type); static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data); -static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, +static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, BOOL set_prop, MSIFOLDER **folder); static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path); @@ -223,12 +230,9 @@ const static WCHAR szPublishProduct[] = ********************************************************/ inline static void reduce_to_longfilename(WCHAR* filename) { - if (strchrW(filename,'|')) - { - WCHAR newname[MAX_PATH]; - strcpyW(newname,strchrW(filename,'|')+1); - strcpyW(filename,newname); - } + LPWSTR p = strchrW(filename,'|'); + if (p) + memmove(filename, p+1, (strlenW(p+1)+1)*sizeof(WCHAR)); } inline static char *strdupWtoA( const WCHAR *str ) @@ -256,6 +260,15 @@ inline static WCHAR *strdupAtoW( const char *str ) return ret; } +static LPWSTR dupstrW(LPCWSTR src) +{ + LPWSTR dest; + if (!src) return NULL; + dest = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR)); + strcpyW(dest, src); + return dest; +} + inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index) { UINT rc; @@ -263,16 +276,58 @@ inline static WCHAR *load_dynamic_stringW(MSIRECORD *row, INT index) LPWSTR ret; sz = 0; - rc = MSI_RecordGetStringW(row,index,NULL,&sz); - if (sz <= 0) + if (MSI_RecordIsNull(row,index)) return NULL; + rc = MSI_RecordGetStringW(row,index,NULL,&sz); + + /* having an empty string is different than NULL */ + if (sz == 0) + { + ret = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)); + ret[0] = 0; + return ret; + } + sz ++; ret = HeapAlloc(GetProcessHeap(),0,sz * sizeof (WCHAR)); rc = MSI_RecordGetStringW(row,index,ret,&sz); + if (rc!=ERROR_SUCCESS) + { + ERR("Unable to load dynamic string\n"); + HeapFree(GetProcessHeap(), 0, ret); + ret = NULL; + } return ret; } +inline static LPWSTR load_dynamic_property(MSIPACKAGE *package, LPCWSTR prop, + UINT* rc) +{ + DWORD sz = 0; + LPWSTR str; + UINT r; + + r = MSI_GetPropertyW(package, prop, NULL, &sz); + if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA) + { + if (rc) + *rc = r; + return NULL; + } + sz++; + str = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR)); + r = MSI_GetPropertyW(package, prop, str, &sz); + if (r != ERROR_SUCCESS) + { + HeapFree(GetProcessHeap(),0,str); + str = NULL; + } + if (rc) + *rc = r; + return str; +} + inline static int get_loaded_component(MSIPACKAGE* package, LPCWSTR Component ) { int rc = -1; @@ -321,6 +376,7 @@ inline static int get_loaded_file(MSIPACKAGE* package, LPCWSTR file) return rc; } + static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path) { DWORD i; @@ -343,8 +399,8 @@ static int track_tempfile(MSIPACKAGE *package, LPCWSTR name, LPCWSTR path) memset(&package->files[index],0,sizeof(MSIFILE)); - strcpyW(package->files[index].File,name); - strcpyW(package->files[index].TargetPath,path); + package->files[index].File = dupstrW(name); + package->files[index].TargetPath = dupstrW(path); package->files[index].Temporary = TRUE; TRACE("Tracking tempfile (%s)\n",debugstr_w(package->files[index].File)); @@ -362,11 +418,103 @@ void ACTION_remove_tracked_tempfiles(MSIPACKAGE* package) for (i = 0; i < package->loaded_files; i++) { if (package->files[i].Temporary) + { + TRACE("Cleaning up %s\n",debugstr_w(package->files[i].TargetPath)); DeleteFileW(package->files[i].TargetPath); + } } } +/* Called when the package is being closed */ +extern void ACTION_free_package_structures( MSIPACKAGE* package) +{ + INT i; + + TRACE("Freeing package action data\n"); + + /* No dynamic buffers in features */ + if (package->features && package->loaded_features > 0) + HeapFree(GetProcessHeap(),0,package->features); + + for (i = 0; i < package->loaded_folders; i++) + { + HeapFree(GetProcessHeap(),0,package->folders[i].Directory); + HeapFree(GetProcessHeap(),0,package->folders[i].TargetDefault); + HeapFree(GetProcessHeap(),0,package->folders[i].SourceDefault); + HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget); + HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedSource); + HeapFree(GetProcessHeap(),0,package->folders[i].Property); + } + if (package->folders && package->loaded_folders > 0) + HeapFree(GetProcessHeap(),0,package->folders); + + /* no dynamic buffers in components */ + if (package->components && package->loaded_components > 0) + HeapFree(GetProcessHeap(),0,package->components); + + for (i = 0; i < package->loaded_files; i++) + { + HeapFree(GetProcessHeap(),0,package->files[i].File); + HeapFree(GetProcessHeap(),0,package->files[i].FileName); + HeapFree(GetProcessHeap(),0,package->files[i].Version); + HeapFree(GetProcessHeap(),0,package->files[i].Language); + HeapFree(GetProcessHeap(),0,package->files[i].SourcePath); + HeapFree(GetProcessHeap(),0,package->files[i].TargetPath); + } + + if (package->files && package->loaded_files > 0) + HeapFree(GetProcessHeap(),0,package->files); +} + +static UINT ACTION_OpenQuery( MSIDATABASE *db, MSIQUERY **view, LPCWSTR fmt, ... ) +{ + LPWSTR szQuery; + LPCWSTR p; + UINT sz, rc; + va_list va; + + /* figure out how much space we need to allocate */ + va_start(va, fmt); + sz = strlenW(fmt) + 1; + p = fmt; + while (*p) + { + p = strchrW(p, '%'); + if (!p) + break; + p++; + switch (*p) + { + case 's': /* a string */ + sz += strlenW(va_arg(va,LPCWSTR)); + break; + case 'd': + case 'i': /* an integer -2147483648 seems to be longest */ + sz += 3*sizeof(int); + (void)va_arg(va,int); + break; + case '%': /* a single % - leave it alone */ + break; + default: + FIXME("Unhandled character type %c\n",*p); + } + p++; + } + va_end(va); + + /* construct the string */ + szQuery = HeapAlloc(GetProcessHeap(), 0, sz*sizeof(WCHAR)); + va_start(va, fmt); + vsnprintfW(szQuery, sz, fmt, va); + va_end(va); + + /* perform the query */ + rc = MSI_DatabaseOpenViewW(db, szQuery, view); + HeapFree(GetProcessHeap(), 0, szQuery); + return rc; +} + static void ui_progress(MSIPACKAGE *package, int a, int b, int c, int d ) { MSIRECORD * row; @@ -390,17 +538,14 @@ static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * recor UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - static WCHAR *ActionFormat=NULL; - static WCHAR LastAction[0x100] = {0}; - WCHAR Query[1024]; LPWSTR ptr; - if (strcmpW(LastAction,action)!=0) + if (!package->LastAction || strcmpW(package->LastAction,action)) { - sprintfW(Query,Query_t,action); - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + rc = ACTION_OpenQuery(package->db, &view, Query_t, action); if (rc != ERROR_SUCCESS) return; + rc = MSI_ViewExecute(view, 0); if (rc != ERROR_SUCCESS) { @@ -422,18 +567,22 @@ static void ui_actiondata(MSIPACKAGE *package, LPCWSTR action, MSIRECORD * recor return; } - if (ActionFormat) - HeapFree(GetProcessHeap(),0,ActionFormat); + /* update the cached actionformat */ + if (package->ActionFormat) + HeapFree(GetProcessHeap(),0,package->ActionFormat); + package->ActionFormat = load_dynamic_stringW(row,3); + + if (package->LastAction) + HeapFree(GetProcessHeap(),0,package->LastAction); + package->LastAction = dupstrW(action); - ActionFormat = load_dynamic_stringW(row,3); - strcpyW(LastAction,action); msiobj_release(&row->hdr); MSI_ViewClose(view); msiobj_release(&view->hdr); } message[0]=0; - ptr = ActionFormat; + ptr = package->ActionFormat; while (*ptr) { LPWSTR ptr2; @@ -489,12 +638,10 @@ static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action) MSIQUERY * view; MSIRECORD * row = 0; WCHAR *ActionText=NULL; - WCHAR Query[1024]; GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100); - sprintfW(Query,Query_t,action); - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + rc = ACTION_OpenQuery(package->db, &view, Query_t, action); if (rc != ERROR_SUCCESS) return; rc = MSI_ViewExecute(view, 0); @@ -555,6 +702,58 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, msiobj_release(&row->hdr); } +/* + * build_directory_name() + * + * This function is to save messing round with directory names + * It handles adding backslashes between path segments, + * and can add \ at the end of the directory name if told to. + * + * It takes a variable number of arguments. + * It always allocates a new string for the result, so make sure + * to free the return value when finished with it. + * + * The first arg is the number of path segments that follow. + * The arguments following count are a list of path segments. + * A path segment may be NULL. + * + * Path segments will be added with a \ separating them. + * A \ will not be added after the last segment, however if the + * last segment is NULL, then the last character will be a \ + * + */ +static LPWSTR build_directory_name(DWORD count, ...) +{ + DWORD sz = 1, i; + LPWSTR dir; + va_list va; + + va_start(va,count); + for(i=0; i 0) { - TRACE("Found commandline property (%s) = (%s)\n", debugstr_w(prop), debugstr_w(val)); + TRACE("Found commandline property (%s) = (%s)\n", + debugstr_w(prop), debugstr_w(val)); MSI_SetPropertyW(package,prop,val); } + HeapFree(GetProcessHeap(),0,val); + HeapFree(GetProcessHeap(),0,prop); } ptr++; } @@ -653,9 +859,92 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, else rc = ACTION_ProcessExecSequence(package,FALSE); + /* process the ending type action */ + if (rc == ERROR_SUCCESS) + rc = ACTION_PerformActionSequence(package,-1); + else if (rc == ERROR_FUNCTION_FAILED) + rc = ACTION_PerformActionSequence(package,-3); + return rc; } +static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq) +{ + MSIQUERY * view; + UINT rc; + WCHAR buffer[0x100]; + DWORD sz = 0x100; + MSIRECORD * row = 0; + static const WCHAR ExecSeqQuery[] = { + 's','e','l','e','c','t',' ','*',' ', + 'f','r','o','m',' ', + 'I','n','s','t','a','l','l','E','x','e','c','u','t','e', + 'S','e','q','u','e','n','c','e',' ', + 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', + '=',' ','%','i',0}; + + rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq); + + if (rc == ERROR_SUCCESS) + { + rc = MSI_ViewExecute(view, 0); + + if (rc != ERROR_SUCCESS) + { + MSI_ViewClose(view); + msiobj_release(&view->hdr); + goto end; + } + + TRACE("Running the actions\n"); + + rc = MSI_ViewFetch(view,&row); + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + goto end; + } + + /* check conditions */ + if (!MSI_RecordIsNull(row,2)) + { + LPWSTR cond = NULL; + cond = load_dynamic_stringW(row,2); + + if (cond) + { + /* this is a hack to skip errors in the condition code */ + if (MSI_EvaluateConditionW(package, cond) == MSICONDITION_FALSE) + { + HeapFree(GetProcessHeap(),0,cond); + msiobj_release(&row->hdr); + goto end; + } + else + HeapFree(GetProcessHeap(),0,cond); + } + } + + sz=0x100; + rc = MSI_RecordGetStringW(row,1,buffer,&sz); + if (rc != ERROR_SUCCESS) + { + ERR("Error is %x\n",rc); + msiobj_release(&row->hdr); + goto end; + } + + rc = ACTION_PerformAction(package,buffer); + msiobj_release(&row->hdr); +end: + MSI_ViewClose(view); + msiobj_release(&view->hdr); + } + else + rc = ERROR_SUCCESS; + + return rc; +} static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) { @@ -669,7 +958,6 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) 'w','h','e','r','e',' ','S','e','q','u','e','n','c','e',' ', '>',' ','%','i',' ','o','r','d','e','r',' ', 'b','y',' ','S','e','q','u','e','n','c','e',0 }; - WCHAR Query[1024]; MSIRECORD * row = 0; static const WCHAR IVQuery[] = { 's','e','l','e','c','t',' ','S','e','q','u','e','n','c','e',' ', @@ -678,11 +966,11 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) 'w','h','e','r','e',' ','A','c','t','i','o','n',' ','=',' ', '`','I','n','s','t','a','l','l','V','a','l','i','d','a','t','e','`', 0}; + INT seq = 0; + /* get the sequence number */ if (UIran) { - INT seq = 0; - rc = MSI_DatabaseOpenViewW(package->db, IVQuery, &view); if (rc != ERROR_SUCCESS) return rc; @@ -704,12 +992,9 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) msiobj_release(&row->hdr); MSI_ViewClose(view); msiobj_release(&view->hdr); - sprintfW(Query,ExecSeqQuery,seq); } - else - sprintfW(Query,ExecSeqQuery,0); - - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + + rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, seq); if (rc == ERROR_SUCCESS) { rc = MSI_ViewExecute(view, 0); @@ -721,7 +1006,7 @@ static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran) goto end; } - TRACE("Running the actions \n"); + TRACE("Running the actions\n"); while (1) { @@ -900,7 +1185,6 @@ UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action) TRACE("Performing action (%s)\n",debugstr_w(action)); ui_actioninfo(package, action, TRUE, 0); ui_actionstart(package, action); - ui_progress(package,2,1,0,0); /* pre install, setup and configuration block */ if (strcmpW(action,szLaunchConditions)==0) @@ -961,21 +1245,16 @@ static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action) UINT rc = ERROR_SUCCESS; MSIQUERY * view; MSIRECORD * row = 0; - WCHAR ExecSeqQuery[1024] = + static const WCHAR ExecSeqQuery[] = {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','C','u','s','t','o' -,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i' -,'o','n','`',' ','=',' ','`',0}; - static const WCHAR end[]={'`',0}; + ,'m','A','c','t','i','o','n',' ','w','h','e','r','e',' ','`','A','c','t','i' + ,'o','n','`',' ','=',' ','`','%','s','`',0}; UINT type; LPWSTR source; LPWSTR target; WCHAR *deformated=NULL; - strcatW(ExecSeqQuery,action); - strcatW(ExecSeqQuery,end); - - rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view); - + rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, action); if (rc != ERROR_SUCCESS) return rc; @@ -1022,6 +1301,10 @@ static UINT ACTION_CustomAction(MSIPACKAGE *package,const WCHAR *action) rc = HANDLE_CustomType34(package,source,target,type); break; case 35: /* Directory set with formatted text. */ + deformat_string(package,target,&deformated); + MSI_SetTargetPathW(package, source, deformated); + HeapFree(GetProcessHeap(),0,deformated); + break; case 51: /* Property set with formatted text. */ deformat_string(package,target,&deformated); rc = MSI_SetPropertyW(package,source,deformated); @@ -1063,10 +1346,9 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source, UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - WCHAR Query[1024] = + static const WCHAR fmt[] = {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','B','i' -,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`',0}; - static const WCHAR end[]={'`',0}; +,'n','a','r','y',' ','w','h','e','r','e',' ','N','a','m','e','=','`','%','s','`',0}; HANDLE the_file; CHAR buffer[1024]; @@ -1079,10 +1361,7 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source, if (the_file == INVALID_HANDLE_VALUE) return ERROR_FUNCTION_FAILED; - strcatW(Query,source); - strcatW(Query,end); - - rc = MSI_DatabaseOpenViewW( package->db, Query, &view); + rc = ACTION_OpenQuery(package->db, &view, fmt, source); if (rc != ERROR_SUCCESS) return rc; @@ -1127,66 +1406,82 @@ static UINT store_binary_to_temp(MSIPACKAGE *package, const LPWSTR source, return ERROR_SUCCESS; } - typedef UINT __stdcall CustomEntry(MSIHANDLE); typedef struct { MSIPACKAGE *package; - WCHAR target[MAX_PATH]; - WCHAR source[MAX_PATH]; + WCHAR *target; + WCHAR *source; } thread_struct; -#if 0 -static DWORD WINAPI DllThread(LPVOID info) +static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff) { - HANDLE DLL; + HANDLE hModule; LPSTR proc; - thread_struct *stuff; CustomEntry *fn; - - stuff = (thread_struct*)info; - TRACE("Asynchronous start (%s, %s) \n", debugstr_w(stuff->source), + TRACE("calling function (%s, %s) \n", debugstr_w(stuff->source), debugstr_w(stuff->target)); - DLL = LoadLibraryW(stuff->source); - if (DLL) + hModule = LoadLibraryW(stuff->source); + if (hModule) { proc = strdupWtoA( stuff->target ); - fn = (CustomEntry*)GetProcAddress(DLL,proc); + fn = (CustomEntry*)GetProcAddress(hModule,proc); if (fn) { MSIHANDLE hPackage; MSIPACKAGE *package = stuff->package; - TRACE("Calling function\n"); + TRACE("Calling function %s\n", proc); hPackage = msiobj_findhandle( &package->hdr ); - if( !hPackage ) + if (hPackage ) + { + fn(hPackage); + msiobj_release( &package->hdr ); + } + else ERR("Handle for object %p not found\n", package ); - fn(hPackage); - msiobj_release( &package->hdr ); } else ERR("Cannot load functon\n"); HeapFree(GetProcessHeap(),0,proc); - FreeLibrary(DLL); + FreeLibrary(hModule); } else ERR("Unable to load library\n"); msiobj_release( &stuff->package->hdr ); - HeapFree( GetProcessHeap(), 0, info ); + HeapFree(GetProcessHeap(),0,stuff->source); + HeapFree(GetProcessHeap(),0,stuff->target); + HeapFree(GetProcessHeap(), 0, stuff); return 0; } -#endif + +static DWORD WINAPI DllThread(LPVOID info) +{ + thread_struct *stuff; + DWORD rc = 0; + + TRACE("MSI Thread (0x%lx) started for custom action\n", + GetCurrentThreadId()); + + stuff = (thread_struct*)info; + rc = ACTION_CallDllFunction(stuff); + + TRACE("MSI Thread (0x%lx) finished\n",GetCurrentThreadId()); + /* clse all handles for this thread */ + MsiCloseAllHandles(); + return rc; +} static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type) { WCHAR tmp_file[MAX_PATH]; - CustomEntry *fn; - HANDLE DLL; - LPSTR proc; + thread_struct *info; + DWORD ThreadId; + HANDLE ThreadHandle; store_binary_to_temp(package, source, tmp_file); @@ -1199,76 +1494,57 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, const LPWSTR source, strcatW(tmp_file,dot); } - if (type & 0xc0) - { - /* DWORD ThreadId; */ - thread_struct *info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); + info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) ); + msiobj_addref( &package->hdr ); + info->package = package; + info->target = dupstrW(target); + info->source = dupstrW(tmp_file); - /* msiobj_addref( &package->hdr ); */ - info->package = package; - strcpyW(info->target,target); - strcpyW(info->source,tmp_file); - TRACE("Start Asynchronous execution\n"); - FIXME("DATABASE NOT THREADSAFE... not starting\n"); - /* CreateThread(NULL,0,DllThread,(LPVOID)&info,0,&ThreadId); */ - /* FIXME: release the package if the CreateThread fails */ - HeapFree( GetProcessHeap(), 0, info ); - return ERROR_SUCCESS; - } + ThreadHandle = CreateThread(NULL,0,DllThread,(LPVOID)info,0,&ThreadId); + + if (!(type & 0xc0)) + WaitForSingleObject(ThreadHandle,INFINITE); + + CloseHandle(ThreadHandle); - DLL = LoadLibraryW(tmp_file); - if (DLL) - { - proc = strdupWtoA( target ); - fn = (CustomEntry*)GetProcAddress(DLL,proc); - if (fn) - { - MSIHANDLE hPackage; - - TRACE("Calling function\n"); - hPackage = msiobj_findhandle( &package->hdr ); - if( !hPackage ) - ERR("Handle for object %p not found\n", package ); - fn(hPackage); - msiobj_release( &package->hdr ); - } - else - ERR("Cannot load functon\n"); - - HeapFree(GetProcessHeap(),0,proc); - FreeLibrary(DLL); - } - else - ERR("Unable to load library\n"); - return ERROR_SUCCESS; } static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type) { - WCHAR tmp_file[MAX_PATH*2]; + WCHAR tmp_file[MAX_PATH]; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL rc; + INT len; WCHAR *deformated; + WCHAR *cmd; static const WCHAR spc[] = {' ',0}; memset(&si,0,sizeof(STARTUPINFOW)); store_binary_to_temp(package, source, tmp_file); - strcatW(tmp_file,spc); deformat_string(package,target,&deformated); - strcatW(tmp_file,deformated); + + len = strlenW(tmp_file) + strlenW(deformated) + 2; + + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + + strcpyW(cmd,tmp_file); + strcatW(cmd,spc); + strcatW(cmd,deformated); HeapFree(GetProcessHeap(),0,deformated); - TRACE("executing exe %s \n",debugstr_w(tmp_file)); + TRACE("executing exe %s \n",debugstr_w(cmd)); - rc = CreateProcessW(NULL, tmp_file, NULL, NULL, FALSE, 0, NULL, + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, c_collen, &si, &info); + HeapFree(GetProcessHeap(),0,cmd); + if ( !rc ) { ERR("Unable to execute command\n"); @@ -1283,33 +1559,43 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, const LPWSTR source, return ERROR_SUCCESS; } -static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, +static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type) { - WCHAR filename[MAX_PATH*2]; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL rc; WCHAR *deformated; + WCHAR *cmd; + INT len; static const WCHAR spc[] = {' ',0}; int index; memset(&si,0,sizeof(STARTUPINFOW)); index = get_loaded_file(package,source); - strcpyW(filename,package->files[index].TargetPath); - strcatW(filename,spc); + len = strlenW(package->files[index].TargetPath); + deformat_string(package,target,&deformated); - strcatW(filename,deformated); + len += strlenW(deformated); + len += 2; + + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,len * sizeof(WCHAR)); + + strcpyW(cmd, package->files[index].TargetPath); + strcatW(cmd, spc); + strcatW(cmd, deformated); HeapFree(GetProcessHeap(),0,deformated); - TRACE("executing exe %s \n",debugstr_w(filename)); + TRACE("executing exe %s \n",debugstr_w(cmd)); - rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, c_collen, &si, &info); + HeapFree(GetProcessHeap(),0,cmd); + if ( !rc ) { ERR("Unable to execute command\n"); @@ -1324,74 +1610,82 @@ static UINT HANDLE_CustomType18(MSIPACKAGE *package, const LPWSTR source, return ERROR_SUCCESS; } -static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, +static UINT HANDLE_CustomType50(MSIPACKAGE *package, const LPWSTR source, const LPWSTR target, const INT type) { - WCHAR filename[MAX_PATH*2]; + STARTUPINFOW si; + PROCESS_INFORMATION info; + WCHAR *prop; + BOOL rc; + WCHAR *deformated; + WCHAR *cmd; + INT len; + UINT prc; + static const WCHAR spc[] = {' ',0}; + + memset(&si,0,sizeof(STARTUPINFOW)); + memset(&info,0,sizeof(PROCESS_INFORMATION)); + + prop = load_dynamic_property(package,source,&prc); + if (!prop) + return prc; + + deformat_string(package,target,&deformated); + len = strlenW(prop) + strlenW(deformated) + 2; + cmd = (WCHAR*)HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*len); + + strcpyW(cmd,prop); + strcatW(cmd,spc); + strcatW(cmd,deformated); + + HeapFree(GetProcessHeap(),0,deformated); + + TRACE("executing exe %s \n",debugstr_w(cmd)); + + rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, + c_collen, &si, &info); + + HeapFree(GetProcessHeap(),0,cmd); + + if ( !rc ) + { + ERR("Unable to execute command\n"); + return ERROR_SUCCESS; + } + + if (!(type & 0xc0)) + WaitForSingleObject(info.hProcess,INFINITE); + + CloseHandle( info.hProcess ); + CloseHandle( info.hThread ); + return ERROR_SUCCESS; +} + +static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, + const LPWSTR target, const INT type) +{ + LPWSTR filename, deformated; STARTUPINFOW si; PROCESS_INFORMATION info; BOOL rc; - WCHAR *deformated; - static const WCHAR spc[] = {' ',0}; - DWORD sz; memset(&si,0,sizeof(STARTUPINFOW)); - sz = MAX_PATH*2; - if (MSI_GetPropertyW(package,source,filename,&sz) != ERROR_SUCCESS) + filename = resolve_folder(package, source, FALSE, FALSE, NULL); + + if (!filename) return ERROR_FUNCTION_FAILED; - strcatW(filename,spc); - deformat_string(package,target,&deformated); - strcatW(filename,deformated); - - HeapFree(GetProcessHeap(),0,deformated); - - TRACE("executing exe %s \n",debugstr_w(filename)); - - rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, - c_collen, &si, &info); - - if ( !rc ) - { - ERR("Unable to execute command\n"); - return ERROR_SUCCESS; - } - - if (!(type & 0xc0)) - WaitForSingleObject(info.hProcess,INFINITE); - - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - return ERROR_SUCCESS; -} - -static UINT HANDLE_CustomType34(MSIPACKAGE *package, const LPWSTR source, - const LPWSTR target, const INT type) -{ - WCHAR filename[MAX_PATH*2]; - STARTUPINFOW si; - PROCESS_INFORMATION info; - BOOL rc; - WCHAR *deformated; - - memset(&si,0,sizeof(STARTUPINFOW)); - - rc = resolve_folder(package, source, filename, FALSE, FALSE, NULL); - if (rc != ERROR_SUCCESS) - return rc; - SetCurrentDirectoryW(filename); + HeapFree(GetProcessHeap(),0,filename); deformat_string(package,target,&deformated); - strcpyW(filename,deformated); - HeapFree(GetProcessHeap(),0,deformated); + TRACE("executing exe %s \n",debugstr_w(deformated)); - TRACE("executing exe %s \n",debugstr_w(filename)); - - rc = CreateProcessW(NULL, filename, NULL, NULL, FALSE, 0, NULL, + rc = CreateProcessW(NULL, deformated, NULL, NULL, FALSE, 0, NULL, c_collen, &si, &info); + HeapFree(GetProcessHeap(),0,deformated); if ( !rc ) { @@ -1421,7 +1715,8 @@ static BOOL create_full_pathW(const WCHAR *path) WCHAR *new_path; new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * -sizeof(WCHAR)); + sizeof(WCHAR)); + strcpyW(new_path, path); while((len = strlenW(new_path)) && new_path[len - 1] == '\\') @@ -1429,31 +1724,31 @@ sizeof(WCHAR)); while(!CreateDirectoryW(new_path, NULL)) { - WCHAR *slash; - DWORD last_error = GetLastError(); - if(last_error == ERROR_ALREADY_EXISTS) - break; + WCHAR *slash; + DWORD last_error = GetLastError(); + if(last_error == ERROR_ALREADY_EXISTS) + break; - if(last_error != ERROR_PATH_NOT_FOUND) - { - ret = FALSE; - break; - } + if(last_error != ERROR_PATH_NOT_FOUND) + { + ret = FALSE; + break; + } - if(!(slash = strrchrW(new_path, '\\'))) - { - ret = FALSE; - break; - } + if(!(slash = strrchrW(new_path, '\\'))) + { + ret = FALSE; + break; + } - len = slash - new_path; - new_path[len] = 0; - if(!create_full_pathW(new_path)) - { - ret = FALSE; - break; - } - new_path[len] = '\\'; + len = slash - new_path; + new_path[len] = 0; + if(!create_full_pathW(new_path)) + { + ret = FALSE; + break; + } + new_path[len] = '\\'; } HeapFree(GetProcessHeap(), 0, new_path); @@ -1488,7 +1783,7 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package) while (1) { WCHAR dir[0x100]; - WCHAR full_path[MAX_PATH]; + LPWSTR full_path; DWORD sz; MSIRECORD *row = NULL, *uirow; @@ -1510,9 +1805,8 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package) } sz = MAX_PATH; - rc = resolve_folder(package,dir,full_path,FALSE,FALSE,&folder); - - if (rc != ERROR_SUCCESS) + full_path = resolve_folder(package,dir,FALSE,FALSE,&folder); + if (!full_path) { ERR("Unable to resolve folder id %s\n",debugstr_w(dir)); msiobj_release(&row->hdr); @@ -1533,6 +1827,7 @@ static UINT ACTION_CreateFolders(MSIPACKAGE *package) folder->State = 3; msiobj_release(&row->hdr); + HeapFree(GetProcessHeap(),0,full_path); } MSI_ViewClose(view); msiobj_release(&view->hdr); @@ -1579,9 +1874,11 @@ static int load_component(MSIPACKAGE* package, MSIRECORD * row) sz = 96; MSI_RecordGetStringW(row,6,package->components[index].KeyPath,&sz); - package->components[index].State = INSTALLSTATE_UNKNOWN; + package->components[index].Installed = INSTALLSTATE_ABSENT; + package->components[index].Action = INSTALLSTATE_UNKNOWN; + package->components[index].ActionRequest = INSTALLSTATE_UNKNOWN; + package->components[index].Enabled = TRUE; - package->components[index].FeatureState= FALSE; return index; } @@ -1591,13 +1888,12 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row) int index = package->loaded_features; DWORD sz; static const WCHAR Query1[] = {'S','E','L','E','C','T',' ','C','o','m','p', -'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e', -'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e', -'a','t','u','r','e','_','=','\'','%','s','\'',0}; + 'o','n','e','n','t','_',' ','F','R','O','M',' ','F','e','a','t','u','r','e', + 'C','o','m','p','o','n','e','n','t','s',' ','W','H','E','R','E',' ','F','e', + 'a','t','u','r','e','_','=','\'','%','s','\'',0}; static const WCHAR Query2[] = {'S','E','L','E','C','T',' ','*',' ','F','R', -'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C', -'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0}; - WCHAR Query[1024]; + 'O','M',' ','C','o','m','p','o','n','e','n','t',' ','W','H','E','R','E',' ','C', + 'o','m','p','o','n','e','n','t','=','\'','%','s','\'',0}; MSIQUERY * view; MSIQUERY * view2; MSIRECORD * row2; @@ -1642,12 +1938,14 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row) MSI_RecordGetStringW(row,7,package->features[index].Directory,&sz); package->features[index].Attributes= MSI_RecordGetInteger(row,8); - package->features[index].State = INSTALLSTATE_UNKNOWN; + + package->features[index].Installed = INSTALLSTATE_ABSENT; + package->features[index].Action = INSTALLSTATE_UNKNOWN; + package->features[index].ActionRequest = INSTALLSTATE_UNKNOWN; /* load feature components */ - sprintfW(Query,Query1,package->features[index].Feature); - rc = MSI_DatabaseOpenViewW(package->db,Query,&view); + rc = ACTION_OpenQuery(package->db, &view, Query1, package->features[index].Feature); if (rc != ERROR_SUCCESS) return; rc = MSI_ViewExecute(view,0); @@ -1680,11 +1978,10 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row) c_indx); package->features[index].Components[cnt] = c_indx; package->features[index].ComponentCount ++; + continue; } - sprintfW(Query,Query2,buffer); - - rc = MSI_DatabaseOpenViewW(package->db,Query,&view2); + rc = ACTION_OpenQuery(package->db, &view2, Query2, buffer); if (rc != ERROR_SUCCESS) { msiobj_release( &row2->hdr ); @@ -1710,6 +2007,7 @@ static void load_feature(MSIPACKAGE* package, MSIRECORD * row) package->features[index].Components[cnt] = c_indx; package->features[index].ComponentCount ++; + TRACE("Loaded new component to index %i\n",c_indx); } MSI_ViewClose(view2); msiobj_release( &view2->hdr ); @@ -1736,7 +2034,6 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package) { MSIQUERY * view; MSIRECORD * row; - DWORD sz; UINT rc; static const WCHAR Query_all[] = { 'S','E','L','E','C','T',' ','*',' ', @@ -1748,7 +2045,6 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package) MSI_SetPropertyW(package, szCosting, szZero); MSI_SetPropertyW(package, cszRootDrive , c_collen); - sz = 0x100; rc = MSI_DatabaseOpenViewW(package->db,Query_all,&view); if (rc != ERROR_SUCCESS) return rc; @@ -1780,8 +2076,7 @@ static UINT load_file(MSIPACKAGE* package, MSIRECORD * row) { DWORD index = package->loaded_files; DWORD i; - WCHAR buffer[0x100]; - DWORD sz; + LPWSTR buffer; /* fill in the data */ @@ -1793,12 +2088,9 @@ static UINT load_file(MSIPACKAGE* package, MSIRECORD * row) package->files , package->loaded_files * sizeof(MSIFILE)); memset(&package->files[index],0,sizeof(MSIFILE)); - - sz = 72; - MSI_RecordGetStringW(row,1,package->files[index].File,&sz); - - sz = 0x100; - MSI_RecordGetStringW(row,2,buffer,&sz); + + package->files[index].File = load_dynamic_stringW(row, 1); + buffer = load_dynamic_stringW(row, 2); package->files[index].ComponentIndex = -1; for (i = 0; i < package->loaded_components; i++) @@ -1809,25 +2101,16 @@ static UINT load_file(MSIPACKAGE* package, MSIRECORD * row) } if (package->files[index].ComponentIndex == -1) ERR("Unfound Component %s\n",debugstr_w(buffer)); + HeapFree(GetProcessHeap(), 0, buffer); - sz = MAX_PATH; - MSI_RecordGetStringW(row,3,package->files[index].FileName,&sz); + package->files[index].FileName = load_dynamic_stringW(row,3); reduce_to_longfilename(package->files[index].FileName); package->files[index].FileSize = MSI_RecordGetInteger(row,4); - - sz = 72; - if (!MSI_RecordIsNull(row,5)) - MSI_RecordGetStringW(row,5,package->files[index].Version,&sz); - - sz = 20; - if (!MSI_RecordIsNull(row,6)) - MSI_RecordGetStringW(row,6,package->files[index].Language,&sz); - - if (!MSI_RecordIsNull(row,7)) - package->files[index].Attributes= MSI_RecordGetInteger(row,7); - + package->files[index].Version = load_dynamic_stringW(row, 5); + package->files[index].Language = load_dynamic_stringW(row, 6); + package->files[index].Attributes= MSI_RecordGetInteger(row,7); package->files[index].Sequence= MSI_RecordGetInteger(row,8); package->files[index].Temporary = FALSE; @@ -1883,18 +2166,13 @@ static UINT ACTION_FileCost(MSIPACKAGE *package) static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) { - WCHAR Query[1024] = -{'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c', -'t','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t', -'o','r','y','`',' ','=',' ','`',0}; - static const WCHAR end[]={'`',0}; + static const WCHAR Query[] = + {'s','e','l','e','c','t',' ','*',' ','f','r','o','m',' ','D','i','r','e','c', + 't','o','r','y',' ','w','h','e','r','e',' ','`','D','i','r','e','c','t', + 'o','r','y','`',' ','=',' ','`','%','s','`',0}; UINT rc; MSIQUERY * view; - WCHAR targetbuffer[0x100]; - WCHAR *srcdir = NULL; - WCHAR *targetdir = NULL; - WCHAR parent[0x100]; - DWORD sz=0x100; + LPWSTR targetdir, parent, srcdir; MSIRECORD * row = 0; INT index = -1; DWORD i; @@ -1912,10 +2190,8 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) TRACE("Working to load %s\n",debugstr_w(dir)); - index = package->loaded_folders; - - package->loaded_folders++; - if (package->loaded_folders== 1) + index = package->loaded_folders++; + if (package->loaded_folders==1) package->folders = HeapAlloc(GetProcessHeap(),0, sizeof(MSIFOLDER)); else @@ -1925,13 +2201,9 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) memset(&package->folders[index],0,sizeof(MSIFOLDER)); - strcpyW(package->folders[index].Directory,dir); - - strcatW(Query,dir); - strcatW(Query,end); - - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + package->folders[index].Directory = dupstrW(dir); + rc = ACTION_OpenQuery(package->db, &view, Query, dir); if (rc != ERROR_SUCCESS) return -1; @@ -1951,9 +2223,7 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) return -1; } - sz=0x100; - MSI_RecordGetStringW(row,3,targetbuffer,&sz); - targetdir=targetbuffer; + targetdir = load_dynamic_stringW(row,3); /* split src and target dir */ if (strchrW(targetdir,':')) @@ -1986,38 +2256,35 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) if (srcdir && srcdir[0] == '.' && srcdir[1] == 0) srcdir = NULL; - if (targetdir) - strcpyW(package->folders[index].TargetDefault,targetdir); - - if (srcdir) - strcpyW(package->folders[index].SourceDefault,srcdir); - else if (targetdir) - strcpyW(package->folders[index].SourceDefault,targetdir); - - if (MSI_RecordIsNull(row,2)) - parent[0]=0; - else + if (targetdir) { - sz=0x100; - MSI_RecordGetStringW(row,2,parent,&sz); + TRACE(" TargetDefault = %s\n",debugstr_w(targetdir)); + if (package->folders[index].TargetDefault) + HeapFree(GetProcessHeap(),0, package->folders[index].TargetDefault); + package->folders[index].TargetDefault = dupstrW(targetdir); } - if (parent[0]) + if (srcdir) + package->folders[index].SourceDefault = dupstrW(srcdir); + else if (targetdir) + package->folders[index].SourceDefault = dupstrW(targetdir); + HeapFree(GetProcessHeap(), 0, targetdir); + + parent = load_dynamic_stringW(row,2); + if (parent) { i = load_folder(package,parent); package->folders[index].ParentIndex = i; TRACE("Parent is index %i... %s %s\n", package->folders[index].ParentIndex, - debugstr_w(package->folders[package->folders[index].ParentIndex].Directory), + debugstr_w(package->folders[package->folders[index].ParentIndex].Directory), debugstr_w(parent)); } else package->folders[index].ParentIndex = -2; + HeapFree(GetProcessHeap(), 0, parent); - sz = MAX_PATH; - rc = MSI_GetPropertyW(package, dir, package->folders[index].Property, &sz); - if (rc != ERROR_SUCCESS) - package->folders[index].Property[0]=0; + package->folders[index].Property = load_dynamic_property(package, dir,NULL); msiobj_release(&row->hdr); MSI_ViewClose(view); @@ -2026,57 +2293,61 @@ static INT load_folder(MSIPACKAGE *package, const WCHAR* dir) return index; } -static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, + +static LPWSTR resolve_folder(MSIPACKAGE *package, LPCWSTR name, BOOL source, BOOL set_prop, MSIFOLDER **folder) { DWORD i; - UINT rc = ERROR_SUCCESS; - DWORD sz; + LPWSTR p, path = NULL; TRACE("Working to resolve %s\n",debugstr_w(name)); - if (!path) - return rc; - /* special resolving for Target and Source root dir */ if (strcmpW(name,cszTargetDir)==0 || strcmpW(name,cszSourceDir)==0) { if (!source) { - sz = MAX_PATH; - rc = MSI_GetPropertyW(package,cszTargetDir,path,&sz); - if (rc != ERROR_SUCCESS) + path = load_dynamic_property(package,cszTargetDir,NULL); + if (!path) { - sz = MAX_PATH; - rc = MSI_GetPropertyW(package,cszRootDrive,path,&sz); + path = load_dynamic_property(package,cszRootDrive,NULL); if (set_prop) MSI_SetPropertyW(package,cszTargetDir,path); } if (folder) - *folder = &(package->folders[0]); - return rc; + { + for (i = 0; i < package->loaded_folders; i++) + { + if (strcmpW(package->folders[i].Directory,name)==0) + break; + } + *folder = &(package->folders[i]); + } + return path; } else { - sz = MAX_PATH; - rc = MSI_GetPropertyW(package,cszSourceDir,path,&sz); - if (rc != ERROR_SUCCESS) + path = load_dynamic_property(package,cszSourceDir,NULL); + if (!path) { - sz = MAX_PATH; - rc = MSI_GetPropertyW(package,cszDatabase,path,&sz); - if (rc == ERROR_SUCCESS) + path = load_dynamic_property(package,cszDatabase,NULL); + if (path) { - LPWSTR ptr = strrchrW(path,'\\'); - if (ptr) - { - ptr++; - *ptr = 0; - } + p = strrchrW(path,'\\'); + if (p) + *(p+1) = 0; } } if (folder) - *folder = &(package->folders[0]); - return rc; + { + for (i = 0; i < package->loaded_folders; i++) + { + if (strcmpW(package->folders[i].Directory,name)==0) + break; + } + *folder = &(package->folders[i]); + } + return path; } } @@ -2087,67 +2358,186 @@ static UINT resolve_folder(MSIPACKAGE *package, LPCWSTR name, LPWSTR path, } if (i >= package->loaded_folders) - return ERROR_FUNCTION_FAILED; + return NULL; if (folder) *folder = &(package->folders[i]); - if (!source && package->folders[i].ResolvedTarget[0]) + if (!source && package->folders[i].ResolvedTarget) { - strcpyW(path,package->folders[i].ResolvedTarget); + path = dupstrW(package->folders[i].ResolvedTarget); TRACE(" already resolved to %s\n",debugstr_w(path)); - return ERROR_SUCCESS; + return path; } - else if (source && package->folders[i].ResolvedSource[0]) + else if (source && package->folders[i].ResolvedSource) { - strcpyW(path,package->folders[i].ResolvedSource); - return ERROR_SUCCESS; + path = dupstrW(package->folders[i].ResolvedSource); + return path; } - else if (!source && package->folders[i].Property[0]) + else if (!source && package->folders[i].Property) { - strcpyW(path,package->folders[i].Property); + path = dupstrW(package->folders[i].Property); TRACE(" internally set to %s\n",debugstr_w(path)); if (set_prop) MSI_SetPropertyW(package,name,path); - return ERROR_SUCCESS; + return path; } if (package->folders[i].ParentIndex >= 0) { - int len; - TRACE(" ! Parent is %s\n", debugstr_w(package->folders[ - package->folders[i].ParentIndex].Directory)); - resolve_folder(package, package->folders[ - package->folders[i].ParentIndex].Directory, path,source, - set_prop, NULL); + LPWSTR parent = package->folders[package->folders[i].ParentIndex].Directory; - len = strlenW(path); - if (len && path[len-1] != '\\') - strcatW(path, cszbs); + TRACE(" ! Parent is %s\n", debugstr_w(parent)); + p = resolve_folder(package, parent, source, set_prop, NULL); if (!source) { - if (package->folders[i].TargetDefault[0]) - { - strcatW(path,package->folders[i].TargetDefault); - strcatW(path,cszbs); - } - strcpyW(package->folders[i].ResolvedTarget,path); + TRACE(" TargetDefault = %s\n",debugstr_w(package->folders[i].TargetDefault)); + path = build_directory_name(3, p, package->folders[i].TargetDefault, NULL); + package->folders[i].ResolvedTarget = dupstrW(path); TRACE(" resolved into %s\n",debugstr_w(path)); if (set_prop) MSI_SetPropertyW(package,name,path); } else { - if (package->folders[i].SourceDefault[0]) + path = build_directory_name(3, p, package->folders[i].SourceDefault, NULL); + package->folders[i].ResolvedSource = dupstrW(path); + } + HeapFree(GetProcessHeap(),0,p); + } + return path; +} + +static UINT SetFeatureStates(MSIPACKAGE *package) +{ + LPWSTR level; + INT install_level; + DWORD i; + INT j; + LPWSTR override = NULL; + static const WCHAR all[]={'A','L','L',0}; + static const WCHAR szlevel[] = { + 'I','N','S','T','A','L','L','L','E','V','E','L',0}; + static const WCHAR szAddLocal[] = { + 'A','D','D','L','O','C','A','L',0}; + + /* I do not know if this is where it should happen.. but */ + + TRACE("Checking Install Level\n"); + + level = load_dynamic_property(package,szlevel,NULL); + if (level) + { + install_level = atoiW(level); + HeapFree(GetProcessHeap(), 0, level); + } + else + install_level = 1; + + /* ok hereis the rub + * ADDLOCAL and its friend OVERRIDE INSTALLLEVLE + * I have confirmed this if ADDLOCALis stated then the INSTALLLEVEL is + * itnored for all the features. seems strange, epsecially since it is not + * documented anywhere, but it is how it works. + */ + + override = load_dynamic_property(package,szAddLocal,NULL); + + if (override) + { + for(i = 0; i < package->loaded_features; i++) + { + if (strcmpiW(override,all)==0) { - strcatW(path,package->folders[i].SourceDefault); - strcatW(path,cszbs); + package->features[i].ActionRequest= INSTALLSTATE_LOCAL; + package->features[i].Action = INSTALLSTATE_LOCAL; + } + else + { + LPWSTR ptr = override; + LPWSTR ptr2 = strchrW(override,','); + + while (ptr) + { + if ((ptr2 && + strncmpW(ptr,package->features[i].Feature, ptr2-ptr)==0) + || (!ptr2 && + strcmpW(ptr,package->features[i].Feature)==0)) + { + package->features[i].ActionRequest= INSTALLSTATE_LOCAL; + package->features[i].Action = INSTALLSTATE_LOCAL; + break; + } + if (ptr2) + { + ptr=ptr2+1; + ptr2 = strchrW(ptr,','); + } + else + break; + } + } + } + HeapFree(GetProcessHeap(),0,override); + } + else + { + for(i = 0; i < package->loaded_features; i++) + { + BOOL feature_state= ((package->features[i].Level > 0) && + (package->features[i].Level <= install_level)); + + if (feature_state) + { + package->features[i].ActionRequest= INSTALLSTATE_LOCAL; + package->features[i].Action = INSTALLSTATE_LOCAL; } - strcpyW(package->folders[i].ResolvedSource,path); } } - return rc; + + /* + * now we want to enable or disable components base on feature + */ + + for(i = 0; i < package->loaded_features; i++) + { + MSIFEATURE* feature = &package->features[i]; + TRACE("Examining Feature %s (Installed %i, Action %i, Request %i)\n", + debugstr_w(feature->Feature), feature->Installed, feature->Action, + feature->ActionRequest); + + for( j = 0; j < feature->ComponentCount; j++) + { + MSICOMPONENT* component = &package->components[ + feature->Components[j]]; + + if (!component->Enabled) + { + component->Action = INSTALLSTATE_ABSENT; + component->ActionRequest = INSTALLSTATE_ABSENT; + } + else + { + if (feature->Action == INSTALLSTATE_LOCAL) + component->Action = INSTALLSTATE_LOCAL; + if (feature->ActionRequest == INSTALLSTATE_LOCAL) + component->ActionRequest = INSTALLSTATE_LOCAL; + } + } + } + + for(i = 0; i < package->loaded_components; i++) + { + MSICOMPONENT* component= &package->components[i]; + + TRACE("Result: Component %s (Installed %i, Action %i, Request %i)\n", + debugstr_w(component->Component), component->Installed, + component->Action, component->ActionRequest); + } + + + return ERROR_SUCCESS; } /* @@ -2166,10 +2556,13 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) 'C','o','n','d','i','t','i','o','n',0}; static const WCHAR szCosting[] = { 'C','o','s','t','i','n','g','C','o','m','p','l','e','t','e',0 }; + static const WCHAR szlevel[] = { + 'I','N','S','T','A','L','L','L','E','V','E','L',0}; static const WCHAR szOne[] = { '1', 0 }; UINT rc; MSIQUERY * view; DWORD i; + LPWSTR level; TRACE("Building Directory properties\n"); @@ -2187,7 +2580,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) while (1) { WCHAR name[0x100]; - WCHAR path[MAX_PATH]; + LPWSTR path; MSIRECORD * row = 0; DWORD sz; @@ -2204,8 +2597,9 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) /* This helper function now does ALL the work */ TRACE("Dir %s ...\n",debugstr_w(name)); load_folder(package,name); - resolve_folder(package,name,path,FALSE,TRUE,NULL); + path = resolve_folder(package,name,FALSE,TRUE,NULL); TRACE("resolves to %s\n",debugstr_w(path)); + HeapFree( GetProcessHeap(), 0, path); msiobj_release(&row->hdr); } @@ -2224,21 +2618,29 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) if (file->ComponentIndex >= 0) comp = &package->components[file->ComponentIndex]; + if (file->Temporary == TRUE) + continue; + if (comp) { - int len; + LPWSTR p; + /* calculate target */ - resolve_folder(package, comp->Directory, file->TargetPath, FALSE, - FALSE, NULL); - /* make sure that the path ends in a \ */ - len = strlenW(file->TargetPath); - if (len && file->TargetPath[len-1] != '\\') - strcatW(file->TargetPath, cszbs); - strcatW(file->TargetPath,file->FileName); + p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL); + + if (file->TargetPath) + HeapFree(GetProcessHeap(),0,file->TargetPath); + + TRACE("file %s is named %s\n", + debugstr_w(file->File),debugstr_w(file->FileName)); + + file->TargetPath = build_directory_name(2, p, file->FileName); + + HeapFree(GetProcessHeap(),0,p); TRACE("file %s resolves to %s\n", debugstr_w(file->File),debugstr_w(file->TargetPath)); - + if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES) { file->State = 1; @@ -2246,7 +2648,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) } else { - if (file->Version[0]) + if (file->Version) { DWORD handle; DWORD versize; @@ -2295,55 +2697,55 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) rc = MSI_DatabaseOpenViewW(package->db, ConditionQuery, &view); if (rc == ERROR_SUCCESS) { - rc = MSI_ViewExecute(view, 0); - if (rc != ERROR_SUCCESS) - { - MSI_ViewClose(view); - msiobj_release(&view->hdr); - return rc; - } - - while (1) - { - WCHAR Feature[0x100]; - MSIRECORD * row = 0; - DWORD sz; - int feature_index; - - rc = MSI_ViewFetch(view,&row); - + rc = MSI_ViewExecute(view, 0); if (rc != ERROR_SUCCESS) { - rc = ERROR_SUCCESS; - break; + MSI_ViewClose(view); + msiobj_release(&view->hdr); + return rc; } - - sz = 0x100; - MSI_RecordGetStringW(row,1,Feature,&sz); - - feature_index = get_loaded_feature(package,Feature); - if (feature_index < 0) - ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature)); - else + + while (1) { - LPWSTR Condition; - Condition = load_dynamic_stringW(row,3); + WCHAR Feature[0x100]; + MSIRECORD * row = 0; + DWORD sz; + int feature_index; + + rc = MSI_ViewFetch(view,&row); + + if (rc != ERROR_SUCCESS) + { + rc = ERROR_SUCCESS; + break; + } + + sz = 0x100; + MSI_RecordGetStringW(row,1,Feature,&sz); + + feature_index = get_loaded_feature(package,Feature); + if (feature_index < 0) + ERR("FAILED to find loaded feature %s\n",debugstr_w(Feature)); + else + { + LPWSTR Condition; + Condition = load_dynamic_stringW(row,3); if (MSI_EvaluateConditionW(package,Condition) == MSICONDITION_TRUE) - { - int level = MSI_RecordGetInteger(row,2); + { + int level = MSI_RecordGetInteger(row,2); TRACE("Reseting feature %s to level %i\n", debugstr_w(Feature), level); - package->features[feature_index].Level = level; + package->features[feature_index].Level = level; + } + HeapFree(GetProcessHeap(),0,Condition); } - HeapFree(GetProcessHeap(),0,Condition); - } - msiobj_release(&row->hdr); - } - MSI_ViewClose(view); - msiobj_release(&view->hdr); + msiobj_release(&row->hdr); + } + MSI_ViewClose(view); + msiobj_release(&view->hdr); } TRACE("Enabling or Disabling Components\n"); @@ -2362,7 +2764,15 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) } MSI_SetPropertyW(package,szCosting,szOne); - return ERROR_SUCCESS; + /* set default run level if not set */ + level = load_dynamic_property(package,szlevel,NULL); + if (!level) + MSI_SetPropertyW(package,szlevel, szOne); + else + HeapFree(GetProcessHeap(),0,level); + + return SetFeatureStates(package); + } /* @@ -2408,6 +2818,12 @@ end: /* Support functions for FDI functions */ +typedef struct +{ + MSIPACKAGE* package; + LPCSTR cab_path; + LPCSTR file_name; +} CabData; static void * cabinet_alloc(ULONG cb) { @@ -2480,14 +2896,39 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) { case fdintCOPY_FILE: { - ULONG len = strlen((char*)pfdin->pv) + strlen(pfdin->psz1); - char *file = cabinet_alloc((len+1)*sizeof(char)); + CabData *data = (CabData*) pfdin->pv; + ULONG len = strlen(data->cab_path) + strlen(pfdin->psz1); + char *file; - strcpy(file, (char*)pfdin->pv); + LPWSTR trackname; + LPWSTR trackpath; + LPWSTR tracknametmp; + static const WCHAR tmpprefix[] = {'C','A','B','T','M','P','_',0}; + + if (data->file_name && strcmp(data->file_name,pfdin->psz1)) + return 0; + + file = cabinet_alloc((len+1)*sizeof(char)); + strcpy(file, data->cab_path); strcat(file, pfdin->psz1); TRACE("file: %s\n", debugstr_a(file)); + /* track this file so it can be deleted if not installed */ + trackpath=strdupAtoW(file); + tracknametmp=strdupAtoW(strrchr(file,'\\')+1); + trackname = HeapAlloc(GetProcessHeap(),0,(strlenW(tracknametmp) + + strlenW(tmpprefix)+1) * sizeof(WCHAR)); + + strcpyW(trackname,tmpprefix); + strcatW(trackname,tracknametmp); + + track_tempfile(data->package, trackname, trackpath); + + HeapFree(GetProcessHeap(),0,trackpath); + HeapFree(GetProcessHeap(),0,trackname); + HeapFree(GetProcessHeap(),0,tracknametmp); + return cabinet_open(file, _O_WRONLY | _O_CREAT, 0); } case fdintCLOSE_FILE_INFO: @@ -2514,15 +2955,19 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) * * Extract files from a cab file. */ -static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path) +static BOOL extract_a_cabinet_file(MSIPACKAGE* package, const WCHAR* source, + const WCHAR* path, const WCHAR* file) { HFDI hfdi; ERF erf; BOOL ret; char *cabinet; char *cab_path; + char *file_name; + CabData data; - TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path)); + TRACE("Extracting %s (%s) to %s\n",debugstr_w(source), + debugstr_w(file), debugstr_w(path)); hfdi = FDICreate(cabinet_alloc, cabinet_free, @@ -2551,7 +2996,12 @@ static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path) return FALSE; } - ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, cab_path); + data.package = package; + data.cab_path = cab_path; + file_name = strdupWtoA(file); + data.file_name = file_name; + + ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data); if (!ret) ERR("FDICopy failed\n"); @@ -2560,17 +3010,18 @@ static BOOL extract_cabinet_file(const WCHAR* source, const WCHAR* path) HeapFree(GetProcessHeap(), 0, cabinet); HeapFree(GetProcessHeap(), 0, cab_path); + HeapFree(GetProcessHeap(), 0, file_name); return ret; } static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, - WCHAR* path) + WCHAR* path, WCHAR* file) { UINT rc; MSIQUERY * view; MSIRECORD * row = 0; - WCHAR source[MAX_PATH]; + static WCHAR source[MAX_PATH]; static const WCHAR ExecSeqQuery[] = { 's','e','l','e','c','t',' ','*',' ', 'f','r','o','m',' ','M','e','d','i','a',' ', @@ -2585,6 +3036,7 @@ static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, if (sequence <= last_sequence) { TRACE("Media already ready (%u, %u)\n",sequence,last_sequence); + extract_a_cabinet_file(package, source,path,file); return ERROR_SUCCESS; } @@ -2643,7 +3095,7 @@ static UINT ready_media_for_file(MSIPACKAGE *package, UINT sequence, GetTempPathW(MAX_PATH,path); } } - rc = !extract_cabinet_file(source,path); + rc = !extract_a_cabinet_file(package, source,path,file); } msiobj_release(&row->hdr); MSI_ViewClose(view); @@ -2655,13 +3107,12 @@ inline static UINT create_component_directory ( MSIPACKAGE* package, INT compone { UINT rc; MSIFOLDER *folder; - WCHAR install_path[MAX_PATH]; + LPWSTR install_path; - rc = resolve_folder(package, package->components[component].Directory, - install_path, FALSE, FALSE, &folder); - - if (rc != ERROR_SUCCESS) - return rc; + install_path = resolve_folder(package, package->components[component].Directory, + FALSE, FALSE, &folder); + if (!install_path) + return ERROR_FUNCTION_FAILED; /* create the path */ if (folder->State == 0) @@ -2669,6 +3120,7 @@ inline static UINT create_component_directory ( MSIPACKAGE* package, INT compone create_full_pathW(install_path); folder->State = 2; } + HeapFree(GetProcessHeap(), 0, install_path); return rc; } @@ -2684,7 +3136,7 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) return ERROR_INVALID_HANDLE; /* increment progress bar each time action data is sent */ - ui_progress(package,1,1,1,0); + ui_progress(package,1,1,0,0); for (index = 0; index < package->loaded_files; index++) { @@ -2696,18 +3148,25 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) if (file->Temporary) continue; - if (!package->components[file->ComponentIndex].Enabled || - !package->components[file->ComponentIndex].FeatureState) + if (package->components[file->ComponentIndex].ActionRequest != + INSTALLSTATE_LOCAL) { + ui_progress(package,2,file->FileSize,0,0); TRACE("File %s is not scheduled for install\n", debugstr_w(file->File)); + continue; } if ((file->State == 1) || (file->State == 2)) { + LPWSTR p; + INT len; + MSICOMPONENT* comp = NULL; + TRACE("Installing %s\n",debugstr_w(file->File)); - rc = ready_media_for_file(package,file->Sequence,path_to_source); + rc = ready_media_for_file(package,file->Sequence,path_to_source, + file->File); /* * WARNING! * our file table could change here because a new temp file @@ -2723,6 +3182,19 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) create_component_directory( package, file->ComponentIndex); + /* recalculate file paths because things may have changed */ + + if (file->ComponentIndex >= 0) + comp = &package->components[file->ComponentIndex]; + + p = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL); + if (file->TargetPath) + HeapFree(GetProcessHeap(),0,file->TargetPath); + + file->TargetPath = build_directory_name(2, p, file->FileName); + + len = strlenW(path_to_source) + strlenW(file->File) + 2; + file->SourcePath = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); strcpyW(file->SourcePath, path_to_source); strcatW(file->SourcePath, file->File); @@ -2738,6 +3210,7 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) MSI_RecordSetInteger(uirow,6,file->FileSize); ui_actiondata(package,szInstallFiles,uirow); msiobj_release( &uirow->hdr ); + ui_progress(package,2,file->FileSize,0,0); if (!MoveFileW(file->SourcePath,file->TargetPath)) { @@ -2751,13 +3224,19 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) DeleteFileW(file->SourcePath); rc = 0; } + else if (rc == ERROR_FILE_NOT_FOUND) + { + ERR("Source File Not Found! Continueing\n"); + rc = 0; + } else - break; + { + ERR("Ignoring Error and continuing...\n"); + rc = 0; + } } else file->State = 4; - - ui_progress(package,2,0,0,0); } } @@ -2765,7 +3244,7 @@ static UINT ACTION_InstallFiles(MSIPACKAGE *package) } inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, - LPWSTR file_source) + LPWSTR* file_source) { DWORD index; @@ -2778,7 +3257,7 @@ inline static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key, { if (package->files[index].State >= 3) { - strcpyW(file_source,package->files[index].TargetPath); + *file_source = dupstrW(package->files[index].TargetPath); return ERROR_SUCCESS; } else @@ -2816,9 +3295,9 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) while (1) { WCHAR file_key[0x100]; - WCHAR file_source[MAX_PATH]; + WCHAR *file_source = NULL; WCHAR dest_name[0x100]; - WCHAR dest_path[MAX_PATH]; + LPWSTR dest_path, dest; WCHAR component[0x100]; INT component_index; @@ -2841,8 +3320,8 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) } component_index = get_loaded_component(package,component); - if (!package->components[component_index].Enabled || - !package->components[component_index].FeatureState) + if (package->components[component_index].ActionRequest != + INSTALLSTATE_LOCAL) { TRACE("Skipping copy due to disabled component\n"); msiobj_release(&row->hdr); @@ -2858,12 +3337,14 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) break; } - rc = get_file_target(package,file_key,file_source); + rc = get_file_target(package,file_key,&file_source); if (rc != ERROR_SUCCESS) { ERR("Original file unknown %s\n",debugstr_w(file_key)); msiobj_release(&row->hdr); + if (file_source) + HeapFree(GetProcessHeap(),0,file_source); break; } @@ -2880,8 +3361,11 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) if (MSI_RecordIsNull(row,5)) { - strcpyW(dest_path,file_source); - *strrchrW(dest_path,'\\')=0; + LPWSTR p; + dest_path = dupstrW(file_source); + p = strrchrW(dest_path,'\\'); + if (p) + *p=0; } else { @@ -2889,22 +3373,25 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) sz=0x100; MSI_RecordGetStringW(row,5,destkey,&sz); sz = 0x100; - rc = resolve_folder(package, destkey, dest_path,FALSE,FALSE,NULL); - if (rc != ERROR_SUCCESS) + dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL); + if (!dest_path) { ERR("Unable to get destination folder\n"); msiobj_release(&row->hdr); + if (file_source) + HeapFree(GetProcessHeap(),0,file_source); break; } } - strcatW(dest_path,dest_name); + dest = build_directory_name(2, dest_path, dest_name); + HeapFree(GetProcessHeap(), 0, dest_path); TRACE("Duplicating file %s to %s\n",debugstr_w(file_source), - debugstr_w(dest_path)); + debugstr_w(dest)); - if (strcmpW(file_source,dest_path)) - rc = !CopyFileW(file_source,dest_path,TRUE); + if (strcmpW(file_source,dest)) + rc = !CopyFileW(file_source,dest,TRUE); else rc = ERROR_SUCCESS; @@ -2914,11 +3401,12 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package) FIXME("We should track these duplicate files as well\n"); msiobj_release(&row->hdr); + HeapFree(GetProcessHeap(),0,dest); + HeapFree(GetProcessHeap(),0,file_source); } MSI_ViewClose(view); msiobj_release(&view->hdr); return rc; - } @@ -3024,7 +3512,7 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) } /* increment progress bar each time action data is sent */ - ui_progress(package,1,1,1,0); + ui_progress(package,1,REG_PROGRESS_VALUE,1,0); while (1) { @@ -3038,19 +3526,15 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) static const WCHAR szHU[] = {'H','K','E','Y','_','U','S','E','R','S','\\',0}; - WCHAR key[0x100]; - WCHAR name[0x100]; - LPWSTR value; LPSTR value_data = NULL; HKEY root_key, hkey; DWORD type,size; - WCHAR component[0x100]; + LPWSTR value, key, name, component, deformated; + LPCWSTR szRoot; INT component_index; MSIRECORD * uirow; - WCHAR uikey[0x110]; - + LPWSTR uikey; INT root; - DWORD sz=0x100; rc = MSI_ViewFetch(view,&row); if (rc != ERROR_SUCCESS) @@ -3058,17 +3542,22 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) rc = ERROR_SUCCESS; break; } + ui_progress(package,2,0,0,0); - sz= 0x100; - MSI_RecordGetStringW(row,6,component,&sz); + value = NULL; + key = NULL; + uikey = NULL; + name = NULL; + + component = load_dynamic_stringW(row, 6); component_index = get_loaded_component(package,component); - if (!package->components[component_index].Enabled || - !package->components[component_index].FeatureState) + if (package->components[component_index].ActionRequest != + INSTALLSTATE_LOCAL) { TRACE("Skipping write due to disabled component\n"); msiobj_release(&row->hdr); - continue; + goto next; } /* null values have special meanings during uninstalls and such */ @@ -3076,59 +3565,68 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) if(MSI_RecordIsNull(row,5)) { msiobj_release(&row->hdr); - continue; + goto next; } root = MSI_RecordGetInteger(row,2); - sz = 0x100; - MSI_RecordGetStringW(row,3,key,&sz); + key = load_dynamic_stringW(row, 3); - sz = 0x100; - if (MSI_RecordIsNull(row,4)) - name[0]=0; - else - MSI_RecordGetStringW(row,4,name,&sz); + name = load_dynamic_stringW(row, 4); /* get the root key */ switch (root) { case 0: root_key = HKEY_CLASSES_ROOT; - strcpyW(uikey,szHCR); break; + szRoot = szHCR; + break; case 1: root_key = HKEY_CURRENT_USER; - strcpyW(uikey,szHCU); break; + szRoot = szHCU; + break; case 2: root_key = HKEY_LOCAL_MACHINE; - strcpyW(uikey,szHLM); break; + szRoot = szHLM; + break; case 3: root_key = HKEY_USERS; - strcpyW(uikey,szHU); break; + szRoot = szHU; + break; default: ERR("Unknown root %i\n",root); root_key=NULL; + szRoot = NULL; break; } if (!root_key) { msiobj_release(&row->hdr); - continue; + goto next; } - strcatW(uikey,key); - if (RegCreateKeyW( root_key, key, &hkey)) + deformat_string(package, key , &deformated); + size = strlenW(deformated) + strlenW(szRoot) + 1; + uikey = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR)); + strcpyW(uikey,szRoot); + strcatW(uikey,deformated); + + if (RegCreateKeyW( root_key, deformated, &hkey)) { - ERR("Could not create key %s\n",debugstr_w(key)); + ERR("Could not create key %s\n",debugstr_w(deformated)); msiobj_release(&row->hdr); - continue; + HeapFree(GetProcessHeap(),0,deformated); + goto next; } + HeapFree(GetProcessHeap(),0,deformated); value = load_dynamic_stringW(row,5); value_data = parse_value(package, value, &type, &size); + deformat_string(package, name, &deformated); + if (value_data) { - TRACE("Setting value %s\n",debugstr_w(name)); - RegSetValueExW(hkey, name, 0, type, value_data, size); + TRACE("Setting value %s\n",debugstr_w(deformated)); + RegSetValueExW(hkey, deformated, 0, type, value_data, size); uirow = MSI_CreateRecord(3); - MSI_RecordSetStringW(uirow,2,name); + MSI_RecordSetStringW(uirow,2,deformated); MSI_RecordSetStringW(uirow,1,uikey); if (type == REG_SZ) @@ -3137,15 +3635,24 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package) MSI_RecordSetStringW(uirow,3,value); ui_actiondata(package,szWriteRegistryValues,uirow); - ui_progress(package,2,0,0,0); msiobj_release( &uirow->hdr ); HeapFree(GetProcessHeap(),0,value_data); } HeapFree(GetProcessHeap(),0,value); + HeapFree(GetProcessHeap(),0,deformated); msiobj_release(&row->hdr); RegCloseKey(hkey); +next: + if (uikey) + HeapFree(GetProcessHeap(),0,uikey); + if (key) + HeapFree(GetProcessHeap(),0,key); + if (name) + HeapFree(GetProcessHeap(),0,name); + if (component) + HeapFree(GetProcessHeap(),0,component); } MSI_ViewClose(view); msiobj_release(&view->hdr); @@ -3167,6 +3674,12 @@ static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data) DWORD sz; UINT rc; + if (ptr==NULL) + { + TRACE("Deformatting NULL string\n"); + *data = NULL; + return 0; + } /* scan for special characters */ if (!strchrW(ptr,'[') || (strchrW(ptr,'[') && !strchrW(ptr,']'))) { @@ -3241,82 +3754,21 @@ static DWORD deformat_string(MSIPACKAGE *package, WCHAR* ptr,WCHAR** data) static UINT ACTION_InstallInitialize(MSIPACKAGE *package) { - WCHAR level[10000]; - INT install_level; - DWORD sz; - DWORD i; - INT j; - DWORD rc; - LPWSTR override = NULL; - static const WCHAR addlocal[]={'A','D','D','L','O','C','A','L',0}; - static const WCHAR all[]={'A','L','L',0}; - static const WCHAR szlevel[] = { - 'I','N','S','T','A','L','L','L','E','V','E','L',0}; - static const WCHAR szAddLocal[] = { - 'A','D','D','L','O','C','A','L',0}; - - /* I do not know if this is where it should happen.. but */ - - TRACE("Checking Install Level\n"); - - sz = 10000; - if (MSI_GetPropertyW(package,szlevel,level,&sz)==ERROR_SUCCESS) - install_level = atoiW(level); - else - install_level = 1; - - sz = 0; - rc = MSI_GetPropertyW(package,szAddLocal,NULL,&sz); - if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA) - { - sz++; - override = HeapAlloc(GetProcessHeap(),0,sz*sizeof(WCHAR)); - MSI_GetPropertyW(package, addlocal,override,&sz); - } - - /* - * Components FeatureState defaults to FALSE. The idea is we want to - * enable the component is ANY feature that uses it is enabled to install - */ - for(i = 0; i < package->loaded_features; i++) - { - BOOL feature_state= ((package->features[i].Level > 0) && - (package->features[i].Level <= install_level)); - - if (override && (strcmpiW(override,all)==0 || - strstrW(override,package->features[i].Feature))) - { - TRACE("Override of install level found\n"); - feature_state = TRUE; - package->features[i].Enabled = feature_state; - } - - TRACE("Feature %s has a state of %i\n", - debugstr_w(package->features[i].Feature), feature_state); - for( j = 0; j < package->features[i].ComponentCount; j++) - { - package->components[package->features[i].Components[j]].FeatureState - |= feature_state; - } - } - if (override != NULL) - HeapFree(GetProcessHeap(),0,override); - /* - * So basically we ONLY want to install a component if its Enabled AND - * FeatureState are both TRUE - */ return ERROR_SUCCESS; } + static UINT ACTION_InstallValidate(MSIPACKAGE *package) { DWORD progress = 0; + DWORD total = 0; static const WCHAR q1[]={ 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ','R','e','g','i','s','t','r','y',0}; UINT rc; MSIQUERY * view; MSIRECORD * row = 0; + int i; TRACE(" InstallValidate \n"); @@ -3346,7 +3798,11 @@ static UINT ACTION_InstallValidate(MSIPACKAGE *package) MSI_ViewClose(view); msiobj_release(&view->hdr); - ui_progress(package,0,progress+package->loaded_files,0,0); + total = total + progress * REG_PROGRESS_VALUE; + total = total + package->loaded_components * COMPONENT_PROGRESS_VALUE; + for (i=0; i < package->loaded_files; i++) + total += package->files[i].FileSize; + ui_progress(package,0,total,0,0); return ERROR_SUCCESS; } @@ -3406,20 +3862,20 @@ static UINT ACTION_LaunchConditions(MSIPACKAGE *package) return rc; } -static void resolve_keypath( MSIPACKAGE* package, INT - component_index, WCHAR *keypath) +static LPWSTR resolve_keypath( MSIPACKAGE* package, INT + component_index) { MSICOMPONENT* cmp = &package->components[component_index]; if (cmp->KeyPath[0]==0) { - resolve_folder(package,cmp->Directory,keypath,FALSE,FALSE,NULL); - return; + LPWSTR p = resolve_folder(package,cmp->Directory,FALSE,FALSE,NULL); + return p; } if ((cmp->Attributes & 0x4) || (cmp->Attributes & 0x20)) { FIXME("UNIMPLEMENTED keypath as Registry or ODBC Source\n"); - keypath[0]=0; + return NULL; } else { @@ -3427,8 +3883,12 @@ static void resolve_keypath( MSIPACKAGE* package, INT j = get_loaded_file(package,cmp->KeyPath); if (j>=0) - strcpyW(keypath,package->files[j].TargetPath); + { + LPWSTR p = dupstrW(package->files[j].TargetPath); + return p; + } } + return NULL; } /* @@ -3440,34 +3900,32 @@ static void resolve_keypath( MSIPACKAGE* package, INT */ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) { - WCHAR productcode[0x100]; + LPWSTR productcode; WCHAR squished_pc[0x100]; WCHAR squished_cc[0x100]; - DWORD sz; UINT rc; DWORD i; HKEY hkey=0,hkey2=0,hkey3=0; static const WCHAR szProductCode[]= -{'P','r','o','d','u','c','t','C','o','d','e',0}; + {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szInstaller[] = { -'S','o','f','t','w','a','r','e','\\', -'M','i','c','r','o','s','o','f','t','\\', -'W','i','n','d','o','w','s','\\', -'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', -'I','n','s','t','a','l','l','e','r',0 }; + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'I','n','s','t','a','l','l','e','r',0 }; static const WCHAR szFeatures[] = { -'F','e','a','t','u','r','e','s',0 }; + 'F','e','a','t','u','r','e','s',0 }; static const WCHAR szComponents[] = { -'C','o','m','p','o','n','e','n','t','s',0 }; + 'C','o','m','p','o','n','e','n','t','s',0 }; if (!package) return ERROR_INVALID_HANDLE; /* writes the Component and Features values to the registry */ - sz = 0x100; - rc = MSI_GetPropertyW(package,szProductCode,productcode,&sz); - if (rc != ERROR_SUCCESS) - return ERROR_SUCCESS; + productcode = load_dynamic_property(package,szProductCode,&rc); + if (!productcode) + return rc; squash_guid(productcode,squished_pc); rc = RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller,&hkey); @@ -3519,12 +3977,14 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) rc = RegCreateKeyW(hkey,szComponents,&hkey2); if (rc != ERROR_SUCCESS) goto end; - + + ui_progress(package,1,COMPONENT_PROGRESS_VALUE,1,0); for (i = 0; i < package->loaded_components; i++) { + ui_progress(package,2,0,0,0); if (package->components[i].ComponentId[0]!=0) { - WCHAR keypath[0x1000]; + WCHAR *keypath = NULL; MSIRECORD * uirow; squash_guid(package->components[i].ComponentId,squished_cc); @@ -3532,22 +3992,27 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) continue; - resolve_keypath(package,i,keypath); - - RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath, + keypath = resolve_keypath(package,i); + if (keypath) + { + RegSetValueExW(hkey3,squished_pc,0,REG_SZ,(LPVOID)keypath, (strlenW(keypath)+1)*sizeof(WCHAR)); - RegCloseKey(hkey3); + RegCloseKey(hkey3); - /* UI stuff */ - uirow = MSI_CreateRecord(3); - MSI_RecordSetStringW(uirow,1,productcode); - MSI_RecordSetStringW(uirow,2,package->components[i].ComponentId); - MSI_RecordSetStringW(uirow,3,keypath); - ui_actiondata(package,szProcessComponents,uirow); - msiobj_release( &uirow->hdr ); + /* UI stuff */ + uirow = MSI_CreateRecord(3); + MSI_RecordSetStringW(uirow,1,productcode); + MSI_RecordSetStringW(uirow,2,package->components[i]. + ComponentId); + MSI_RecordSetStringW(uirow,3,keypath); + ui_actiondata(package,szProcessComponents,uirow); + msiobj_release( &uirow->hdr ); + HeapFree(GetProcessHeap(),0,keypath); + } } } end: + HeapFree(GetProcessHeap(), 0, productcode); RegCloseKey(hkey2); RegCloseKey(hkey); return rc; @@ -3608,8 +4073,7 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) continue; } - if (!package->components[index].Enabled || - !package->components[index].FeatureState) + if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) { TRACE("Skipping typelib reg due to disabled component\n"); msiobj_release(&row->hdr); @@ -3627,15 +4091,16 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package) res = LoadTypeLib(package->files[index].TargetPath,&ptLib); if (SUCCEEDED(res)) { - WCHAR help[MAX_PATH]; + LPWSTR help; WCHAR helpid[0x100]; sz = 0x100; MSI_RecordGetStringW(row,6,helpid,&sz); - resolve_folder(package,helpid,help,FALSE,FALSE,NULL); - + help = resolve_folder(package,helpid,FALSE,FALSE,NULL); res = RegisterTypeLib(ptLib,package->files[index].TargetPath,help); + HeapFree(GetProcessHeap(),0,help); + if (!SUCCEEDED(res)) ERR("Failed to register type library %s\n", debugstr_w(package->files[index].TargetPath)); @@ -3672,18 +4137,15 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) MSIQUERY * view; MSIRECORD * row = 0; static const WCHAR ExecSeqQuery[] = -{'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I' -,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0}; - WCHAR Query[0x1000]; + {'S','E','L','E','C','T',' ','*',' ','f','r','o','m',' ','A','p','p','I' + ,'d',' ','w','h','e','r','e',' ','A','p','p','I','d','=','`','%','s','`',0}; HKEY hkey2,hkey3; LPWSTR buffer=0; if (!package) return ERROR_INVALID_HANDLE; - sprintfW(Query,ExecSeqQuery,clsid); - - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + rc = ACTION_OpenQuery(package->db, &view, ExecSeqQuery, clsid); if (rc != ERROR_SUCCESS) return rc; @@ -3713,7 +4175,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) LPWSTR deformated=0; UINT size; static const WCHAR szRemoteServerName[] = -{'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0}; + {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0}; buffer = load_dynamic_stringW(row,2); size = deformat_string(package,buffer,&deformated); RegSetValueExW(hkey3,szRemoteServerName,0,REG_SZ,(LPVOID)deformated, @@ -3725,7 +4187,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) if (!MSI_RecordIsNull(row,3)) { static const WCHAR szLocalService[] = -{'L','o','c','a','l','S','e','r','v','i','c','e',0}; + {'L','o','c','a','l','S','e','r','v','i','c','e',0}; UINT size; buffer = load_dynamic_stringW(row,3); size = (strlenW(buffer)+1) * sizeof(WCHAR); @@ -3736,7 +4198,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) if (!MSI_RecordIsNull(row,4)) { static const WCHAR szService[] = -{'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0}; + {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0}; UINT size; buffer = load_dynamic_stringW(row,4); size = (strlenW(buffer)+1) * sizeof(WCHAR); @@ -3747,7 +4209,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) if (!MSI_RecordIsNull(row,5)) { static const WCHAR szDLL[] = -{'D','l','l','S','u','r','r','o','g','a','t','e',0}; + {'D','l','l','S','u','r','r','o','g','a','t','e',0}; UINT size; buffer = load_dynamic_stringW(row,5); size = (strlenW(buffer)+1) * sizeof(WCHAR); @@ -3758,7 +4220,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) if (!MSI_RecordIsNull(row,6)) { static const WCHAR szActivate[] = -{'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0}; + {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0}; static const WCHAR szY[] = {'Y',0}; if (MSI_RecordGetInteger(row,6)) @@ -3769,7 +4231,7 @@ static UINT register_appid(MSIPACKAGE *package, LPCWSTR clsid, LPCWSTR app ) { static const WCHAR szRunAs[] = {'R','u','n','A','s',0}; static const WCHAR szUser[] = -{'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0}; + {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0}; if (MSI_RecordGetInteger(row,7)) RegSetValueExW(hkey3,szRunAs,0,REG_SZ,(LPVOID)szUser,34); @@ -3855,8 +4317,7 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package) continue; } - if (!package->components[index].Enabled || - !package->components[index].FeatureState) + if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) { TRACE("Skipping class reg due to disabled component\n"); msiobj_release(&row->hdr); @@ -3984,17 +4445,14 @@ static UINT register_parent_progid(MSIPACKAGE *package, LPCWSTR parent, MSIQUERY * view; MSIRECORD * row = 0; static const WCHAR Query_t[] = -{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g' -,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`' -,'%','s','`',0}; - WCHAR Query[0x1000]; + {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','P','r','o','g' + ,'I','d',' ','w','h','e','r','e',' ','P','r','o','g','I','d',' ','=',' ','`' + ,'%','s','`',0}; if (!package) return ERROR_INVALID_HANDLE; - sprintfW(Query,Query_t,parent); - - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); + rc = ACTION_OpenQuery(package->db, &view, Query_t, parent); if (rc != ERROR_SUCCESS) return rc; @@ -4127,33 +4585,35 @@ static UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package) } static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name, - LPWSTR FilePath) + LPWSTR *FilePath) { - WCHAR ProductCode[0x100]; - WCHAR SystemFolder[MAX_PATH]; - DWORD sz; + LPWSTR ProductCode; + LPWSTR SystemFolder; + LPWSTR dest; + UINT rc; static const WCHAR szInstaller[] = -{'I','n','s','t','a','l','l','e','r','\\',0}; + {'I','n','s','t','a','l','l','e','r','\\',0}; static const WCHAR szProductCode[] = -{'P','r','o','d','u','c','t','C','o','d','e',0}; + {'P','r','o','d','u','c','t','C','o','d','e',0}; static const WCHAR szFolder[] = -{'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; + {'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; - sz = 0x100; - MSI_GetPropertyW(package,szProductCode,ProductCode,&sz); - if (strlenW(ProductCode)==0) - return ERROR_FUNCTION_FAILED; + ProductCode = load_dynamic_property(package,szProductCode,&rc); + if (!ProductCode) + return rc; - sz = MAX_PATH; - MSI_GetPropertyW(package,szFolder,SystemFolder,&sz); - strcatW(SystemFolder,szInstaller); - strcatW(SystemFolder,ProductCode); - create_full_pathW(SystemFolder); + SystemFolder = load_dynamic_property(package,szFolder,NULL); - strcpyW(FilePath,SystemFolder); - strcatW(FilePath,cszbs); - strcatW(FilePath,icon_name); + dest = build_directory_name(3, SystemFolder, szInstaller, ProductCode); + + create_full_pathW(dest); + + *FilePath = build_directory_name(2, dest, icon_name); + + HeapFree(GetProcessHeap(),0,SystemFolder); + HeapFree(GetProcessHeap(),0,ProductCode); + HeapFree(GetProcessHeap(),0,dest); return ERROR_SUCCESS; } @@ -4193,7 +4653,7 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) while (1) { - WCHAR target_file[MAX_PATH]; + LPWSTR target_file, target_folder; WCHAR buffer[0x100]; DWORD sz; DWORD index; @@ -4217,8 +4677,7 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) continue; } - if (!package->components[index].Enabled || - !package->components[index].FeatureState) + if (package->components[index].ActionRequest != INSTALLSTATE_LOCAL) { TRACE("Skipping shortcut creation due to disabled component\n"); msiobj_release(&row->hdr); @@ -4247,14 +4706,18 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) sz = 0x100; MSI_RecordGetStringW(row,2,buffer,&sz); - resolve_folder(package, buffer,target_file,FALSE,FALSE,NULL); + target_folder = resolve_folder(package, buffer,FALSE,FALSE,NULL); + + /* may be needed because of a bug somehwere else */ + create_full_pathW(target_folder); sz = 0x100; MSI_RecordGetStringW(row,3,buffer,&sz); reduce_to_longfilename(buffer); - strcatW(target_file,buffer); - if (!strchrW(target_file,'.')) - strcatW(target_file,szlnk); + if (!strchrW(buffer,'.') || strcmpiW(strchrW(buffer,'.'),szlnk)) + strcatW(buffer,szlnk); + target_file = build_directory_name(2, target_folder, buffer); + HeapFree(GetProcessHeap(),0,target_folder); sz = 0x100; MSI_RecordGetStringW(row,5,buffer,&sz); @@ -4297,16 +4760,17 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) if (!MSI_RecordIsNull(row,9)) { - WCHAR Path[MAX_PATH]; + WCHAR *Path = NULL; INT index; sz = 0x100; MSI_RecordGetStringW(row,9,buffer,&sz); - build_icon_path(package,buffer,Path); + build_icon_path(package,buffer,&Path); index = MSI_RecordGetInteger(row,10); IShellLinkW_SetIconLocation(sl,Path,index); + HeapFree(GetProcessHeap(),0,Path); } if (!MSI_RecordIsNull(row,11)) @@ -4314,17 +4778,19 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package) if (!MSI_RecordIsNull(row,12)) { - WCHAR Path[MAX_PATH]; - + LPWSTR Path; sz = 0x100; MSI_RecordGetStringW(row,12,buffer,&sz); - resolve_folder(package, buffer, Path, FALSE, FALSE, NULL); + Path = resolve_folder(package, buffer, FALSE, FALSE, NULL); IShellLinkW_SetWorkingDirectory(sl,Path); + HeapFree(GetProcessHeap(), 0, Path); } TRACE("Writing shortcut to %s\n",debugstr_w(target_file)); IPersistFile_Save(pf,target_file,FALSE); - + + HeapFree(GetProcessHeap(),0,target_file); + IPersistFile_Release( pf ); IShellLinkW_Release( sl ); @@ -4374,8 +4840,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) while (1) { HANDLE the_file; - WCHAR FilePath[MAX_PATH]; - WCHAR FileName[MAX_PATH]; + WCHAR *FilePath=NULL; + WCHAR *FileName=NULL; CHAR buffer[1024]; rc = MSI_ViewFetch(view,&row); @@ -4385,16 +4851,17 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) break; } - sz = MAX_PATH; - MSI_RecordGetStringW(row,1,FileName,&sz); - if (sz == 0) + FileName = load_dynamic_stringW(row,1); + if (!FileName) { ERR("Unable to get FileName\n"); msiobj_release(&row->hdr); continue; } - build_icon_path(package,FileName,FilePath); + build_icon_path(package,FileName,&FilePath); + + HeapFree(GetProcessHeap(),0,FileName); TRACE("Creating icon file at %s\n",debugstr_w(FilePath)); @@ -4405,6 +4872,7 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) { ERR("Unable to create file %s\n",debugstr_w(FilePath)); msiobj_release(&row->hdr); + HeapFree(GetProcessHeap(),0,FilePath); continue; } @@ -4423,6 +4891,8 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) WriteFile(the_file,buffer,sz,&write,NULL); } while (sz == 1024); + HeapFree(GetProcessHeap(),0,FilePath); + CloseHandle(the_file); msiobj_release(&row->hdr); } @@ -4507,29 +4977,31 @@ UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR szPathBuf, DWORD* pcchPathBuf) { - WCHAR path[MAX_PATH]; - UINT rc; + LPWSTR path; + UINT rc = ERROR_FUNCTION_FAILED; MSIPACKAGE *package; TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf); package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); - if( !package ) + if (!package) return ERROR_INVALID_HANDLE; - rc = resolve_folder(package, szFolder, path, FALSE, FALSE, NULL); + path = resolve_folder(package, szFolder, FALSE, FALSE, NULL); msiobj_release( &package->hdr ); - if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf) + if (path && (strlenW(path) > *pcchPathBuf)) { *pcchPathBuf = strlenW(path)+1; - return ERROR_MORE_DATA; + rc = ERROR_MORE_DATA; } - else if (rc == ERROR_SUCCESS) + else if (path) { *pcchPathBuf = strlenW(path)+1; strcpyW(szPathBuf,path); TRACE("Returning Path %s\n",debugstr_w(path)); + rc = ERROR_SUCCESS; } + HeapFree(GetProcessHeap(),0,path); return rc; } @@ -4569,8 +5041,8 @@ UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR szPathBuf, DWORD* pcchPathBuf) { - WCHAR path[MAX_PATH]; - UINT rc; + LPWSTR path; + UINT rc = ERROR_FUNCTION_FAILED; MSIPACKAGE *package; TRACE("(%s %p %li)\n",debugstr_w(szFolder),szPathBuf,*pcchPathBuf); @@ -4578,20 +5050,22 @@ UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder, LPWSTR package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE); if( !package ) return ERROR_INVALID_HANDLE; - rc = resolve_folder(package, szFolder, path, TRUE, FALSE, NULL); + path = resolve_folder(package, szFolder, TRUE, FALSE, NULL); msiobj_release( &package->hdr ); - if (rc == ERROR_SUCCESS && strlenW(path) > *pcchPathBuf) + if (path && strlenW(path) > *pcchPathBuf) { *pcchPathBuf = strlenW(path)+1; - return ERROR_MORE_DATA; + rc = ERROR_MORE_DATA; } - else if (rc == ERROR_SUCCESS) + else if (path) { *pcchPathBuf = strlenW(path)+1; strcpyW(szPathBuf,path); TRACE("Returning Path %s\n",debugstr_w(path)); + rc = ERROR_SUCCESS; } + HeapFree(GetProcessHeap(),0,path); return rc; } @@ -4632,7 +5106,9 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, LPCWSTR szFolderPath) { DWORD i; - WCHAR path[MAX_PATH]; + LPWSTR path = NULL; + LPWSTR path2 = NULL; + INT len; MSIFOLDER *folder; TRACE("(%p %s %s)\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath)); @@ -4646,19 +5122,54 @@ UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, if (GetFileAttributesW(szFolderPath) == INVALID_FILE_ATTRIBUTES) return ERROR_FUNCTION_FAILED; - resolve_folder(package,szFolder,path,FALSE,FALSE,&folder); + path = resolve_folder(package,szFolder,FALSE,FALSE,&folder); - if (!folder) + if (!path) return ERROR_INVALID_PARAMETER; - strcpyW(folder->Property,szFolderPath); + if (folder->Property) + HeapFree(GetProcessHeap(),0,folder->Property); - for (i = 0; i < package->loaded_folders; i++) - package->folders[i].ResolvedTarget[0]=0; + len = strlenW(szFolderPath); - for (i = 0; i < package->loaded_folders; i++) - resolve_folder(package, package->folders[i].Directory, path, FALSE, + if (szFolderPath[len-1]!='\\') + { + len +=2; + folder->Property = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + strcpyW(folder->Property,szFolderPath); + strcatW(folder->Property,cszbs); + } + else + folder->Property = dupstrW(szFolderPath); + + if (strcmpiW(path, szFolderPath) == 0) + { + /* + * Resolved Target has not really changed, so just + * set this folder and do not recalculate everything. + */ + HeapFree(GetProcessHeap(),0,folder->ResolvedTarget); + folder->ResolvedTarget = NULL; + path2 = resolve_folder(package,szFolder,FALSE,TRUE,NULL); + HeapFree(GetProcessHeap(),0,path2); + } + else + { + for (i = 0; i < package->loaded_folders; i++) + { + if (package->folders[i].ResolvedTarget) + HeapFree(GetProcessHeap(),0,package->folders[i].ResolvedTarget); + package->folders[i].ResolvedTarget=NULL; + } + + for (i = 0; i < package->loaded_folders; i++) + { + path2=resolve_folder(package, package->folders[i].Directory, FALSE, TRUE, NULL); + HeapFree(GetProcessHeap(),0,path2); + } + } + HeapFree(GetProcessHeap(),0,path); return ERROR_SUCCESS; } @@ -4677,10 +5188,44 @@ UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, return ret; } -BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, DWORD iRunMode) +/*********************************************************************** + * MsiGetMode (MSI.@) + * + * Returns an internal installer state (if it is running in a mode iRunMode) + * + * PARAMS + * hInstall [I] Handle to the installation + * hRunMode [I] Checking run mode + * MSIRUNMODE_ADMIN Administrative mode + * MSIRUNMODE_ADVERTISE Advertisement mode + * MSIRUNMODE_MAINTENANCE Maintenance mode + * MSIRUNMODE_ROLLBACKENABLED Rollback is enabled + * MSIRUNMODE_LOGENABLED Log file is writing + * MSIRUNMODE_OPERATIONS Operations in progress?? + * MSIRUNMODE_REBOOTATEND We need to reboot after installation completed + * MSIRUNMODE_REBOOTNOW We need to reboot to continue the installation + * MSIRUNMODE_CABINET Files from cabinet are installed + * MSIRUNMODE_SOURCESHORTNAMES Long names in source files is supressed + * MSIRUNMODE_TARGETSHORTNAMES Long names in destination files is supressed + * MSIRUNMODE_RESERVED11 Reserved + * MSIRUNMODE_WINDOWS9X Running under Windows95/98 + * MSIRUNMODE_ZAWENABLED Demand installation is supported + * MSIRUNMODE_RESERVED14 Reserved + * MSIRUNMODE_RESERVED15 Reserved + * MSIRUNMODE_SCHEDULED called from install script + * MSIRUNMODE_ROLLBACK called from rollback script + * MSIRUNMODE_COMMIT called from commit script + * + * RETURNS + * In the state: TRUE + * Not in the state: FALSE + * + */ + +BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode) { - FIXME("STUB (%li)\n",iRunMode); - return FALSE; + FIXME("STUB (iRunMode=%i)\n",iRunMode); + return TRUE; } /* @@ -4721,7 +5266,7 @@ UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature, if (index < 0) return ERROR_UNKNOWN_FEATURE; - package->features[index].State = iState; + package->features[index].ActionRequest= iState; return ERROR_SUCCESS; } @@ -4751,15 +5296,12 @@ UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPWSTR szFeature, return ERROR_UNKNOWN_FEATURE; if (piInstalled) - *piInstalled = package->features[index].State; + *piInstalled = package->features[index].Installed; if (piAction) - { - if (package->features[index].Enabled) - *piAction = INSTALLSTATE_LOCAL; - else - *piAction = INSTALLSTATE_UNKNOWN; - } + *piAction = package->features[index].Action; + + TRACE("returning %i %i\n",*piInstalled,*piAction); return ERROR_SUCCESS; } @@ -4809,16 +5351,10 @@ piAction); return ERROR_UNKNOWN_COMPONENT; if (piInstalled) - *piInstalled = package->components[index].State; + *piInstalled = package->components[index].Installed; if (piAction) - { - if (package->components[index].Enabled && - package->components[index].FeatureState) - *piAction = INSTALLSTATE_LOCAL; - else - *piAction = INSTALLSTATE_UNKNOWN; - } + *piInstalled = package->components[index].Action; return ERROR_SUCCESS; } diff --git a/reactos/lib/msi/handle.c b/reactos/lib/msi/handle.c index ade5e1bf2ba..bd33099c1f0 100644 --- a/reactos/lib/msi/handle.c +++ b/reactos/lib/msi/handle.c @@ -41,7 +41,23 @@ static CRITICAL_SECTION_DEBUG MSI_handle_cs_debug = }; static CRITICAL_SECTION MSI_handle_cs = { &MSI_handle_cs_debug, -1, 0, 0, 0, 0 }; -MSIOBJECTHDR *msihandletable[MSIMAXHANDLES]; +static CRITICAL_SECTION MSI_object_cs; +static CRITICAL_SECTION_DEBUG MSI_object_cs_debug = +{ + 0, 0, &MSI_object_cs, + { &MSI_object_cs_debug.ProcessLocksList, + &MSI_object_cs_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": MSI_object_cs") } +}; +static CRITICAL_SECTION MSI_object_cs = { &MSI_object_cs_debug, -1, 0, 0, 0, 0 }; + +typedef struct msi_handle_info_t +{ + MSIOBJECTHDR *obj; + DWORD dwThreadId; +} msi_handle_info; + +static msi_handle_info msihandletable[MSIMAXHANDLES]; MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj ) { @@ -52,13 +68,14 @@ MSIHANDLE alloc_msihandle( MSIOBJECTHDR *obj ) /* find a slot */ for(i=0; i=MSIMAXHANDLES) || msihandletable[i] ) + if( (i>=MSIMAXHANDLES) || msihandletable[i].obj ) goto out; msiobj_addref( obj ); - msihandletable[i] = obj; + msihandletable[i].obj = obj; + msihandletable[i].dwThreadId = GetCurrentThreadId(); ret = (MSIHANDLE) (i+1); out: TRACE("%p -> %ld\n", obj, ret ); @@ -77,13 +94,13 @@ void *msihandle2msiinfo(MSIHANDLE handle, UINT type) goto out; if( handle>=MSIMAXHANDLES ) goto out; - if( !msihandletable[handle] ) + if( !msihandletable[handle].obj ) goto out; - if( msihandletable[handle]->magic != MSIHANDLE_MAGIC ) + if( msihandletable[handle].obj->magic != MSIHANDLE_MAGIC ) goto out; - if( type && (msihandletable[handle]->type != type) ) + if( type && (msihandletable[handle].obj->type != type) ) goto out; - ret = msihandletable[handle]; + ret = msihandletable[handle].obj; msiobj_addref( ret ); out: @@ -101,7 +118,7 @@ MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr ) EnterCriticalSection( &MSI_handle_cs ); for(i=0; (irefcount++; } +void msiobj_lock( MSIOBJECTHDR *info ) +{ + EnterCriticalSection( &MSI_object_cs ); +} + +void msiobj_unlock( MSIOBJECTHDR *info ) +{ + LeaveCriticalSection( &MSI_object_cs ); +} + int msiobj_release( MSIOBJECTHDR *info ) { int ret; @@ -170,6 +197,9 @@ int msiobj_release( MSIOBJECTHDR *info ) return ret; } +/*********************************************************** + * MsiCloseHandle [MSI.@] + */ UINT WINAPI MsiCloseHandle(MSIHANDLE handle) { MSIOBJECTHDR *info; @@ -190,7 +220,7 @@ UINT WINAPI MsiCloseHandle(MSIHANDLE handle) } msiobj_release( info ); - msihandletable[handle-1] = NULL; + msihandletable[handle-1].obj = NULL; ret = ERROR_SUCCESS; TRACE("handle %lx Destroyed\n", handle); @@ -202,14 +232,28 @@ out: return ret; } +/*********************************************************** + * MsiCloseAllHandles [MSI.@] + * + * Closes all handles owned by the current thread + * + * RETURNS: + * The number of handles closed + */ UINT WINAPI MsiCloseAllHandles(void) { - UINT i; + UINT i, n=0; TRACE("\n"); for(i=0; iref); + return InterlockedIncrement(&This->ref); } static ULONG WINAPI MsiCF_Release(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; /* static class, won't be freed */ - return --(This->ref); + return InterlockedDecrement(&This->ref); } static HRESULT WINAPI MsiCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, LPVOID *ppobj) { @@ -1592,10 +1606,34 @@ BOOL WINAPI MSI_DllCanUnloadNow(void) return S_FALSE; } -UINT WINAPI MsiEnumRelatedProductsA (LPCSTR lpUpgradeCode, DWORD dwReserved, - DWORD iProductIndex, LPSTR lpProductBuf) +UINT WINAPI MsiEnumRelatedProductsW(LPCWSTR szUpgradeCode, DWORD dwReserved, + DWORD iProductIndex, LPWSTR lpProductBuf) { - FIXME("STUB: (%s, %li %li %s)\n",lpUpgradeCode, dwReserved, iProductIndex, - lpProductBuf); + FIXME("%s %lu %lu %p\n", debugstr_w(szUpgradeCode), dwReserved, + iProductIndex, lpProductBuf); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiEnumRelatedProductsA(LPCSTR szUpgradeCode, DWORD dwReserved, + DWORD iProductIndex, LPSTR lpProductBuf) +{ + FIXME("%s %lu %lu %p\n", debugstr_a(szUpgradeCode), dwReserved, + iProductIndex, lpProductBuf); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiGetFeatureUsageW(LPCWSTR szProduct, LPCWSTR szFeature, + DWORD* pdwUseCount, WORD* pwDateUsed) +{ + FIXME("%s %s %p %p\n",debugstr_w(szProduct), debugstr_w(szFeature), + pdwUseCount, pwDateUsed); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +UINT WINAPI MsiGetFeatureUsageA(LPCSTR szProduct, LPCSTR szFeature, + DWORD* pdwUseCount, WORD* pwDateUsed) +{ + FIXME("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szFeature), + pdwUseCount, pwDateUsed); return ERROR_CALL_NOT_IMPLEMENTED; } diff --git a/reactos/lib/msi/msi.spec b/reactos/lib/msi/msi.spec index e8a98a30582..7b6029ae8f1 100644 --- a/reactos/lib/msi/msi.spec +++ b/reactos/lib/msi/msi.spec @@ -56,8 +56,8 @@ 56 stub MsiGetFeatureInfoW 57 stdcall MsiGetFeatureStateA(long str ptr ptr) 58 stdcall MsiGetFeatureStateW(long wstr ptr ptr) -59 stub MsiGetFeatureUsageA -60 stub MsiGetFeatureUsageW +59 stdcall MsiGetFeatureUsageA(str str ptr ptr) +60 stdcall MsiGetFeatureUsageW(wstr wstr ptr ptr) 61 stub MsiGetFeatureValidStatesA 62 stub MsiGetFeatureValidStatesW 63 stub MsiGetLanguage @@ -134,7 +134,7 @@ 134 stub MsiSetComponentStateA 135 stub MsiSetComponentStateW 136 stdcall MsiSetExternalUIA(ptr long ptr) -137 stub MsiSetExternalUIW +137 stdcall MsiSetExternalUIW(ptr long ptr) 138 stdcall MsiSetFeatureStateA(long str long) 139 stdcall MsiSetFeatureStateW(long wstr long) 140 stub MsiSetInstallLevel @@ -201,8 +201,8 @@ 201 stub MsiDecomposeDescriptorW 202 stub MsiProvideQualifiedComponentExA 203 stub MsiProvideQualifiedComponentExW -204 stdcall MsiEnumRelatedProductsA(str long long str) -205 stub MsiEnumRelatedProductsW +204 stdcall MsiEnumRelatedProductsA(str long long ptr) +205 stdcall MsiEnumRelatedProductsW(wstr long long ptr) 206 stub MsiSetFeatureAttributesA 207 stub MsiSetFeatureAttributesW 208 stub MsiSourceListClearAllA diff --git a/reactos/lib/msi/msipriv.h b/reactos/lib/msi/msipriv.h index ba36dcb2eda..306feca76f8 100644 --- a/reactos/lib/msi/msipriv.h +++ b/reactos/lib/msi/msipriv.h @@ -194,6 +194,8 @@ typedef struct tagMSIPACKAGE UINT loaded_components; struct tagMSIFILE *files; UINT loaded_files; + LPWSTR ActionFormat; + LPWSTR LastAction; } MSIPACKAGE; #define MSIHANDLETYPE_ANY 0 @@ -228,6 +230,8 @@ extern MSIHANDLE alloc_msihandle( MSIOBJECTHDR * ); extern void *alloc_msiobject(UINT type, UINT size, msihandledestructor destroy ); extern void msiobj_addref(MSIOBJECTHDR *); extern int msiobj_release(MSIOBJECTHDR *); +extern void msiobj_lock(MSIOBJECTHDR *); +extern void msiobj_unlock(MSIOBJECTHDR *); extern MSIHANDLE msiobj_findhandle( MSIOBJECTHDR *hdr ); /* add this table to the list of cached tables in the database */ @@ -269,6 +273,7 @@ extern UINT read_raw_stream_data( MSIDATABASE*, LPCWSTR stname, USHORT **pdata, UINT *psz ); extern UINT ACTION_DoTopLevelINSTALL( MSIPACKAGE *, LPCWSTR, LPCWSTR ); extern void ACTION_remove_tracked_tempfiles( MSIPACKAGE* ); +extern void ACTION_free_package_structures( MSIPACKAGE* ); /* record internals */ extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *); diff --git a/reactos/lib/msi/package.c b/reactos/lib/msi/package.c index cad20ed665b..639af427eaa 100644 --- a/reactos/lib/msi/package.c +++ b/reactos/lib/msi/package.c @@ -27,6 +27,7 @@ #include "winreg.h" #include "winnls.h" #include "shlwapi.h" +#include "wingdi.h" #include "wine/debug.h" #include "msi.h" #include "msiquery.h" @@ -53,18 +54,8 @@ void MSI_FreePackage( MSIOBJECTHDR *arg) MSIPACKAGE *package= (MSIPACKAGE*) arg; ACTION_remove_tracked_tempfiles(package); + ACTION_free_package_structures(package); - if (package->features && package->loaded_features > 0) - HeapFree(GetProcessHeap(),0,package->features); - - if (package->folders && package->loaded_folders > 0) - HeapFree(GetProcessHeap(),0,package->folders); - - if (package->components && package->loaded_components > 0) - HeapFree(GetProcessHeap(),0,package->components); - - if (package->files && package->loaded_files > 0) - HeapFree(GetProcessHeap(),0,package->files); msiobj_release( &package->db->hdr ); } @@ -169,9 +160,11 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/prope static VOID set_installer_properties(MSIPACKAGE *package) { WCHAR pth[MAX_PATH]; + WCHAR *ptr; OSVERSIONINFOA OSVersion; DWORD verval; - WCHAR verstr[10], msiver[10]; + WCHAR verstr[10], bufstr[20]; + HDC dc; static const WCHAR cszbs[]={'\\',0}; static const WCHAR CFF[] = @@ -202,6 +195,8 @@ static VOID set_installer_properties(MSIPACKAGE *package) {'A','p','p','D','a','t','a','F','o','l','d','e','r',0}; static const WCHAR SF[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0}; + static const WCHAR SF16[] = +{'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0}; static const WCHAR LADF[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0}; static const WCHAR MPF[] = @@ -210,6 +205,8 @@ static VOID set_installer_properties(MSIPACKAGE *package) {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0}; static const WCHAR WF[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0}; + static const WCHAR WV[] = +{'W','i','n','d','o','w','s','V','o','l','u','m','e',0}; static const WCHAR TF[]= {'T','e','m','p','F','o','l','d','e','r',0}; static const WCHAR szAdminUser[] = @@ -229,12 +226,15 @@ static VOID set_installer_properties(MSIPACKAGE *package) static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 }; static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0}; +/* Screen properties */ + static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0}; + static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0}; + static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0}; + static const WCHAR szScreenFormat[] = {'%','d',0}; /* * Other things I notice set * -ScreenY -ScreenX SystemLanguageID ComputerName UserLanguageID @@ -251,7 +251,6 @@ CaptionHeight BorderTop BorderSide TextHeight -ColorBits RedirectedDllSupport Time Date @@ -313,6 +312,7 @@ Privileged SHGetFolderPathW(NULL,CSIDL_SYSTEM,NULL,0,pth); strcatW(pth,cszbs); MSI_SetPropertyW(package, SF, pth); + MSI_SetPropertyW(package, SF16, pth); SHGetFolderPathW(NULL,CSIDL_LOCAL_APPDATA,NULL,0,pth); strcatW(pth,cszbs); @@ -330,6 +330,12 @@ Privileged strcatW(pth,cszbs); MSI_SetPropertyW(package, WF, pth); + SHGetFolderPathW(NULL,CSIDL_WINDOWS,NULL,0,pth); + ptr = strchrW(pth,'\\'); + if (ptr) + *(ptr+1) = 0; + MSI_SetPropertyW(package, WV, pth); + GetTempPathW(MAX_PATH,pth); MSI_SetPropertyW(package, TF, pth); @@ -357,8 +363,18 @@ Privileged /* just fudge this */ MSI_SetPropertyW(package,szSPL,szSix); - sprintfW( msiver, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION); - MSI_SetPropertyW( package, szVersionMsi, msiver ); + sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION); + MSI_SetPropertyW( package, szVersionMsi, bufstr ); + + /* Screen properties. */ + dc = GetDC(0); + sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, HORZRES ) ); + MSI_SetPropertyW( package, szScreenX, bufstr ); + sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, VERTRES )); + MSI_SetPropertyW( package, szScreenY, bufstr ); + sprintfW( bufstr, szScreenFormat, GetDeviceCaps( dc, BITSPIXEL )); + MSI_SetPropertyW( package, szColorBits, bufstr ); + ReleaseDC(0, dc); } UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) @@ -406,6 +422,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) package->loaded_folders = 0; package->loaded_components= 0; package->loaded_files = 0; + package->ActionFormat = NULL; + package->LastAction = NULL; /* OK, here is where we do a slew of things to the database to * prep for all that is to come as a package */ @@ -747,6 +765,10 @@ UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName, UINT rc; rc = MSI_GetPropertyRow(package, szName, &row); + + if (*pchValueBuf > 0) + szValueBuf[0] = 0; + if (rc == ERROR_SUCCESS) { rc = MSI_RecordGetStringW(row,1,szValueBuf,pchValueBuf); @@ -756,6 +778,9 @@ UINT MSI_GetPropertyW(MSIPACKAGE *package, LPCWSTR szName, if (rc == ERROR_SUCCESS) TRACE("returning %s for property %s\n", debugstr_w(szValueBuf), debugstr_w(szName)); + else if (rc == ERROR_MORE_DATA) + TRACE("need %li sized buffer for %s\n", *pchValueBuf, + debugstr_w(szName)); else { *pchValueBuf = 0; @@ -772,6 +797,9 @@ UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName, UINT rc, len; LPWSTR szwName; + if (*pchValueBuf > 0) + szValueBuf[0] = 0; + len = MultiByteToWideChar( CP_ACP, 0, szName, -1, NULL, 0 ); szwName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); if (!szwName) @@ -788,6 +816,9 @@ UINT MSI_GetPropertyA(MSIPACKAGE *package, LPCSTR szName, if (rc == ERROR_SUCCESS) TRACE("returning %s for property %s\n", debugstr_a(szValueBuf), debugstr_a(szName)); + else if (rc == ERROR_MORE_DATA) + TRACE("need %ld sized buffer for %s\n", *pchValueBuf, + debugstr_a(szName)); else { *pchValueBuf = 0; diff --git a/reactos/lib/msi/query.h b/reactos/lib/msi/query.h index fc8ce425e56..dfe5816936d 100644 --- a/reactos/lib/msi/query.h +++ b/reactos/lib/msi/query.h @@ -52,6 +52,7 @@ #define EXPR_STRCMP 7 #define EXPR_UTF8 8 #define EXPR_WILDCARD 9 +#define EXPR_COL_NUMBER_STRING 10 struct sql_str { LPCWSTR data; diff --git a/reactos/lib/msi/record.c b/reactos/lib/msi/record.c index 3def0974a2b..30cde0f80ef 100644 --- a/reactos/lib/msi/record.c +++ b/reactos/lib/msi/record.c @@ -32,6 +32,7 @@ #include "msipriv.h" #include "objidl.h" #include "winnls.h" +#include "ole2.h" #include "query.h" @@ -77,10 +78,13 @@ MSIRECORD *MSI_CreateRecord( unsigned int cParams ) TRACE("%d\n", cParams); + if( cParams>65535 ) + return NULL; + len = sizeof (MSIRECORD) + sizeof (MSIFIELD)*cParams; rec = alloc_msiobject( MSIHANDLETYPE_RECORD, len, MSI_CloseRecord ); if( rec ) - rec->count = cParams; + rec->count = cParams; return rec; } @@ -111,12 +115,11 @@ unsigned int WINAPI MsiRecordGetFieldCount( MSIHANDLE handle ) rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) - { - ERR("Record not found!\n"); - return 0; - } + return -1; + msiobj_lock( &rec->hdr ); ret = MSI_RecordGetFieldCount( rec ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; @@ -180,7 +183,9 @@ int WINAPI MsiRecordGetInteger( MSIHANDLE handle, unsigned int iField) if( !rec ) return MSI_NULL_INTEGER; + msiobj_lock( &rec->hdr ); ret = MSI_RecordGetInteger( rec, iField ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; @@ -197,12 +202,14 @@ UINT WINAPI MsiRecordClearData( MSIHANDLE handle ) if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); for( i=0; i<=rec->count; i++) { MSI_FreeField( &rec->fields[i] ); rec->fields[i].type = MSIFIELD_NULL; rec->fields[i].u.iVal = 0; } + msiobj_unlock( &rec->hdr ); return ERROR_SUCCESS; } @@ -211,12 +218,12 @@ UINT MSI_RecordSetInteger( MSIRECORD *rec, unsigned int iField, int iVal ) { TRACE("%p %u %d\n", rec, iField, iVal); - if( iField <= rec->count ) - { - MSI_FreeField( &rec->fields[iField] ); - rec->fields[iField].type = MSIFIELD_INT; - rec->fields[iField].u.iVal = iVal; - } + if( iField > rec->count ) + return ERROR_INVALID_PARAMETER; + + MSI_FreeField( &rec->fields[iField] ); + rec->fields[iField].type = MSIFIELD_INT; + rec->fields[iField].u.iVal = iVal; return ERROR_SUCCESS; } @@ -232,7 +239,9 @@ UINT WINAPI MsiRecordSetInteger( MSIHANDLE handle, unsigned int iField, int iVal if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordSetInteger( rec, iField, iVal ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } @@ -258,8 +267,10 @@ BOOL WINAPI MsiRecordIsNull( MSIHANDLE handle, unsigned int iField ) rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) - return ERROR_INVALID_HANDLE; + return 0; + msiobj_lock( &rec->hdr ); ret = MSI_RecordIsNull( rec, iField ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; @@ -289,9 +300,12 @@ UINT MSI_RecordGetStringA(MSIRECORD *rec, unsigned int iField, NULL, 0 , NULL, NULL); WideCharToMultiByte( CP_ACP, 0, rec->fields[iField].u.szwVal, -1, szValue, *pcchValue, NULL, NULL); + if( *pcchValue && len>*pcchValue ) + szValue[*pcchValue-1] = 0; + if( len ) + len--; break; case MSIFIELD_NULL: - len = 1; if( *pcchValue > 0 ) szValue[0] = 0; break; @@ -318,7 +332,9 @@ UINT WINAPI MsiRecordGetStringA(MSIHANDLE handle, unsigned int iField, rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordGetStringA( rec, iField, szValue, pcchValue); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } @@ -385,17 +401,49 @@ UINT WINAPI MsiRecordGetStringW(MSIHANDLE handle, unsigned int iField, if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordGetStringW( rec, iField, szValue, pcchValue ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } -UINT WINAPI MsiRecordDataSize(MSIHANDLE hRecord, unsigned int iField) +UINT MSI_RecordDataSize(MSIRECORD *rec, unsigned int iField) { - FIXME("%ld %d\n", hRecord, iField); + TRACE("%p %d\n", rec, iField); + + if( iField > rec->count ) + return 0; + + switch( rec->fields[iField].type ) + { + case MSIFIELD_INT: + return sizeof (INT); + case MSIFIELD_WSTR: + return lstrlenW( rec->fields[iField].u.szwVal ); + case MSIFIELD_NULL: + break; + } return 0; } +UINT WINAPI MsiRecordDataSize(MSIHANDLE handle, unsigned int iField) +{ + MSIRECORD *rec; + UINT ret; + + TRACE("%ld %d\n", handle, iField); + + rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); + if( !rec ) + return 0; + msiobj_lock( &rec->hdr ); + ret = MSI_RecordDataSize( rec, iField); + msiobj_unlock( &rec->hdr ); + msiobj_release( &rec->hdr ); + return ret; +} + UINT MSI_RecordSetStringA( MSIRECORD *rec, unsigned int iField, LPCSTR szValue ) { LPWSTR str; @@ -426,7 +474,9 @@ UINT WINAPI MsiRecordSetStringA( MSIHANDLE handle, unsigned int iField, LPCSTR s rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordSetStringA( rec, iField, szValue ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } @@ -463,7 +513,9 @@ UINT WINAPI MsiRecordSetStringW( MSIHANDLE handle, unsigned int iField, LPCWSTR if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordSetStringW( rec, iField, szValue ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } @@ -480,16 +532,133 @@ UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szRes return ERROR_CALL_NOT_IMPLEMENTED; } -UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename) +/* read the data in a file into an IStream */ +UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm) { - FIXME("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename)); - return ERROR_CALL_NOT_IMPLEMENTED; + DWORD sz, szHighWord = 0, read; + HANDLE handle; + HGLOBAL hGlob = 0; + HRESULT hr; + ULARGE_INTEGER ulSize; + + TRACE("reading %s\n", debugstr_w(szFile)); + + /* read the file into memory */ + handle = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if( handle == INVALID_HANDLE_VALUE ) + return GetLastError(); + sz = GetFileSize(handle, &szHighWord); + if( sz != INVALID_FILE_SIZE && szHighWord == 0 ) + { + hGlob = GlobalAlloc(GMEM_FIXED, sz); + if( hGlob ) + { + BOOL r = ReadFile(handle, hGlob, sz, &read, NULL); + if( !r ) + { + GlobalFree(hGlob); + hGlob = 0; + } + } + } + CloseHandle(handle); + if( !hGlob ) + return ERROR_FUNCTION_FAILED; + + /* make a stream out of it, and set the correct file size */ + hr = CreateStreamOnHGlobal(hGlob, TRUE, pstm); + if( FAILED( hr ) ) + { + GlobalFree(hGlob); + return ERROR_FUNCTION_FAILED; + } + + /* set the correct size - CreateStreamOnHGlobal screws it up */ + ulSize.QuadPart = sz; + IStream_SetSize(*pstm, ulSize); + + TRACE("read %s, %ld bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm); + + return ERROR_SUCCESS; } -UINT WINAPI MsiRecordSetStreamW(MSIHANDLE hRecord, unsigned int iField, LPCWSTR szFilename) +UINT MSI_RecordSetStreamW(MSIRECORD *rec, unsigned int iField, LPCWSTR szFilename) { - FIXME("%ld %d %s\n", hRecord, iField, debugstr_w(szFilename)); - return ERROR_CALL_NOT_IMPLEMENTED; + IStream *stm = NULL; + HRESULT r; + + if( (iField == 0) || (iField > rec->count) ) + return ERROR_INVALID_PARAMETER; + + /* no filename means we should seek back to the start of the stream */ + if( !szFilename ) + { + LARGE_INTEGER ofs; + ULARGE_INTEGER cur; + + if( rec->fields[iField].type != MSIFIELD_STREAM ) + return ERROR_INVALID_FIELD; + + stm = rec->fields[iField].u.stream; + if( !stm ) + return ERROR_INVALID_FIELD; + + ofs.QuadPart = 0; + r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur ); + if( FAILED( r ) ) + return ERROR_FUNCTION_FAILED; + } + else + { + /* read the file into a stream and save the stream in the record */ + r = RECORD_StreamFromFile(szFilename, &stm); + if( r != ERROR_SUCCESS ) + return r; + + /* if all's good, store it in the record */ + MSI_FreeField( &rec->fields[iField] ); + rec->fields[iField].type = MSIFIELD_STREAM; + rec->fields[iField].u.stream = stm; + } + + return ERROR_SUCCESS; +} + +UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename) +{ + LPWSTR wstr = NULL; + UINT ret, len; + + TRACE("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename)); + + if( szFilename ) + { + len = MultiByteToWideChar(CP_ACP,0,szFilename,-1,NULL,0); + wstr = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP,0,szFilename,-1,wstr,len); + } + ret = MsiRecordSetStreamW(hRecord, iField, wstr); + HeapFree(GetProcessHeap(),0,wstr); + + return ret; +} + +UINT WINAPI MsiRecordSetStreamW(MSIHANDLE handle, unsigned int iField, LPCWSTR szFilename) +{ + MSIRECORD *rec; + UINT ret; + + TRACE("%ld %d %s\n", handle, iField, debugstr_w(szFilename)); + + rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); + if( !rec ) + return ERROR_INVALID_HANDLE; + + msiobj_lock( &rec->hdr ); + ret = MSI_RecordSetStreamW( rec, iField, szFilename ); + msiobj_unlock( &rec->hdr ); + msiobj_release( &rec->hdr ); + return ret; } UINT MSI_RecordReadStream(MSIRECORD *rec, unsigned int iField, char *buf, DWORD *sz) @@ -500,18 +669,18 @@ UINT MSI_RecordReadStream(MSIRECORD *rec, unsigned int iField, char *buf, DWORD TRACE("%p %d %p %p\n", rec, iField, buf, sz); - if( iField > rec->count ) - return ERROR_INVALID_FIELD; + if( !sz ) + return ERROR_INVALID_PARAMETER; + + if( iField > rec->count) + return ERROR_INVALID_PARAMETER; if( rec->fields[iField].type != MSIFIELD_STREAM ) - { - *sz = 0; - return ERROR_INVALID_FIELD; - } + return ERROR_INVALID_DATATYPE; stm = rec->fields[iField].u.stream; if( !stm ) - return ERROR_INVALID_FIELD; + return ERROR_INVALID_PARAMETER; /* if there's no buffer pointer, calculate the length to the end */ if( !buf ) @@ -554,7 +723,9 @@ UINT WINAPI MsiRecordReadStream(MSIHANDLE handle, unsigned int iField, char *buf rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD ); if( !rec ) return ERROR_INVALID_HANDLE; + msiobj_lock( &rec->hdr ); ret = MSI_RecordReadStream( rec, iField, buf, sz ); + msiobj_unlock( &rec->hdr ); msiobj_release( &rec->hdr ); return ret; } diff --git a/reactos/lib/msi/sql.tab.c b/reactos/lib/msi/sql.tab.c index dafec32332e..eb700d78e53 100644 --- a/reactos/lib/msi/sql.tab.c +++ b/reactos/lib/msi/sql.tab.c @@ -1,2180 +1,2496 @@ -/* A Bison parser, made from ./sql.y - by GNU bison 1.35. */ - -#define YYBISON 1 /* Identify Bison output. */ - -#define yyparse SQL_parse -#define yylex SQL_lex -#define yyerror SQL_error -#define yylval SQL_lval -#define yychar SQL_char -#define yydebug SQL_debug -#define yynerrs SQL_nerrs -# define TK_ABORT 257 -# define TK_AFTER 258 -# define TK_AGG_FUNCTION 259 -# define TK_ALL 260 -# define TK_AND 261 -# define TK_AS 262 -# define TK_ASC 263 -# define TK_BEFORE 264 -# define TK_BEGIN 265 -# define TK_BETWEEN 266 -# define TK_BITAND 267 -# define TK_BITNOT 268 -# define TK_BITOR 269 -# define TK_BY 270 -# define TK_CASCADE 271 -# define TK_CASE 272 -# define TK_CHAR 273 -# define TK_CHECK 274 -# define TK_CLUSTER 275 -# define TK_COLLATE 276 -# define TK_COLUMN 277 -# define TK_COMMA 278 -# define TK_COMMENT 279 -# define TK_COMMIT 280 -# define TK_CONCAT 281 -# define TK_CONFLICT 282 -# define TK_CONSTRAINT 283 -# define TK_COPY 284 -# define TK_CREATE 285 -# define TK_DEFAULT 286 -# define TK_DEFERRABLE 287 -# define TK_DEFERRED 288 -# define TK_DELETE 289 -# define TK_DELIMITERS 290 -# define TK_DESC 291 -# define TK_DISTINCT 292 -# define TK_DOT 293 -# define TK_DROP 294 -# define TK_EACH 295 -# define TK_ELSE 296 -# define TK_END 297 -# define TK_END_OF_FILE 298 -# define TK_EQ 299 -# define TK_EXCEPT 300 -# define TK_EXPLAIN 301 -# define TK_FAIL 302 -# define TK_FLOAT 303 -# define TK_FOR 304 -# define TK_FOREIGN 305 -# define TK_FROM 306 -# define TK_FUNCTION 307 -# define TK_GE 308 -# define TK_GLOB 309 -# define TK_GROUP 310 -# define TK_GT 311 -# define TK_HAVING 312 -# define TK_HOLD 313 -# define TK_IGNORE 314 -# define TK_ILLEGAL 315 -# define TK_IMMEDIATE 316 -# define TK_IN 317 -# define TK_INDEX 318 -# define TK_INITIALLY 319 -# define TK_ID 320 -# define TK_INSERT 321 -# define TK_INSTEAD 322 -# define TK_INT 323 -# define TK_INTEGER 324 -# define TK_INTERSECT 325 -# define TK_INTO 326 -# define TK_IS 327 -# define TK_ISNULL 328 -# define TK_JOIN 329 -# define TK_JOIN_KW 330 -# define TK_KEY 331 -# define TK_LE 332 -# define TK_LIKE 333 -# define TK_LIMIT 334 -# define TK_LONG 335 -# define TK_LONGCHAR 336 -# define TK_LP 337 -# define TK_LSHIFT 338 -# define TK_LT 339 -# define TK_LOCALIZABLE 340 -# define TK_MATCH 341 -# define TK_MINUS 342 -# define TK_NE 343 -# define TK_NOT 344 -# define TK_NOTNULL 345 -# define TK_NULL 346 -# define TK_OBJECT 347 -# define TK_OF 348 -# define TK_OFFSET 349 -# define TK_ON 350 -# define TK_OR 351 -# define TK_ORACLE_OUTER_JOIN 352 -# define TK_ORDER 353 -# define TK_PLUS 354 -# define TK_PRAGMA 355 -# define TK_PRIMARY 356 -# define TK_RAISE 357 -# define TK_REFERENCES 358 -# define TK_REM 359 -# define TK_REPLACE 360 -# define TK_RESTRICT 361 -# define TK_ROLLBACK 362 -# define TK_ROW 363 -# define TK_RP 364 -# define TK_RSHIFT 365 -# define TK_SELECT 366 -# define TK_SEMI 367 -# define TK_SET 368 -# define TK_SHORT 369 -# define TK_SLASH 370 -# define TK_SPACE 371 -# define TK_STAR 372 -# define TK_STATEMENT 373 -# define TK_STRING 374 -# define TK_TABLE 375 -# define TK_TEMP 376 -# define TK_THEN 377 -# define TK_TRANSACTION 378 -# define TK_TRIGGER 379 -# define TK_UMINUS 380 -# define TK_UNCLOSED_STRING 381 -# define TK_UNION 382 -# define TK_UNIQUE 383 -# define TK_UPDATE 384 -# define TK_UPLUS 385 -# define TK_USING 386 -# define TK_VACUUM 387 -# define TK_VALUES 388 -# define TK_VIEW 389 -# define TK_WHEN 390 -# define TK_WHERE 391 -# define TK_WILDCARD 392 -# define END_OF_FILE 393 -# define ILLEGAL 394 -# define SPACE 395 -# define UNCLOSED_STRING 396 -# define COMMENT 397 -# define FUNCTION 398 -# define COLUMN 399 - -#line 1 "./sql.y" - - -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2002-2004 Mike McCormack for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "config.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "query.h" -#include "wine/debug.h" -#include "wine/unicode.h" - -#define YYLEX_PARAM info -#define YYPARSE_PARAM info - -extern int SQL_error(const char *str); - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - -typedef struct tag_SQL_input -{ - MSIDATABASE *db; - LPCWSTR command; - DWORD n, len; - MSIVIEW **view; /* view structure for the resulting query */ -} SQL_input; - -static LPWSTR SQL_getstring( struct sql_str *str ); -static INT SQL_getint( SQL_input *sql ); -static int SQL_lex( void *SQL_lval, SQL_input *info); - -static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, - string_list *columns ); -static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, - string_list *columns ); - -static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, - string_list *keys); - -static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r ); -static struct expr * EXPR_column( LPWSTR ); -static struct expr * EXPR_ival( struct sql_str *); -static struct expr * EXPR_sval( struct sql_str *); -static struct expr * EXPR_wildcard(void); - - -#line 73 "./sql.y" -#ifndef YYSTYPE -typedef union -{ - struct sql_str str; - LPWSTR string; - string_list *column_list; - value_list *val_list; - MSIVIEW *query; - struct expr *expr; - USHORT column_type; - create_col_info *column_info; - column_assignment update_col_info; -} yystype; -# define YYSTYPE yystype -# define YYSTYPE_IS_TRIVIAL 1 -#endif -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - - - -#define YYFINAL 121 -#define YYFLAG -32768 -#define YYNTBASE 147 - -/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ -#define YYTRANSLATE(x) ((unsigned)(x) <= 400 ? yytranslate[x] : 171) - -/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ -static const short yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146 -}; - -#if YYDEBUG -static const short yyprhs[] = -{ - 0, 0, 2, 4, 6, 8, 19, 31, 38, 46, - 53, 58, 63, 66, 68, 71, 73, 77, 79, 84, - 86, 88, 90, 92, 94, 96, 101, 103, 107, 112, - 114, 118, 120, 123, 128, 132, 136, 140, 144, 148, - 152, 156, 160, 164, 168, 172, 177, 179, 181, 183, - 187, 189, 193, 197, 199, 201, 203, 205, 209, 211, - 213, 215 -}; -static const short yyrhs[] = -{ - 157, 0, 149, 0, 148, 0, 150, 0, 67, 72, - 169, 83, 159, 110, 134, 83, 163, 110, 0, 67, - 72, 169, 83, 159, 110, 134, 83, 163, 110, 122, - 0, 31, 121, 169, 83, 151, 110, 0, 31, 121, - 169, 83, 151, 110, 59, 0, 130, 169, 114, 164, - 137, 161, 0, 152, 102, 77, 159, 0, 152, 24, - 168, 153, 0, 168, 153, 0, 154, 0, 154, 86, - 0, 155, 0, 155, 90, 92, 0, 19, 0, 19, - 83, 156, 110, 0, 82, 0, 115, 0, 69, 0, - 81, 0, 93, 0, 70, 0, 158, 99, 16, 159, - 0, 158, 0, 112, 159, 160, 0, 112, 38, 159, - 160, 0, 168, 0, 168, 24, 159, 0, 118, 0, - 52, 169, 0, 52, 169, 137, 161, 0, 83, 161, - 110, 0, 167, 45, 167, 0, 161, 7, 161, 0, - 161, 97, 161, 0, 167, 45, 162, 0, 167, 57, - 162, 0, 167, 85, 162, 0, 167, 78, 162, 0, - 167, 54, 162, 0, 167, 89, 162, 0, 167, 73, - 92, 0, 167, 73, 90, 92, 0, 167, 0, 166, - 0, 166, 0, 163, 24, 166, 0, 165, 0, 165, - 24, 164, 0, 168, 45, 166, 0, 70, 0, 120, - 0, 138, 0, 168, 0, 169, 39, 170, 0, 170, - 0, 170, 0, 66, 0, 120, 0 -}; - -#endif - -#if YYDEBUG -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const short yyrline[] = -{ - 0, 141, 147, 152, 157, 164, 173, 183, 194, 206, - 217, 227, 247, 258, 263, 270, 275, 281, 286, 290, - 294, 298, 302, 306, 312, 323, 335, 338, 353, 370, - 384, 397, 403, 415, 433, 438, 442, 446, 450, 454, - 458, 462, 466, 470, 474, 478, 484, 486, 489, 502, - 517, 519, 527, 543, 548, 552, 558, 565, 570, 576, - 583, 588 -}; -#endif - - -#if (YYDEBUG) || defined YYERROR_VERBOSE - -/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ -static const char *const yytname[] = -{ - "$", "error", "$undefined.", "TK_ABORT", "TK_AFTER", "TK_AGG_FUNCTION", - "TK_ALL", "TK_AND", "TK_AS", "TK_ASC", "TK_BEFORE", "TK_BEGIN", - "TK_BETWEEN", "TK_BITAND", "TK_BITNOT", "TK_BITOR", "TK_BY", - "TK_CASCADE", "TK_CASE", "TK_CHAR", "TK_CHECK", "TK_CLUSTER", - "TK_COLLATE", "TK_COLUMN", "TK_COMMA", "TK_COMMENT", "TK_COMMIT", - "TK_CONCAT", "TK_CONFLICT", "TK_CONSTRAINT", "TK_COPY", "TK_CREATE", - "TK_DEFAULT", "TK_DEFERRABLE", "TK_DEFERRED", "TK_DELETE", - "TK_DELIMITERS", "TK_DESC", "TK_DISTINCT", "TK_DOT", "TK_DROP", - "TK_EACH", "TK_ELSE", "TK_END", "TK_END_OF_FILE", "TK_EQ", "TK_EXCEPT", - "TK_EXPLAIN", "TK_FAIL", "TK_FLOAT", "TK_FOR", "TK_FOREIGN", "TK_FROM", - "TK_FUNCTION", "TK_GE", "TK_GLOB", "TK_GROUP", "TK_GT", "TK_HAVING", - "TK_HOLD", "TK_IGNORE", "TK_ILLEGAL", "TK_IMMEDIATE", "TK_IN", - "TK_INDEX", "TK_INITIALLY", "TK_ID", "TK_INSERT", "TK_INSTEAD", - "TK_INT", "TK_INTEGER", "TK_INTERSECT", "TK_INTO", "TK_IS", "TK_ISNULL", - "TK_JOIN", "TK_JOIN_KW", "TK_KEY", "TK_LE", "TK_LIKE", "TK_LIMIT", - "TK_LONG", "TK_LONGCHAR", "TK_LP", "TK_LSHIFT", "TK_LT", - "TK_LOCALIZABLE", "TK_MATCH", "TK_MINUS", "TK_NE", "TK_NOT", - "TK_NOTNULL", "TK_NULL", "TK_OBJECT", "TK_OF", "TK_OFFSET", "TK_ON", - "TK_OR", "TK_ORACLE_OUTER_JOIN", "TK_ORDER", "TK_PLUS", "TK_PRAGMA", - "TK_PRIMARY", "TK_RAISE", "TK_REFERENCES", "TK_REM", "TK_REPLACE", - "TK_RESTRICT", "TK_ROLLBACK", "TK_ROW", "TK_RP", "TK_RSHIFT", - "TK_SELECT", "TK_SEMI", "TK_SET", "TK_SHORT", "TK_SLASH", "TK_SPACE", - "TK_STAR", "TK_STATEMENT", "TK_STRING", "TK_TABLE", "TK_TEMP", - "TK_THEN", "TK_TRANSACTION", "TK_TRIGGER", "TK_UMINUS", - "TK_UNCLOSED_STRING", "TK_UNION", "TK_UNIQUE", "TK_UPDATE", "TK_UPLUS", - "TK_USING", "TK_VACUUM", "TK_VALUES", "TK_VIEW", "TK_WHEN", "TK_WHERE", - "TK_WILDCARD", "END_OF_FILE", "ILLEGAL", "SPACE", "UNCLOSED_STRING", - "COMMENT", "FUNCTION", "COLUMN", "AGG_FUNCTION.", "onequery", - "oneinsert", "onecreate", "oneupdate", "table_def", "column_def", - "column_type", "data_type_l", "data_type", "data_count", "oneselect", - "unorderedsel", "selcollist", "from", "expr", "val", "constlist", - "update_assign_list", "column_assignment", "const_val", "column_val", - "column", "table", "string_or_id", 0 -}; -#endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const short yyr1[] = -{ - 0, 147, 147, 147, 147, 148, 148, 149, 149, 150, - 151, 152, 152, 153, 153, 154, 154, 155, 155, 155, - 155, 155, 155, 155, 156, 157, 157, 158, 158, 159, - 159, 159, 160, 160, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 161, 161, 162, 162, 163, 163, - 164, 164, 165, 166, 166, 166, 167, 168, 168, 169, - 170, 170 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const short yyr2[] = -{ - 0, 1, 1, 1, 1, 10, 11, 6, 7, 6, - 4, 4, 2, 1, 2, 1, 3, 1, 4, 1, - 1, 1, 1, 1, 1, 4, 1, 3, 4, 1, - 3, 1, 2, 4, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 4, 1, 1, 1, 3, - 1, 3, 3, 1, 1, 1, 1, 3, 1, 1, - 1, 1 -}; - -/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE - doesn't specify something else to do. Zero means the default is an - error. */ -static const short yydefact[] = -{ - 0, 0, 0, 0, 0, 3, 2, 4, 1, 26, - 0, 0, 0, 60, 31, 61, 0, 29, 0, 58, - 0, 59, 0, 0, 0, 0, 0, 27, 0, 0, - 0, 0, 0, 0, 28, 32, 30, 57, 0, 50, - 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 0, 0, 17, 21, 22, 19, 23, 20, 12, - 13, 15, 0, 0, 33, 0, 56, 9, 51, 53, - 54, 55, 52, 8, 0, 0, 0, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11, 10, 24, 0, 16, 0, 34, 36, 37, 54, - 38, 47, 35, 42, 46, 39, 0, 44, 41, 40, - 43, 18, 0, 48, 45, 0, 5, 49, 6, 0, - 0, 0 -}; - -static const short yydefgoto[] = -{ - 119, 5, 6, 7, 42, 43, 59, 60, 61, 93, - 8, 9, 16, 27, 64, 100, 112, 38, 39, 101, - 65, 66, 18, 19 -}; - -static const short yypact[] = -{ - -30, -113, -49, -34, -50,-32768,-32768,-32768,-32768, -79, - -50, -50, -52,-32768,-32768,-32768, -25, 4, -10, 0, - -72,-32768, 30, -36, -35, -25, -50,-32768, -52, -50, - -50, -52, -50, -52,-32768, -87,-32768,-32768, -84, 33, - 13,-32768, -51, -15, -17, -41, -53, -53, -50, -58, - 1, -50, -5, -8,-32768,-32768,-32768,-32768,-32768,-32768, - -13, -9, -57, -53, -4, 47,-32768, -4,-32768,-32768, - -32768,-32768,-32768,-32768, -17, -52, 18,-32768, -3, 11, - -7, -53, -53, -59, -59, -59, -71, -59, -59, -59, - -32768,-32768,-32768, -14,-32768, -58,-32768, -4, -4, 56, - -32768,-32768,-32768,-32768,-32768,-32768, 5,-32768,-32768,-32768, - -32768,-32768, -19,-32768,-32768, -58, -23,-32768,-32768, 102, - 108,-32768 -}; - -static const short yypgoto[] = -{ - -32768,-32768,-32768,-32768,-32768,-32768, 40,-32768,-32768,-32768, - -32768,-32768, 10, 93, -37, 28,-32768, 71,-32768, -32, - 22, 3, 14, 45 -}; - - -#define YYLAST 136 - - -static const short yytable[] = -{ - 81, 1, 53, 81, 12, 115, 17, 13, 10, 51, - 67, 69, 69, 13, 13, 17, 13, 72, 20, 106, - 22, 107, 25, 11, 23, 24, 80, 26, 28, 29, - 63, 17, 13, 40, 17, 44, 17, 2, 36, -59, - 35, 41, 30, 45, 97, 98, 31, 32, 33, 21, - 46, 40, 54, 47, 74, 21, 21, 48, 49, 50, - 73, 99, 70, 113, 55, 56, 14, 15, 15, 62, - 15, 21, 75, 77, 37, 76, 57, 79, 17, 71, - 71, 78, 3, 117, 14, 91, 15, 52, 92, 94, - 82, 116, 83, 82, 95, -61, 111, 114, 58, 118, - 4, 84, 120, 96, 85, 102, 104, 104, 121, 104, - 104, 104, 103, 105, 90, 108, 109, 110, 34, 68, - 86, 0, 0, 0, 0, 87, 0, 0, 0, 0, - 0, 0, 88, 0, 0, 0, 89 -}; - -static const short yycheck[] = -{ - 7, 31, 19, 7, 38, 24, 3, 66, 121, 24, - 47, 70, 70, 66, 66, 12, 66, 49, 4, 90, - 99, 92, 12, 72, 10, 11, 63, 52, 24, 39, - 83, 28, 66, 30, 31, 32, 33, 67, 28, 39, - 26, 31, 114, 33, 81, 82, 16, 83, 83, 4, - 137, 48, 69, 137, 51, 10, 11, 24, 45, 110, - 59, 120, 120, 95, 81, 82, 118, 120, 120, 110, - 120, 26, 77, 86, 29, 83, 93, 134, 75, 138, - 138, 90, 112, 115, 118, 75, 120, 102, 70, 92, - 97, 110, 45, 97, 83, 39, 110, 92, 115, 122, - 130, 54, 0, 110, 57, 83, 84, 85, 0, 87, - 88, 89, 84, 85, 74, 87, 88, 89, 25, 48, - 73, -1, -1, -1, -1, 78, -1, -1, -1, -1, - -1, -1, 85, -1, -1, -1, 89 -}; -#define YYPURE 1 - -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/bison/bison.simple" - -/* Skeleton output parser for bison, - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* This is the parser code that is written into each bison parser when - the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free -# endif -#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ - - -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - short yyss; - YYSTYPE yyvs; -# if YYLSP_NEEDED - YYLTYPE yyls; -# endif -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# if YYLSP_NEEDED -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAX) -# else -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAX) -# endif - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - register YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - - -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 -#define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ -#define YYFAIL goto yyerrlab -#define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yychar1 = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror ("syntax error: cannot back up"); \ - YYERROR; \ - } \ -while (0) - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). - - When YYLLOC_DEFAULT is run, CURRENT is set the location of the - first token. By default, to implement support for ranges, extend - its range to the last symbol. */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#if YYPURE -# if YYLSP_NEEDED -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval, &yylloc) -# endif -# else /* !YYLSP_NEEDED */ -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval) -# endif -# endif /* !YYLSP_NEEDED */ -#else /* !YYPURE */ -# define YYLEX yylex () -#endif /* !YYPURE */ - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -#endif /* !YYDEBUG */ - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#if YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - -#ifdef YYERROR_VERBOSE - -# ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) -yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif -{ - register const char *yys = yystr; - - while (*yys++ != '\0') - continue; - - return yys - yystr - 1; -} -# endif -# endif - -# ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -# if defined (__STDC__) || defined (__cplusplus) -yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif -{ - register char *yyd = yydest; - register const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif -#endif - -#line 315 "/usr/share/bison/bison.simple" - - -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ - -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -# define YYPARSE_PARAM_DECL -# else -# define YYPARSE_PARAM_ARG YYPARSE_PARAM -# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -# endif -#else /* !YYPARSE_PARAM */ -# define YYPARSE_PARAM_ARG -# define YYPARSE_PARAM_DECL -#endif /* !YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -# ifdef YYPARSE_PARAM -int yyparse (void *); -# else -int yyparse (void); -# endif -#endif - -/* YY_DECL_VARIABLES -- depending whether we use a pure parser, - variables are global, or local to YYPARSE. */ - -#define YY_DECL_NON_LSP_VARIABLES \ -/* The lookahead symbol. */ \ -int yychar; \ - \ -/* The semantic value of the lookahead symbol. */ \ -YYSTYPE yylval; \ - \ -/* Number of parse errors so far. */ \ -int yynerrs; - -#if YYLSP_NEEDED -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES \ - \ -/* Location data for the lookahead symbol. */ \ -YYLTYPE yylloc; -#else -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES -#endif - - -/* If nonreentrant, generate the variables here. */ - -#if !YYPURE -YY_DECL_VARIABLES -#endif /* !YYPURE */ - -int -yyparse (YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - /* If reentrant, generate the variables here. */ -#if YYPURE - YY_DECL_VARIABLES -#endif /* !YYPURE */ - - register int yystate; - register int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ - int yychar1 = 0; - - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; - register short *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; - -#if YYLSP_NEEDED - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; -#endif - -#if YYLSP_NEEDED -# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else -# define YYPOPSTACK (yyvsp--, yyssp--) -#endif - - YYSIZE_T yystacksize = YYINITDEPTH; - - - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; -#if YYLSP_NEEDED - YYLTYPE yyloc; -#endif - - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; -#if YYLSP_NEEDED - yylsp = yyls; -#endif - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyssp >= yyss + yystacksize - 1) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. */ -# if YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - yyls = yyls1; -# else - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); -# endif - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyoverflowlab; -# else - /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - goto yyoverflowlab; - yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) - yystacksize = YYMAXDEPTH; - - { - short *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); -# if YYLSP_NEEDED - YYSTACK_RELOCATE (yyls); -# endif -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; -#if YYLSP_NEEDED - yylsp = yyls + yysize - 1; -#endif - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyssp >= yyss + yystacksize - 1) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ - - /* First try to decide what to do without reference to lookahead token. */ - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ - { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yychar1 = YYTRANSLATE (yychar); - -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables - which are defined only if `YYDEBUG' is set. */ - if (yydebug) - { - YYFPRINTF (stderr, "Next token is %d (%s", - yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise - meaning of a token, for further debugging info. */ -# ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -# endif - YYFPRINTF (stderr, ")\n"); - } -#endif - } - - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) - goto yydefault; - - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrlab; - - if (yyn == YYFINAL) - YYACCEPT; - - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %d (%s), ", - yychar, yytname[yychar1])); - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; -#if YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - yystate = yyn; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to the semantic value of - the lookahead token. This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - -#if YYLSP_NEEDED - /* Similarly for the default location. Let the user run additional - commands if for instance locations are ranges. */ - yyloc = yylsp[1-yylen]; - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); -#endif - -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables which - are defined only if `YYDEBUG' is set. */ - if (yydebug) - { - int yyi; - - YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif - - switch (yyn) { - -case 1: -#line 143 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - *sql->view = yyvsp[0].query; - ; - break;} -case 2: -#line 148 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - *sql->view = yyvsp[0].query; - ; - break;} -case 3: -#line 153 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - *sql->view = yyvsp[0].query; - ; - break;} -case 4: -#line 158 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - *sql->view = yyvsp[0].query; - ; - break;} -case 5: -#line 166 "./sql.y" -{ - SQL_input *sql = (SQL_input*) info; - MSIVIEW *insert = NULL; - - INSERT_CreateView( sql->db, &insert, yyvsp[-7].string, yyvsp[-5].column_list, yyvsp[-1].val_list, FALSE ); - yyval.query = insert; - ; - break;} -case 6: -#line 174 "./sql.y" -{ - SQL_input *sql = (SQL_input*) info; - MSIVIEW *insert = NULL; - - INSERT_CreateView( sql->db, &insert, yyvsp[-8].string, yyvsp[-6].column_list, yyvsp[-2].val_list, TRUE ); - yyval.query = insert; - ; - break;} -case 7: -#line 185 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - MSIVIEW *create = NULL; - - if( !yyvsp[-1].column_info ) - YYABORT; - CREATE_CreateView( sql->db, &create, yyvsp[-3].string, yyvsp[-1].column_info, FALSE ); - yyval.query = create; - ; - break;} -case 8: -#line 195 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - MSIVIEW *create = NULL; - - if( !yyvsp[-2].column_info ) - YYABORT; - CREATE_CreateView( sql->db, &create, yyvsp[-4].string, yyvsp[-2].column_info, TRUE ); - yyval.query = create; - ; - break;} -case 9: -#line 208 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - MSIVIEW *update = NULL; - - UPDATE_CreateView( sql->db, &update, yyvsp[-4].string, &yyvsp[-2].update_col_info, yyvsp[0].expr ); - yyval.query = update; - ; - break;} -case 10: -#line 219 "./sql.y" -{ - if( SQL_MarkPrimaryKeys( yyvsp[-3].column_info, yyvsp[0].column_list ) ) - yyval.column_info = yyvsp[-3].column_info; - else - yyval.column_info = NULL; - ; - break;} -case 11: -#line 229 "./sql.y" -{ - create_col_info *ci; - - for( ci = yyvsp[-3].column_info; ci->next; ci = ci->next ) - ; - - ci->next = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info ); - if( !ci->next ) - { - /* FIXME: free $1 */ - YYABORT; - } - ci->next->colname = yyvsp[-1].string; - ci->next->type = yyvsp[0].column_type; - ci->next->next = NULL; - - yyval.column_info = yyvsp[-3].column_info; - ; - break;} -case 12: -#line 248 "./sql.y" -{ - yyval.column_info = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info ); - if( ! yyval.column_info ) - YYABORT; - yyval.column_info->colname = yyvsp[-1].string; - yyval.column_info->type = yyvsp[0].column_type; - yyval.column_info->next = NULL; - ; - break;} -case 13: -#line 260 "./sql.y" -{ - yyval.column_type = yyvsp[0].column_type | MSITYPE_VALID; - ; - break;} -case 14: -#line 264 "./sql.y" -{ - FIXME("LOCALIZABLE ignored\n"); - yyval.column_type = yyvsp[-1].column_type | MSITYPE_VALID; - ; - break;} -case 15: -#line 272 "./sql.y" -{ - yyval.column_type |= MSITYPE_NULLABLE; - ; - break;} -case 16: -#line 276 "./sql.y" -{ - yyval.column_type = yyvsp[-2].column_type; - ; - break;} -case 17: -#line 283 "./sql.y" -{ - yyval.column_type = MSITYPE_STRING | 1; - ; - break;} -case 18: -#line 287 "./sql.y" -{ - yyval.column_type = MSITYPE_STRING | 0x400 | yyvsp[-1].column_type; - ; - break;} -case 19: -#line 291 "./sql.y" -{ - yyval.column_type = 2; - ; - break;} -case 20: -#line 295 "./sql.y" -{ - yyval.column_type = 2; - ; - break;} -case 21: -#line 299 "./sql.y" -{ - yyval.column_type = 2; - ; - break;} -case 22: -#line 303 "./sql.y" -{ - yyval.column_type = 4; - ; - break;} -case 23: -#line 307 "./sql.y" -{ - yyval.column_type = 0; - ; - break;} -case 24: -#line 314 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - int val = SQL_getint(sql); - if( ( val > 255 ) || ( val < 0 ) ) - YYABORT; - yyval.column_type = val; - ; - break;} -case 25: -#line 325 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - - if( !yyvsp[-3].query ) - YYABORT; - if( yyvsp[0].column_list ) - yyval.query = do_order_by( sql->db, yyvsp[-3].query, yyvsp[0].column_list ); - else - yyval.query = yyvsp[-3].query; - ; - break;} -case 27: -#line 340 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - if( !yyvsp[0].query ) - YYABORT; - if( yyvsp[-1].column_list ) - { - yyval.query = do_one_select( sql->db, yyvsp[0].query, yyvsp[-1].column_list ); - if( !yyval.query ) - YYABORT; - } - else - yyval.query = yyvsp[0].query; - ; - break;} -case 28: -#line 354 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - MSIVIEW *view = yyvsp[0].query; - - if( !view ) - YYABORT; - if( yyvsp[-1].column_list ) - { - view = do_one_select( sql->db, view, yyvsp[-1].column_list ); - if( !view ) - YYABORT; - } - DISTINCT_CreateView( sql->db, & yyval.query, view ); - ; - break;} -case 29: -#line 372 "./sql.y" -{ - string_list *list; - - list = HeapAlloc( GetProcessHeap(), 0, sizeof *list ); - if( !list ) - YYABORT; - list->string = yyvsp[0].string; - list->next = NULL; - - yyval.column_list = list; - TRACE("Collist %s\n",debugstr_w(yyval.column_list->string)); - ; - break;} -case 30: -#line 385 "./sql.y" -{ - string_list *list; - - list = HeapAlloc( GetProcessHeap(), 0, sizeof *list ); - if( !list ) - YYABORT; - list->string = yyvsp[-2].string; - list->next = yyvsp[0].column_list; - - yyval.column_list = list; - TRACE("From table: %s\n",debugstr_w(yyval.column_list->string)); - ; - break;} -case 31: -#line 398 "./sql.y" -{ - yyval.column_list = NULL; - ; - break;} -case 32: -#line 405 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - UINT r; - - yyval.query = NULL; - TRACE("From table: %s\n",debugstr_w(yyvsp[0].string)); - r = TABLE_CreateView( sql->db, yyvsp[0].string, & yyval.query ); - if( r != ERROR_SUCCESS ) - YYABORT; - ; - break;} -case 33: -#line 416 "./sql.y" -{ - SQL_input* sql = (SQL_input*) info; - MSIVIEW *view = NULL; - UINT r; - - yyval.query = NULL; - TRACE("From table: %s\n",debugstr_w(yyvsp[-2].string)); - r = TABLE_CreateView( sql->db, yyvsp[-2].string, &view ); - if( r != ERROR_SUCCESS ) - YYABORT; - r = WHERE_CreateView( sql->db, &view, view, yyvsp[0].expr ); - if( r != ERROR_SUCCESS ) - YYABORT; - yyval.query = view; - ; - break;} -case 34: -#line 435 "./sql.y" -{ - yyval.expr = yyvsp[-1].expr; - ; - break;} -case 35: -#line 439 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr ); - ; - break;} -case 36: -#line 443 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_AND, yyvsp[0].expr ); - ; - break;} -case 37: -#line 447 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_OR, yyvsp[0].expr ); - ; - break;} -case 38: -#line 451 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr ); - ; - break;} -case 39: -#line 455 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GT, yyvsp[0].expr ); - ; - break;} -case 40: -#line 459 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LT, yyvsp[0].expr ); - ; - break;} -case 41: -#line 463 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LE, yyvsp[0].expr ); - ; - break;} -case 42: -#line 467 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GE, yyvsp[0].expr ); - ; - break;} -case 43: -#line 471 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_NE, yyvsp[0].expr ); - ; - break;} -case 44: -#line 475 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_ISNULL, NULL ); - ; - break;} -case 45: -#line 479 "./sql.y" -{ - yyval.expr = EXPR_complex( yyvsp[-3].expr, OP_NOTNULL, NULL ); - ; - break;} -case 48: -#line 491 "./sql.y" -{ - value_list *vals; - - vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); - if( vals ) - { - vals->val = yyvsp[0].expr; - vals->next = NULL; - } - yyval.val_list = vals; - ; - break;} -case 49: -#line 503 "./sql.y" -{ - value_list *vals; - - vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); - if( vals ) - { - vals->val = yyvsp[0].expr; - vals->next = NULL; - } - yyvsp[-2].val_list->next = vals; - yyval.val_list = yyvsp[-2].val_list; - ; - break;} -case 51: -#line 520 "./sql.y" -{ - yyvsp[-2].update_col_info.col_list->next = yyvsp[0].update_col_info.col_list; - yyvsp[-2].update_col_info.val_list->next = yyvsp[0].update_col_info.val_list; - yyval.update_col_info = yyvsp[-2].update_col_info; - ; - break;} -case 52: -#line 529 "./sql.y" -{ - yyval.update_col_info.col_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.col_list ); - if( !yyval.update_col_info.col_list ) - YYABORT; - yyval.update_col_info.col_list->string = yyvsp[-2].string; - yyval.update_col_info.col_list->next = NULL; - yyval.update_col_info.val_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.val_list ); - if( !yyval.update_col_info.val_list ) - YYABORT; - yyval.update_col_info.val_list->val = yyvsp[0].expr; - yyval.update_col_info.val_list->next = 0; - ; - break;} -case 53: -#line 545 "./sql.y" -{ - yyval.expr = EXPR_ival( &yyvsp[0].str ); - ; - break;} -case 54: -#line 549 "./sql.y" -{ - yyval.expr = EXPR_sval( &yyvsp[0].str ); - ; - break;} -case 55: -#line 553 "./sql.y" -{ - yyval.expr = EXPR_wildcard(); - ; - break;} -case 56: -#line 560 "./sql.y" -{ - yyval.expr = EXPR_column( yyvsp[0].string ); - ; - break;} -case 57: -#line 567 "./sql.y" -{ - yyval.string = yyvsp[0].string; /* FIXME */ - ; - break;} -case 58: -#line 571 "./sql.y" -{ - yyval.string = yyvsp[0].string; - ; - break;} -case 59: -#line 578 "./sql.y" -{ - yyval.string = yyvsp[0].string; - ; - break;} -case 60: -#line 585 "./sql.y" -{ - yyval.string = SQL_getstring( &yyvsp[0].str ); - ; - break;} -case 61: -#line 589 "./sql.y" -{ - yyval.string = SQL_getstring( &yyvsp[0].str ); - ; - break;} -} - -#line 705 "/usr/share/bison/bison.simple" - - - yyvsp -= yylen; - yyssp -= yylen; -#if YYLSP_NEEDED - yylsp -= yylen; -#endif - -#if YYDEBUG - if (yydebug) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); - } -#endif - - *++yyvsp = yyval; -#if YYLSP_NEEDED - *++yylsp = yyloc; -#endif - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTBASE]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - -#ifdef YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (yyn > YYFLAG && yyn < YYLAST) - { - YYSIZE_T yysize = 0; - char *yymsg; - int yyx, yycount; - - yycount = 0; - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) - if (yycheck[yyx + yyn] == yyx) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("parse error, unexpected ") + 1; - yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) - { - char *yyp = yystpcpy (yymsg, "parse error, unexpected "); - yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); - - if (yycount < 5) - { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) - if (yycheck[yyx + yyn] == yyx) - { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); - yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; - } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); - } - else - yyerror ("parse error; also virtual memory exhausted"); - } - else -#endif /* defined (YYERROR_VERBOSE) */ - yyerror ("parse error"); - } - goto yyerrlab1; - - -/*--------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action | -`--------------------------------------------------*/ -yyerrlab1: - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - /* return failure if at end of input */ - if (yychar == YYEOF) - YYABORT; - YYDPRINTF ((stderr, "Discarding token %d (%s).\n", - yychar, yytname[yychar1])); - yychar = YYEMPTY; - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; - - -/*-------------------------------------------------------------------. -| yyerrdefault -- current state does not do anything special for the | -| error token. | -`-------------------------------------------------------------------*/ -yyerrdefault: -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - - /* If its default is to accept any token, ok. Otherwise pop it. */ - yyn = yydefact[yystate]; - if (yyn) - goto yydefault; -#endif - - -/*---------------------------------------------------------------. -| yyerrpop -- pop the current state because it cannot handle the | -| error token | -`---------------------------------------------------------------*/ -yyerrpop: - if (yyssp == yyss) - YYABORT; - yyvsp--; - yystate = *--yyssp; -#if YYLSP_NEEDED - yylsp--; -#endif - -#if YYDEBUG - if (yydebug) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "Error: state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); - } -#endif - -/*--------------. -| yyerrhandle. | -`--------------*/ -yyerrhandle: - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; - - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; - - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; - } - else if (yyn == 0) - goto yyerrpop; - - if (yyn == YYFINAL) - YYACCEPT; - - YYDPRINTF ((stderr, "Shifting error token, ")); - - *++yyvsp = yylval; -#if YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -/*---------------------------------------------. -| yyoverflowab -- parser overflow comes here. | -`---------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); - yyresult = 2; - /* Fall through. */ - -yyreturn: -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - return yyresult; -} -#line 594 "./sql.y" - - -int SQL_lex( void *SQL_lval, SQL_input *sql) -{ - int token; - struct sql_str * str = SQL_lval; - - do - { - sql->n += sql->len; - if( ! sql->command[sql->n] ) - return 0; /* end of input */ - - TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); - sql->len = sqliteGetToken( &sql->command[sql->n], &token ); - if( sql->len==0 ) - break; - str->data = &sql->command[sql->n]; - str->len = sql->len; - } - while( token == TK_SPACE ); - - TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); - - return token; -} - -LPWSTR SQL_getstring( struct sql_str *strdata) -{ - LPCWSTR p = strdata->data; - UINT len = strdata->len; - LPWSTR str; - - /* if there's quotes, remove them */ - if( ( (p[0]=='`') && (p[len-1]=='`') ) || - ( (p[0]=='\'') && (p[len-1]=='\'') ) ) - { - p++; - len -= 2; - } - str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR)); - if(!str ) - return str; - memcpy(str, p, len*sizeof(WCHAR) ); - str[len]=0; - - return str; -} - -INT SQL_getint( SQL_input *sql ) -{ - LPCWSTR p = &sql->command[sql->n]; - - return atoiW( p ); -} - -int SQL_error(const char *str) -{ - return 0; -} - -static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, - string_list *columns ) -{ - MSIVIEW *view = NULL; - - SELECT_CreateView( db, &view, in, columns ); - delete_string_list( columns ); - if( !view ) - ERR("Error creating select query\n"); - return view; -} - -static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, - string_list *columns ) -{ - MSIVIEW *view = NULL; - - ORDER_CreateView( db, &view, in ); - if( view ) - { - string_list *x = columns; - - for( x = columns; x ; x = x->next ) - ORDER_AddColumn( view, x->string ); - } - else - ERR("Error creating select query\n"); - delete_string_list( columns ); - return view; -} - -static struct expr * EXPR_wildcard() -{ - struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); - if( e ) - { - e->type = EXPR_WILDCARD; - } - return e; -} - -static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r ) -{ - struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); - if( e ) - { - e->type = EXPR_COMPLEX; - e->u.expr.left = l; - e->u.expr.op = op; - e->u.expr.right = r; - } - return e; -} - -static struct expr * EXPR_column( LPWSTR str ) -{ - struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); - if( e ) - { - e->type = EXPR_COLUMN; - e->u.sval = str; - } - return e; -} - -static struct expr * EXPR_ival( struct sql_str *str ) -{ - struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); - if( e ) - { - e->type = EXPR_IVAL; - e->u.ival = atoiW( str->data ); - } - return e; -} - -static struct expr * EXPR_sval( struct sql_str *str ) -{ - struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); - if( e ) - { - e->type = EXPR_SVAL; - e->u.sval = SQL_getstring( str ); - } - return e; -} - -void delete_expr( struct expr *e ) -{ - if( !e ) - return; - if( e->type == EXPR_COMPLEX ) - { - delete_expr( e->u.expr.left ); - delete_expr( e->u.expr.right ); - } - else if( e->type == EXPR_UTF8 ) - HeapFree( GetProcessHeap(), 0, e->u.utf8 ); - else if( e->type == EXPR_SVAL ) - HeapFree( GetProcessHeap(), 0, e->u.sval ); - HeapFree( GetProcessHeap(), 0, e ); -} - -void delete_string_list( string_list *sl ) -{ - while( sl ) - { - string_list *t = sl->next; - HeapFree( GetProcessHeap(), 0, sl->string ); - HeapFree( GetProcessHeap(), 0, sl ); - sl = t; - } -} - -void delete_value_list( value_list *vl ) -{ - while( vl ) - { - value_list *t = vl->next; - delete_expr( vl->val ); - HeapFree( GetProcessHeap(), 0, vl ); - vl = t; - } -} - -static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, - string_list *keys ) -{ - string_list *k; - BOOL found = TRUE; - - for( k = keys; k && found; k = k->next ) - { - create_col_info *c; - - found = FALSE; - for( c = cols; c && !found; c = c->next ) - { - if( lstrcmpW( k->string, c->colname ) ) - continue; - c->type |= MSITYPE_KEY; - found = TRUE; - } - } - - return found; -} - -UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview ) -{ - SQL_input sql; - int r; - - *phview = NULL; - - sql.db = db; - sql.command = command; - sql.n = 0; - sql.len = 0; - sql.view = phview; - - r = SQL_parse(&sql); - - TRACE("Parse returned %d\n", r); - if( r ) - { - if( *sql.view ) - (*sql.view)->ops->delete( *sql.view ); - *sql.view = NULL; - return ERROR_BAD_QUERY_SYNTAX; - } - - return ERROR_SUCCESS; -} +/* A Bison parser, made by GNU Bison 1.875b. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse SQL_parse +#define yylex SQL_lex +#define yyerror SQL_error +#define yylval SQL_lval +#define yychar SQL_char +#define yydebug SQL_debug +#define yynerrs SQL_nerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TK_ABORT = 258, + TK_AFTER = 259, + TK_AGG_FUNCTION = 260, + TK_ALL = 261, + TK_AND = 262, + TK_AS = 263, + TK_ASC = 264, + TK_BEFORE = 265, + TK_BEGIN = 266, + TK_BETWEEN = 267, + TK_BITAND = 268, + TK_BITNOT = 269, + TK_BITOR = 270, + TK_BY = 271, + TK_CASCADE = 272, + TK_CASE = 273, + TK_CHAR = 274, + TK_CHECK = 275, + TK_CLUSTER = 276, + TK_COLLATE = 277, + TK_COLUMN = 278, + TK_COMMA = 279, + TK_COMMENT = 280, + TK_COMMIT = 281, + TK_CONCAT = 282, + TK_CONFLICT = 283, + TK_CONSTRAINT = 284, + TK_COPY = 285, + TK_CREATE = 286, + TK_DEFAULT = 287, + TK_DEFERRABLE = 288, + TK_DEFERRED = 289, + TK_DELETE = 290, + TK_DELIMITERS = 291, + TK_DESC = 292, + TK_DISTINCT = 293, + TK_DOT = 294, + TK_DROP = 295, + TK_EACH = 296, + TK_ELSE = 297, + TK_END = 298, + TK_END_OF_FILE = 299, + TK_EQ = 300, + TK_EXCEPT = 301, + TK_EXPLAIN = 302, + TK_FAIL = 303, + TK_FLOAT = 304, + TK_FOR = 305, + TK_FOREIGN = 306, + TK_FROM = 307, + TK_FUNCTION = 308, + TK_GE = 309, + TK_GLOB = 310, + TK_GROUP = 311, + TK_GT = 312, + TK_HAVING = 313, + TK_HOLD = 314, + TK_IGNORE = 315, + TK_ILLEGAL = 316, + TK_IMMEDIATE = 317, + TK_IN = 318, + TK_INDEX = 319, + TK_INITIALLY = 320, + TK_ID = 321, + TK_INSERT = 322, + TK_INSTEAD = 323, + TK_INT = 324, + TK_INTEGER = 325, + TK_INTERSECT = 326, + TK_INTO = 327, + TK_IS = 328, + TK_ISNULL = 329, + TK_JOIN = 330, + TK_JOIN_KW = 331, + TK_KEY = 332, + TK_LE = 333, + TK_LIKE = 334, + TK_LIMIT = 335, + TK_LONG = 336, + TK_LONGCHAR = 337, + TK_LP = 338, + TK_LSHIFT = 339, + TK_LT = 340, + TK_LOCALIZABLE = 341, + TK_MATCH = 342, + TK_MINUS = 343, + TK_NE = 344, + TK_NOT = 345, + TK_NOTNULL = 346, + TK_NULL = 347, + TK_OBJECT = 348, + TK_OF = 349, + TK_OFFSET = 350, + TK_ON = 351, + TK_OR = 352, + TK_ORACLE_OUTER_JOIN = 353, + TK_ORDER = 354, + TK_PLUS = 355, + TK_PRAGMA = 356, + TK_PRIMARY = 357, + TK_RAISE = 358, + TK_REFERENCES = 359, + TK_REM = 360, + TK_REPLACE = 361, + TK_RESTRICT = 362, + TK_ROLLBACK = 363, + TK_ROW = 364, + TK_RP = 365, + TK_RSHIFT = 366, + TK_SELECT = 367, + TK_SEMI = 368, + TK_SET = 369, + TK_SHORT = 370, + TK_SLASH = 371, + TK_SPACE = 372, + TK_STAR = 373, + TK_STATEMENT = 374, + TK_STRING = 375, + TK_TABLE = 376, + TK_TEMP = 377, + TK_THEN = 378, + TK_TRANSACTION = 379, + TK_TRIGGER = 380, + TK_UMINUS = 381, + TK_UNCLOSED_STRING = 382, + TK_UNION = 383, + TK_UNIQUE = 384, + TK_UPDATE = 385, + TK_UPLUS = 386, + TK_USING = 387, + TK_VACUUM = 388, + TK_VALUES = 389, + TK_VIEW = 390, + TK_WHEN = 391, + TK_WHERE = 392, + TK_WILDCARD = 393, + COLUMN = 395, + FUNCTION = 396, + COMMENT = 397, + UNCLOSED_STRING = 398, + SPACE = 399, + ILLEGAL = 400, + END_OF_FILE = 401 + }; +#endif +#define TK_ABORT 258 +#define TK_AFTER 259 +#define TK_AGG_FUNCTION 260 +#define TK_ALL 261 +#define TK_AND 262 +#define TK_AS 263 +#define TK_ASC 264 +#define TK_BEFORE 265 +#define TK_BEGIN 266 +#define TK_BETWEEN 267 +#define TK_BITAND 268 +#define TK_BITNOT 269 +#define TK_BITOR 270 +#define TK_BY 271 +#define TK_CASCADE 272 +#define TK_CASE 273 +#define TK_CHAR 274 +#define TK_CHECK 275 +#define TK_CLUSTER 276 +#define TK_COLLATE 277 +#define TK_COLUMN 278 +#define TK_COMMA 279 +#define TK_COMMENT 280 +#define TK_COMMIT 281 +#define TK_CONCAT 282 +#define TK_CONFLICT 283 +#define TK_CONSTRAINT 284 +#define TK_COPY 285 +#define TK_CREATE 286 +#define TK_DEFAULT 287 +#define TK_DEFERRABLE 288 +#define TK_DEFERRED 289 +#define TK_DELETE 290 +#define TK_DELIMITERS 291 +#define TK_DESC 292 +#define TK_DISTINCT 293 +#define TK_DOT 294 +#define TK_DROP 295 +#define TK_EACH 296 +#define TK_ELSE 297 +#define TK_END 298 +#define TK_END_OF_FILE 299 +#define TK_EQ 300 +#define TK_EXCEPT 301 +#define TK_EXPLAIN 302 +#define TK_FAIL 303 +#define TK_FLOAT 304 +#define TK_FOR 305 +#define TK_FOREIGN 306 +#define TK_FROM 307 +#define TK_FUNCTION 308 +#define TK_GE 309 +#define TK_GLOB 310 +#define TK_GROUP 311 +#define TK_GT 312 +#define TK_HAVING 313 +#define TK_HOLD 314 +#define TK_IGNORE 315 +#define TK_ILLEGAL 316 +#define TK_IMMEDIATE 317 +#define TK_IN 318 +#define TK_INDEX 319 +#define TK_INITIALLY 320 +#define TK_ID 321 +#define TK_INSERT 322 +#define TK_INSTEAD 323 +#define TK_INT 324 +#define TK_INTEGER 325 +#define TK_INTERSECT 326 +#define TK_INTO 327 +#define TK_IS 328 +#define TK_ISNULL 329 +#define TK_JOIN 330 +#define TK_JOIN_KW 331 +#define TK_KEY 332 +#define TK_LE 333 +#define TK_LIKE 334 +#define TK_LIMIT 335 +#define TK_LONG 336 +#define TK_LONGCHAR 337 +#define TK_LP 338 +#define TK_LSHIFT 339 +#define TK_LT 340 +#define TK_LOCALIZABLE 341 +#define TK_MATCH 342 +#define TK_MINUS 343 +#define TK_NE 344 +#define TK_NOT 345 +#define TK_NOTNULL 346 +#define TK_NULL 347 +#define TK_OBJECT 348 +#define TK_OF 349 +#define TK_OFFSET 350 +#define TK_ON 351 +#define TK_OR 352 +#define TK_ORACLE_OUTER_JOIN 353 +#define TK_ORDER 354 +#define TK_PLUS 355 +#define TK_PRAGMA 356 +#define TK_PRIMARY 357 +#define TK_RAISE 358 +#define TK_REFERENCES 359 +#define TK_REM 360 +#define TK_REPLACE 361 +#define TK_RESTRICT 362 +#define TK_ROLLBACK 363 +#define TK_ROW 364 +#define TK_RP 365 +#define TK_RSHIFT 366 +#define TK_SELECT 367 +#define TK_SEMI 368 +#define TK_SET 369 +#define TK_SHORT 370 +#define TK_SLASH 371 +#define TK_SPACE 372 +#define TK_STAR 373 +#define TK_STATEMENT 374 +#define TK_STRING 375 +#define TK_TABLE 376 +#define TK_TEMP 377 +#define TK_THEN 378 +#define TK_TRANSACTION 379 +#define TK_TRIGGER 380 +#define TK_UMINUS 381 +#define TK_UNCLOSED_STRING 382 +#define TK_UNION 383 +#define TK_UNIQUE 384 +#define TK_UPDATE 385 +#define TK_UPLUS 386 +#define TK_USING 387 +#define TK_VACUUM 388 +#define TK_VALUES 389 +#define TK_VIEW 390 +#define TK_WHEN 391 +#define TK_WHERE 392 +#define TK_WILDCARD 393 +#define COLUMN 395 +#define FUNCTION 396 +#define COMMENT 397 +#define UNCLOSED_STRING 398 +#define SPACE 399 +#define ILLEGAL 400 +#define END_OF_FILE 401 + + + + +/* Copy the first part of user declarations. */ +#line 1 "./sql.y" + + +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2002-2004 Mike McCormack for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "config.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "query.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +#define YYLEX_PARAM info +#define YYPARSE_PARAM info + +extern int SQL_error(const char *str); + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +typedef struct tag_SQL_input +{ + MSIDATABASE *db; + LPCWSTR command; + DWORD n, len; + MSIVIEW **view; /* view structure for the resulting query */ +} SQL_input; + +static LPWSTR SQL_getstring( struct sql_str *str ); +static INT SQL_getint( SQL_input *sql ); +static int SQL_lex( void *SQL_lval, SQL_input *info); + +static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, + string_list *columns ); +static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, + string_list *columns ); + +static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, + string_list *keys); + +static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r ); +static struct expr * EXPR_column( LPWSTR ); +static struct expr * EXPR_ival( struct sql_str *, int sign); +static struct expr * EXPR_sval( struct sql_str *); +static struct expr * EXPR_wildcard(); + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 74 "./sql.y" +typedef union YYSTYPE { + struct sql_str str; + LPWSTR string; + string_list *column_list; + value_list *val_list; + MSIVIEW *query; + struct expr *expr; + USHORT column_type; + create_col_info *column_info; + column_assignment update_col_info; +} YYSTYPE; +/* Line 191 of yacc.c. */ +#line 457 "sql.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 214 of yacc.c. */ +#line 469 "sql.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 23 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 125 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 147 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 25 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 63 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 123 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 401 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 11, 22, 34, 41, + 49, 56, 61, 66, 69, 71, 74, 76, 80, 82, + 87, 89, 91, 93, 95, 97, 99, 104, 106, 110, + 115, 117, 121, 123, 126, 131, 135, 139, 143, 147, + 151, 155, 159, 163, 167, 171, 175, 180, 182, 184, + 186, 190, 192, 196, 200, 202, 205, 207, 209, 211, + 215, 217, 219, 221 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short yyrhs[] = +{ + 148, 0, -1, 158, -1, 150, -1, 149, -1, 151, + -1, 67, 72, 170, 83, 160, 110, 134, 83, 164, + 110, -1, 67, 72, 170, 83, 160, 110, 134, 83, + 164, 110, 122, -1, 31, 121, 170, 83, 152, 110, + -1, 31, 121, 170, 83, 152, 110, 59, -1, 130, + 170, 114, 165, 137, 162, -1, 153, 102, 77, 160, + -1, 153, 24, 169, 154, -1, 169, 154, -1, 155, + -1, 155, 86, -1, 156, -1, 156, 90, 92, -1, + 19, -1, 19, 83, 157, 110, -1, 82, -1, 115, + -1, 69, -1, 81, -1, 93, -1, 70, -1, 159, + 99, 16, 160, -1, 159, -1, 112, 160, 161, -1, + 112, 38, 160, 161, -1, 169, -1, 169, 24, 160, + -1, 118, -1, 52, 170, -1, 52, 170, 137, 162, + -1, 83, 162, 110, -1, 168, 45, 168, -1, 162, + 7, 162, -1, 162, 97, 162, -1, 168, 45, 163, + -1, 168, 57, 163, -1, 168, 85, 163, -1, 168, + 78, 163, -1, 168, 54, 163, -1, 168, 89, 163, + -1, 168, 73, 92, -1, 168, 73, 90, 92, -1, + 168, -1, 167, -1, 167, -1, 164, 24, 167, -1, + 166, -1, 166, 24, 165, -1, 169, 45, 167, -1, + 70, -1, 88, 70, -1, 120, -1, 138, -1, 169, + -1, 170, 39, 171, -1, 171, -1, 171, -1, 66, + -1, 120, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 142, 142, 147, 152, 157, 165, 173, 184, 194, + 207, 218, 228, 247, 259, 263, 271, 275, 282, 286, + 290, 294, 298, 302, 306, 313, 324, 335, 339, 353, + 371, 384, 397, 404, 415, 434, 438, 442, 446, 450, + 454, 458, 462, 466, 470, 474, 478, 485, 486, 490, + 502, 518, 519, 528, 544, 548, 552, 556, 563, 570, + 574, 581, 588, 592 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TK_ABORT", "TK_AFTER", "TK_AGG_FUNCTION", + "TK_ALL", "TK_AND", "TK_AS", "TK_ASC", "TK_BEFORE", "TK_BEGIN", + "TK_BETWEEN", "TK_BITAND", "TK_BITNOT", "TK_BITOR", "TK_BY", + "TK_CASCADE", "TK_CASE", "TK_CHAR", "TK_CHECK", "TK_CLUSTER", + "TK_COLLATE", "TK_COLUMN", "TK_COMMA", "TK_COMMENT", "TK_COMMIT", + "TK_CONCAT", "TK_CONFLICT", "TK_CONSTRAINT", "TK_COPY", "TK_CREATE", + "TK_DEFAULT", "TK_DEFERRABLE", "TK_DEFERRED", "TK_DELETE", + "TK_DELIMITERS", "TK_DESC", "TK_DISTINCT", "TK_DOT", "TK_DROP", + "TK_EACH", "TK_ELSE", "TK_END", "TK_END_OF_FILE", "TK_EQ", "TK_EXCEPT", + "TK_EXPLAIN", "TK_FAIL", "TK_FLOAT", "TK_FOR", "TK_FOREIGN", "TK_FROM", + "TK_FUNCTION", "TK_GE", "TK_GLOB", "TK_GROUP", "TK_GT", "TK_HAVING", + "TK_HOLD", "TK_IGNORE", "TK_ILLEGAL", "TK_IMMEDIATE", "TK_IN", + "TK_INDEX", "TK_INITIALLY", "TK_ID", "TK_INSERT", "TK_INSTEAD", + "TK_INT", "TK_INTEGER", "TK_INTERSECT", "TK_INTO", "TK_IS", "TK_ISNULL", + "TK_JOIN", "TK_JOIN_KW", "TK_KEY", "TK_LE", "TK_LIKE", "TK_LIMIT", + "TK_LONG", "TK_LONGCHAR", "TK_LP", "TK_LSHIFT", "TK_LT", + "TK_LOCALIZABLE", "TK_MATCH", "TK_MINUS", "TK_NE", "TK_NOT", + "TK_NOTNULL", "TK_NULL", "TK_OBJECT", "TK_OF", "TK_OFFSET", "TK_ON", + "TK_OR", "TK_ORACLE_OUTER_JOIN", "TK_ORDER", "TK_PLUS", "TK_PRAGMA", + "TK_PRIMARY", "TK_RAISE", "TK_REFERENCES", "TK_REM", "TK_REPLACE", + "TK_RESTRICT", "TK_ROLLBACK", "TK_ROW", "TK_RP", "TK_RSHIFT", + "TK_SELECT", "TK_SEMI", "TK_SET", "TK_SHORT", "TK_SLASH", "TK_SPACE", + "TK_STAR", "TK_STATEMENT", "TK_STRING", "TK_TABLE", "TK_TEMP", + "TK_THEN", "TK_TRANSACTION", "TK_TRIGGER", "TK_UMINUS", + "TK_UNCLOSED_STRING", "TK_UNION", "TK_UNIQUE", "TK_UPDATE", "TK_UPLUS", + "TK_USING", "TK_VACUUM", "TK_VALUES", "TK_VIEW", "TK_WHEN", "TK_WHERE", + "TK_WILDCARD", "AGG_FUNCTION.", "COLUMN", "FUNCTION", "COMMENT", + "UNCLOSED_STRING", "SPACE", "ILLEGAL", "END_OF_FILE", "$accept", + "onequery", "oneinsert", "onecreate", "oneupdate", "table_def", + "column_def", "column_type", "data_type_l", "data_type", "data_count", + "oneselect", "unorderedsel", "selcollist", "from", "expr", "val", + "constlist", "update_assign_list", "column_assignment", "const_val", + "column_val", "column", "table", "string_or_id", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 147, 148, 148, 148, 148, 149, 149, 150, 150, + 151, 152, 153, 153, 154, 154, 155, 155, 156, 156, + 156, 156, 156, 156, 156, 157, 158, 158, 159, 159, + 160, 160, 160, 161, 161, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 163, 163, 164, + 164, 165, 165, 166, 167, 167, 167, 167, 168, 169, + 169, 170, 171, 171 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 10, 11, 6, 7, + 6, 4, 4, 2, 1, 2, 1, 3, 1, 4, + 1, 1, 1, 1, 1, 1, 4, 1, 3, 4, + 1, 3, 1, 2, 4, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 1, 1, 1, + 3, 1, 3, 3, 1, 2, 1, 1, 1, 3, + 1, 1, 1, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 0, 0, 0, 0, 4, 3, 5, 2, + 27, 0, 0, 0, 62, 32, 63, 0, 30, 0, + 60, 0, 61, 1, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 0, 0, 29, 33, 31, 59, + 0, 51, 0, 26, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 18, 22, 23, 20, 24, + 21, 13, 14, 16, 0, 0, 34, 0, 58, 10, + 52, 54, 0, 56, 57, 53, 9, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 55, 12, 11, 25, 0, 17, 0, + 35, 37, 38, 56, 39, 48, 36, 43, 47, 40, + 0, 45, 42, 41, 44, 19, 0, 49, 46, 0, + 6, 50, 7 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 5, 6, 7, 8, 44, 45, 61, 62, 63, + 97, 9, 10, 17, 29, 66, 104, 116, 40, 41, + 105, 67, 68, 19, 20 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -105 +static const yysigned_char yypact[] = +{ + -30, -104, -46, -34, -51, 21, -105, -105, -105, -105, + -77, -51, -51, -52, -105, -105, -105, -25, 7, -1, + 2, -79, -105, -105, 31, -33, -32, -25, -51, -105, + -52, -51, -51, -52, -51, -52, -105, -88, -105, -105, + -82, 33, 14, -105, -48, -15, -17, -43, -50, -50, + -51, -64, 13, -51, -2, -6, -105, -105, -105, -105, + -105, -105, 6, -9, -49, -50, -4, 26, -105, -4, + -105, -105, 24, -105, -105, -105, -105, -17, -52, 25, + -105, 9, 19, -7, -50, -50, -59, -59, -59, -44, + -59, -59, -59, -105, -105, -105, -105, -3, -105, -64, + -105, -4, -4, 73, -105, -105, -105, -105, -105, -105, + 22, -105, -105, -105, -105, -105, -19, -105, -105, -64, + 1, -105, -105 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -105, -105, -105, -105, -105, -105, -105, 42, -105, -105, + -105, -105, -105, -5, 97, -31, 18, -105, 75, -105, + -41, 30, 10, 85, 8 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -64 +static const yysigned_char yytable[] = +{ + 84, 1, 55, 84, 13, 119, 71, 14, 27, 53, + 75, 71, 22, 18, 14, 14, 14, 11, 69, 22, + 22, 23, 24, 18, 72, 38, 12, 28, 43, 72, + 47, 30, 14, 65, 83, 32, 22, 2, 31, 39, + 18, -61, 42, 18, 46, 18, 110, 33, 111, 48, + 34, 35, 56, 101, 102, 49, 73, 50, 117, 51, + 42, 103, 52, 77, 57, 58, 15, 64, 16, 16, + 16, 86, 76, 95, 74, 78, 59, 79, 121, 74, + 87, 81, 3, 88, 15, 82, 16, 54, 18, 21, + 85, 120, 80, 85, 93, 96, 25, 26, 60, 89, + 4, 98, 99, 100, 90, 107, 109, 115, 112, 113, + 114, 91, -63, 37, 118, 92, 106, 108, 108, 94, + 108, 108, 108, 122, 36, 70 +}; + +static const unsigned char yycheck[] = +{ + 7, 31, 19, 7, 38, 24, 70, 66, 13, 24, + 51, 70, 4, 3, 66, 66, 66, 121, 49, 11, + 12, 0, 99, 13, 88, 30, 72, 52, 33, 88, + 35, 24, 66, 83, 65, 114, 28, 67, 39, 31, + 30, 39, 32, 33, 34, 35, 90, 16, 92, 137, + 83, 83, 69, 84, 85, 137, 120, 24, 99, 45, + 50, 120, 110, 53, 81, 82, 118, 110, 120, 120, + 120, 45, 59, 78, 138, 77, 93, 83, 119, 138, + 54, 90, 112, 57, 118, 134, 120, 102, 78, 4, + 97, 110, 86, 97, 70, 70, 11, 12, 115, 73, + 130, 92, 83, 110, 78, 87, 88, 110, 90, 91, + 92, 85, 39, 28, 92, 89, 86, 87, 88, 77, + 90, 91, 92, 122, 27, 50 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 31, 67, 112, 130, 148, 149, 150, 151, 158, + 159, 121, 72, 38, 66, 118, 120, 160, 169, 170, + 171, 170, 171, 0, 99, 170, 170, 160, 52, 161, + 24, 39, 114, 16, 83, 83, 161, 170, 160, 171, + 165, 166, 169, 160, 152, 153, 169, 160, 137, 137, + 24, 45, 110, 24, 102, 19, 69, 81, 82, 93, + 115, 154, 155, 156, 110, 83, 162, 168, 169, 162, + 165, 70, 88, 120, 138, 167, 59, 169, 77, 83, + 86, 90, 134, 162, 7, 97, 45, 54, 57, 73, + 78, 85, 89, 70, 154, 160, 70, 157, 92, 83, + 110, 162, 162, 120, 163, 167, 168, 163, 168, 163, + 90, 92, 163, 163, 163, 110, 164, 167, 92, 24, + 110, 167, 122 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + /* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 143 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + *sql->view = yyvsp[0].query; + ;} + break; + + case 3: +#line 148 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + *sql->view = yyvsp[0].query; + ;} + break; + + case 4: +#line 153 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + *sql->view = yyvsp[0].query; + ;} + break; + + case 5: +#line 158 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + *sql->view = yyvsp[0].query; + ;} + break; + + case 6: +#line 166 "./sql.y" + { + SQL_input *sql = (SQL_input*) info; + MSIVIEW *insert = NULL; + + INSERT_CreateView( sql->db, &insert, yyvsp[-7].string, yyvsp[-5].column_list, yyvsp[-1].val_list, FALSE ); + yyval.query = insert; + ;} + break; + + case 7: +#line 174 "./sql.y" + { + SQL_input *sql = (SQL_input*) info; + MSIVIEW *insert = NULL; + + INSERT_CreateView( sql->db, &insert, yyvsp[-8].string, yyvsp[-6].column_list, yyvsp[-2].val_list, TRUE ); + yyval.query = insert; + ;} + break; + + case 8: +#line 185 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *create = NULL; + + if( !yyvsp[-1].column_info ) + YYABORT; + CREATE_CreateView( sql->db, &create, yyvsp[-3].string, yyvsp[-1].column_info, FALSE ); + yyval.query = create; + ;} + break; + + case 9: +#line 195 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *create = NULL; + + if( !yyvsp[-2].column_info ) + YYABORT; + CREATE_CreateView( sql->db, &create, yyvsp[-4].string, yyvsp[-2].column_info, TRUE ); + yyval.query = create; + ;} + break; + + case 10: +#line 208 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *update = NULL; + + UPDATE_CreateView( sql->db, &update, yyvsp[-4].string, &yyvsp[-2].update_col_info, yyvsp[0].expr ); + yyval.query = update; + ;} + break; + + case 11: +#line 219 "./sql.y" + { + if( SQL_MarkPrimaryKeys( yyvsp[-3].column_info, yyvsp[0].column_list ) ) + yyval.column_info = yyvsp[-3].column_info; + else + yyval.column_info = NULL; + ;} + break; + + case 12: +#line 229 "./sql.y" + { + create_col_info *ci; + + for( ci = yyvsp[-3].column_info; ci->next; ci = ci->next ) + ; + + ci->next = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info ); + if( !ci->next ) + { + /* FIXME: free $1 */ + YYABORT; + } + ci->next->colname = yyvsp[-1].string; + ci->next->type = yyvsp[0].column_type; + ci->next->next = NULL; + + yyval.column_info = yyvsp[-3].column_info; + ;} + break; + + case 13: +#line 248 "./sql.y" + { + yyval.column_info = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.column_info ); + if( ! yyval.column_info ) + YYABORT; + yyval.column_info->colname = yyvsp[-1].string; + yyval.column_info->type = yyvsp[0].column_type; + yyval.column_info->next = NULL; + ;} + break; + + case 14: +#line 260 "./sql.y" + { + yyval.column_type = yyvsp[0].column_type | MSITYPE_VALID; + ;} + break; + + case 15: +#line 264 "./sql.y" + { + FIXME("LOCALIZABLE ignored\n"); + yyval.column_type = yyvsp[-1].column_type | MSITYPE_VALID; + ;} + break; + + case 16: +#line 272 "./sql.y" + { + yyval.column_type |= MSITYPE_NULLABLE; + ;} + break; + + case 17: +#line 276 "./sql.y" + { + yyval.column_type = yyvsp[-2].column_type; + ;} + break; + + case 18: +#line 283 "./sql.y" + { + yyval.column_type = MSITYPE_STRING | 1; + ;} + break; + + case 19: +#line 287 "./sql.y" + { + yyval.column_type = MSITYPE_STRING | 0x400 | yyvsp[-1].column_type; + ;} + break; + + case 20: +#line 291 "./sql.y" + { + yyval.column_type = 2; + ;} + break; + + case 21: +#line 295 "./sql.y" + { + yyval.column_type = 2; + ;} + break; + + case 22: +#line 299 "./sql.y" + { + yyval.column_type = 2; + ;} + break; + + case 23: +#line 303 "./sql.y" + { + yyval.column_type = 4; + ;} + break; + + case 24: +#line 307 "./sql.y" + { + yyval.column_type = 0; + ;} + break; + + case 25: +#line 314 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + int val = SQL_getint(sql); + if( ( val > 255 ) || ( val < 0 ) ) + YYABORT; + yyval.column_type = val; + ;} + break; + + case 26: +#line 325 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + + if( !yyvsp[-3].query ) + YYABORT; + if( yyvsp[0].column_list ) + yyval.query = do_order_by( sql->db, yyvsp[-3].query, yyvsp[0].column_list ); + else + yyval.query = yyvsp[-3].query; + ;} + break; + + case 28: +#line 340 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + if( !yyvsp[0].query ) + YYABORT; + if( yyvsp[-1].column_list ) + { + yyval.query = do_one_select( sql->db, yyvsp[0].query, yyvsp[-1].column_list ); + if( !yyval.query ) + YYABORT; + } + else + yyval.query = yyvsp[0].query; + ;} + break; + + case 29: +#line 354 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *view = yyvsp[0].query; + + if( !view ) + YYABORT; + if( yyvsp[-1].column_list ) + { + view = do_one_select( sql->db, view, yyvsp[-1].column_list ); + if( !view ) + YYABORT; + } + DISTINCT_CreateView( sql->db, & yyval.query, view ); + ;} + break; + + case 30: +#line 372 "./sql.y" + { + string_list *list; + + list = HeapAlloc( GetProcessHeap(), 0, sizeof *list ); + if( !list ) + YYABORT; + list->string = yyvsp[0].string; + list->next = NULL; + + yyval.column_list = list; + TRACE("Collist %s\n",debugstr_w(yyval.column_list->string)); + ;} + break; + + case 31: +#line 385 "./sql.y" + { + string_list *list; + + list = HeapAlloc( GetProcessHeap(), 0, sizeof *list ); + if( !list ) + YYABORT; + list->string = yyvsp[-2].string; + list->next = yyvsp[0].column_list; + + yyval.column_list = list; + TRACE("From table: %s\n",debugstr_w(yyval.column_list->string)); + ;} + break; + + case 32: +#line 398 "./sql.y" + { + yyval.column_list = NULL; + ;} + break; + + case 33: +#line 405 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + UINT r; + + yyval.query = NULL; + TRACE("From table: %s\n",debugstr_w(yyvsp[0].string)); + r = TABLE_CreateView( sql->db, yyvsp[0].string, & yyval.query ); + if( r != ERROR_SUCCESS ) + YYABORT; + ;} + break; + + case 34: +#line 416 "./sql.y" + { + SQL_input* sql = (SQL_input*) info; + MSIVIEW *view = NULL; + UINT r; + + yyval.query = NULL; + TRACE("From table: %s\n",debugstr_w(yyvsp[-2].string)); + r = TABLE_CreateView( sql->db, yyvsp[-2].string, &view ); + if( r != ERROR_SUCCESS ) + YYABORT; + r = WHERE_CreateView( sql->db, &view, view, yyvsp[0].expr ); + if( r != ERROR_SUCCESS ) + YYABORT; + yyval.query = view; + ;} + break; + + case 35: +#line 435 "./sql.y" + { + yyval.expr = yyvsp[-1].expr; + ;} + break; + + case 36: +#line 439 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr ); + ;} + break; + + case 37: +#line 443 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_AND, yyvsp[0].expr ); + ;} + break; + + case 38: +#line 447 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_OR, yyvsp[0].expr ); + ;} + break; + + case 39: +#line 451 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_EQ, yyvsp[0].expr ); + ;} + break; + + case 40: +#line 455 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GT, yyvsp[0].expr ); + ;} + break; + + case 41: +#line 459 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LT, yyvsp[0].expr ); + ;} + break; + + case 42: +#line 463 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_LE, yyvsp[0].expr ); + ;} + break; + + case 43: +#line 467 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_GE, yyvsp[0].expr ); + ;} + break; + + case 44: +#line 471 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_NE, yyvsp[0].expr ); + ;} + break; + + case 45: +#line 475 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-2].expr, OP_ISNULL, NULL ); + ;} + break; + + case 46: +#line 479 "./sql.y" + { + yyval.expr = EXPR_complex( yyvsp[-3].expr, OP_NOTNULL, NULL ); + ;} + break; + + case 49: +#line 491 "./sql.y" + { + value_list *vals; + + vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); + if( vals ) + { + vals->val = yyvsp[0].expr; + vals->next = NULL; + } + yyval.val_list = vals; + ;} + break; + + case 50: +#line 503 "./sql.y" + { + value_list *vals; + + vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); + if( vals ) + { + vals->val = yyvsp[0].expr; + vals->next = NULL; + } + yyvsp[-2].val_list->next = vals; + yyval.val_list = yyvsp[-2].val_list; + ;} + break; + + case 52: +#line 520 "./sql.y" + { + yyvsp[-2].update_col_info.col_list->next = yyvsp[0].update_col_info.col_list; + yyvsp[-2].update_col_info.val_list->next = yyvsp[0].update_col_info.val_list; + yyval.update_col_info = yyvsp[-2].update_col_info; + ;} + break; + + case 53: +#line 529 "./sql.y" + { + yyval.update_col_info.col_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.col_list ); + if( !yyval.update_col_info.col_list ) + YYABORT; + yyval.update_col_info.col_list->string = yyvsp[-2].string; + yyval.update_col_info.col_list->next = NULL; + yyval.update_col_info.val_list = HeapAlloc( GetProcessHeap(), 0, sizeof *yyval.update_col_info.val_list ); + if( !yyval.update_col_info.val_list ) + YYABORT; + yyval.update_col_info.val_list->val = yyvsp[0].expr; + yyval.update_col_info.val_list->next = 0; + ;} + break; + + case 54: +#line 545 "./sql.y" + { + yyval.expr = EXPR_ival( &yyvsp[0].str, 1 ); + ;} + break; + + case 55: +#line 549 "./sql.y" + { + yyval.expr = EXPR_ival( &yyvsp[0].str, -1 ); + ;} + break; + + case 56: +#line 553 "./sql.y" + { + yyval.expr = EXPR_sval( &yyvsp[0].str ); + ;} + break; + + case 57: +#line 557 "./sql.y" + { + yyval.expr = EXPR_wildcard(); + ;} + break; + + case 58: +#line 564 "./sql.y" + { + yyval.expr = EXPR_column( yyvsp[0].string ); + ;} + break; + + case 59: +#line 571 "./sql.y" + { + yyval.string = yyvsp[0].string; /* FIXME */ + ;} + break; + + case 60: +#line 575 "./sql.y" + { + yyval.string = yyvsp[0].string; + ;} + break; + + case 61: +#line 582 "./sql.y" + { + yyval.string = yyvsp[0].string; + ;} + break; + + case 62: +#line 589 "./sql.y" + { + yyval.string = SQL_getstring( &yyvsp[0].str ); + ;} + break; + + case 63: +#line 593 "./sql.y" + { + yyval.string = SQL_getstring( &yyvsp[0].str ); + ;} + break; + + + } + +/* Line 999 of yacc.c. */ +#line 2055 "sql.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyss < yyssp) + { + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; + + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + yyvsp--; + yystate = *--yyssp; + + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 598 "./sql.y" + + +int SQL_lex( void *SQL_lval, SQL_input *sql) +{ + int token; + struct sql_str * str = SQL_lval; + + do + { + sql->n += sql->len; + if( ! sql->command[sql->n] ) + return 0; /* end of input */ + + TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); + sql->len = sqliteGetToken( &sql->command[sql->n], &token ); + if( sql->len==0 ) + break; + str->data = &sql->command[sql->n]; + str->len = sql->len; + } + while( token == TK_SPACE ); + + TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); + + return token; +} + +LPWSTR SQL_getstring( struct sql_str *strdata) +{ + LPCWSTR p = strdata->data; + UINT len = strdata->len; + LPWSTR str; + + /* if there's quotes, remove them */ + if( ( (p[0]=='`') && (p[len-1]=='`') ) || + ( (p[0]=='\'') && (p[len-1]=='\'') ) ) + { + p++; + len -= 2; + } + str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR)); + if(!str ) + return str; + memcpy(str, p, len*sizeof(WCHAR) ); + str[len]=0; + + return str; +} + +INT SQL_getint( SQL_input *sql ) +{ + LPCWSTR p = &sql->command[sql->n]; + + return atoiW( p ); +} + +int SQL_error(const char *str) +{ + return 0; +} + +static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, + string_list *columns ) +{ + MSIVIEW *view = NULL; + + SELECT_CreateView( db, &view, in, columns ); + delete_string_list( columns ); + if( !view ) + ERR("Error creating select query\n"); + return view; +} + +static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, + string_list *columns ) +{ + MSIVIEW *view = NULL; + + ORDER_CreateView( db, &view, in ); + if( view ) + { + string_list *x = columns; + + for( x = columns; x ; x = x->next ) + ORDER_AddColumn( view, x->string ); + } + else + ERR("Error creating select query\n"); + delete_string_list( columns ); + return view; +} + +static struct expr * EXPR_wildcard() +{ + struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); + if( e ) + { + e->type = EXPR_WILDCARD; + } + return e; +} + +static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r ) +{ + struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); + if( e ) + { + e->type = EXPR_COMPLEX; + e->u.expr.left = l; + e->u.expr.op = op; + e->u.expr.right = r; + } + return e; +} + +static struct expr * EXPR_column( LPWSTR str ) +{ + struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); + if( e ) + { + e->type = EXPR_COLUMN; + e->u.sval = str; + } + return e; +} + +static struct expr * EXPR_ival( struct sql_str *str , int sign) +{ + struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); + if( e ) + { + e->type = EXPR_IVAL; + e->u.ival = atoiW( str->data ) * sign; + } + return e; +} + +static struct expr * EXPR_sval( struct sql_str *str ) +{ + struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); + if( e ) + { + e->type = EXPR_SVAL; + e->u.sval = SQL_getstring( str ); + } + return e; +} + +void delete_expr( struct expr *e ) +{ + if( !e ) + return; + if( e->type == EXPR_COMPLEX ) + { + delete_expr( e->u.expr.left ); + delete_expr( e->u.expr.right ); + } + else if( e->type == EXPR_UTF8 ) + HeapFree( GetProcessHeap(), 0, e->u.utf8 ); + else if( e->type == EXPR_SVAL ) + HeapFree( GetProcessHeap(), 0, e->u.sval ); + HeapFree( GetProcessHeap(), 0, e ); +} + +void delete_string_list( string_list *sl ) +{ + while( sl ) + { + string_list *t = sl->next; + HeapFree( GetProcessHeap(), 0, sl->string ); + HeapFree( GetProcessHeap(), 0, sl ); + sl = t; + } +} + +void delete_value_list( value_list *vl ) +{ + while( vl ) + { + value_list *t = vl->next; + delete_expr( vl->val ); + HeapFree( GetProcessHeap(), 0, vl ); + vl = t; + } +} + +static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, + string_list *keys ) +{ + string_list *k; + BOOL found = TRUE; + + for( k = keys; k && found; k = k->next ) + { + create_col_info *c; + + found = FALSE; + for( c = cols; c && !found; c = c->next ) + { + if( lstrcmpW( k->string, c->colname ) ) + continue; + c->type |= MSITYPE_KEY; + found = TRUE; + } + } + + return found; +} + +UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview ) +{ + SQL_input sql; + int r; + + *phview = NULL; + + sql.db = db; + sql.command = command; + sql.n = 0; + sql.len = 0; + sql.view = phview; + + r = SQL_parse(&sql); + + TRACE("Parse returned %d\n", r); + if( r ) + { + if( *sql.view ) + (*sql.view)->ops->delete( *sql.view ); + *sql.view = NULL; + return ERROR_BAD_QUERY_SYNTAX; + } + + return ERROR_SUCCESS; +} + diff --git a/reactos/lib/msi/sql.tab.h b/reactos/lib/msi/sql.tab.h index 62fdccd2012..bfc66b3f050 100644 --- a/reactos/lib/msi/sql.tab.h +++ b/reactos/lib/msi/sql.tab.h @@ -1,165 +1,347 @@ -#ifndef BISON_SQL_TAB_H -# define BISON_SQL_TAB_H - -#ifndef YYSTYPE -typedef union -{ - struct sql_str str; - LPWSTR string; - string_list *column_list; - value_list *val_list; - MSIVIEW *query; - struct expr *expr; - USHORT column_type; - create_col_info *column_info; - column_assignment update_col_info; -} yystype; -# define YYSTYPE yystype -# define YYSTYPE_IS_TRIVIAL 1 -#endif -# define TK_ABORT 257 -# define TK_AFTER 258 -# define TK_AGG_FUNCTION 259 -# define TK_ALL 260 -# define TK_AND 261 -# define TK_AS 262 -# define TK_ASC 263 -# define TK_BEFORE 264 -# define TK_BEGIN 265 -# define TK_BETWEEN 266 -# define TK_BITAND 267 -# define TK_BITNOT 268 -# define TK_BITOR 269 -# define TK_BY 270 -# define TK_CASCADE 271 -# define TK_CASE 272 -# define TK_CHAR 273 -# define TK_CHECK 274 -# define TK_CLUSTER 275 -# define TK_COLLATE 276 -# define TK_COLUMN 277 -# define TK_COMMA 278 -# define TK_COMMENT 279 -# define TK_COMMIT 280 -# define TK_CONCAT 281 -# define TK_CONFLICT 282 -# define TK_CONSTRAINT 283 -# define TK_COPY 284 -# define TK_CREATE 285 -# define TK_DEFAULT 286 -# define TK_DEFERRABLE 287 -# define TK_DEFERRED 288 -# define TK_DELETE 289 -# define TK_DELIMITERS 290 -# define TK_DESC 291 -# define TK_DISTINCT 292 -# define TK_DOT 293 -# define TK_DROP 294 -# define TK_EACH 295 -# define TK_ELSE 296 -# define TK_END 297 -# define TK_END_OF_FILE 298 -# define TK_EQ 299 -# define TK_EXCEPT 300 -# define TK_EXPLAIN 301 -# define TK_FAIL 302 -# define TK_FLOAT 303 -# define TK_FOR 304 -# define TK_FOREIGN 305 -# define TK_FROM 306 -# define TK_FUNCTION 307 -# define TK_GE 308 -# define TK_GLOB 309 -# define TK_GROUP 310 -# define TK_GT 311 -# define TK_HAVING 312 -# define TK_HOLD 313 -# define TK_IGNORE 314 -# define TK_ILLEGAL 315 -# define TK_IMMEDIATE 316 -# define TK_IN 317 -# define TK_INDEX 318 -# define TK_INITIALLY 319 -# define TK_ID 320 -# define TK_INSERT 321 -# define TK_INSTEAD 322 -# define TK_INT 323 -# define TK_INTEGER 324 -# define TK_INTERSECT 325 -# define TK_INTO 326 -# define TK_IS 327 -# define TK_ISNULL 328 -# define TK_JOIN 329 -# define TK_JOIN_KW 330 -# define TK_KEY 331 -# define TK_LE 332 -# define TK_LIKE 333 -# define TK_LIMIT 334 -# define TK_LONG 335 -# define TK_LONGCHAR 336 -# define TK_LP 337 -# define TK_LSHIFT 338 -# define TK_LT 339 -# define TK_LOCALIZABLE 340 -# define TK_MATCH 341 -# define TK_MINUS 342 -# define TK_NE 343 -# define TK_NOT 344 -# define TK_NOTNULL 345 -# define TK_NULL 346 -# define TK_OBJECT 347 -# define TK_OF 348 -# define TK_OFFSET 349 -# define TK_ON 350 -# define TK_OR 351 -# define TK_ORACLE_OUTER_JOIN 352 -# define TK_ORDER 353 -# define TK_PLUS 354 -# define TK_PRAGMA 355 -# define TK_PRIMARY 356 -# define TK_RAISE 357 -# define TK_REFERENCES 358 -# define TK_REM 359 -# define TK_REPLACE 360 -# define TK_RESTRICT 361 -# define TK_ROLLBACK 362 -# define TK_ROW 363 -# define TK_RP 364 -# define TK_RSHIFT 365 -# define TK_SELECT 366 -# define TK_SEMI 367 -# define TK_SET 368 -# define TK_SHORT 369 -# define TK_SLASH 370 -# define TK_SPACE 371 -# define TK_STAR 372 -# define TK_STATEMENT 373 -# define TK_STRING 374 -# define TK_TABLE 375 -# define TK_TEMP 376 -# define TK_THEN 377 -# define TK_TRANSACTION 378 -# define TK_TRIGGER 379 -# define TK_UMINUS 380 -# define TK_UNCLOSED_STRING 381 -# define TK_UNION 382 -# define TK_UNIQUE 383 -# define TK_UPDATE 384 -# define TK_UPLUS 385 -# define TK_USING 386 -# define TK_VACUUM 387 -# define TK_VALUES 388 -# define TK_VIEW 389 -# define TK_WHEN 390 -# define TK_WHERE 391 -# define TK_WILDCARD 392 -# define END_OF_FILE 393 -# define ILLEGAL 394 -# define SPACE 395 -# define UNCLOSED_STRING 396 -# define COMMENT 397 -# define FUNCTION 398 -# define COLUMN 399 - - -#endif /* not BISON_SQL_TAB_H */ +/* A Bison parser, made by GNU Bison 1.875b. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TK_ABORT = 258, + TK_AFTER = 259, + TK_AGG_FUNCTION = 260, + TK_ALL = 261, + TK_AND = 262, + TK_AS = 263, + TK_ASC = 264, + TK_BEFORE = 265, + TK_BEGIN = 266, + TK_BETWEEN = 267, + TK_BITAND = 268, + TK_BITNOT = 269, + TK_BITOR = 270, + TK_BY = 271, + TK_CASCADE = 272, + TK_CASE = 273, + TK_CHAR = 274, + TK_CHECK = 275, + TK_CLUSTER = 276, + TK_COLLATE = 277, + TK_COLUMN = 278, + TK_COMMA = 279, + TK_COMMENT = 280, + TK_COMMIT = 281, + TK_CONCAT = 282, + TK_CONFLICT = 283, + TK_CONSTRAINT = 284, + TK_COPY = 285, + TK_CREATE = 286, + TK_DEFAULT = 287, + TK_DEFERRABLE = 288, + TK_DEFERRED = 289, + TK_DELETE = 290, + TK_DELIMITERS = 291, + TK_DESC = 292, + TK_DISTINCT = 293, + TK_DOT = 294, + TK_DROP = 295, + TK_EACH = 296, + TK_ELSE = 297, + TK_END = 298, + TK_END_OF_FILE = 299, + TK_EQ = 300, + TK_EXCEPT = 301, + TK_EXPLAIN = 302, + TK_FAIL = 303, + TK_FLOAT = 304, + TK_FOR = 305, + TK_FOREIGN = 306, + TK_FROM = 307, + TK_FUNCTION = 308, + TK_GE = 309, + TK_GLOB = 310, + TK_GROUP = 311, + TK_GT = 312, + TK_HAVING = 313, + TK_HOLD = 314, + TK_IGNORE = 315, + TK_ILLEGAL = 316, + TK_IMMEDIATE = 317, + TK_IN = 318, + TK_INDEX = 319, + TK_INITIALLY = 320, + TK_ID = 321, + TK_INSERT = 322, + TK_INSTEAD = 323, + TK_INT = 324, + TK_INTEGER = 325, + TK_INTERSECT = 326, + TK_INTO = 327, + TK_IS = 328, + TK_ISNULL = 329, + TK_JOIN = 330, + TK_JOIN_KW = 331, + TK_KEY = 332, + TK_LE = 333, + TK_LIKE = 334, + TK_LIMIT = 335, + TK_LONG = 336, + TK_LONGCHAR = 337, + TK_LP = 338, + TK_LSHIFT = 339, + TK_LT = 340, + TK_LOCALIZABLE = 341, + TK_MATCH = 342, + TK_MINUS = 343, + TK_NE = 344, + TK_NOT = 345, + TK_NOTNULL = 346, + TK_NULL = 347, + TK_OBJECT = 348, + TK_OF = 349, + TK_OFFSET = 350, + TK_ON = 351, + TK_OR = 352, + TK_ORACLE_OUTER_JOIN = 353, + TK_ORDER = 354, + TK_PLUS = 355, + TK_PRAGMA = 356, + TK_PRIMARY = 357, + TK_RAISE = 358, + TK_REFERENCES = 359, + TK_REM = 360, + TK_REPLACE = 361, + TK_RESTRICT = 362, + TK_ROLLBACK = 363, + TK_ROW = 364, + TK_RP = 365, + TK_RSHIFT = 366, + TK_SELECT = 367, + TK_SEMI = 368, + TK_SET = 369, + TK_SHORT = 370, + TK_SLASH = 371, + TK_SPACE = 372, + TK_STAR = 373, + TK_STATEMENT = 374, + TK_STRING = 375, + TK_TABLE = 376, + TK_TEMP = 377, + TK_THEN = 378, + TK_TRANSACTION = 379, + TK_TRIGGER = 380, + TK_UMINUS = 381, + TK_UNCLOSED_STRING = 382, + TK_UNION = 383, + TK_UNIQUE = 384, + TK_UPDATE = 385, + TK_UPLUS = 386, + TK_USING = 387, + TK_VACUUM = 388, + TK_VALUES = 389, + TK_VIEW = 390, + TK_WHEN = 391, + TK_WHERE = 392, + TK_WILDCARD = 393, + COLUMN = 395, + FUNCTION = 396, + COMMENT = 397, + UNCLOSED_STRING = 398, + SPACE = 399, + ILLEGAL = 400, + END_OF_FILE = 401 + }; +#endif +#define TK_ABORT 258 +#define TK_AFTER 259 +#define TK_AGG_FUNCTION 260 +#define TK_ALL 261 +#define TK_AND 262 +#define TK_AS 263 +#define TK_ASC 264 +#define TK_BEFORE 265 +#define TK_BEGIN 266 +#define TK_BETWEEN 267 +#define TK_BITAND 268 +#define TK_BITNOT 269 +#define TK_BITOR 270 +#define TK_BY 271 +#define TK_CASCADE 272 +#define TK_CASE 273 +#define TK_CHAR 274 +#define TK_CHECK 275 +#define TK_CLUSTER 276 +#define TK_COLLATE 277 +#define TK_COLUMN 278 +#define TK_COMMA 279 +#define TK_COMMENT 280 +#define TK_COMMIT 281 +#define TK_CONCAT 282 +#define TK_CONFLICT 283 +#define TK_CONSTRAINT 284 +#define TK_COPY 285 +#define TK_CREATE 286 +#define TK_DEFAULT 287 +#define TK_DEFERRABLE 288 +#define TK_DEFERRED 289 +#define TK_DELETE 290 +#define TK_DELIMITERS 291 +#define TK_DESC 292 +#define TK_DISTINCT 293 +#define TK_DOT 294 +#define TK_DROP 295 +#define TK_EACH 296 +#define TK_ELSE 297 +#define TK_END 298 +#define TK_END_OF_FILE 299 +#define TK_EQ 300 +#define TK_EXCEPT 301 +#define TK_EXPLAIN 302 +#define TK_FAIL 303 +#define TK_FLOAT 304 +#define TK_FOR 305 +#define TK_FOREIGN 306 +#define TK_FROM 307 +#define TK_FUNCTION 308 +#define TK_GE 309 +#define TK_GLOB 310 +#define TK_GROUP 311 +#define TK_GT 312 +#define TK_HAVING 313 +#define TK_HOLD 314 +#define TK_IGNORE 315 +#define TK_ILLEGAL 316 +#define TK_IMMEDIATE 317 +#define TK_IN 318 +#define TK_INDEX 319 +#define TK_INITIALLY 320 +#define TK_ID 321 +#define TK_INSERT 322 +#define TK_INSTEAD 323 +#define TK_INT 324 +#define TK_INTEGER 325 +#define TK_INTERSECT 326 +#define TK_INTO 327 +#define TK_IS 328 +#define TK_ISNULL 329 +#define TK_JOIN 330 +#define TK_JOIN_KW 331 +#define TK_KEY 332 +#define TK_LE 333 +#define TK_LIKE 334 +#define TK_LIMIT 335 +#define TK_LONG 336 +#define TK_LONGCHAR 337 +#define TK_LP 338 +#define TK_LSHIFT 339 +#define TK_LT 340 +#define TK_LOCALIZABLE 341 +#define TK_MATCH 342 +#define TK_MINUS 343 +#define TK_NE 344 +#define TK_NOT 345 +#define TK_NOTNULL 346 +#define TK_NULL 347 +#define TK_OBJECT 348 +#define TK_OF 349 +#define TK_OFFSET 350 +#define TK_ON 351 +#define TK_OR 352 +#define TK_ORACLE_OUTER_JOIN 353 +#define TK_ORDER 354 +#define TK_PLUS 355 +#define TK_PRAGMA 356 +#define TK_PRIMARY 357 +#define TK_RAISE 358 +#define TK_REFERENCES 359 +#define TK_REM 360 +#define TK_REPLACE 361 +#define TK_RESTRICT 362 +#define TK_ROLLBACK 363 +#define TK_ROW 364 +#define TK_RP 365 +#define TK_RSHIFT 366 +#define TK_SELECT 367 +#define TK_SEMI 368 +#define TK_SET 369 +#define TK_SHORT 370 +#define TK_SLASH 371 +#define TK_SPACE 372 +#define TK_STAR 373 +#define TK_STATEMENT 374 +#define TK_STRING 375 +#define TK_TABLE 376 +#define TK_TEMP 377 +#define TK_THEN 378 +#define TK_TRANSACTION 379 +#define TK_TRIGGER 380 +#define TK_UMINUS 381 +#define TK_UNCLOSED_STRING 382 +#define TK_UNION 383 +#define TK_UNIQUE 384 +#define TK_UPDATE 385 +#define TK_UPLUS 386 +#define TK_USING 387 +#define TK_VACUUM 388 +#define TK_VALUES 389 +#define TK_VIEW 390 +#define TK_WHEN 391 +#define TK_WHERE 392 +#define TK_WILDCARD 393 +#define COLUMN 395 +#define FUNCTION 396 +#define COMMENT 397 +#define UNCLOSED_STRING 398 +#define SPACE 399 +#define ILLEGAL 400 +#define END_OF_FILE 401 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 74 "./sql.y" +typedef union YYSTYPE { + struct sql_str str; + LPWSTR string; + string_list *column_list; + value_list *val_list; + MSIVIEW *query; + struct expr *expr; + USHORT column_type; + create_col_info *column_info; + column_assignment update_col_info; +} YYSTYPE; +/* Line 1252 of yacc.c. */ +#line 339 "sql.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + + + diff --git a/reactos/lib/msi/sql.y b/reactos/lib/msi/sql.y index 709e78e3601..892dd9ad9e9 100644 --- a/reactos/lib/msi/sql.y +++ b/reactos/lib/msi/sql.y @@ -62,9 +62,9 @@ static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r ); static struct expr * EXPR_column( LPWSTR ); -static struct expr * EXPR_ival( struct sql_str *); +static struct expr * EXPR_ival( struct sql_str *, int sign); static struct expr * EXPR_sval( struct sql_str *); -static struct expr * EXPR_wildcard(void); +static struct expr * EXPR_wildcard(); %} @@ -543,7 +543,11 @@ column_assignment: const_val: TK_INTEGER { - $$ = EXPR_ival( &$1 ); + $$ = EXPR_ival( &$1, 1 ); + } + | TK_MINUS TK_INTEGER + { + $$ = EXPR_ival( &$2, -1 ); } | TK_STRING { @@ -717,13 +721,13 @@ static struct expr * EXPR_column( LPWSTR str ) return e; } -static struct expr * EXPR_ival( struct sql_str *str ) +static struct expr * EXPR_ival( struct sql_str *str , int sign) { struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e ); if( e ) { e->type = EXPR_IVAL; - e->u.ival = atoiW( str->data ); + e->u.ival = atoiW( str->data ) * sign; } return e; } diff --git a/reactos/lib/msi/table.c b/reactos/lib/msi/table.c index 7f097e9d0ad..52a5f01652a 100644 --- a/reactos/lib/msi/table.c +++ b/reactos/lib/msi/table.c @@ -1088,7 +1088,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT * return ERROR_FUNCTION_FAILED; } - TRACE("Data [%d][%d] = %d \n", row, col, *val ); + /* TRACE("Data [%d][%d] = %d \n", row, col, *val ); */ return ERROR_SUCCESS; } diff --git a/reactos/lib/msi/where.c b/reactos/lib/msi/where.c index 8500deec1eb..9ae20480cb9 100644 --- a/reactos/lib/msi/where.c +++ b/reactos/lib/msi/where.c @@ -137,7 +137,7 @@ static const WCHAR *STRING_evaluate( string_table *st, switch( expr->type ) { - case EXPR_COL_NUMBER: + case EXPR_COL_NUMBER_STRING: r = table->ops->fetch_int( table, row, expr->u.col_number, &val ); if( r != ERROR_SUCCESS ) return NULL; @@ -190,6 +190,7 @@ static UINT WHERE_evaluate( MSIDATABASE *db, MSIVIEW *table, UINT row, switch( cond->type ) { + case EXPR_COL_NUMBER_STRING: case EXPR_COL_NUMBER: return table->ops->fetch_int( table, row, cond->u.col_number, val ); @@ -368,9 +369,19 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr r = VIEW_find_column( table, cond->u.column, &val ); if( r == ERROR_SUCCESS ) { - *valid = 1; - cond->type = EXPR_COL_NUMBER; - cond->u.col_number = val; + UINT type = 0; + r = table->ops->get_column_info( table, val, NULL, &type ); + if( r == ERROR_SUCCESS ) + { + if (type&MSITYPE_STRING) + cond->type = EXPR_COL_NUMBER_STRING; + else + cond->type = EXPR_COL_NUMBER; + cond->u.col_number = val; + *valid = 1; + } + else + *valid = 0; } else { @@ -390,7 +401,9 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr /* check the type of the comparison */ if( ( cond->u.expr.left->type == EXPR_SVAL ) || - ( cond->u.expr.right->type == EXPR_SVAL ) ) + ( cond->u.expr.left->type == EXPR_COL_NUMBER_STRING ) || + ( cond->u.expr.right->type == EXPR_SVAL ) || + ( cond->u.expr.right->type == EXPR_COL_NUMBER_STRING ) ) { switch( cond->u.expr.op ) { diff --git a/reactos/lib/msimg32/msimg32.xml b/reactos/lib/msimg32/msimg32.xml new file mode 100644 index 00000000000..0e228270d7f --- /dev/null +++ b/reactos/lib/msimg32/msimg32.xml @@ -0,0 +1,11 @@ + + + . + include + + ntdll + kernel32 + gdi32 + msimg32_main.c + msimg32.spec + diff --git a/reactos/lib/msvcrt/Makefile b/reactos/lib/msvcrt/Makefile index 0c3976c27c0..86fed1639d3 100644 --- a/reactos/lib/msvcrt/Makefile +++ b/reactos/lib/msvcrt/Makefile @@ -15,9 +15,9 @@ TARGET_BASE = $(TARGET_BASE_LIB_MSVCRT) # don't remove @nn from exported symbols - needed so dlltool doesn't mess up mangled c++ exports RM_AT_FROM_SYMBOLS = no -TARGET_LFLAGS = -nostartfiles --enable-stdcall-fixup +TARGET_LFLAGS = -nostartfiles -nostdlib -TARGET_SDKLIBS = wine.a string.a kernel32.a ntdll.a +TARGET_SDKLIBS = crt.a string.a kernel32.a ntdll.a wine.a TARGET_GCCLIBS = gcc @@ -33,477 +33,10 @@ TARGET_CFLAGS += \ -DUSE_MSVCRT_PREFIX \ -D_MT -TARGET_OBJECTS = $(TARGET_NAME).o - -TARGET_CLEAN = \ - conio/*.o \ - ctype/*.o \ - direct/*.o \ - except/*.o \ - float/*.o \ - io/*.o \ - locale/*.o \ - math/*.o \ - mbstring/*.o \ - misc/*.o \ - process/*.o \ - search/*.o \ - setjmp/*.o \ - setjmp/i386/*.o \ - signal/*.o \ - stdio/*.o \ - stdlib/*.o \ - string/*.o \ - sys_stat/*.o \ - time/*.o \ - wine/*.o \ - wstring/*.o - +TARGET_OBJECTS = dllmain.o include $(PATH_TO_TOP)/rules.mak include $(TOOLS_PATH)/helper.mk - -CONIO_OBJECTS = \ - conio/cgets.o \ - conio/cprintf.o \ - conio/cputs.o \ - conio/cscanf.o \ - conio/getch.o \ - conio/getche.o \ - conio/kbhit.o \ - conio/putch.o \ - conio/ungetch.o - -CTYPE_OBJECTS = \ - ctype/ctype.o \ - ctype/isalnum.o \ - ctype/isalpha.o \ - ctype/isascii.o \ - ctype/iscntrl.o \ - ctype/isdigit.o \ - ctype/isgraph.o \ - ctype/islower.o \ - ctype/isprint.o \ - ctype/ispunct.o \ - ctype/isspace.o \ - ctype/isupper.o \ - ctype/isxdigit.o \ - ctype/toascii.o \ - ctype/tolower.o \ - ctype/toupper.o \ - ctype/iscsym.o \ - ctype/isctype.o - -DIRECT_OBJECTS = \ - direct/chdir.o \ - direct/chdrive.o \ - direct/getcwd.o \ - direct/getdcwd.o \ - direct/getdfree.o \ - direct/getdrive.o \ - direct/mkdir.o \ - direct/rmdir.o \ - direct/wchdir.o \ - direct/wgetcwd.o \ - direct/wgetdcwd.o \ - direct/wmkdir.o \ - direct/wrmdir.o - -EXCEPT_OBJECTS = \ - except/seh.o \ - except/abnorter.o \ - except/exhand2.o \ - except/matherr.o \ - except/unwind.o \ - except/xcptfil.o - -FLOAT_OBJECTS = \ - float/chgsign.o \ - float/clearfp.o \ - float/cntrlfp.o \ - float/copysign.o \ - float/fpclass.o \ - float/fpecode.o \ - float/fpreset.o \ - float/isnan.o \ - float/logb.o \ - float/nafter.o \ - float/scalb.o \ - float/statfp.o - -IO_OBJECTS = \ - io/access.o \ - io/chmod.o \ - io/chsize.o \ - io/close.o \ - io/commit.o \ - io/create.o \ - io/dup.o \ - io/dup2.o \ - io/eof.o \ - io/filelen.o \ - io/fileleni.o \ - io/find.o \ - io/fmode.o \ - io/isatty.o \ - io/locking.o \ - io/lseek.o \ - io/lseeki64.o \ - io/mktemp.o \ - io/open.o \ - io/pipe.o \ - io/read.o \ - io/setmode.o \ - io/sopen.o \ - io/stubs.o \ - io/tell.o \ - io/telli64.o \ - io/umask.o \ - io/unlink.o \ - io/utime.o \ - io/waccess.o \ - io/wchmod.o \ - io/wcreate.o \ - io/wfind.o \ - io/wmktemp.o \ - io/wopen.o \ - io/write.o \ - io/wunlink.o \ - io/wutime.o - -LOCALE_OBJECTS = \ - locale/locale.o - -MATH_OBJECTS = \ - math/acos.o \ - math/adjust.o \ - math/asin.o \ - math/atan.o \ - math/atan2.o \ - math/cabs.o \ - math/ceil.o \ - math/cos.o \ - math/cosh.o \ - math/exp.o \ - math/fabs.o \ - math/floor.o \ - math/fmod.o \ - math/frexp.o \ - math/huge_val.o \ - math/hypot.o \ - math/j0_y0.o \ - math/j1_y1.o \ - math/jn_yn.o \ - math/ldexp.o \ - math/log.o \ - math/log10.o \ - math/modf.o \ - math/pow.o \ - math/sin.o \ - math/sinh.o \ - math/sqrt.o \ - math/stubs.o \ - math/tan.o \ - math/tanh.o - -MBSTRING_OBJECTS = \ - mbstring/hanzen.o \ - mbstring/ischira.o \ - mbstring/iskana.o \ - mbstring/iskpun.o \ - mbstring/islead.o \ - mbstring/islwr.o \ - mbstring/ismbal.o \ - mbstring/ismbaln.o \ - mbstring/ismbc.o \ - mbstring/ismbgra.o \ - mbstring/ismbkaln.o \ - mbstring/ismblead.o \ - mbstring/ismbpri.o \ - mbstring/ismbpun.o \ - mbstring/ismbtrl.o \ - mbstring/isuppr.o \ - mbstring/jistojms.o \ - mbstring/jmstojis.o \ - mbstring/mbbtype.o \ - mbstring/mbccpy.o \ - mbstring/mbclen.o \ - mbstring/mbscat.o \ - mbstring/mbschr.o \ - mbstring/mbscmp.o \ - mbstring/mbscoll.o \ - mbstring/mbscpy.o \ - mbstring/mbscspn.o \ - mbstring/mbsdec.o \ - mbstring/mbsdup.o \ - mbstring/mbsicmp.o \ - mbstring/mbsicoll.o \ - mbstring/mbsinc.o \ - mbstring/mbslen.o \ - mbstring/mbslwr.o \ - mbstring/mbsncat.o \ - mbstring/mbsnccnt.o \ - mbstring/mbsncmp.o \ - mbstring/mbsncoll.o \ - mbstring/mbsncpy.o \ - mbstring/mbsnextc.o \ - mbstring/mbsnicmp.o \ - mbstring/mbsnicoll.o \ - mbstring/mbsninc.o \ - mbstring/mbsnset.o \ - mbstring/mbspbrk.o \ - mbstring/mbsrchr.o \ - mbstring/mbsrev.o \ - mbstring/mbsset.o \ - mbstring/mbsspn.o \ - mbstring/mbsspnp.o \ - mbstring/mbsstr.o \ - mbstring/mbstok.o \ - mbstring/mbstrlen.o \ - mbstring/mbsupr.o - -MISC_OBJECTS = \ - misc/amsg.o \ - misc/assert.o \ - misc/crtmain.o \ - misc/dllmain.o \ - misc/environ.o \ - misc/getargs.o \ - misc/initterm.o \ - misc/lock.o \ - misc/purecall.o \ - misc/stubs.o \ - misc/tls.o - -PROCESS_OBJECTS = \ - process/_cwait.o \ - process/_system.o \ - process/dll.o \ - process/process.o \ - process/procid.o \ - process/thread.o \ - process/threadid.o \ - process/threadx.o - -SEARCH_OBJECTS = \ - search/lfind.o \ - search/lsearch.o - -SETJMP_OBJECTS = \ - setjmp/i386/setjmp.o - -SIGNAL_OBJECTS = \ - signal/signal.o - -STDIO_OBJECTS = \ - stdio/allocfil.o \ - stdio/clearerr.o \ - stdio/fclose.o \ - stdio/fdopen.o \ - stdio/feof.o \ - stdio/ferror.o \ - stdio/fflush.o \ - stdio/fgetc.o \ - stdio/fgetchar.o \ - stdio/fgetpos.o \ - stdio/fgets.o \ - stdio/fgetws.o \ - stdio/filbuf.o \ - stdio/fileno.o \ - stdio/flsbuf.o \ - stdio/fopen.o \ - stdio/fprintf.o \ - stdio/fputc.o \ - stdio/fputchar.o \ - stdio/fputs.o \ - stdio/fread.o \ - stdio/freopen.o \ - stdio/fscanf.o \ - stdio/fseek.o \ - stdio/fsetpos.o \ - stdio/fsopen.o \ - stdio/ftell.o \ - stdio/fwalk.o \ - stdio/fwrite.o \ - stdio/getc.o \ - stdio/getchar.o \ - stdio/gets.o \ - stdio/getw.o \ - stdio/perror.o \ - stdio/popen.o \ - stdio/printf.o \ - stdio/putc.o \ - stdio/putchar.o \ - stdio/puts.o \ - stdio/putw.o \ - stdio/remove.o \ - stdio/rename.o \ - stdio/rewind.o \ - stdio/rmtmp.o \ - stdio/scanf.o \ - stdio/setbuf.o \ - stdio/setvbuf.o \ - stdio/sprintf.o \ - stdio/sscanf.o \ - stdio/stdhnd.o \ - stdio/tempnam.o \ - stdio/tmpfile.o \ - stdio/tmpnam.o \ - stdio/ungetc.o \ - stdio/vfprintf.o \ - stdio/vfscanf.o \ - stdio/vfwprint.o \ - stdio/vprintf.o \ - stdio/vscanf.o \ - stdio/vsprintf.o \ - stdio/vsscanf.o \ - stdio/wfdopen.o \ - stdio/wrename.o \ - stdio/wtempnam.o \ - stdio/wtmpnam.o - -STDLIB_OBJECTS = \ - stdlib/_exit.o \ - stdlib/abort.o \ - stdlib/abs.o \ - stdlib/atexit.o \ - stdlib/atof.o \ - stdlib/atoi.o \ - stdlib/atoi64.o \ - stdlib/atol.o \ - stdlib/bsearch.o \ - stdlib/div.o \ - stdlib/ecvt.o \ - stdlib/ecvtbuf.o \ - stdlib/errno.o \ - stdlib/fcvt.o \ - stdlib/fcvtbuf.o \ - stdlib/fullpath.o \ - stdlib/gcvt.o \ - stdlib/getenv.o \ - stdlib/itoa.o \ - stdlib/itow.o \ - stdlib/labs.o \ - stdlib/ldiv.o \ - stdlib/makepath.o \ - stdlib/malloc.o \ - stdlib/mbstowcs.o \ - stdlib/mbtowc.o \ - stdlib/obsol.o \ - stdlib/putenv.o \ - stdlib/qsort.o \ - stdlib/rand.o \ - stdlib/rot.o \ - stdlib/senv.o \ - stdlib/splitp.o \ - stdlib/strtod.o \ - stdlib/strtol.o \ - stdlib/strtoul.o \ - stdlib/swab.o \ - stdlib/wcstod.o \ - stdlib/wcstol.o \ - stdlib/wcstombs.o \ - stdlib/wcstoul.o \ - stdlib/wctomb.o \ - stdlib/wfulpath.o \ - stdlib/witoa.o \ - stdlib/witow.o \ - stdlib/wputenv.o \ - stdlib/wsenv.o \ - stdlib/wsplitp.o \ - stdlib/wmakpath.o \ - stdlib/wtoi.o \ - stdlib/wtoi64.o - -STRING_OBJECTS = \ - string/lasttok.o \ - string/memicmp.o \ - string/strcoll.o \ - string/strdup.o \ - string/strerror.o \ - string/stricmp.o \ - string/strlwr.o \ - string/strncoll.o \ - string/strnicmp.o \ - string/strpbrk.o \ - string/strrev.o\ - string/strset.o \ - string/strstr.o \ - string/strtok.o \ - string/strupr.o \ - string/strxfrm.o - -SYS_STAT_OBJECTS = \ - sys_stat/fstat.o \ - sys_stat/fstati64.o \ - sys_stat/futime.o \ - sys_stat/stat.o \ - sys_stat/wstat.o - -TIME_OBJECTS = \ - time/clock.o \ - time/ctime.o \ - time/difftime.o \ - time/ftime.o \ - time/strdate.o \ - time/strftime.o \ - time/strtime.o \ - time/time.o \ - time/tz_vars.o \ - time/wctime.o \ - time/wstrdate.o \ - time/wstrtime.o - -WINE_OBJECTS = \ - wine/cpp.o \ - wine/cppexcept.o \ - wine/heap.o \ - wine/thread.o - -WSTRING_OBJECTS = \ - wstring/wcscoll.o \ - wstring/wcscspn.o \ - wstring/wcsdup.o \ - wstring/wcsicmp.o \ - wstring/wcslwr.o \ - wstring/wcsnicmp.o \ - wstring/wcspbrk.o \ - wstring/wcsrev.o \ - wstring/wcsset.o \ - wstring/wcsspn.o \ - wstring/wcsstr.o \ - wstring/wcstok.o \ - wstring/wcsupr.o \ - wstring/wcsxfrm.o \ - wstring/wlasttok.o - -OBJECTS = \ - $(CONIO_OBJECTS) \ - $(CTYPE_OBJECTS) \ - $(DIRECT_OBJECTS) \ - $(EXCEPT_OBJECTS) \ - $(FLOAT_OBJECTS) \ - $(IO_OBJECTS) \ - $(LOCALE_OBJECTS) \ - $(MATH_OBJECTS) \ - $(MBSTRING_OBJECTS) \ - $(MISC_OBJECTS) \ - $(PROCESS_OBJECTS) \ - $(SEARCH_OBJECTS) \ - $(SETJMP_OBJECTS) \ - $(SIGNAL_OBJECTS) \ - $(STDIO_OBJECTS) \ - $(STDLIB_OBJECTS) \ - $(STRING_OBJECTS) \ - $(SYS_STAT_OBJECTS) \ - $(TIME_OBJECTS) \ - $(WINE_OBJECTS) \ - $(WSTRING_OBJECTS) - -$(TARGET_NAME).o: $(OBJECTS) - $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o - - # EOF diff --git a/reactos/lib/msvcrt/conio/cprintf.c b/reactos/lib/msvcrt/conio/cprintf.c deleted file mode 100644 index b668157a39d..00000000000 --- a/reactos/lib/msvcrt/conio/cprintf.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -/* - * @unimplemented - */ -int -_cprintf(const char *fmt, ...) -{ - int cnt; - char buf[ 2048 ]; /* this is buggy, because buffer might be too small. */ - va_list ap; - - va_start(ap, fmt); - cnt = vsprintf(buf, fmt, ap); - va_end(ap); - - _cputs(buf); - return cnt; -} diff --git a/reactos/lib/msvcrt/conio/cscanf.c b/reactos/lib/msvcrt/conio/cscanf.c deleted file mode 100644 index 4839931aef7..00000000000 --- a/reactos/lib/msvcrt/conio/cscanf.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include - -/* - * @unimplemented - */ -int _cscanf(char *fmt, ...) -{ - int cnt; - - va_list ap; - - //fixme cscanf should scan the console's keyboard - va_start(ap, fmt); - cnt = __vscanf(fmt, ap); - va_end(ap); - - return cnt; -} diff --git a/reactos/lib/msvcrt/ctype/iscntrl.c b/reactos/lib/msvcrt/ctype/iscntrl.c deleted file mode 100644 index 754d456e06a..00000000000 --- a/reactos/lib/msvcrt/ctype/iscntrl.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - -#undef iswcntrl -/* - * @implemented - */ -int iswcntrl(wint_t c) -{ - return iswctype(c, _CONTROL); -} diff --git a/reactos/lib/msvcrt/ctype/isdigit.c b/reactos/lib/msvcrt/ctype/isdigit.c deleted file mode 100644 index 9b1b7039e34..00000000000 --- a/reactos/lib/msvcrt/ctype/isdigit.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - -#undef isdigit -/* - * @implemented - */ -int isdigit(int c) -{ - return _isctype(c, _DIGIT); -} - -#undef iswdigit -/* - * @implemented - */ -int iswdigit(wint_t c) -{ - return iswctype(c, _DIGIT); -} diff --git a/reactos/lib/msvcrt/ctype/isgraph.c b/reactos/lib/msvcrt/ctype/isgraph.c deleted file mode 100644 index 027e5d29a20..00000000000 --- a/reactos/lib/msvcrt/ctype/isgraph.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - -#undef iswgraph -/* - * @implemented - */ -int iswgraph(wint_t c) -{ - return iswctype(c,_PUNCT | _ALPHA | _DIGIT); -} diff --git a/reactos/lib/msvcrt/ctype/islower.c b/reactos/lib/msvcrt/ctype/islower.c deleted file mode 100644 index 8c1766b535c..00000000000 --- a/reactos/lib/msvcrt/ctype/islower.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - -#undef islower -/* - * @implemented - */ -int islower(int c) -{ - return _isctype(c, _LOWER); -} - -/* - * @implemented - */ -int iswlower(wint_t c) -{ - return iswctype(c, _LOWER); -} diff --git a/reactos/lib/msvcrt/ctype/isprint.c b/reactos/lib/msvcrt/ctype/isprint.c deleted file mode 100644 index 5996783eb53..00000000000 --- a/reactos/lib/msvcrt/ctype/isprint.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -int iswprint(wint_t c) -{ - return iswctype((unsigned short)c,_BLANK | _PUNCT | _ALPHA | _DIGIT); -} diff --git a/reactos/lib/msvcrt/ctype/ispunct.c b/reactos/lib/msvcrt/ctype/ispunct.c deleted file mode 100644 index 7f7bd7e8538..00000000000 --- a/reactos/lib/msvcrt/ctype/ispunct.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - -#undef iswpunct -/* - * @implemented - */ -int iswpunct(wint_t c) -{ - return iswctype(c, _PUNCT); -} diff --git a/reactos/lib/msvcrt/ctype/isupper.c b/reactos/lib/msvcrt/ctype/isupper.c deleted file mode 100644 index f91f7a3138e..00000000000 --- a/reactos/lib/msvcrt/ctype/isupper.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - -#undef isupper - -/* - * @implemented - */ -int iswupper(wint_t c) -{ - return iswctype(c, _UPPER); -} diff --git a/reactos/lib/msvcrt/ctype/isxdigit.c b/reactos/lib/msvcrt/ctype/isxdigit.c deleted file mode 100644 index dbe269d4ee8..00000000000 --- a/reactos/lib/msvcrt/ctype/isxdigit.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - -#undef isxdigit -/* - * @implemented - */ -int isxdigit(int c) -{ - return _isctype(c, _HEX); -} - -#undef iswxdigit -/* - * @implemented - */ -int iswxdigit(wint_t c) -{ - return iswctype(c, _HEX); -} - diff --git a/reactos/lib/msvcrt/ctype/toascii.c b/reactos/lib/msvcrt/ctype/toascii.c deleted file mode 100644 index 9330cf73890..00000000000 --- a/reactos/lib/msvcrt/ctype/toascii.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include - - -/* - * @implemented - */ -int __toascii(int c) -{ - return((unsigned)(c) & 0x7F); -} diff --git a/reactos/lib/msvcrt/direct/getdfree.c b/reactos/lib/msvcrt/direct/getdfree.c deleted file mode 100644 index 84601c43eeb..00000000000 --- a/reactos/lib/msvcrt/direct/getdfree.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "precomp.h" -#include -#include - - -/* - * @implemented - */ -unsigned int _getdiskfree(unsigned int _drive, struct _diskfree_t* _diskspace) -{ - char RootPathName[10]; - - RootPathName[0] = toupper(_drive +'@'); - RootPathName[1] = ':'; - RootPathName[2] = '\\'; - RootPathName[3] = 0; - if (_diskspace == NULL) - return 0; - if (!GetDiskFreeSpaceA(RootPathName,(LPDWORD)&_diskspace->sectors_per_cluster,(LPDWORD)&_diskspace->bytes_per_sector, - (LPDWORD )&_diskspace->avail_clusters,(LPDWORD )&_diskspace->total_clusters)) - return 0; - return _diskspace->avail_clusters; -} diff --git a/reactos/lib/msvcrt/direct/getdrive.c b/reactos/lib/msvcrt/direct/getdrive.c deleted file mode 100644 index 4074bafbd18..00000000000 --- a/reactos/lib/msvcrt/direct/getdrive.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "precomp.h" -#include -#include - - -extern int cur_drive; - -/* - * @implemented - */ -int _getdrive(void) -{ - char Buffer[MAX_PATH]; - - if (cur_drive == 0) { - GetCurrentDirectoryA(MAX_PATH, Buffer); - cur_drive = toupper(Buffer[0] - '@'); - } - return cur_drive; -} - -/* - * @unimplemented - */ -unsigned long _getdrives(void) -{ - //fixme get logical drives - //return GetLogicalDrives(); - return 5; // drive A and C -} diff --git a/reactos/lib/msvcrt/misc/dllmain.c b/reactos/lib/msvcrt/dllmain.c similarity index 98% rename from reactos/lib/msvcrt/misc/dllmain.c rename to reactos/lib/msvcrt/dllmain.c index e8057c6a829..23134c91d29 100644 --- a/reactos/lib/msvcrt/misc/dllmain.c +++ b/reactos/lib/msvcrt/dllmain.c @@ -23,7 +23,7 @@ #include "precomp.h" #include #include -#include "../wine/msvcrt.h" +#include #define NDEBUG #include @@ -62,6 +62,7 @@ BOOL STDCALL DllMain(PVOID hinstDll, ULONG dwReason, PVOID reserved) { + DbgPrint("DllMain"); switch (dwReason) { case DLL_PROCESS_ATTACH://1 diff --git a/reactos/lib/msvcrt/float/cntrlfp.c b/reactos/lib/msvcrt/float/cntrlfp.c deleted file mode 100644 index c093d827e64..00000000000 --- a/reactos/lib/msvcrt/float/cntrlfp.c +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include - -#define X87_CW_IM (1<<0) /* Invalid operation mask */ -#define X87_CW_DM (1<<1) /* Denormal operand mask */ -#define X87_CW_ZM (1<<2) /* Zero divide mask */ -#define X87_CW_OM (1<<3) /* Overflow mask */ -#define X87_CW_UM (1<<4) /* Underflow mask */ -#define X87_CW_PM (1<<5) /* Precision mask */ - -#define X87_CW_PC_MASK (3<<8) /* precision control mask */ -#define X87_CW_PC24 (0<<8) /* 24 bit precision */ -#define X87_CW_PC53 (2<<8) /* 53 bit precision */ -#define X87_CW_PC64 (3<<8) /* 64 bit precision */ - -#define X87_CW_RC_MASK (3<<10) /* rounding control mask */ -#define X87_CW_RC_NEAREST (0<<10) /* round to nearest */ -#define X87_CW_RC_DOWN (1<<10) /* round down */ -#define X87_CW_RC_UP (2<<10) /* round up */ -#define X87_CW_RC_ZERO (3<<10) /* round toward zero (chop) */ - -#define X87_CW_IC (1<<12) /* infinity control flag */ - -/* - * @implemented - */ -unsigned int _controlfp(unsigned int unNew, unsigned int unMask) -{ - return _control87(unNew,unMask); -} - -/* - * @implemented - */ -unsigned int _control87(unsigned int unNew, unsigned int unMask) -{ - unsigned int FpuCw; - unsigned int DummyCw = 0; - - /* get the controlword */ - asm volatile("fstcw %0\n\t" : "=m"(FpuCw)); - FpuCw &= 0x0000ffff; - - /* translate it into _control87 format */ - if (FpuCw & X87_CW_IM) - DummyCw |= _EM_INVALID; - if (FpuCw & X87_CW_DM) - DummyCw |= _EM_DENORMAL; - if (FpuCw & X87_CW_ZM) - DummyCw |= _EM_ZERODIVIDE; - if (FpuCw & X87_CW_OM) - DummyCw |= _EM_OVERFLOW; - if (FpuCw & X87_CW_UM) - DummyCw |= _EM_UNDERFLOW; - if (FpuCw & X87_CW_PM) - DummyCw |= _EM_INEXACT; - - switch (FpuCw & X87_CW_PC_MASK) - { - case X87_CW_PC24: - DummyCw |= _PC_24; - break; - case X87_CW_PC53: - DummyCw |= _PC_53; - break; - case X87_CW_PC64: - DummyCw |= _PC_64; - break; - } - - switch (FpuCw & X87_CW_RC_MASK) - { - case X87_CW_RC_NEAREST: - DummyCw |= _RC_NEAR; - break; - case X87_CW_RC_DOWN: - DummyCw |= _RC_DOWN; - break; - case X87_CW_RC_UP: - DummyCw |= _RC_UP; - break; - case X87_CW_RC_ZERO: - DummyCw |= _RC_CHOP; - break; - } - - /* unset (un)masked bits */ - DummyCw &= ~unMask; - unNew &= unMask; - - /* set new bits */ - DummyCw |= unNew; - - /* translate back into x87 format - * FIXME: translate infinity control! - */ - FpuCw = 0; - if (DummyCw & _EM_INVALID) - FpuCw |= X87_CW_IM; - if (DummyCw & _EM_DENORMAL) - FpuCw |= X87_CW_DM; - if (DummyCw & _EM_ZERODIVIDE) - FpuCw |= X87_CW_ZM; - if (DummyCw & _EM_OVERFLOW) - FpuCw |= X87_CW_OM; - if (DummyCw & _EM_UNDERFLOW) - FpuCw |= X87_CW_UM; - if (DummyCw & _EM_INEXACT) - FpuCw |= X87_CW_PM; - - switch (DummyCw & _MCW_PC) - { - case _PC_24: - FpuCw |= X87_CW_PC24; - break; - case _PC_53: - FpuCw |= X87_CW_PC53; - break; - case _PC_64: - default: - FpuCw |= X87_CW_PC64; - break; - } - - switch (DummyCw & _MCW_RC) - { - case _RC_NEAR: - FpuCw |= X87_CW_RC_NEAREST; - break; - case _RC_DOWN: - FpuCw |= X87_CW_RC_DOWN; - break; - case _RC_UP: - FpuCw |= X87_CW_RC_UP; - break; - case _RC_CHOP: - FpuCw |= X87_CW_RC_ZERO; - break; - } - - /* set controlword */ - asm volatile("fldcw %0" : : "m"(FpuCw)); - - return DummyCw; - -#if 0 /* The follwing is the original code, broken I think! -blight */ -register unsigned int __res; -#ifdef __GNUC__ -__asm__ __volatile__ ( - "pushl %%eax \n\t" /* make room on stack */ - "fstcw (%%esp) \n\t" - "fwait \n\t" - "popl %%eax \n\t" - "andl $0xffff, %%eax \n\t" /* OK; we have the old value ready */ - - "movl %1, %%ecx \n\t" - "notl %%ecx \n\t" - "andl %%eax, %%ecx \n\t" /* the bits we want to keep */ - - "movl %2, %%edx \n\t" - "andl %1, %%edx \n\t" /* the bits we want to change */ - - "orl %%ecx, %%edx\n\t" /* the new value */ - "pushl %%edx \n\t" - "fldcw (%%esp) \n\t" - "popl %%edx \n\t" - - :"=a" (__res):"r" (unNew),"r" (unMask): "dx", "cx"); -#else -#endif /*__GNUC__*/ - return __res; -#endif -} diff --git a/reactos/lib/msvcrt/float/logb.c b/reactos/lib/msvcrt/float/logb.c deleted file mode 100644 index d71c654ee77..00000000000 --- a/reactos/lib/msvcrt/float/logb.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double _logb (double __x) -{ - register double __value; -#ifdef __GNUC__ - register double __junk; - __asm __volatile__ - ("fxtract\n\t" - : "=t" (__junk), "=u" (__value) : "0" (__x)); -#else -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/float/statfp.c b/reactos/lib/msvcrt/float/statfp.c deleted file mode 100644 index e2d2112afb6..00000000000 --- a/reactos/lib/msvcrt/float/statfp.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned int _statusfp (void) -{ - -register unsigned short __res; -#ifdef __GNUC__ -__asm__ __volatile__ ( - "fstsw %0 \n\t" -// "movzwl %ax, %eax" - :"=a" (__res) - ); -#else -#endif /*__GNUC__*/ - return __res; -} diff --git a/reactos/lib/msvcrt/io/chsize.c b/reactos/lib/msvcrt/io/chsize.c deleted file mode 100644 index 678c0f5e24e..00000000000 --- a/reactos/lib/msvcrt/io/chsize.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -#include - -#define NDEBUG -#include - -/* - * @implemented - */ -int _chsize(int _fd, long size) -{ - DPRINT("_chsize(fd %d, size %d)\n", _fd, size); - if (lseek(_fd, size, 0) == -1) - return -1; - if (_write(_fd, 0, 0) < 0) - return -1; - return 0; -} diff --git a/reactos/lib/msvcrt/io/close.c b/reactos/lib/msvcrt/io/close.c deleted file mode 100644 index 9388877e866..00000000000 --- a/reactos/lib/msvcrt/io/close.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "precomp.h" -#include -#include - -#define NDEBUG -#include - -/* - * @implemented - */ -int _close(int _fd) -{ - DPRINT("_close(fd %d)\n", _fd); - if (_fd == -1) - return -1; - if (CloseHandle(_get_osfhandle(_fd)) == FALSE) - return -1; - return __fileno_close(_fd); -} diff --git a/reactos/lib/msvcrt/io/isatty.c b/reactos/lib/msvcrt/io/isatty.c deleted file mode 100644 index a1d67b85289..00000000000 --- a/reactos/lib/msvcrt/io/isatty.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#define NDEBUG -#include - -/* - * @implemented - */ -int _isatty( int fd ) -{ - struct stat buf; - DPRINT("_isatty(fd %d)\n", fd); - if (_fstat (fd, &buf) < 0) - return 0; - if (S_ISCHR (buf.st_mode)) - return 1; - return 0; -} diff --git a/reactos/lib/msvcrt/math/acos.c b/reactos/lib/msvcrt/math/acos.c deleted file mode 100644 index 23376a6116c..00000000000 --- a/reactos/lib/msvcrt/math/acos.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - - -double acos(double __x) -{ - return atan2(sqrt(1.0 - __x * __x), __x); -} diff --git a/reactos/lib/msvcrt/math/asin.c b/reactos/lib/msvcrt/math/asin.c deleted file mode 100644 index fa57df2850c..00000000000 --- a/reactos/lib/msvcrt/math/asin.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - - -double asin(double __x) -{ - return atan2(__x, sqrt(1.0 - __x * __x)); -} diff --git a/reactos/lib/msvcrt/math/atan.c b/reactos/lib/msvcrt/math/atan.c deleted file mode 100644 index af0e219e728..00000000000 --- a/reactos/lib/msvcrt/math/atan.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double atan (double __x); - -double atan (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fld1\n\t" - "fpatan" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_atan(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/atan2.c b/reactos/lib/msvcrt/math/atan2.c deleted file mode 100644 index 8ce57f1e433..00000000000 --- a/reactos/lib/msvcrt/math/atan2.c +++ /dev/null @@ -1,21 +0,0 @@ - -#include - -double atan2 (double __y, double __x); - -/* - * @implemented - */ -double atan2 (double __y, double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fpatan\n\t" - "fld %%st(0)" - : "=t" (__value) : "0" (__x), "u" (__y)); -#else - __value = linkme_atan2(__x, __y); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/cabs.c b/reactos/lib/msvcrt/math/cabs.c deleted file mode 100644 index ca9e8426c73..00000000000 --- a/reactos/lib/msvcrt/math/cabs.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -/* - * @implemented - */ -double _cabs( struct _complex z ) -{ - return sqrt( z.x*z.x + z.y*z.y ); -// return hypot(z.x,z.y); -} - - - - diff --git a/reactos/lib/msvcrt/math/cos.c b/reactos/lib/msvcrt/math/cos.c deleted file mode 100644 index 131fa2dbdb0..00000000000 --- a/reactos/lib/msvcrt/math/cos.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -double cos (double __x); - -/* - * @implemented - */ -double cos (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fcos" - : "=t" (__value): "0" (__x)); -#else - __value = linkme_cos(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/cosh.c b/reactos/lib/msvcrt/math/cosh.c deleted file mode 100644 index a21e717cadc..00000000000 --- a/reactos/lib/msvcrt/math/cosh.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - - -/* - * @implemented - */ -double cosh(double x) -{ - const double ebig = exp(fabs(x)); - return (ebig + 1.0/ebig) / 2.0; -} diff --git a/reactos/lib/msvcrt/math/exp.c b/reactos/lib/msvcrt/math/exp.c deleted file mode 100644 index 2707cf8ca3a..00000000000 --- a/reactos/lib/msvcrt/math/exp.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double exp (double __x); - -double exp (double __x) -{ -#ifdef __GNUC__ - register double __value, __exponent; - __asm __volatile__ - ("fldl2e # e^x = 2^(x * log2(e))\n\t" - "fmul %%st(1) # x * log2(e)\n\t" - "fst %%st(1)\n\t" - "frndint # int(x * log2(e))\n\t" - "fxch\n\t" - "fsub %%st(1) # fract(x * log2(e))\n\t" - "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" - : "=t" (__value), "=u" (__exponent) : "0" (__x)); - __value += 1.0; - __asm __volatile__ - ("fscale" - : "=t" (__value) : "0" (__value), "u" (__exponent)); - - return __value; -#else - return linkme_exp(__x); -#endif /*__GNUC__*/ -} diff --git a/reactos/lib/msvcrt/math/fabs.c b/reactos/lib/msvcrt/math/fabs.c deleted file mode 100644 index 5db505ad11b..00000000000 --- a/reactos/lib/msvcrt/math/fabs.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double fabs (double __x); - -double fabs (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fabs" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_fabs(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/fmod.c b/reactos/lib/msvcrt/math/fmod.c deleted file mode 100644 index 263d6878829..00000000000 --- a/reactos/lib/msvcrt/math/fmod.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double fmod (double __x, double __y); - -double fmod (double __x, double __y) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("1: fprem\n\t" - "fstsw %%ax\n\t" - "sahf\n\t" - "jp 1b" - : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); -#else - __value = linkme_fmod(__x, __y); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/hypot.c b/reactos/lib/msvcrt/math/hypot.c deleted file mode 100644 index de078a140e8..00000000000 --- a/reactos/lib/msvcrt/math/hypot.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -/* - * hypot() function for DJGPP. - * - * hypot() computes sqrt(x^2 + y^2). The problem with the obvious - * naive implementation is that it might fail for very large or - * very small arguments. For instance, for large x or y the result - * might overflow even if the value of the function should not, - * because squaring a large number might trigger an overflow. For - * very small numbers, their square might underflow and will be - * silently replaced by zero; this won't cause an exception, but might - * have an adverse effect on the accuracy of the result. - * - * This implementation tries to avoid the above pitfals, without - * inflicting too much of a performance hit. - * - */ - -#include -#include -#include - -/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers - between these two shouldn't neither overflow nor underflow - when squared. */ -#define __SQRT_DBL_MAX 1.3e+154 -#define __SQRT_DBL_MIN 2.3e-162 - -/* - * @implemented - */ -double -_hypot(double x, double y) -{ - double abig = fabs(x), asmall = fabs(y); - double ratio; - - /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ - if (abig < asmall) - { - double temp = abig; - - abig = asmall; - asmall = temp; - } - - /* Trivial case. */ - if (asmall == 0.) - return abig; - - /* Scale the numbers as much as possible by using its ratio. - For example, if both ABIG and ASMALL are VERY small, then - X^2 + Y^2 might be VERY inaccurate due to loss of - significant digits. Dividing ASMALL by ABIG scales them - to a certain degree, so that accuracy is better. */ - - if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) - return abig * sqrt(1.0 + ratio*ratio); - else - { - /* Slower but safer algorithm due to Moler and Morrison. Never - produces any intermediate result greater than roughly the - larger of X and Y. Should converge to machine-precision - accuracy in 3 iterations. */ - - double r = ratio*ratio, t, s, p = abig, q = asmall; - - do { - t = 4. + r; - if (t == 4.) - break; - s = r / t; - p += 2. * s * p; - q *= s; - r = (q / p) * (q / p); - } while (1); - - return p; - } -} - -#ifdef TEST - -#include - -int -main(void) -{ - printf("hypot(3, 4) =\t\t\t %25.17e\n", _hypot(3., 4.)); - printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", _hypot(3.e+150, 4.e+150)); - printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", _hypot(3.e+306, 4.e+306)); - printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",_hypot(3.e-320, 4.e-320)); - printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",_hypot(0.7*DBL_MAX, 0.7*DBL_MAX)); - printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", _hypot(DBL_MAX, 1.0)); - printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", _hypot(1.0, DBL_MAX)); - printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", _hypot(0.0, DBL_MAX)); - - return 0; -} - -#endif diff --git a/reactos/lib/msvcrt/math/j0_y0.c b/reactos/lib/msvcrt/math/j0_y0.c deleted file mode 100644 index 01143ef3dcc..00000000000 --- a/reactos/lib/msvcrt/math/j0_y0.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - - -/* - * @unimplemented - */ -double _j0(double x) -{ - return x; -} - -/* - * @unimplemented - */ -double _y0(double x) -{ - return x; -} diff --git a/reactos/lib/msvcrt/math/j1_y1.c b/reactos/lib/msvcrt/math/j1_y1.c deleted file mode 100644 index 3c899886491..00000000000 --- a/reactos/lib/msvcrt/math/j1_y1.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - - -/* - * @unimplemented - */ -double _j1(double x) -{ - return x; -} - -/* - * @unimplemented - */ -double _y1(double x) -{ - return x; -} diff --git a/reactos/lib/msvcrt/math/jn_yn.c b/reactos/lib/msvcrt/math/jn_yn.c deleted file mode 100644 index a9304720a2e..00000000000 --- a/reactos/lib/msvcrt/math/jn_yn.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - - -/* - * @unimplemented - */ -double _jn(int n, double x) -{ - return x; -} - -/* - * @unimplemented - */ -double _yn(int n, double x) -{ - return x; -} diff --git a/reactos/lib/msvcrt/math/ldexp.c b/reactos/lib/msvcrt/math/ldexp.c deleted file mode 100644 index 9c603445509..00000000000 --- a/reactos/lib/msvcrt/math/ldexp.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double ldexp (double __x, int __y); - -double ldexp (double __x, int __y) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fscale" - : "=t" (__value) : "0" (__x), "u" ((double) __y)); -#else - __value = linkme_ldexp(__x, __y); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/log.c b/reactos/lib/msvcrt/math/log.c deleted file mode 100644 index 014c78a2304..00000000000 --- a/reactos/lib/msvcrt/math/log.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double log (double __x); - -double log (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fldln2\n\t" - "fxch\n\t" - "fyl2x" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_log(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/log10.c b/reactos/lib/msvcrt/math/log10.c deleted file mode 100644 index 58e8cd6ebc9..00000000000 --- a/reactos/lib/msvcrt/math/log10.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double log10 (double __x); - -double log10 (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fldlg2\n\t" - "fxch\n\t" - "fyl2x" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_log10(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/pow.c b/reactos/lib/msvcrt/math/pow.c deleted file mode 100644 index 3ae40eeae30..00000000000 --- a/reactos/lib/msvcrt/math/pow.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -long double powl (long double __x,long double __y) -{ - return pow(__x,__y/2)*pow(__x,__y/2); -} diff --git a/reactos/lib/msvcrt/math/sin.c b/reactos/lib/msvcrt/math/sin.c deleted file mode 100644 index db070a31d17..00000000000 --- a/reactos/lib/msvcrt/math/sin.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double sin (double __x); - -double sin (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fsin" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_sin(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/sinh.c b/reactos/lib/msvcrt/math/sinh.c deleted file mode 100644 index f977a6acfa5..00000000000 --- a/reactos/lib/msvcrt/math/sinh.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -double sinh(double x) -{ - if(x >= 0.0) - { - const double epos = exp(x); - return (epos - 1.0/epos) / 2.0; - } - else - { - const double eneg = exp(-x); - return (1.0/eneg - eneg) / 2.0; - } -} diff --git a/reactos/lib/msvcrt/math/sqrt.c b/reactos/lib/msvcrt/math/sqrt.c deleted file mode 100644 index d414fcdbc2e..00000000000 --- a/reactos/lib/msvcrt/math/sqrt.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ -#include - -double sqrt (double __x); - -double sqrt (double __x) -{ - register double __value; -#ifdef __GNUC__ - __asm __volatile__ - ("fsqrt" - : "=t" (__value) : "0" (__x)); -#else - __value = linkme_sqrt(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/stubs.c b/reactos/lib/msvcrt/math/stubs.c deleted file mode 100644 index 82fe881ebc0..00000000000 --- a/reactos/lib/msvcrt/math/stubs.c +++ /dev/null @@ -1,133 +0,0 @@ -#include - - -double _CIsin(double x); -double _CIcos(double x); -double _CItan(double x); -double _CIsinh(double x); -double _CIcosh(double x); -double _CItanh(double x); -double _CIasin(double x); -double _CIacos(double x); -double _CIatan(double x); -double _CIatan2(double y, double x); -double _CIexp(double x); -double _CIlog(double x); -double _CIlog10(double x); -double _CIpow(double x, double y); -double _CIsqrt(double x); -double _CIfmod(double x, double y); - - -/* - * @implemented - */ -double _CIsin(double x) -{ - return sin(x); -} -/* - * @implemented - */ -double _CIcos(double x) -{ - return cos(x); -} -/* - * @implemented - */ -double _CItan(double x) -{ - return tan(x); -} -/* - * @implemented - */ -double _CIsinh(double x) -{ - return sinh(x); -} -/* - * @implemented - */ -double _CIcosh(double x) -{ - return cosh(x); -} -/* - * @implemented - */ -double _CItanh(double x) -{ - return tanh(x); -} -/* - * @implemented - */ -double _CIasin(double x) -{ - return asin(x); -} -/* - * @implemented - */ -double _CIacos(double x) -{ - return acos(x); -} -/* - * @implemented - */ -double _CIatan(double x) -{ - return atan(x); -} -/* - * @implemented - */ -double _CIatan2(double y, double x) -{ - return atan2(y, x); -} -/* - * @implemented - */ -double _CIexp(double x) -{ - return exp(x); -} -/* - * @implemented - */ -double _CIlog(double x) -{ - return log(x); -} -/* - * @implemented - */ -double _CIlog10(double x) -{ - return log10(x); -} -/* - * @implemented - */ -double _CIpow(double x, double y) -{ - return pow(x, y); -} -/* - * @implemented - */ -double _CIsqrt(double x) -{ - return sqrt(x); -} -/* - * @implemented - */ -double _CIfmod(double x, double y) -{ - return fmod(x, y); -} diff --git a/reactos/lib/msvcrt/math/tan.c b/reactos/lib/msvcrt/math/tan.c deleted file mode 100644 index 1acc03619f9..00000000000 --- a/reactos/lib/msvcrt/math/tan.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Math functions for i387. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by John C. Bowman , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include - -double tan (double __x); - -double tan (double __x) -{ - register double __value; -#ifdef __GNUC__ - register double __value2 __attribute__ ((unused)); - __asm __volatile__ - ("fptan" - : "=t" (__value2), "=u" (__value) : "0" (__x)); -#else - __value = linkme_tan(__x); -#endif /*__GNUC__*/ - return __value; -} diff --git a/reactos/lib/msvcrt/math/tanh.c b/reactos/lib/msvcrt/math/tanh.c deleted file mode 100644 index 88b9acca5ae..00000000000 --- a/reactos/lib/msvcrt/math/tanh.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -#include - -/* - * @implemented - */ -double tanh(double x) -{ - if (x > 50) - return 1; - else if (x < -50) - return -1; - else - { - const double ebig = exp(x); - const double esmall = 1.0/ebig; - return (ebig - esmall) / (ebig + esmall); - } -} diff --git a/reactos/lib/msvcrt/mbstring/jistojms.c b/reactos/lib/msvcrt/mbstring/jistojms.c deleted file mode 100644 index c47b223a58a..00000000000 --- a/reactos/lib/msvcrt/mbstring/jistojms.c +++ /dev/null @@ -1,27 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned short _mbcjistojms(unsigned short c) -{ - int c1, c2; - - c2 = (unsigned char)c; - c1 = c >> 8; - if (c1 >= 0x21 && c1 <= 0x7e && c2 >= 0x21 && c2 <= 0x7e) { - if (c1 & 0x01) { - c2 += 0x1f; - if (c2 >= 0x7f) - c2 ++; - } else { - c2 += 0x7e; - } - c1 += 0xe1; - c1 >>= 1; - if (c1 >= 0xa0) - c1 += 0x40; - return ((c1 << 8) | c2); - } - return 0; -} diff --git a/reactos/lib/msvcrt/mbstring/jmstojis.c b/reactos/lib/msvcrt/mbstring/jmstojis.c deleted file mode 100644 index cf349f673db..00000000000 --- a/reactos/lib/msvcrt/mbstring/jmstojis.c +++ /dev/null @@ -1,28 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned short _mbcjmstojis(unsigned short c) -{ - int c1, c2; - - c2 = (unsigned char)c; - c1 = c >> 8; - if (c1 < 0xf0 && _ismbblead(c1) && _ismbbtrail(c2)) { - if (c1 >= 0xe0) - c1 -= 0x40; - c1 -= 0x70; - c1 <<= 1; - if (c2 < 0x9f) { - c1 --; - c2 -= 0x1f; - if (c2 >= (0x80-0x1f)) - c2 --; - } else { - c2 -= 0x7e; - } - return ((c1 << 8) | c2); - } - return 0; -} diff --git a/reactos/lib/msvcrt/mbstring/mbsdec.c b/reactos/lib/msvcrt/mbstring/mbsdec.c deleted file mode 100644 index 14c228c81c5..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbsdec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned char * _mbsdec(const unsigned char *str, const unsigned char *cur) -{ - unsigned char *s = (unsigned char *)cur; - if ( str >= cur ) - return NULL; - - s--; - if (_ismbblead(*(s-1)) ) - s--; - - return s; -} diff --git a/reactos/lib/msvcrt/mbstring/mbsinc.c b/reactos/lib/msvcrt/mbstring/mbsinc.c deleted file mode 100644 index 98a5fb5dbd9..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbsinc.c +++ /dev/null @@ -1,13 +0,0 @@ -#include - -/* - * @implemented - */ -unsigned char * _mbsinc(const unsigned char *s) -{ - unsigned char *c = (unsigned char *)s; - if (_ismbblead(*s) ) - c++; - c++; - return c; -} diff --git a/reactos/lib/msvcrt/mbstring/mbslen.c b/reactos/lib/msvcrt/mbstring/mbslen.c deleted file mode 100644 index 8529fbf27f5..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbslen.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - -size_t _mbclen2(const unsigned int s); - -/* - * @implemented - */ -size_t _mbslen(const unsigned char *str) -{ - int i = 0; - unsigned char *s; - - if (str == 0) - return 0; - - for (s = (unsigned char *)str; *s; s+=_mbclen2(*s),i++); - return i; -} diff --git a/reactos/lib/msvcrt/mbstring/mbslwr.c b/reactos/lib/msvcrt/mbstring/mbslwr.c deleted file mode 100644 index 071a7659ca1..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbslwr.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -unsigned int _mbbtolower(unsigned int c) -{ - if (!_ismbblead(c) ) - return tolower(c); - return c; -} - -// code page 952 -#define CASE_DIFF (0x8281 - 0x8260) - -/* - * @implemented - */ -unsigned int _mbctolower(unsigned int c) -{ - if ((c & 0xFF00) != 0) { - // true multibyte case conversion needed - if (_ismbclower(c)) - return c + CASE_DIFF; - } else { - return _mbbtolower(c); - } - return 0; -} - -/* - * @implemented - */ -unsigned char * _mbslwr(unsigned char *x) -{ - unsigned char *y=x; - - while (*y) { - if (!_ismbblead(*y)) { - *y = tolower(*y); - } else { - *y=_mbctolower(*(unsigned short *)y); - y++; - } - } - return x; -} diff --git a/reactos/lib/msvcrt/mbstring/mbsnccnt.c b/reactos/lib/msvcrt/mbstring/mbsnccnt.c deleted file mode 100644 index af739200fd0..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbsnccnt.c +++ /dev/null @@ -1,35 +0,0 @@ -#include - -/* - * @implemented - */ -size_t _mbsnccnt(const unsigned char *str, size_t n) -{ - unsigned char *s = (unsigned char *)str; - size_t cnt = 0; - while(*s != 0 && n > 0) { - if (_ismbblead(*s) ) - s++; - else - n--; - s++; - cnt++; - } - - return cnt; -} - -/* - * @implemented - */ -size_t _mbsnbcnt(const unsigned char *str, size_t n) -{ - unsigned char *s = (unsigned char *)str; - while(*s != 0 && n > 0) { - if (!_ismbblead(*s) ) - n--; - s++; - } - - return (size_t)(s - str); -} diff --git a/reactos/lib/msvcrt/mbstring/mbstrlen.c b/reactos/lib/msvcrt/mbstring/mbstrlen.c deleted file mode 100644 index b8c64cce6f1..00000000000 --- a/reactos/lib/msvcrt/mbstring/mbstrlen.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -/* - * @implemented - */ -size_t _mbstrlen( const char *string ) -{ - char *s = (char *)string; - size_t i = 0; - - while ( *s != 0 ) { - if ( _ismbblead(*s) ) - s++; - s++; - i++; - } - return i; -} diff --git a/reactos/lib/msvcrt/msvcrt.def b/reactos/lib/msvcrt/msvcrt.def index 15e5c2ce422..c640040688b 100644 --- a/reactos/lib/msvcrt/msvcrt.def +++ b/reactos/lib/msvcrt/msvcrt.def @@ -108,7 +108,7 @@ __RTtypeid=MSVCRT___RTtypeid __argc DATA __argv DATA __badioinfo DATA -__crtCompareStringA ;=NTDLL.RtlCompareString +;__crtCompareStringA ;=NTDLL.RtlCompareString ;__crtGetLocaleInfoW __crtLCMapStringA __dllonexit @@ -117,8 +117,8 @@ __fpecode __getmainargs __initenv DATA __isascii=NTDLL.__isascii -__iscsym -__iscsymf +__iscsym=NTDLL.__iscsym +__iscsymf=NTDLL.__iscsymf __lc_codepage __lc_collate_cp __lc_handle @@ -126,7 +126,7 @@ __lc_handle __mb_cur_max DATA __p___argc __p___argv -__p___wargv +;__p___wargv __p___initenv __p___mb_cur_max __p___winitenv @@ -154,14 +154,14 @@ __p__winminor __p__winver ;__p__wpgmptr __pioinfo -;__pxcptinfoptrs +__pxcptinfoptrs __set_app_type __setlc_active DATA __setusermatherr __threadhandle __threadid -__toascii -__unDName +__toascii=NTDLL.__toascii +;__unDName ;__unDNameEx __unguarded_readlc_active DATA __wargv @@ -205,7 +205,7 @@ _aexit_rtn _amsg_exit _assert ;_atodbl -_atoi64 +_atoi64=NTDLL._atoi64 ;_atoldbl _beep _beginthread @@ -281,7 +281,7 @@ _findnexti64 _finite _flsbuf _flushall -_fmode DATA +_fmode=__fmode DATA _fpclass _fpieee_flt _fpreset @@ -311,7 +311,7 @@ _getdrives ;_getmaxstdio ;_getmbcp _getpid -;_getsystime +_getsystime _getw ;_getwch ;_getwche @@ -325,8 +325,8 @@ _heapset ;_heapused _heapwalk _hypot -_i64toa -_i64tow +_i64toa=NTDLL._i64toa +_i64tow=NTDLL._i64tow _initterm ;_inp ;_inpd @@ -364,8 +364,8 @@ _ismbcupper _ismbslead _ismbstrail _isnan -_itoa -_itow +_itoa=NTDLL._itoa +_itow=NTDLL._itow _j0 _j1 _jn @@ -382,7 +382,7 @@ _lrotr _lsearch _lseek _lseeki64 -_ltoa +_ltoa=NTDLL._ltoa _ltow _makepath _mbbtombc @@ -441,7 +441,7 @@ _mbstok _mbstrlen _mbsupr _memccpy -_memicmp +_memicmp=NTDLL._memicmp _mkdir _mktemp ;_mktime64 @@ -481,7 +481,7 @@ _scalb ;_scprintf ;_scwprintf _searchenv -_seh_longjmp_unwind +_seh_longjmp_unwind=_seh_longjmp_unwind@4 ;_set_error_mode ;_set_SSE2_enable ;_set_sbh_threshold @@ -491,12 +491,12 @@ _setjmp3 ;_setmaxstdio _setmbcp _setmode -;_setsystime +_setsystime _sleep -_snprintf=msvcrt__snprintf +_snprintf=crt__snprintf ;_snscanf ;_snwscanf -_snwprintf=msvcrt__snwprintf +_snwprintf=crt__snwprintf _sopen _spawnl _spawnle @@ -506,7 +506,7 @@ _spawnv _spawnve _spawnvp _spawnvpe -_splitpath +_splitpath=NTDLL._splitpath _stat ;_stat64 _stati64 @@ -515,11 +515,11 @@ _strcmpi _strdate _strdup _strerror -_stricmp +_stricmp=NTDLL.stricmp _stricoll -_strlwr +_strlwr=NTDLL._strlwr _strncoll -_strnicmp +_strnicmp=NTDLL.strnicmp _strnicoll _strnset _strrev @@ -536,14 +536,14 @@ _telli64 _tempnam ;_time64 _timezone DATA -_tolower -_toupper +_tolower=NTDLL._tolower +_toupper=NTDLL._toupper _tzname DATA _tzset -_ui64toa -_ui64tow -_ultoa -_ultow +_ui64toa=NTDLL._i64toa +_ui64tow=NTDLL._i64tow +_ultoa=NTDLL._ultoa +_ultow=NTDLL._ultow _umask _ungetch ;_ungetwch @@ -554,8 +554,8 @@ _utime ;_utime64 ;_vscprintf ;_vscwprintf -_vsnprintf=msvcrt__vsnprintf -_vsnwprintf=msvcrt__vsnwprintf +_vsnprintf=crt__vsnprintf +_vsnwprintf=crt__vsnwprintf _waccess _wasctime _wchdir @@ -637,8 +637,8 @@ _wstrtime _wtempnam _wtmpnam ;_wtof -_wtoi -_wtoi64 +_wtoi=NTDLL._wtoi +_wtoi64=NTDLL._wtoi64 _wtol _wunlink _wutime @@ -647,29 +647,29 @@ _y0 _y1 _yn abort -abs +abs=NTDLL.abs acos asctime asin -atan +atan=NTDLL.atan atan2 atexit atof -atoi -atol -bsearch +atoi=NTDLL.atoi +atol=NTDLL.atol +bsearch=NTDLL.bsearch calloc -ceil +ceil=NTDLL.ceil clearerr clock -cos +cos=NTDLL.cos cosh ctime difftime div exit exp -fabs +fabs=NTDLL.fabs fclose feof ferror @@ -679,7 +679,7 @@ fgetpos fgets fgetwc fgetws -floor +floor=NTDLL.floor fmod fopen fprintf @@ -707,41 +707,41 @@ getwchar gmtime is_wctype isalnum=NTDLL.isalnum -isalpha +isalpha=NTDLL.isalpha iscntrl=NTDLL.iscntrl -isdigit +isdigit=NTDLL.isdigit isgraph=NTDLL.isgraph isleadbyte -islower +islower=NTDLL.islower isprint=NTDLL.isprint ispunct=NTDLL.ispunct -isspace +isspace=NTDLL.isspace isupper=NTDLL.isupper iswalnum -iswalpha +iswalpha=NTDLL.iswalpha iswascii iswcntrl -iswctype -iswdigit +iswctype=NTDLL.iswctype +iswdigit=NTDLL.iswdigit iswgraph -iswlower +iswlower=NTDLL.iswlower iswprint iswpunct -iswspace +iswspace=NTDLL.iswspace iswupper -iswxdigit -isxdigit -labs +iswxdigit=NTDLL.iswxdigit +isxdigit=NTDLL.isxdigit +labs=NTDLL.labs ldexp ldiv localeconv localtime -log +log=NTDLL.log log10 longjmp malloc mblen -mbstowcs +mbstowcs=NTDLL.mbstowcs mbtowc memchr memcmp @@ -758,7 +758,7 @@ putchar puts putwc putwchar -qsort +qsort=NTDLL.qsort raise rand realloc @@ -770,15 +770,15 @@ setbuf setlocale setvbuf signal -sin +sin=NTDLL.sin sinh -sprintf=msvcrt_sprintf -sqrt +sprintf=crt_sprintf +sqrt=NTDLL.sqrt srand -sscanf=msvcrt_sscanf +sscanf=crt_sscanf strcat strchr -strcmp +strcmp=NTDLL.strcmp strcoll strcpy strcspn @@ -794,27 +794,27 @@ strspn strstr strtod strtok -strtol +strtol=NTDLL.strtol strtoul strxfrm -swprintf=msvcrt_swprintf +swprintf=crt_swprintf swscanf system -tan +tan=NTDLL.tan tanh time tmpfile tmpnam tolower -toupper -towlower -towupper +toupper=NTDLL.toupper +towlower=NTDLL.towlower +towupper=NTDLL.towupper ungetc ungetwc vfprintf vfwprintf vprintf -vsprintf=msvcrt_vsprintf +vsprintf=crt_vsprintf vswprintf vwprintf wcscat @@ -834,9 +834,9 @@ wcsspn wcsstr wcstod wcstok -wcstol +wcstol=NTDLL.wcstol wcstombs -wcstoul +wcstoul=NTDLL.wcstoul wcsxfrm wctomb wprintf diff --git a/reactos/lib/msvcrt/msvcrt.xml b/reactos/lib/msvcrt/msvcrt.xml index f7fd8d0d0c4..a9bfbdc3819 100644 --- a/reactos/lib/msvcrt/msvcrt.xml +++ b/reactos/lib/msvcrt/msvcrt.xml @@ -17,184 +17,6 @@ kernel32 ntdll crt - - isalpha.c - iscsym.c - isctype.c - isdigit.c - islower.c - isspace.c - isxdigit.c - toascii.c - tolower.c - toupper.c - - - wchdir.c - wgetcwd.c - wgetdcwd.c - wmkdir.c - wrmdir.c - - - abnorter.c - exhand2.c - matherr.c - seh.s - unwind.c - xcptfil.c - - - create.c - dup.c - eof.c - fileleni.c - find.c - fmode.c - lseek.c - lseeki64.c - open.c - pipe.c - read.c - stubs.c - telli64.c - unlink.c - waccess.c - wchmod.c - wcreate.c - wfind.c - wmktemp.c - wopen.c - wunlink.c - wutime.c - - - adjust.c - ceil.c - floor.c - huge_val.c - math.c - - - crtmain.c - dllmain.c - getargs.c - lock.c - purecall.c - stubs.c - tls.c - - - _cwait.c - _system.c - process.c - thread.c - threadx.c - - - ferror.c - fflush.c - fgetchar.c - fgets.c - fgetws.c - filbuf.c - fileno.c - fopen.c - fputchar.c - fputs.c - fread.c - freopen.c - fscanf.c - fsopen.c - ftell.c - fwrite.c - getc.c - getchar.c - gets.c - perror.c - popen.c - printf.c - putc.c - putchar.c - puts.c - remove.c - wfdopen.c - wrename.c - wtempnam.c - wtmpnam.c - - - atoi64.c - atold.c - errno.c - fullpath.c - getenv.c - itow.c - malloc.c - mbstowcs.c - mbtowc.c - putenv.c - qsort.c - rand.c - strtold.c - strtoll.c - strtoull.c - wcstol.c - wcstomb.c - wcstombs.c - wcstoul.c - wctomb.c - wfulpath.c - witoa.c - witow.c - wmakpath.c - wputenv.c - wsenv.c - wsplitp.c - wtoi.c - wtoi64.c - - - memicmp.c - strerror.c - stricmp.c - strlwr.c - strncoll.c - strnicmp.c - strpbrk.c - strstr.c - strupr.c - - - fstat.c - fstati64.c - stat.c - wstat.c - - - ftime.c - tz_vars.c - wctime.c - wstrdate.c - wstrtime.c - - - cpp.c - cppexcept.c - heap.c - thread.c - - - wcscoll.c - wcscspn.c - wcsicmp.c - wcslwr.c - wcsnicmp.c - wcspbrk.c - wcsspn.c - wcsstr.c - wcsupr.c - wlasttok.c - + dllmain.c msvcrt.rc diff --git a/reactos/lib/msvcrt/process/procid.c b/reactos/lib/msvcrt/process/procid.c deleted file mode 100644 index 87c145828c6..00000000000 --- a/reactos/lib/msvcrt/process/procid.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "precomp.h" -#include - -/* - * @implemented - */ -int _getpid (void) -{ - return (int)GetCurrentProcessId(); -} - diff --git a/reactos/lib/msvcrt/search/lfind.c b/reactos/lib/msvcrt/search/lfind.c deleted file mode 100644 index e89efa63c9b..00000000000 --- a/reactos/lib/msvcrt/search/lfind.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - - -/* - * @implemented - */ -void *_lfind(const void *key, const void *base, size_t *nelp, - size_t width, int (*compar)(const void *, const void *)) -{ - char* char_base = (char*)base; - int i; - - for (i = 0; i < *nelp; i++) { - if (compar(key, char_base) == 0) - return char_base; - char_base += width; - } - return NULL; -} - diff --git a/reactos/lib/msvcrt/search/lsearch.c b/reactos/lib/msvcrt/search/lsearch.c deleted file mode 100644 index a8465ae7853..00000000000 --- a/reactos/lib/msvcrt/search/lsearch.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -/* - * @implemented - */ -void *_lsearch(const void *key, void *base, size_t *nelp, size_t width, - int (*compar)(const void *, const void *)) -{ - void *ret_find = _lfind(key,base,nelp,width,compar); - - if (ret_find != NULL) - return ret_find; - -#ifdef __GNUC__ - memcpy(base + (*nelp*width), key, width); -#else - memcpy((int*)base + (*nelp*width), key, width); -#endif - (*nelp)++; - return base; -} - diff --git a/reactos/lib/msvcrt/signal/signal.c b/reactos/lib/msvcrt/signal/signal.c deleted file mode 100644 index 6272b2f6854..00000000000 --- a/reactos/lib/msvcrt/signal/signal.c +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include -#include -#include - -void _default_handler(int signal); - -typedef struct _sig_element -{ - int signal; - char *signame; - _p_sig_fn_t handler; -} sig_element; - -static sig_element signal_list[SIGMAX] = - { - { 0, "Signal 0", SIG_DFL }, - { SIGABRT, "Aborted",SIG_DFL }, - { SIGFPE, "Erroneous arithmetic operation",SIG_DFL }, - { SIGILL, "Illegal instruction",SIG_DFL }, - { SIGINT, "Interrupt",SIG_DFL }, - { SIGSEGV, "Invalid access to storage",SIG_DFL }, - { SIGTERM, "Terminated",SIG_DFL }, - { SIGHUP, "Hangup",SIG_DFL }, - { SIGQUIT, "Quit",SIG_DFL }, - { SIGPIPE, "Broken pipe",SIG_DFL }, - { SIGKILL, "Killed",SIG_DFL }, - { SIGALRM, "Alarm clock",SIG_DFL }, - { 0, "Stopped (signal)",SIG_DFL }, - { 0, "Stopped",SIG_DFL }, - { 0, "Continued",SIG_DFL }, - { 0, "Child exited",SIG_DFL }, - { 0, "Stopped (tty input)",SIG_DFL }, - { 0, "Stopped (tty output)",SIG_DFL }, - { 0, NULL, SIG_DFL } - }; - -int nsignal = 21; - -/* - * @implemented - */ -_p_sig_fn_t signal(int sig, _p_sig_fn_t func) -{ - _p_sig_fn_t temp; - int i; - if(sig <= 0 || sig > SIGMAX || sig == SIGKILL) - { - __set_errno(EINVAL); - return SIG_ERR; - } -// check with IsBadCodePtr - - if ( func < (_p_sig_fn_t)4096 ) { - __set_errno(EINVAL); - return SIG_ERR; - } - - for(i=0;i SIGMAX) - return -1; - for(i=0;i -#include -#include - -#ifdef clearerr -#undef clearerr -void clearerr(FILE *stream); -#endif - -/* - * @implemented - */ -void -clearerr(FILE *f) -{ - if (!__validfp (f)) { - __set_errno (EINVAL); - return; - } - f->_flag &= ~(_IOERR|_IOEOF); -} diff --git a/reactos/lib/msvcrt/stdio/fclose.c b/reactos/lib/msvcrt/stdio/fclose.c deleted file mode 100644 index f39c21f1a91..00000000000 --- a/reactos/lib/msvcrt/stdio/fclose.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include -#include -#include -#include -#include - -// changed check for writable stream - - -/* - * @implemented - */ -int -fclose(FILE *f) -{ - int r = 0; - - if (f == NULL) { - __set_errno (EINVAL); - return EOF; - } - - - -// flush only if stream was opened for writing - if ( !(f->_flag&_IOSTRG) ) { - if ( OPEN4WRITING(f) ) - r = fflush(f); - - if (_close(fileno(f)) < 0) - r = EOF; - if (f->_flag&_IOMYBUF) - free(f->_base); - -// Kernel might do this later - if (f->_flag & _IORMONCL && f->_name_to_remove) - { - remove(f->_name_to_remove); - free(f->_name_to_remove); - f->_name_to_remove = 0; - } - } - f->_cnt = 0; - f->_base = 0; - f->_ptr = 0; - f->_bufsiz = 0; - f->_flag = 0; - f->_file = -1; - return r; -} diff --git a/reactos/lib/msvcrt/stdio/feof.c b/reactos/lib/msvcrt/stdio/feof.c deleted file mode 100644 index 9591e213705..00000000000 --- a/reactos/lib/msvcrt/stdio/feof.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -#ifdef feof -#undef feof -int feof(FILE *stream); -#endif - -/* - * @implemented - */ -int feof(FILE *stream) -{ - if (stream == NULL) { - __set_errno (EINVAL); - return EOF; - } - - return stream->_flag & _IOEOF; -} diff --git a/reactos/lib/msvcrt/stdio/fprintf.c b/reactos/lib/msvcrt/stdio/fprintf.c deleted file mode 100644 index a5589b6de6a..00000000000 --- a/reactos/lib/msvcrt/stdio/fprintf.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -/* - * @implemented - */ -int -fprintf(register FILE *iop, const char *fmt, ...) -{ - int len; - char localbuf[BUFSIZ]; - va_list a=0; - - - va_start( a, fmt ); - if (iop->_flag & _IONBF) - { - iop->_flag &= ~_IONBF; - iop->_ptr = iop->_base = localbuf; - iop->_bufsiz = BUFSIZ; - len = vfprintf(iop,fmt,a); - fflush(iop); - iop->_flag |= _IONBF; - iop->_base = NULL; - iop->_bufsiz = 0; - iop->_cnt = 0; - } - else - len = vfprintf(iop, fmt, a); - return ferror(iop) ? EOF : len; -} - -/* - * @implemented - */ -int -fwprintf(register FILE *iop, const wchar_t *fmt, ...) -{ - int len; - wchar_t localbuf[BUFSIZ]; - va_list a=0; - - - va_start( a, fmt ); - if (iop->_flag & _IONBF) - { - iop->_flag &= ~_IONBF; - iop->_ptr = iop->_base = (char *)localbuf; - iop->_bufsiz = BUFSIZ; - len = vfwprintf(iop,fmt,a); - fflush(iop); - iop->_flag |= _IONBF; - iop->_base = NULL; - iop->_bufsiz = 0; - iop->_cnt = 0; - } - else - len = vfwprintf(iop, fmt, a); - return ferror(iop) ? EOF : len; -} diff --git a/reactos/lib/msvcrt/stdio/putw.c b/reactos/lib/msvcrt/stdio/putw.c deleted file mode 100644 index dab2f31ee0c..00000000000 --- a/reactos/lib/msvcrt/stdio/putw.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 1991 Free Software Foundation, Inc. - * This file is part of the GNU C Library. - * - * The GNU C Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The GNU C Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the GNU C Library; see the file COPYING.LIB. If - * not, write to the Free Software Foundation, Inc., 675 Mass Ave, - * Cambridge, MA 02139, USA. */ - - -#include - - -/* - * Write the word (int) W to STREAM. - * - * @implemented - */ -int _putw(int w,FILE *stream) -{ - /* Is there a better way? */ - if (fwrite( &w, sizeof(w), 1, stream) < 1) - return(EOF); - return(0); -} diff --git a/reactos/lib/msvcrt/stdio/rewind.c b/reactos/lib/msvcrt/stdio/rewind.c deleted file mode 100644 index e3b6703e43e..00000000000 --- a/reactos/lib/msvcrt/stdio/rewind.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -#include -#include -#include - - -/* - * @implemented - */ -void rewind(FILE *f) -{ - fflush(f); - lseek(fileno(f), 0L, SEEK_SET); - f->_cnt = 0; - f->_ptr = f->_base; - f->_flag &= ~(_IOERR|_IOEOF|_IOAHEAD); -} diff --git a/reactos/lib/msvcrt/stdio/setbuf.c b/reactos/lib/msvcrt/stdio/setbuf.c deleted file mode 100644 index b18dfb588b9..00000000000 --- a/reactos/lib/msvcrt/stdio/setbuf.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -/* - * @implemented - */ -void setbuf(FILE *f, char *buf) -{ - if (buf) - setvbuf(f, buf, _IOFBF, BUFSIZ); - else - setvbuf(f, 0, _IONBF, BUFSIZ); -} diff --git a/reactos/lib/msvcrt/stdio/sprintf.c b/reactos/lib/msvcrt/stdio/sprintf.c deleted file mode 100644 index bde188a96f9..00000000000 --- a/reactos/lib/msvcrt/stdio/sprintf.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include - -#undef sprintf -#undef wsprintf - -int -msvcrt_sprintf(char *str, const char *fmt, ...) -{ - va_list arg; - int done; - - va_start (arg, fmt); - done = vsprintf (str, fmt, arg); - va_end (arg); - return done; -} - -int -msvcrt_swprintf(wchar_t *str, const wchar_t *fmt, ...) -{ - va_list arg; - int done; - - va_start (arg, fmt); - done = vswprintf (str, fmt, arg); - va_end (arg); - return done; -} - - - -/* Write formatted output into S, according to the format - string FORMAT, writing no more than MAXLEN characters. */ -/* VARARGS3 */ -int -msvcrt__snprintf (char *s, size_t maxlen,const char *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = _vsnprintf (s, maxlen, format, arg); - va_end (arg); - - return done; -} - -int -msvcrt__snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = _vsnwprintf (s, maxlen, format, arg); - va_end (arg); - - return done; -} - - diff --git a/reactos/lib/msvcrt/stdio/vfscanf.c b/reactos/lib/msvcrt/stdio/vfscanf.c deleted file mode 100644 index 8bd49b7d001..00000000000 --- a/reactos/lib/msvcrt/stdio/vfscanf.c +++ /dev/null @@ -1,1208 +0,0 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __USE_W32API -int __set_errno(int err); -#else -#include -#endif - -/* The internal entry points for `strtoX' take an extra flag argument - saying whether or not to parse locale-dependent number grouping. */ - -double __strtod_internal (const char *__nptr,char **__endptr, int __group); -float __strtof_internal (const char *__nptr, char **__endptr,int __group); -long double __strtold_internal (const char *__nptr,char **__endptr, int __group); -long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group); -unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group); - - -#include // robd -//#ifdef __GNUC__ -//#define HAVE_LONGLONG -//#define LONGLONG LONGLONG -//#else -//#define LONGLONG long -//#endif - -/* Those are flags in the conversion format. */ -# define LONG 0x001 /* l: long or double */ -# define LONGDBL 0x002 /* L: LONGLONG or long double */ -# define SHORT 0x004 /* h: short */ -# define SUPPRESS 0x008 /* *: suppress assignment */ -# define POINTER 0x010 /* weird %p pointer (`fake hex') */ -# define NOSKIP 0x020 /* do not skip blanks */ -# define WIDTH 0x040 /* width was given */ -# define GROUP 0x080 /* ': group numbers */ -# define MALLOC 0x100 /* a: malloc strings */ - -# define TYPEMOD (LONG|LONGDBL|SHORT) - - -# define UNGETC(c, s) ((void) (((wint_t)c) != ((wint_t)EOF) && --read_in), ungetc (c, s)) -# define inchar() ((c = getc (s)), (void) (c != EOF && ++read_in), c) -# define encode_error() do { \ - funlockfile (s); \ - __set_errno (EILSEQ); \ - return done; \ - } while (0) -# define conv_error() do { \ - funlockfile (s); \ - return done; \ - } while (0) -# define input_error() do { \ - funlockfile (s); \ - return done ? 0 : EOF; \ - } while (0) -# define memory_error() do { \ - funlockfile (s); \ - __set_errno (ENOMEM); \ - return EOF; \ - } while (0) -# define ARGCHECK(s, format) \ - do \ - { \ - /* Check file argument for consistence. */ \ - if (!__validfp (s) || !s->__mode.__read) \ - { \ - __set_errno (EBADF); \ - return EOF; \ - } \ - else if (format == NULL) \ - { \ - __set_errno (EINVAL); \ - return EOF; \ - } \ - } while (0) - -# define flockfile(S) /* nothing */ -# define funlockfile(S) /* nothing */ - -# define ADDW(Ch) \ -do{ \ - if (wpsize == wpmax) \ - { \ - char *old = wp; \ - wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \ - wp = (char *) malloc (wpmax); \ - if (old != NULL) \ - { \ - memcpy (wp, old, wpsize); \ - free(old); \ - } \ - } \ - wp[wpsize++] = (Ch); \ -}while(0) - - -int __vfscanf (FILE *s, const char *format, va_list argptr) -{ - va_list arg; - register const char *f = format; - register unsigned char fc; /* Current character of the format. */ - register size_t done = 0; /* Assignments done. */ - register size_t read_in = 0; /* Chars read in. */ - register int c = 0; /* Last char read. */ - register int width; /* Maximum field width. */ - register int flags; /* Modifiers for current format element. */ - - /* Status for reading F-P nums. */ - char got_dot, got_e, negative; - /* If a [...] is a [^...]. */ - char not_in; - /* Base for integral numbers. */ - int base; - /* Signedness for integral numbers. */ - int number_signed; - /* Decimal point character. */ - wchar_t decimal = '.'; - /* The thousands character of the current locale. */ - wchar_t thousands = ','; - /* Integral holding variables. */ - union - { - LONGLONG q; - ULONGLONG uq; - long int l; - unsigned long int ul; - } num; - /* Character-buffer pointer. */ - char *str = NULL; - wchar_t *wstr = NULL; - char **strptr = NULL; - size_t strsize = 0; - /* We must not react on white spaces immediately because they can - possibly be matched even if in the input stream no character is - available anymore. */ - int skip_space = 0; - /* Workspace. */ - char *wp = NULL; /* Workspace. */ - size_t wpmax = 0; /* Maximal size of workspace. */ - size_t wpsize = 0; /* Currently used bytes in workspace. */ - char *tw; /* Temporary pointer. */ - -#ifdef __va_copy - __va_copy (arg, argptr); -#else - arg = (va_list) argptr; -#endif - - - - /* Run through the format string. */ - while (*f != '\0') - { - unsigned int argpos; - /* Extract the next argument, which is of type TYPE. - For a %N$... spec, this is the Nth argument from the beginning; - otherwise it is the next argument after the state now in ARG. */ -#define ARG(type) va_arg(argptr,type) - - if (!isascii (*f)) - { - /* Non-ASCII, may be a multibyte. */ - // int len = mblen (f, strlen (f)); - int len =1; - if (len > 0) - { - do - { - c = inchar (); - if (c == EOF) - input_error (); - else if (c != *f++) - { - UNGETC (c, s); - conv_error (); - } - } - while (--len > 0); - continue; - } - } - - fc = *f++; - if (fc != '%') - { - /* Remember to skip spaces. */ - if (isspace (fc)) - { - skip_space = 1; - continue; - } - - /* Read a character. */ - c = inchar (); - - /* Characters other than format specs must just match. */ - if (c == EOF) - input_error (); - - /* We saw white space char as the last character in the format - string. Now it's time to skip all leading white space. */ - if (skip_space) - { - while (isspace (c)) - if (inchar () == EOF && *_errno() == EINTR) - conv_error (); - skip_space = 0; - } - - if (c != fc) - { - UNGETC (c, s); - conv_error (); - } - - continue; - } - - /* This is the start of the conversion string. */ - flags = 0; - - /* Initialize state of modifiers. */ - argpos = 0; - - /* Prepare temporary buffer. */ - wpsize = 0; - - /* Check for a positional parameter specification. */ - if (isdigit (*f)) - { - argpos = *f++ - '0'; - while (isdigit (*f)) - argpos = argpos * 10 + (*f++ - '0'); - if (*f == '$') - ++f; - else - { - /* Oops; that was actually the field width. */ - width = argpos; - flags |= WIDTH; - argpos = 0; - goto got_width; - } - } - - /* Check for the assignment-suppressing and the number grouping flag. */ - while (*f == '*' || *f == '\'') - switch (*f++) - { - case '*': - flags |= SUPPRESS; - break; - case '\'': - flags |= GROUP; - break; - } - - /* We have seen width. */ - if (isdigit (*f)) - flags |= WIDTH; - - /* Find the maximum field width. */ - width = 0; - while (isdigit (*f)) - { - width *= 10; - width += *f++ - '0'; - } - got_width: - if (width == 0) - width = -1; - - /* Check for type modifiers. */ - while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q') - switch (*f++) - { - case 'h': - /* int's are short int's. */ - if (flags & TYPEMOD) - /* Signal illegal format element. */ - conv_error (); - flags |= SHORT; - break; - case 'l': - if (flags & (SHORT|LONGDBL)) - conv_error (); - else if (flags & LONG) - { - /* A double `l' is equivalent to an `L'. */ - flags &= ~LONG; - flags |= LONGDBL; - } - else - /* int's are long int's. */ - flags |= LONG; - break; - case 'q': - case 'L': - /* double's are long double's, and int's are LONGLONG int's. */ - if (flags & TYPEMOD) - /* Signal illegal format element. */ - conv_error (); - flags |= LONGDBL; - break; - case 'a': - if (flags & TYPEMOD) - /* Signal illegal format element. */ - conv_error (); - /* String conversions (%s, %[) take a `char **' - arg and fill it in with a malloc'd pointer. */ - flags |= MALLOC; - break; - } - - /* End of the format string? */ - if (*f == '\0') - conv_error (); - - /* We must take care for EINTR errors. */ - if (c == EOF && *_errno() == EINTR) - input_error (); - - /* Find the conversion specifier. */ - fc = *f++; - if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) - { - /* Eat whitespace. */ - do - if (inchar () == EOF && *_errno() == EINTR) - input_error (); - while (isspace (c)); - UNGETC (c, s); - skip_space = 0; - } - - switch (fc) - { - case '%': /* Must match a literal '%'. */ - c = inchar (); - if (c != fc) - { - UNGETC (c, s); - conv_error (); - } - break; - - case 'n': /* Answer number of assignments done. */ - /* Corrigendum 1 to ISO C 1990 describes the allowed flags - with the 'n' conversion specifier. */ - if (!(flags & SUPPRESS)) - { - /* Don't count the read-ahead. */ - if (flags & LONGDBL) - *ARG (long int *) = read_in; - else if (flags & LONG) - *ARG (long int *) = read_in; - else if (flags & SHORT) - *ARG (short int *) = read_in; - else - *ARG (int *) = read_in; - -#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1 - /* We have a severe problem here. The ISO C standard - contradicts itself in explaining the effect of the %n - format in `scanf'. While in ISO C:1990 and the ISO C - Amendement 1:1995 the result is described as - - Execution of a %n directive does not effect the - assignment count returned at the completion of - execution of the f(w)scanf function. - - in ISO C Corrigendum 1:1994 the following was added: - - Subclause 7.9.6.2 - Add the following fourth example: - In: - #include - int d1, d2, n1, n2, i; - i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2); - the value 123 is assigned to d1 and the value3 to n1. - Because %n can never get an input failure the value - of 3 is also assigned to n2. The value of d2 is not - affected. The value 3 is assigned to i. - - We go for now with the historically correct code fro ISO C, - i.e., we don't count the %n assignments. When it ever - should proof to be wrong just remove the #ifdef above. */ - ++done; -#endif - } - break; - - case 'c': /* Match characters. */ - if ((flags & LONG) == 0) - { - if (!(flags & SUPPRESS)) - { - str = ARG (char *); - if (str == NULL) - conv_error (); - } - - c = inchar (); - if (c == EOF) - input_error (); - - if (width == -1) - width = 1; - - if (!(flags & SUPPRESS)) - { - do - *str++ = c; - while (--width > 0 && inchar () != EOF); - } - else - while (--width > 0 && inchar () != EOF); - - if (width > 0) - /* I.e., EOF was read. */ - --read_in; - - if (!(flags & SUPPRESS)) - ++done; - - break; - } - /* FALLTHROUGH */ - case 'C': - /* Get UTF-8 encoded wide character. Here we assume (as in - other parts of the libc) that we only have to handle - UTF-8. */ - { - wint_t val; - size_t cnt = 0; - int first = 1; - - if (!(flags & SUPPRESS)) - { - wstr = ARG (wchar_t *); - if (str == NULL) - conv_error (); - } - - do - { -#define NEXT_WIDE_CHAR(First) \ - c = inchar (); \ - if (c == EOF) { \ - /* EOF is only an error for the first character. */ \ - if (First) { \ - input_error (); \ - } \ - else \ - { \ - --read_in; \ - break; \ - } \ - } \ - val = c; \ - if (val >= 0x80) \ - { \ - if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ - encode_error (); \ - if ((c & 0xe0) == 0xc0) \ - { \ - /* We expect two bytes. */ \ - cnt = 1; \ - val &= 0x1f; \ - } \ - else if ((c & 0xf0) == 0xe0) \ - { \ - /* We expect three bytes. */ \ - cnt = 2; \ - val &= 0x0f; \ - } \ - else if ((c & 0xf8) == 0xf0) \ - { \ - /* We expect four bytes. */ \ - cnt = 3; \ - val &= 0x07; \ - } \ - else if ((c & 0xfc) == 0xf8) \ - { \ - /* We expect five bytes. */ \ - cnt = 4; \ - val &= 0x03; \ - } \ - else \ - { \ - /* We expect six bytes. */ \ - cnt = 5; \ - val &= 0x01; \ - } \ - \ - do \ - { \ - c = inchar (); \ - if (c == EOF \ - || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ - encode_error (); \ - val <<= 6; \ - val |= c & 0x3f; \ - } \ - while (--cnt > 0); \ - } \ - \ - if (!(flags & SUPPRESS)) \ - *wstr++ = val; \ - first = 0 - - NEXT_WIDE_CHAR (first); - } - while (--width > 0); - - if (width > 0) - /* I.e., EOF was read. */ - --read_in; - - if (!(flags & SUPPRESS)) - ++done; - } - break; - - case 's': /* Read a string. */ - if (flags & LONG) - /* We have to process a wide character string. */ - goto wide_char_string; - -#define STRING_ARG(Str, Type) \ - if (!(flags & SUPPRESS)) \ - { \ - if (flags & MALLOC) \ - { \ - /* The string is to be stored in a malloc'd buffer. */ \ - strptr = ARG (char **); \ - if (strptr == NULL) \ - conv_error (); \ - /* Allocate an initial buffer. */ \ - strsize = 100; \ - *strptr = malloc (strsize * sizeof (Type)); \ - Str = (Type *) *strptr; \ - } \ - else \ - Str = ARG (Type *); \ - if (Str == NULL) \ - conv_error (); \ - } - STRING_ARG (str, char); - - c = inchar (); - if (c == EOF) - input_error (); - - do - { - if (isspace (c)) - { - UNGETC (c, s); - break; - } -#define STRING_ADD_CHAR(Str, c, Type) \ - if (!(flags & SUPPRESS)) \ - { \ - *Str++ = c; \ - if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \ - { \ - /* Enlarge the buffer. */ \ - Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \ - if (Str == NULL) \ - { \ - /* Can't allocate that much. Last-ditch effort. */\ - Str = realloc (*strptr, \ - (strsize + 1) * sizeof (Type)); \ - if (Str == NULL) \ - { \ - /* We lose. Oh well. \ - Terminate the string and stop converting, \ - so at least we don't skip any input. */ \ - ((Type *) (*strptr))[strsize] = '\0'; \ - ++done; \ - conv_error (); \ - } \ - else \ - { \ - *strptr = (char *) Str; \ - Str = ((Type *) *strptr) + strsize; \ - ++strsize; \ - } \ - } \ - else \ - { \ - *strptr = (char *) Str; \ - Str = ((Type *) *strptr) + strsize; \ - strsize *= 2; \ - } \ - } \ - } - STRING_ADD_CHAR (str, c, char); - } while ((width <= 0 || --width > 0) && inchar () != EOF); - - if (!(flags & SUPPRESS)) - { - *str = '\0'; - ++done; - } - break; - - case 'S': - /* Wide character string. */ - wide_char_string: - { - wint_t val; - int first = 1; - STRING_ARG (wstr, wchar_t); - - do - { - size_t cnt = 0; - NEXT_WIDE_CHAR (first); - - if (iswspace (val)) - { - /* XXX We would have to push back the whole wide char - with possibly many bytes. But since scanf does - not make a difference for white space characters - we can simply push back a simple which is - guaranteed to be in the [:space:] class. */ - UNGETC (' ', s); - break; - } - - STRING_ADD_CHAR (wstr, val, wchar_t); - first = 0; - } - while (width <= 0 || --width > 0); - - if (!(flags & SUPPRESS)) - { - *wstr = L'\0'; - ++done; - } - } - break; - - case 'x': /* Hexadecimal integer. */ - case 'X': /* Ditto. */ - base = 16; - number_signed = 0; - goto number; - - case 'o': /* Octal integer. */ - base = 8; - number_signed = 0; - goto number; - - case 'u': /* Unsigned decimal integer. */ - base = 10; - number_signed = 0; - goto number; - - case 'd': /* Signed decimal integer. */ - base = 10; - number_signed = 1; - goto number; - - case 'i': /* Generic number. */ - base = 0; - number_signed = 1; - - number: - c = inchar (); - if (c == EOF) - input_error (); - - /* Check for a sign. */ - if (c == '-' || c == '+') - { - ADDW (c); - if (width > 0) - --width; - c = inchar (); - } - - /* Look for a leading indication of base. */ - if (width != 0 && c == '0') - { - if (width > 0) - --width; - - ADDW (c); - c = inchar (); - - if (width != 0 && tolower (c) == 'x') - { - if (base == 0) - base = 16; - if (base == 16) - { - if (width > 0) - --width; - c = inchar (); - } - } - else if (base == 0) - base = 8; - } - - if (base == 0) - base = 10; - - /* Read the number into workspace. */ - while (c != EOF && width != 0) - { - if (base == 16 ? !isxdigit (c) : - ((!isdigit (c) || c - '0' >= base) && - !((flags & GROUP) && base == 10 && c == thousands))) - break; - ADDW (c); - if (width > 0) - --width; - - c = inchar (); - } - - /* The just read character is not part of the number anymore. */ - UNGETC (c, s); - - if (wpsize == 0 || - (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) - /* There was no number. */ - conv_error (); - - /* Convert the number. */ - ADDW ('\0'); - if (flags & LONGDBL) - { -// if (number_signed) -// num.q = __strtoq_internal (wp, &tw, base, flags & GROUP); -// else -// num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP); - } - else - { - if (number_signed) - num.l = __strtol_internal (wp, &tw, base, flags & GROUP); - else - num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); - } - if (wp == tw) - conv_error (); - - if (!(flags & SUPPRESS)) - { - if (! number_signed) - { - if (flags & LONGDBL) { - *ARG (ULONGLONG*) = num.uq; - } - else if (flags & LONG) - *ARG (unsigned long int*) = num.ul; - else if (flags & SHORT) - *ARG (unsigned short int*) = (unsigned short int) num.ul; - else - *ARG (unsigned int*) = (unsigned int) num.ul; - } - else - { - if (flags & LONGDBL) { - *ARG (LONGLONG*) = num.q; - } - else if (flags & LONG) - *ARG (long int *) = num.l; - else if (flags & SHORT) - *ARG (short int *) = (short int) num.l; - else - *ARG (int *) = (int) num.l; - } - ++done; - } - break; - - case 'e': /* Floating-point numbers. */ - case 'E': - case 'f': - case 'g': - case 'G': - c = inchar (); - if (c == EOF) - input_error (); - - /* Check for a sign. */ - if (c == '-' || c == '+') - { - negative = c == '-'; - if (inchar () == EOF) - /* EOF is only an input error before we read any chars. */ - conv_error (); - if (width > 0) - --width; - } - else - negative = 0; - - got_dot = got_e = 0; - do - { - if (isdigit (c)) - ADDW (c); - else if (got_e && wp[wpsize - 1] == 'e' - && (c == '-' || c == '+')) - ADDW (c); - else if (wpsize > 0 && !got_e && tolower (c) == 'e') - { - ADDW ('e'); - got_e = got_dot = 1; - } - else if (c == decimal && !got_dot) - { - ADDW (c); - got_dot = 1; - } - else if ((flags & GROUP) && c == thousands && !got_dot) - ADDW (c); - else - { - /* The last read character is not part of the number - anymore. */ - UNGETC (c, s); - break; - } - if (width > 0) - --width; - } - while (width != 0 && inchar () != EOF); - - if (wpsize == 0) - conv_error (); - - /* Convert the number. */ - ADDW ('\0'); - if (flags & LONGDBL) - { - long double d = __strtold_internal (wp, &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != wp) - *ARG (long double *) = negative ? -d : d; - } - else if (flags & LONG) - { - double d = __strtod_internal (wp, &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != wp) - *ARG (double *) = negative ? -d : d; - } - else - { - float d = __strtof_internal (wp, &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != wp) - *ARG (float *) = negative ? -d : d; - } - - if (tw == wp) - conv_error (); - - if (!(flags & SUPPRESS)) - ++done; - break; - - case '[': /* Character class. */ - if (flags & LONG) - { - STRING_ARG (wstr, wchar_t); - c = '\0'; /* This is to keep gcc quiet. */ - } - else - { - STRING_ARG (str, char); - - c = inchar (); - if (c == EOF) - input_error (); - } - - if (*f == '^') - { - ++f; - not_in = 1; - } - else - not_in = 0; - - /* Fill WP with byte flags indexed by character. - We will use this flag map for matching input characters. */ - if (wpmax < UCHAR_MAX) - { - wpmax = UCHAR_MAX; - wp = (char *) alloca (wpmax); - } - memset (wp, 0, UCHAR_MAX); - - fc = *f; - if (fc == ']' || fc == '-') - { - /* If ] or - appears before any char in the set, it is not - the terminator or separator, but the first char in the - set. */ - wp[fc] = 1; - ++f; - } - - while ((fc = *f++) != '\0' && fc != ']') - { - if (fc == '-' && *f != '\0' && *f != ']' && - (unsigned char) f[-2] <= (unsigned char) *f) - { - /* Add all characters from the one before the '-' - up to (but not including) the next format char. */ - for (fc = f[-2]; fc < *f; ++fc) - wp[fc] = 1; - } - else - /* Add the character to the flag map. */ - wp[fc] = 1; - } - if (fc == '\0') - { - if (!(flags & LONG)) - UNGETC (c, s); - conv_error(); - } - - if (flags & LONG) - { - wint_t val; - int first = 1; - - do - { - size_t cnt = 0; - NEXT_WIDE_CHAR (first); - if (val > 255 || wp[val] == not_in) - { - /* XXX We have a problem here. We read a wide - character and this possibly took several - bytes. But we can only push back one single - character. To be sure we don't create wrong - input we push it back only in case it is - representable within one byte. */ - if (val < 0x80) - UNGETC (val, s); - break; - } - STRING_ADD_CHAR (wstr, val, wchar_t); - if (width > 0) - --width; - first = 0; - } - while (width != 0); - - if (first) - conv_error (); - - if (!(flags & SUPPRESS)) - { - *wstr = L'\0'; - ++done; - } - } - else - { - num.ul = read_in - 1; /* -1 because we already read one char. */ - do - { - if (wp[c] == not_in) - { - UNGETC (c, s); - break; - } - STRING_ADD_CHAR (str, c, char); - if (width > 0) - --width; - } - while (width != 0 && inchar () != EOF); - - if (read_in == num.ul) - conv_error (); - - if (!(flags & SUPPRESS)) - { - *str = '\0'; - ++done; - } - } - break; - - case 'p': /* Generic pointer. */ - base = 16; - /* A PTR must be the same size as a `long int'. */ - flags &= ~(SHORT|LONGDBL); - flags |= LONG; - number_signed = 0; - goto number; - } - } - - /* The last thing we saw int the format string was a white space. - Consume the last white spaces. */ - if (skip_space) - { - do - c = inchar (); - while (isspace (c)); - UNGETC (c, s); - } - - - return done; -} - - - -int -xfscanf(FILE *f, const char *fmt, ...) -{ - int r; - va_list a=0; - va_start(a, fmt); - r = __vfscanf(f, fmt, a); - va_end(a); - return r; -} - - -double __strtod_internal (const char *__nptr,char **__endptr, int __group) -{ - return strtod(__nptr,__endptr); -} -float __strtof_internal (const char *__nptr, char **__endptr,int __group) -{ - return (float)strtod(__nptr,__endptr); -} -static double powten[] = -{ - 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, -#ifdef __GNUC__ - 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L -#else - 1e256L, 1e256L, 1e256L, 1e256L -#endif -}; - -long double __strtold_internal (const char *s,char **sret, int __group) -{ - - long double r; /* result */ - int e, ne; /* exponent */ - int sign; /* +- 1.0 */ - int esign; - int flags=0; - int l2powm1; - - r = 0.0L; - sign = 1; - e = ne = 0; - esign = 1; - - while(*s && isspace(*s)) - s++; - - if (*s == '+') - s++; - else if (*s == '-') - { - sign = -1; - s++; - } - - while ((*s >= '0') && (*s <= '9')) - { - flags |= 1; - r *= 10.0L; - r += *s - '0'; - s++; - } - - if (*s == '.') - { - s++; - while ((*s >= '0') && (*s <= '9')) - { - flags |= 2; - r *= 10.0L; - r += *s - '0'; - s++; - ne++; - } - } - if (flags == 0) - { - if (sret) - *sret = (char *)s; - return 0.0L; - } - - if ((*s == 'e') || (*s == 'E')) - { - s++; - if (*s == '+') - s++; - else if (*s == '-') - { - s++; - esign = -1; - } - while ((*s >= '0') && (*s <= '9')) - { - e *= 10; - e += *s - '0'; - s++; - } - } - if (esign < 0) - { - esign = -esign; - e = -e; - } - e = e - ne; - if (e < -4096) - { - /* possibly subnormal number, 10^e would overflow */ - r *= 1.0e-2048L; - e += 2048; - } - if (e < 0) - { - e = -e; - esign = -esign; - } - if (e >= 8192) - e = 8191; - if (e) - { - double d = 1.0L; - l2powm1 = 0; - while (e) - { - if (e & 1) - d *= powten[l2powm1]; - e >>= 1; - l2powm1++; - } - if (esign > 0) - r *= d; - else - r /= d; - } - if (sret) - *sret = (char *)s; - return r * sign; - - return 0; -} -long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group) -{ - return strtol(__nptr,__endptr, __base); -} -unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group) -{ - return strtoul(__nptr,__endptr, __base); -} - - - - - - - - - diff --git a/reactos/lib/msvcrt/stdio/vscanf.c b/reactos/lib/msvcrt/stdio/vscanf.c deleted file mode 100644 index 4c6b7968964..00000000000 --- a/reactos/lib/msvcrt/stdio/vscanf.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include - - -#undef vscanf - - -/* Read formatted input from stdin according to the format - string in FORMAT, using the argument list in ARG. */ -int __vscanf (const char *format, va_list arg) -{ - return __vfscanf(stdin, format, arg); -} - diff --git a/reactos/lib/msvcrt/stdlib/_exit.c b/reactos/lib/msvcrt/stdlib/_exit.c deleted file mode 100644 index cb7b5e1a37b..00000000000 --- a/reactos/lib/msvcrt/stdlib/_exit.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "precomp.h" -#include -#include -#include -#include - -struct __atexit *__atexit_ptr = 0; - -/* - * @implemented - */ -void exit(int status) -{ - //int i; - struct __atexit *a = __atexit_ptr; - __atexit_ptr = 0; /* to prevent infinite loops */ - while (a) - { - (a->__function)(); - a = a->__next; - } -/* - if (__stdio_cleanup_hook) - __stdio_cleanup_hook(); - for (i=0; i -#include -#include -#include - -char *msg ="Abort\n\r"; - -/* - * @implemented - */ -void abort() -{ - fflush(NULL); - fcloseall(); - raise(SIGABRT); - _write(stderr->_file, msg, sizeof(msg)-1); - exit(3); -} - diff --git a/reactos/lib/msvcrt/stdlib/abs.c b/reactos/lib/msvcrt/stdlib/abs.c deleted file mode 100644 index 3efdce831fd..00000000000 --- a/reactos/lib/msvcrt/stdlib/abs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -/* - * @implemented - */ -int -abs(int j) -{ - return j<0 ? -j : j; -} diff --git a/reactos/lib/msvcrt/stdlib/atof.c b/reactos/lib/msvcrt/stdlib/atof.c deleted file mode 100644 index e3021084b92..00000000000 --- a/reactos/lib/msvcrt/stdlib/atof.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -double -atof(const char *ascii) -{ - return strtod(ascii, 0); -} diff --git a/reactos/lib/msvcrt/stdlib/atoi.c b/reactos/lib/msvcrt/stdlib/atoi.c deleted file mode 100644 index df6a0c47002..00000000000 --- a/reactos/lib/msvcrt/stdlib/atoi.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -int -atoi(const char *str) -{ - return (int)strtol(str, 0, 10); -} diff --git a/reactos/lib/msvcrt/stdlib/atol.c b/reactos/lib/msvcrt/stdlib/atol.c deleted file mode 100644 index 663301d95fc..00000000000 --- a/reactos/lib/msvcrt/stdlib/atol.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -long -atol(const char *str) -{ - return strtol(str, 0, 10); -} diff --git a/reactos/lib/msvcrt/stdlib/atold.c b/reactos/lib/msvcrt/stdlib/atold.c deleted file mode 100644 index c9b511684a4..00000000000 --- a/reactos/lib/msvcrt/stdlib/atold.c +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -long double -_atold(const char *ascii) -{ - return _strtold(ascii, 0); -} diff --git a/reactos/lib/msvcrt/stdlib/bsearch.c b/reactos/lib/msvcrt/stdlib/bsearch.c deleted file mode 100644 index 7efbdbd9897..00000000000 --- a/reactos/lib/msvcrt/stdlib/bsearch.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -void * -bsearch(const void *key, const void *base0, size_t nelem, - size_t size, int (*cmp)(const void *ck, const void *ce)) -{ - char *base = (char *)base0; - int lim, cmpval; - void *p; - - for (lim = nelem; lim != 0; lim >>= 1) - { - p = base + (lim >> 1) * size; - cmpval = (*cmp)(key, p); - if (cmpval == 0) - return p; - if (cmpval > 0) - { /* key > p: move right */ - base = (char *)p + size; - lim--; - } /* else move left */ - } - return 0; -} diff --git a/reactos/lib/msvcrt/stdlib/div.c b/reactos/lib/msvcrt/stdlib/div.c deleted file mode 100644 index 56b8b4422f8..00000000000 --- a/reactos/lib/msvcrt/stdlib/div.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -div_t -div(int num, int denom) -{ - div_t r; - - if (num > 0 && denom < 0) { - num = -num; - denom = -denom; - } - r.quot = num / denom; - r.rem = num % denom; - if (num < 0 && denom > 0) - { - if (r.rem > 0) - { - r.quot++; - r.rem -= denom; - } - } - return r; -} diff --git a/reactos/lib/msvcrt/stdlib/ecvt.c b/reactos/lib/msvcrt/stdlib/ecvt.c deleted file mode 100644 index 940ffb2ed27..00000000000 --- a/reactos/lib/msvcrt/stdlib/ecvt.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -char *ecvtbuf (double, int, int *, int *, char *); - -/* - * @implemented - */ -char * -_ecvt (double value, int ndigits, int *decpt, int *sign) -{ - static char ecvt_buf[DBL_MAX_10_EXP + 10]; - return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf); -} diff --git a/reactos/lib/msvcrt/stdlib/ecvtbuf.c b/reactos/lib/msvcrt/stdlib/ecvtbuf.c deleted file mode 100644 index 1d0f65fbba8..00000000000 --- a/reactos/lib/msvcrt/stdlib/ecvtbuf.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include -#include -// #include - -void __ecvround (char *, char *, const char *, int *); - -void -__ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt) -{ - char *p; - int carry = 0; - - /* Do we have at all to round the last digit? */ - if (*after_last > '4') - { - p = last_digit; - carry = 1; - - /* Propagate the rounding through trailing '9' digits. */ - do { - int sum = *p + carry; - carry = sum > '9'; - *p-- = sum - carry * 10; - } while (carry && p >= numbuf); - - /* We have 9999999... which needs to be rounded to 100000.. */ - if (carry && p == numbuf) - { - *p = '1'; - *decpt += 1; - } - } -} - -char * -ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) -{ - static char INFINITY[] = "Infinity"; - char decimal = '.' /* localeconv()->decimal_point[0] */; - char *cvtbuf = (char *)alloca (ndigits + 20); /* +3 for sign, dot, null; */ - /* two extra for rounding */ - /* 15 extra for alignment */ - char *s = cvtbuf, *d = buf; - - /* Produce two extra digits, so we could round properly. */ - sprintf (cvtbuf, "%-+.*E", ndigits + 2, value); - *decpt = 0; - - /* The sign. */ - if (*s++ == '-') - *sign = 1; - else - *sign = 0; - - /* Special values get special treatment. */ - if (strncmp (s, "Inf", 3) == 0) - { - /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */ - memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); - if (ndigits < 8) - buf[3] = '\0'; - } - else if (strcmp (s, "NaN") == 0) - memcpy (buf, s, 4); - else - { - char *last_digit, *digit_after_last; - - /* Copy (the single) digit before the decimal. */ - while (*s && *s != decimal && d - buf < ndigits) - *d++ = *s++; - - /* If we don't see any exponent, here's our decimal point. */ - *decpt = d - buf; - if (*s) - s++; - - /* Copy the fraction digits. */ - while (*s && *s != 'E' && d - buf < ndigits) - *d++ = *s++; - - /* Remember the last digit copied and the one after it. */ - last_digit = d > buf ? d - 1 : d; - digit_after_last = s; - - /* Get past the E in exponent field. */ - while (*s && *s++ != 'E') - ; - - /* Adjust the decimal point by the exponent value. */ - *decpt += atoi (s); - - /* Pad with zeroes if needed. */ - while (d - buf < ndigits) - *d++ = '0'; - - /* Zero-terminate. */ - *d = '\0'; - - /* Round if necessary. */ - __ecvround (buf, last_digit, digit_after_last, decpt); - } - return buf; -} diff --git a/reactos/lib/msvcrt/stdlib/fcvt.c b/reactos/lib/msvcrt/stdlib/fcvt.c deleted file mode 100644 index 423b7f2380d..00000000000 --- a/reactos/lib/msvcrt/stdlib/fcvt.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -char *fcvtbuf (double, int, int *, int *, char *); - -/* - * @implemented - */ -char * -_fcvt (double value, int ndigits, int *decpt, int *sign) -{ - static char fcvt_buf[2 * DBL_MAX_10_EXP + 10]; - return fcvtbuf (value, ndigits, decpt, sign, fcvt_buf); -} diff --git a/reactos/lib/msvcrt/stdlib/fcvtbuf.c b/reactos/lib/msvcrt/stdlib/fcvtbuf.c deleted file mode 100644 index 2bf85aa6483..00000000000 --- a/reactos/lib/msvcrt/stdlib/fcvtbuf.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include -#include -#include -// #include - -void __ecvround (char *, char *, const char *, int *); -char *ecvtbuf (double, int, int *, int *, char *); - -char * -fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) -{ - static char INFINITY[] = "Infinity"; - char decimal = '.' /* localeconv()->decimal_point[0] */; - int digits = ndigits >= 0 ? ndigits : 0; - char *cvtbuf = (char *)alloca (2*DBL_MAX_10_EXP + 16); - char *s = cvtbuf; - char *dot; - - sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value); - - /* The sign. */ - if (*s++ == '-') - *sign = 1; - else - *sign = 0; - - /* Where's the decimal point? */ - dot = strchr (s, decimal); - *decpt = dot ? dot - s : strlen (s); - - /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity" - instead of "Inf". */ - if (strncmp (s, "Inf", 3) == 0) - { - memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); - if (ndigits < 8) - buf[3] = '\0'; - return buf; - } - else if (ndigits < 0) - return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf); - else if (*s == '0' && value != 0.0) - return ecvtbuf (value, ndigits, decpt, sign, buf); - else - { - memcpy (buf, s, *decpt); - if (s[*decpt] == decimal) - { - memcpy (buf + *decpt, s + *decpt + 1, ndigits); - buf[*decpt + ndigits] = '\0'; - } - else - buf[*decpt] = '\0'; - __ecvround (buf, buf + *decpt + ndigits - 1, - s + *decpt + ndigits + 1, decpt); - return buf; - } -} diff --git a/reactos/lib/msvcrt/stdlib/gcvt.c b/reactos/lib/msvcrt/stdlib/gcvt.c deleted file mode 100644 index c077566c83a..00000000000 --- a/reactos/lib/msvcrt/stdlib/gcvt.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -#include -#include -#include - -/* - * @implemented - */ -char * -_gcvt (double value, int ndigits, char *buf) -{ - char *p = buf; - - sprintf (buf, "%-#.*g", ndigits, value); - - /* It seems they expect us to return .XXXX instead of 0.XXXX */ - if (*p == '-') - p++; - if (*p == '0' && p[1] == '.') - memmove (p, p + 1, strlen (p + 1) + 1); - - /* They want Xe-YY, not X.e-YY, and XXXX instead of XXXX. */ - p = strchr (buf, 'e'); - if (!p) - { - p = buf + strlen (buf); - /* They don't want trailing zeroes. */ - while (p[-1] == '0' && p > buf + 2) - *--p = '\0'; - } - if (p > buf && p[-1] == '.') - memmove (p - 1, p, strlen (p) + 1); - return buf; -} diff --git a/reactos/lib/msvcrt/stdlib/labs.c b/reactos/lib/msvcrt/stdlib/labs.c deleted file mode 100644 index 8c1d3fff3f0..00000000000 --- a/reactos/lib/msvcrt/stdlib/labs.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -/* - * @implemented - */ -long -labs(long j) -{ - return j<0 ? -j : j; -} diff --git a/reactos/lib/msvcrt/stdlib/ldiv.c b/reactos/lib/msvcrt/stdlib/ldiv.c deleted file mode 100644 index a40597d0e95..00000000000 --- a/reactos/lib/msvcrt/stdlib/ldiv.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -ldiv_t -ldiv(long num, long denom) -{ - ldiv_t r; - - if (num > 0 && denom < 0) - { - num = -num; - denom = -denom; - } - r.quot = num / denom; - r.rem = num % denom; - if (num < 0 && denom > 0) - { - if (r.rem > 0) - { - r.quot++; - r.rem -= denom; - } - } - return r; -} diff --git a/reactos/lib/msvcrt/stdlib/obsol.c b/reactos/lib/msvcrt/stdlib/obsol.c deleted file mode 100644 index 48e465fc2d0..00000000000 --- a/reactos/lib/msvcrt/stdlib/obsol.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "precomp.h" -#include - -#undef _cpumode -unsigned char _cpumode = 0; -unsigned char *_cpumode_dll = &_cpumode; - -/* - * @implemented - */ -void _seterrormode(int nMode) -{ - SetErrorMode(nMode); - return; -} - -/* - * @implemented - */ -void _beep(unsigned nFreq, unsigned nDur) -{ - Beep(nFreq,nDur); - return; -} - -/* - * @implemented - */ -void _sleep(unsigned long ulTime) -{ - Sleep(ulTime); - return; -} diff --git a/reactos/lib/msvcrt/stdlib/strtod.c b/reactos/lib/msvcrt/stdlib/strtod.c deleted file mode 100644 index 29d936ebdd0..00000000000 --- a/reactos/lib/msvcrt/stdlib/strtod.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -#include - - -/* - * @implemented - */ -double -strtod(const char *s, char **sret) -{ - long double r; /* result */ - int e; /* exponent */ - long double d; /* scale */ - int sign; /* +- 1.0 */ - int esign; - int i; - int flags=0; - - r = 0.0; - sign = 1; - e = 0; - esign = 1; - - while ((*s == ' ') || (*s == '\t')) - s++; - - if (*s == '+') - s++; - else if (*s == '-') - { - sign = -1; - s++; - } - - while ((*s >= '0') && (*s <= '9')) - { - flags |= 1; - r *= 10.0; - r += *s - '0'; - s++; - } - - if (*s == '.') - { - d = 0.1L; - s++; - while ((*s >= '0') && (*s <= '9')) - { - flags |= 2; - r += d * (*s - '0'); - s++; - d *= 0.1L; - } - } - - if (flags == 0) - { - if (sret) - *sret = (char *)s; - return 0; - } - - if ((*s == 'e') || (*s == 'E')) - { - s++; - if (*s == '+') - s++; - else if (*s == '-') - { - s++; - esign = -1; - } - if ((*s < '0') || (*s > '9')) - { - if (sret) - *sret = (char *)s; - return r; - } - - while ((*s >= '0') && (*s <= '9')) - { - e *= 10; - e += *s - '0'; - s++; - } - } - - if (esign < 0) - for (i = 1; i <= e; i++) - r *= 0.1L; - else - for (i = 1; i <= e; i++) - r *= 10.0; - - if (sret) - *sret = (char *)s; - return r * sign; -} diff --git a/reactos/lib/msvcrt/time/difftime.c b/reactos/lib/msvcrt/time/difftime.c deleted file mode 100644 index 9e9d590a2cb..00000000000 --- a/reactos/lib/msvcrt/time/difftime.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ -#include - -/* - * @implemented - */ -double -difftime(time_t time1, time_t time0) -{ - return time1-time0; -} diff --git a/reactos/lib/msvcrt/time/posixrul.h b/reactos/lib/msvcrt/time/posixrul.h deleted file mode 100644 index 48c5ceeab0d..00000000000 --- a/reactos/lib/msvcrt/time/posixrul.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -/* generated with bin2h from DJGPP/zoneinfo/posixrules */ - -unsigned char _posixrules_data[] = { -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, -0,1,16,0,0,0,2,0,0,0,8,0,151,254,240,1,135,225,224,2,119,224,240,3,112,254,96,4,96,253,112,5,80, -224,96,6,64,223,112,7,48,194,96,7,141,25,112,9,16,164,96,9,173,148,240,10,240,134,96,11,224,133,112,12,217,162, -224,13,192,103,112,14,185,132,224,15,169,131,240,16,153,102,224,17,137,101,240,18,121,72,224,19,105,71,240,20,89,42,224, -21,73,41,240,22,57,12,224,23,41,11,240,24,34,41,96,25,8,237,240,26,2,11,96,26,242,10,112,27,225,237,96,28, -209,236,112,29,193,207,96,30,177,206,112,31,161,177,96,32,118,0,240,33,129,147,96,34,85,226,240,35,106,175,224,36,53, -196,240,37,74,145,224,38,21,166,240,39,42,115,224,39,254,195,112,41,10,85,224,41,222,165,112,42,234,55,224,43,190,135, -112,44,211,84,96,45,158,105,112,46,179,54,96,47,126,75,112,48,147,24,96,49,103,103,240,50,114,250,96,51,71,73,240, -52,82,220,96,53,39,43,240,54,50,190,96,55,7,13,240,56,27,218,224,56,230,239,240,57,251,188,224,58,198,209,240,59, -219,158,224,60,175,238,112,61,187,128,224,62,143,208,112,63,155,98,224,64,111,178,112,65,132,127,96,66,79,148,112,67,100, -97,96,68,47,118,112,69,68,67,96,70,15,88,112,71,36,37,96,71,248,116,240,73,4,7,96,73,216,86,240,74,227,233, -96,75,184,56,240,76,205,5,224,77,152,26,240,78,172,231,224,79,119,252,240,80,140,201,224,81,97,25,112,82,108,171,224, -83,64,251,112,84,76,141,224,85,32,221,112,86,44,111,224,87,0,191,112,88,21,140,96,88,224,161,112,89,245,110,96,90, -192,131,112,91,213,80,96,92,169,159,240,93,181,50,96,94,137,129,240,95,149,20,96,96,105,99,240,97,126,48,224,98,73, -69,240,99,94,18,224,100,41,39,240,101,61,244,224,102,18,68,112,103,29,214,224,103,242,38,112,104,253,184,224,105,210,8, -112,106,221,154,224,107,177,234,112,108,198,183,96,109,145,204,112,110,166,153,96,111,113,174,112,112,134,123,96,113,90,202,240, -114,102,93,96,115,58,172,240,116,70,63,96,117,26,142,240,118,47,91,224,118,250,112,240,120,15,61,224,120,218,82,240,121, -239,31,224,122,186,52,240,123,207,1,224,124,163,81,112,125,174,227,224,126,131,51,112,127,142,197,224,128,99,21,112,129,119, -226,96,130,66,247,112,131,87,196,96,132,34,217,112,133,55,166,96,134,11,245,240,135,23,136,96,135,235,215,240,136,247,106, -96,137,203,185,240,138,215,76,96,139,171,155,240,140,192,104,224,141,139,125,240,142,160,74,224,143,107,95,240,144,128,44,224, -145,84,124,112,146,96,14,224,147,52,94,112,148,63,240,224,149,20,64,112,150,41,13,96,150,244,34,112,152,8,239,96,152, -212,4,112,153,232,209,96,154,189,32,240,155,200,179,96,156,157,2,240,157,168,149,96,158,124,228,240,159,136,119,96,160,92, -198,240,161,113,147,224,162,60,168,240,163,81,117,224,164,28,138,240,165,49,87,224,166,5,167,112,167,17,57,224,167,229,137, -112,168,241,27,224,169,197,107,112,170,218,56,96,171,165,77,112,172,186,26,96,173,133,47,112,174,153,252,96,175,101,17,112, -176,121,222,96,177,78,45,240,178,89,192,96,179,46,15,240,180,57,162,96,181,13,241,240,182,34,190,224,182,237,211,240,184, -2,160,224,184,205,181,240,185,226,130,224,186,182,210,112,187,194,100,224,188,150,180,112,189,162,70,224,190,118,150,112,191,130, -40,224,192,86,120,112,193,107,69,96,194,54,90,112,195,75,39,96,196,22,60,112,197,43,9,96,197,255,88,240,199,10,235, -96,199,223,58,240,200,234,205,96,201,191,28,240,202,211,233,224,203,158,254,240,204,179,203,224,205,126,224,240,206,147,173,224, -207,103,253,112,208,115,143,224,209,71,223,112,210,83,113,224,211,39,193,112,212,51,83,224,213,7,163,112,214,28,112,96,214, -231,133,112,215,252,82,96,216,199,103,112,217,220,52,96,218,176,131,240,219,188,22,96,220,144,101,240,221,155,248,96,222,112, -71,240,223,133,20,224,224,80,41,240,225,100,246,224,226,48,11,240,227,68,216,224,228,15,237,240,229,36,186,224,229,249,10, -112,231,4,156,224,231,216,236,112,232,228,126,224,233,184,206,112,234,205,155,96,235,152,176,112,236,173,125,96,237,120,146,112, -238,141,95,96,239,97,174,240,240,109,65,96,241,65,144,240,242,77,35,96,243,33,114,240,244,45,5,96,245,1,84,240,246, -22,33,224,246,225,54,240,247,246,3,224,248,193,24,240,249,213,229,224,250,160,250,240,251,181,199,224,252,138,23,112,253,149, -169,224,254,105,249,112,255,117,139,224,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, -1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, -0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, -1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, -0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, -1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, -0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, -1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, -0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,255,255,199,192,1,0,255,255,185,176,0,4,69,68,84, -0,69,83,84,0,0,0 -}; diff --git a/reactos/lib/msvcrt/time/tzfile.h b/reactos/lib/msvcrt/time/tzfile.h deleted file mode 100644 index 3999029adb9..00000000000 --- a/reactos/lib/msvcrt/time/tzfile.h +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#ifndef __dj_include_tzfile_h__ -#define __dj_include_tzfile_h__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __dj_ENFORCE_ANSI_FREESTANDING - -#ifndef __STRICT_ANSI__ - -#ifndef _POSIX_SOURCE - -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Arthur David Olson of the National Cancer Institute. - * - * Redistribution and use in source and binary forms are permitted provided - * that: (1) source distributions retain this entire copyright notice and - * comment, and (2) distributions including binaries display the following - * acknowledgement: ``This product includes software developed by the - * University of California, Berkeley and its contributors'' in the - * documentation or other materials provided with the distribution and in - * all advertising materials mentioning features or use of this software. - * Neither the name of the University nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#)tzfile.h 5.9 (Berkeley) 6/11/90 - */ - -/* -** Information about time zone files. -*/ - - /* Time zone object file directory */ -#define TZDIR "/usr/share/zoneinfo" -#define TZDEFAULT "/etc/localtime" -#define TZDEFRULES "posixrules" - -/* -** Each file begins with. . . -*/ - -struct tzhead { - char tzh_reserved[24]; /* reserved for future use */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded GMT offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition -** time is standard time, if FALSE, -** transition time is wall clock time -** if absent, transition times are -** assumed to be wall clock time -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -/* -** The TZ_MAX_TIMES value below is enough to handle a bit more than a -** year's worth of solar time (corrected daily to the nearest second) or -** 138 years of Pacific Presidential Election time -** (where there are three time zone transitions every fourth year). -*/ -#define TZ_MAX_TIMES 370 - -#define NOSOLAR /* 4BSD doesn't currently handle solar time */ - -#ifndef NOSOLAR -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#else -#define TZ_MAX_TYPES 10 /* Maximum number of local time types */ -#endif - -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ - -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -/* -** Accurate only for the past couple of centuries; -** that will probably do. -*/ - -#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) - -#endif /* !_POSIX_SOURCE */ -#endif /* !__STRICT_ANSI__ */ -#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ - -#ifndef __dj_ENFORCE_FUNCTION_CALLS -#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ - -#ifdef __cplusplus -} -#endif - -#endif /* __dj_include_tzfile_h__ */ diff --git a/reactos/lib/msvcrt/tests/Makefile b/reactos/lib/msvcrt/winetests/Makefile similarity index 100% rename from reactos/lib/msvcrt/tests/Makefile rename to reactos/lib/msvcrt/winetests/Makefile diff --git a/reactos/lib/msvcrt/tests/Makefile.in b/reactos/lib/msvcrt/winetests/Makefile.in similarity index 100% rename from reactos/lib/msvcrt/tests/Makefile.in rename to reactos/lib/msvcrt/winetests/Makefile.in diff --git a/reactos/lib/msvcrt/tests/cpp.c b/reactos/lib/msvcrt/winetests/cpp.c similarity index 100% rename from reactos/lib/msvcrt/tests/cpp.c rename to reactos/lib/msvcrt/winetests/cpp.c diff --git a/reactos/lib/msvcrt/tests/environ.c b/reactos/lib/msvcrt/winetests/environ.c similarity index 100% rename from reactos/lib/msvcrt/tests/environ.c rename to reactos/lib/msvcrt/winetests/environ.c diff --git a/reactos/lib/msvcrt/tests/file.c b/reactos/lib/msvcrt/winetests/file.c similarity index 100% rename from reactos/lib/msvcrt/tests/file.c rename to reactos/lib/msvcrt/winetests/file.c diff --git a/reactos/lib/msvcrt/tests/heap.c b/reactos/lib/msvcrt/winetests/heap.c similarity index 100% rename from reactos/lib/msvcrt/tests/heap.c rename to reactos/lib/msvcrt/winetests/heap.c diff --git a/reactos/lib/msvcrt/tests/msvcrt_test.dsp b/reactos/lib/msvcrt/winetests/msvcrt_test.dsp similarity index 100% rename from reactos/lib/msvcrt/tests/msvcrt_test.dsp rename to reactos/lib/msvcrt/winetests/msvcrt_test.dsp diff --git a/reactos/lib/msvcrt/tests/printf.c b/reactos/lib/msvcrt/winetests/printf.c similarity index 100% rename from reactos/lib/msvcrt/tests/printf.c rename to reactos/lib/msvcrt/winetests/printf.c diff --git a/reactos/lib/msvcrt/tests/scanf.c b/reactos/lib/msvcrt/winetests/scanf.c similarity index 100% rename from reactos/lib/msvcrt/tests/scanf.c rename to reactos/lib/msvcrt/winetests/scanf.c diff --git a/reactos/lib/msvcrt/tests/string.c b/reactos/lib/msvcrt/winetests/string.c similarity index 100% rename from reactos/lib/msvcrt/tests/string.c rename to reactos/lib/msvcrt/winetests/string.c diff --git a/reactos/lib/msvcrt/tests/testlist.c b/reactos/lib/msvcrt/winetests/testlist.c similarity index 100% rename from reactos/lib/msvcrt/tests/testlist.c rename to reactos/lib/msvcrt/winetests/testlist.c diff --git a/reactos/lib/msvcrt/tests/time.c b/reactos/lib/msvcrt/winetests/time.c similarity index 100% rename from reactos/lib/msvcrt/tests/time.c rename to reactos/lib/msvcrt/winetests/time.c diff --git a/reactos/lib/mswsock/Makefile b/reactos/lib/mswsock/Makefile index d71df74e68a..2a06f804fe2 100644 --- a/reactos/lib/mswsock/Makefile +++ b/reactos/lib/mswsock/Makefile @@ -20,9 +20,9 @@ TARGET_CFLAGS = \ TARGET_LFLAGS = -nostartfiles -nostdlib -TARGET_SDKLIBS = kernel32.a +TARGET_SDKLIBS = kernel32.a ws2_32.a -TARGET_OBJECTS = stubs.o +TARGET_OBJECTS = stubs.o extensions.o TARGET_CLEAN = $(DEP_FILES) diff --git a/reactos/lib/mswsock/extensions.c b/reactos/lib/mswsock/extensions.c new file mode 100644 index 00000000000..0e79d5e1e74 --- /dev/null +++ b/reactos/lib/mswsock/extensions.c @@ -0,0 +1,54 @@ +/* $Id: stubs.c 12852 2005-01-06 13:58:04Z mf $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock DLL + * FILE: stubs.c + * PURPOSE: WSAIoctl wrappers for Microsoft extensions to Winsock + * PROGRAMMERS: KJK::Hyperion + * REVISIONS: + */ + +#include +#include +#include + +/* + * @implemented + */ +BOOL +STDCALL +TransmitFile(SOCKET Socket, + HANDLE File, + DWORD NumberOfBytesToWrite, + DWORD NumberOfBytesPerSend, + LPOVERLAPPED Overlapped, + LPTRANSMIT_FILE_BUFFERS TransmitBuffers, + DWORD Flags) +{ + static GUID TransmitFileGUID = WSAID_TRANSMITFILE; + LPFN_TRANSMITFILE pfnTransmitFile; + DWORD cbBytesReturned; + + if (WSAIoctl(Socket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &TransmitFileGUID, + sizeof(TransmitFileGUID), + &pfnTransmitFile, + sizeof(pfnTransmitFile), + &cbBytesReturned, + NULL, + NULL) == SOCKET_ERROR) + { + return FALSE; + } + + return pfnTransmitFile(Socket, + File, + NumberOfBytesToWrite, + NumberOfBytesPerSend, + Overlapped, + TransmitBuffers, + Flags); +} + +/* EOF */ diff --git a/reactos/lib/mswsock/stubs.c b/reactos/lib/mswsock/stubs.c index 7fb4cb5fefd..dc910121f31 100644 --- a/reactos/lib/mswsock/stubs.c +++ b/reactos/lib/mswsock/stubs.c @@ -252,24 +252,6 @@ SetServiceW(DWORD NameSpace, } -/* - * @unimplemented - */ -BOOL -STDCALL -TransmitFile(SOCKET Socket, - HANDLE File, - DWORD NumberOfBytesToWrite, - DWORD NumberOfBytesPerSend, - LPOVERLAPPED Overlapped, - LPTRANSMIT_FILE_BUFFERS TransmitBuffers, - DWORD Flags) -{ - OutputDebugStringW(L"w32sock TransmitFile stub called\n"); - - return FALSE; -} - /* * @unimplemented */ diff --git a/reactos/lib/ntdll/csr/lpc.c b/reactos/lib/ntdll/csr/lpc.c index 1c63f07bd7d..81467b5d149 100644 --- a/reactos/lib/ntdll/csr/lpc.c +++ b/reactos/lib/ntdll/csr/lpc.c @@ -71,7 +71,10 @@ CsrCaptureParameterBuffer(PVOID ParameterBuffer, { return(STATUS_NO_MEMORY); } - memcpy(Block, ParameterBuffer, ParameterBufferSize); + if(ParameterBuffer != NULL) + { + memcpy(Block, ParameterBuffer, ParameterBufferSize); + } *ClientAddress = Block; *ServerAddress = Block - CsrSectionMapBase + CsrSectionMapServerBase; return(STATUS_SUCCESS); diff --git a/reactos/lib/ntdll/def/ntdll.def b/reactos/lib/ntdll/def/ntdll.def index f879410a890..e1d6af97011 100644 --- a/reactos/lib/ntdll/def/ntdll.def +++ b/reactos/lib/ntdll/def/ntdll.def @@ -77,7 +77,6 @@ NtCloseObjectAuditAlarm@12 NtCompleteConnectPort@4 NtConnectPort@32 NtContinue@8 -NtCreateChannel@8 NtCreateDirectoryObject@12 NtCreateEvent@20 NtCreateEventPair@12 @@ -128,7 +127,6 @@ NtImpersonateClientOfPort@8 NtImpersonateThread@12 NtInitializeRegistry@4 NtIsProcessInJob@8 -NtListenChannel@8 NtListenPort@8 NtLoadDriver@4 NtLoadKey@8 @@ -139,7 +137,6 @@ NtMakeTemporaryObject@4 NtMapViewOfSection@40 NtNotifyChangeDirectoryFile@36 NtNotifyChangeKey@40 -NtOpenChannel@8 NtOpenDirectoryObject@12 NtOpenEvent@12 NtOpenEventPair@12 @@ -157,7 +154,7 @@ NtOpenSymbolicLinkObject@12 NtOpenThread@16 NtOpenThreadToken@16 NtOpenTimer@12 -NtPlugPlayControl@16 +NtPlugPlayControl@12 NtPrivilegeCheck@12 NtPrivilegedServiceAuditAlarm@20 NtPrivilegeObjectAuditAlarm@24 @@ -185,7 +182,6 @@ NtQueryKey@20 NtQueryMultipleValueKey@24 NtQueryMutant@20 NtQueryObject@20 -NtQueryOleDirectoryFile@44 NtQueryPerformanceCounter@8 NtQuerySection@20 NtQuerySecurityObject@20 @@ -212,17 +208,14 @@ NtReleaseSemaphore@12 NtRemoveIoCompletion@20 NtReplaceKey@12 NtReplyPort@8 -NtReplyWaitReceivePort@16 NtReplyWaitReplyPort@8 -NtReplyWaitSendChannel@12 +NtReplyWaitReceivePort@16 NtRequestPort@8 NtRequestWaitReplyPort@12 NtResetEvent@8 NtRestoreKey@12 NtResumeThread@8 NtSaveKey@8 -NtSendWaitReplyChannel@16 -NtSetContextChannel@4 NtSetContextThread@8 NtSetDefaultHardErrorPort@4 NtSetDefaultLocale@8 @@ -328,7 +321,6 @@ RtlCharToInteger@12 RtlCheckRegistryKey@8 RtlClearAllBits@4 RtlClearBits@12 -;RtlClosePropertySet RtlCompactHeap@8 RtlCompareMemory@12 RtlCompareMemoryUlong@12 @@ -357,7 +349,6 @@ RtlCreateAtomTable@8 RtlCreateEnvironment@8 RtlCreateHeap@24 RtlCreateProcessParameters@40 -;RtlCreatePropertySet RtlCreateQueryDebugBuffer@8 RtlCreateRegistryKey@8 RtlCreateSecurityDescriptor@8 @@ -370,7 +361,7 @@ RtlCreateUserProcess@40 ;RtlCreateUserSecurityObject RtlCreateUserThread@40 RtlCustomCPToUnicodeN@24 -;RtlCutoverTimeToSystemTime +RtlCutoverTimeToSystemTime@16 RtlDeNormalizeProcessParams@4 RtlDecompressBuffer@24 RtlDecompressFragment@32 @@ -378,8 +369,6 @@ RtlDecompressFragment@32 RtlDeleteAce@8 RtlDeleteAtomFromAtomTable@8 RtlDeleteCriticalSection@4 -RtlDuplicateUnicodeString@12 -RtlSetCriticalSectionSpinCount@8 ;RtlDeleteElementGenericTable ;RtlDeleteNoSplay RtlDeleteOwnersRanges@8 @@ -403,6 +392,7 @@ RtlDosSearchPath_U@24 RtlDowncaseUnicodeChar@4 RtlDowncaseUnicodeString@12 RtlDumpResource@4 +RtlDuplicateUnicodeString@12 RtlEmptyAtomTable@8 RtlEnlargedIntegerMultiply@8 RtlEnlargedUnsignedDivide@16 @@ -411,7 +401,6 @@ RtlEnterCriticalSection@4 RtlEnumProcessHeaps@8 ;RtlEnumerateGenericTable ;RtlEnumerateGenericTableWithoutSplaying -;RtlEnumerateProperties RtlEqualComputerName@8 RtlEqualDomainName@8 RtlEqualLuid@8 @@ -442,7 +431,6 @@ RtlFindRange@48 RtlFindSetBits@12 RtlFindSetBitsAndClear@12 RtlFirstFreeAce@8 -;RtlFlushPropertySet RtlFormatCurrentUserKeyPath@4 RtlFormatMessage@32 RtlFreeAnsiString@4 @@ -465,6 +453,8 @@ RtlGetDaclSecurityDescriptor@16 RtlGetFirstRange@12 RtlGetFullPathName_U@16 RtlGetGroupSecurityDescriptor@12 +RtlGetLastNtStatus@0 +RtlGetLastWin32Error@0 RtlGetLongestNtPathLength@0 RtlGetNextRange@12 RtlGetNtGlobalFlags@0 @@ -473,9 +463,9 @@ RtlGetNtVersionNumbers@12 RtlGetOwnerSecurityDescriptor@12 RtlGetProcessHeaps@8 RtlGetSaclSecurityDescriptor@16 +RtlGetSecurityDescriptorRMControl@8 ;RtlGetUserInfoHeap RtlGetVersion@4 -;RtlGuidToPropertySetName RtlIdentifierAuthoritySid@4 RtlImageDirectoryEntryToData@16 RtlImageNtHeader@4 @@ -566,7 +556,6 @@ RtlOpenCurrentUser@8 RtlPinAtomInAtomTable@8 RtlPrefixString@12 RtlPrefixUnicodeString@12 -;RtlPropertySetNameToGuid ;RtlProtectHeap RtlQueryAtomInAtomTable@24 RtlQueryEnvironmentVariable_U@12 @@ -575,11 +564,8 @@ RtlQueryInformationAcl@16 RtlQueryProcessDebugInformation@12 ;RtlQueryProcessHeapInformation ;RtlQueryProcessLockInformation -;RtlQueryProperties -;RtlQueryPropertyNames -;RtlQueryPropertySet RtlQueryRegistryValues@20 -;RtlQuerySecutityObject +;RtlQuerySecurityObject ;RtlQueryTagHeap RtlQueryTimeZoneInformation@4 RtlRaiseException@4 @@ -593,6 +579,7 @@ RtlReleasePebLock@0 RtlReleaseResource@4 ;RtlRemoteCall RtlResetRtlTranslations@4 +RtlRestoreLastWin32Error@4=RtlSetLastWin32Error@4 RtlRunDecodeUnicodeString@8 RtlRunEncodeUnicodeString@8 RtlSecondsSince1970ToTime@8 @@ -601,17 +588,19 @@ RtlSelfRelativeToAbsoluteSD@44 RtlSetAllBits@4 ;RtlSetAttributesSecurityDescriptor RtlSetBits@12 +RtlSetControlSecurityDescriptor@12 +RtlSetCriticalSectionSpinCount@8 RtlSetCurrentDirectory_U@4 RtlSetCurrentEnvironment@8 RtlSetDaclSecurityDescriptor@16 RtlSetEnvironmentVariable@12 RtlSetGroupSecurityDescriptor@12 RtlSetInformationAcl@16 +RtlSetLastWin32Error@4 +RtlSetLastWin32ErrorAndNtStatusFromNtStatus@4 RtlSetOwnerSecurityDescriptor@12 -;RtlSetProperties -;RtlSetPropertyNames -;RtlSetPropertySetClassId RtlSetSaclSecurityDescriptor@16 +RtlSetSecurityDescriptorRMControl@8 ;RtlSetSecurityObject RtlSetTimeZoneInformation@4 ;RtlSetUnicodeCallouts @@ -704,7 +693,6 @@ ZwCloseObjectAuditAlarm@12 ZwCompleteConnectPort@4 ZwConnectPort@32 ZwContinue@8 -ZwCreateChannel@8 ZwCreateDirectoryObject@12 ZwCreateEvent@20 ZwCreateEventPair@12 @@ -751,7 +739,6 @@ ZwGetTickCount@0 ZwImpersonateClientOfPort@8 ZwImpersonateThread@12 ZwInitializeRegistry@4 -ZwListenChannel@8 ZwListenPort@8 ZwLoadDriver@4 ZwLoadKey@8 @@ -762,7 +749,6 @@ ZwMakeTemporaryObject@4 ZwMapViewOfSection@40 ZwNotifyChangeDirectoryFile@36 ZwNotifyChangeKey@40 -ZwOpenChannel@8 ZwOpenDirectoryObject@12 ZwOpenEvent@12 ZwOpenEventPair@12 @@ -779,7 +765,7 @@ ZwOpenSymbolicLinkObject@12 ZwOpenThread@16 ZwOpenThreadToken@16 ZwOpenTimer@12 -ZwPlugPlayControl@16 +ZwPlugPlayControl@12 ZwPrivilegeCheck@12 ZwPrivilegedServiceAuditAlarm@20 ZwPrivilegeObjectAuditAlarm@24 @@ -807,7 +793,6 @@ ZwQueryKey@20 ZwQueryMultipleValueKey@24 ZwQueryMutant@20 ZwQueryObject@20 -ZwQueryOleDirectoryFile@44 ZwQueryPerformanceCounter@8 ZwQuerySection@20 ZwQuerySecurityObject@20 @@ -835,15 +820,12 @@ ZwReplaceKey@12 ZwReplyPort@8 ZwReplyWaitReceivePort@16 ZwReplyWaitReplyPort@8 -ZwReplyWaitSendChannel@12 ZwRequestPort@8 ZwRequestWaitReplyPort@12 ZwResetEvent@8 ZwRestoreKey@12 ZwResumeThread@8 ZwSaveKey@8 -ZwSendWaitReplyChannel@16 -ZwSetContextChannel@4 ZwSetContextThread@8 ZwSetDefaultHardErrorPort@4 ZwSetDefaultLocale@8 diff --git a/reactos/lib/ntdll/ldr/res.c b/reactos/lib/ntdll/ldr/res.c index b829e98e945..91676aa3554 100644 --- a/reactos/lib/ntdll/ldr/res.c +++ b/reactos/lib/ntdll/ldr/res.c @@ -110,12 +110,14 @@ LdrFindResource_U(PVOID BaseAddress, int j, pos = 0; LCID UserLCID, SystemLCID; LANGID UserLangID, SystemLangID; + BOOLEAN MappedAsDataFile; + MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress); DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry); /* Get the pointer to the resource directory */ ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress, - TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i); + ! MappedAsDataFile, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i); if (ResDir == NULL) { return STATUS_RESOURCE_DATA_NOT_FOUND; } @@ -278,18 +280,20 @@ LdrAccessResource(IN PVOID BaseAddress, ULONG DataSize; ULONG Offset = 0; ULONG Data; + BOOLEAN MappedAsDataFile; if(!ResourceDataEntry) return STATUS_RESOURCE_DATA_NOT_FOUND; + MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress); Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize); if (Data == 0) { return STATUS_RESOURCE_DATA_NOT_FOUND; } - if ((ULONG)BaseAddress & 1) { + if (MappedAsDataFile) { /* loaded as ordinary file */ - NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL)); + NtHeader = RtlImageNtHeader(BaseAddress); Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); if (Section == NULL) { diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index e7fbe960fd4..f16e6a7d786 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -37,14 +37,12 @@ static CRITICAL_SECTION LoaderLock; static RTL_BITMAP TlsBitMap; PLDR_MODULE ExeModule; -ULONG NtGlobalFlag = 0; - NTSTATUS LdrpAttachThread (VOID); #define VALUE_BUFFER_SIZE 256 -BOOL FASTCALL +BOOLEAN FASTCALL ReadCompatibilitySetting(HANDLE Key, LPWSTR Value, PKEY_VALUE_PARTIAL_INFORMATION ValueInfo, DWORD *Buffer) { UNICODE_STRING ValueName; @@ -102,13 +100,12 @@ LoadImageFileExecutionOptions(PPEB Peb) * read more options */ } - NtGlobalFlag = Peb->NtGlobalFlag; } -BOOL FASTCALL +BOOLEAN FASTCALL LoadCompatibilitySettings(PPEB Peb) { NTSTATUS Status; @@ -225,7 +222,6 @@ finish: return FALSE; } - /* FUNCTIONS *****************************************************************/ VOID STDCALL @@ -242,6 +238,8 @@ __true_LdrInitializeThunk (ULONG Unknown1, PLDR_MODULE NtModule; // ntdll NLSTABLEINFO NlsTable; WCHAR FullNtDllPath[MAX_PATH]; + SYSTEM_BASIC_INFORMATION SystemInformation; + NTSTATUS Status; DPRINT("LdrInitializeThunk()\n"); if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE) @@ -259,6 +257,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, /* If MZ header exists */ PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; DPRINT("PEDosHeader %x\n", PEDosHeader); + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L || *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC) @@ -279,6 +278,21 @@ __true_LdrInitializeThunk (ULONG Unknown1, NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew); + /* Get number of processors */ + Status = ZwQuerySystemInformation(SystemBasicInformation, + &SystemInformation, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + ZwTerminateProcess(NtCurrentProcess(), Status); + } + + Peb->NumberOfProcessors = SystemInformation.NumberProcessors; + + /* Initialize Critical Section Data */ + RtlpInitDeferedCriticalSection(); + /* create process heap */ RtlInitializeHeapManager(); Peb->ProcessHeap = RtlCreateHeap(HEAP_GROWABLE, @@ -292,7 +306,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, DPRINT1("Failed to create process heap\n"); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); } - + /* initalize peb lock support */ RtlInitializeCriticalSection (&PebLock); Peb->FastPebLock = &PebLock; @@ -311,7 +325,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(PVOID) * (USER32_CALLBACK_MAXIMUM + 1)); - + /* initalize loader lock */ RtlInitializeCriticalSection (&LoaderLock); Peb->LoaderLock = &LoaderLock; @@ -367,7 +381,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, NtModule->CheckSum = 0; NTHeaders = RtlImageNtHeader (NtModule->BaseAddress); - NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + NtModule->ResidentSize = LdrpGetResidentSize(NTHeaders); NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; InsertTailList(&Peb->Ldr->InLoadOrderModuleList, @@ -415,7 +429,7 @@ __true_LdrInitializeThunk (ULONG Unknown1, ExeModule->CheckSum = 0; NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress); - ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + ExeModule->ResidentSize = LdrpGetResidentSize(NTHeaders); ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; InsertHeadList(&Peb->Ldr->InLoadOrderModuleList, diff --git a/reactos/lib/ntdll/ldr/utils.c b/reactos/lib/ntdll/ldr/utils.c index 73e8a49cbec..0ef7154e0e4 100644 --- a/reactos/lib/ntdll/ldr/utils.c +++ b/reactos/lib/ntdll/ldr/utils.c @@ -51,20 +51,20 @@ static ULONG LdrpTlsSize = 0; static HANDLE LdrpKnownDllsDirHandle = NULL; static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL}; static PLDR_MODULE LdrpLastModule = NULL; -extern ULONG NtGlobalFlag; extern PLDR_MODULE ExeModule; /* PROTOTYPES ****************************************************************/ -static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module, BOOL Ref); +static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module, BOOLEAN Ref); static PVOID LdrFixupForward(PCHAR ForwardName); static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint); static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, IN ULONG LoadFlags, IN PUNICODE_STRING Name, - OUT PLDR_MODULE *Module); + OUT PLDR_MODULE *Module, + OUT PVOID *BaseAddress OPTIONAL); static NTSTATUS LdrpAttachProcess(VOID); -static VOID LdrpDetachProcess(BOOL UnloadAll); +static VOID LdrpDetachProcess(BOOLEAN UnloadAll); /* FUNCTIONS *****************************************************************/ @@ -84,7 +84,19 @@ LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule) #endif /* DBG || KDBG */ -static inline LONG LdrpDecrementLoadCount(PLDR_MODULE Module, BOOL Locked) +BOOLEAN +LdrMappedAsDataFile(PVOID *BaseAddress) +{ + if (0 != ((DWORD_PTR) *BaseAddress & (PAGE_SIZE - 1))) + { + *BaseAddress = (PVOID) ((DWORD_PTR) *BaseAddress & ~ ((DWORD_PTR) PAGE_SIZE - 1)); + return TRUE; + } + + return FALSE; +} + +static inline LONG LdrpDecrementLoadCount(PLDR_MODULE Module, BOOLEAN Locked) { LONG LoadCount; if (!Locked) @@ -103,7 +115,7 @@ static inline LONG LdrpDecrementLoadCount(PLDR_MODULE Module, BOOL Locked) return LoadCount; } -static inline LONG LdrpIncrementLoadCount(PLDR_MODULE Module, BOOL Locked) +static inline LONG LdrpIncrementLoadCount(PLDR_MODULE Module, BOOLEAN Locked) { LONG LoadCount; if (!Locked) @@ -122,7 +134,7 @@ static inline LONG LdrpIncrementLoadCount(PLDR_MODULE Module, BOOL Locked) return LoadCount; } -static inline VOID LdrpAcquireTlsSlot(PLDR_MODULE Module, ULONG Size, BOOL Locked) +static inline VOID LdrpAcquireTlsSlot(PLDR_MODULE Module, ULONG Size, BOOLEAN Locked) { if (!Locked) { @@ -156,7 +168,7 @@ static inline VOID LdrpTlsCallback(PLDR_MODULE Module, ULONG dwReason) } } -static BOOL LdrpCallDllEntry(PLDR_MODULE Module, DWORD dwReason, PVOID lpReserved) +static BOOLEAN LdrpCallDllEntry(PLDR_MODULE Module, DWORD dwReason, PVOID lpReserved) { if (!(Module->Flags & IMAGE_DLL) || Module->EntryPoint == 0) @@ -456,7 +468,7 @@ LdrAddModuleEntry(PVOID ImageBase, Module->EntryPoint = NTHeaders->OptionalHeader.AddressOfEntryPoint; if (Module->EntryPoint != 0) Module->EntryPoint += (ULONG)Module->BaseAddress; - Module->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + Module->ResidentSize = LdrpGetResidentSize(NTHeaders); if (NtCurrentPeb()->Ldr->Initialized == TRUE) { /* loading while app is running */ @@ -549,6 +561,7 @@ static NTSTATUS LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL, IN PUNICODE_STRING DllName, OUT PUNICODE_STRING FullDosName, + IN BOOLEAN MapAsDataFile, OUT PHANDLE SectionHandle) { WCHAR SearchPathBuffer[MAX_PATH]; @@ -559,8 +572,6 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL, char BlockBuffer [1024]; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NTHeaders; - PVOID ImageBase; - ULONG ImageSize; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; ULONG len; @@ -619,7 +630,7 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL, GENERIC_READ|SYNCHRONIZE, &FileObjectAttributes, &IoStatusBlock, - 0, + FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { @@ -664,11 +675,6 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL, return STATUS_UNSUCCESSFUL; } - ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase; - ImageSize = NTHeaders->OptionalHeader.SizeOfImage; - - DPRINT("ImageBase 0x%08x\n", ImageBase); - /* * Create a section for dll. */ @@ -677,7 +683,7 @@ LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL, NULL, NULL, PAGE_READWRITE, - SEC_COMMIT | SEC_IMAGE, + SEC_COMMIT | (MapAsDataFile ? 0 : SEC_IMAGE), FileHandle); NtClose(FileHandle); @@ -733,8 +739,8 @@ LdrLoadDll (IN PWSTR SearchPath OPTIONAL, *BaseAddress = NULL; - Status = LdrpLoadModule(SearchPath, LoadFlags, Name, &Module); - if (NT_SUCCESS(Status)) + Status = LdrpLoadModule(SearchPath, LoadFlags, Name, &Module, BaseAddress); + if (NT_SUCCESS(Status) && 0 == (LoadFlags & LOAD_LIBRARY_AS_DATAFILE)) { RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock); Status = LdrpAttachProcess(); @@ -793,7 +799,7 @@ LdrFindEntryForAddress(PVOID Address, DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->BaseAddress); if ((Address >= ModulePtr->BaseAddress) && - (Address <= (ModulePtr->BaseAddress + ModulePtr->SizeOfImage))) + (Address <= (ModulePtr->BaseAddress + ModulePtr->ResidentSize))) { *Module = ModulePtr; RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); @@ -828,7 +834,7 @@ LdrFindEntryForAddress(PVOID Address, static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module, - BOOL Ref) + BOOLEAN Ref) { PLIST_ENTRY ModuleListHead; PLIST_ENTRY Entry; @@ -1332,7 +1338,7 @@ static NTSTATUS LdrpGetOrLoadModule(PWCHAR SerachPath, PCHAR Name, PLDR_MODULE* Module, - BOOL Load) + BOOLEAN Load) { UNICODE_STRING DllName; NTSTATUS Status; @@ -1347,7 +1353,8 @@ LdrpGetOrLoadModule(PWCHAR SerachPath, Status = LdrpLoadModule(SerachPath, NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME, &DllName, - Module); + Module, + NULL); if (NT_SUCCESS(Status)) { Status = LdrFindEntryForName (&DllName, Module, FALSE); @@ -1574,7 +1581,7 @@ LdrpAdjustImportDirectory(PLDR_MODULE Module, NTHeaders = RtlImageNtHeader (ImportedModule->BaseAddress); Start = (PVOID)NTHeaders->OptionalHeader.ImageBase; - End = Start + ImportedModule->SizeOfImage; + End = Start + ImportedModule->ResidentSize; Offset = ImportedModule->BaseAddress - Start; /* Walk through function list and fixup addresses. */ @@ -1710,7 +1717,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL, } else { - BOOL WrongForwarder; + BOOLEAN WrongForwarder; WrongForwarder = FALSE; if (ImportedModule->Flags & IMAGE_NOT_AT_BASE) { @@ -1979,7 +1986,8 @@ static NTSTATUS LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, IN ULONG LoadFlags, IN PUNICODE_STRING Name, - PLDR_MODULE *Module) + PLDR_MODULE *Module, + PVOID *BaseAddress OPTIONAL) { UNICODE_STRING AdjustedName; UNICODE_STRING FullDosName; @@ -1989,6 +1997,7 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, ULONG ViewSize; PVOID ImageBase; PIMAGE_NT_HEADERS NtHeaders; + BOOLEAN MappedAsDataFile; if (Module == NULL) { @@ -1999,11 +2008,16 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, DPRINT("%wZ\n", &AdjustedName); + MappedAsDataFile = FALSE; /* Test if dll is already loaded */ Status = LdrFindEntryForName(&AdjustedName, Module, TRUE); if (NT_SUCCESS(Status)) { RtlFreeUnicodeString(&AdjustedName); + if (NULL != BaseAddress) + { + *BaseAddress = (*Module)->BaseAddress; + } } else { @@ -2011,7 +2025,9 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, Status = LdrpMapKnownDll(&AdjustedName, &FullDosName, &SectionHandle); if (!NT_SUCCESS(Status)) { - Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName, &SectionHandle); + MappedAsDataFile = (0 != (LoadFlags & LOAD_LIBRARY_AS_DATAFILE)); + Status = LdrpMapDllImageFile(SearchPath, &AdjustedName, &FullDosName, + MappedAsDataFile, &SectionHandle); } if (!NT_SUCCESS(Status)) { @@ -2040,6 +2056,10 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, NtClose(SectionHandle); return(Status); } + if (NULL != BaseAddress) + { + *BaseAddress = ImageBase; + } /* Get and check the NT headers */ NtHeaders = RtlImageNtHeader(ImageBase); if (NtHeaders == NULL) @@ -2050,6 +2070,19 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, RtlFreeUnicodeString(&FullDosName); return STATUS_UNSUCCESSFUL; } + DPRINT("Mapped %wZ at %x\n", &FullDosName, ImageBase); + if (MappedAsDataFile) + { + assert(NULL != BaseAddress); + if (NULL != BaseAddress) + { + *BaseAddress = (PVOID) ((char *) *BaseAddress + 1); + } + *Module = NULL; + RtlFreeUnicodeString(&FullDosName); + NtClose(SectionHandle); + return STATUS_SUCCESS; + } /* If the base address is different from the * one the DLL is actually loaded, perform any * relocation. */ @@ -2097,7 +2130,7 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL, static NTSTATUS LdrpUnloadModule(PLDR_MODULE Module, - BOOL Unload) + BOOLEAN Unload) { PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory; PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor; @@ -2213,12 +2246,20 @@ LdrUnloadDll (IN PVOID BaseAddress) if (BaseAddress == NULL) return STATUS_SUCCESS; - Status = LdrFindEntryForAddress(BaseAddress, &Module); - if (NT_SUCCESS(Status)) + if (LdrMappedAsDataFile(&BaseAddress)) { - TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName); - Status = LdrpUnloadModule(Module, TRUE); + Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } + else + { + Status = LdrFindEntryForAddress(BaseAddress, &Module); + if (NT_SUCCESS(Status)) + { + TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module->BaseDllName); + Status = LdrpUnloadModule(Module, TRUE); + } + } + return Status; } @@ -2359,7 +2400,7 @@ LdrGetProcedureAddress (IN PVOID BaseAddress, * The loader lock must be held on enty. */ static VOID -LdrpDetachProcess(BOOL UnloadAll) +LdrpDetachProcess(BOOLEAN UnloadAll) { PLIST_ENTRY ModuleListHead; PLIST_ENTRY Entry; @@ -2458,7 +2499,7 @@ LdrpAttachProcess(VOID) PLIST_ENTRY ModuleListHead; PLIST_ENTRY Entry; PLDR_MODULE Module; - BOOL Result; + BOOLEAN Result; NTSTATUS Status = STATUS_SUCCESS; DPRINT("LdrpAttachProcess() called for %wZ\n", @@ -2667,7 +2708,7 @@ LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTION { ModulePtr->Reserved[0] = ModulePtr->Reserved[1] = 0; // FIXME: ?? ModulePtr->Base = Module->BaseAddress; - ModulePtr->Size = Module->SizeOfImage; + ModulePtr->Size = Module->ResidentSize; ModulePtr->Flags = Module->Flags; ModulePtr->Index = 0; // FIXME: index ?? ModulePtr->Unknown = 0; // FIXME: ?? @@ -2773,6 +2814,33 @@ LdrpCheckImageChecksum (IN PVOID BaseAddress, return (BOOLEAN)(CalcSum == HeaderSum); } +/* + * Compute size of an image as it is actually present in virt memory + * (i.e. excluding NEVER_LOAD sections) + */ +ULONG +LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders) +{ + PIMAGE_SECTION_HEADER SectionHeader; + unsigned SectionIndex; + ULONG ResidentSize; + + SectionHeader = (PIMAGE_SECTION_HEADER)((char *) &NTHeaders->OptionalHeader + + NTHeaders->FileHeader.SizeOfOptionalHeader); + ResidentSize = 0; + for (SectionIndex = 0; SectionIndex < NTHeaders->FileHeader.NumberOfSections; SectionIndex++) + { + if (0 == (SectionHeader->Characteristics & IMAGE_SCN_LNK_REMOVE) + && ResidentSize < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) + { + ResidentSize = SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize; + } + SectionHeader++; + } + + return ResidentSize; +} + /*************************************************************************** * NAME EXPORTED diff --git a/reactos/lib/ntdll/makefile b/reactos/lib/ntdll/makefile index 44dad1d4d8a..aeba6521db0 100644 --- a/reactos/lib/ntdll/makefile +++ b/reactos/lib/ntdll/makefile @@ -77,7 +77,6 @@ RTL_OBJECTS = \ rtl/process.o \ rtl/propvar.o \ rtl/rangelist.o \ - rtl/registry.o \ rtl/resource.o \ rtl/teb.o \ rtl/thread.o \ diff --git a/reactos/lib/ntdll/ntdll.xml b/reactos/lib/ntdll/ntdll.xml index 3a6ddf15e87..d6b672731ef 100644 --- a/reactos/lib/ntdll/ntdll.xml +++ b/reactos/lib/ntdll/ntdll.xml @@ -1,5 +1,4 @@ - genntdll @@ -38,7 +37,6 @@ aullrem.s aullshr.s chkstk.s - except.s exception.c float.c ftol.c @@ -62,7 +60,6 @@ process.c propvar.c rangelist.c - registry.c resource.c teb.c thread.c @@ -108,5 +105,5 @@ ntdll.rc - napi.c + napi.S diff --git a/reactos/lib/ntdll/rtl/critical.c b/reactos/lib/ntdll/rtl/critical.c index 8974c6bce02..6da74fc197f 100644 --- a/reactos/lib/ntdll/rtl/critical.c +++ b/reactos/lib/ntdll/rtl/critical.c @@ -6,6 +6,8 @@ * PURPOSE: Critical sections * UPDATE HISTORY: * Created 30/09/98 + * Rewritten ROS version, based on WINE code plus + * some fixes useful only for ROS right now - 03/01/05 */ /* INCLUDES ******************************************************************/ @@ -19,160 +21,651 @@ /* FUNCTIONS *****************************************************************/ -/* - * @implemented - */ -VOID STDCALL -RtlDeleteCriticalSection(PCRITICAL_SECTION CriticalSection) +#define MAX_STATIC_CS_DEBUG_OBJECTS 64 + +static RTL_CRITICAL_SECTION RtlCriticalSectionLock; +static LIST_ENTRY RtlCriticalSectionList; +static BOOLEAN RtlpCritSectInitialized = FALSE; +static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS]; +static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS]; + +/*++ + * RtlDeleteCriticalSection + * @implemented NT4 + * + * Deletes a Critical Section + * + * Params: + * CriticalSection - Critical section to delete. + * + * Returns: + * STATUS_SUCCESS, or error value returned by NtClose. + * + * Remarks: + * The critical section members should not be read after this call. + * + *--*/ +NTSTATUS +STDCALL +RtlDeleteCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - NtClose(CriticalSection->LockSemaphore); - CriticalSection->LockCount = -1; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("Deleting Critical Section: %x\n", CriticalSection); + /* Close the Event Object Handle if it exists */ + if (CriticalSection->LockSemaphore) { + + /* In case NtClose fails, return the status */ + Status = NtClose(CriticalSection->LockSemaphore); + + } + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Remove it from the list */ + RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + /* Free it */ + RtlpFreeDebugInfo(CriticalSection->DebugInfo); + + /* Wipe it out */ + RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION)); + + /* Return */ + return Status; } -/* - * @implemented - */ -DWORD STDCALL +/*++ + * RtlSetCriticalSectionSpinCount + * @implemented NT4 + * + * Sets the spin count for a critical section. + * + * Params: + * CriticalSection - Critical section to set the spin count for. + * + * SpinCount - Spin count for the critical section. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +DWORD +STDCALL RtlSetCriticalSectionSpinCount( - LPCRITICAL_SECTION CriticalSection, + PRTL_CRITICAL_SECTION CriticalSection, DWORD SpinCount ) +{ + DWORD OldCount = CriticalSection->SpinCount; + + /* Set to parameter if MP, or to 0 if this is Uniprocessor */ + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + return OldCount; +} + +/*++ + * RtlEnterCriticalSection + * @implemented NT4 + * + * Waits to gain ownership of the critical section. + * + * Params: + * CriticalSection - Critical section to wait for. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * Uses a fast-path unless contention happens. + * + *--*/ +NTSTATUS +STDCALL +RtlEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + /* Try to Lock it */ + if (InterlockedIncrement(&CriticalSection->LockCount)) { + + /* + * We've failed to lock it! Does this thread + * actually own it? + */ + if (Thread == CriticalSection->OwningThread) { + + /* You own it, so you'll get it when you're done with it! */ + CriticalSection->RecursionCount++; + return STATUS_SUCCESS; + } + + /* We don't own it, so we must wait for it */ + RtlpWaitForCriticalSection(CriticalSection); + } + + /* Lock successful */ + CriticalSection->OwningThread = Thread; + CriticalSection->RecursionCount = 1; + return STATUS_SUCCESS; +} + +/*++ + * RtlInitializeCriticalSection + * @implemented NT4 + * + * Initialises a new critical section. + * + * Params: + * CriticalSection - Critical section to initialise + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * Simply calls RtlInitializeCriticalSectionAndSpinCount + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Call the Main Function */ + return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0); +} + +/*++ + * RtlInitializeCriticalSectionAndSpinCount + * @implemented NT4 + * + * Initialises a new critical section. + * + * Params: + * CriticalSection - Critical section to initialise + * + * SpinCount - Spin count for the critical section. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * SpinCount is ignored on single-processor systems. + * + *--*/ +NTSTATUS +STDCALL +RtlInitializeCriticalSectionAndSpinCount ( + PRTL_CRITICAL_SECTION CriticalSection, + DWORD SpinCount) +{ + PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData; + + /* First things first, set up the Object */ + DPRINT("Initializing Critical Section: %x\n", CriticalSection); + CriticalSection->LockCount = -1; + CriticalSection->RecursionCount = 0; + CriticalSection->OwningThread = 0; + CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0; + CriticalSection->LockSemaphore = 0; + + /* Allocate the Debug Data */ + CritcalSectionDebugData = RtlpAllocateDebugInfo(); + DPRINT("Allocated Debug Data: %x inside Process: %x\n", + CritcalSectionDebugData, + NtCurrentTeb()->Cid.UniqueProcess); + + if (!CritcalSectionDebugData) { + + /* This is bad! */ + DPRINT1("Couldn't allocate Debug Data for: %x\n", CriticalSection); + return STATUS_NO_MEMORY; + } + + /* Set it up */ + CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE; + CritcalSectionDebugData->ContentionCount = 0; + CritcalSectionDebugData->EntryCount = 0; + CritcalSectionDebugData->CriticalSection = CriticalSection; + CriticalSection->DebugInfo = CritcalSectionDebugData; + + /* + * Add it to the List of Critical Sections owned by the process. + * If we've initialized the Lock, then use it. If not, then probably + * this is the lock initialization itself, so insert it directly. + */ + if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) { + + DPRINT("Securely Inserting into ProcessLocks: %x, %x, %x\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); + + /* Protect List */ + RtlEnterCriticalSection(&RtlCriticalSectionLock); + + /* Add this one */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + + /* Unprotect */ + RtlLeaveCriticalSection(&RtlCriticalSectionLock); + + } else { + + DPRINT("Inserting into ProcessLocks: %x, %x, %x\n", + &CritcalSectionDebugData->ProcessLocksList, + CriticalSection, + &RtlCriticalSectionList); + + /* Add it directly */ + InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList); + } + + return STATUS_SUCCESS; +} + +/*++ + * RtlLeaveCriticalSection + * @implemented NT4 + * + * Releases a critical section and makes if available for new owners. + * + * Params: + * CriticalSection - Critical section to release. + * + * Returns: + * STATUS_SUCCESS. + * + * Remarks: + * If another thread was waiting, the slow path is entered. + * + *--*/ +NTSTATUS +STDCALL +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Decrease the Recursion Count */ + if (--CriticalSection->RecursionCount) { + + /* Someone still owns us, but we are free */ + InterlockedDecrement(&CriticalSection->LockCount); + + } else { + + /* Nobody owns us anymore */ + CriticalSection->OwningThread = 0; + + /* Was someone wanting us? */ + if (InterlockedDecrement(&CriticalSection->LockCount) >= 0) { + + /* Let him have us */ + RtlpUnWaitCriticalSection(CriticalSection); + + } + } + + /* Sucessful! */ + return STATUS_SUCCESS; +} + +/*++ + * RtlTryEnterCriticalSection + * @implemented NT4 + * + * Attemps to gain ownership of the critical section without waiting. + * + * Params: + * CriticalSection - Critical section to attempt acquiring. + * + * Returns: + * TRUE if the critical section has been acquired, FALSE otherwise. + * + * Remarks: + * None + * + *--*/ +BOOLEAN +STDCALL +RtlTryEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + /* Try to take control */ + if (InterlockedCompareExchange(&CriticalSection->LockCount, + 0, + -1) == -1) { + + /* It's ours */ + CriticalSection->OwningThread = NtCurrentTeb()->Cid.UniqueThread; + CriticalSection->RecursionCount = 1; + return TRUE; -#ifdef MP - DWORD PrevSpinCount = CriticalSection->SpinCount; - CriticalSection->SpinCount = SpinCount; - return PrevSpinCount; -#else - return 0; -#endif - -} - - -/* - * @implemented - */ -VOID STDCALL -RtlEnterCriticalSection(PCRITICAL_SECTION CriticalSection) -{ - HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; - - if (InterlockedIncrement(&CriticalSection->LockCount)) - { - NTSTATUS Status; - - if (CriticalSection->OwningThread == Thread) - { - CriticalSection->RecursionCount++; - return; - } - - DPRINT("Entering wait for critical section\n"); - Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, - 0, FALSE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlEnterCriticalSection: Failed to wait (Status %x)\n", - Status); - } - DPRINT("Left wait for critical section\n"); - } - CriticalSection->OwningThread = Thread; - CriticalSection->RecursionCount = 1; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlInitializeCriticalSection(PCRITICAL_SECTION CriticalSection) -{ - return RtlInitializeCriticalSectionAndSpinCount (CriticalSection, - 0); -} - - -/* - * @implemented - */ -VOID STDCALL -RtlLeaveCriticalSection(PCRITICAL_SECTION CriticalSection) -{ - HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; - - if (CriticalSection->OwningThread != Thread) - { - DPRINT1("Freeing critical section not owned\n"); - } - - CriticalSection->RecursionCount--; - if (CriticalSection->RecursionCount > 0) - { - InterlockedDecrement(&CriticalSection->LockCount); - return; - } - CriticalSection->OwningThread = 0; - if (InterlockedDecrement(&CriticalSection->LockCount) >= 0) - { - NTSTATUS Status; - - Status = NtReleaseSemaphore(CriticalSection->LockSemaphore, 1, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to release semaphore (Status %x)\n", - Status); - } - } -} - -/* - * @implemented - */ -BOOLEAN STDCALL -RtlTryEnterCriticalSection(PCRITICAL_SECTION CriticalSection) -{ - if (InterlockedCompareExchange((PVOID*)&CriticalSection->LockCount, - (PVOID)0, (PVOID)-1 ) == (PVOID)-1) - { - CriticalSection->OwningThread = - (HANDLE) NtCurrentTeb()->Cid.UniqueThread; - CriticalSection->RecursionCount = 1; - return TRUE; - } - if (CriticalSection->OwningThread == - (HANDLE)NtCurrentTeb()->Cid.UniqueThread) - { + } else if (CriticalSection->OwningThread == NtCurrentTeb()->Cid.UniqueThread) { + + /* It's already ours */ InterlockedIncrement(&CriticalSection->LockCount); - CriticalSection->RecursionCount++; - return TRUE; - } - return FALSE; + CriticalSection->RecursionCount++; + return TRUE; + } + + /* It's not ours */ + return FALSE; } - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlInitializeCriticalSectionAndSpinCount (PCRITICAL_SECTION CriticalSection, - ULONG SpinCount) +/*++ + * RtlpWaitForCriticalSection + * + * Slow path of RtlEnterCriticalSection. Waits on an Event Object. + * + * Params: + * CriticalSection - Critical section to acquire. + * + * Returns: + * STATUS_SUCCESS, or raises an exception if a deadlock is occuring. + * + * Remarks: + * None + * + *--*/ +NTSTATUS +STDCALL +RtlpWaitForCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - CriticalSection->LockCount = -1; - CriticalSection->RecursionCount = 0; - CriticalSection->OwningThread = (HANDLE)0; -#ifdef MP - CriticalSection->SpinCount = SpinCount; -#else - CriticalSection->SpinCount = 0; -#endif + NTSTATUS Status; + EXCEPTION_RECORD ExceptionRecord; + BOOLEAN LastChance = FALSE; + LARGE_INTEGER Timeout; + + /* Wait 2.5 minutes */ + Timeout.QuadPart = 150000L * (ULONGLONG)10000; + Timeout.QuadPart = -Timeout.QuadPart; + /* ^^ HACK HACK HACK. Good way: + Timeout = &NtCurrentPeb()->CriticalSectionTimeout */ + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Increase the Debug Entry count */ + DPRINT("Waiting on Critical Section Event: %x %x\n", + CriticalSection, + CriticalSection->LockSemaphore); + CriticalSection->DebugInfo->EntryCount++; + + for (;;) { + + /* Increase the number of times we've had contention */ + CriticalSection->DebugInfo->ContentionCount++; + + /* Wait on the Event */ + Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, + FALSE, + &Timeout); + + /* We have Timed out */ + if (Status == STATUS_TIMEOUT) { + + /* Is this the 2nd time we've timed out? */ + if (LastChance) { + + DPRINT1("Deadlock: %x\n", CriticalSection); + + /* Yes it is, we are raising an exception */ + ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; + ExceptionRecord.ExceptionFlags = 0; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.ExceptionAddress = RtlRaiseException; + ExceptionRecord.NumberParameters = 1; + ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; + RtlRaiseException(&ExceptionRecord); + + } + + /* One more try */ + LastChance = TRUE; + + } else { + + /* If we are here, everything went fine */ + return STATUS_SUCCESS; + } + } +} - return NtCreateSemaphore (&CriticalSection->LockSemaphore, - SEMAPHORE_ALL_ACCESS, - NULL, - 0, - 1); +/*++ + * RtlpUnWaitCriticalSection + * + * Slow path of RtlLeaveCriticalSection. Fires an Event Object. + * + * Params: + * CriticalSection - Critical section to release. + * + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpUnWaitCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) + +{ + NTSTATUS Status; + + /* Do we have an Event yet? */ + if (!CriticalSection->LockSemaphore) { + RtlpCreateCriticalSectionSem(CriticalSection); + } + + /* Signal the Event */ + DPRINT("Signaling Critical Section Event: %x, %x\n", + CriticalSection, + CriticalSection->LockSemaphore); + Status = NtSetEvent(CriticalSection->LockSemaphore, NULL); + + if (!NT_SUCCESS(Status)) { + + /* We've failed */ + DPRINT1("Signaling Failed for: %x, %x, %x\n", + CriticalSection, + CriticalSection->LockSemaphore, + Status); + RtlRaiseStatus(Status); + } +} + +/*++ + * RtlpCreateCriticalSectionSem + * + * Checks if an Event has been created for the critical section. + * + * Params: + * None + * + * Returns: + * None. Raises an exception if the system call failed. + * + * Remarks: + * None + * + *--*/ +VOID +STDCALL +RtlpCreateCriticalSectionSem( + PRTL_CRITICAL_SECTION CriticalSection) +{ + HANDLE hEvent = CriticalSection->LockSemaphore; + HANDLE hNewEvent; + NTSTATUS Status; + + /* Chevk if we have an event */ + if (!hEvent) { + + /* No, so create it */ + if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE))) { + + /* We failed, this is bad... */ + DPRINT1("Failed to Create Event!\n"); + InterlockedDecrement(&CriticalSection->LockCount); + RtlRaiseStatus(Status); + return; + } + DPRINT("Created Event: %x \n", hNewEvent); + + if ((hEvent = InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore, + (PVOID)hNewEvent, + 0))) { + + /* Some just created an event */ + DPRINT("Closing already created event: %x\n", hNewEvent); + NtClose(hNewEvent); + } + } + + return; +} + +/*++ + * RtlpInitDeferedCriticalSection + * + * Initializes the Critical Section implementation. + * + * Params: + * None + * + * Returns: + * None. + * + * Remarks: + * After this call, the Process Critical Section list is protected. + * + *--*/ +VOID +STDCALL +RtlpInitDeferedCriticalSection( + VOID) +{ + + /* Initialize the Process Critical Section List */ + InitializeListHead(&RtlCriticalSectionList); + + /* Initialize the CS Protecting the List */ + RtlInitializeCriticalSection(&RtlCriticalSectionLock); + + /* It's now safe to enter it */ + RtlpCritSectInitialized = TRUE; +} + +/*++ + * RtlpAllocateDebugInfo + * + * Finds or allocates memory for a Critical Section Debug Object + * + * Params: + * None + * + * Returns: + * A pointer to an empty Critical Section Debug Object. + * + * Remarks: + * For optimization purposes, the first 64 entries can be cached. From + * then on, future Critical Sections will allocate memory from the heap. + * + *--*/ +PRTL_CRITICAL_SECTION_DEBUG +STDCALL +RtlpAllocateDebugInfo( + VOID) +{ + ULONG i; + + /* Try to allocate from our buffer first */ + for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) { + + /* Check if Entry is free */ + if (!RtlpDebugInfoFreeList[i]) { + + /* Mark entry in use */ + DPRINT("Using entry: %d. Buffer: %x\n", i, &RtlpStaticDebugInfo[i]); + RtlpDebugInfoFreeList[i] = TRUE; + + /* Use free entry found */ + return &RtlpStaticDebugInfo[i]; + } + + } + + /* We are out of static buffer, allocate dynamic */ + return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, + 0, + sizeof(RTL_CRITICAL_SECTION_DEBUG)); +} + +/*++ + * RtlpFreeDebugInfo + * + * Frees the memory for a Critical Section Debug Object + * + * Params: + * DebugInfo - Pointer to Critical Section Debug Object to free. + * + * Returns: + * None. + * + * Remarks: + * If the pointer is part of the static buffer, then the entry is made + * free again. If not, the object is de-allocated from the heap. + * + *--*/ +VOID +STDCALL +RtlpFreeDebugInfo( + PRTL_CRITICAL_SECTION_DEBUG DebugInfo) +{ + ULONG EntryId; + + /* Is it part of our cached entries? */ + if ((DebugInfo >= RtlpStaticDebugInfo) && + (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) { + + /* Yes. zero it out */ + RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + + /* Mark as free */ + EntryId = (DebugInfo - RtlpStaticDebugInfo); + DPRINT("Freeing from Buffer: %x. Entry: %d inside Process: %x\n", + DebugInfo, + EntryId, + NtCurrentTeb()->Cid.UniqueProcess); + RtlpDebugInfoFreeList[EntryId] = FALSE; + + } else { + + /* It's a dynamic one, so free from the heap */ + DPRINT("Freeing from Heap: %x inside Process: %x\n", + DebugInfo, + NtCurrentTeb()->Cid.UniqueProcess); + RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo); + + } } /* EOF */ diff --git a/reactos/lib/ntdll/rtl/dbgbuffer.c b/reactos/lib/ntdll/rtl/dbgbuffer.c index f490f75ec18..707635d40c8 100644 --- a/reactos/lib/ntdll/rtl/dbgbuffer.c +++ b/reactos/lib/ntdll/rtl/dbgbuffer.c @@ -219,7 +219,7 @@ RtlpQueryRemoteProcessModules(HANDLE ProcessHandle, { ModulePtr->Reserved[0] = ModulePtr->Reserved[1] = 0; // FIXME: ?? ModulePtr->Base = lmModule.BaseAddress; - ModulePtr->Size = lmModule.SizeOfImage; + ModulePtr->Size = lmModule.ResidentSize; ModulePtr->Flags = lmModule.Flags; ModulePtr->Index = 0; // FIXME: ?? ModulePtr->Unknown = 0; // FIXME: ?? diff --git a/reactos/lib/ntdll/rtl/i386/except.s b/reactos/lib/ntdll/rtl/i386/except.s deleted file mode 100755 index 49acc79a5ee..00000000000 --- a/reactos/lib/ntdll/rtl/i386/except.s +++ /dev/null @@ -1,291 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: User-mode exception support for IA-32 - * FILE: lib/ntdll/rtl/i386/except.s - * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * NOTES: This file is shared with ntoskrnl/rtl/i386/except.s. - * Please keep them in sync. - */ - -#define EXCEPTION_UNWINDING 0x02 - -#define EREC_FLAGS 0x04 - -#define ExceptionContinueExecution 0 -#define ExceptionContinueSearch 1 -#define ExceptionNestedException 2 -#define ExceptionCollidedUnwind 3 - -.globl _RtlpExecuteHandlerForException -.globl _RtlpExecuteHandlerForUnwind - -#define CONTEXT_FLAGS 0x00 -#define CONTEXT_SEGGS 0x8C -#define CONTEXT_SEGFS 0x90 -#define CONTEXT_SEGES 0x94 -#define CONTEXT_SEGDS 0x98 -#define CONTEXT_EDI 0x9C -#define CONTEXT_ESI 0xA0 -#define CONTEXT_EBX 0xA4 -#define CONTEXT_EDX 0xA8 -#define CONTEXT_ECX 0xAC -#define CONTEXT_EAX 0xB0 -#define CONTEXT_EBP 0xB4 -#define CONTEXT_EIP 0xB8 -#define CONTEXT_SEGCS 0xBC -#define CONTEXT_EFLAGS 0xC0 -#define CONTEXT_ESP 0xC4 -#define CONTEXT_SEGSS 0xC8 - - -#define RCC_CONTEXT 0x08 - -// EAX = value to print -_do_debug: - pushal - pushl %eax - call _AsmDebug@4 - popal - ret - -#ifndef __NTOSKRNL__ - -// -// VOID -// RtlpCaptureContext(PCONTEXT pContext); -// -// Parameters: -// [ESP+08h] - PCONTEXT_X86 pContext -// Registers: -// None -// Returns: -// Nothing -// Notes: -// Grabs the current CPU context. -.globl _RtlpCaptureContext -_RtlpCaptureContext: - pushl %ebp - movl %esp, %ebp - movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure - - cld - pushf - pop %eax - movl %eax, CONTEXT_EFLAGS(%edx) - xorl %eax, %eax - movl %eax, CONTEXT_EAX(%edx) - movl %eax, CONTEXT_EBX(%edx) - movl %eax, CONTEXT_ECX(%edx) - movl %eax, CONTEXT_EDX(%edx) - movl %eax, CONTEXT_ESI(%edx) - movl %eax, CONTEXT_EDI(%edx) - movl %cs, %eax - movl %eax, CONTEXT_SEGCS(%edx) - movl %ds, %eax - movl %eax, CONTEXT_SEGDS(%edx) - movl %es, %eax - movl %eax, CONTEXT_SEGES(%edx) - movl %fs, %eax - movl %eax, CONTEXT_SEGFS(%edx) - movl %gs, %eax - movl %eax, CONTEXT_SEGGS(%edx) - movl %ss, %eax - movl %eax, CONTEXT_SEGSS(%edx) - - // - // STACK LAYOUT: - (ESP to put in context structure) - // - RETURN ADDRESS OF CALLER OF CALLER - // - EBP OF CALLER OF CALLER - // ... - // - RETURN ADDRESS OF CALLER - // - EBP OF CALLER - // ... - // - - // Get return address of the caller of the caller of this function - movl %ebp, %ebx - //movl 4(%ebx), %eax // EAX = return address of caller - movl (%ebx), %ebx // EBX = EBP of caller - - movl 4(%ebx), %eax // EAX = return address of caller of caller - movl (%ebx), %ebx // EBX = EBP of caller of caller - - movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller - movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller - addl $8, %ebx - movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 - - movl %ebp, %esp - popl %ebp - ret - -#endif /* !__NTOSKRNL__ */ - -#define REH_ERECORD 0x08 -#define REH_RFRAME 0x0C -#define REH_CONTEXT 0x10 -#define REH_DCONTEXT 0x14 -#define REH_EROUTINE 0x18 - -// Parameters: -// None -// Registers: -// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord -// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame -// [EBP+10h] - PVOID Context -// [EBP+14h] - PVOID DispatcherContext -// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine -// EDX - Address of protecting exception handler -// Returns: -// EXCEPTION_DISPOSITION -// Notes: -// Setup the protecting exception handler and call the exception -// handler in the right context. -_RtlpExecuteHandler: - pushl %ebp - movl %esp, %ebp - pushl REH_RFRAME(%ebp) - - pushl %edx - pushl %fs:0x0 - movl %esp, %fs:0x0 - - // Prepare to call the exception handler - pushl REH_DCONTEXT(%ebp) - pushl REH_CONTEXT(%ebp) - pushl REH_RFRAME(%ebp) - pushl REH_ERECORD(%ebp) - - // Now call the exception handler - movl REH_EROUTINE(%ebp), %eax - call *%eax - - cmpl $-1, %fs:0x0 - jne .reh_stack_looks_ok - - // This should not happen - pushl 0 - pushl 0 - pushl 0 - pushl 0 - call _RtlAssert@16 - -.reh_loop: - jmp .reh_loop - -.reh_stack_looks_ok: - movl %fs:0x0, %esp - - // Return to the 'front-end' for this function - popl %fs:0x0 - movl %ebp, %esp - popl %ebp - ret - - -#define REP_ERECORD 0x04 -#define REP_RFRAME 0x08 -#define REP_CONTEXT 0x0C -#define REP_DCONTEXT 0x10 - -// Parameters: -// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord -// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame -// [ESP+0Ch] - PCONTEXT Context -// [ESP+10h] - PVOID DispatcherContext -// Registers: -// None -// Returns: -// EXCEPTION_DISPOSITION -// Notes: -// This exception handler protects the exception handling -// mechanism by detecting nested exceptions. -_RtlpExceptionProtector: - movl $ExceptionContinueSearch, %eax - movl REP_ERECORD(%esp), %ecx - testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) - jnz .rep_end - - // Unwinding is not taking place, so return ExceptionNestedException - - // Set DispatcherContext field to the exception registration for the - // exception handler that executed when a nested exception occurred - movl REP_DCONTEXT(%esp), %ecx - movl REP_RFRAME(%esp), %eax - movl %eax, (%ecx) - movl $ExceptionNestedException, %eax - -.rep_end: - ret - - -// Parameters: -// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord -// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame -// [ESP+0Ch] - PCONTEXT Context -// [ESP+10h] - PVOID DispatcherContext -// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler -// Registers: -// None -// Returns: -// EXCEPTION_DISPOSITION -// Notes: -// Front-end -_RtlpExecuteHandlerForException: - movl $_RtlpExceptionProtector, %edx - jmp _RtlpExecuteHandler - - -#define RUP_ERECORD 0x04 -#define RUP_RFRAME 0x08 -#define RUP_CONTEXT 0x0C -#define RUP_DCONTEXT 0x10 - -// Parameters: -// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord -// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame -// [ESP+0Ch] - PCONTEXT Context -// [ESP+10h] - PVOID DispatcherContext -// Registers: -// None -// Returns: -// EXCEPTION_DISPOSITION -// Notes: -// This exception handler protects the exception handling -// mechanism by detecting collided unwinds. -_RtlpUnwindProtector: - movl $ExceptionContinueSearch, %eax - movl %ecx, RUP_ERECORD(%esp) - testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) - jz .rup_end - - // Unwinding is taking place, so return ExceptionCollidedUnwind - - movl RUP_RFRAME(%esp), %ecx - movl RUP_DCONTEXT(%esp), %edx - - // Set DispatcherContext field to the exception registration for the - // exception handler that executed when a collision occurred - movl RUP_RFRAME(%ecx), %eax - movl %eax, (%edx) - movl $ExceptionCollidedUnwind, %eax - -.rup_end: - ret - - -// Parameters: -// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord -// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame -// [ESP+0Ch] - PCONTEXT Context -// [ESP+10h] - PVOID DispatcherContext -// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler -// Registers: -// None -// Returns: -// EXCEPTION_DISPOSITION -_RtlpExecuteHandlerForUnwind: - movl $_RtlpUnwindProtector, %edx - jmp _RtlpExecuteHandler diff --git a/reactos/lib/ntdll/rtl/intrlck.c b/reactos/lib/ntdll/rtl/intrlck.c index 5e91816b2a7..49f8b76ed93 100644 --- a/reactos/lib/ntdll/rtl/intrlck.c +++ b/reactos/lib/ntdll/rtl/intrlck.c @@ -116,12 +116,11 @@ InterlockedExchange(LPLONG target, LONG value ) * RETURNS * Prior value of value pointed to by Destination */ -PVOID -STDCALL -InterlockedCompareExchange( - PVOID *Destination, - PVOID Exchange, - PVOID Comperand ) +LONG +STDCALL +InterlockedCompareExchange(PLONG Destination, + LONG Exchange, + LONG Comperand) { PVOID ret; __asm__ ( /* lock for SMP systems */ diff --git a/reactos/lib/ntdll/rtl/misc.c b/reactos/lib/ntdll/rtl/misc.c index b8366000cbf..75345916583 100644 --- a/reactos/lib/ntdll/rtl/misc.c +++ b/reactos/lib/ntdll/rtl/misc.c @@ -96,3 +96,14 @@ RtlGetNtVersionNumbers(LPDWORD major, LPDWORD minor, LPDWORD build) *build = (0xF0000000 | pPeb->OSBuildNumber); } } + +/* +* @implemented +*/ +ULONG +STDCALL +RtlGetNtGlobalFlags(VOID) +{ + PPEB pPeb = NtCurrentPeb(); + return pPeb->NtGlobalFlag; +} diff --git a/reactos/lib/ntdll/rtl/path.c b/reactos/lib/ntdll/rtl/path.c index 9a3f4175773..3e60798b07b 100644 --- a/reactos/lib/ntdll/rtl/path.c +++ b/reactos/lib/ntdll/rtl/path.c @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include #include #define NDEBUG @@ -26,141 +28,27 @@ #define IS_PATH_SEPARATOR(x) (((x)==L'\\')||((x)==L'/')) + /* GLOBALS ********************************************************************/ -static const UNICODE_STRING _condev = -{ - .Length = sizeof(L"\\\\.\\CON") - sizeof(WCHAR), - .MaximumLength = sizeof(L"\\\\.\\CON"), - .Buffer = L"\\\\.\\CON" -}; +static const WCHAR DeviceRootW[] = L"\\\\.\\"; -static const UNICODE_STRING _lpt = -{ - .Length = sizeof(L"LPT") - sizeof(WCHAR), - .MaximumLength = sizeof(L"LPT"), - .Buffer = L"LPT" -}; +static const UNICODE_STRING _condev = RTL_CONSTANT_STRING(L"\\\\.\\CON"); -static const UNICODE_STRING _com = -{ - .Length = sizeof(L"COM") - sizeof(WCHAR), - .MaximumLength = sizeof(L"COM"), - .Buffer = L"COM" -}; +static const UNICODE_STRING _lpt = RTL_CONSTANT_STRING(L"LPT"); -static const UNICODE_STRING _prn = -{ - .Length = sizeof(L"PRN") - sizeof(WCHAR), - .MaximumLength = sizeof(L"PRN"), - .Buffer = L"PRN" -}; +static const UNICODE_STRING _com = RTL_CONSTANT_STRING(L"COM"); -static const UNICODE_STRING _aux = -{ - .Length = sizeof(L"AUX") - sizeof(WCHAR), - .MaximumLength = sizeof(L"AUX"), - .Buffer = L"AUX" -}; +static const UNICODE_STRING _prn = RTL_CONSTANT_STRING(L"PRN"); -static const UNICODE_STRING _con = -{ - .Length = sizeof(L"CON") - sizeof(WCHAR), - .MaximumLength = sizeof(L"CON"), - .Buffer = L"CON" -}; +static const UNICODE_STRING _aux = RTL_CONSTANT_STRING(L"AUX"); -static const UNICODE_STRING _nul = -{ - .Length = sizeof(L"NUL") - sizeof(WCHAR), - .MaximumLength = sizeof(L"NUL"), - .Buffer = L"NUL" -}; +static const UNICODE_STRING _con = RTL_CONSTANT_STRING(L"CON"); + +static const UNICODE_STRING _nul = RTL_CONSTANT_STRING(L"NUL"); /* FUNCTIONS *****************************************************************/ -static ULONG RtlpGetDotSequence (PWSTR p) -{ - ULONG Count = 0; - - for (;;) - { - if (*p == '.') - Count++; - else if ((*p == '\\' || *p == '\0') && Count) - return Count; - else - return 0; - p++; - } - return 0; -} - - -static VOID RtlpEatPath (PWSTR Path) -{ - PWSTR p, prev; - - p = Path + 2; - prev = p; - - while ((*p) != 0 || ((*p) == L'\\' && (*(p+1)) == 0)) - { - ULONG DotLen; - - DotLen = RtlpGetDotSequence (p+1); - DPRINT("DotSequenceLength %u\n", DotLen); - DPRINT("prev '%S' p '%S'\n",prev,p); - - if (DotLen == 0) - { - prev = p; - p = wcschr(p + 1, L'\\'); - if (p == NULL) - { - break; - } - } - else if (DotLen == 1) - { - wcscpy (p, p+2); - } - else - { - if (DotLen > 2) - { - int n = DotLen - 2; - - while (n > 0 && prev > (Path + 2)) - { - prev--; - if ((*prev) == L'\\') - n--; - } - } - - if (*(p + DotLen + 1) == 0) - *(prev + 1) = 0; - else - wcscpy (prev, p + DotLen + 1); - p = prev; - if (prev > (Path + 2)) - { - prev--; - while ((*prev) != L'\\') - { - prev--; - } - } - } - } - if (Path[2] == 0) - { - Path[2] = L'\\'; - Path[3] = 0; - } -} - /* * @implemented @@ -532,224 +420,338 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING name) return STATUS_SUCCESS; } -/* + + +/****************************************************************** + * collapse_path + * + * Helper for RtlGetFullPathName_U. + * 1) Convert slashes into backslashes + * 2) Get rid of duplicate backslashes + * 3) Get rid of . and .. components in the path. + */ +static inline void collapse_path( WCHAR *path, UINT mark ) +{ + WCHAR *p, *next; + + /* convert every / into a \ */ + for (p = path; *p; p++) if (*p == '/') *p = '\\'; + + /* collapse duplicate backslashes */ + next = path + max( 1, mark ); + for (p = next; *p; p++) if (*p != '\\' || next[-1] != '\\') *next++ = *p; + *next = 0; + + p = path + mark; + while (*p) + { + if (*p == '.') + { + switch(p[1]) + { + case '\\': /* .\ component */ + next = p + 2; + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + case 0: /* final . */ + if (p > path + mark) p--; + *p = 0; + continue; + case '.': + if (p[2] == '\\') /* ..\ component */ + { + next = p + 3; + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\\') p--; + } + memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + continue; + } + else if (!p[2]) /* final .. */ + { + if (p > path + mark) + { + p--; + while (p > path + mark && p[-1] != '\\') p--; + if (p > path + mark) p--; + } + *p = 0; + continue; + } + break; + } + } + /* skip to the next component */ + while (*p && *p != '\\') p++; + if (*p == '\\') p++; + } + + /* remove trailing spaces and dots (yes, Windows really does that, don't ask) */ + while (p > path + mark && (p[-1] == ' ' || p[-1] == '.')) p--; + *p = 0; +} + + + +/****************************************************************** + * skip_unc_prefix + * + * Skip the \\share\dir\ part of a file name. Helper for RtlGetFullPathName_U. + */ +static const WCHAR *skip_unc_prefix( const WCHAR *ptr ) +{ + ptr += 2; + while (*ptr && !IS_PATH_SEPARATOR(*ptr)) ptr++; /* share name */ + while (IS_PATH_SEPARATOR(*ptr)) ptr++; + while (*ptr && !IS_PATH_SEPARATOR(*ptr)) ptr++; /* dir name */ + while (IS_PATH_SEPARATOR(*ptr)) ptr++; + return ptr; +} + + +/****************************************************************** + * get_full_path_helper + * + * Helper for RtlGetFullPathName_U + * Note: name and buffer are allowed to point to the same memory spot + */ +static ULONG get_full_path_helper( + LPCWSTR name, + LPWSTR buffer, + ULONG size) +{ + ULONG reqsize = 0, mark = 0, dep = 0, deplen; + DOS_PATHNAME_TYPE type; + LPWSTR ins_str = NULL; + LPCWSTR ptr; + const UNICODE_STRING* cd; + WCHAR tmp[4]; + + /* return error if name only consists of spaces */ + for (ptr = name; *ptr; ptr++) if (*ptr != ' ') break; + if (!*ptr) return 0; + + RtlAcquirePebLock(); + + cd = &((PCURDIR)&NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectoryName)->DosPath; + + switch (type = RtlDetermineDosPathNameType_U(name)) + { + case UNC_PATH: /* \\foo */ + ptr = skip_unc_prefix( name ); + mark = (ptr - name); + break; + + case DEVICE_PATH: /* \\.\foo */ + mark = 4; + break; + + case ABSOLUTE_DRIVE_PATH: /* c:\foo */ + reqsize = sizeof(WCHAR); + tmp[0] = towupper(name[0]); + ins_str = tmp; + dep = 1; + mark = 3; + break; + + case RELATIVE_DRIVE_PATH: /* c:foo */ + dep = 2; + if (towupper(name[0]) != towupper(cd->Buffer[0]) || cd->Buffer[1] != ':') + { + UNICODE_STRING var, val; + + tmp[0] = '='; + tmp[1] = name[0]; + tmp[2] = ':'; + tmp[3] = '\0'; + var.Length = 3 * sizeof(WCHAR); + var.MaximumLength = 4 * sizeof(WCHAR); + var.Buffer = tmp; + val.Length = 0; + val.MaximumLength = size; + val.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, size); + + switch (RtlQueryEnvironmentVariable_U(NULL, &var, &val)) + { + case STATUS_SUCCESS: + /* FIXME: Win2k seems to check that the environment variable actually points + * to an existing directory. If not, root of the drive is used + * (this seems also to be the only spot in RtlGetFullPathName that the + * existence of a part of a path is checked) + */ + /* fall thru */ + case STATUS_BUFFER_TOO_SMALL: + reqsize = val.Length + sizeof(WCHAR); /* append trailing '\\' */ + val.Buffer[val.Length / sizeof(WCHAR)] = '\\'; + ins_str = val.Buffer; + break; + case STATUS_VARIABLE_NOT_FOUND: + reqsize = 3 * sizeof(WCHAR); + tmp[0] = name[0]; + tmp[1] = ':'; + tmp[2] = '\\'; + ins_str = tmp; + break; + default: + DPRINT1("Unsupported status code\n"); + break; + } + mark = 3; + break; + } + /* fall through */ + + case RELATIVE_PATH: /* foo */ + reqsize = cd->Length; + ins_str = cd->Buffer; + if (cd->Buffer[1] != ':') + { + ptr = skip_unc_prefix( cd->Buffer ); + mark = ptr - cd->Buffer; + } + else mark = 3; + break; + + case ABSOLUTE_PATH: /* \xxx */ +#ifdef __WINE__ + if (name[0] == '/') /* may be a Unix path */ + { + const WCHAR *ptr = name; + int drive = find_drive_root( &ptr ); + if (drive != -1) + { + reqsize = 3 * sizeof(WCHAR); + tmp[0] = 'A' + drive; + tmp[1] = ':'; + tmp[2] = '\\'; + ins_str = tmp; + mark = 3; + dep = ptr - name; + break; + } + } +#endif + if (cd->Buffer[1] == ':') + { + reqsize = 2 * sizeof(WCHAR); + tmp[0] = cd->Buffer[0]; + tmp[1] = ':'; + ins_str = tmp; + mark = 3; + } + else + { + ptr = skip_unc_prefix( cd->Buffer ); + reqsize = (ptr - cd->Buffer) * sizeof(WCHAR); + mark = reqsize / sizeof(WCHAR); + ins_str = cd->Buffer; + } + break; + + case UNC_DOT_PATH: /* \\. */ + reqsize = 4 * sizeof(WCHAR); + dep = 3; + tmp[0] = '\\'; + tmp[1] = '\\'; + tmp[2] = '.'; + tmp[3] = '\\'; + ins_str = tmp; + mark = 4; + break; + + case INVALID_PATH: + goto done; + } + + /* enough space ? */ + deplen = wcslen(name + dep) * sizeof(WCHAR); + if (reqsize + deplen + sizeof(WCHAR) > size) + { + /* not enough space, return need size (including terminating '\0') */ + reqsize += deplen + sizeof(WCHAR); + goto done; + } + + memmove(buffer + reqsize / sizeof(WCHAR), name + dep, deplen + sizeof(WCHAR)); + if (reqsize) memcpy(buffer, ins_str, reqsize); + reqsize += deplen; + + if (ins_str && ins_str != tmp && ins_str != cd->Buffer) + RtlFreeHeap(RtlGetProcessHeap(), 0, ins_str); + + collapse_path( buffer, mark ); + reqsize = wcslen(buffer) * sizeof(WCHAR); + +done: + RtlReleasePebLock(); + return reqsize; +} + + +/****************************************************************** + * RtlGetFullPathName_U (NTDLL.@) + * + * Returns the number of bytes written to buffer (not including the + * terminating NULL) if the function succeeds, or the required number of bytes + * (including the terminating NULL) if the buffer is too small. + * + * file_part will point to the filename part inside buffer (except if we use + * DOS device name, in which case file_in_buf is NULL) + * * @implemented */ -ULONG STDCALL -RtlGetFullPathName_U(PWSTR DosName, - ULONG size, - PWSTR buf, - PWSTR *FilePart) +DWORD STDCALL RtlGetFullPathName_U( + const WCHAR* name, + ULONG size, + WCHAR* buffer, + WCHAR** file_part) { - WCHAR *wcs, var[4], drive; - ULONG len; - ULONG templen = 0; - DWORD offs, sz, type; - UNICODE_STRING usvar, pfx; - PCURDIR cd; - NTSTATUS Status; - WCHAR TempFullPathName[MAX_PATH] = L""; + WCHAR* ptr; + DWORD dosdev; + DWORD reqsize; - DPRINT("RtlGetFullPathName_U %S %ld %p %p\n", - DosName, size, buf, FilePart); + DPRINT("RtlGetFullPathName_U(%S %lu %p %p)\n", name, size, buffer, file_part); - /* FIXME: this code is a mess! We should use Wine's implementation - of this function, since it's cleaner and IMO better. -Gunnar */ - - if (!DosName || !*DosName) - return 0; + if (!name || !*name) return 0; - len = wcslen (DosName); + if (file_part) *file_part = NULL; - /* strip trailing spaces */ - while (len && DosName[len - 1] == L' ') - len--; - if (!len) - return 0; - - /* strip trailing path separator (but don't change '\') */ - if ((len > 1) && - IS_PATH_SEPARATOR(DosName[len - 1])) - len--; - if (FilePart) - *FilePart = NULL; - if (buf) - *buf = 0; + /* check for DOS device name */ + dosdev = RtlIsDosDeviceName_U((WCHAR*)name); + if (dosdev) + { + DWORD offset = HIWORD(dosdev) / sizeof(WCHAR); /* get it in WCHARs, not bytes */ + DWORD sz = LOWORD(dosdev); /* in bytes */ -CHECKPOINT; - /* check for DOS device name */ - sz = RtlIsDosDeviceName_U (DosName); - if (sz) - { - offs = sz >> 17; - sz &= 0x0000FFFF; - if (sz + 8 >= size) - return sz + 10; - if (buf) - { - wcscpy (buf, L"\\\\.\\"); - wcsncat (buf, DosName + offs, sz / sizeof(WCHAR)); - } - return sz + 8; - } + if (8 + sz + 2 > size) return sz + 10; + wcscpy(buffer, DeviceRootW); + memmove(buffer + 4, name + offset, sz); + buffer[4 + sz / sizeof(WCHAR)] = '\0'; + /* file_part isn't set in this case */ + return sz + 8; + } -CHECKPOINT; - type = RtlDetermineDosPathNameType_U (DosName); - - RtlAcquirePebLock(); - - cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName); -DPRINT("type %ld\n", type); - switch (type) - { - case 1: /* \\xxx or \\.xxx */ - case 6: /* \\.\xxx */ - break; - - case 2: - break; -#if 0 - /* this makes a direct CreateFileW call crash! */ - - case 2: /* x:\xxx */ - *DosName = RtlUpcaseUnicodeChar (*DosName); - break; -#endif - - case 3: /* x:xxx */ - drive = RtlUpcaseUnicodeChar (*DosName); - DosName += 2; - len -= 2; -CHECKPOINT; - if (drive == RtlUpcaseUnicodeChar (cd->DosPath.Buffer[0])) - { -CHECKPOINT; - memcpy (TempFullPathName, cd->DosPath.Buffer, cd->DosPath.Length); - templen = cd->DosPath.Length / sizeof(WCHAR); - } - else - { -CHECKPOINT; - var[0] = L'='; - var[1] = drive; - var[2] = L':'; - var[3] = 0; - usvar.Length = 3 * sizeof(WCHAR); - usvar.MaximumLength = 4 * sizeof(WCHAR); - usvar.Buffer = var; - pfx.Length = 0; - pfx.MaximumLength = MAX_PATH; - pfx.Buffer = TempFullPathName; - Status = RtlQueryEnvironmentVariable_U (NULL, - &usvar, - &pfx); -CHECKPOINT; - if (!NT_SUCCESS(Status)) - { -CHECKPOINT; - if (Status == STATUS_BUFFER_TOO_SMALL) - return pfx.Length + len * 2 + 2; -CHECKPOINT; - TempFullPathName[0] = drive; - TempFullPathName[1] = L':'; - TempFullPathName[2] = L'\\'; - TempFullPathName[3] = 0; - templen = 3; - } - else - { -CHECKPOINT; - templen = pfx.Length / sizeof(WCHAR); - } - - } - break; - - case 4: /* \xxx */ - wcsncpy (TempFullPathName, cd->DosPath.Buffer, 2); - TempFullPathName[2] = 0; - templen = wcslen(TempFullPathName); - break; - - case 5: /* xxx */ - memcpy (TempFullPathName, cd->DosPath.Buffer, cd->DosPath.Length); - templen = cd->DosPath.Length / sizeof(WCHAR); - break; - - case 7: /* \\. */ - memcpy (TempFullPathName, L"\\\\.\\", 8); - templen = 4; - break; - - default: - return 0; - } - - - RtlReleasePebLock(); - - DPRINT("TempFullPathName \'%S\' DosName \'%S\' len %ld\n", TempFullPathName, DosName, len); - /* add dosname to prefix */ - memcpy (TempFullPathName + templen, DosName, len * sizeof(WCHAR)); - - /* dirty/temporary fix for the CreateFileW problem */ - if (type == 2){ - TempFullPathName[0] = RtlUpcaseUnicodeChar(TempFullPathName[0]); - } - len += templen; - TempFullPathName[len] = 0; - - CHECKPOINT; - /* replace slashes */ - wcs = wcschr(TempFullPathName, L'/'); - while(wcs) - { - *wcs = L'\\'; - wcs = wcschr(wcs + 1, L'/'); - } - - if (len == 2 && TempFullPathName[1] == L':') - { - TempFullPathName[len++] = L'\\'; - TempFullPathName[len] = 0; - } - - - DPRINT("TempFullPathName \'%S\'\n", TempFullPathName); - RtlpEatPath (TempFullPathName); - DPRINT("TempFullPathName \'%S\'\n", TempFullPathName); - - len = wcslen (TempFullPathName); - - if (len < (size / sizeof(WCHAR))) - { - if (buf) - memcpy (buf, TempFullPathName, (len + 1) * sizeof(WCHAR)); - - /* find file part */ - if (FilePart && buf) - { -#if 0 - *FilePart = wcsrchr(buf, L'\\'); - if (*FilePart) - { - (*FilePart)++; - } - else - { - *FilePart = buf; - } -#else - *FilePart = buf + len; - while (*FilePart != buf && **FilePart != L'\\') - --(*FilePart); - if (**FilePart == L'\\') - ++(*FilePart); -#endif - } + reqsize = get_full_path_helper(name, buffer, size); + if (!reqsize) return 0; + if (reqsize > size) + { + LPWSTR tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, reqsize); + reqsize = get_full_path_helper(name, tmp, reqsize); + if (reqsize > size) /* it may have worked the second time */ + { + RtlFreeHeap(RtlGetProcessHeap(), 0, tmp); + return reqsize + sizeof(WCHAR); } + memcpy( buffer, tmp, reqsize + sizeof(WCHAR) ); + RtlFreeHeap(RtlGetProcessHeap(), 0, tmp); + } - return len * sizeof(WCHAR); + /* find file part */ + if (file_part && (ptr = wcsrchr(buffer, '\\')) != NULL && ptr >= buffer + 2 && *++ptr) + *file_part = ptr; + return reqsize; } @@ -837,6 +839,12 @@ RtlDosPathNameToNtPathName_U(PWSTR dosname, Length = wcslen(fullname + Offset); memcpy (Buffer + tmpLength, fullname + Offset, (Length + 1) * sizeof(WCHAR)); Length += tmpLength; + if (Type == ABSOLUTE_DRIVE_PATH || + Type == RELATIVE_DRIVE_PATH) + { + /* make the drive letter to uppercase */ + Buffer[tmpLength] = towupper(Buffer[tmpLength]); + } /* set NT filename */ ntname->Length = Length * sizeof(WCHAR); diff --git a/reactos/lib/ntdll/rtl/process.c b/reactos/lib/ntdll/rtl/process.c index 78d7271ee21..36f2071424d 100644 --- a/reactos/lib/ntdll/rtl/process.c +++ b/reactos/lib/ntdll/rtl/process.c @@ -48,6 +48,13 @@ static NTSTATUS RtlpCreateFirstThread ); } +PPEB +STDCALL +RtlpCurrentPeb(VOID) +{ + return NtCurrentPeb(); +} + static NTSTATUS RtlpMapFile(PUNICODE_STRING ImageFileName, PRTL_USER_PROCESS_PARAMETERS Ppb, diff --git a/reactos/lib/ole32/Makefile.in b/reactos/lib/ole32/Makefile.in index 59f42bef30e..229f1367c1a 100644 --- a/reactos/lib/ole32/Makefile.in +++ b/reactos/lib/ole32/Makefile.in @@ -35,7 +35,8 @@ C_SRCS = \ rpc.c \ stg_bigblockfile.c \ stg_stream.c \ - storage32.c + storage32.c \ + stubmanager.c C_SRCS16 = \ memlockbytes16.c \ diff --git a/reactos/lib/ole32/bindctx.c b/reactos/lib/ole32/bindctx.c index 9fab4715c6b..58a647df18d 100644 --- a/reactos/lib/ole32/bindctx.c +++ b/reactos/lib/ole32/bindctx.c @@ -275,8 +275,7 @@ HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk) if(This->bindCtxTable[index].pObj) IUnknown_Release(This->bindCtxTable[index].pObj); - if(This->bindCtxTable[index].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); /* left-shift all elements in the right side of the current revoked object */ for(j=index; jbindCtxTableLastIndex-1; j++) @@ -302,8 +301,7 @@ HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface) { if(This->bindCtxTable[i].pObj) IUnknown_Release(This->bindCtxTable[i].pObj); - if(This->bindCtxTable[i].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj); } This->bindCtxTableLastIndex = 0; @@ -472,8 +470,7 @@ HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum) /* release the object if it's found */ if(This->bindCtxTable[index].pObj) IUnknown_Release(This->bindCtxTable[index].pObj); - if(This->bindCtxTable[index].pkeyObj) - HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); + HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj); /* remove the object from the table with a left-shifting of all objects in the right side */ for(j=index; jbindCtxTableLastIndex-1; j++) diff --git a/reactos/lib/ole32/clipboard.c b/reactos/lib/ole32/clipboard.c index 9bbd6932430..e21eb5bc061 100644 --- a/reactos/lib/ole32/clipboard.c +++ b/reactos/lib/ole32/clipboard.c @@ -736,7 +736,7 @@ static HWND OLEClipbrd_CreateWindow() * We don't bother doing this since the FindClassByAtom code * would have to be changed to deal with this idiosyncrasy. */ wcex.style = CS_GLOBALCLASS; - wcex.lpfnWndProc = (WNDPROC)OLEClipbrd_WndProc; + wcex.lpfnWndProc = OLEClipbrd_WndProc; wcex.hInstance = 0; wcex.lpszClassName = OLEClipbrd_WNDCLASS; @@ -1489,8 +1489,7 @@ CLEANUP: /* * Free the array of FORMATETC's */ - if (afmt) - HeapFree(GetProcessHeap(), 0, afmt); + HeapFree(GetProcessHeap(), 0, afmt); /* * Close Windows clipboard diff --git a/reactos/lib/ole32/compobj.c b/reactos/lib/ole32/compobj.c index 17cff88167f..1ed832a8a12 100644 --- a/reactos/lib/ole32/compobj.c +++ b/reactos/lib/ole32/compobj.c @@ -21,6 +21,44 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note + * 1. COINIT_MULTITHREADED is 0; it is the lack of COINIT_APARTMENTTHREADED + * Therefore do not test against COINIT_MULTITHREADED + * + * TODO list: (items bunched together depend on each other) + * + * - Switch wine_marshal_id to use IPIDs not IIDs + * - Once that's done, replace wine_marshal_id with STDOBJREF + * + * - Rewrite the CoLockObjectExternal code, it does totally the wrong + * thing currently (should be controlling the stub manager) + * + * - Make the MTA dynamically allocated and refcounted + * - Free the ReservedForOle data in DllMain(THREAD_DETACH) + * + * - Implement the service control manager (in rpcss) to keep track + * of registered class objects: ISCM::ServerRegisterClsid et al + * - Implement the OXID resolver so we don't need magic pipe names for + * clients and servers to meet up + * - Flip our marshalling on top of the RPC runtime transport API, + * so we no longer use named pipes to communicate + * - Rework threading so re-entrant calls don't need to be sent on + * the incoming pipe + * - Implement RPC thread affinity (should fix InstallShield painting + * problems) + * + * - Implement IRemUnknown and marshalling for it, then use that for + * reffing/unreffing the stub manager from a proxy instead of our + * current hack of simply reffing the stub manager once when it's + * registered. + * - Implement table marshalling, then use it to let us do the final + * rework of the threading + * + * - Make our custom marshalling use NDR to be wire compatible with + * native DCOM + * + * */ #include "config.h" @@ -61,15 +99,15 @@ typedef LPCSTR LPCOLESTR16; * * TODO: Most of these things will have to be made thread-safe. */ -HINSTANCE COMPOBJ_hInstance32 = 0; static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN* ppUnk); -static void COM_RevokeAllClasses(); -static void COM_ExternalLockFreeList(); +static void COM_RevokeAllClasses(void); +static void COM_ExternalLockFreeList(void); const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} }; -APARTMENT MTA, *apts; +APARTMENT MTA; +static struct list apts = LIST_INIT( apts ); static CRITICAL_SECTION csApartment; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -102,7 +140,7 @@ typedef struct tagRegisteredClass DWORD runContext; DWORD connectFlags; DWORD dwCookie; - HANDLE hThread; /* only for localserver */ + LPSTREAM pMarshaledData; /* FIXME: only really need to store OXID and IPID */ struct tagRegisteredClass* nextClass; } RegisteredClass; @@ -206,6 +244,7 @@ static void COM_UninitMTA(void) MTA.oxid = 0; } + /* creates an apartment structure which stores OLE thread-local * information. Call with COINIT_UNINITIALIZED to create an apartment * that will be initialized with a model later. Note: do not call @@ -213,81 +252,138 @@ static void COM_UninitMTA(void) * with a different COINIT value */ APARTMENT* COM_CreateApartment(DWORD model) { - APARTMENT *apt; - BOOL create = (NtCurrentTeb()->ReservedForOle == NULL); + APARTMENT *apt = COM_CurrentApt(); - if (create) + if (!apt) { + if (!(model & COINIT_APARTMENTTHREADED)) /* See note 1 above */ + { + TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId()); + COM_CurrentInfo()->apt = &MTA; + return COM_CurrentInfo()->apt; + } + + TRACE("creating new apartment, model=%ld\n", model); + apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT)); apt->tid = GetCurrentThreadId(); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &apt->thread, THREAD_ALL_ACCESS, FALSE, 0); - } - else - apt = NtCurrentTeb()->ReservedForOle; - apt->model = model; - if (model & COINIT_APARTMENTTHREADED) { - /* FIXME: how does windoze create OXIDs? */ - apt->oxid = MTA.oxid | GetCurrentThreadId(); - apt->win = CreateWindowA(aptWinClass, NULL, 0, - 0, 0, 0, 0, - 0, 0, OLE32_hInstance, NULL); - InitializeCriticalSection(&apt->cs); + list_init(&apt->proxies); + list_init(&apt->stubmgrs); + apt->oidc = 1; + apt->refs = 1; + InitializeCriticalSection(&apt->cs); + + apt->model = model; + + /* we don't ref the apartment as CoInitializeEx will do it for us */ + + if (model & COINIT_APARTMENTTHREADED) + { + /* FIXME: how does windoze create OXIDs? */ + apt->oxid = MTA.oxid | GetCurrentThreadId(); + TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid)); + apt->win = CreateWindowA(aptWinClass, NULL, 0, + 0, 0, 0, 0, + 0, 0, OLE32_hInstance, NULL); + } + + EnterCriticalSection(&csApartment); + list_add_head(&apts, &apt->entry); + LeaveCriticalSection(&csApartment); + + COM_CurrentInfo()->apt = apt; } - else if (!(model & COINIT_UNINITIALIZED)) { - apt->parent = &MTA; - apt->oxid = MTA.oxid; - } - EnterCriticalSection(&csApartment); - if (create) - { - if (apts) apts->prev = apt; - apt->next = apts; - apts = apt; - } - LeaveCriticalSection(&csApartment); - NtCurrentTeb()->ReservedForOle = apt; + return apt; } -static void COM_DestroyApartment(APARTMENT *apt) +DWORD COM_ApartmentAddRef(struct apartment *apt) { - EnterCriticalSection(&csApartment); - if (apt->prev) apt->prev->next = apt->next; - if (apt->next) apt->next->prev = apt->prev; - if (apts == apt) apts = apt->next; - apt->prev = NULL; apt->next = NULL; - LeaveCriticalSection(&csApartment); - if (apt->model & COINIT_APARTMENTTHREADED) { - if (apt->win) DestroyWindow(apt->win); - DeleteCriticalSection(&apt->cs); - } - CloseHandle(apt->thread); - HeapFree(GetProcessHeap(), 0, apt); + return InterlockedIncrement(&apt->refs); } -/* The given OXID must be local to this process: you cannot use apartment - windows to send RPCs to other processes. This all needs to move to rpcrt4 */ -HWND COM_GetApartmentWin(OXID oxid) +DWORD COM_ApartmentRelease(struct apartment *apt) { - APARTMENT *apt; - HWND win = 0; + DWORD ret; + + ret = InterlockedDecrement(&apt->refs); + if (ret == 0) + { + TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid)); + + EnterCriticalSection(&csApartment); + list_remove(&apt->entry); + LeaveCriticalSection(&csApartment); + + MARSHAL_Disconnect_Proxies(apt); + + if (apt->win) DestroyWindow(apt->win); + + if (!list_empty(&apt->stubmgrs)) + { + FIXME("Destroy outstanding stubs\n"); + } + + if (apt->filter) IUnknown_Release(apt->filter); + + + DeleteCriticalSection(&apt->cs); + CloseHandle(apt->thread); + HeapFree(GetProcessHeap(), 0, apt); + + apt = NULL; + } + + return ret; +} + +/* The given OXID must be local to this process: you cannot use + * apartment windows to send RPCs to other processes. This all needs + * to move to rpcrt4. + * + * The ref parameter is here mostly to ensure people remember that + * they get one, you should normally take a ref for thread safety. + */ +APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref) +{ + APARTMENT *result = NULL; + struct list *cursor; EnterCriticalSection(&csApartment); - apt = apts; - while (apt && apt->oxid != oxid) apt = apt->next; - if (apt) win = apt->win; + LIST_FOR_EACH( cursor, &apts ) + { + struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry ); + if (apt->oxid == oxid) + { + result = apt; + if (ref) COM_ApartmentAddRef(result); + break; + } + } LeaveCriticalSection(&csApartment); - return win; + + return result; +} + +HWND COM_GetApartmentWin(OXID oxid, BOOL ref) +{ + APARTMENT *apt; + + apt = COM_ApartmentFromOXID(oxid, ref); + if (!apt) return NULL; + + return apt->win; } /* Currently inter-thread marshalling is not fully implemented, so this does nothing */ static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hWnd, msg, wParam, lParam); -} +} /***************************************************************************** * This section contains OpenDllList implemantation @@ -418,8 +514,7 @@ HRESULT WINAPI CoInitialize( * CoUninitialize */ HRESULT WINAPI CoInitializeEx( - LPVOID lpReserved, /* [in] pointer to win32 malloc interface - (obsolete, should be NULL) */ + LPVOID lpReserved, /* [in] pointer to win32 malloc interface (obsolete, should be NULL) */ DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */ ) { @@ -433,21 +528,6 @@ HRESULT WINAPI CoInitializeEx( ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved); } - apt = NtCurrentTeb()->ReservedForOle; - if (apt && !(apt->model == COINIT_UNINITIALIZED)) - { - if (dwCoInit != apt->model) - { - /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine - code then we are probably using the wrong threading model to implement that API. */ - ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); - return RPC_E_CHANGED_MODE; - } - hr = S_FALSE; - } - else - hr = S_OK; - /* * Check the lock count. If this is the first time going through the initialize * process, we have to initialize the libraries. @@ -463,13 +543,25 @@ HRESULT WINAPI CoInitializeEx( COM_InitMTA(); + /* we may need to defer this until after apartment initialisation */ RunningObjectTableImpl_Initialize(); } - if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit); + if (!(apt = COM_CurrentInfo()->apt)) + { + apt = COM_CreateApartment(dwCoInit); + if (!apt) return E_OUTOFMEMORY; + } + else if (dwCoInit != apt->model) + { + /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine + code then we are probably using the wrong threading model to implement that API. */ + ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit); + COM_ApartmentRelease(apt); + return RPC_E_CHANGED_MODE; + } - InterlockedIncrement(&apt->inits); - if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt; + COM_CurrentInfo()->inits++; return hr; } @@ -480,14 +572,20 @@ HRESULT WINAPI CoInitializeEx( void COM_FlushMessageQueue(void) { MSG message; - APARTMENT *apt = NtCurrentTeb()->ReservedForOle; + APARTMENT *apt = COM_CurrentApt(); if (!apt || !apt->win) return; TRACE("Flushing STA message queue\n"); - while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) { - if (message.hwnd != apt->win) continue; + while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) + { + if (message.hwnd != apt->win) + { + WARN("discarding message 0x%x for window %p\n", message.message, message.hwnd); + continue; + } + TranslateMessage(&message); DispatchMessageA(&message); } @@ -511,17 +609,25 @@ void COM_FlushMessageQueue(void) */ void WINAPI CoUninitialize(void) { + struct oletls * info = COM_CurrentInfo(); LONG lCOMRefCnt; - APARTMENT *apt; TRACE("()\n"); - apt = NtCurrentTeb()->ReservedForOle; - if (!apt) return; - if (InterlockedDecrement(&apt->inits)==0) { - NtCurrentTeb()->ReservedForOle = NULL; - COM_DestroyApartment(apt); - apt = NULL; + /* will only happen on OOM */ + if (!info) return; + + /* sanity check */ + if (!info->inits) + { + ERR("Mismatched CoUninitialize\n"); + return; + } + + if (!--info->inits) + { + COM_ApartmentRelease(info->apt); + info->apt = NULL; } /* @@ -536,14 +642,6 @@ void WINAPI CoUninitialize(void) RunningObjectTableImpl_UnInitialize(); - /* disconnect proxies to release the corresponding stubs. - * It is confirmed in "Essential COM" in the sub-chapter on - * "Lifecycle Management and Marshalling" that the native version also - * does some kind of proxy cleanup in this function. - * FIXME: does it just disconnect or completely destroy the proxies? - * FIXME: should this be in the apartment destructor? */ - MARSHAL_Disconnect_Proxies(); - /* Release the references to the registered class objects */ COM_RevokeAllClasses(); @@ -1091,117 +1189,24 @@ end: return hr; } -static DWORD WINAPI -_LocalServerThread(LPVOID param) { - HANDLE hPipe; - char pipefn[200]; - RegisteredClass *newClass = (RegisteredClass*)param; - HRESULT hres; - IStream *pStm; - STATSTG ststg; - unsigned char *buffer; - int buflen; - IClassFactory *classfac; - LARGE_INTEGER seekto; - ULARGE_INTEGER newpos; - ULONG res; - - TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier)); - - strcpy(pipefn,PIPEPREF); - WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF)); - - hPipe = CreateNamedPipeA( pipefn, PIPE_ACCESS_DUPLEX, - PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, - 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, NULL ); - if (hPipe == INVALID_HANDLE_VALUE) { - FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError()); - return 1; - } - while (1) { - if (!ConnectNamedPipe(hPipe,NULL)) { - ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError()); - break; - } - - TRACE("marshalling IClassFactory to client\n"); - - hres = IUnknown_QueryInterface(newClass->classObject,&IID_IClassFactory,(LPVOID*)&classfac); - if (hres) return hres; - - hres = CreateStreamOnHGlobal(0,TRUE,&pStm); - if (hres) { - FIXME("Failed to create stream on hglobal.\n"); - return hres; - } - hres = CoMarshalInterface(pStm,&IID_IClassFactory,(LPVOID)classfac,0,NULL,0); - if (hres) { - FIXME("CoMarshalInterface failed, %lx!\n",hres); - return hres; - } - - IUnknown_Release(classfac); /* is this right? */ - - hres = IStream_Stat(pStm,&ststg,0); - if (hres) return hres; - - buflen = ststg.cbSize.u.LowPart; - buffer = HeapAlloc(GetProcessHeap(),0,buflen); - seekto.u.LowPart = 0; - seekto.u.HighPart = 0; - hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); - if (hres) { - FIXME("IStream_Seek failed, %lx\n",hres); - return hres; - } - - hres = IStream_Read(pStm,buffer,buflen,&res); - if (hres) { - FIXME("Stream Read failed, %lx\n",hres); - return hres; - } - - IStream_Release(pStm); - - WriteFile(hPipe,buffer,buflen,&res,NULL); - FlushFileBuffers(hPipe); - DisconnectNamedPipe(hPipe); - - TRACE("done marshalling IClassFactory\n"); - } - CloseHandle(hPipe); - return 0; -} - /****************************************************************************** * CoRegisterClassObject [OLE32.@] - * - * This method will register the class object for a given class - * ID. Servers housed in EXE files use this method instead of - * exporting DllGetClassObject to allow other code to connect to their - * objects. * - * When a class object (an object which implements IClassFactory) is - * registered in this way, a new thread is started which listens for - * connections on a named pipe specific to the registered CLSID. When - * something else connects to it, it writes out the marshalled - * IClassFactory interface to the pipe. The code on the other end uses - * this buffer to unmarshal the class factory, and can then call - * methods on it. - * - * In Windows, such objects are registered with the RPC endpoint - * mapper, not with a unique named pipe. - * - * MSDN claims that multiple interface registrations are legal, but we - * can't do that with our current implementation. + * Registers the class object for a given class ID. Servers housed in EXE + * files use this method instead of exporting DllGetClassObject to allow + * other code to connect to their objects. * * RETURNS - * S_OK on success, - * E_INVALIDARG if lpdwRegister or pUnk are NULL, + * S_OK on success, + * E_INVALIDARG if lpdwRegister or pUnk are NULL, * CO_E_OBJISREG if the object is already registered. We should not return this. * * SEE ALSO * CoRevokeClassObject, CoGetClassObject + * + * BUGS + * MSDN claims that multiple interface registrations are legal, but we + * can't do that with our current implementation. */ HRESULT WINAPI CoRegisterClassObject( REFCLSID rclsid, /* [in] CLSID of the object to register */ @@ -1220,6 +1225,12 @@ HRESULT WINAPI CoRegisterClassObject( if ( (lpdwRegister==0) || (pUnk==0) ) return E_INVALIDARG; + if (!COM_CurrentApt()) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; + } + *lpdwRegister = 0; /* @@ -1243,7 +1254,7 @@ HRESULT WINAPI CoRegisterClassObject( newClass->connectFlags = flags; /* * Use the address of the chain node as the cookie since we are sure it's - * unique. + * unique. FIXME: not on 64-bit platforms. */ newClass->dwCookie = (DWORD)newClass; newClass->nextClass = firstRegisteredClass; @@ -1261,10 +1272,30 @@ HRESULT WINAPI CoRegisterClassObject( *lpdwRegister = newClass->dwCookie; if (dwClsContext & CLSCTX_LOCAL_SERVER) { - DWORD tid; + IClassFactory *classfac; - STUBMGR_Start(); - newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid); + hr = IUnknown_QueryInterface(newClass->classObject, &IID_IClassFactory, + (LPVOID*)&classfac); + if (hr) return hr; + + hr = CreateStreamOnHGlobal(0, TRUE, &newClass->pMarshaledData); + if (hr) { + FIXME("Failed to create stream on hglobal, %lx\n", hr); + IUnknown_Release(classfac); + return hr; + } + hr = CoMarshalInterface(newClass->pMarshaledData, &IID_IClassFactory, + (LPVOID)classfac, MSHCTX_LOCAL, NULL, + MSHLFLAGS_TABLESTRONG); + if (hr) { + FIXME("CoMarshalInterface failed, %lx!\n",hr); + IUnknown_Release(classfac); + return hr; + } + + IUnknown_Release(classfac); + + RPC_StartLocalServer(&newClass->classIdentifier, newClass->pMarshaledData); } return S_OK; } @@ -1310,6 +1341,15 @@ HRESULT WINAPI CoRevokeClassObject( */ IUnknown_Release(curClass->classObject); + if (curClass->pMarshaledData) + { + LARGE_INTEGER zero; + memset(&zero, 0, sizeof(zero)); + /* FIXME: stop local server thread */ + IStream_Seek(curClass->pMarshaledData, zero, SEEK_SET, NULL); + CoReleaseMarshalData(curClass->pMarshaledData); + } + /* * Free the memory used by the chain node. */ @@ -1509,7 +1549,7 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid) pat=ReadPatternFromRegistry(i,j); hFile=CreateFileW(filePathName,,,,,,hFile); SetFilePosition(hFile,pat.offset); - ReadFile(hFile,buf,pat.size,NULL,NULL); + ReadFile(hFile,buf,pat.size,&r,NULL); if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){ *pclsid=ReadCLSIDFromRegistry(i); @@ -1573,7 +1613,7 @@ HRESULT WINAPI CoCreateInstance( LPCLASSFACTORY lpclf = 0; if (!COM_CurrentApt()) return CO_E_NOTINITIALIZED; - + /* * Sanity check */ @@ -1590,15 +1630,15 @@ HRESULT WINAPI CoCreateInstance( * Rather than create a class factory, we can just check for it here */ if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) { - if (StdGlobalInterfaceTableInstance == NULL) + if (StdGlobalInterfaceTableInstance == NULL) StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); hres = IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, iid, ppv); if (hres) return hres; - + TRACE("Retrieved GIT (%p)\n", *ppv); return S_OK; } - + /* * Get a class factory to construct the object we want. */ @@ -1982,6 +2022,8 @@ HRESULT WINAPI CoLockObjectExternal( BOOL fLock, /* [in] do lock */ BOOL fLastUnlockReleases) /* [in] unlock all */ { + TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n", + pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE"); if (fLock) { /* @@ -2015,19 +2057,19 @@ HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) { */ HRESULT WINAPI CoGetState(IUnknown ** ppv) { - APARTMENT * apt = COM_CurrentInfo(); + HRESULT hr = E_FAIL; - FIXME("\n"); + *ppv = NULL; - if(apt && apt->state) { - IUnknown_AddRef(apt->state); - *ppv = apt->state; - FIXME("-- %p\n", *ppv); - return S_OK; - } - *ppv = NULL; - return E_FAIL; + if (COM_CurrentInfo()->state) + { + IUnknown_AddRef(COM_CurrentInfo()->state); + *ppv = COM_CurrentInfo()->state; + TRACE("apt->state=%p\n", COM_CurrentInfo()->state); + hr = S_OK; + } + return hr; } /*********************************************************************** @@ -2036,22 +2078,17 @@ HRESULT WINAPI CoGetState(IUnknown ** ppv) */ HRESULT WINAPI CoSetState(IUnknown * pv) { - APARTMENT * apt = COM_CurrentInfo(); + if (pv) IUnknown_AddRef(pv); - if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED); + if (COM_CurrentInfo()->state) + { + TRACE("-- release %p now\n", COM_CurrentInfo()->state); + IUnknown_Release(COM_CurrentInfo()->state); + } - FIXME("(%p),stub!\n", pv); + COM_CurrentInfo()->state = pv; - if (pv) { - IUnknown_AddRef(pv); - } - - if (apt->state) { - TRACE("-- release %p now\n", apt->state); - IUnknown_Release(apt->state); - } - apt->state = pv; - return S_OK; + return S_OK; } @@ -2206,7 +2243,7 @@ HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew) done: if (hkey) RegCloseKey(hkey); return res; - + } /*********************************************************************** diff --git a/reactos/lib/ole32/compobj_private.h b/reactos/lib/ole32/compobj_private.h index 2ba004eef90..e950eeaca33 100644 --- a/reactos/lib/ole32/compobj_private.h +++ b/reactos/lib/ole32/compobj_private.h @@ -5,6 +5,7 @@ * Copyright 1999 Sylvain St-Germain * Copyright 2002 Marcus Meissner * Copyright 2003 Ove Kåven, TransGaming Technologies + * Copyright 2004 Mike Hearn, CodeWeavers Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,8 @@ #include +#include "wine/list.h" + #include "windef.h" #include "winbase.h" #include "wtypes.h" @@ -35,12 +38,8 @@ #include "winreg.h" #include "winternl.h" -/* Windows maps COINIT values to 0x80 for apartment threaded, 0x140 - * for free threaded, and 0 for uninitialized apartments. There is - * no real advantage in us doing this and certainly no release version - * of an app should be poking around with these flags. So we need a - * special value for uninitialized */ -#define COINIT_UNINITIALIZED 0x100 +struct apartment; + /* exported interface */ typedef struct tagXIF { @@ -56,7 +55,7 @@ typedef struct tagXIF { /* exported object */ typedef struct tagXOBJECT { IRpcStubBufferVtbl *lpVtbl; - struct tagAPARTMENT *parent; + struct apartment *parent; struct tagXOBJECT *next; LPUNKNOWN obj; /* object identity (IUnknown) */ OID oid; /* object ID */ @@ -65,51 +64,54 @@ typedef struct tagXOBJECT { DWORD refs; /* external reference count */ } XOBJECT; -/* imported interface */ -typedef struct tagIIF { - struct tagIIF *next; +/* imported interface proxy */ +struct ifproxy +{ + struct list entry; LPVOID iface; /* interface pointer */ IID iid; /* interface ID */ IPID ipid; /* imported interface ID */ LPRPCPROXYBUFFER proxy; /* interface proxy */ DWORD refs; /* imported (public) references */ - HRESULT hres; /* result of proxy creation attempt */ -} IIF; +}; -/* imported object */ -typedef struct tagIOBJECT { - IRemUnknownVtbl *lpVtbl; - struct tagAPARTMENT *parent; - struct tagIOBJECT *next; +/* imported object / proxy manager */ +struct proxy_manager +{ + const IInternalUnknownVtbl *lpVtbl; + struct apartment *parent; + struct list entry; LPRPCCHANNELBUFFER chan; /* channel to object */ OXID oxid; /* object exported ID */ OID oid; /* object ID */ - IPID ipid; /* first imported interface ID */ - IIF *ifaces; /* imported interfaces */ + struct list interfaces; /* imported interfaces */ DWORD refs; /* proxy reference count */ -} IOBJECT; + CRITICAL_SECTION cs; /* thread safety for this object and children */ +}; -/* apartment */ -typedef struct tagAPARTMENT { - struct tagAPARTMENT *next, *prev, *parent; +/* this needs to become a COM object that implements IRemUnknown */ +struct apartment +{ + struct list entry; + + DWORD refs; /* refcount of the apartment */ DWORD model; /* threading model */ - DWORD inits; /* CoInitialize count */ DWORD tid; /* thread id */ HANDLE thread; /* thread handle */ OXID oxid; /* object exporter ID */ - OID oidc; /* object ID counter */ + OID oidc; /* object ID counter, starts at 1, zero is invalid OID */ HWND win; /* message window */ CRITICAL_SECTION cs; /* thread safety */ LPMESSAGEFILTER filter; /* message filter */ XOBJECT *objs; /* exported objects */ - IOBJECT *proxies; /* imported objects */ - LPUNKNOWN state; /* state object (see Co[Get,Set]State) */ - LPVOID ErrorInfo; /* thread error info */ -} APARTMENT; + struct list proxies; /* imported objects */ + DWORD listenertid; /* id of apartment_listener_thread */ + struct list stubmgrs; /* stub managers for exported objects */ +}; -extern APARTMENT MTA, *apts; +typedef struct apartment APARTMENT; -extern void* StdGlobalInterfaceTable_Construct(); +extern void* StdGlobalInterfaceTable_Construct(void); extern void StdGlobalInterfaceTable_Destroy(void* self); extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv); @@ -118,74 +120,123 @@ extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) extern void* StdGlobalInterfaceTableInstance; -#define PIPEPREF "\\\\.\\pipe\\" -#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr" - /* Standard Marshalling definitions */ typedef struct _wine_marshal_id { - DWORD processid; - DWORD objectid; /* unique value corresp. IUnknown of object */ - IID iid; + OXID oxid; /* id of apartment */ + OID oid; /* id of stub manager */ + IPID ipid; /* id of interface pointer */ } wine_marshal_id; inline static BOOL MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) { return - (mid1->processid == mid2->processid) && - (mid1->objectid == mid2->objectid) && - IsEqualIID(&(mid1->iid),&(mid2->iid)) + (mid1->oxid == mid2->oxid) && + (mid1->oid == mid2->oid) && + IsEqualGUID(&(mid1->ipid),&(mid2->ipid)) ; } -/* compare without interface compare */ -inline static BOOL -MARSHAL_Compare_Mids_NoInterface(wine_marshal_id *mid1, wine_marshal_id *mid2) { - return - (mid1->processid == mid2->processid) && - (mid1->objectid == mid2->objectid) - ; -} - -HRESULT MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub); -void MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid); -HRESULT MARSHAL_Disconnect_Proxies(); - +HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt); HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv); -void STUBMGR_Start(); +/* Thread-safety Annotation Legend: + * + * RO - The value is read only. It never changes after creation, so no + * locking is required. + * LOCK - The value is written to only using Interlocked* functions. + * CS - The value is read or written to with a critical section held. + * The identifier following "CS" is the specific critical section that + * must be used. + */ + +/* an interface stub */ +struct ifstub +{ + struct list entry; /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */ + IRpcStubBuffer *stubbuffer; /* RO */ + IID iid; /* RO */ + IPID ipid; /* RO */ + IUnknown *iface; /* RO */ + BOOL table; /* CS stub_manager->lock */ +}; + + +/* stub managers hold refs on the object and each interface stub */ +struct stub_manager +{ + struct list entry; /* entry in apartment stubmgr list (CS apt->cs) */ + struct list ifstubs; /* list of active ifstubs for the object (CS lock) */ + CRITICAL_SECTION lock; + APARTMENT *apt; /* owning apt (RO) */ + + ULONG extrefs; /* number of 'external' references (LOCK) */ + ULONG refs; /* internal reference count (CS apt->cs) */ + OID oid; /* apartment-scoped unique identifier (RO) */ + IUnknown *object; /* the object we are managing the stub for (RO) */ + ULONG next_ipid; /* currently unused (LOCK) */ +}; + +ULONG stub_manager_int_addref(struct stub_manager *This); +ULONG stub_manager_int_release(struct stub_manager *This); +struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object); +ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs); +ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs); +IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *iid); +struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal); +struct stub_manager *get_stub_manager(OXID oxid, OID oid); +struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object); + +IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid); + +void start_apartment_listener_thread(void); extern HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf); +void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); /* This function initialize the Running Object Table */ -HRESULT WINAPI RunningObjectTableImpl_Initialize(); +HRESULT WINAPI RunningObjectTableImpl_Initialize(void); /* This function uninitialize the Running Object Table */ -HRESULT WINAPI RunningObjectTableImpl_UnInitialize(); +HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void); /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id); +/* compobj.c */ +APARTMENT *COM_CreateApartment(DWORD model); +APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref); +DWORD COM_ApartmentAddRef(struct apartment *apt); +DWORD COM_ApartmentRelease(struct apartment *apt); + +/* this is what is stored in TEB->ReservedForOle */ +struct oletls +{ + struct apartment *apt; + IErrorInfo *errorinfo; /* see errorinfo.c */ + IUnknown *state; /* see CoSetState */ + DWORD inits; /* number of times CoInitializeEx called */ +}; + /* * Per-thread values are stored in the TEB on offset 0xF80, * see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm */ -static inline APARTMENT* COM_CurrentInfo(void) + +/* will create if necessary */ +static inline struct oletls *COM_CurrentInfo(void) { - APARTMENT* apt = NtCurrentTeb()->ReservedForOle; - return apt; -} -static inline APARTMENT* COM_CurrentApt(void) -{ - APARTMENT* apt = COM_CurrentInfo(); - if (apt && apt->parent) apt = apt->parent; - return apt; + if (!NtCurrentTeb()->ReservedForOle) + NtCurrentTeb()->ReservedForOle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct oletls)); + + return NtCurrentTeb()->ReservedForOle; } -/* compobj.c */ -APARTMENT* COM_CreateApartment(DWORD model); -HWND COM_GetApartmentWin(OXID oxid); +static inline APARTMENT* COM_CurrentApt(void) +{ + return COM_CurrentInfo()->apt; +} #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) diff --git a/reactos/lib/ole32/compositemoniker.c b/reactos/lib/ole32/compositemoniker.c index 839c8e89d48..94c5bb7c01b 100644 --- a/reactos/lib/ole32/compositemoniker.c +++ b/reactos/lib/ole32/compositemoniker.c @@ -445,7 +445,7 @@ HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* p IMoniker_Enum(iface,TRUE,&enumMk); - while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){ + while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)){ IMoniker_GetSizeMax(pmk,&ptmpSize); diff --git a/reactos/lib/ole32/datacache.c b/reactos/lib/ole32/datacache.c index 8caef4e4cf6..867ec85c54b 100644 --- a/reactos/lib/ole32/datacache.c +++ b/reactos/lib/ole32/datacache.c @@ -1132,8 +1132,7 @@ static HRESULT WINAPI DataCache_GetData( cleanup: - if (mfBits) - HeapFree(GetProcessHeap(), 0, mfBits); + HeapFree(GetProcessHeap(), 0, mfBits); if (pStream) IStream_Release(pStream); diff --git a/reactos/lib/ole32/defaulthandler.c b/reactos/lib/ole32/defaulthandler.c index 62af03a615c..14a06121d80 100644 --- a/reactos/lib/ole32/defaulthandler.c +++ b/reactos/lib/ole32/defaulthandler.c @@ -514,17 +514,10 @@ static void DefaultHandler_Destroy( /* * Free the strings idenfitying the object */ - if (ptrToDestroy->containerApp!=NULL) - { - HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerApp ); - ptrToDestroy->containerApp = NULL; - } - - if (ptrToDestroy->containerObj!=NULL) - { - HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerObj ); - ptrToDestroy->containerObj = NULL; - } + HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerApp ); + ptrToDestroy->containerApp = NULL; + HeapFree( GetProcessHeap(), 0, ptrToDestroy->containerObj ); + ptrToDestroy->containerObj = NULL; /* * Release our reference to the data cache. @@ -822,17 +815,10 @@ static HRESULT WINAPI DefaultHandler_SetHostNames( /* * Be sure to cleanup before re-assinging the strings. */ - if (this->containerApp!=NULL) - { - HeapFree( GetProcessHeap(), 0, this->containerApp ); - this->containerApp = NULL; - } - - if (this->containerObj!=NULL) - { - HeapFree( GetProcessHeap(), 0, this->containerObj ); - this->containerObj = NULL; - } + HeapFree( GetProcessHeap(), 0, this->containerApp ); + this->containerApp = NULL; + HeapFree( GetProcessHeap(), 0, this->containerObj ); + this->containerObj = NULL; /* * Copy the string supplied. diff --git a/reactos/lib/ole32/errorinfo.c b/reactos/lib/ole32/errorinfo.c index 4adae830c70..5c127347f3f 100644 --- a/reactos/lib/ole32/errorinfo.c +++ b/reactos/lib/ole32/errorinfo.c @@ -20,7 +20,7 @@ * NOTES: * * The errorinfo is a per-thread object. The reference is stored in the - * TEB at offset 0xf80 + * TEB at offset 0xf80. */ #include @@ -149,13 +149,13 @@ static ISupportErrorInfoVtbl ISupportErrorInfoImpl_VTable; converts a objectpointer to This */ #define _IErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtei))) -#define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset); +#define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset) #define _ICreateErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtcei))) -#define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset); +#define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset) #define _ISupportErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtsei))) -#define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset); +#define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset) /* converts This to a objectpointer @@ -227,15 +227,17 @@ static ULONG WINAPI IErrorInfoImpl_Release( IErrorInfo* iface) { _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); - TRACE("(%p)->(count=%lu)\n",This,This->ref); + ULONG ref = InterlockedDecrement(&This->ref); - if (!InterlockedDecrement(&This->ref)) + TRACE("(%p)->(count=%lu)\n",This,ref+1); + + if (!ref) { TRACE("-- destroying IErrorInfo(%p)\n",This); HeapFree(GetProcessHeap(),0,This); return 0; } - return This->ref; + return ref; } static HRESULT WINAPI IErrorInfoImpl_GetGUID( @@ -483,20 +485,20 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo) */ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) { - APARTMENT * apt = COM_CurrentInfo(); - - TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo); + TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->errorinfo); if(!pperrinfo) return E_INVALIDARG; - if (!apt || !apt->ErrorInfo) + + if (!COM_CurrentInfo()->errorinfo) { *pperrinfo = NULL; return S_FALSE; } - *pperrinfo = (IErrorInfo*)(apt->ErrorInfo); + *pperrinfo = COM_CurrentInfo()->errorinfo; + /* clear thread error state */ - apt->ErrorInfo = NULL; + COM_CurrentInfo()->errorinfo = NULL; return S_OK; } @@ -506,18 +508,16 @@ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo) { IErrorInfo * pei; - APARTMENT * apt = COM_CurrentInfo(); TRACE("(%ld, %p)\n", dwReserved, perrinfo); - if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED); - /* release old errorinfo */ - pei = (IErrorInfo*)apt->ErrorInfo; - if(pei) IErrorInfo_Release(pei); + pei = COM_CurrentInfo()->errorinfo; + if (pei) IErrorInfo_Release(pei); /* set to new value */ - apt->ErrorInfo = perrinfo; - if(perrinfo) IErrorInfo_AddRef(perrinfo); + COM_CurrentInfo()->errorinfo = perrinfo; + if (perrinfo) IErrorInfo_AddRef(perrinfo); + return S_OK; } diff --git a/reactos/lib/ole32/filemoniker.c b/reactos/lib/ole32/filemoniker.c index 182a2c67564..d9536989e8e 100644 --- a/reactos/lib/ole32/filemoniker.c +++ b/reactos/lib/ole32/filemoniker.c @@ -325,8 +325,7 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) return E_FAIL; } - if (This->filePathName!=NULL) - HeapFree(GetProcessHeap(),0,This->filePathName); + HeapFree(GetProcessHeap(),0,This->filePathName); This->filePathName=filePathW; @@ -540,9 +539,7 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This) { TRACE("(%p)\n",This); - if (This->filePathName!=NULL) - HeapFree(GetProcessHeap(),0,This->filePathName); - + HeapFree(GetProcessHeap(),0,This->filePathName); HeapFree(GetProcessHeap(),0,This); return S_OK; diff --git a/reactos/lib/ole32/ftmarshal.c b/reactos/lib/ole32/ftmarshal.c index 915ff3e0723..3c6a9d346a7 100644 --- a/reactos/lib/ole32/ftmarshal.c +++ b/reactos/lib/ole32/ftmarshal.c @@ -156,8 +156,6 @@ HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, vo hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize); IMarshal_Release (pMarshal); return hres; - - return S_OK; } HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv, diff --git a/reactos/lib/ole32/hglobalstream.c b/reactos/lib/ole32/hglobalstream.c index 13a9d612eeb..0fbeab48765 100644 --- a/reactos/lib/ole32/hglobalstream.c +++ b/reactos/lib/ole32/hglobalstream.c @@ -598,8 +598,9 @@ HRESULT WINAPI HGLOBALStreamImpl_Seek( * If the file pointer ends-up after the end of the stream, the next Write operation will * make the file larger. This is how it is documented. */ + if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart) return STG_E_INVALIDFUNCTION; + newPosition.QuadPart = RtlLargeIntegerAdd(newPosition.QuadPart, dlibMove.QuadPart); - if (newPosition.QuadPart < 0) return STG_E_INVALIDFUNCTION; if (plibNewPosition) *plibNewPosition = newPosition; This->currentPosition = newPosition; diff --git a/reactos/lib/ole32/ifs.c b/reactos/lib/ole32/ifs.c index 8af7ca5f56d..325f08444d1 100644 --- a/reactos/lib/ole32/ifs.c +++ b/reactos/lib/ole32/ifs.c @@ -394,10 +394,11 @@ static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface) { _MallocSpy *This = (_MallocSpy *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE ("(%p)->(count=%lu)\n", This, This->ref); + TRACE ("(%p)->(count=%lu)\n", This, ref - 1); - return ++(This->ref); + return ref; } /****************************************************************************** @@ -410,13 +411,14 @@ static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface) { _MallocSpy *This = (_MallocSpy *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - TRACE ("(%p)->(count=%lu)\n", This, This->ref); + TRACE ("(%p)->(count=%lu)\n", This, ref + 1); - if (!--(This->ref)) { + if (!ref) { /* our allocation list MUST be empty here */ } - return This->ref; + return ref; } static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest) diff --git a/reactos/lib/ole32/ifs.h b/reactos/lib/ole32/ifs.h index 55a6bc0fd9c..72a5c527219 100644 --- a/reactos/lib/ole32/ifs.h +++ b/reactos/lib/ole32/ifs.h @@ -55,7 +55,7 @@ typedef struct IMalloc16 *LPMALLOC16; /**********************************************************************/ -extern LPMALLOC16 IMalloc16_Constructor(); +extern LPMALLOC16 IMalloc16_Constructor(void); /**********************************************************************/ diff --git a/reactos/lib/ole32/itemmoniker.c b/reactos/lib/ole32/itemmoniker.c index be769ddbe44..4c1e4e3c8d1 100644 --- a/reactos/lib/ole32/itemmoniker.c +++ b/reactos/lib/ole32/itemmoniker.c @@ -415,12 +415,8 @@ HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This) { TRACE("(%p)\n",This); - if (This->itemName) - HeapFree(GetProcessHeap(),0,This->itemName); - - if (This->itemDelimiter) - HeapFree(GetProcessHeap(),0,This->itemDelimiter); - + HeapFree(GetProcessHeap(),0,This->itemName); + HeapFree(GetProcessHeap(),0,This->itemDelimiter); HeapFree(GetProcessHeap(),0,This); return S_OK; diff --git a/reactos/lib/ole32/marshal.c b/reactos/lib/ole32/marshal.c index 9c89a7d9b2c..2962d538255 100644 --- a/reactos/lib/ole32/marshal.c +++ b/reactos/lib/ole32/marshal.c @@ -1,7 +1,9 @@ /* * Marshalling library * - * Copyright 2002 Marcus Meissner + * Copyright 2002 Marcus Meissner + * Copyright 2004 Mike Hearn, for CodeWeavers + * Copyright 2004 Rob Shearman, for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,16 +35,13 @@ #include "winuser.h" #include "objbase.h" #include "ole2.h" -#include "ole2ver.h" #include "rpc.h" #include "winerror.h" #include "winreg.h" -#include "wownt32.h" #include "wtypes.h" #include "wine/unicode.h" -#include "wine/winbase16.h" + #include "compobj_private.h" -#include "ifs.h" #include "wine/debug.h" @@ -58,6 +57,13 @@ extern const CLSID CLSID_DfMarshal; * Process Identifier, Object IUnknown ptr, IID * * Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value! + * + * In Windows, a different triple is used: OXID (apt id), OID (stub + * manager id), IPID (interface ptr/stub id). + * + * OXIDs identify an apartment and are network scoped + * OIDs identify a stub manager and are apartment scoped + * IPIDs identify an interface stub and are apartment scoped */ inline static HRESULT @@ -75,121 +81,347 @@ typedef struct _wine_marshal_data { DWORD mshlflags; } wine_marshal_data; -typedef struct _mid2unknown { - wine_marshal_id mid; - LPUNKNOWN pUnk; -} mid2unknown; +IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid) +{ + IRpcStubBuffer *ret; + struct stub_manager *m; -typedef struct _mid2stub { - wine_marshal_id mid; - IRpcStubBuffer *stub; - LPUNKNOWN pUnkServer; - BOOL valid; -} mid2stub; + if (!(m = get_stub_manager(mid->oxid, mid->oid))) + { + WARN("unknown OID %s\n", wine_dbgstr_longlong(mid->oid)); + return NULL; + } -static mid2stub *stubs = NULL; -static int nrofstubs = 0; + ret = stub_manager_ipid_to_stubbuffer(m, &mid->ipid); -static mid2unknown *proxies = NULL; -static int nrofproxies = 0; + stub_manager_int_release(m); + return ret; +} -void MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid) { - int i; +/* creates a new stub manager and sets mid->oid when mid->oid == 0 */ +static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj, IRpcStubBuffer *stub, BOOL tablemarshal) +{ + struct stub_manager *manager = NULL; + struct ifstub *ifstub; - for (i=0;ioid of zero means create a new stub manager */ + + if (mid->oid && (manager = get_stub_manager(mid->oxid, mid->oid))) + { + TRACE("registering new ifstub on pre-existing manager\n"); + } + else + { + struct apartment *apt; - if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) { - stubs[i].valid = FALSE; - return; - } + TRACE("constructing new stub manager\n"); + + apt = COM_ApartmentFromOXID(mid->oxid, TRUE); + manager = new_stub_manager(apt, obj); + COM_ApartmentRelease(apt); + if (!manager) return E_OUTOFMEMORY; + + mid->oid = manager->oid; } - - return; -} -HRESULT -MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub) { - int i; - - for (i=0;iipid = ifstub->ipid; - if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) { - *pUnk = stubs[i].pUnkServer; - IUnknown_AddRef((*pUnk)); - return S_OK; - } - } - return E_FAIL; -} - -static HRESULT -MARSHAL_Register_Stub(wine_marshal_id *mid,LPUNKNOWN pUnk,IRpcStubBuffer *stub) { - LPUNKNOWN xPunk; - if (!MARSHAL_Find_Stub(mid,&xPunk)) { - FIXME("Already have entry for (%lx/%s)!\n",mid->objectid,debugstr_guid(&(mid->iid))); - return S_OK; - } - if (nrofstubs) - stubs=HeapReAlloc(GetProcessHeap(),0,stubs,sizeof(stubs[0])*(nrofstubs+1)); - else - stubs=HeapAlloc(GetProcessHeap(),0,sizeof(stubs[0])); - if (!stubs) return E_OUTOFMEMORY; - stubs[nrofstubs].stub = stub; - stubs[nrofstubs].pUnkServer = pUnk; - memcpy(&(stubs[nrofstubs].mid),mid,sizeof(*mid)); - stubs[nrofstubs].valid = TRUE; /* set to false when released by ReleaseMarshalData */ - nrofstubs++; + stub_manager_int_release(manager); return S_OK; } -HRESULT -MARSHAL_Disconnect_Proxies() { - int i; - TRACE("Disconnecting %d proxies\n", nrofproxies); - for (i = 0; i < nrofproxies; i++) - IRpcProxyBuffer_Disconnect((IRpcProxyBuffer*)proxies[i].pUnk); - +/* Client-side identity of the server object */ + +static void proxy_manager_destroy(struct proxy_manager * This); +static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found); + +static HRESULT WINAPI ClientIdentity_QueryInterface(IInternalUnknown * iface, REFIID riid, void ** ppv) +{ + struct proxy_manager * This = (struct proxy_manager *)iface; + HRESULT hr; + struct ifproxy * ifproxy; + + TRACE("%s\n", debugstr_guid(riid)); + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IInternalUnknown)) + { + *ppv = (void *)iface; + IInternalUnknown_AddRef(iface); + return S_OK; + } + + hr = proxy_manager_find_ifproxy(This, riid, &ifproxy); + if (hr == S_OK) + { + *ppv = ifproxy->iface; + IUnknown_AddRef((IUnknown *)*ppv); + return S_OK; + } + + FIXME("interface not found %s\n", debugstr_guid(riid)); + + /* FIXME: call IRemUnknown::RemQueryInterface */ + return E_NOINTERFACE; +} + +static ULONG WINAPI ClientIdentity_AddRef(IInternalUnknown * iface) +{ + struct proxy_manager * This = (struct proxy_manager *)iface; + TRACE("%p - before %ld\n", iface, This->refs); + return InterlockedIncrement(&This->refs); +} + +static ULONG WINAPI ClientIdentity_Release(IInternalUnknown * iface) +{ + struct proxy_manager * This = (struct proxy_manager *)iface; + ULONG refs = InterlockedDecrement(&This->refs); + TRACE("%p - after %ld\n", iface, refs); + if (!refs) + proxy_manager_destroy(This); + return refs; +} + +static HRESULT WINAPI ClientIdentity_QueryInternalInterface(IInternalUnknown * iface, REFIID riid, void ** ppv) +{ + FIXME("(%s, %p): stub!\n", debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static const IInternalUnknownVtbl ClientIdentity_Vtbl = +{ + ClientIdentity_QueryInterface, + ClientIdentity_AddRef, + ClientIdentity_Release, + ClientIdentity_QueryInternalInterface +}; + +static HRESULT ifproxy_get_public_ref(struct ifproxy * This) +{ + /* FIXME: call IRemUnknown::RemAddRef if necessary */ return S_OK; } -static HRESULT -MARSHAL_Register_Proxy(wine_marshal_id *mid,LPUNKNOWN punk) { - int i; +static HRESULT ifproxy_release_public_refs(struct ifproxy * This) +{ + /* FIXME: call IRemUnknown::RemRelease */ + return S_OK; +} - for (i=0;iproxy); +} + +static void ifproxy_destroy(struct ifproxy * This) +{ + /* release public references to this object so that the stub can know + * when to destroy itself */ + ifproxy_release_public_refs(This); + + list_remove(&This->entry); + + if (This->proxy) IRpcProxyBuffer_Release(This->proxy); + HeapFree(GetProcessHeap(), 0, This); +} + +static HRESULT proxy_manager_construct(APARTMENT * apt, OXID oxid, OID oid, IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager) +{ + struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) return E_OUTOFMEMORY; + + This->lpVtbl = &ClientIdentity_Vtbl; + + list_init(&This->entry); + list_init(&This->interfaces); + + InitializeCriticalSection(&This->cs); + + /* the apartment the object was unmarshaled into */ + This->parent = apt; + + /* the source apartment and id of the object */ + This->oxid = oxid; + This->oid = oid; + + This->refs = 0; /* will be incremented on creation of first proxy */ + + This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */ + + EnterCriticalSection(&apt->cs); + list_add_head(&apt->proxies, &This->entry); + LeaveCriticalSection(&apt->cs); + + *proxy_manager = This; + return S_OK; +} + +static HRESULT proxy_manager_create_ifproxy(struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs, struct ifproxy ** iif_out) +{ + HRESULT hr; + IPSFactoryBuffer * psfb; + struct ifproxy * ifproxy = HeapAlloc(GetProcessHeap(), 0, sizeof(*ifproxy)); + if (!ifproxy) return E_OUTOFMEMORY; + + list_init(&ifproxy->entry); + + ifproxy->ipid = ipid; + ifproxy->iid = *riid; + ifproxy->refs = cPublicRefs; + ifproxy->proxy = NULL; + + hr = get_facbuf_for_iid(riid, &psfb); + if (hr == S_OK) + { + /* important note: the outer unknown is set to the proxy manager. + * This ensures the COM identity rules are not violated, by having a + * one-to-one mapping of objects on the proxy side to objects on the + * stub side, no matter which interface you view the object through */ + hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown *)&This->lpVtbl, riid, + &ifproxy->proxy, &ifproxy->iface); + IPSFactoryBuffer_Release(psfb); + } + + if (hr == S_OK) + hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan); + + /* get at least one external reference to the object to keep it alive */ + if (hr == S_OK) + hr = ifproxy_get_public_ref(ifproxy); + + if (hr == S_OK) + { + EnterCriticalSection(&This->cs); + list_add_tail(&This->interfaces, &ifproxy->entry); + LeaveCriticalSection(&This->cs); + + *iif_out = ifproxy; } - if (nrofproxies) - proxies = HeapReAlloc(GetProcessHeap(),0,proxies,sizeof(proxies[0])*(nrofproxies+1)); else - proxies = HeapAlloc(GetProcessHeap(),0,sizeof(proxies[0])); - memcpy(&(proxies[nrofproxies].mid),mid,sizeof(*mid)); - proxies[nrofproxies].pUnk = punk; - nrofproxies++; - IUnknown_AddRef(punk); + ifproxy_destroy(ifproxy); + + return hr; +} + +static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found) +{ + HRESULT hr = E_NOINTERFACE; /* assume not found */ + struct list * cursor; + + EnterCriticalSection(&This->cs); + LIST_FOR_EACH(cursor, &This->interfaces) + { + struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry); + if (IsEqualIID(riid, &ifproxy->iid)) + { + *ifproxy_found = ifproxy; + hr = S_OK; + break; + } + } + LeaveCriticalSection(&This->cs); + + return hr; +} + +static void proxy_manager_disconnect(struct proxy_manager * This) +{ + struct list * cursor; + + EnterCriticalSection(&This->cs); + + LIST_FOR_EACH(cursor, &This->interfaces) + { + struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry); + ifproxy_disconnect(ifproxy); + } + + /* apartment is being destroyed so don't keep a pointer around to it */ + This->parent = NULL; + + LeaveCriticalSection(&This->cs); +} + +static void proxy_manager_destroy(struct proxy_manager * This) +{ + struct list * cursor; + + if (This->parent) + { + EnterCriticalSection(&This->parent->cs); + + /* remove ourself from the list of proxy objects in the apartment */ + LIST_FOR_EACH(cursor, &This->parent->proxies) + { + if (cursor == &This->entry) + { + list_remove(&This->entry); + break; + } + } + + LeaveCriticalSection(&This->parent->cs); + } + + /* destroy all of the interface proxies */ + while (!(cursor = list_head(&This->interfaces))) + { + struct ifproxy * ifproxy = LIST_ENTRY(cursor, struct ifproxy, entry); + ifproxy_destroy(ifproxy); + } + + IRpcChannelBuffer_Release(This->chan); + + DeleteCriticalSection(&This->cs); + + HeapFree(GetProcessHeap(), 0, This); +} + +static BOOL find_proxy_manager(APARTMENT * apt, OXID oxid, OID oid, struct proxy_manager ** proxy_found) +{ + BOOL found = FALSE; + struct list * cursor; + + EnterCriticalSection(&apt->cs); + LIST_FOR_EACH(cursor, &apt->proxies) + { + struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry); + if ((oxid == proxy->oxid) && (oid == proxy->oid)) + { + *proxy_found = proxy; + found = TRUE; + break; + } + } + LeaveCriticalSection(&apt->cs); + return found; +} + +HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt) +{ + struct list * cursor; + + EnterCriticalSection(&apt->cs); + LIST_FOR_EACH(cursor, &apt->proxies) + { + struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry); + proxy_manager_disconnect(proxy); + } + LeaveCriticalSection(&apt->cs); + return S_OK; } @@ -254,134 +486,155 @@ StdMarshalImpl_MarshalInterface( LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags ) { - wine_marshal_id mid; - wine_marshal_data md; - IUnknown *pUnk; - ULONG res; - HRESULT hres; - IRpcStubBuffer *stub; - IPSFactoryBuffer *psfacbuf; - + wine_marshal_id mid; + wine_marshal_data md; + IUnknown *pUnk; + ULONG res; + HRESULT hres; + IRpcStubBuffer *stubbuffer; + IPSFactoryBuffer *psfacbuf; + BOOL tablemarshal; + struct stub_manager *manager; + TRACE("(...,%s,...)\n",debugstr_guid(riid)); - IUnknown_QueryInterface((LPUNKNOWN)pv,&IID_IUnknown,(LPVOID*)&pUnk); - mid.processid = GetCurrentProcessId(); - mid.objectid = (DWORD)pUnk; /* FIXME */ - IUnknown_Release(pUnk); - memcpy(&mid.iid,riid,sizeof(mid.iid)); - md.dwDestContext = dwDestContext; - md.mshlflags = mshlflags; - hres = IStream_Write(pStm,&mid,sizeof(mid),&res); - if (hres) return hres; - hres = IStream_Write(pStm,&md,sizeof(md),&res); - if (hres) return hres; + start_apartment_listener_thread(); /* just to be sure we have one running. */ - if (SUCCEEDED(MARSHAL_Find_Stub_Buffer(&mid,&stub))) { - /* Find_Stub_Buffer gives us a ref but we want to keep it, as if we'd created a new one */ - TRACE("Found RpcStubBuffer %p\n", stub); - return S_OK; - } hres = get_facbuf_for_iid(riid,&psfacbuf); if (hres) return hres; - hres = IPSFactoryBuffer_CreateStub(psfacbuf,riid,pv,&stub); + hres = IPSFactoryBuffer_CreateStub(psfacbuf,riid,pv,&stubbuffer); IPSFactoryBuffer_Release(psfacbuf); if (hres) { - FIXME("Failed to create a stub for %s\n",debugstr_guid(riid)); + FIXME("Failed to create an RpcStubBuffer from PSFactory for %s\n",debugstr_guid(riid)); return hres; } - IUnknown_QueryInterface((LPUNKNOWN)pv,riid,(LPVOID*)&pUnk); - MARSHAL_Register_Stub(&mid,pUnk,stub); + + tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK)); + if (tablemarshal) FIXME("table marshalling unimplemented\n"); + + /* now fill out the MID */ + mid.oxid = COM_CurrentApt()->oxid; + + IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk); + + if ((manager = get_stub_manager_from_object(mid.oxid, pUnk))) + { + mid.oid = manager->oid; + stub_manager_int_release(manager); + } + else + { + mid.oid = 0; /* will be set by register_ifstub */ + } + + hres = register_ifstub(&mid, riid, pUnk, stubbuffer, tablemarshal); + IUnknown_Release(pUnk); + + if (hres) + { + FIXME("Failed to create ifstub, hres=0x%lx\n", hres); + return hres; + } + + hres = IStream_Write(pStm,&mid,sizeof(mid),&res); + if (hres) return hres; + + /* and then the marshal data */ + md.dwDestContext = dwDestContext; + md.mshlflags = mshlflags; + hres = IStream_Write(pStm,&md,sizeof(md),&res); + if (hres) return hres; + return S_OK; } static HRESULT WINAPI -StdMarshalImpl_UnmarshalInterface( - LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv -) { +StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) +{ + struct stub_manager *stubmgr; wine_marshal_id mid; wine_marshal_data md; ULONG res; HRESULT hres; - IPSFactoryBuffer *psfacbuf; - IRpcProxyBuffer *rpcproxy; IRpcChannelBuffer *chanbuf; + struct proxy_manager *proxy_manager; + APARTMENT *apt = COM_CurrentApt(); TRACE("(...,%s,....)\n",debugstr_guid(riid)); + + if (!apt) return CO_E_NOTINITIALIZED; + hres = IStream_Read(pStm,&mid,sizeof(mid),&res); if (hres) return hres; hres = IStream_Read(pStm,&md,sizeof(md),&res); if (hres) return hres; - if (SUCCEEDED(MARSHAL_Find_Stub(&mid,(LPUNKNOWN*)ppv))) { - FIXME("Calling back to ourselves for %s!\n",debugstr_guid(riid)); - return S_OK; - } - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_NULL)) { - /* should return proxy manager IUnknown object */ - FIXME("Special treatment required for IID of %s\n", debugstr_guid(riid)); - } - hres = get_facbuf_for_iid(riid,&psfacbuf); - if (hres) return hres; - hres = IPSFactoryBuffer_CreateProxy(psfacbuf,NULL,riid,&rpcproxy,ppv); - if (hres) { - FIXME("Failed to create a proxy for %s\n",debugstr_guid(riid)); - return hres; + + /* check if we're marshalling back to ourselves */ + /* FIXME: commented out until we can get the tests passing with it uncommented. */ + if (/*(apt->oxid == mid.oxid) &&*/ (stubmgr = get_stub_manager(mid.oxid, mid.oid))) + { + TRACE("Unmarshalling object marshalled in same apartment for iid %s, returning original object %p\n", debugstr_guid(riid), stubmgr->object); + + hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv); + if ((md.mshlflags & MSHLFLAGS_TABLESTRONG) || (md.mshlflags & MSHLFLAGS_TABLEWEAK)) + FIXME("table marshalling unimplemented\n"); + + /* unref the ifstub. FIXME: only do this on success? */ + stub_manager_ext_release(stubmgr, 1); + + stub_manager_int_release(stubmgr); + return hres; } - MARSHAL_Register_Proxy(&mid, (LPUNKNOWN) rpcproxy); - - hres = PIPE_GetNewPipeBuf(&mid,&chanbuf); - IPSFactoryBuffer_Release(psfacbuf); - if (hres) { - ERR("Failed to get an rpc channel buffer for %s\n",debugstr_guid(riid)); - } else { - /* Connect the channel buffer to the proxy and release the no longer - * needed proxy. - * NOTE: The proxy should have taken an extra reference because it also - * aggregates the object, so we can safely release our reference to it. */ - IRpcProxyBuffer_Connect(rpcproxy,chanbuf); - IRpcProxyBuffer_Release(rpcproxy); - /* IRpcProxyBuffer takes a reference on the channel buffer and - * we no longer need it, so release it */ - IRpcChannelBuffer_Release(chanbuf); + if (!find_proxy_manager(apt, mid.oxid, mid.oid, &proxy_manager)) + { + hres = PIPE_GetNewPipeBuf(&mid,&chanbuf); + if (hres == S_OK) + hres = proxy_manager_construct(apt, mid.oxid, mid.oid, chanbuf, &proxy_manager); } + + if (hres == S_OK) + { + struct ifproxy * ifproxy; + hres = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy); + if (hres == S_OK) + IUnknown_AddRef((IUnknown *)ifproxy->iface); + else if (hres == E_NOINTERFACE) + hres = proxy_manager_create_ifproxy(proxy_manager, mid.ipid, riid, 1, &ifproxy); + + if (hres == S_OK) + *ppv = ifproxy->iface; /* AddRef'd above */ + } + return hres; } static HRESULT WINAPI StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) { - wine_marshal_id mid; - ULONG res; - HRESULT hres; - IRpcStubBuffer *stub = NULL; - int i; + wine_marshal_id mid; + ULONG res; + HRESULT hres; + struct stub_manager *stubmgr; - hres = IStream_Read(pStm,&mid,sizeof(mid),&res); - if (hres) return hres; + TRACE("iface=%p, pStm=%p\n", iface, pStm); + + hres = IStream_Read(pStm,&mid,sizeof(mid),&res); + if (hres) return hres; - for (i=0; i < nrofstubs; i++) - { - if (!stubs[i].valid) continue; + if (!(stubmgr = get_stub_manager(mid.oxid, mid.oid))) + { + ERR("could not map MID to stub manager, oxid=%s, oid=%s\n", + wine_dbgstr_longlong(mid.oxid), wine_dbgstr_longlong(mid.oid)); + return RPC_E_INVALID_OBJREF; + } + + stub_manager_ext_release(stubmgr, 1); - if (MARSHAL_Compare_Mids(&mid, &(stubs[i].mid))) - { - stub = stubs[i].stub; - break; - } - } + stub_manager_int_release(stubmgr); - if (!stub) - { - FIXME("Could not map MID to stub??\n"); - return E_FAIL; - } - - res = IRpcStubBuffer_Release(stub); - stubs[i].valid = FALSE; - TRACE("stub refcount of %p is %ld\n", stub, res); - - return S_OK; + return S_OK; } static HRESULT WINAPI @@ -402,37 +655,57 @@ IMarshalVtbl stdmvtbl = { StdMarshalImpl_DisconnectObject }; +static HRESULT StdMarshalImpl_Construct(REFIID riid, void** ppvObject) +{ + StdMarshalImpl * pStdMarshal = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(StdMarshalImpl)); + if (!pStdMarshal) + return E_OUTOFMEMORY; + pStdMarshal->lpvtbl = &stdmvtbl; + pStdMarshal->ref = 0; + return IMarshal_QueryInterface((IMarshal*)pStdMarshal, riid, ppvObject); +} + /*********************************************************************** * CoGetStandardMarshal [OLE32.@] * - * When the COM library in the client process receives a marshalled - * interface pointer, it looks for a CLSID to be used in creating a proxy - * for the purposes of unmarshalling the packet. If the packet does not - * contain a CLSID for the proxy, COM calls CoGetStandardMarshal, passing a - * NULL pUnk value. - * This function creates a standard proxy in the client process and returns - * a pointer to that proxy's implementation of IMarshal. - * COM uses this pointer to call CoUnmarshalInterface to retrieve the pointer - * to the requested interface. + * Gets or creates a standard marshal object. + * + * PARAMS + * riid [I] Interface identifier of the pUnk object. + * pUnk [I] Optional. Object to get the marshal object for. + * dwDestContext [I] Destination. Used to enable or disable optimizations. + * pvDestContext [I] Reserved. Must be NULL. + * mshlflags [I] Flags affecting the marshaling process. + * ppMarshal [O] Address where marshal object will be stored. + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + * + * NOTES + * + * The function retrieves the IMarshal object associated with an object if + * that object is currently an active stub, otherwise a new marshal object is + * created. */ -HRESULT WINAPI -CoGetStandardMarshal( - REFIID riid,IUnknown *pUnk,DWORD dwDestContext,LPVOID pvDestContext, - DWORD mshlflags, LPMARSHAL *pMarshal -) { +HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, + DWORD dwDestContext, LPVOID pvDestContext, + DWORD mshlflags, LPMARSHAL *ppMarshal) +{ StdMarshalImpl *dm; if (pUnk == NULL) { FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n", - debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,pMarshal + debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal ); return E_FAIL; } TRACE("(%s,%p,%lx,%p,%lx,%p)\n", - debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,pMarshal + debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal ); - *pMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl)); - dm = (StdMarshalImpl*) *pMarshal; + *ppMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl)); + dm = (StdMarshalImpl*) *ppMarshal; if (!dm) return E_FAIL; dm->lpvtbl = &stdmvtbl; dm->ref = 1; @@ -444,205 +717,383 @@ CoGetStandardMarshal( return S_OK; } -/* Helper function for getting Marshaler */ -static HRESULT WINAPI -_GetMarshaller(REFIID riid, IUnknown *pUnk,DWORD dwDestContext, - void *pvDestContext, DWORD mshlFlags, LPMARSHAL *pMarshal -) { - HRESULT hres; +/*********************************************************************** + * get_marshaler [internal] + * + * Retrieves an IMarshal interface for an object. + */ +static HRESULT get_marshaler(REFIID riid, IUnknown *pUnk, DWORD dwDestContext, + void *pvDestContext, DWORD mshlFlags, + LPMARSHAL *pMarshal) +{ + HRESULT hr; - if (!pUnk) - return E_POINTER; - hres = IUnknown_QueryInterface(pUnk,&IID_IMarshal,(LPVOID*)pMarshal); - if (hres) - hres = CoGetStandardMarshal(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pMarshal); - return hres; + if (!pUnk) + return E_POINTER; + hr = IUnknown_QueryInterface(pUnk, &IID_IMarshal, (LPVOID*)pMarshal); + if (hr) + hr = CoGetStandardMarshal(riid, pUnk, dwDestContext, pvDestContext, + mshlFlags, pMarshal); + return hr; +} + +/*********************************************************************** + * get_unmarshaler_from_stream [internal] + * + * Creates an IMarshal* object according to the data marshaled to the stream. + * The function leaves the stream pointer at the start of the data written + * to the stream by the IMarshal* object. + */ +static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal) +{ + HRESULT hr; + ULONG res; + OBJREF objref; + + /* read common OBJREF header */ + hr = IStream_Read(stream, &objref, FIELD_OFFSET(OBJREF, u_objref), &res); + if (hr || (res != FIELD_OFFSET(OBJREF, u_objref))) + { + ERR("Failed to read common OBJREF header, 0x%08lx\n", hr); + return STG_E_READFAULT; + } + + /* sanity check on header */ + if (objref.signature != OBJREF_SIGNATURE) + { + ERR("Bad OBJREF signature 0x%08lx\n", objref.signature); + return RPC_E_INVALID_OBJREF; + } + + /* FIXME: handler marshaling */ + if (objref.flags & OBJREF_STANDARD) + { + TRACE("Using standard unmarshaling\n"); + hr = StdMarshalImpl_Construct(&IID_IMarshal, (LPVOID*)marshal); + } + else if (objref.flags & OBJREF_CUSTOM) + { + ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - + FIELD_OFFSET(OBJREF, u_objref.u_custom); + TRACE("Using custom unmarshaling\n"); + /* read constant sized OR_CUSTOM data from stream */ + hr = IStream_Read(stream, &objref.u_objref.u_custom, + custom_header_size, &res); + if (hr || (res != custom_header_size)) + { + ERR("Failed to read OR_CUSTOM header, 0x%08lx\n", hr); + return STG_E_READFAULT; + } + /* now create the marshaler specified in the stream */ + hr = CoCreateInstance(&objref.u_objref.u_custom.clsid, NULL, + CLSCTX_INPROC_SERVER, &IID_IMarshal, + (LPVOID*)marshal); + } + else + { + FIXME("Invalid or unimplemented marshaling type specified: %lx\n", + objref.flags); + return RPC_E_INVALID_OBJREF; + } + + if (hr) + ERR("Failed to create marshal, 0x%08lx\n", hr); + + return hr; } /*********************************************************************** * CoGetMarshalSizeMax [OLE32.@] + * + * Gets the maximum amount of data that will be needed by a marshal. + * + * PARAMS + * pulSize [O] Address where maximum marshal size will be stored. + * riid [I] Identifier of the interface to marshal. + * pUnk [I] Pointer to the object to marshal. + * dwDestContext [I] Destination. Used to enable or disable optimizations. + * pvDestContext [I] Reserved. Must be NULL. + * mshlFlags [I] Flags that affect the marshaling. See CoMarshalInterface(). + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + * + * SEE ALSO + * CoMarshalInterface(). */ -HRESULT WINAPI -CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk, - DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags -) { - HRESULT hres; - LPMARSHAL pMarshal; +HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk, + DWORD dwDestContext, void *pvDestContext, + DWORD mshlFlags) +{ + HRESULT hr; + LPMARSHAL pMarshal; + CLSID marshaler_clsid; - hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,&pMarshal); - if (hres) - return hres; - hres = IMarshal_GetMarshalSizeMax(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pulSize); - *pulSize += sizeof(wine_marshal_id)+sizeof(wine_marshal_data)+sizeof(CLSID); - IMarshal_Release(pMarshal); - return hres; + hr = get_marshaler(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal); + if (hr) + return hr; + + hr = IMarshal_GetUnmarshalClass(pMarshal, riid, pUnk, dwDestContext, + pvDestContext, mshlFlags, &marshaler_clsid); + if (hr) + { + ERR("IMarshal::GetUnmarshalClass failed, 0x%08lx\n", hr); + IMarshal_Release(pMarshal); + return hr; + } + + hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext, + pvDestContext, mshlFlags, pulSize); + /* add on the size of the common header */ + *pulSize += FIELD_OFFSET(OBJREF, u_objref); + + /* if custom marshaling, add on size of custom header */ + if (!IsEqualCLSID(&marshaler_clsid, &CLSID_DfMarshal)) + *pulSize += FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - + FIELD_OFFSET(OBJREF, u_objref.u_custom); + + IMarshal_Release(pMarshal); + return hr; } /*********************************************************************** * CoMarshalInterface [OLE32.@] + * + * Marshals an interface into a stream so that the object can then be + * unmarshaled from another COM apartment and used remotely. + * + * PARAMS + * pStream [I] Stream the object will be marshaled into. + * riid [I] Identifier of the interface to marshal. + * pUnk [I] Pointer to the object to marshal. + * dwDestContext [I] Destination. Used to enable or disable optimizations. + * pvDestContext [I] Reserved. Must be NULL. + * mshlFlags [I] Flags that affect the marshaling. See notes. + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + * + * NOTES + * + * The mshlFlags parameter can take one or more of the following flags: + *| MSHLFLAGS_NORMAL - Unmarshal once, releases stub on last proxy release. + *| MSHLFLAGS_TABLESTRONG - Unmarshal many, release when CoReleaseMarshalData() called. + *| MSHLFLAGS_TABLEWEAK - Unmarshal many, releases stub on last proxy release. + *| MSHLFLAGS_NOPING - No automatic garbage collection (and so reduces network traffic). + * + * If a marshaled object is not unmarshaled, then CoReleaseMarshalData() must + * be called in order to release the resources used in the marshaling. + * + * SEE ALSO + * CoUnmarshalInterface(), CoReleaseMarshalData(). */ -HRESULT WINAPI -CoMarshalInterface( IStream *pStm, REFIID riid, IUnknown *pUnk, - DWORD dwDestContext, void *pvDestContext, DWORD mshlflags -) { - HRESULT hres; - LPMARSHAL pMarshal; - CLSID xclsid; - ULONG writeres; - wine_marshal_id mid; - wine_marshal_data md; - ULONG res; - IUnknown *pUnknown; +HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, + DWORD dwDestContext, void *pvDestContext, + DWORD mshlFlags) +{ + HRESULT hr; + CLSID marshaler_clsid; + OBJREF objref; + IStream * pMarshalStream = NULL; + LPMARSHAL pMarshal; - TRACE("(%p, %s, %p, %lx, %p, %lx)\n", - pStm,debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags - ); + TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStream, debugstr_guid(riid), pUnk, + dwDestContext, pvDestContext, mshlFlags); - if (pUnk == NULL) - return E_INVALIDARG; + if (pUnk == NULL) + return E_INVALIDARG; - STUBMGR_Start(); /* Just to be sure we have one running. */ - mid.processid = GetCurrentProcessId(); - IUnknown_QueryInterface(pUnk,&IID_IUnknown,(LPVOID*)&pUnknown); - mid.objectid = (DWORD)pUnknown; - IUnknown_Release(pUnknown); - memcpy(&mid.iid,riid,sizeof(mid.iid)); - md.dwDestContext = dwDestContext; - md.mshlflags = mshlflags; - hres = IStream_Write(pStm,&mid,sizeof(mid),&res); - if (hres) return hres; - hres = IStream_Write(pStm,&md,sizeof(md),&res); - if (hres) return hres; - hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlflags,&pMarshal); - if (hres) { - FIXME("Failed to get marshaller, %lx?\n",hres); - return hres; - } - hres = IMarshal_GetUnmarshalClass(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlflags,&xclsid); - if (hres) { - FIXME("IMarshal:GetUnmarshalClass failed, %lx\n",hres); - goto release_marshal; - } - hres = IStream_Write(pStm,&xclsid,sizeof(xclsid),&writeres); - if (hres) { - FIXME("Stream write failed, %lx\n",hres); - goto release_marshal; - } + objref.signature = OBJREF_SIGNATURE; + objref.iid = *riid; - TRACE("Calling IMarshal::MarshalInterace\n"); - hres = IMarshal_MarshalInterface(pMarshal,pStm,riid,pUnk,dwDestContext,pvDestContext,mshlflags); - - if (hres) { - if (IsEqualGUID(riid,&IID_IOleObject)) { - ERR("WINE currently cannot marshal IOleObject interfaces. This means you cannot embed/link OLE objects between applications.\n"); - } else { - FIXME("Failed to marshal the interface %s, %lx?\n",debugstr_guid(riid),hres); + /* get the marshaler for the specified interface */ + hr = get_marshaler(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal); + if (hr) + { + ERR("Failed to get marshaller, 0x%08lx\n", hr); + return hr; } - } -release_marshal: - IMarshal_Release(pMarshal); - return hres; -} + hr = IMarshal_GetUnmarshalClass(pMarshal, riid, pUnk, dwDestContext, + pvDestContext, mshlFlags, &marshaler_clsid); + if (hr) + { + ERR("IMarshal::GetUnmarshalClass failed, 0x%08lx\n", hr); + goto cleanup; + } + + /* FIXME: implement handler marshaling too */ + if (IsEqualCLSID(&marshaler_clsid, &CLSID_DfMarshal)) + { + TRACE("Using standard marshaling\n"); + objref.flags = OBJREF_STANDARD; + pMarshalStream = pStream; + } + else + { + TRACE("Using custom marshaling\n"); + objref.flags = OBJREF_CUSTOM; + /* we do custom marshaling into a memory stream so that we know what + * size to write into the OR_CUSTOM header */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &pMarshalStream); + if (hr) + { + ERR("CreateStreamOnHGLOBAL failed with 0x%08lx\n", hr); + goto cleanup; + } + } + + /* write the common OBJREF header to the stream */ + hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL); + if (hr) + { + ERR("Failed to write OBJREF header to stream, 0x%08lx\n", hr); + goto cleanup; + } + + TRACE("Calling IMarshal::MarshalInterace\n"); + /* call helper object to do the actual marshaling */ + hr = IMarshal_MarshalInterface(pMarshal, pMarshalStream, riid, pUnk, dwDestContext, + pvDestContext, mshlFlags); + + if (hr) + { + ERR("Failed to marshal the interface %s, %lx\n", debugstr_guid(riid), hr); + goto cleanup; + } + + if (objref.flags & OBJREF_CUSTOM) + { + ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - + FIELD_OFFSET(OBJREF, u_objref.u_custom); + HGLOBAL hGlobal; + LPVOID data; + hr = GetHGlobalFromStream(pMarshalStream, &hGlobal); + if (hr) + { + ERR("Couldn't get HGLOBAL from stream\n"); + hr = E_UNEXPECTED; + goto cleanup; + } + objref.u_objref.u_custom.cbExtension = 0; + objref.u_objref.u_custom.size = GlobalSize(hGlobal); + /* write constant sized OR_CUSTOM data into stream */ + hr = IStream_Write(pStream, &objref.u_objref.u_custom, + custom_header_size, NULL); + if (hr) + { + ERR("Failed to write OR_CUSTOM header to stream with 0x%08lx\n", hr); + goto cleanup; + } + + data = GlobalLock(hGlobal); + if (!data) + { + ERR("GlobalLock failed\n"); + hr = E_UNEXPECTED; + goto cleanup; + } + /* write custom marshal data */ + hr = IStream_Write(pStream, data, objref.u_objref.u_custom.size, NULL); + if (hr) + { + ERR("Failed to write custom marshal data with 0x%08lx\n", hr); + goto cleanup; + } + GlobalUnlock(hGlobal); + } + +cleanup: + if (pMarshalStream && (objref.flags & OBJREF_CUSTOM)) + IStream_Release(pMarshalStream); + IMarshal_Release(pMarshal); + return hr; +} /*********************************************************************** * CoUnmarshalInterface [OLE32.@] + * + * Unmarshals an object from a stream by creating a proxy to the remote + * object, if necessary. + * + * PARAMS + * + * pStream [I] Stream containing the marshaled object. + * riid [I] Interface identifier of the object to create a proxy to. + * ppv [O] Address where proxy will be stored. + * + * RETURNS + * + * Success: S_OK. + * Failure: HRESULT code. + * + * SEE ALSO + * CoMarshalInterface(). */ -HRESULT WINAPI -CoUnmarshalInterface(IStream *pStm, REFIID riid, LPVOID *ppv) { - HRESULT hres; - wine_marshal_id mid; - wine_marshal_data md; - ULONG res; - LPMARSHAL pMarshal; - LPUNKNOWN pUnk; - CLSID xclsid; +HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv) +{ + HRESULT hr; + LPMARSHAL pMarshal; - TRACE("(%p,%s,%p)\n",pStm,debugstr_guid(riid),ppv); + TRACE("(%p, %s, %p)\n", pStream, debugstr_guid(riid), ppv); - hres = IStream_Read(pStm,&mid,sizeof(mid),&res); - if (hres) { - FIXME("Stream read 1 failed, %lx, (%ld of %d)\n",hres,res,sizeof(mid)); - return hres; - } - hres = IStream_Read(pStm,&md,sizeof(md),&res); - if (hres) { - FIXME("Stream read 2 failed, %lx, (%ld of %d)\n",hres,res,sizeof(md)); - return hres; - } - hres = IStream_Read(pStm,&xclsid,sizeof(xclsid),&res); - if (hres) { - FIXME("Stream read 3 failed, %lx, (%ld of %d)\n",hres,res,sizeof(xclsid)); - return hres; - } - hres=CoCreateInstance(&xclsid,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,&IID_IMarshal,(void**)&pUnk); - if (hres) { - FIXME("Failed to create instance of unmarshaller %s.\n",debugstr_guid(&xclsid)); - return hres; - } - hres = _GetMarshaller(riid,pUnk,md.dwDestContext,NULL,md.mshlflags,&pMarshal); - if (hres) { - FIXME("Failed to get unmarshaller, %lx?\n",hres); - return hres; - } - hres = IMarshal_UnmarshalInterface(pMarshal,pStm,riid,ppv); - if (hres) { - FIXME("Failed to Unmarshal the interface, %lx?\n",hres); - goto release_marshal; - } -release_marshal: - IMarshal_Release(pMarshal); - return hres; + hr = get_unmarshaler_from_stream(pStream, &pMarshal); + if (hr != S_OK) + return hr; + + /* call the helper object to do the actual unmarshaling */ + hr = IMarshal_UnmarshalInterface(pMarshal, pStream, riid, ppv); + if (hr) + ERR("IMarshal::UnmarshalInterface failed, 0x%08lx\n", hr); + + IMarshal_Release(pMarshal); + return hr; } /*********************************************************************** * CoReleaseMarshalData [OLE32.@] + * + * Releases resources associated with an object that has been marshaled into + * a stream. + * + * PARAMS + * + * pStream [I] The stream that the object has been marshaled into. + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT error code. + * + * NOTES + * + * Call this function to release resources associated with a normal or + * table-weak marshal that will not be unmarshaled, and all table-strong + * marshals when they are no longer needed. + * + * SEE ALSO + * CoMarshalInterface(), CoUnmarshalInterface(). */ -HRESULT WINAPI -CoReleaseMarshalData(IStream *pStm) { - HRESULT hres; - wine_marshal_id mid; - wine_marshal_data md; - ULONG res; - LPMARSHAL pMarshal; - LPUNKNOWN pUnk; - CLSID xclsid; +HRESULT WINAPI CoReleaseMarshalData(IStream *pStream) +{ + HRESULT hr; + LPMARSHAL pMarshal; - TRACE("(%p)\n",pStm); + TRACE("(%p)\n", pStream); - hres = IStream_Read(pStm,&mid,sizeof(mid),&res); - if (hres) { - FIXME("Stream read 1 failed, %lx, (%ld of %d)\n",hres,res,sizeof(mid)); - return hres; - } - hres = IStream_Read(pStm,&md,sizeof(md),&res); - if (hres) { - FIXME("Stream read 2 failed, %lx, (%ld of %d)\n",hres,res,sizeof(md)); - return hres; - } - hres = IStream_Read(pStm,&xclsid,sizeof(xclsid),&res); - if (hres) { - FIXME("Stream read 3 failed, %lx, (%ld of %d)\n",hres,res,sizeof(xclsid)); - return hres; - } - hres=CoCreateInstance(&xclsid,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,&IID_IMarshal,(void**)(char*)&pUnk); - if (hres) { - FIXME("Failed to create instance of unmarshaller %s.\n",debugstr_guid(&xclsid)); - return hres; - } - hres = IUnknown_QueryInterface(pUnk,&IID_IMarshal,(LPVOID*)(char*)&pMarshal); - if (hres) { - FIXME("Failed to get IMarshal iface, %lx?\n",hres); - return hres; - } - hres = IMarshal_ReleaseMarshalData(pMarshal,pStm); - if (hres) { - FIXME("Failed to releasemarshaldata the interface, %lx?\n",hres); - } - IMarshal_Release(pMarshal); - IUnknown_Release(pUnk); - return hres; + hr = get_unmarshaler_from_stream(pStream, &pMarshal); + if (hr != S_OK) + return hr; + + /* call the helper object to do the releasing of marshal data */ + hr = IMarshal_ReleaseMarshalData(pMarshal, pStream); + if (hr) + ERR("IMarshal::ReleaseMarshalData failed with error 0x%08lx\n", hr); + + IMarshal_Release(pMarshal); + return hr; } @@ -660,12 +1111,11 @@ CoReleaseMarshalData(IStream *pStm) { * Success: S_OK * Failure: E_OUTOFMEMORY and other COM error codes * - * SEE + * SEE ALSO * CoMarshalInterface(), CoUnmarshalInterface() and CoGetInterfaceAndReleaseStream() */ -HRESULT WINAPI -CoMarshalInterThreadInterfaceInStream( - REFIID riid, LPUNKNOWN pUnk, LPSTREAM * ppStm) +HRESULT WINAPI CoMarshalInterThreadInterfaceInStream( + REFIID riid, LPUNKNOWN pUnk, LPSTREAM * ppStm) { ULARGE_INTEGER xpos; LARGE_INTEGER seekto; @@ -698,11 +1148,11 @@ CoMarshalInterThreadInterfaceInStream( * Success: S_OK * Failure: A COM error code * - * SEE + * SEE ALSO * CoMarshalInterThreadInterfaceInStream() and CoUnmarshalInteface() */ -HRESULT WINAPI -CoGetInterfaceAndReleaseStream(LPSTREAM pStm,REFIID riid, LPVOID *ppv) +HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID riid, + LPVOID *ppv) { HRESULT hres; @@ -713,55 +1163,58 @@ CoGetInterfaceAndReleaseStream(LPSTREAM pStm,REFIID riid, LPVOID *ppv) return hres; } -static HRESULT WINAPI -SMCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) { - *ppv = NULL; - if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IClassFactory)) { - *ppv = (LPVOID)iface; - return S_OK; - } - return E_NOINTERFACE; +static HRESULT WINAPI StdMarshalCF_QueryInterface(LPCLASSFACTORY iface, + REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) + { + *ppv = (LPVOID)iface; + return S_OK; + } + return E_NOINTERFACE; } -static ULONG WINAPI SMCF_AddRef(LPCLASSFACTORY iface) { return 2; } -static ULONG WINAPI SMCF_Release(LPCLASSFACTORY iface) { return 1; } -static HRESULT WINAPI -SMCF_CreateInstance( - LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv -) { - if (IsEqualIID(riid,&IID_IMarshal)) { - StdMarshalImpl *dm; - dm=(StdMarshalImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl)); - if (!dm) - return E_FAIL; - dm->lpvtbl = &stdmvtbl; - dm->ref = 1; - *ppv = (LPVOID)dm; - return S_OK; - } +static ULONG WINAPI StdMarshalCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; /* non-heap based object */ +} + +static ULONG WINAPI StdMarshalCF_Release(LPCLASSFACTORY iface) +{ + return 1; /* non-heap based object */ +} + +static HRESULT WINAPI StdMarshalCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) +{ + if (IsEqualIID(riid,&IID_IMarshal)) + return StdMarshalImpl_Construct(riid, ppv); + FIXME("(%s), not supported.\n",debugstr_guid(riid)); return E_NOINTERFACE; } -static HRESULT WINAPI -SMCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) { +static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ FIXME("(%d), stub!\n",fLock); return S_OK; } -static IClassFactoryVtbl dfmarshalcfvtbl = { - SMCF_QueryInterface, - SMCF_AddRef, - SMCF_Release, - SMCF_CreateInstance, - SMCF_LockServer +static IClassFactoryVtbl StdMarshalCFVtbl = +{ + StdMarshalCF_QueryInterface, + StdMarshalCF_AddRef, + StdMarshalCF_Release, + StdMarshalCF_CreateInstance, + StdMarshalCF_LockServer }; -static IClassFactoryVtbl *pdfmarshalcfvtbl = &dfmarshalcfvtbl; +static IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl; -HRESULT -MARSHAL_GetStandardMarshalCF(LPVOID *ppv) { - *ppv = &pdfmarshalcfvtbl; - return S_OK; +HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv) +{ + *ppv = &StdMarshalCF; + return S_OK; } /*********************************************************************** @@ -770,18 +1223,17 @@ MARSHAL_GetStandardMarshalCF(LPVOID *ppv) { * Marshals an HRESULT value into a stream. * * PARAMS - * pStm [I] Stream that hresult will be marshaled into. - * hresult [I] HRESULT to be marshaled. + * pStm [I] Stream that hresult will be marshalled into. + * hresult [I] HRESULT to be marshalled. * * RETURNS * Success: S_OK * Failure: A COM error code * - * SEE + * SEE ALSO * CoUnmarshalHresult(). */ -HRESULT WINAPI -CoMarshalHresult(LPSTREAM pStm, HRESULT hresult) +HRESULT WINAPI CoMarshalHresult(LPSTREAM pStm, HRESULT hresult) { return IStream_Write(pStm, &hresult, sizeof(hresult), NULL); } @@ -792,18 +1244,17 @@ CoMarshalHresult(LPSTREAM pStm, HRESULT hresult) * Unmarshals an HRESULT value from a stream. * * PARAMS - * pStm [I] Stream that hresult will be unmarshaled from. - * phresult [I] Pointer to HRESULT where the value will be unmarshaled to. + * pStm [I] Stream that hresult will be unmarshalled from. + * phresult [I] Pointer to HRESULT where the value will be unmarshalled to. * * RETURNS * Success: S_OK * Failure: A COM error code * - * SEE + * SEE ALSO * CoMarshalHresult(). */ -HRESULT WINAPI -CoUnmarshalHresult(LPSTREAM pStm, HRESULT * phresult) +HRESULT WINAPI CoUnmarshalHresult(LPSTREAM pStm, HRESULT * phresult) { return IStream_Read(pStm, phresult, sizeof(*phresult), NULL); } diff --git a/reactos/lib/ole32/memlockbytes.c b/reactos/lib/ole32/memlockbytes.c index 8bb10ae00dc..1f74c5367c4 100644 --- a/reactos/lib/ole32/memlockbytes.c +++ b/reactos/lib/ole32/memlockbytes.c @@ -32,13 +32,10 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "wine/winbase16.h" #include "objbase.h" #include "ole2.h" #include "winerror.h" -#include "ifs.h" - #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); diff --git a/reactos/lib/ole32/moniker.c b/reactos/lib/ole32/moniker.c index b114c59854d..f0fcdd5550d 100644 --- a/reactos/lib/ole32/moniker.c +++ b/reactos/lib/ole32/moniker.c @@ -86,9 +86,9 @@ static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime); static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker); /* Local functions*/ -HRESULT WINAPI RunningObjectTableImpl_Initialize(); -HRESULT WINAPI RunningObjectTableImpl_UnInitialize(); -HRESULT WINAPI RunningObjectTableImpl_Destroy(); +HRESULT WINAPI RunningObjectTableImpl_Initialize(void); +HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void); +HRESULT WINAPI RunningObjectTableImpl_Destroy(void); HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx); /* Virtual function table for the IRunningObjectTable class. */ diff --git a/reactos/lib/ole32/ole2.c b/reactos/lib/ole32/ole2.c index 515752327df..2a428123d62 100644 --- a/reactos/lib/ole32/ole2.c +++ b/reactos/lib/ole32/ole2.c @@ -129,8 +129,8 @@ static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue); /****************************************************************************** * These are the prototypes of the utility methods used to manage a shared menu */ -static void OLEMenu_Initialize(); -static void OLEMenu_UnInitialize(); +static void OLEMenu_Initialize(void); +static void OLEMenu_UnInitialize(void); BOOL OLEMenu_InstallHooks( DWORD tid ); BOOL OLEMenu_UnInstallHooks( DWORD tid ); OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid ); @@ -142,14 +142,14 @@ LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam); /****************************************************************************** * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c) */ -void OLEClipbrd_UnInitialize(); -void OLEClipbrd_Initialize(); +void OLEClipbrd_UnInitialize(void); +void OLEClipbrd_Initialize(void); /****************************************************************************** * These are the prototypes of the utility methods used for OLE Drag n Drop */ -static void OLEDD_Initialize(); -static void OLEDD_UnInitialize(); +static void OLEDD_Initialize(void); +static void OLEDD_UnInitialize(void); static void OLEDD_InsertDropTarget( DropTargetNode* nodeToAdd); static DropTargetNode* OLEDD_ExtractDropTarget( @@ -169,7 +169,7 @@ static void OLEDD_TrackStateChange( TrackerWindowInfo* trackerInfo, POINT mousePos, DWORD keyState); -static DWORD OLEDD_GetButtonState(); +static DWORD OLEDD_GetButtonState(void); /****************************************************************************** @@ -985,8 +985,7 @@ BOOL OLEMenu_UnInstallHooks( DWORD tid ) CLEANUP: /* Release the hook table entry */ - if (pHookItem) - HeapFree(pHookItem->hHeap, 0, pHookItem ); + HeapFree(pHookItem->hHeap, 0, pHookItem ); return FALSE; } @@ -1602,7 +1601,7 @@ static void OLEDD_Initialize() ZeroMemory (&wndClass, sizeof(WNDCLASSA)); wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc; + wndClass.lpfnWndProc = OLEDD_DragTrackerWindowProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = sizeof(TrackerWindowInfo*); wndClass.hCursor = 0; diff --git a/reactos/lib/ole32/ole32.xml b/reactos/lib/ole32/ole32.xml index 839df99d164..b534d0d341f 100644 --- a/reactos/lib/ole32/ole32.xml +++ b/reactos/lib/ole32/ole32.xml @@ -46,6 +46,7 @@ stg_bigblockfile.c stg_stream.c storage32.c + stubmanager.c ole32res.rc ole32.spec diff --git a/reactos/lib/ole32/oleobj.c b/reactos/lib/ole32/oleobj.c index e3bbe30db71..e83c59268c5 100644 --- a/reactos/lib/ole32/oleobj.c +++ b/reactos/lib/ole32/oleobj.c @@ -50,7 +50,7 @@ typedef struct OleAdviseHolderImpl } OleAdviseHolderImpl; -static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(); +static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void); static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy); static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*); static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER); @@ -181,8 +181,11 @@ static ULONG WINAPI OleAdviseHolderImpl_AddRef( LPOLEADVISEHOLDER iface) { OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface; - TRACE("(%p)->(ref=%ld)\n", This, This->ref); - return ++(This->ref); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(ref=%ld)\n", This, ref - 1); + + return ref; } /****************************************************************************** @@ -377,7 +380,7 @@ typedef struct DataAdviseHolder /************************************************************************** * DataAdviseHolder method prototypes */ -static IDataAdviseHolder* DataAdviseHolder_Constructor(); +static IDataAdviseHolder* DataAdviseHolder_Constructor(void); static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy); static HRESULT WINAPI DataAdviseHolder_QueryInterface( IDataAdviseHolder* iface, diff --git a/reactos/lib/ole32/oleproxy.c b/reactos/lib/ole32/oleproxy.c index c38dc8feec9..5532988d533 100644 --- a/reactos/lib/ole32/oleproxy.c +++ b/reactos/lib/ole32/oleproxy.c @@ -271,6 +271,7 @@ typedef struct _CFProxy { DWORD ref; IRpcChannelBuffer *chanbuf; + IUnknown *outer_unknown; } CFProxy; static HRESULT WINAPI IRpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) { @@ -317,6 +318,8 @@ static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) { static HRESULT WINAPI CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) { + ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface); + if (This->outer_unknown) return IUnknown_QueryInterface(This->outer_unknown, riid, ppv); *ppv = NULL; if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) { *ppv = (LPVOID)iface; @@ -331,15 +334,22 @@ CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) { static ULONG WINAPI CFProxy_AddRef(LPCLASSFACTORY iface) { ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface); + if (This->outer_unknown) return IUnknown_AddRef(This->outer_unknown); return InterlockedIncrement(&This->ref); } static ULONG WINAPI CFProxy_Release(LPCLASSFACTORY iface) { ULONG ref; ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface); - - ref = InterlockedDecrement(&This->ref); - if (!ref) HeapFree(GetProcessHeap(),0,This); + if (This->outer_unknown) + ref = IUnknown_Release(This->outer_unknown); + else + ref = InterlockedDecrement(&This->ref); + + if (!ref) { + if (This->chanbuf) IRpcChannelBuffer_Release(This->chanbuf); + HeapFree(GetProcessHeap(),0,This); + } return ref; } @@ -425,7 +435,7 @@ static IClassFactoryVtbl cfproxyvt = { }; static HRESULT -CFProxy_Construct(LPVOID *ppv,LPVOID *ppProxy) { +CFProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) { CFProxy *cf; cf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFProxy)); @@ -434,10 +444,13 @@ CFProxy_Construct(LPVOID *ppv,LPVOID *ppProxy) { cf->lpvtbl_cf = &cfproxyvt; cf->lpvtbl_proxy = &pspbvtbl; - /* 1 reference for the proxy and 1 for the object */ - cf->ref = 2; + /* 1 reference for the proxy... */ + cf->ref = 1; + cf->outer_unknown = pUnkOuter; *ppv = &(cf->lpvtbl_cf); *ppProxy = &(cf->lpvtbl_proxy); + /* ...and 1 for the object */ + IUnknown_AddRef((IUnknown *)*ppv); return S_OK; } @@ -465,7 +478,7 @@ PSFacBuf_CreateProxy( if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid) ) - return CFProxy_Construct(ppv,(LPVOID*)ppProxy); + return CFProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy); FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid)); return E_FAIL; } diff --git a/reactos/lib/ole32/rpc.c b/reactos/lib/ole32/rpc.c index 53dbd00085c..158016fab20 100644 --- a/reactos/lib/ole32/rpc.c +++ b/reactos/lib/ole32/rpc.c @@ -33,18 +33,14 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" +#include "winsvc.h" #include "objbase.h" #include "ole2.h" -#include "ole2ver.h" #include "rpc.h" #include "winerror.h" #include "winreg.h" -#include "wownt32.h" #include "wtypes.h" #include "wine/unicode.h" -#include "wine/winbase16.h" -#include "compobj_private.h" -#include "ifs.h" #include "compobj_private.h" @@ -52,6 +48,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +#define PIPEPREF "\\\\.\\pipe\\" +#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr" + #define REQTYPE_REQUEST 0 typedef struct _wine_rpc_request_header { DWORD reqid; @@ -96,18 +95,24 @@ static wine_rpc_request **reqs = NULL; static int nrofreqs = 0; /* This pipe is _thread_ based, each thread which talks to a remote - * apartment (mid) has its own pipe */ + * apartment (mid) has its own pipe. The same structure is used both + * for outgoing and incoming RPCs. + */ typedef struct _wine_pipe { wine_marshal_id mid; /* target mid */ - DWORD tid; /* thread which owns this outgoing pipe */ + DWORD tid; /* thread which owns this pipe */ HANDLE hPipe; int pending; HANDLE hThread; CRITICAL_SECTION crit; + + APARTMENT *apt; /* apartment of the marshalling thread for the stub dispatch case */ } wine_pipe; -static wine_pipe *pipes = NULL; +#define MAX_WINE_PIPES 256 + +static wine_pipe pipes[MAX_WINE_PIPES]; static int nrofpipes = 0; typedef struct _PipeBuf { @@ -115,14 +120,13 @@ typedef struct _PipeBuf { DWORD ref; wine_marshal_id mid; - wine_pipe *pipe; } PipeBuf; static HRESULT WINAPI read_pipe(HANDLE hf, LPVOID ptr, DWORD size) { DWORD res; if (!ReadFile(hf,ptr,size,&res,NULL)) { - FIXME("Failed to read from %p, le is %lx\n",hf,GetLastError()); + FIXME("Failed to read from %p, le is %ld\n",hf,GetLastError()); return E_FAIL; } if (res!=size) { @@ -162,7 +166,7 @@ static HRESULT WINAPI write_pipe(HANDLE hf, LPVOID ptr, DWORD size) { DWORD res; if (!WriteFile(hf,ptr,size,&res,NULL)) { - FIXME("Failed to write to %p, le is %lx\n",hf,GetLastError()); + FIXME("Failed to write to %p, le is %ld\n",hf,GetLastError()); return E_FAIL; } if (res!=size) { @@ -172,30 +176,30 @@ write_pipe(HANDLE hf, LPVOID ptr, DWORD size) { return S_OK; } -static DWORD WINAPI _StubReaderThread(LPVOID); +static DWORD WINAPI stub_dispatch_thread(LPVOID); static HRESULT PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) { int i; char pipefn[100]; - wine_pipe *new_pipes; for (i=0;iprocessid) + if (pipes[i].mid.oxid==mid->oxid) return S_OK; - if (pipes) - new_pipes=(wine_pipe*)HeapReAlloc(GetProcessHeap(),0,pipes,sizeof(pipes[0])*(nrofpipes+1)); - else - new_pipes=(wine_pipe*)HeapAlloc(GetProcessHeap(),0,sizeof(pipes[0])); - if (!new_pipes) return E_OUTOFMEMORY; - pipes = new_pipes; - sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid); + if (nrofpipes + 1 >= MAX_WINE_PIPES) + { + FIXME("Out of pipes, please increase MAX_WINE_PIPES\n"); + return E_OUTOFMEMORY; + } + sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid); memcpy(&(pipes[nrofpipes].mid),mid,sizeof(*mid)); pipes[nrofpipes].hPipe = hPipe; + pipes[nrofpipes].apt = COM_CurrentApt(); + assert( pipes[nrofpipes].apt ); InitializeCriticalSection(&(pipes[nrofpipes].crit)); nrofpipes++; if (startreader) { - pipes[nrofpipes-1].hThread = CreateThread(NULL,0,_StubReaderThread,(LPVOID)(pipes+(nrofpipes-1)),0,&(pipes[nrofpipes-1].tid)); + pipes[nrofpipes-1].hThread = CreateThread(NULL,0,stub_dispatch_thread,(LPVOID)(pipes+(nrofpipes-1)),0,&(pipes[nrofpipes-1].tid)); } else { pipes[nrofpipes-1].tid = GetCurrentThreadId(); } @@ -206,7 +210,7 @@ static HANDLE PIPE_FindByMID(wine_marshal_id *mid) { int i; for (i=0;iprocessid) && + if ((pipes[i].mid.oxid==mid->oxid) && (GetCurrentThreadId()==pipes[i].tid) ) return pipes[i].hPipe; @@ -217,7 +221,7 @@ static wine_pipe* PIPE_GetFromMID(wine_marshal_id *mid) { int i; for (i=0;iprocessid) && + if ((pipes[i].mid.oxid==mid->oxid) && (GetCurrentThreadId()==pipes[i].tid) ) return pipes+i; @@ -303,8 +307,6 @@ PipeBuf_Release(LPRPCCHANNELBUFFER iface) { if (ref) return ref; - FIXME("Free all stuff\n"); - memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id)); pipe = PIPE_FindByMID(&This->mid); @@ -333,16 +335,18 @@ PipeBuf_GetBuffer( static HRESULT COM_InvokeAndRpcSend(wine_rpc_request *req) { - IRpcStubBuffer *stub; + IRpcStubBuffer *stub; RPCOLEMESSAGE msg; HRESULT hres; DWORD reqtype; - hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub); - if (hres) { + if (!(stub = mid_to_stubbuffer(&(req->reqh.mid)))) + { ERR("Stub not found?\n"); - return hres; + return E_FAIL; } + + IUnknown_AddRef(stub); msg.Buffer = req->Buffer; msg.iMethod = req->reqh.iMethod; msg.cbBuffer = req->reqh.cbBuffer; @@ -378,10 +382,6 @@ RPC_QueueRequestAndWait(wine_rpc_request *req) { FIXME("no pipe found.\n"); return E_POINTER; } - if (GetCurrentProcessId() == req->reqh.mid.processid) { - ERR("In current process?\n"); - return E_FAIL; - } req->hPipe = xpipe->hPipe; req->state = REQSTATE_REQ_WAITING_FOR_REPLY; reqtype = REQTYPE_REQUEST; @@ -423,7 +423,7 @@ PipeBuf_SendReceive( TRACE("()\n"); - if (This->mid.processid == GetCurrentProcessId()) { + if (This->mid.oxid == COM_CurrentApt()->oxid) { ERR("Need to call directly!\n"); return E_FAIL; } @@ -489,7 +489,7 @@ PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) { hPipe = PIPE_FindByMID(mid); if (hPipe == INVALID_HANDLE_VALUE) { char pipefn[200]; - sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid); + sprintf(pipefn,OLESTUBMGR"_%08lx%08lx",(DWORD)(mid->oxid >> 32),(DWORD)mid->oxid); hPipe = CreateFileA( pipefn, GENERIC_READ|GENERIC_WRITE, @@ -506,7 +506,7 @@ PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) { hres = PIPE_RegisterPipe(mid, hPipe, FALSE); if (hres) return hres; memset(&ourid,0,sizeof(ourid)); - ourid.processid = GetCurrentProcessId(); + ourid.oxid = COM_CurrentApt()->oxid; if (!WriteFile(hPipe,&ourid,sizeof(ourid),&res,NULL)||(res!=sizeof(ourid))) { ERR("Failed writing startup mid!\n"); return E_FAIL; @@ -569,6 +569,116 @@ create_server(REFCLSID rclsid) { return S_OK; } + +/* + * start_local_service() - start a service given its name and parameters + */ +static DWORD +start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) +{ + SC_HANDLE handle, hsvc; + DWORD r = ERROR_FUNCTION_FAILED; + + TRACE("Starting service %s %ld params\n", debugstr_w(name), num); + + handle = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (!handle) + return r; + hsvc = OpenServiceW(handle, name, SC_MANAGER_ALL_ACCESS); + if (hsvc) + { + if(StartServiceW(hsvc, num, (LPCWSTR*)params)) + r = ERROR_SUCCESS; + else + r = GetLastError(); + if (r==ERROR_SERVICE_ALREADY_RUNNING) + r = ERROR_SUCCESS; + CloseServiceHandle(hsvc); + } + CloseServiceHandle(handle); + + TRACE("StartService returned error %ld (%s)\n", r, r?"ok":"failed"); + + return r; +} + +/* + * create_local_service() - start a COM server in a service + * + * To start a Local Service, we read the AppID value under + * the class's CLSID key, then open the HKCR\\AppId key specified + * there and check for a LocalService value. + * + * Note: Local Services are not supported under Windows 9x + */ +static HRESULT +create_local_service(REFCLSID rclsid) +{ + HRESULT hres = REGDB_E_READREGDB; + WCHAR buf[40], keyname[50]; + static const WCHAR szClsId[] = { 'C','L','S','I','D','\\',0 }; + static const WCHAR szAppId[] = { 'A','p','p','I','d',0 }; + static const WCHAR szAppIdKey[] = { 'A','p','p','I','d','\\',0 }; + static const WCHAR szLocalService[] = { + 'L','o','c','a','l','S','e','r','v','i','c','e',0 }; + static const WCHAR szServiceParams[] = { + 'S','e','r','v','i','c','e','P','a','r','a','m','s',0}; + HKEY hkey; + LONG r; + DWORD type, sz; + + TRACE("Attempting to start Local service for %s\n", debugstr_guid(rclsid)); + + /* read the AppID value under the class's key */ + strcpyW(keyname,szClsId); + StringFromGUID2(rclsid,&keyname[6],39); + r = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &hkey); + if (r!=ERROR_SUCCESS) + return hres; + sz = sizeof buf; + r = RegQueryValueExW(hkey, szAppId, NULL, &type, (LPBYTE)buf, &sz); + RegCloseKey(hkey); + if (r!=ERROR_SUCCESS || type!=REG_SZ) + return hres; + + /* read the LocalService and ServiceParameters values from the AppID key */ + strcpyW(keyname, szAppIdKey); + strcatW(keyname, buf); + r = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &hkey); + if (r!=ERROR_SUCCESS) + return hres; + sz = sizeof buf; + r = RegQueryValueExW(hkey, szLocalService, NULL, &type, (LPBYTE)buf, &sz); + if (r==ERROR_SUCCESS && type==REG_SZ) + { + DWORD num_args = 0; + LPWSTR args[1] = { NULL }; + + /* + * FIXME: I'm not really sure how to deal with the service parameters. + * I suspect that the string returned from RegQueryValueExW + * should be split into a number of arguments by spaces. + * It would make more sense if ServiceParams contained a + * REG_MULTI_SZ here, but it's a REG_SZ for the services + * that I'm interested in for the moment. + */ + r = RegQueryValueExW(hkey, szServiceParams, NULL, &type, NULL, &sz); + if (r == ERROR_SUCCESS && type == REG_SZ && sz) + { + args[0] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sz); + num_args++; + RegQueryValueExW(hkey, szServiceParams, NULL, &type, (LPBYTE)args[0], &sz); + } + r = start_local_service(buf, num_args, args); + if (r==ERROR_SUCCESS) + hres = S_OK; + HeapFree(GetProcessHeap(),0,args[0]); + } + RegCloseKey(hkey); + + return hres; +} + /* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { HRESULT hres; @@ -588,6 +698,8 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF)); while (tries++hPipe; HRESULT hres = S_OK; - TRACE("STUB reader thread %lx\n",GetCurrentProcessId()); + TRACE("starting for apartment OXID %08lx%08lx\n", (DWORD)(xpipe->mid.oxid >> 32), (DWORD)(xpipe->mid.oxid)); + + /* join marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */ + NtCurrentTeb()->ReservedForOle = xpipe->apt; + while (!hres) { int i; + hres = COM_RpcReceive(xpipe); if (hres) break; @@ -754,18 +870,41 @@ _StubReaderThread(LPVOID param) { } } } - FIXME("Failed with hres %lx\n",hres); + + /* fixme: this thread never quits naturally */ + WARN("exiting with hres %lx\n",hres); CloseHandle(xhPipe); return 0; } -static DWORD WINAPI -_StubMgrThread(LPVOID param) { +struct apartment_listener_params +{ + APARTMENT *apt; + HANDLE event; +}; + +/* This thread listens on a named pipe for each apartment that exports + * objects. It deals with incoming connection requests. Each time a + * client connects a separate thread is spawned for that particular + * connection. + * + * This architecture is different in native DCOM. + */ +static DWORD WINAPI apartment_listener_thread(LPVOID p) +{ char pipefn[200]; HANDLE listenPipe; + struct apartment_listener_params * params = (struct apartment_listener_params *)p; + APARTMENT *apt = params->apt; + HANDLE event = params->event; - sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId()); - TRACE("Stub Manager Thread starting on (%s)\n",pipefn); + HeapFree(GetProcessHeap(), 0, params); + + /* we must join the marshalling threads apartment. we already have a ref here */ + NtCurrentTeb()->ReservedForOle = apt; + + sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid)); + TRACE("Apartment listener thread starting on (%s)\n",pipefn); while (1) { listenPipe = CreateNamedPipeA( @@ -778,28 +917,148 @@ _StubMgrThread(LPVOID param) { NMPWAIT_USE_DEFAULT_WAIT, NULL ); + + /* tell function that started this thread that we have attempted to created the + * named pipe. */ + if (event) { + SetEvent(event); + event = NULL; + } + if (listenPipe == INVALID_HANDLE_VALUE) { - FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError()); + FIXME("pipe creation failed for %s, error %ld\n",pipefn,GetLastError()); return 1; /* permanent failure, so quit stubmgr thread */ } - if (!ConnectNamedPipe(listenPipe,NULL)) { - ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError()); + + /* an already connected pipe is not an error */ + if (!ConnectNamedPipe(listenPipe,NULL) && + (GetLastError() != ERROR_PIPE_CONNECTED)) { + ERR("Failure during ConnectNamedPipe %ld!\n",GetLastError()); CloseHandle(listenPipe); continue; } + PIPE_StartRequestThread(listenPipe); } return 0; } -void -STUBMGR_Start() { - static BOOL stubMgrRunning = FALSE; - DWORD tid; +void start_apartment_listener_thread() +{ + APARTMENT *apt = COM_CurrentApt(); + + assert( apt ); + + TRACE("apt->listenertid=%ld\n", apt->listenertid); - if (!stubMgrRunning) { - stubMgrRunning = TRUE; - CreateThread(NULL,0,_StubMgrThread,NULL,0,&tid); - Sleep(2000); /* actually we just try opening the pipe until it succeeds */ - } + /* apt->listenertid is a hack which needs to die at some point, as + * it leaks information into the apartment structure. in fact, + * this thread isn't quite correct anyway as native RPC doesn't + * use a thread per apartment at all, instead the dispatch thread + * either enters the apartment to perform the RPC (for MTAs, RTAs) + * or does a context switch into it for STAs. + */ + + if (!apt->listenertid) + { + HANDLE thread; + HANDLE event = CreateEventW(NULL, TRUE, FALSE, NULL); + struct apartment_listener_params * params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params)); + + params->apt = apt; + params->event = event; + thread = CreateThread(NULL, 0, apartment_listener_thread, params, 0, &apt->listenertid); + CloseHandle(thread); + /* wait for pipe to be created before returning, otherwise we + * might try to use it and fail */ + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } +} + +struct local_server_params +{ + CLSID clsid; + IStream *stream; +}; + +static DWORD WINAPI local_server_thread(LPVOID param) +{ + struct local_server_params * lsp = (struct local_server_params *)param; + HANDLE hPipe; + char pipefn[200]; + HRESULT hres; + IStream *pStm = lsp->stream; + STATSTG ststg; + unsigned char *buffer; + int buflen; + LARGE_INTEGER seekto; + ULARGE_INTEGER newpos; + ULONG res; + + TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid)); + + strcpy(pipefn,PIPEPREF); + WINE_StringFromCLSID(&lsp->clsid,pipefn+strlen(PIPEPREF)); + + HeapFree(GetProcessHeap(), 0, lsp); + + hPipe = CreateNamedPipeA( pipefn, PIPE_ACCESS_DUPLEX, + PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, + 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, NULL ); + if (hPipe == INVALID_HANDLE_VALUE) { + FIXME("pipe creation failed for %s, le is %ld\n",pipefn,GetLastError()); + return 1; + } + while (1) { + if (!ConnectNamedPipe(hPipe,NULL)) { + ERR("Failure during ConnectNamedPipe %ld, ABORT!\n",GetLastError()); + break; + } + + TRACE("marshalling IClassFactory to client\n"); + + hres = IStream_Stat(pStm,&ststg,0); + if (hres) return hres; + + buflen = ststg.cbSize.u.LowPart; + buffer = HeapAlloc(GetProcessHeap(),0,buflen); + seekto.u.LowPart = 0; + seekto.u.HighPart = 0; + hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); + if (hres) { + FIXME("IStream_Seek failed, %lx\n",hres); + return hres; + } + + hres = IStream_Read(pStm,buffer,buflen,&res); + if (hres) { + FIXME("Stream Read failed, %lx\n",hres); + return hres; + } + + IStream_Release(pStm); + + WriteFile(hPipe,buffer,buflen,&res,NULL); + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + + TRACE("done marshalling IClassFactory\n"); + } + CloseHandle(hPipe); + return 0; +} + +void RPC_StartLocalServer(REFCLSID clsid, IStream *stream) +{ + DWORD tid; + HANDLE thread; + struct local_server_params *lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp)); + + lsp->clsid = *clsid; + lsp->stream = stream; + + thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid); + CloseHandle(thread); + /* FIXME: failure handling */ } diff --git a/reactos/lib/ole32/stg_bigblockfile.c b/reactos/lib/ole32/stg_bigblockfile.c index 050eb537d57..47ed3384c44 100644 --- a/reactos/lib/ole32/stg_bigblockfile.c +++ b/reactos/lib/ole32/stg_bigblockfile.c @@ -423,6 +423,7 @@ void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize) if (This->fileBased) { char buf[10]; + DWORD w; /* * close file-mapping object, must be done before call to SetEndFile @@ -445,7 +446,7 @@ void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize) */ memset(buf, '0', 10); SetFilePointer(This->hfile, newSize.u.LowPart, NULL, FILE_BEGIN); - WriteFile(This->hfile, buf, 10, NULL, NULL); + WriteFile(This->hfile, buf, 10, &w, NULL); /* * END HACK */ diff --git a/reactos/lib/ole32/stg_stream.c b/reactos/lib/ole32/stg_stream.c index 5070ede59fc..e6569f5d1b4 100644 --- a/reactos/lib/ole32/stg_stream.c +++ b/reactos/lib/ole32/stg_stream.c @@ -447,6 +447,9 @@ HRESULT WINAPI StgStreamImpl_Write( return STG_E_ACCESSDENIED; } + if (!pv) + return STG_E_INVALIDPOINTER; + /* * If the caller is not interested in the number of bytes written, * we use another buffer to avoid "if" statements in the code. diff --git a/reactos/lib/ole32/storage32.c b/reactos/lib/ole32/storage32.c index c9ee7f2dce7..633657f319a 100644 --- a/reactos/lib/ole32/storage32.c +++ b/reactos/lib/ole32/storage32.c @@ -51,6 +51,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage); #define FILE_BEGIN 0 +#define STGM_SHARE_MODE(stgm) ((stgm)&0xf0) /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ #define OLESTREAM_ID 0x501 @@ -872,18 +873,23 @@ HRESULT WINAPI StorageBaseImpl_CreateStream( if (pwcsName == 0) return STG_E_INVALIDNAME; + if (reserved1 || reserved2) + return STG_E_INVALIDPARAMETER; + /* * Validate the STGM flags */ if ( FAILED( validateSTGM(grfMode) )) return STG_E_INVALIDFLAG; + if ( !(grfMode & STGM_SHARE_EXCLUSIVE) ) + return STG_E_INVALIDFLAG; + /* * As documented. */ - if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || - (grfMode & STGM_DELETEONRELEASE) || - (grfMode & STGM_TRANSACTED) ) + if ((grfMode & STGM_DELETEONRELEASE) || + (grfMode & STGM_TRANSACTED)) return STG_E_INVALIDFUNCTION; /* @@ -1680,7 +1686,7 @@ HRESULT WINAPI StorageImpl_DestroyElement( This->rootPropertySetIndex, &parentProperty); - assert(res==TRUE); + assert(res); /* * Second, check to see if by any chance the actual storage (This) is not @@ -2395,8 +2401,7 @@ void StorageImpl_Destroy( { TRACE("(%p)\n", This); - if(This->pwcsName) - HeapFree(GetProcessHeap(), 0, This->pwcsName); + HeapFree(GetProcessHeap(), 0, This->pwcsName); BlockChainStream_Destroy(This->smallBlockRootChain); BlockChainStream_Destroy(This->rootBlockChain); @@ -5426,6 +5431,8 @@ HRESULT WINAPI StgCreateDocfile( */ if (ppstgOpen == 0) return STG_E_INVALIDPOINTER; + if (reserved != 0) + return STG_E_INVALIDPARAMETER; /* * Validate the STGM flags @@ -5433,6 +5440,14 @@ HRESULT WINAPI StgCreateDocfile( if ( FAILED( validateSTGM(grfMode) )) return STG_E_INVALIDFLAG; + /* StgCreateDocFile always opens for write */ + if (!(grfMode & (STGM_WRITE|STGM_READWRITE))) + return STG_E_INVALIDFLAG; + + /* always opens non-shared */ + if (!(grfMode & STGM_SHARE_EXCLUSIVE)) + return STG_E_INVALIDFLAG; + /* * Generate a unique name. */ @@ -5493,6 +5508,8 @@ HRESULT WINAPI StgCreateDocfile( if (hFile == INVALID_HANDLE_VALUE) { + if(GetLastError() == ERROR_FILE_EXISTS) + return STG_E_FILEALREADYEXISTS; return E_FAIL; } @@ -5564,18 +5581,44 @@ HRESULT WINAPI StgOpenStorage( snbExclude, reserved, ppstgOpen); /* - * Perform a sanity check + * Perform sanity checks */ - if (( pwcsName == 0) || (ppstgOpen == 0) ) + if (pwcsName == 0) + { + hr = STG_E_INVALIDNAME; + goto end; + } + + if (ppstgOpen == 0) { hr = STG_E_INVALIDPOINTER; goto end; } + if (reserved) + { + hr = STG_E_INVALIDPARAMETER; + goto end; + } + + /* + * Validate the sharing mode + */ + switch(STGM_SHARE_MODE(grfMode)) + { + case STGM_SHARE_EXCLUSIVE: + case STGM_SHARE_DENY_WRITE: + break; + default: + hr = STG_E_INVALIDFLAG; + goto end; + } + /* * Validate the STGM flags */ - if ( FAILED( validateSTGM(grfMode) )) + if ( FAILED( validateSTGM(grfMode) ) || + (grfMode&STGM_CREATE)) { hr = STG_E_INVALIDFLAG; goto end; @@ -5600,8 +5643,6 @@ HRESULT WINAPI StgOpenStorage( FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0); - length = GetFileSize(hFile, NULL); - if (hFile==INVALID_HANDLE_VALUE) { DWORD last_error = GetLastError(); @@ -5634,6 +5675,8 @@ HRESULT WINAPI StgOpenStorage( goto end; } + length = GetFileSize(hFile, NULL); + /* * Allocate and initialize the new IStorage32object. */ @@ -7355,15 +7398,9 @@ HRESULT WINAPI OleConvertOLESTREAMToIStorage ( /* Free allocated memory */ for(i=0; i < 2; i++) { - if(pOleStreamData[i].pData != NULL) - { - HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); - } - if(pOleStreamData[i].pstrOleObjFileName != NULL) - { - HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName); - pOleStreamData[i].pstrOleObjFileName = NULL; - } + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName); + pOleStreamData[i].pstrOleObjFileName = NULL; } return hRes; } @@ -7432,10 +7469,7 @@ HRESULT WINAPI OleConvertIStorageToOLESTREAM ( /* Free allocated memory */ for(i=0; i < 2; i++) { - if(pOleStreamData[i].pData != NULL) - { - HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); - } + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); } return hRes; diff --git a/reactos/lib/ole32/stubmanager.c b/reactos/lib/ole32/stubmanager.c new file mode 100644 index 00000000000..54a42904788 --- /dev/null +++ b/reactos/lib/ole32/stubmanager.c @@ -0,0 +1,300 @@ +/* + * A stub manager is an object that controls interface stubs. It is + * identified by an OID (object identifier) and acts as the network + * identity of the object. There can be many stub managers in a + * process or apartment. + * + * Copyright 2002 Marcus Meissner + * Copyright 2004 Mike Hearn for CodeWeavers + * Copyright 2004 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "objbase.h" +#include "ole2.h" +#include "ole2ver.h" +#include "rpc.h" +#include "wine/debug.h" +#include "compobj_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub); +static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid); + +/* creates a new stub manager and adds it into the apartment. caller must + * release stub manager when it is no longer required. the apartment and + * external refs together take one implicit ref */ +struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object) +{ + struct stub_manager *sm; + + assert( apt ); + + sm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct stub_manager)); + if (!sm) return NULL; + + list_init(&sm->ifstubs); + InitializeCriticalSection(&sm->lock); + IUnknown_AddRef(object); + sm->object = object; + sm->apt = apt; + + /* start off with 2 references because the stub is in the apartment + * and the caller will also hold a reference */ + sm->refs = 2; + + /* yes, that's right, this starts at zero. that's zero EXTERNAL + * refs, ie nobody has unmarshalled anything yet. we can't have + * negative refs because the stub manager cannot be explicitly + * killed, it has to die by somebody unmarshalling then releasing + * the marshalled ifptr. + */ + sm->extrefs = 0; + + EnterCriticalSection(&apt->cs); + sm->oid = apt->oidc++; + list_add_head(&apt->stubmgrs, &sm->entry); + LeaveCriticalSection(&apt->cs); + + TRACE("Created new stub manager (oid=%s) at %p for object with IUnknown %p\n", wine_dbgstr_longlong(sm->oid), sm, object); + + return sm; +} + +/* m->apt->cs must be held on entry to this function */ +static void stub_manager_delete(struct stub_manager *m) +{ + struct list *cursor; + + TRACE("destroying %p (oid=%s)\n", m, wine_dbgstr_longlong(m->oid)); + + list_remove(&m->entry); + + while ((cursor = list_head(&m->ifstubs))) + { + struct ifstub *ifstub = LIST_ENTRY(cursor, struct ifstub, entry); + stub_manager_delete_ifstub(m, ifstub); + } + + IUnknown_Release(m->object); + + DeleteCriticalSection(&m->lock); + + HeapFree(GetProcessHeap(), 0, m); +} + +/* gets the stub manager associated with an object - caller must call + * release on the stub manager when it is no longer needed */ +struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object) +{ + struct stub_manager *result = NULL; + struct list *cursor; + APARTMENT *apt; + + if (!(apt = COM_ApartmentFromOXID(oxid, TRUE))) + { + WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid)); + return NULL; + } + + EnterCriticalSection(&apt->cs); + LIST_FOR_EACH( cursor, &apt->stubmgrs ) + { + struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); + + if (m->object == object) + { + result = m; + stub_manager_int_addref(result); + break; + } + } + LeaveCriticalSection(&apt->cs); + + COM_ApartmentRelease(apt); + + TRACE("found %p from object %p\n", result, object); + + return result; +} + +/* increments the internal refcount */ +ULONG stub_manager_int_addref(struct stub_manager *This) +{ + ULONG refs; + + EnterCriticalSection(&This->apt->cs); + refs = ++This->refs; + LeaveCriticalSection(&This->apt->cs); + + TRACE("before %ld\n", refs - 1); + + return refs; +} + +/* decrements the internal refcount */ +ULONG stub_manager_int_release(struct stub_manager *This) +{ + ULONG refs; + APARTMENT *apt = This->apt; + + EnterCriticalSection(&apt->cs); + refs = --This->refs; + + TRACE("after %ld\n", refs); + + if (!refs) + stub_manager_delete(This); + LeaveCriticalSection(&apt->cs); + + return refs; +} + +/* gets the stub manager associated with an object id - caller must call + * release on the stub manager when it is no longer needed */ +struct stub_manager *get_stub_manager(OXID oxid, OID oid) +{ + struct stub_manager *result = NULL; + struct list *cursor; + APARTMENT *apt; + + if (!(apt = COM_ApartmentFromOXID(oxid, TRUE))) + { + WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid)); + return NULL; + } + + EnterCriticalSection(&apt->cs); + LIST_FOR_EACH( cursor, &apt->stubmgrs ) + { + struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry ); + + if (m->oid == oid) + { + result = m; + stub_manager_int_addref(result); + break; + } + } + LeaveCriticalSection(&apt->cs); + + COM_ApartmentRelease(apt); + + TRACE("found %p from oid %s\n", result, wine_dbgstr_longlong(oid)); + + return result; +} + +/* add some external references (ie from a client that unmarshaled an ifptr) */ +ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs) +{ + ULONG rc = InterlockedExchangeAdd(&m->extrefs, refs) + refs; + + TRACE("added %lu refs to %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc); + + return rc; +} + +/* remove some external references */ +ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs) +{ + ULONG rc = InterlockedExchangeAdd(&m->extrefs, -refs) - refs; + + TRACE("removed %lu refs from %p (oid %s), rc is now %lu\n", refs, m, wine_dbgstr_longlong(m->oid), rc); + + if (rc == 0) + stub_manager_int_release(m); + + return rc; +} + +static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const IPID *ipid) +{ + struct list *cursor; + struct ifstub *result = NULL; + + EnterCriticalSection(&m->lock); + LIST_FOR_EACH( cursor, &m->ifstubs ) + { + struct ifstub *ifstub = LIST_ENTRY( cursor, struct ifstub, entry ); + + if (IsEqualGUID(ipid, &ifstub->ipid)) + { + result = ifstub; + break; + } + } + LeaveCriticalSection(&m->lock); + + return result; +} + +IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *ipid) +{ + struct ifstub *ifstub = stub_manager_ipid_to_ifstub(m, ipid); + + return ifstub ? ifstub->stubbuffer : NULL; +} + +/* registers a new interface stub COM object with the stub manager and returns registration record */ +struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal) +{ + struct ifstub *stub; + + TRACE("oid=%s, stubbuffer=%p, iptr=%p, iid=%s, tablemarshal=%s\n", + wine_dbgstr_longlong(m->oid), sb, iptr, debugstr_guid(iid), tablemarshal ? "TRUE" : "FALSE"); + + stub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct ifstub)); + if (!stub) return NULL; + + stub->stubbuffer = sb; + IUnknown_AddRef(sb); + + /* no need to ref this, same object as sb */ + stub->iface = iptr; + stub->table = tablemarshal; + stub->iid = *iid; + stub->ipid = *iid; /* FIXME: should be globally unique */ + + EnterCriticalSection(&m->lock); + list_add_head(&m->ifstubs, &stub->entry); + LeaveCriticalSection(&m->lock); + + return stub; +} + +static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *ifstub) +{ + TRACE("m=%p, m->oid=%s, ipid=%s\n", m, wine_dbgstr_longlong(m->oid), debugstr_guid(&ifstub->ipid)); + + list_remove(&ifstub->entry); + + IUnknown_Release(ifstub->stubbuffer); + IUnknown_Release(ifstub->iface); + + HeapFree(GetProcessHeap(), 0, ifstub); +} diff --git a/reactos/lib/oleaut32/ole2disp.c b/reactos/lib/oleaut32/ole2disp.c index 37cbef0d7fd..8fc355cbfab 100644 --- a/reactos/lib/oleaut32/ole2disp.c +++ b/reactos/lib/oleaut32/ole2disp.c @@ -33,7 +33,6 @@ #include "winerror.h" #include "ole2disp.h" -#include "olectl.h" #include "wine/debug.h" diff --git a/reactos/lib/oleaut32/oleaut32.rc b/reactos/lib/oleaut32/oleaut32.rc index 2825a4885d1..9eac4859472 100644 --- a/reactos/lib/oleaut32/oleaut32.rc +++ b/reactos/lib/oleaut32/oleaut32.rc @@ -36,12 +36,13 @@ #include "oleaut32_No.rc" #include "oleaut32_Pl.rc" #include "oleaut32_Pt.rc" +#include "oleaut32_Ru.rc" #include "oleaut32_Sv.rc" #include "oleaut32_Th.rc" /* * FIXME: * Finnish, Greek, Hebrew, Japanese, Korean, Portuguese, - * Russian, Turkish, Slovenian (at least) are localised in XP Home. + * Turkish, Slovenian (at least) are localised in XP Home. * I expect Chinese etc are localised in Asian Editions also. */ diff --git a/reactos/lib/crtdll/stdio/fgets.c b/reactos/lib/oleaut32/oleaut32_Ru.rc similarity index 54% rename from reactos/lib/crtdll/stdio/fgets.c rename to reactos/lib/oleaut32/oleaut32_Ru.rc index c2eaffaa3c8..08edd96459d 100644 --- a/reactos/lib/crtdll/stdio/fgets.c +++ b/reactos/lib/oleaut32/oleaut32_Ru.rc @@ -1,47 +1,31 @@ -/* $Id$ - * - * ReactOS msvcrt library - * - * fgets.c - * - * Copyright (C) 2002 Robert Dickenson - * - * Based on original work Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details - * 28/12/1998: Appropriated for Reactos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ - -#include -#include - - -char* fgets(char* s, int n, FILE* f) -{ - int c=0; - char *cs; - - cs = s; - while (--n>0 && (c = getc(f)) != EOF) { - *cs++ = c; - if (c == '\n') - break; - } - if (c == EOF && cs == s) - return NULL; - *cs++ = '\0'; - return s; -} +/* + * Russian resources for oleaut32 + * + * Copyright 2004 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_TRUE "Ïðàâäà" + IDS_FALSE "Ëîæü" + IDS_YES "Äà" + IDS_NO "Íåò" + IDS_ON "Âêëþ÷åíî" + IDS_OFF "Âûêëþ÷åíî" +} diff --git a/reactos/lib/oleaut32/olefont.c b/reactos/lib/oleaut32/olefont.c index 2a6ad27a095..27d1fc5b010 100644 --- a/reactos/lib/oleaut32/olefont.c +++ b/reactos/lib/oleaut32/olefont.c @@ -454,8 +454,7 @@ static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc) { TRACE("(%p)\n", fontDesc); - if (fontDesc->description.lpstrName!=0) - HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName); + HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName); if (fontDesc->gdiFont!=0) DeleteObject(fontDesc->gdiFont); @@ -1594,8 +1593,7 @@ static HRESULT WINAPI OLEFontImpl_Load( if (cbRead!=bStringSize) return E_FAIL; - if (this->description.lpstrName!=0) - HeapFree(GetProcessHeap(), 0, this->description.lpstrName); + HeapFree(GetProcessHeap(), 0, this->description.lpstrName); len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 ); this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) ); diff --git a/reactos/lib/oleaut32/olepicture.c b/reactos/lib/oleaut32/olepicture.c index 317ae0730b4..a7bbed07185 100644 --- a/reactos/lib/oleaut32/olepicture.c +++ b/reactos/lib/oleaut32/olepicture.c @@ -301,7 +301,7 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj) break; } } - if (Obj->data) HeapFree(GetProcessHeap(), 0, Obj->data); + HeapFree(GetProcessHeap(), 0, Obj->data); HeapFree(GetProcessHeap(), 0, Obj); } @@ -1172,7 +1172,6 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n"); return E_FAIL; #endif - break; } case 0xd8ff: { /* JPEG */ #ifdef HAVE_JPEGLIB_H diff --git a/reactos/lib/oleaut32/safearray.c b/reactos/lib/oleaut32/safearray.c index dca1ba2298d..b79f56ab76b 100644 --- a/reactos/lib/oleaut32/safearray.c +++ b/reactos/lib/oleaut32/safearray.c @@ -154,7 +154,7 @@ static inline DWORD SAFEARRAY_GetHiddenDWORD(SAFEARRAY* psa) /* Get the number of cells in a SafeArray */ static ULONG SAFEARRAY_GetCellCount(const SAFEARRAY *psa) { - SAFEARRAYBOUND* psab = psa->rgsabound; + const SAFEARRAYBOUND* psab = psa->rgsabound; USHORT cCount = psa->cDims; ULONG ulNumCells = 1; diff --git a/reactos/lib/oleaut32/tmarshal.c b/reactos/lib/oleaut32/tmarshal.c index 288e4b341f7..0957d74ae4e 100644 --- a/reactos/lib/oleaut32/tmarshal.c +++ b/reactos/lib/oleaut32/tmarshal.c @@ -42,11 +42,8 @@ #include "winuser.h" #include "ole2.h" -#include "wine/unicode.h" -#include "ole2disp.h" #include "typelib.h" #include "wine/debug.h" -#include "winternl.h" static const WCHAR riidW[5] = {'r','i','i','d',0}; static const WCHAR pdispparamsW[] = {'p','d','i','s','p','p','a','r','a','m','s',0}; @@ -1159,7 +1156,6 @@ _get_funcdesc( } i++; } - return E_FAIL; } static DWORD @@ -1185,6 +1181,13 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) return E_FAIL; } + if (!tpinfo->chanbuf) + { + WARN("Tried to use disconnected proxy\n"); + LeaveCriticalSection(&tpinfo->crit); + return RPC_E_DISCONNECTED; + } + if (relaydeb) { TRACE_(olerelay)("->"); if (iname) @@ -1471,6 +1474,7 @@ PSFacBuf_CreateProxy( proxy->ref = 2; proxy->tinfo = tinfo; memcpy(&proxy->iid,riid,sizeof(*riid)); + proxy->chanbuf = 0; *ppv = (LPVOID)proxy; *ppProxy = (IRpcProxyBuffer *)&(proxy->lpvtbl2); return S_OK; diff --git a/reactos/lib/oleaut32/typelib.c b/reactos/lib/oleaut32/typelib.c index 4f8861178be..1d09c2a1141 100644 --- a/reactos/lib/oleaut32/typelib.c +++ b/reactos/lib/oleaut32/typelib.c @@ -74,7 +74,6 @@ #include "wine/unicode.h" #include "objbase.h" -#include "ole2disp.h" #include "typelib.h" #include "wine/debug.h" #include "variant.h" @@ -848,7 +847,7 @@ typedef struct tagITypeLibImpl { ITypeLib2Vtbl *lpVtbl; ITypeCompVtbl *lpVtblTypeComp; - UINT ref; + ULONG ref; TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */ /* strings can be stored in tlb as multibyte strings BUT they are *always* @@ -959,7 +958,7 @@ typedef struct tagITypeInfoImpl { ITypeInfo2Vtbl *lpVtbl; ITypeCompVtbl *lpVtblTypeComp; - UINT ref; + ULONG ref; TYPEATTR TypeAttr ; /* _lots_ of type information. */ ITypeLibImpl * pTypeLib; /* back pointer to typelib */ int index; /* index in this typelib; */ @@ -989,7 +988,7 @@ typedef struct tagITypeInfoImpl static struct ITypeInfo2Vtbl tinfvt; static struct ITypeCompVtbl tcompvt; -static ITypeInfo2 * WINAPI ITypeInfo_Constructor(); +static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void); typedef struct tagTLBContext { @@ -1277,7 +1276,7 @@ static void dump_DispParms(DISPPARAMS * pdp) static void dump_TypeInfo(ITypeInfoImpl * pty) { - TRACE("%p ref=%u\n", pty, pty->ref); + TRACE("%p ref=%lu\n", pty, pty->ref); TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid))); TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]); TRACE("fct:%u var:%u impl:%u\n", @@ -1331,6 +1330,50 @@ static void TLB_Free(void * ptr) HeapFree(GetProcessHeap(), 0, ptr); } +/* deep copy a typedesc */ +static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in) +{ + out->vt = in->vt; + switch(in->vt) { + case VT_PTR: + out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC)); + copy_typedesc(out->u.lptdesc, in->u.lptdesc); + break; + case VT_USERDEFINED: + out->u.hreftype = in->u.hreftype; + break; + case VT_CARRAY: + out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) + + (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND)); + copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem); + out->u.lpadesc->cDims = in->u.lpadesc->cDims; + memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND)); + break; + default: + break; + } +} + +/* free()s any allocated memory pointed to by the tdesc. NB does not + free the tdesc itself - this is because the tdesc is typically part + of a larger structure */ +static void free_deep_typedesc(TYPEDESC *tdesc) +{ + switch(tdesc->vt) { + case VT_PTR: + free_deep_typedesc(tdesc->u.lptdesc); + HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc); + tdesc->u.lptdesc = NULL; + break; + case VT_CARRAY: + free_deep_typedesc(&tdesc->u.lpadesc->tdescElem); + HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc); + tdesc->u.lpadesc = NULL; + break; + default: + break; + } +} /********************************************************************** * @@ -1473,7 +1516,7 @@ static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) if(offset <0) { /* data are packed in here */ V_VT(pVar) = (offset & 0x7c000000 )>> 26; - V_UNION(pVar, iVal) = offset & 0xffff; + V_UNION(pVar, iVal) = offset & 0x3ffffff; return; } MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx, @@ -1604,7 +1647,7 @@ MSFT_DoFuncs(TLBContext* pcx, * of this (first) part excluding this field. Then follow the records, * for each member there is one record. * - * First entry is always the length of the record (excluding this + * First entry is always the length of the record (including this * length word). * Rest of the record depends on the type of the member. If there is * a field indicating the member type (function variable intereface etc) @@ -3391,10 +3434,11 @@ static HRESULT WINAPI ITypeLib2_fnQueryInterface( static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface) { ITypeLibImpl *This = (ITypeLibImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->ref was %u\n",This, This->ref); + TRACE("(%p)->ref was %lu\n",This, ref - 1); - return ++(This->ref); + return ref; } /* ITypeLib::Release @@ -3402,12 +3446,11 @@ static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface) static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) { ITypeLibImpl *This = (ITypeLibImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - --(This->ref); + TRACE("(%p)->(%lu)\n",This, ref); - TRACE("(%p)->(%u)\n",This, This->ref); - - if (!This->ref) + if (!ref) { /* remove cache entry */ TRACE("removing from cache list\n"); @@ -3450,7 +3493,7 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) return 0; } - return This->ref; + return ref; } /* ITypeLib::GetTypeInfoCount @@ -4067,12 +4110,12 @@ static HRESULT WINAPI ITypeInfo_fnQueryInterface( static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - ++(This->ref); ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib); - TRACE("(%p)->ref is %u\n",This, This->ref); - return This->ref; + TRACE("(%p)->ref is %lu\n",This, ref); + return ref; } /* ITypeInfo::Release @@ -4080,12 +4123,11 @@ static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface) static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - --(This->ref); + TRACE("(%p)->(%lu)\n",This, ref); - TRACE("(%p)->(%u)\n",This, This->ref); - - if (This->ref) { + if (ref) { /* We don't release ITypeLib when ref=0 becouse it means that funtion is called by ITypeLi2_Release */ ITypeLib2_Release((ITypeLib2*)This->pTypeLib); @@ -4113,7 +4155,7 @@ static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) HeapFree(GetProcessHeap(),0,This); return 0; } - return This->ref; + return ref; } /* ITypeInfo::GetTypeAttr @@ -4127,8 +4169,18 @@ static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface, { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; TRACE("(%p)\n",This); - /* FIXME: must do a copy here */ - *ppTypeAttr=&This->TypeAttr; + *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr)); + memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr)); + + if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */ + copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias); + + if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) { + (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited + funcs */ + (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */ + (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION; + } return S_OK; } @@ -4683,9 +4735,9 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( UINT *pArgErr) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - TLBFuncDesc * pFDesc; - TLBVarDesc * pVDesc; int i; + unsigned int func_index, var_index; + TYPEKIND type_kind; HRESULT hres; TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n", @@ -4693,31 +4745,30 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( ); dump_DispParms(pDispParams); - for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) - if (pFDesc->funcdesc.memid == memid) { - if (pFDesc->funcdesc.invkind & dwFlags) - break; - } - - if (pFDesc) { - if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc); - /* dump_FUNCDESC(&pFDesc->funcdesc);*/ - switch (pFDesc->funcdesc.funckind) { + hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index); + if (SUCCEEDED(hres)) { + FUNCDESC *func_desc; + + hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc); + if(FAILED(hres)) return hres; + + switch (func_desc->funckind) { case FUNC_PUREVIRTUAL: case FUNC_VIRTUAL: { DWORD res; int numargs, numargs2, argspos, args2pos; DWORD *args , *args2; - VARIANT *rgvarg = HeapAlloc(GetProcessHeap(),0,sizeof(VARIANT)*pFDesc->funcdesc.cParams); + VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams); memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs); + hres = S_OK; numargs = 1; numargs2 = 0; - for (i=0;ifuncdesc.cParams;i++) { + for (i = 0; i < func_desc->cParams; i++) { if (icArgs) - numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt); + numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt); else { numargs += 1; /* sizeof(lpvoid) */ - numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt); + numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt); } } @@ -4726,14 +4777,14 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( args[0] = (DWORD)pIUnk; argspos = 1; args2pos = 0; - for (i=0;ifuncdesc.cParams;i++) { - int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt); + for (i = 0; i < func_desc->cParams; i++) { + int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt); if (icArgs) { VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1]; - TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc; - USHORT paramFlags = pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags; + TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; + USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; if (paramFlags & PARAMFLAG_FOPT) { - if(i < pFDesc->funcdesc.cParams-pFDesc->funcdesc.cParamsOpt) + if(i < func_desc->cParams - func_desc->cParamsOpt) ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n"); if(V_VT(arg) == VT_EMPTY || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) { @@ -4748,23 +4799,23 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( } } hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); - if (FAILED(hres)) return hres; + if (FAILED(hres)) goto func_fail; argspos += arglen; - } else if(pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) { + } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) { VARIANT *arg = &rgvarg[i]; - TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc; - if(i < pFDesc->funcdesc.cParams-pFDesc->funcdesc.cParamsOpt) + TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc; + if(i < func_desc->cParams - func_desc->cParamsOpt) ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n"); - if(pFDesc->funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n"); V_VT(arg) = VT_ERROR; V_ERROR(arg) = DISP_E_PARAMNOTFOUND; arglen = _argsize(VT_ERROR); hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt); - if (FAILED(hres)) return hres; + if (FAILED(hres)) goto func_fail; argspos += arglen; } else { - TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc); + TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc); if (tdesc->vt != VT_PTR) FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt); /*FIXME: give pointers for the rest, so propertyget works*/ @@ -4774,32 +4825,28 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( if ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_VARIANT) && pVarResult - ) - args[argspos]= (DWORD)pVarResult; + ) + args[argspos]= (DWORD)pVarResult; argspos += 1; args2pos += arglen; } } - if (pFDesc->funcdesc.cParamsOpt < 0) - FIXME("Does not support optional parameters (%d)\n", - pFDesc->funcdesc.cParamsOpt - ); + if (func_desc->cParamsOpt < 0) + FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt); - res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4], - pFDesc->funcdesc.callconv, + res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4], + func_desc->callconv, numargs, args ); - HeapFree(GetProcessHeap(), 0, rgvarg); - if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) { args2pos = 0; - for (i=0;ifuncdesc.cParams-pDispParams->cArgs;i++) { - int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt); - TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc); - TYPEDESC i4_tdesc; - i4_tdesc.vt = VT_I4; + for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) { + int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt); + TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc); + TYPEDESC i4_tdesc; + i4_tdesc.vt = VT_I4; /* If we are a pointer to a variant, we are done already */ if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT)) @@ -4815,16 +4862,16 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( TYPEATTR *tattr; hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2); - if (hres) { + if (FAILED(hres)) { FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype); - return E_FAIL; + goto func_fail; } ITypeInfo_GetTypeAttr(tinfo2,&tattr); switch (tattr->typekind) { case TKIND_ENUM: - /* force the return type to be VT_I4 */ - tdesc = &i4_tdesc; - break; + /* force the return type to be VT_I4 */ + tdesc = &i4_tdesc; + break; case TKIND_ALIAS: TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt); tdesc = &(tattr->tdescAlias); @@ -4859,57 +4906,67 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( args2pos += arglen; } } +func_fail: + HeapFree(GetProcessHeap(), 0, rgvarg); HeapFree(GetProcessHeap(),0,args2); HeapFree(GetProcessHeap(),0,args); - return S_OK; + break; } case FUNC_DISPATCH: { IDispatch *disp; - HRESULT hr; - hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp); - if (hr) { + hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp); + if (SUCCEEDED(hres)) { + FIXME("Calling Invoke in IDispatch iface. untested!\n"); + hres = IDispatch_Invoke( + disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams, + pVarResult,pExcepInfo,pArgErr + ); + if (FAILED(hres)) + FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres); + IDispatch_Release(disp); + } else FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n"); - return hr; - } - FIXME("Calling Invoke in IDispatch iface. untested!\n"); - hr = IDispatch_Invoke( - disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams, - pVarResult,pExcepInfo,pArgErr - ); - if (hr) - FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr); - IDispatch_Release(disp); - return hr; + break; } default: - FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind); - return E_FAIL; - } - } else { - for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) { - if (pVDesc->vardesc.memid == memid) { - FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name))); - dump_TLBVarDesc(pVDesc); - break; - } - } - } - /* not found, look for it in inherited interfaces */ - if (This->TypeAttr.cImplTypes && - (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) { - /* recursive search */ - ITypeInfo *pTInfo; - HRESULT hr; - hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo); - if(SUCCEEDED(hr)){ - hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); - ITypeInfo_Release(pTInfo); - return hr; + FIXME("Unknown function invocation type %d\n", func_desc->funckind); + hres = E_FAIL; + break; } - WARN("Could not search inherited interface!\n"); + + ITypeInfo2_ReleaseFuncDesc(iface, func_desc); + return hres; + + } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) { + VARDESC *var_desc; + + hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc); + if(FAILED(hres)) return hres; + + FIXME("varseek: Found memid, but variable-based invoking not supported\n"); + dump_VARDESC(var_desc); + ITypeInfo2_ReleaseVarDesc(iface, var_desc); + return E_NOTIMPL; } - ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags); + + /* not found, look for it in inherited interfaces */ + ITypeInfo2_GetTypeKind(iface, &type_kind); + if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) { + HREFTYPE ref_type; + if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) { + /* recursive search */ + ITypeInfo *pTInfo; + hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo); + if(SUCCEEDED(hres)){ + hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); + ITypeInfo_Release(pTInfo); + return hres; + } + WARN("Could not search inherited interface!\n"); + } + } + ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags); return DISP_E_MEMBERNOTFOUND; } @@ -5176,6 +5233,9 @@ static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface, { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; TRACE("(%p)->(%p)\n", This, pTypeAttr); + if(This->TypeAttr.typekind == TKIND_ALIAS) + free_deep_typedesc(&pTypeAttr->tdescAlias); + HeapFree(GetProcessHeap(), 0, pTypeAttr); } /* ITypeInfo::ReleaseFuncDesc @@ -5242,18 +5302,18 @@ static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface, TLBFuncDesc *pFuncInfo; int i; HRESULT result; - /* FIXME: should check for invKind??? */ - for(i=0, pFuncInfo=This->funclist;pFuncInfo && - memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next); - if(pFuncInfo){ - *pFuncIndex=i; - result= S_OK; - }else{ - *pFuncIndex=0; - result=E_INVALIDARG; - } + + for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next) + if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind)) + break; + if(pFuncInfo) { + *pFuncIndex = i; + result = S_OK; + } else + result = TYPE_E_ELEMENTNOTFOUND; + TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This, - memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED"); + memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); return result; } @@ -5273,15 +5333,14 @@ static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface, for(i=0, pVarInfo=This->varlist; pVarInfo && memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next) ; - if(pVarInfo){ - *pVarIndex=i; - result= S_OK; - }else{ - *pVarIndex=0; - result=E_INVALIDARG; - } + if(pVarInfo) { + *pVarIndex = i; + result = S_OK; + } else + result = TYPE_E_ELEMENTNOTFOUND; + TRACE("(%p) memid 0x%08lx -> %s\n", This, - memid, SUCCEEDED(result)? "SUCCES":"FAILED"); + memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED"); return result; } diff --git a/reactos/lib/oleaut32/typelib16.c b/reactos/lib/oleaut32/typelib16.c index 7750d2761b4..b48debd1d94 100644 --- a/reactos/lib/oleaut32/typelib16.c +++ b/reactos/lib/oleaut32/typelib16.c @@ -39,7 +39,6 @@ #include "objbase.h" #include "ole2disp.h" -#include "typelib.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); diff --git a/reactos/lib/oleaut32/typelib2.c b/reactos/lib/oleaut32/typelib2.c index 72f37bda2f3..0c13afe92f2 100644 --- a/reactos/lib/oleaut32/typelib2.c +++ b/reactos/lib/oleaut32/typelib2.c @@ -48,10 +48,8 @@ #include "wine/unicode.h" #include "objbase.h" -#include "ole2disp.h" #include "typelib.h" #include "wine/debug.h" -#include "variant.h" WINE_DEFAULT_DEBUG_CHANNEL(typelib2); /* WINE_DEFAULT_DEBUG_CHANNEL(ole); */ @@ -150,7 +148,7 @@ typedef struct tagICreateTypeLib2Impl ICreateTypeLib2Vtbl *lpVtbl; ITypeLib2Vtbl *lpVtblTypeLib2; - UINT ref; + ULONG ref; WCHAR *filename; @@ -176,7 +174,7 @@ typedef struct tagICreateTypeInfo2Impl ICreateTypeInfo2Vtbl *lpVtbl; ITypeInfo2Vtbl *lpVtblTypeInfo2; - UINT ref; + ULONG ref; ICreateTypeLib2Impl *typelib; MSFT_TypeInfoBase *typeinfo; @@ -979,18 +977,25 @@ static int ctl2_encode_typedesc( break; case VT_CARRAY: + { /* FIXME: Make with the error checking. */ - FIXME("Array vartype, hacking badly.\n"); + int num_dims = tdesc->u.lpadesc->cDims, elements = 1, dim; ctl2_encode_typedesc(This, &tdesc->u.lpadesc->tdescElem, &target_type, width, alignment, NULL); - arrayoffset = ctl2_alloc_segment(This, MSFT_SEG_ARRAYDESC, 16, 0); + arrayoffset = ctl2_alloc_segment(This, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(int), 0); arraydata = (void *)&This->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset]; arraydata[0] = target_type; - arraydata[1] = 0x00080001; - arraydata[2] = 0x8; - arraydata[3] = 0; + arraydata[1] = num_dims; + arraydata[1] |= ((num_dims * 2 * sizeof(int)) << 16); + arraydata += 2; + for(dim = 0; dim < num_dims; dim++) { + arraydata[0] = tdesc->u.lpadesc->rgbounds[dim].cElements; + arraydata[1] = tdesc->u.lpadesc->rgbounds[dim].lLbound; + elements *= tdesc->u.lpadesc->rgbounds[dim].cElements; + arraydata += 2; + } typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0); typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; @@ -998,12 +1003,11 @@ static int ctl2_encode_typedesc( typedata[1] = arrayoffset; *encoded_tdesc = typeoffset; - *width = 8; - *alignment = 1; - *decoded_size = sizeof(ARRAYDESC); + *width = *width * elements; + *decoded_size = sizeof(ARRAYDESC) + (num_dims - 1) * sizeof(SAFEARRAYBOUND); break; - + } case VT_USERDEFINED: TRACE("USERDEFINED.\n"); for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { @@ -1138,10 +1142,11 @@ static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface( static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface) { ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->ref was %u\n",This, This->ref); + TRACE("(%p)->ref was %lu\n",This, ref - 1); - return ++(This->ref); + return ref; } /****************************************************************************** @@ -1152,12 +1157,11 @@ static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface) static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface) { ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - --(This->ref); + TRACE("(%p)->(%lu)\n",This, ref); - TRACE("(%p)->(%u)\n",This, This->ref); - - if (!This->ref) { + if (!ref) { if (This->typelib) { ICreateTypeLib2_fnRelease((ICreateTypeLib2 *)This->typelib); This->typelib = NULL; @@ -1168,7 +1172,7 @@ static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface) return 0; } - return This->ref; + return ref; } @@ -3005,10 +3009,11 @@ static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface( static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface) { ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->ref was %u\n",This, This->ref); + TRACE("(%p)->ref was %lu\n",This, ref - 1); - return ++(This->ref); + return ref; } /****************************************************************************** @@ -3019,30 +3024,25 @@ static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface) static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface) { ICreateTypeLib2Impl *This = (ICreateTypeLib2Impl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - --(This->ref); + TRACE("(%p)->(%lu)\n",This, ref); - TRACE("(%p)->(%u)\n",This, This->ref); - - if (!This->ref) { + if (!ref) { int i; for (i = 0; i < MSFT_SEG_MAX; i++) { - if (This->typelib_segment_data[i]) { - HeapFree(GetProcessHeap(), 0, This->typelib_segment_data[i]); - This->typelib_segment_data[i] = NULL; - } + HeapFree(GetProcessHeap(), 0, This->typelib_segment_data[i]); + This->typelib_segment_data[i] = NULL; } - if (This->filename) { - HeapFree(GetProcessHeap(), 0, This->filename); - This->filename = NULL; - } + HeapFree(GetProcessHeap(), 0, This->filename); + This->filename = NULL; while (This->typeinfos) { ICreateTypeInfo2Impl *typeinfo = This->typeinfos; This->typeinfos = typeinfo->next_typeinfo; - if (typeinfo->typedata) HeapFree(GetProcessHeap(), 0, typeinfo->typedata); + HeapFree(GetProcessHeap(), 0, typeinfo->typedata); HeapFree(GetProcessHeap(), 0, typeinfo); } @@ -3050,7 +3050,7 @@ static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface) return 0; } - return This->ref; + return ref; } diff --git a/reactos/lib/oleaut32/varformat.c b/reactos/lib/oleaut32/varformat.c index de43577dcd2..ba91af1231c 100644 --- a/reactos/lib/oleaut32/varformat.c +++ b/reactos/lib/oleaut32/varformat.c @@ -1310,12 +1310,10 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat, case FMT_NUM_YES_NO: boolFlag = VAR_BOOLYESNO; goto VARIANT_FormatNumber_Bool; - break; case FMT_NUM_ON_OFF: boolFlag = VAR_BOOLONOFF; goto VARIANT_FormatNumber_Bool; - break; case FMT_NUM_TRUE_FALSE: boolFlag = VAR_LOCALBOOL; @@ -1452,7 +1450,6 @@ VARIANT_FormatNumber_Bool: ERR("Unknown token 0x%02x!\n", *pToken); hRes = E_INVALIDARG; goto VARIANT_FormatNumber_Exit; - break; } if (localeValue) { @@ -1762,7 +1759,6 @@ static HRESULT VARIANT_FormatDate(LPVARIANT pVarIn, LPOLESTR lpszFormat, ERR("Unknown token 0x%02x!\n", *pToken); hRes = E_INVALIDARG; goto VARIANT_FormatDate_Exit; - break; } if (localeValue) { @@ -1916,7 +1912,6 @@ static HRESULT VARIANT_FormatString(LPVARIANT pVarIn, LPOLESTR lpszFormat, ERR("Unknown token 0x%02x!\n", *pToken); hRes = E_INVALIDARG; goto VARIANT_FormatString_Exit; - break; } pToken++; } diff --git a/reactos/lib/oleaut32/variant.c b/reactos/lib/oleaut32/variant.c index 3ace2b7bdf7..c6d5e58a3d8 100644 --- a/reactos/lib/oleaut32/variant.c +++ b/reactos/lib/oleaut32/variant.c @@ -764,24 +764,24 @@ static inline size_t VARIANT_DataSize(const VARIANT* pv) switch (V_TYPE(pv)) { case VT_I1: - case VT_UI1: return sizeof(BYTE); break; + case VT_UI1: return sizeof(BYTE); case VT_I2: - case VT_UI2: return sizeof(SHORT); break; + case VT_UI2: return sizeof(SHORT); case VT_INT: case VT_UINT: case VT_I4: - case VT_UI4: return sizeof(LONG); break; + case VT_UI4: return sizeof(LONG); case VT_I8: - case VT_UI8: return sizeof(LONGLONG); break; - case VT_R4: return sizeof(float); break; - case VT_R8: return sizeof(double); break; - case VT_DATE: return sizeof(DATE); break; - case VT_BOOL: return sizeof(VARIANT_BOOL); break; + case VT_UI8: return sizeof(LONGLONG); + case VT_R4: return sizeof(float); + case VT_R8: return sizeof(double); + case VT_DATE: return sizeof(DATE); + case VT_BOOL: return sizeof(VARIANT_BOOL); case VT_DISPATCH: case VT_UNKNOWN: - case VT_BSTR: return sizeof(void*); break; - case VT_CY: return sizeof(CY); break; - case VT_ERROR: return sizeof(SCODE); break; + case VT_BSTR: return sizeof(void*); + case VT_CY: return sizeof(CY); + case VT_ERROR: return sizeof(SCODE); } TRACE("Shouldn't be called for vt %s%s!\n", debugstr_VT(pv), debugstr_VF(pv)); return 0; @@ -3925,7 +3925,7 @@ HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut) * Failure: An HRESULT error code indicating the error. * * NOTES - * - Strictly speaking, this function performs a bitwise ones compliment + * - Strictly speaking, this function performs a bitwise ones complement * on the variants value (after possibly converting to VT_I4, see below). * This only behaves like a boolean not operation if the value in * pVarIn is either VARIANT_TRUE or VARIANT_FALSE and the type is signed. diff --git a/reactos/lib/opengl32/gl.c b/reactos/lib/opengl32/gl.c index fc05d3e5b24..edf981423eb 100644 --- a/reactos/lib/opengl32/gl.c +++ b/reactos/lib/opengl32/gl.c @@ -61,11 +61,12 @@ int STDCALL glEmptyFunc56( long l1, long l2, long l3, long l4, long l5, #if defined(_M_IX86) # define FOO(x) #x # define X(func, ret, typeargs, args, icdidx, tebidx, stack) \ -__asm__(".globl _"#func"@"#stack "\n\t" \ +__asm__(".align 4" "\n\t" \ + ".globl _"#func"@"#stack "\n\t" \ "_"#func"@"#stack":" "\n\t" \ - " movl %fs:0x18, %eax" "\n\t" \ - " movl 0xbe8(%eax), %eax" "\n\t" \ - " jmp *"FOO((icdidx*4))"(%eax)" "\n\t"); + " movl %fs:0x18, %eax" "\n\t" \ + " movl 0xbe8(%eax), %eax" "\n\t" \ + " jmp *"FOO((icdidx*4))"(%eax)" "\n\t"); GLFUNCS_MACRO # undef FOO @@ -74,19 +75,19 @@ GLFUNCS_MACRO # define X(func, ret, typeargs, args, icdidx, tebidx, stack) \ ret STDCALL func typeargs \ { \ - PROC *table; \ - PROC fn; \ - if (tebidx >= 0 && 0) \ - { \ - table = (PROC *)NtCurrentTeb()->glDispatchTable; \ - fn = table[tebidx]; \ - } \ - else \ - { \ - table = (PROC *)NtCurrentTeb()->glTable; \ - fn = table[icdidx]; \ - } \ - return (ret)((ret(*)typeargs)fn)args; \ + PROC *table; \ + PROC fn; \ + if (tebidx >= 0 && 0) \ + { \ + table = (PROC *)NtCurrentTeb()->glDispatchTable; \ + fn = table[tebidx]; \ + } \ + else \ + { \ + table = (PROC *)NtCurrentTeb()->glTable; \ + fn = table[icdidx]; \ + } \ + return (ret)((ret(*)typeargs)fn)args; \ } GLFUNCS_MACRO diff --git a/reactos/lib/opengl32/wgl.c b/reactos/lib/opengl32/wgl.c index 549a4207937..6d17b172feb 100644 --- a/reactos/lib/opengl32/wgl.c +++ b/reactos/lib/opengl32/wgl.c @@ -10,6 +10,7 @@ #define WIN32_LEAN_AND_MEAN #include +#include #include #include #include "teb.h" @@ -334,6 +335,15 @@ ROSGL_ICDForHDC( HDC hdc ) } /* load driver (or get a reference) */ dcdata->icd = OPENGL32_LoadICD( info.driver_name ); + if (dcdata->icd == NULL) + { + WCHAR Buffer[256]; + snwprintf(Buffer, sizeof(Buffer)/sizeof(WCHAR), + L"Couldn't load driver \"%s\".", driverName); + MessageBox(WindowFromDC( hdc ), Buffer, + L"OPENGL32.dll: Warning", + MB_OK | MB_ICONWARNING); + } } return dcdata->icd; @@ -398,7 +408,6 @@ ROSGL_SetContextCallBack( const ICDTable *table ) #undef X DBGPRINT( "Done." ); -/* DBGBREAK();*/ return ERROR_SUCCESS; } @@ -894,7 +903,6 @@ rosglMakeCurrent( HDC hdc, HGLRC hglrc ) if (glrc->hglrc != NULL) { DBGPRINT( "Info: Calling DrvSetContext!" ); - DBGBREAK(); icdTable = glrc->icd->DrvSetContext( hdc, glrc->hglrc, ROSGL_SetContextCallBack ); if (icdTable == NULL) diff --git a/reactos/lib/psapi/makefile b/reactos/lib/psapi/makefile index e6a14634e6e..bf0eeea1d58 100644 --- a/reactos/lib/psapi/makefile +++ b/reactos/lib/psapi/makefile @@ -6,12 +6,12 @@ TARGET_TYPE = dynlink TARGET_NAME = psapi -TARGET_SDKLIBS = epsapi.a ntdll.a kernel32.a +TARGET_SDKLIBS = pseh.a epsapi.a ntdll.a kernel32.a TARGET_CFLAGS = -I./include -Wall -Werror # require os code to explicitly request A/W version of structs/functions -TARGET_CFLAGS += -D_DISABLE_TIDENTS +TARGET_CFLAGS += -D_DISABLE_TIDENTS -D_SEH_NO_NATIVE_NLG TARGET_LFLAGS = -nostartfiles -nostdlib @@ -19,11 +19,7 @@ TARGET_BASE = $(TARGET_BASE_LIB_PSAPI) TARGET_PCH = precomp.h -TARGET_OBJECTS = \ - misc/dllmain.o \ - misc/malloc.o \ - misc/stubs.o \ - misc/win32.o +TARGET_OBJECTS = malloc.o psapi.o DEP_OBJECTS = $(TARGET_OBJECTS) diff --git a/reactos/lib/psapi/misc/malloc.c b/reactos/lib/psapi/malloc.c similarity index 100% rename from reactos/lib/psapi/misc/malloc.c rename to reactos/lib/psapi/malloc.c diff --git a/reactos/lib/psapi/misc/dllmain.c b/reactos/lib/psapi/misc/dllmain.c deleted file mode 100644 index f3d489c5a28..00000000000 --- a/reactos/lib/psapi/misc/dllmain.c +++ /dev/null @@ -1,34 +0,0 @@ -/* $Id$ -*/ -/* - * COPYRIGHT: None - * LICENSE: Public domain - * PROJECT: ReactOS system libraries - * FILE: reactos/lib/psapi/misc/malloc.c - * PURPOSE: PSAPI.DLL main procedure - * PROGRAMMER: KJK::Hyperion - * UPDATE HISTORY: - * 28/11/2001: Created (Emanuele Aliberti ) - * 30/08/2002: Minimal tweak (KJK::Hyperion ) - */ -#include "precomp.h" - -#define NDEBUG -#include - -BOOLEAN STDCALL DllMain -( - PVOID hinstDll, - ULONG dwReason, - PVOID reserved -) -{ - if(dwReason == DLL_PROCESS_ATTACH) - /* don't bother calling the entry point on thread startup - PSAPI.DLL doesn't - store any per-thread data */ - LdrDisableThreadCalloutsForDll(hinstDll); - - return (TRUE); -} - -/* EOF */ diff --git a/reactos/lib/psapi/misc/stubs.c b/reactos/lib/psapi/misc/stubs.c deleted file mode 100644 index 0d7abd97d7a..00000000000 --- a/reactos/lib/psapi/misc/stubs.c +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id$ */ -#include "precomp.h" - -#define NDEBUG -#include - - -/* - * @unimplemented - */ -BOOL -STDCALL -GetProcessMemoryInfo(HANDLE Process, - PPROCESS_MEMORY_COUNTERS ppsmemCounters, - DWORD cb) -{ - DPRINT1("PSAPI: GetProcessMemoryInfo is UNIMPLEMENTED!\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -STDCALL -QueryWorkingSet(HANDLE hProcess, - PVOID pv, - DWORD cb) -{ - DPRINT1("PSAPI: QueryWorkingSet is UNIMPLEMENTED!\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* EOF */ diff --git a/reactos/lib/psapi/precomp.h b/reactos/lib/psapi/precomp.h index 551dc305239..f0f87b357f2 100644 --- a/reactos/lib/psapi/precomp.h +++ b/reactos/lib/psapi/precomp.h @@ -11,4 +11,4 @@ #include #include #include - +#include diff --git a/reactos/lib/psapi/misc/win32.c b/reactos/lib/psapi/psapi.c similarity index 91% rename from reactos/lib/psapi/misc/win32.c rename to reactos/lib/psapi/psapi.c index 34a2c085f1e..34b79d10fb6 100644 --- a/reactos/lib/psapi/misc/win32.c +++ b/reactos/lib/psapi/psapi.c @@ -17,6 +17,22 @@ #define NDEBUG #include +BOOLEAN +WINAPI +DllMain(HINSTANCE hDllHandle, + DWORD nReason, + LPVOID Reserved) +{ + switch(nReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hDllHandle); + break; + } + + return TRUE; +} + /* INTERNAL *******************************************************************/ typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT @@ -67,7 +83,7 @@ EnumProcessesCallback(IN PSYSTEM_PROCESSES CurrentProcess, } /* return current process */ - *Context->lpidProcess = CurrentProcess->ProcessId; + *Context->lpidProcess = (DWORD)CurrentProcess->ProcessId; /* go to next array slot */ Context->lpidProcess++; @@ -505,10 +521,10 @@ exitWithStatus: } /* image size */ - if(nSize >= sizeof(CurrentModule->SizeOfImage)) + if(nSize >= sizeof(CurrentModule->ResidentSize)) { - Context->lpmodinfo->SizeOfImage = CurrentModule->SizeOfImage; - nSize -= sizeof(CurrentModule->SizeOfImage); + Context->lpmodinfo->SizeOfImage = CurrentModule->ResidentSize; + nSize -= sizeof(CurrentModule->ResidentSize); } /* entry point */ @@ -935,7 +951,7 @@ InitializeProcessForWsWatch(HANDLE hProcess) 0); if(!NT_SUCCESS(Status)) { - SetLastError(RtlNtStatusToDosError(Status)); + SetLastErrorByStatus(Status); return FALSE; } @@ -961,7 +977,7 @@ GetWsChanges(HANDLE hProcess, NULL); if(!NT_SUCCESS(Status)) { - SetLastError(RtlNtStatusToDosError(Status)); + SetLastErrorByStatus(Status); return FALSE; } @@ -1302,4 +1318,94 @@ GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation, return TRUE; } + +/* + * @implemented + */ +BOOL +STDCALL +GetProcessMemoryInfo(HANDLE Process, + PPROCESS_MEMORY_COUNTERS ppsmemCounters, + DWORD cb) +{ + NTSTATUS Status; + VM_COUNTERS vmc; + BOOL Ret = FALSE; + + /* XP's implementation secures access to ppsmemCounters in SEH, we should behave + similar so we can return the proper error codes when bad pointers are passed + to this function! */ + + _SEH_TRY + { + if(cb < sizeof(PROCESS_MEMORY_COUNTERS)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + _SEH_LEAVE; + } + + /* ppsmemCounters->cb isn't checked at all! */ + + Status = NtQueryInformationProcess(Process, + ProcessVmCounters, + &vmc, + sizeof(vmc), + NULL); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + _SEH_LEAVE; + } + + /* fill the structure with the collected information, in case of bad pointers + SEH will catch the exception and set the appropriate error code */ + ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS); + ppsmemCounters->PageFaultCount = vmc.PageFaultCount; + ppsmemCounters->PeakWorkingSetSize = vmc.PeakWorkingSetSize; + ppsmemCounters->WorkingSetSize = vmc.WorkingSetSize; + ppsmemCounters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage; + ppsmemCounters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage; + ppsmemCounters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage; + ppsmemCounters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage; + ppsmemCounters->PagefileUsage = vmc.PagefileUsage; + ppsmemCounters->PeakPagefileUsage = vmc.PeakPagefileUsage; + + Ret = TRUE; + } + _SEH_HANDLE + { + SetLastErrorByStatus(_SEH_GetExceptionCode()); + } + _SEH_END; + + return Ret; +} + + +/* + * @implemented + */ +BOOL +STDCALL +QueryWorkingSet(HANDLE hProcess, + PVOID pv, + DWORD cb) +{ + NTSTATUS Status; + + Status = NtQueryVirtualMemory(hProcess, + NULL, + MemoryWorkingSetList, + pv, + cb, + NULL); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + /* EOF */ diff --git a/reactos/lib/psapi/psapi.xml b/reactos/lib/psapi/psapi.xml index 61f58efae7e..84f5630fbe7 100644 --- a/reactos/lib/psapi/psapi.xml +++ b/reactos/lib/psapi/psapi.xml @@ -3,14 +3,11 @@ . include + epsapi + pseh ntdll kernel32 - epsapi - - dllmain.c - malloc.c - stubs.c - win32.c - + malloc.c + psapi.c psapi.rc diff --git a/reactos/lib/pseh/i386/setjmp.asm b/reactos/lib/pseh/i386/setjmp.asm index 1467459f02a..50c8d4a0561 100644 --- a/reactos/lib/pseh/i386/setjmp.asm +++ b/reactos/lib/pseh/i386/setjmp.asm @@ -65,4 +65,25 @@ __SEHLongJmp@8: mov edi, [ecx+20] jmp edx + +global SEHLongJmp_KeepEsp +global __SEHLongJmp_KeepEsp@8 +SEHLongJmp_KeepEsp: +__SEHLongJmp_KeepEsp@8: + ; return value + mov eax, [esp+8] + + ; jump buffer + mov ecx, [esp+4] + + ; restore the saved context + mov ebp, [ecx+0] +; don't restore esp +; mov esp, [ecx+4] + mov edx, [ecx+8] + mov ebx, [ecx+12] + mov esi, [ecx+16] + mov edi, [ecx+20] + jmp edx + ; EOF diff --git a/reactos/lib/richedit/reader.c b/reactos/lib/richedit/reader.c index 2cb6d36da20..aab017caa4e 100644 --- a/reactos/lib/richedit/reader.c +++ b/reactos/lib/richedit/reader.c @@ -98,9 +98,9 @@ static void ReadStyleSheet (RTF_Info *); static void ReadInfoGroup (RTF_Info *); static void ReadPictGroup (RTF_Info *); static void ReadObjGroup (RTF_Info *); -static void LookupInit (); +static void LookupInit (void); static void Lookup (RTF_Info *, char *); -static int Hash (); +static int Hash (char*); static void CharSetInit (RTF_Info *); static void ReadCharSetMaps (RTF_Info *); @@ -2451,7 +2451,7 @@ static RTFKey rtfKey[] = * Initialize lookup table hash values. Only need to do this once. */ -static void LookupInit() +static void LookupInit(void) { static int inited = 0; RTFKey *rp; @@ -2546,8 +2546,7 @@ char *p; void RTFFree(char *p) { - if (p != (char *) NULL) - HeapFree(RICHED32_hHeap, 0, p); + HeapFree(RICHED32_hHeap, 0, p); } diff --git a/reactos/lib/richedit/richedit.c b/reactos/lib/richedit/richedit.c index c47cd4d7e9e..648c7be9257 100644 --- a/reactos/lib/richedit/richedit.c +++ b/reactos/lib/richedit/richedit.c @@ -778,7 +778,7 @@ VOID RICHED32_Register(void) ZeroMemory(&wndClass, sizeof(WNDCLASSA)); wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; - wndClass.lpfnWndProc = (WNDPROC)RICHED32_WindowProc; + wndClass.lpfnWndProc = RICHED32_WindowProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = RTFInfoOffset + sizeof(RTFControl_Info*); wndClass.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); diff --git a/reactos/lib/richedit/rtf2text.h b/reactos/lib/richedit/rtf2text.h index 8dec24c2316..a0df850a78a 100644 --- a/reactos/lib/richedit/rtf2text.h +++ b/reactos/lib/richedit/rtf2text.h @@ -1,2 +1,2 @@ -void WriterInit (); -int BeginFile (); +void WriterInit (RTF_Info *); +int BeginFile (RTF_Info *); diff --git a/reactos/lib/rosky/libskygi/libskygi.c b/reactos/lib/rosky/libskygi/libskygi.c index 0d0e25c23bf..5f7c433b62d 100644 --- a/reactos/lib/rosky/libskygi/libskygi.c +++ b/reactos/lib/rosky/libskygi/libskygi.c @@ -900,7 +900,7 @@ GC_blit_from_DIB(GC *Gc, { int Result; HDC hSrcDC; - HBITMAP hOldBitmap; + HBITMAP hOldBitmap = NULL; DBG("GC_blit_from_DIB(0x%x, 0x%x, 0x%x, 0x%x)\n", Gc, Dib, X, Y); @@ -1165,7 +1165,7 @@ GI_messagebox(s_window *Window, MbFlags = MB_YESNOCANCEL; else if (Flags & WGF_MB_YESNO) MbFlags = MB_YESNO; - else if (Flags & WGF_MB_OK) + else /* if (Flags & WGF_MB_OK) */ MbFlags = MB_OK; MbFlags |= (Flags & WGF_MB_ICON_INFO) ? MB_ICONASTERISK : 0; MbFlags |= (Flags & WGF_MB_ICON_ASK) ? MB_ICONQUESTION : 0; diff --git a/reactos/lib/rosrtl/file/path.c b/reactos/lib/rosrtl/file/path.c new file mode 100644 index 00000000000..595f9ee0f59 --- /dev/null +++ b/reactos/lib/rosrtl/file/path.c @@ -0,0 +1,100 @@ +#include +#include + + +/*********************************************************************** + * MakeSureDirectoryPathExistsExA + * + * If a dir is at the end and the path ends with a backslash, FileAtEnd + * is ignored. If the path doesn't end with a backslash, FileAtEnd is + * used to determine if the last part of the path is a file name or a + * directory. + * + * Path may be absolute or relative to current dir. + */ +BOOL STDCALL MakeSureDirectoryPathExistsExA(LPCSTR DirPath, BOOL FileAtEnd) +{ + char Path[MAX_PATH]; + char *SlashPos = Path; + char Slash; + BOOL bRes; + + strcpy(Path, DirPath); + + while((SlashPos=strpbrk(SlashPos+1,"\\/"))) + { + Slash = *SlashPos; + *SlashPos = 0; + + bRes = CreateDirectoryA(Path, NULL); + if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS) + { + return FALSE; + } + + *SlashPos = Slash; + + if (*(SlashPos+1) == 0) return TRUE; + } + + if (!FileAtEnd) + { + bRes = CreateDirectoryA(Path, NULL); + if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS) + { + return FALSE; + } + } + + return TRUE; +} + + + + +/*********************************************************************** + * MakeSureDirectoryPathExistsExW + * + * If a dir is at the end and the path ends with a backslash, FileAtEnd + * is ignored. If the path doesn't end with a backslash, FileAtEnd is + * used to determine if the last part of the path is a file name or a + * directory. + * + * Path may be absolute or relative to current dir. + */ +BOOL STDCALL MakeSureDirectoryPathExistsExW(LPCWSTR DirPath, BOOL FileAtEnd) +{ + WCHAR Path[MAX_PATH]; + WCHAR *SlashPos = Path; + WCHAR Slash; + BOOL bRes; + + wcscpy(Path, DirPath); + + while((SlashPos=wcspbrk(SlashPos+1,L"\\/"))) + { + Slash = *SlashPos; + *SlashPos = 0; + + bRes = CreateDirectoryW(Path, NULL); + if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS) + { + return FALSE; + } + + *SlashPos = Slash; + + if (*(SlashPos+1) == 0) return TRUE; + } + + if (!FileAtEnd) + { + bRes = CreateDirectoryW(Path, NULL); + if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS) + { + return FALSE; + } + } + + return TRUE; +} diff --git a/reactos/lib/rosrtl/makefile b/reactos/lib/rosrtl/makefile index 42fd621ab52..6c0f6acbffc 100644 --- a/reactos/lib/rosrtl/makefile +++ b/reactos/lib/rosrtl/makefile @@ -30,7 +30,8 @@ MISC_OBJECTS = \ misc/qsort.o FILE_OBJECTS = \ - file/sparse.o + file/sparse.o \ + file/path.o RECMUTEX_OBJECTS = recmutex/recmutex.o diff --git a/reactos/lib/rossym/Makefile b/reactos/lib/rossym/Makefile new file mode 100644 index 00000000000..8fad567eef3 --- /dev/null +++ b/reactos/lib/rossym/Makefile @@ -0,0 +1,33 @@ +PATH_TO_TOP = ../.. + +TARGET_TYPE = library + +TARGET_NAME = rossym + +include $(PATH_TO_TOP)/config + +TARGET_CFLAGS = -Wall -Werror -ffreestanding -D__USE_W32API + +TARGET_OBJECTS = \ + delete.o \ + find.o \ + fromfile.o \ + frommem.o \ + fromraw.o \ + getraw.o \ + init.o \ + initkm.o \ + initum.o \ + zwfile.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +DEP_OBJECTS := $(TARGET_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) + +include $(PATH_TO_TOP)/tools/depend.mk + +# EOF diff --git a/reactos/lib/rossym/delete.c b/reactos/lib/rossym/delete.c new file mode 100644 index 00000000000..88740a63c4d --- /dev/null +++ b/reactos/lib/rossym/delete.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/delete.c + * PURPOSE: Free rossym info + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +VOID +RosSymDelete(PROSSYM_INFO RosSymInfo) +{ + RosSymFreeMem(RosSymInfo); +} + +/* EOF */ diff --git a/reactos/lib/rossym/find.c b/reactos/lib/rossym/find.c new file mode 100644 index 00000000000..73c0681eaed --- /dev/null +++ b/reactos/lib/rossym/find.c @@ -0,0 +1,150 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/find.c + * PURPOSE: Find symbol info for an address + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ +/* + * Parts of this file based on work Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +static PROSSYM_ENTRY +FindEntry(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress) +{ + /* + * Perform a binary search. + * + * The code below is a bit sneaky. After a comparison fails, we + * divide the work in half by moving either left or right. If lim + * is odd, moving left simply involves halving lim: e.g., when lim + * is 5 we look at item 2, so we change lim to 2 so that we will + * look at items 0 & 1. If lim is even, the same applies. If lim + * is odd, moving right again involes halving lim, this time moving + * the base up one item past p: e.g., when lim is 5 we change base + * to item 3 and make lim 2 so that we will look at items 3 and 4. + * If lim is even, however, we have to shrink it by one before + * halving: e.g., when lim is 4, we still looked at item 2, so we + * have to make lim 3, then halve, obtaining 1, so that we will only + * look at item 3. + */ + PROSSYM_ENTRY Base = RosSymInfo->Symbols; + ULONG Lim; + PROSSYM_ENTRY Mid, Low; + + if (RelativeAddress < Base->Address) + { + return NULL; + } + + Low = Base; + for (Lim = RosSymInfo->SymbolsCount; Lim != 0; Lim >>= 1) + { + Mid = Base + (Lim >> 1); + if (RelativeAddress == Mid->Address) + { + return Mid; + } + if (Mid->Address < RelativeAddress) /* key > mid: move right */ + { + Low = Mid; + Base = Mid + 1; + Lim--; + } /* else move left */ + } + + return Low; +} + + +BOOLEAN +RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, + ULONG_PTR RelativeAddress, + ULONG *LineNumber, + char *FileName, + char *FunctionName) +{ + PROSSYM_ENTRY RosSymEntry; + + DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress); + + if (RosSymInfo->Symbols == NULL || RosSymInfo->SymbolsCount == 0 || + RosSymInfo->Strings == NULL || RosSymInfo->StringsLength == 0) + { +__asm__("int $3\n"); + DPRINT1("Uninitialized RosSymInfo\n"); + return FALSE; + } + + ASSERT(LineNumber || FileName || FunctionName); + + /* find symbol entry for function */ + RosSymEntry = FindEntry(RosSymInfo, RelativeAddress); + + if (NULL == RosSymEntry) + { + DPRINT("None of the requested information was found!\n"); + return FALSE; + } + + if (LineNumber != NULL) + { + *LineNumber = RosSymEntry->SourceLine; + } + if (FileName != NULL) + { + PCHAR Name = ""; + if (RosSymEntry->FileOffset != 0) + { + Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FileOffset; + } + strcpy(FileName, Name); + } + if (FunctionName != NULL) + { + PCHAR Name = ""; + if (RosSymEntry->FunctionOffset != 0) + { + Name = (PCHAR) RosSymInfo->Strings + RosSymEntry->FunctionOffset; + } + strcpy(FunctionName, Name); + } + + return TRUE; +} + +/* EOF */ diff --git a/reactos/lib/rossym/fromfile.c b/reactos/lib/rossym/fromfile.c new file mode 100644 index 00000000000..d02891d42d0 --- /dev/null +++ b/reactos/lib/rossym/fromfile.c @@ -0,0 +1,146 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/fromfile.c + * PURPOSE: Creating rossym info from a file + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +BOOLEAN +RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo) +{ + IMAGE_DOS_HEADER DosHeader; + IMAGE_NT_HEADERS NtHeaders; + PIMAGE_SECTION_HEADER SectionHeaders, SectionHeader; + unsigned SectionIndex; + char SectionName[IMAGE_SIZEOF_SHORT_NAME]; + ROSSYM_HEADER RosSymHeader; + + /* Load DOS header */ + if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER))) + { + DPRINT1("Failed to read DOS header\n"); + return FALSE; + } + if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader)) + { + DPRINT1("Image doesn't have a valid DOS header\n"); + return FALSE; + } + + /* Load NT headers */ + if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew)) + { + DPRINT1("Failed seeking to NT headers\n"); + return FALSE; + } + if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS))) + { + DPRINT1("Failed to read NT headers\n"); + return FALSE; + } + if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders)) + { + DPRINT1("Image doesn't have a valid PE header\n"); + return FALSE; + } + + /* Load section headers */ + if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) - + (char *) &NtHeaders + DosHeader.e_lfanew)) + { + DPRINT1("Failed seeking to section headers\n"); + return FALSE; + } + SectionHeaders = RosSymAllocMem(NtHeaders.FileHeader.NumberOfSections + * sizeof(IMAGE_SECTION_HEADER)); + if (NULL == SectionHeaders) + { + DPRINT1("Failed to allocate memory for %u section headers\n", + NtHeaders.FileHeader.NumberOfSections); + return FALSE; + } + if (! RosSymReadFile(FileContext, SectionHeaders, + NtHeaders.FileHeader.NumberOfSections + * sizeof(IMAGE_SECTION_HEADER))) + { + RosSymFreeMem(SectionHeaders); + DPRINT1("Failed to read section headers\n"); + return FALSE; + } + + /* Search for the section header */ + strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME); + SectionHeader = SectionHeaders; + for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections; SectionIndex++) + { + if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME)) + { + break; + } + SectionHeader++; + } + if (NtHeaders.FileHeader.NumberOfSections <= SectionIndex) + { + RosSymFreeMem(SectionHeaders); + DPRINT("No %s section found\n", ROSSYM_SECTION_NAME); + return FALSE; + } + + /* Load rossym header */ + if (! RosSymSeekFile(FileContext, SectionHeader->PointerToRawData)) + { + RosSymFreeMem(SectionHeaders); + DPRINT1("Failed seeking to section data\n"); + return FALSE; + } + RosSymFreeMem(SectionHeaders); + if (! RosSymReadFile(FileContext, &RosSymHeader, sizeof(ROSSYM_HEADER))) + { + DPRINT1("Failed to read rossym header\n"); + return FALSE; + } + if (RosSymHeader.SymbolsOffset < sizeof(ROSSYM_HEADER) + || RosSymHeader.StringsOffset < RosSymHeader.SymbolsOffset + RosSymHeader.SymbolsLength + || 0 != (RosSymHeader.SymbolsLength % sizeof(ROSSYM_ENTRY))) + { + DPRINT1("Invalid ROSSYM_HEADER\n"); + return FALSE; + } + + *RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER) + + RosSymHeader.StringsOffset + RosSymHeader.StringsLength + 1); + if (NULL == *RosSymInfo) + { + DPRINT1("Failed to allocate memory for rossym\n"); + return FALSE; + } + (*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO) + - sizeof(ROSSYM_HEADER) + RosSymHeader.SymbolsOffset); + (*RosSymInfo)->SymbolsCount = RosSymHeader.SymbolsLength / sizeof(ROSSYM_ENTRY); + (*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) - sizeof(ROSSYM_HEADER) + + RosSymHeader.StringsOffset; + (*RosSymInfo)->StringsLength = RosSymHeader.StringsLength; + if (! RosSymReadFile(FileContext, *RosSymInfo + 1, + RosSymHeader.StringsOffset + RosSymHeader.StringsLength + - sizeof(ROSSYM_HEADER))) + { + DPRINT1("Failed to read rossym headers\n"); + return FALSE; + } + /* Make sure the last string is null terminated, we allocated an extra byte for that */ + (*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0'; + + return TRUE; +} + +/* EOF */ diff --git a/reactos/lib/rossym/frommem.c b/reactos/lib/rossym/frommem.c new file mode 100644 index 00000000000..866347e4822 --- /dev/null +++ b/reactos/lib/rossym/frommem.c @@ -0,0 +1,81 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/frommem.c + * PURPOSE: Creating rossym info from an in-memory image + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +BOOLEAN +RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, PROSSYM_INFO *RosSymInfo) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NtHeaders; + PIMAGE_SECTION_HEADER SectionHeader; + unsigned SectionIndex; + char SectionName[IMAGE_SIZEOF_SHORT_NAME]; + + /* Check if MZ header is valid */ + DosHeader = (PIMAGE_DOS_HEADER) ImageStart; + if (ImageSize < sizeof(IMAGE_DOS_HEADER) + || ! ROSSYM_IS_VALID_DOS_HEADER(DosHeader)) + { + DPRINT1("Image doesn't have a valid DOS header\n"); + return FALSE; + } + + /* Locate NT header */ + NtHeaders = (PIMAGE_NT_HEADERS)((char *) ImageStart + DosHeader->e_lfanew); + if (ImageSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + || ! ROSSYM_IS_VALID_NT_HEADERS(NtHeaders)) + { + DPRINT1("Image doesn't have a valid PE header\n"); + return FALSE; + } + + /* Search for the section header */ + SectionHeader = IMAGE_FIRST_SECTION(NtHeaders); + if (ImageSize < (char *) (SectionHeader + NtHeaders->FileHeader.NumberOfSections) + - (char *) ImageStart) + { + DPRINT1("Image doesn't have valid section headers\n"); + return FALSE; + } + strncpy(SectionName, ROSSYM_SECTION_NAME, IMAGE_SIZEOF_SHORT_NAME); + for (SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections; SectionIndex++) + { + if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME)) + { + break; + } + SectionHeader++; + } + if (NtHeaders->FileHeader.NumberOfSections <= SectionIndex) + { + DPRINT("No %s section found\n", ROSSYM_SECTION_NAME); + return FALSE; + } + + /* Locate the section itself */ + if (ImageSize < SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData + || SectionHeader->SizeOfRawData < sizeof(ROSSYM_HEADER)) + { + DPRINT1("Invalid %s section\n", ROSSYM_SECTION_NAME); + return FALSE; + } + + /* Load it */ + return RosSymCreateFromRaw((char *) ImageStart + SectionHeader->PointerToRawData, + SectionHeader->SizeOfRawData, RosSymInfo); +} + +/* EOF */ diff --git a/reactos/lib/rossym/fromraw.c b/reactos/lib/rossym/fromraw.c new file mode 100644 index 00000000000..7007a1b6975 --- /dev/null +++ b/reactos/lib/rossym/fromraw.c @@ -0,0 +1,55 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/frommem.c + * PURPOSE: Creating rossym info from an in-memory image + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +BOOLEAN +RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize, PROSSYM_INFO *RosSymInfo) +{ + PROSSYM_HEADER RosSymHeader; + + RosSymHeader = (PROSSYM_HEADER) RawData; + if (RosSymHeader->SymbolsOffset < sizeof(ROSSYM_HEADER) + || RosSymHeader->StringsOffset < RosSymHeader->SymbolsOffset + RosSymHeader->SymbolsLength + || DataSize < RosSymHeader->StringsOffset + RosSymHeader->StringsLength + || 0 != (RosSymHeader->SymbolsLength % sizeof(ROSSYM_ENTRY))) + { + DPRINT1("Invalid ROSSYM_HEADER\n"); + return FALSE; + } + + /* Copy */ + *RosSymInfo = RosSymAllocMem(sizeof(ROSSYM_INFO) + RosSymHeader->SymbolsLength + + RosSymHeader->StringsLength + 1); + if (NULL == *RosSymInfo) + { + DPRINT1("Failed to allocate memory for rossym\n"); + return FALSE; + } + (*RosSymInfo)->Symbols = (PROSSYM_ENTRY)((char *) *RosSymInfo + sizeof(ROSSYM_INFO)); + (*RosSymInfo)->SymbolsCount = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); + (*RosSymInfo)->Strings = (PCHAR) *RosSymInfo + sizeof(ROSSYM_INFO) + RosSymHeader->SymbolsLength; + (*RosSymInfo)->StringsLength = RosSymHeader->StringsLength; + memcpy((*RosSymInfo)->Symbols, (char *) RosSymHeader + RosSymHeader->SymbolsOffset, + RosSymHeader->SymbolsLength); + memcpy((*RosSymInfo)->Strings, (char *) RosSymHeader + RosSymHeader->StringsOffset, + RosSymHeader->StringsLength); + /* Make sure the last string is null terminated, we allocated an extra byte for that */ + (*RosSymInfo)->Strings[(*RosSymInfo)->StringsLength] = '\0'; + + return TRUE; +} + +/* EOF */ diff --git a/reactos/lib/rossym/getraw.c b/reactos/lib/rossym/getraw.c new file mode 100644 index 00000000000..dd6cb17ab99 --- /dev/null +++ b/reactos/lib/rossym/getraw.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/getraw.c + * PURPOSE: Convert rossym info to raw external format + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +ULONG +RosSymGetRawDataLength(PROSSYM_INFO RosSymInfo) +{ + return sizeof(ROSSYM_HEADER) + + RosSymInfo->SymbolsCount * sizeof(ROSSYM_ENTRY) + + RosSymInfo->StringsLength; +} + +VOID +RosSymGetRawData(PROSSYM_INFO RosSymInfo, PVOID RawData) +{ + PROSSYM_HEADER RosSymHeader; + + RosSymHeader = (PROSSYM_HEADER) RawData; + RosSymHeader->SymbolsOffset = sizeof(ROSSYM_HEADER); + RosSymHeader->SymbolsLength = RosSymInfo->SymbolsCount * sizeof(ROSSYM_ENTRY); + RosSymHeader->StringsOffset = RosSymHeader->SymbolsOffset + RosSymHeader->SymbolsLength; + RosSymHeader->StringsLength = RosSymInfo->StringsLength; + + memcpy((char *) RawData + RosSymHeader->SymbolsOffset, RosSymInfo->Symbols, + RosSymHeader->SymbolsLength); + memcpy((char *) RawData + RosSymHeader->StringsOffset, RosSymInfo->Strings, + RosSymHeader->StringsLength); +} + +/* EOF */ diff --git a/reactos/lib/rossym/init.c b/reactos/lib/rossym/init.c new file mode 100644 index 00000000000..354b74b2b49 --- /dev/null +++ b/reactos/lib/rossym/init.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/data.c + * PURPOSE: Definition of external variables + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#include +#include +#include "rossympriv.h" + +ROSSYM_CALLBACKS RosSymCallbacks; + +VOID +RosSymInit(PROSSYM_CALLBACKS Callbacks) +{ + RosSymCallbacks = *Callbacks; +} + +/* EOF */ diff --git a/reactos/lib/rossym/initkm.c b/reactos/lib/rossym/initkm.c new file mode 100644 index 00000000000..c6981391570 --- /dev/null +++ b/reactos/lib/rossym/initkm.c @@ -0,0 +1,46 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/initkm.c + * PURPOSE: Initialize library for use in kernel mode + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +#define TAG_ROSSYM TAG('R', 'S', 'Y', 'M') + +static PVOID +RosSymAllocMemKM(ULONG_PTR Size) +{ + return ExAllocatePoolWithTag(NonPagedPool, Size, TAG_ROSSYM); +} + +static VOID +RosSymFreeMemKM(PVOID Area) +{ + return ExFreePool(Area); +} + +VOID +RosSymInitKernelMode(VOID) +{ + static ROSSYM_CALLBACKS KmCallbacks = + { + RosSymAllocMemKM, + RosSymFreeMemKM, + RosSymZwReadFile, + RosSymZwSeekFile + }; + + RosSymInit(&KmCallbacks); +} + +/* EOF */ diff --git a/reactos/lib/rossym/initum.c b/reactos/lib/rossym/initum.c new file mode 100644 index 00000000000..3c67da659e4 --- /dev/null +++ b/reactos/lib/rossym/initum.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/initum.c + * PURPOSE: Initialize library for use in user mode + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +static PVOID +RosSymAllocMemUM(ULONG_PTR Size) +{ + return HeapAlloc(GetProcessHeap(), 0, Size); +} + +static VOID +RosSymFreeMemUM(PVOID Area) +{ + HeapFree(GetProcessHeap(), 0, Area); +} + +VOID +RosSymInitUserMode(VOID) +{ + static ROSSYM_CALLBACKS KmCallbacks = + { + RosSymAllocMemUM, + RosSymFreeMemUM, + RosSymZwReadFile, + RosSymZwSeekFile + }; + + RosSymInit(&KmCallbacks); +} + +/* EOF */ diff --git a/reactos/lib/rossym/rossym.xml b/reactos/lib/rossym/rossym.xml new file mode 100644 index 00000000000..bcb0bca4cff --- /dev/null +++ b/reactos/lib/rossym/rossym.xml @@ -0,0 +1,13 @@ + + + delete.c + find.c + fromfile.c + frommem.c + fromraw.c + getraw.c + init.c + initkm.c + initum.c + zwfile.c + diff --git a/reactos/lib/rossym/rossympriv.h b/reactos/lib/rossym/rossympriv.h new file mode 100644 index 00000000000..b0b739ac5e9 --- /dev/null +++ b/reactos/lib/rossym/rossympriv.h @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/rossympriv.h + * PURPOSE: Private header for rossym + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#ifndef ROSSYMPRIV_H_INCLUDED +#define ROSSYMPRIV_H_INCLUDED + +typedef struct _ROSSYM_INFO { + PROSSYM_ENTRY Symbols; + ULONG SymbolsCount; + PCHAR Strings; + ULONG StringsLength; +} ROSSYM_INFO; + +extern ROSSYM_CALLBACKS RosSymCallbacks; + +#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size) +#define RosSymFreeMem(Area) (*RosSymCallbacks.FreeMemProc)(Area) +#define RosSymReadFile(FileContext, Buffer, Size) (*RosSymCallbacks.ReadFileProc)((FileContext), (Buffer), (Size)) +#define RosSymSeekFile(FileContext, Position) (*RosSymCallbacks.SeekFileProc)((FileContext), (Position)) + +extern BOOLEAN RosSymZwReadFile(PVOID FileContext, PVOID Buffer, ULONG Size); +extern BOOLEAN RosSymZwSeekFile(PVOID FileContext, ULONG_PTR Position); + +#define ROSSYM_IS_VALID_DOS_HEADER(DosHeader) (IMAGE_DOS_SIGNATURE == (DosHeader)->e_magic \ + && 0L != (DosHeader)->e_lfanew) +#define ROSSYM_IS_VALID_NT_HEADERS(NtHeaders) (IMAGE_NT_SIGNATURE == (NtHeaders)->Signature \ + && IMAGE_NT_OPTIONAL_HDR_MAGIC == (NtHeaders)->OptionalHeader.Magic) + + +#endif /* ROSSYMPRIV_H_INCLUDED */ + +/* EOF */ + diff --git a/reactos/lib/rossym/zwfile.c b/reactos/lib/rossym/zwfile.c new file mode 100644 index 00000000000..8f7a6859f84 --- /dev/null +++ b/reactos/lib/rossym/zwfile.c @@ -0,0 +1,52 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/rossym/zwfile.c + * PURPOSE: File I/O using native functions + * + * PROGRAMMERS: Ge van Geldorp (gvg@reactos.com) + */ + +#define NTOSAPI +#include +#include +#include "rossympriv.h" + +#define NDEBUG +#include + +BOOLEAN +RosSymZwReadFile(PVOID FileContext, PVOID Buffer, ULONG Size) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + + Status = ZwReadFile(*((HANDLE *) FileContext), + 0, 0, 0, + &IoStatusBlock, + Buffer, + Size, + 0, 0); + + return NT_SUCCESS(Status) && IoStatusBlock.Information == Size; +} + +BOOLEAN +RosSymZwSeekFile(PVOID FileContext, ULONG_PTR Position) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + FILE_POSITION_INFORMATION NewPosition; + + NewPosition.CurrentByteOffset.u.HighPart = 0; + NewPosition.CurrentByteOffset.u.LowPart = Position; + Status = ZwSetInformationFile(*((HANDLE *) FileContext), + &IoStatusBlock, + (PVOID) &NewPosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + + return NT_SUCCESS(Status); +} + +/* EOF */ diff --git a/reactos/lib/rpcrt4/ndr_midl.c b/reactos/lib/rpcrt4/ndr_midl.c index 9804b7c8963..76f972b69f4 100644 --- a/reactos/lib/rpcrt4/ndr_midl.c +++ b/reactos/lib/rpcrt4/ndr_midl.c @@ -100,6 +100,13 @@ void WINAPI NdrProxySendReceive(void *This, HRESULT hr; TRACE("(%p,%p)\n", This, pStubMsg); + + if (!pStubMsg->pRpcChannelBuffer) + { + WARN("Trying to use disconnected proxy %p\n", This); + RpcRaiseException(RPC_E_DISCONNECTED); + } + pStubMsg->dwStubPhase = PROXY_SENDRECEIVE; hr = IRpcChannelBuffer_SendReceive(pStubMsg->pRpcChannelBuffer, (RPCOLEMESSAGE*)pStubMsg->RpcMsg, diff --git a/reactos/lib/rpcrt4/rpc_binding.c b/reactos/lib/rpcrt4/rpc_binding.c index 32b71433e86..82e1690ea5f 100644 --- a/reactos/lib/rpcrt4/rpc_binding.c +++ b/reactos/lib/rpcrt4/rpc_binding.c @@ -96,7 +96,7 @@ LPWSTR RPCRT4_strndupW(LPWSTR src, INT slen) void RPCRT4_strfree(LPSTR src) { - if (src) HeapFree(GetProcessHeap(), 0, src); + HeapFree(GetProcessHeap(), 0, src); } RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions, RpcBinding* Binding) @@ -147,7 +147,7 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); HeapFree(GetProcessHeap(), 0, pname); memset(&Connection->ovl, 0, sizeof(Connection->ovl)); - Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) { WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError()); if (GetLastError() == ERROR_PIPE_CONNECTED) { @@ -171,7 +171,7 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); HeapFree(GetProcessHeap(), 0, pname); memset(&Connection->ovl, 0, sizeof(Connection->ovl)); - Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) { WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError()); if (GetLastError() == ERROR_PIPE_CONNECTED) { @@ -223,7 +223,7 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) /* pipe is connected; change to message-read mode. */ dwMode = PIPE_READMODE_MESSAGE; SetNamedPipeHandleState(conn, &dwMode, NULL, NULL); - Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); Connection->conn = conn; } /* protseq=ncacn_np: named pipes */ @@ -257,7 +257,7 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) /* pipe is connected; change to message-read mode. */ dwMode = PIPE_READMODE_MESSAGE; SetNamedPipeHandleState(conn, &dwMode, NULL, NULL); - Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); Connection->conn = conn; } else { ERR("protseq %s not supported\n", Connection->Protseq); diff --git a/reactos/lib/rpcrt4/rpc_message.c b/reactos/lib/rpcrt4/rpc_message.c index 6a2b8365138..119af8cfab3 100644 --- a/reactos/lib/rpcrt4/rpc_message.c +++ b/reactos/lib/rpcrt4/rpc_message.c @@ -447,8 +447,7 @@ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) * it, we'll leave deallocating the original buffer to the RPC server */ pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength); } else { - if (pMsg->Buffer) - HeapFree(GetProcessHeap(), 0, pMsg->Buffer); + HeapFree(GetProcessHeap(), 0, pMsg->Buffer); pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength); } TRACE("Buffer=%p\n", pMsg->Buffer); @@ -463,9 +462,7 @@ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) { TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); /* FIXME: pfnFree? */ - if (pMsg->Buffer != NULL) { - HeapFree(GetProcessHeap(), 0, pMsg->Buffer); - } + HeapFree(GetProcessHeap(), 0, pMsg->Buffer); pMsg->Buffer = NULL; return S_OK; } diff --git a/reactos/lib/rpcrt4/rpc_server.c b/reactos/lib/rpcrt4/rpc_server.c index 57eb4abbd30..bb3cb95da82 100644 --- a/reactos/lib/rpcrt4/rpc_server.c +++ b/reactos/lib/rpcrt4/rpc_server.c @@ -434,7 +434,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) #endif msg = NULL; } - if (msg) HeapFree(GetProcessHeap(), 0, msg); + HeapFree(GetProcessHeap(), 0, msg); RPCRT4_DestroyConnection(conn); return 0; } @@ -554,8 +554,8 @@ static void RPCRT4_start_listen(void) EnterCriticalSection(&listen_cs); if (! ++listen_count) { - if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL); - if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL); + if (!mgr_event) mgr_event = CreateEventW(NULL, TRUE, FALSE, NULL); + if (!server_sem) server_sem = CreateSemaphoreW(NULL, 0, MAX_THREADS, NULL); if (!worker_tls) worker_tls = TlsAlloc(); std_listen = TRUE; server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL); diff --git a/reactos/lib/rpcrt4/rpcrt4.spec b/reactos/lib/rpcrt4/rpcrt4.spec index 72efb417851..c2250a8e1e4 100644 --- a/reactos/lib/rpcrt4/rpcrt4.spec +++ b/reactos/lib/rpcrt4/rpcrt4.spec @@ -1,5 +1,5 @@ -@ stub DceErrorInqTextA -@ stub DceErrorInqTextW +@ stdcall DceErrorInqTextA (long ptr) +@ stdcall DceErrorInqTextW (long ptr) @ stdcall -private DllRegisterServer() RPCRT4_DllRegisterServer @ stub MesBufferHandleReset diff --git a/reactos/lib/rpcrt4/rpcrt4_main.c b/reactos/lib/rpcrt4/rpcrt4_main.c index baf7914e2b6..cdf54512aec 100644 --- a/reactos/lib/rpcrt4/rpcrt4_main.c +++ b/reactos/lib/rpcrt4/rpcrt4_main.c @@ -748,3 +748,53 @@ BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPC return TRUE; } + +/* DceErrorInqText + * + * Notes + * 1. On passing a NULL pointer the code does bomb out. + * 2. The size of the required buffer is not defined in the documentation. + * It appears to be 256. + * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know + * of any value for which it does. + * 4. The MSDN documentation currently declares that the second argument is + * unsigned char *, even for the W version. I don't believe it. + */ + +#define MAX_RPC_ERROR_TEXT 256 + +RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, unsigned short *buffer) +{ + DWORD count; + count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); + if (!count) + { + count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); + if (!count) + { + ERR ("Failed to translate error"); + return RPC_S_INVALID_ARG; + } + } + return RPC_S_OK; +} + +RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, unsigned char *buffer) +{ + RPC_STATUS status; + WCHAR bufferW [MAX_RPC_ERROR_TEXT]; + if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK) + { + if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_RPC_ERROR_TEXT, + NULL, NULL)) + { + ERR ("Failed to translate error"); + status = RPC_S_INVALID_ARG; + } + } + return status; +} diff --git a/reactos/lib/rtl/env.c b/reactos/lib/rtl/env.c index fc9e3040223..b12b7186021 100644 --- a/reactos/lib/rtl/env.c +++ b/reactos/lib/rtl/env.c @@ -20,6 +20,7 @@ #define NDEBUG #include +PPEB STDCALL RtlpCurrentPeb(VOID); /* FUNCTIONS *****************************************************************/ /* @@ -511,8 +512,11 @@ RtlQueryEnvironmentVariable_U(PWSTR Environment, if (Environment == NULL) { - Environment = NtCurrentPeb()->ProcessParameters->Environment; - SysEnvUsed = TRUE; + PPEB Peb = RtlpCurrentPeb(); + if (Peb) { + Environment = Peb->ProcessParameters->Environment; + SysEnvUsed = TRUE; + } } if (Environment == NULL) diff --git a/reactos/lib/rtl/error.c b/reactos/lib/rtl/error.c index 5a6e1ce42d2..7765d673616 100644 --- a/reactos/lib/rtl/error.c +++ b/reactos/lib/rtl/error.c @@ -991,4 +991,44 @@ RtlNtStatusToPsxErrno(IN NTSTATUS Status) return -1; /* generic POSIX error */ } + +/* + * @implemented + */ +NTSTATUS STDCALL +RtlGetLastNtStatus(VOID) +{ + return NtCurrentTeb()->LastStatusValue; +} + + +/* + * @implemented + */ +ULONG STDCALL +RtlGetLastWin32Error(VOID) +{ + return NtCurrentTeb()->LastErrorValue; +} + + +/* + * @implemented + */ +VOID STDCALL +RtlSetLastWin32Error(IN ULONG Error) +{ + NtCurrentTeb()->LastErrorValue = Error; +} + + +/* + * @implemented + */ +VOID STDCALL +RtlSetLastWin32ErrorAndNtStatusFromNtStatus(IN NTSTATUS Status) +{ + NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(Status); +} + /* EOF */ diff --git a/reactos/lib/rtl/i386/except.s b/reactos/lib/rtl/i386/except.s index 49acc79a5ee..bd3b631ceae 100644 --- a/reactos/lib/rtl/i386/except.s +++ b/reactos/lib/rtl/i386/except.s @@ -68,6 +68,7 @@ _do_debug: _RtlpCaptureContext: pushl %ebp movl %esp, %ebp + pushl %ebx movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure cld @@ -117,6 +118,7 @@ _RtlpCaptureContext: addl $8, %ebx movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 + popl %ebx movl %ebp, %esp popl %ebp ret diff --git a/reactos/lib/rtl/makefile b/reactos/lib/rtl/makefile index 4931e304571..18e0fb88dc3 100644 --- a/reactos/lib/rtl/makefile +++ b/reactos/lib/rtl/makefile @@ -32,6 +32,7 @@ TARGET_OBJECTS = \ network.o \ nls.o \ random.o \ + registry.o \ sd.o \ security.o \ sid.o \ diff --git a/reactos/lib/rtl/readme.txt b/reactos/lib/rtl/readme.txt new file mode 100644 index 00000000000..82f96f65048 --- /dev/null +++ b/reactos/lib/rtl/readme.txt @@ -0,0 +1,5 @@ +RTL restrictions: + +ExAllocatePool (and friends) must be used exclusively. RtlAllocateHeap (and friends) must NOT be used! ExAllocatePool (and friends) translate to RtlAllocateHeap (and friends) in ntdll\rtl\libsupp.c. + +RtlEnterCriticalSection (and friends) must be used exclusively. ExAcquireFastMutex (and friends) must NOT be used! RtlEnterCriticalSection (and friends) translate to ExAcquireFastMutex (and friends) in ntoskrnl\rtl\libsupp.c. This means that RtlEnterCriticalSection (and friends) can NOT be used recursively in RTL. The reason for choosing RtlEnterCriticalSection (and friends) over ExAcquireFastMutex (and friends) is that the FAST_MUTEX struct is smaller than the RTL_CRITICAL_SECTION struct. \ No newline at end of file diff --git a/reactos/lib/ntdll/rtl/registry.c b/reactos/lib/rtl/registry.c similarity index 85% rename from reactos/lib/ntdll/rtl/registry.c rename to reactos/lib/rtl/registry.c index de4fd705152..725c3074829 100644 --- a/reactos/lib/ntdll/rtl/registry.c +++ b/reactos/lib/rtl/registry.c @@ -1,9 +1,9 @@ -/* $Id$ +/* $Id: registry.c 12852 2005-01-06 13:58:04Z mf $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Rtl registry functions - * FILE: lib/ntdll/rtl/registry.c + * FILE: lib/rtl/registry.c * PROGRAMER: Eric Kohl * REVISION HISTORY: * 2000/08/11: Created @@ -17,6 +17,7 @@ /* INCLUDES ****************************************************************/ +#define __NTDRIVER__ #include #include #include @@ -43,13 +44,20 @@ RtlpGetRegistryHandle(ULONG RelativeTo, if (RelativeTo & RTL_REGISTRY_HANDLE) { - Status = NtDuplicateObject(NtCurrentProcess(), + Status = ZwDuplicateObject(NtCurrentProcess(), (HANDLE)Path, NtCurrentProcess(), KeyHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); +#ifndef NDEBUG + if(!NT_SUCCESS(Status)) + { + DPRINT("ZwDuplicateObject() failed! Status: 0x%x\n", Status); + } +#endif + return(Status); } @@ -57,18 +65,20 @@ RtlpGetRegistryHandle(ULONG RelativeTo, RelativeTo &= ~RTL_REGISTRY_OPTIONAL; if (RelativeTo >= RTL_REGISTRY_MAXIMUM) + { + DPRINT("Invalid relative flag, parameter invalid!\n"); return(STATUS_INVALID_PARAMETER); + } KeyName.Length = 0; - KeyName.MaximumLength = MAX_PATH; + KeyName.MaximumLength = sizeof(KeyBuffer); KeyName.Buffer = KeyBuffer; KeyBuffer[0] = 0; switch (RelativeTo) { case RTL_REGISTRY_ABSOLUTE: - RtlAppendUnicodeToString(&KeyName, - L"\\"); + /* nothing to prefix! */ break; case RTL_REGISTRY_SERVICES: @@ -101,16 +111,8 @@ RtlpGetRegistryHandle(ULONG RelativeTo, RtlAppendUnicodeToString (&KeyName, L"\\"); break; - - /* ReactOS specific */ - case RTL_REGISTRY_ENUM: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - break; } - DPRINT("KeyName %wZ\n", &KeyName); - if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) { Path++; @@ -126,9 +128,9 @@ RtlpGetRegistryHandle(ULONG RelativeTo, NULL, NULL); - if (Create == TRUE) + if (Create) { - Status = NtCreateKey(KeyHandle, + Status = ZwCreateKey(KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -138,11 +140,18 @@ RtlpGetRegistryHandle(ULONG RelativeTo, } else { - Status = NtOpenKey(KeyHandle, + Status = ZwOpenKey(KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); } +#ifndef NDEBUG + if(!NT_SUCCESS(Status)) + { + DPRINT("%s failed! Status: 0x%x\n", (Create ? "ZwCreateKey" : "ZwOpenKey"), Status); + } +#endif + return(Status); } @@ -164,7 +173,7 @@ RtlCheckRegistryKey(IN ULONG RelativeTo, if (!NT_SUCCESS(Status)) return(Status); - NtClose(KeyHandle); + ZwClose(KeyHandle); return(STATUS_SUCCESS); } @@ -187,7 +196,7 @@ RtlCreateRegistryKey(IN ULONG RelativeTo, if (!NT_SUCCESS(Status)) return(Status); - NtClose(KeyHandle); + ZwClose(KeyHandle); return(STATUS_SUCCESS); } @@ -215,10 +224,10 @@ RtlDeleteRegistryValue(IN ULONG RelativeTo, RtlInitUnicodeString(&Name, ValueName); - Status = NtDeleteValueKey(KeyHandle, + Status = ZwDeleteValueKey(KeyHandle, &Name); - NtClose(KeyHandle); + ZwClose(KeyHandle); return(Status); } @@ -239,7 +248,7 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) DPRINT ("RtlFormatCurrentUserKeyPath() called\n"); - Status = NtOpenThreadToken (NtCurrentThread (), + Status = ZwOpenThreadToken (NtCurrentThread (), TOKEN_READ, TRUE, &TokenHandle); @@ -247,30 +256,30 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) { if (Status != STATUS_NO_TOKEN) { - DPRINT1 ("NtOpenThreadToken() failed (Status %lx)\n", Status); + DPRINT1 ("ZwOpenThreadToken() failed (Status %lx)\n", Status); return Status; } - Status = NtOpenProcessToken (NtCurrentProcess (), + Status = ZwOpenProcessToken (NtCurrentProcess (), TOKEN_READ, &TokenHandle); if (!NT_SUCCESS (Status)) { - DPRINT1 ("NtOpenProcessToken() failed (Status %lx)\n", Status); + DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status); return Status; } } SidBuffer = (PSID_AND_ATTRIBUTES)Buffer; - Status = NtQueryInformationToken (TokenHandle, + Status = ZwQueryInformationToken (TokenHandle, TokenUser, (PVOID)SidBuffer, 256, &Length); - NtClose (TokenHandle); + ZwClose (TokenHandle); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtQueryInformationToken() failed (Status %lx)\n", Status); + DPRINT1 ("ZwQueryInformationToken() failed (Status %lx)\n", Status); return Status; } @@ -290,12 +299,11 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) KeyPath->Length = 0; KeyPath->MaximumLength = Length; - KeyPath->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), - 0, - KeyPath->MaximumLength); + KeyPath->Buffer = ExAllocatePool (NonPagedPool, + KeyPath->MaximumLength); if (KeyPath->Buffer == NULL) { - DPRINT1 ("RtlAllocateHeap() failed\n"); + DPRINT1 ("ExAllocatePool() failed\n"); RtlFreeUnicodeString (&SidString); return STATUS_NO_TOKEN; } @@ -329,7 +337,7 @@ RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(KeyHandle, + Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); RtlFreeUnicodeString(&KeyPath); @@ -346,7 +354,7 @@ RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(KeyHandle, + Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); @@ -362,7 +370,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, IN PCWSTR Path, IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context, - IN PVOID Environment) + IN PVOID Environment OPTIONAL) { NTSTATUS Status; HANDLE BaseKeyHandle; @@ -403,7 +411,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) && (BaseKeyHandle != CurrentKeyHandle)) { - NtClose(CurrentKeyHandle); + ZwClose(CurrentKeyHandle); CurrentKeyHandle = BaseKeyHandle; } @@ -418,7 +426,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, OBJ_CASE_INSENSITIVE, BaseKeyHandle, NULL); - Status = NtOpenKey(&CurrentKeyHandle, + Status = ZwOpenKey(&CurrentKeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -432,16 +440,14 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, QueryEntry->Name); BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096; - ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - BufferSize); + ValueInfo = ExAllocatePool(PagedPool, BufferSize); if (ValueInfo == NULL) { Status = STATUS_NO_MEMORY; break; } - Status = NtQueryValueKey(CurrentKeyHandle, + Status = ZwQueryValueKey(CurrentKeyHandle, &KeyName, KeyValuePartialInformation, ValueInfo, @@ -451,7 +457,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, { if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED) { - RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + ExFreePool(ValueInfo); Status = STATUS_OBJECT_NAME_NOT_FOUND; break; } @@ -467,9 +473,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, { ValueString->Length = SourceString->Length; ValueString->MaximumLength = SourceString->MaximumLength; - ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueString->MaximumLength); + ValueString->Buffer = ExAllocatePool(PagedPool, BufferSize); if (!ValueString->Buffer) break; ValueString->Buffer[0] = 0; @@ -507,9 +511,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, if (ValueString->Buffer == NULL) { ValueString->MaximumLength = ValueInfo->DataLength; - ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueString->MaximumLength); + ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength); if (ValueString->Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -532,9 +534,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; - ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueInfo->DataLength * 2); + ExpandBuffer = ExAllocatePool(PagedPool, ValueInfo->DataLength * 2); if (ExpandBuffer == NULL) { Status = STATUS_NO_MEMORY; @@ -557,9 +557,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, { ValueString->MaximumLength = EnvExpandedValue.Length + sizeof(WCHAR); ValueString->Length = EnvExpandedValue.Length; - ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueString->MaximumLength); + ValueString->Buffer = ExAllocatePool(PagedPool, ValueString->MaximumLength); if (ValueString->Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -577,9 +575,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, ValueString->Length); ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ExpandBuffer); + ExFreePool(ExpandBuffer); } else { @@ -595,9 +591,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, } - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ValueInfo); + ExFreePool(ValueInfo); } else { @@ -608,16 +602,14 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, QueryEntry->Name); BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096; - ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - BufferSize); + ValueInfo = ExAllocatePool(PagedPool, BufferSize); if (ValueInfo == NULL) { Status = STATUS_NO_MEMORY; break; } - Status = NtQueryValueKey(CurrentKeyHandle, + Status = ZwQueryValueKey(CurrentKeyHandle, &KeyName, KeyValuePartialInformation, ValueInfo, @@ -659,9 +651,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, { DPRINT("Expand REG_EXPAND_SZ type\n"); - ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueInfo->DataLength * 2); + ExpandBuffer = ExAllocatePool(PagedPool, ValueInfo->DataLength * 2); if (ExpandBuffer == NULL) { Status = STATUS_NO_MEMORY; @@ -688,9 +678,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, Context, QueryEntry->EntryContext); - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ExpandBuffer); + ExFreePool(ExpandBuffer); } else { @@ -708,9 +696,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, } - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ValueInfo); + ExFreePool(ValueInfo); if (!NT_SUCCESS(Status)) break; } @@ -731,18 +717,14 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, DPRINT("Enumerate values\n"); BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096; - FullValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - BufferSize); + FullValueInfo = ExAllocatePool(PagedPool, BufferSize); if (FullValueInfo == NULL) { Status = STATUS_NO_MEMORY; break; } ValueNameSize = 256 * sizeof(WCHAR); - ValueName = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueNameSize); + ValueName = ExAllocatePool(PagedPool, ValueNameSize); if (ValueName == NULL) { Status = STATUS_NO_MEMORY; @@ -751,7 +733,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, Index = 0; while (TRUE) { - Status = NtEnumerateValueKey(CurrentKeyHandle, + Status = ZwEnumerateValueKey(CurrentKeyHandle, Index, KeyValueFullInformation, FullValueInfo, @@ -775,13 +757,9 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR)) { /* Should not happen, because the name length is limited to 255 characters */ - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ValueName); + ExFreePool(ValueName); ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR); - ValueName = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - ValueNameSize); + ValueName = ExAllocatePool(PagedPool, ValueNameSize); if (ValueName == NULL) { Status = STATUS_NO_MEMORY; @@ -820,9 +798,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, DPRINT("Expand REG_EXPAND_SZ type\n"); StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset); - ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - FullValueInfo->DataLength * 2); + ExpandBuffer = ExAllocatePool(PagedPool, FullValueInfo->DataLength * 2); if (ExpandBuffer == NULL) { Status = STATUS_NO_MEMORY; @@ -849,9 +825,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, Context, QueryEntry->EntryContext); - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ExpandBuffer); + ExFreePool(ExpandBuffer); } else { @@ -871,12 +845,8 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, Index++; } - RtlFreeHeap(RtlGetProcessHeap(), - 0, - FullValueInfo); - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ValueName); + ExFreePool(FullValueInfo); + ExFreePool(ValueName); if (!NT_SUCCESS(Status)) break; } @@ -886,9 +856,9 @@ RtlQueryRegistryValues(IN ULONG RelativeTo, } if (CurrentKeyHandle != BaseKeyHandle) - NtClose(CurrentKeyHandle); + ZwClose(CurrentKeyHandle); - NtClose(BaseKeyHandle); + ZwClose(BaseKeyHandle); return(Status); } @@ -914,19 +884,26 @@ RtlWriteRegistryValue(IN ULONG RelativeTo, TRUE, &KeyHandle); if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed! Status: 0x%x\n", Status); return(Status); + } RtlInitUnicodeString(&Name, ValueName); - Status = NtSetValueKey(KeyHandle, + Status = ZwSetValueKey(KeyHandle, &Name, 0, ValueType, ValueData, ValueLength); - if (NT_SUCCESS(Status)) - NtClose(KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ZwSetValueKey() failed! Status: 0x%x\n", Status); + } + + ZwClose(KeyHandle); return(Status); } @@ -946,7 +923,7 @@ RtlpNtCreateKey(OUT HANDLE KeyHandle, if (ObjectAttributes != NULL) ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); - return(NtCreateKey(KeyHandle, + return(ZwCreateKey(KeyHandle, DesiredAccess, ObjectAttributes, 0, @@ -974,14 +951,12 @@ RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, { BufferLength = SubKeyName->MaximumLength + sizeof(KEY_BASIC_INFORMATION); - KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - BufferLength); + KeyInfo = ExAllocatePool(PagedPool, BufferLength); if (KeyInfo == NULL) return(STATUS_NO_MEMORY); } - Status = NtEnumerateKey(KeyHandle, + Status = ZwEnumerateKey(KeyHandle, Index, KeyBasicInformation, KeyInfo, @@ -1005,9 +980,7 @@ RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, if (KeyInfo != NULL) { - RtlFreeHeap(RtlGetProcessHeap(), - 0, - KeyInfo); + ExFreePool(KeyInfo); } return(Status); @@ -1020,7 +993,7 @@ RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, NTSTATUS STDCALL RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle) { - return(NtDeleteKey(KeyHandle)); + return(ZwDeleteKey(KeyHandle)); } @@ -1036,7 +1009,7 @@ RtlpNtOpenKey(OUT HANDLE KeyHandle, if (ObjectAttributes != NULL) ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); - return(NtOpenKey(KeyHandle, + return(ZwOpenKey(KeyHandle, DesiredAccess, ObjectAttributes)); } @@ -1065,13 +1038,11 @@ RtlpNtQueryValueKey(IN HANDLE KeyHandle, if (DataLength != NULL) BufferLength = *DataLength; - ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - BufferLength); + ValueInfo = ExAllocatePool(PagedPool, BufferLength); if (ValueInfo == NULL) return(STATUS_NO_MEMORY); - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueInfo, @@ -1093,9 +1064,7 @@ RtlpNtQueryValueKey(IN HANDLE KeyHandle, } } - RtlFreeHeap(RtlGetProcessHeap(), - 0, - ValueInfo); + ExFreePool(ValueInfo); return(Status); } @@ -1114,7 +1083,7 @@ RtlpNtSetValueKey(IN HANDLE KeyHandle, RtlInitUnicodeString(&ValueName, NULL); - return(NtSetValueKey(KeyHandle, + return(ZwSetValueKey(KeyHandle, &ValueName, 0, Type, diff --git a/reactos/lib/rtl/rtl.xml b/reactos/lib/rtl/rtl.xml index 65a56f41dfc..147aa85f906 100644 --- a/reactos/lib/rtl/rtl.xml +++ b/reactos/lib/rtl/rtl.xml @@ -22,6 +22,7 @@ network.c nls.c random.c + registry.c sd.c security.c sid.c diff --git a/reactos/lib/rtl/sd.c b/reactos/lib/rtl/sd.c index 09ffac238db..a27f2e5e458 100644 --- a/reactos/lib/rtl/sd.c +++ b/reactos/lib/rtl/sd.c @@ -17,6 +17,95 @@ /* FUNCTIONS ***************************************************************/ + +static VOID +RtlpQuerySecurityDescriptorPointers(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + OUT PSID *Owner OPTIONAL, + OUT PSID *Group OPTIONAL, + OUT PACL *Sacl OPTIONAL, + OUT PACL *Dacl OPTIONAL) +{ + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; + if(Owner != NULL) + { + *Owner = ((RelSD->Owner != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Owner) : NULL); + } + if(Group != NULL) + { + *Group = ((RelSD->Group != 0) ? (PSID)((ULONG_PTR)RelSD + RelSD->Group) : NULL); + } + if(Sacl != NULL) + { + *Sacl = (((RelSD->Control & SE_SACL_PRESENT) && (RelSD->Sacl != 0)) ? + (PSID)((ULONG_PTR)RelSD + RelSD->Sacl) : NULL); + } + if(Dacl != NULL) + { + *Dacl = (((RelSD->Control & SE_DACL_PRESENT) && (RelSD->Dacl != 0)) ? + (PSID)((ULONG_PTR)RelSD + RelSD->Dacl) : NULL); + } + } + else + { + if(Owner != NULL) + { + *Owner = SecurityDescriptor->Owner; + } + if(Group != NULL) + { + *Group = SecurityDescriptor->Group; + } + if(Sacl != NULL) + { + *Sacl = ((SecurityDescriptor->Control & SE_SACL_PRESENT) ? SecurityDescriptor->Sacl : NULL); + } + if(Dacl != NULL) + { + *Dacl = ((SecurityDescriptor->Control & SE_DACL_PRESENT) ? SecurityDescriptor->Dacl : NULL); + } + } +} + +static VOID +RtlpQuerySecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Owner, + PULONG OwnerLength, + PSID* Group, + PULONG GroupLength, + PACL* Dacl, + PULONG DaclLength, + PACL* Sacl, + PULONG SaclLength) +{ + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + Owner, + Group, + Sacl, + Dacl); + + if (Owner != NULL) + { + *OwnerLength = ((*Owner != NULL) ? ROUND_UP(RtlLengthSid(*Owner), 4) : 0); + } + + if (Group != NULL) + { + *GroupLength = ((*Group != NULL) ? ROUND_UP(RtlLengthSid(*Group), 4) : 0); + } + + if (Dacl != NULL) + { + *DaclLength = ((*Dacl != NULL) ? ROUND_UP((*Dacl)->AclSize, 4) : 0); + } + + if (Sacl != NULL) + { + *SaclLength = ((*Sacl != NULL) ? ROUND_UP((*Sacl)->AclSize, 4) : 0); + } +} + /* * @implemented */ @@ -40,54 +129,62 @@ RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_SUCCESS; } + +NTSTATUS STDCALL +RtlCreateSecurityDescriptorRelative (PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, + ULONG Revision) +{ + if (Revision != SECURITY_DESCRIPTOR_REVISION1) + { + return STATUS_UNKNOWN_REVISION; + } + + SecurityDescriptor->Revision = Revision; + SecurityDescriptor->Sbz1 = 0; + SecurityDescriptor->Control = SE_SELF_RELATIVE; + SecurityDescriptor->Owner = 0; + SecurityDescriptor->Group = 0; + SecurityDescriptor->Sacl = 0; + SecurityDescriptor->Dacl = 0; + + return STATUS_SUCCESS; +} + + /* * @implemented */ ULONG STDCALL RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) { + PSID Owner, Group; + PACL Sacl, Dacl; ULONG Length = sizeof(SECURITY_DESCRIPTOR); + + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + &Owner, + &Group, + &Sacl, + &Dacl); - if (SecurityDescriptor->Owner != NULL) + if (Owner != NULL) { - PSID Owner = SecurityDescriptor->Owner; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Owner = (PSID)((ULONG_PTR)Owner + (ULONG_PTR)SecurityDescriptor); - } - Length = Length + ROUND_UP(RtlLengthSid(Owner), 4); + Length += ROUND_UP(RtlLengthSid(Owner), 4); } - if (SecurityDescriptor->Group != NULL) + if (Group != NULL) { - PSID Group = SecurityDescriptor->Group; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Group = (PSID)((ULONG_PTR)Group + (ULONG_PTR)SecurityDescriptor); - } - Length = Length + ROUND_UP(RtlLengthSid(Group), 4); + Length += ROUND_UP(RtlLengthSid(Group), 4); } - if (SecurityDescriptor->Control & SE_DACL_PRESENT && - SecurityDescriptor->Dacl != NULL) + if (Dacl != NULL) { - PACL Dacl = SecurityDescriptor->Dacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Dacl = (PACL)((ULONG_PTR)Dacl + (ULONG_PTR)SecurityDescriptor); - } - Length = Length + ROUND_UP(Dacl->AclSize, 4); + Length += ROUND_UP(Dacl->AclSize, 4); } - if (SecurityDescriptor->Control & SE_SACL_PRESENT && - SecurityDescriptor->Sacl != NULL) + if (Sacl != NULL) { - PACL Sacl = SecurityDescriptor->Sacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Sacl = (PACL)((ULONG_PTR)Sacl + (ULONG_PTR)SecurityDescriptor); - } - Length = Length + ROUND_UP(Sacl->AclSize, 4); + Length += ROUND_UP(Sacl->AclSize, 4); } return Length; @@ -115,27 +212,13 @@ RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, } *DaclPresent = TRUE; - if (SecurityDescriptor->Dacl == NULL) - { - *Dacl = NULL; - } - else - { - *Dacl = SecurityDescriptor->Dacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Dacl = (PACL)((ULONG_PTR)*Dacl + (ULONG_PTR)SecurityDescriptor); - } - } + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + NULL, + NULL, + NULL, + Dacl); - if (SecurityDescriptor->Control & SE_DACL_DEFAULTED) - { - *DaclDefaulted = TRUE; - } - else - { - *DaclDefaulted = FALSE; - } + *DaclDefaulted = ((SecurityDescriptor->Control & SE_DACL_DEFAULTED) ? TRUE : FALSE); return STATUS_SUCCESS; } @@ -185,67 +268,26 @@ RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN STDCALL RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) { + PSID Owner, Group; + PACL Sacl, Dacl; + if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) { return FALSE; } + + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + &Owner, + &Group, + &Sacl, + &Dacl); - if (SecurityDescriptor->Owner != NULL) + if ((Owner != NULL && !RtlValidSid(Owner)) || + (Group != NULL && !RtlValidSid(Group)) || + (Sacl != NULL && !RtlValidAcl(Sacl)) || + (Dacl != NULL && !RtlValidAcl(Dacl))) { - PSID Owner = SecurityDescriptor->Owner; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Owner = (PSID)((ULONG_PTR)Owner + (ULONG_PTR)SecurityDescriptor); - } - - if (!RtlValidSid(Owner)) - { - return FALSE; - } - } - - if (SecurityDescriptor->Group != NULL) - { - PSID Group = SecurityDescriptor->Group; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Group = (PSID)((ULONG_PTR)Group + (ULONG_PTR)SecurityDescriptor); - } - - if (!RtlValidSid(Group)) - { - return FALSE; - } - } - - if (SecurityDescriptor->Control & SE_DACL_PRESENT && - SecurityDescriptor->Dacl != NULL) - { - PACL Dacl = SecurityDescriptor->Dacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Dacl = (PACL)((ULONG_PTR)Dacl + (ULONG_PTR)SecurityDescriptor); - } - - if (!RtlValidAcl(Dacl)) - { - return FALSE; - } - } - - if (SecurityDescriptor->Control & SE_SACL_PRESENT && - SecurityDescriptor->Sacl != NULL) - { - PACL Sacl = SecurityDescriptor->Sacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - Sacl = (PACL)((ULONG_PTR)Sacl + (ULONG_PTR)SecurityDescriptor); - } - - if (!RtlValidAcl(Sacl)) - { - return FALSE; - } + return FALSE; } return TRUE; @@ -278,9 +320,10 @@ RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, SecurityDescriptor->Control = SecurityDescriptor->Control | SE_OWNER_DEFAULTED; } - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } + /* * @implemented */ @@ -294,31 +337,18 @@ RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_UNKNOWN_REVISION; } - if (SecurityDescriptor->Owner != NULL) - { - *Owner = SecurityDescriptor->Owner; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Owner = (PSID)((ULONG_PTR)*Owner + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Owner = NULL; - } + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + Owner, + NULL, + NULL, + NULL); - if (SecurityDescriptor->Control & SE_OWNER_DEFAULTED) - { - *OwnerDefaulted = TRUE; - } - else - { - *OwnerDefaulted = FALSE; - } + *OwnerDefaulted = ((SecurityDescriptor->Control & SE_OWNER_DEFAULTED) ? TRUE : FALSE); return STATUS_SUCCESS; } + /* * @implemented */ @@ -347,6 +377,7 @@ RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_SUCCESS; } + /* * @implemented */ @@ -360,142 +391,25 @@ RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_UNKNOWN_REVISION; } - if (SecurityDescriptor->Group != NULL) - { - *Group = SecurityDescriptor->Group; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Group = (PSID)((ULONG_PTR)*Group + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Group = NULL; - } + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + NULL, + Group, + NULL, + NULL); - if (SecurityDescriptor->Control & SE_GROUP_DEFAULTED) - { - *GroupDefaulted = TRUE; - } - else - { - *GroupDefaulted = FALSE; - } + *GroupDefaulted = ((SecurityDescriptor->Control & SE_GROUP_DEFAULTED) ? TRUE : FALSE); return STATUS_SUCCESS; } -static VOID -RtlpQuerySecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, - PSID* Owner, - PULONG OwnerLength, - PSID* Group, - PULONG GroupLength, - PACL* Dacl, - PULONG DaclLength, - PACL* Sacl, - PULONG SaclLength) -{ - if (SecurityDescriptor->Owner != NULL) - { - *Owner = SecurityDescriptor->Owner; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Owner = (PSID)((ULONG_PTR)*Owner + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Owner = NULL; - } - - if (*Owner != NULL) - { - *OwnerLength = ROUND_UP(RtlLengthSid(*Owner), 4); - } - else - { - *OwnerLength = 0; - } - - if ((SecurityDescriptor->Control & SE_DACL_PRESENT) && - SecurityDescriptor->Dacl != NULL) - { - *Dacl = SecurityDescriptor->Dacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Dacl = (PACL)((ULONG_PTR)*Dacl + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Dacl = NULL; - } - - if (*Dacl != NULL) - { - *DaclLength = ROUND_UP((*Dacl)->AclSize, 4); - } - else - { - *DaclLength = 0; - } - - if (SecurityDescriptor->Group != NULL) - { - *Group = SecurityDescriptor->Group; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Group = (PSID)((ULONG_PTR)*Group + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Group = NULL; - } - - if (*Group != NULL) - { - *GroupLength = ROUND_UP(RtlLengthSid(*Group), 4); - } - else - { - *GroupLength = 0; - } - - if ((SecurityDescriptor->Control & SE_SACL_PRESENT) && - SecurityDescriptor->Sacl != NULL) - { - *Sacl = SecurityDescriptor->Sacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Sacl = (PACL)((ULONG_PTR)*Sacl + (ULONG_PTR)SecurityDescriptor); - } - } - else - { - *Sacl = NULL; - } - - if (*Sacl != NULL) - { - *SaclLength = ROUND_UP((*Sacl)->AclSize, 4); - } - else - { - *SaclLength = 0; - } -} - - /* * @implemented */ NTSTATUS STDCALL RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, - PSECURITY_DESCRIPTOR RelSD, - PULONG BufferLength) + PSECURITY_DESCRIPTOR_RELATIVE RelSD, + PULONG BufferLength) { PSID Owner; PSID Group; @@ -518,7 +432,7 @@ RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, &Sacl, &SaclLength); - TotalLength = OwnerLength + GroupLength + SaclLength + DaclLength + sizeof(SECURITY_DESCRIPTOR); + TotalLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength + GroupLength + SaclLength + DaclLength; if (*BufferLength < TotalLength) { return STATUS_BUFFER_TOO_SMALL; @@ -526,48 +440,48 @@ RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, RtlZeroMemory(RelSD, TotalLength); - memmove(RelSD, - AbsSD, - sizeof(SECURITY_DESCRIPTOR)); - Current = (ULONG_PTR)RelSD + sizeof(SECURITY_DESCRIPTOR); + + RelSD->Revision = AbsSD->Revision; + RelSD->Sbz1 = AbsSD->Sbz1; + RelSD->Control = AbsSD->Control | SE_SELF_RELATIVE; + + Current = (ULONG_PTR)(RelSD + 1); if (SaclLength != 0) { - memmove((PVOID)Current, - Sacl, - SaclLength); - RelSD->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)RelSD); + RtlCopyMemory((PVOID)Current, + Sacl, + SaclLength); + RelSD->Sacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)RelSD); Current += SaclLength; } if (DaclLength != 0) { - memmove((PVOID)Current, - Dacl, - DaclLength); - RelSD->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)RelSD); + RtlCopyMemory((PVOID)Current, + Dacl, + DaclLength); + RelSD->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)RelSD); Current += DaclLength; } if (OwnerLength != 0) { - memmove((PVOID)Current, - Owner, - OwnerLength); - RelSD->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)RelSD); + RtlCopyMemory((PVOID)Current, + Owner, + OwnerLength); + RelSD->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)RelSD); Current += OwnerLength; } if (GroupLength != 0) { - memmove((PVOID)Current, - Group, - GroupLength); - RelSD->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)RelSD); + RtlCopyMemory((PVOID)Current, + Group, + GroupLength); + RelSD->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)RelSD); } - RelSD->Control |= SE_SELF_RELATIVE; - return STATUS_SUCCESS; } @@ -577,9 +491,8 @@ RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, */ NTSTATUS STDCALL RtlAbsoluteToSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, - PSECURITY_DESCRIPTOR RelSD, - PULONG BufferLength - ) + PSECURITY_DESCRIPTOR_RELATIVE RelSD, + PULONG BufferLength) { if (AbsSD->Control & SE_SELF_RELATIVE) { @@ -611,6 +524,29 @@ RtlGetControlSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, } +/* + * @implemented + */ +NTSTATUS STDCALL +RtlSetControlSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet) +{ + if (SecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) + { + return STATUS_UNKNOWN_REVISION; + } + + /* Zero the 'bits of interest' */ + SecurityDescriptor->Control &= ~ControlBitsOfInterest; + + /* Set the 'bits to set' */ + SecurityDescriptor->Control |= (ControlBitsToSet & ControlBitsOfInterest); + + return STATUS_SUCCESS; +} + + /* * @implemented */ @@ -632,31 +568,18 @@ RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, } *SaclPresent = TRUE; - if (SecurityDescriptor->Sacl == NULL) - { - *Sacl = NULL; - } - else - { - *Sacl = SecurityDescriptor->Sacl; - if (SecurityDescriptor->Control & SE_SELF_RELATIVE) - { - *Sacl = (PACL)((ULONG_PTR)*Sacl + (ULONG_PTR)SecurityDescriptor); - } - } + RtlpQuerySecurityDescriptorPointers(SecurityDescriptor, + NULL, + NULL, + Sacl, + NULL); - if (SecurityDescriptor->Control & SE_SACL_DEFAULTED) - { - *SaclDefaulted = TRUE; - } - else - { - *SaclDefaulted = FALSE; - } + *SaclDefaulted = ((SecurityDescriptor->Control & SE_SACL_DEFAULTED) ? TRUE : FALSE); return STATUS_SUCCESS; } + /* * @implemented */ @@ -694,11 +617,12 @@ RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, return STATUS_SUCCESS; } + /* * @implemented */ NTSTATUS STDCALL -RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD, +RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR_RELATIVE RelSD, PSECURITY_DESCRIPTOR AbsSD, PDWORD AbsSDSize, PACL Dacl, @@ -719,10 +643,17 @@ RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD, PACL pDacl; PACL pSacl; - if (!(RelSD->Control & SE_SELF_RELATIVE)) - return STATUS_BAD_DESCRIPTOR_FORMAT; + if (RelSD->Revision != SECURITY_DESCRIPTOR_REVISION1) + { + return STATUS_UNKNOWN_REVISION; + } - RtlpQuerySecurityDescriptor (RelSD, + if (!(RelSD->Control & SE_SELF_RELATIVE)) + { + return STATUS_BAD_DESCRIPTOR_FORMAT; + } + + RtlpQuerySecurityDescriptor ((PSECURITY_DESCRIPTOR)RelSD, &pOwner, &OwnerLength, &pGroup, @@ -736,16 +667,18 @@ RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD, GroupLength > *GroupSize || DaclLength > *DaclSize || SaclLength > *SaclSize) + { return STATUS_BUFFER_TOO_SMALL; + } - memmove (Owner, pOwner, OwnerLength); - memmove (Group, pGroup, GroupLength); - memmove (Dacl, pDacl, DaclLength); - memmove (Sacl, pSacl, SaclLength); + RtlCopyMemory (Owner, pOwner, OwnerLength); + RtlCopyMemory (Group, pGroup, GroupLength); + RtlCopyMemory (Dacl, pDacl, DaclLength); + RtlCopyMemory (Sacl, pSacl, SaclLength); - memmove (AbsSD, RelSD, sizeof (SECURITY_DESCRIPTOR)); - - AbsSD->Control &= ~SE_SELF_RELATIVE; + AbsSD->Revision = RelSD->Revision; + AbsSD->Sbz1 = RelSD->Sbz1; + AbsSD->Control = RelSD->Control & ~SE_SELF_RELATIVE; AbsSD->Owner = Owner; AbsSD->Group = Group; AbsSD->Dacl = Dacl; @@ -759,33 +692,35 @@ RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD, return STATUS_SUCCESS; } + /* -* @unimplemented -*/ + * @unimplemented + */ NTSTATUS STDCALL -RtlSelfRelativeToAbsoluteSD2(PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, +RtlSelfRelativeToAbsoluteSD2(PSECURITY_DESCRIPTOR_RELATIVE SelfRelativeSecurityDescriptor, PULONG BufferSize) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; } + /* -* @implemented -*/ + * @implemented + */ BOOLEAN STDCALL -RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, +RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptorInput, IN ULONG SecurityDescriptorLength, IN SECURITY_INFORMATION RequiredInformation) { - if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR) || + if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE) || SecurityDescriptorInput->Revision != SECURITY_DESCRIPTOR_REVISION1 || !(SecurityDescriptorInput->Control & SE_SELF_RELATIVE)) { return FALSE; } - if (SecurityDescriptorInput->Owner != NULL) + if (SecurityDescriptorInput->Owner != 0) { PSID Owner = (PSID)((ULONG_PTR)SecurityDescriptorInput->Owner + (ULONG_PTR)SecurityDescriptorInput); if (!RtlValidSid(Owner)) @@ -798,7 +733,7 @@ RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInp return FALSE; } - if (SecurityDescriptorInput->Group != NULL) + if (SecurityDescriptorInput->Group != 0) { PSID Group = (PSID)((ULONG_PTR)SecurityDescriptorInput->Group + (ULONG_PTR)SecurityDescriptorInput); if (!RtlValidSid(Group)) @@ -813,7 +748,7 @@ RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInp if (SecurityDescriptorInput->Control & SE_DACL_PRESENT) { - if (SecurityDescriptorInput->Dacl != NULL && + if (SecurityDescriptorInput->Dacl != 0 && !RtlValidAcl((PACL)((ULONG_PTR)SecurityDescriptorInput->Dacl + (ULONG_PTR)SecurityDescriptorInput))) { return FALSE; @@ -826,7 +761,7 @@ RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInp if (SecurityDescriptorInput->Control & SE_SACL_PRESENT) { - if (SecurityDescriptorInput->Sacl != NULL && + if (SecurityDescriptorInput->Sacl != 0 && !RtlValidAcl((PACL)((ULONG_PTR)SecurityDescriptorInput->Sacl + (ULONG_PTR)SecurityDescriptorInput))) { return FALSE; @@ -840,4 +775,43 @@ RtlValidRelativeSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptorInp return TRUE; } + +/* + * @implemented + */ +BOOLEAN STDCALL +RtlGetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl) +{ + if (!(SecurityDescriptor->Control & SE_RM_CONTROL_VALID)) + { + *RMControl = 0; + return FALSE; + } + + *RMControl = SecurityDescriptor->Sbz1; + + return TRUE; +} + + +/* + * @implemented + */ +VOID STDCALL +RtlSetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, + PUCHAR RMControl) +{ + if (RMControl == NULL) + { + SecurityDescriptor->Control &= ~SE_RM_CONTROL_VALID; + SecurityDescriptor->Sbz1 = 0; + } + else + { + SecurityDescriptor->Control |= SE_RM_CONTROL_VALID; + SecurityDescriptor->Sbz1 = *RMControl; + } +} + /* EOF */ diff --git a/reactos/lib/rtl/sid.c b/reactos/lib/rtl/sid.c index 2d86832a778..18e99ed6033 100644 --- a/reactos/lib/rtl/sid.c +++ b/reactos/lib/rtl/sid.c @@ -22,8 +22,10 @@ /* FUNCTIONS ***************************************************************/ BOOLEAN STDCALL -RtlValidSid(IN PSID Sid) +RtlValidSid(IN PSID Sid_) { + PISID Sid = Sid_; + if ((Sid->Revision != SID_REVISION) || (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)) { @@ -48,10 +50,12 @@ RtlLengthRequiredSid(IN UCHAR SubAuthorityCount) * @implemented */ NTSTATUS STDCALL -RtlInitializeSid(IN PSID Sid, +RtlInitializeSid(IN PSID Sid_, IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount) { + PISID Sid = Sid_; + Sid->Revision = SID_REVISION; Sid->SubAuthorityCount = SubAuthorityCount; memcpy(&Sid->IdentifierAuthority, @@ -66,9 +70,11 @@ RtlInitializeSid(IN PSID Sid, * @implemented */ PULONG STDCALL -RtlSubAuthoritySid(IN PSID Sid, +RtlSubAuthoritySid(IN PSID Sid_, IN ULONG SubAuthority) { + PISID Sid = Sid_; + return &Sid->SubAuthority[SubAuthority]; } @@ -77,8 +83,10 @@ RtlSubAuthoritySid(IN PSID Sid, * @implemented */ PUCHAR STDCALL -RtlSubAuthorityCountSid(IN PSID Sid) +RtlSubAuthorityCountSid(IN PSID Sid_) { + PISID Sid = Sid_; + return &Sid->SubAuthorityCount; } @@ -87,9 +95,12 @@ RtlSubAuthorityCountSid(IN PSID Sid) * @implemented */ BOOLEAN STDCALL -RtlEqualSid(IN PSID Sid1, - IN PSID Sid2) +RtlEqualSid(IN PSID Sid1_, + IN PSID Sid2_) { + PISID Sid1 = Sid1_; + PISID Sid2 = Sid2_; + if (Sid1->Revision != Sid2->Revision) { return(FALSE); @@ -110,8 +121,10 @@ RtlEqualSid(IN PSID Sid1, * @implemented */ ULONG STDCALL -RtlLengthSid(IN PSID Sid) +RtlLengthSid(IN PSID Sid_) { + PISID Sid = Sid_; + return (sizeof(SID) + (Sid->SubAuthorityCount-1) * sizeof(ULONG)); } @@ -180,8 +193,10 @@ RtlCopySidAndAttributesArray(ULONG Count, * @implemented */ PSID_IDENTIFIER_AUTHORITY STDCALL -RtlIdentifierAuthoritySid(IN PSID Sid) +RtlIdentifierAuthoritySid(IN PSID Sid_) { + PISID Sid = Sid_; + return &Sid->IdentifierAuthority; } @@ -202,7 +217,7 @@ RtlAllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, ULONG SubAuthority7, PSID *Sid) { - PSID pSid; + PISID pSid; if (SubAuthorityCount > 8) return STATUS_INVALID_SID; @@ -267,9 +282,12 @@ RtlFreeSid(IN PSID Sid) * @implemented */ BOOLEAN STDCALL -RtlEqualPrefixSid(IN PSID Sid1, - IN PSID Sid2) +RtlEqualPrefixSid(IN PSID Sid1_, + IN PSID Sid2_) { + PISID Sid1 = Sid1_; + PISID Sid2 = Sid2_; + return(Sid1->SubAuthorityCount == Sid2->SubAuthorityCount && !RtlCompareMemory(Sid1, Sid2, (Sid1->SubAuthorityCount - 1) * sizeof(DWORD) + 8)); @@ -281,13 +299,14 @@ RtlEqualPrefixSid(IN PSID Sid1, */ NTSTATUS STDCALL RtlConvertSidToUnicodeString(PUNICODE_STRING String, - PSID Sid, + PSID Sid_, BOOLEAN AllocateBuffer) { WCHAR Buffer[256]; PWSTR wcs; ULONG Length; ULONG i; + PISID Sid = Sid_; if (RtlValidSid (Sid) == FALSE) return STATUS_INVALID_SID; diff --git a/reactos/lib/rtl/time.c b/reactos/lib/rtl/time.c index 0716a60623c..3e5d54364d8 100644 --- a/reactos/lib/rtl/time.c +++ b/reactos/lib/rtl/time.c @@ -48,9 +48,7 @@ static const int YearLengths[2] = }; static const int MonthLengths[2][MONSPERYEAR] = { - { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }, + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; @@ -69,14 +67,113 @@ static __inline void NormalizeTimeFields(CSHORT *FieldToNormalize, /* FUNCTIONS *****************************************************************/ +/* + * @implemented + */ +BOOLEAN STDCALL +RtlCutoverTimeToSystemTime(IN PTIME_FIELDS CutoverTimeFields, + OUT PLARGE_INTEGER SystemTime, + IN PLARGE_INTEGER CurrentTime, + IN BOOLEAN ThisYearsCutoverOnly) +{ + TIME_FIELDS AdjustedTimeFields; + TIME_FIELDS CurrentTimeFields; + TIME_FIELDS CutoverSystemTimeFields; + LARGE_INTEGER CutoverSystemTime; + CSHORT MonthLength; + CSHORT Days; + BOOLEAN NextYearsCutover = FALSE; + + /* Check fixed cutover time */ + if (CutoverTimeFields->Year != 0) + { + if (!RtlTimeFieldsToTime(CutoverTimeFields, SystemTime)) + return FALSE; + + if (SystemTime->QuadPart < CurrentTime->QuadPart) + return FALSE; + + return TRUE; + } + + /* + * Compute recurring cutover time + */ + + /* Day must be between 1(first) and 5(last) */ + if (CutoverTimeFields->Day == 0 || CutoverTimeFields->Day > 5) + return FALSE; + + RtlTimeToTimeFields(CurrentTime, &CurrentTimeFields); + + while (TRUE) + { + /* Compute the cutover time of the first day of the current month */ + AdjustedTimeFields.Year = CurrentTimeFields.Year; + if (NextYearsCutover == TRUE) + AdjustedTimeFields.Year++; + + AdjustedTimeFields.Month = CutoverTimeFields->Month; + AdjustedTimeFields.Day = 1; + AdjustedTimeFields.Hour = CutoverTimeFields->Hour; + AdjustedTimeFields.Minute = CutoverTimeFields->Minute; + AdjustedTimeFields.Second = CutoverTimeFields->Second; + AdjustedTimeFields.Milliseconds = CutoverTimeFields->Milliseconds; + + if (!RtlTimeFieldsToTime(&AdjustedTimeFields, &CutoverSystemTime)) + return FALSE; + + RtlTimeToTimeFields(&CutoverSystemTime, &CutoverSystemTimeFields); + + /* Adjust day to first matching weekday */ + if (CutoverSystemTimeFields.Weekday != CutoverTimeFields->Weekday) + { + if (CutoverSystemTimeFields.Weekday < CutoverTimeFields->Weekday) + Days = CutoverTimeFields->Weekday - CutoverSystemTimeFields.Weekday; + else + Days = DAYSPERWEEK - (CutoverSystemTimeFields.Weekday - CutoverTimeFields->Weekday); + + AdjustedTimeFields.Day += Days; + } + + /* Adjust the number of weeks */ + if (CutoverTimeFields->Day > 1) + { + Days = DAYSPERWEEK * (CutoverTimeFields->Day - 1); + MonthLength = MonthLengths[IsLeapYear(AdjustedTimeFields.Year)][AdjustedTimeFields.Month - 1]; + if ((AdjustedTimeFields.Day + Days) > MonthLength) + Days -= DAYSPERWEEK; + + AdjustedTimeFields.Day += Days; + } + + if (!RtlTimeFieldsToTime(&AdjustedTimeFields, &CutoverSystemTime)) + return FALSE; + + if (ThisYearsCutoverOnly == TRUE || + NextYearsCutover == TRUE || + CutoverSystemTime.QuadPart >= CurrentTime->QuadPart) + { + break; + } + + NextYearsCutover = TRUE; + } + + SystemTime->QuadPart = CutoverSystemTime.QuadPart; + + return TRUE; +} + + /* * @implemented */ BOOLEAN STDCALL RtlTimeFieldsToTime( - PTIME_FIELDS TimeFields, - PLARGE_INTEGER Time) + IN PTIME_FIELDS TimeFields, + OUT PLARGE_INTEGER Time) { int CurYear; int CurMonth; @@ -179,13 +276,13 @@ RtlTimeToElapsedTimeFields(IN PLARGE_INTEGER Time, /* - * @unimplemented + * @implemented */ VOID STDCALL RtlTimeToTimeFields( - PLARGE_INTEGER Time, - PTIME_FIELDS TimeFields) + IN PLARGE_INTEGER Time, + OUT PTIME_FIELDS TimeFields) { const int *Months; int SecondsInDay, CurYear; @@ -230,7 +327,6 @@ RtlTimeToTimeFields( Days += CurYear - CurYear / 4 + CurYear / 100 - CurYear / 400; CurYear++; Days -= EPOCHYEAR - 1 - (EPOCHYEAR -1) / 4 + (EPOCHYEAR -1) / 100 - (EPOCHYEAR - 1) / 400; - /* FIXME: handle calendar modifications */ while (1) { LeapYear = IsLeapYear(CurYear); @@ -259,8 +355,8 @@ RtlTimeToTimeFields( BOOLEAN STDCALL RtlTimeToSecondsSince1970( - PLARGE_INTEGER Time, - PULONG SecondsSince1970) + IN PLARGE_INTEGER Time, + OUT PULONG SecondsSince1970) { LARGE_INTEGER IntTime; @@ -282,8 +378,8 @@ RtlTimeToSecondsSince1970( BOOLEAN STDCALL RtlTimeToSecondsSince1980( - PLARGE_INTEGER Time, - PULONG SecondsSince1980) + IN PLARGE_INTEGER Time, + OUT PULONG SecondsSince1980) { LARGE_INTEGER IntTime; @@ -304,8 +400,8 @@ RtlTimeToSecondsSince1980( */ NTSTATUS STDCALL -RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime, - PLARGE_INTEGER SystemTime) +RtlLocalTimeToSystemTime(IN PLARGE_INTEGER LocalTime, + OUT PLARGE_INTEGER SystemTime) { SYSTEM_TIMEOFDAY_INFORMATION TimeInformation; NTSTATUS Status; @@ -315,12 +411,12 @@ RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime, sizeof(SYSTEM_TIMEOFDAY_INFORMATION), NULL); if (!NT_SUCCESS(Status)) - return(Status); + return Status; SystemTime->QuadPart = LocalTime->QuadPart + TimeInformation.TimeZoneBias.QuadPart; - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -329,8 +425,8 @@ RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime, */ NTSTATUS STDCALL -RtlSystemTimeToLocalTime(PLARGE_INTEGER SystemTime, - PLARGE_INTEGER LocalTime) +RtlSystemTimeToLocalTime(IN PLARGE_INTEGER SystemTime, + OUT PLARGE_INTEGER LocalTime) { SYSTEM_TIMEOFDAY_INFORMATION TimeInformation; NTSTATUS Status; @@ -340,36 +436,34 @@ RtlSystemTimeToLocalTime(PLARGE_INTEGER SystemTime, sizeof(SYSTEM_TIMEOFDAY_INFORMATION), NULL); if (!NT_SUCCESS(Status)) - return(Status); + return Status; LocalTime->QuadPart = SystemTime->QuadPart - TimeInformation.TimeZoneBias.QuadPart; - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } /* * @implemented */ -VOID -STDCALL +VOID STDCALL RtlSecondsSince1970ToTime( - ULONG SecondsSince1970, - PLARGE_INTEGER Time) + IN ULONG SecondsSince1970, + OUT PLARGE_INTEGER Time) { - Time->QuadPart = ((LONGLONG)SecondsSince1970 * TICKSPERSEC) + TICKSTO1970; + Time->QuadPart = ((LONGLONG)SecondsSince1970 * TICKSPERSEC) + TICKSTO1970; } /* * @implemented */ -VOID -STDCALL +VOID STDCALL RtlSecondsSince1980ToTime( - ULONG SecondsSince1980, - PLARGE_INTEGER Time) + IN ULONG SecondsSince1980, + OUT PLARGE_INTEGER Time) { Time->QuadPart = ((LONGLONG)SecondsSince1980 * TICKSPERSEC) + TICKSTO1980; } diff --git a/reactos/lib/rtl/unicode.c b/reactos/lib/rtl/unicode.c index 00158fbb345..9905fc9e6f4 100644 --- a/reactos/lib/rtl/unicode.c +++ b/reactos/lib/rtl/unicode.c @@ -2195,11 +2195,14 @@ RtlCopyString( return; } - copylen = min (DestinationString->MaximumLength - sizeof(CHAR), + copylen = min (DestinationString->MaximumLength, SourceString->Length); memcpy(DestinationString->Buffer, SourceString->Buffer, copylen); - DestinationString->Buffer[copylen] = 0; + if (DestinationString->MaximumLength >= copylen + sizeof(CHAR)) + { + DestinationString->Buffer[copylen] = 0; + } DestinationString->Length = copylen; } @@ -2222,10 +2225,13 @@ RtlCopyUnicodeString( return; } - copylen = min (DestinationString->MaximumLength - sizeof(WCHAR), + copylen = min (DestinationString->MaximumLength, SourceString->Length); memcpy(DestinationString->Buffer, SourceString->Buffer, copylen); - DestinationString->Buffer[copylen / sizeof(WCHAR)] = 0; + if (DestinationString->MaximumLength >= copylen + sizeof(WCHAR)) + { + DestinationString->Buffer[copylen / sizeof(WCHAR)] = 0; + } DestinationString->Length = copylen; } diff --git a/reactos/lib/rtl/version.c b/reactos/lib/rtl/version.c index 25d85e7980b..6a13c5e5241 100644 --- a/reactos/lib/rtl/version.c +++ b/reactos/lib/rtl/version.c @@ -36,7 +36,6 @@ /* GLOBALS ******************************************************************/ -extern ULONG NtGlobalFlag; /* FUNCTIONS ****************************************************************/ @@ -71,16 +70,6 @@ RtlGetVersion(RTL_OSVERSIONINFOW *Info) return STATUS_INVALID_PARAMETER; } -/* -* @implemented -*/ -ULONG -STDCALL -RtlGetNtGlobalFlags(VOID) -{ - return(NtGlobalFlag); -} - /* * @unimplemented */ diff --git a/reactos/lib/setupapi/Makefile b/reactos/lib/setupapi/Makefile deleted file mode 100644 index 5c2ab0a26c5..00000000000 --- a/reactos/lib/setupapi/Makefile +++ /dev/null @@ -1,415 +0,0 @@ -EXTRADEFS = -D_SETUPAPI_ -TOPSRCDIR = ../.. -TOPOBJDIR = ../.. -SRCDIR = . - -MODULE = setupapi.dll -IMPORTS = user32 version advapi32 rpcrt4 kernel32 ntdll -DELAYIMPORTS = shell32 -EXTRALIBS = $(LIBUNICODE) - -C_SRCS = \ - devinst.c \ - dirid.c \ - diskspace.c \ - install.c \ - misc.c \ - parser.c \ - queue.c \ - setupcab.c \ - stubs.c - -C_SRCS16 = \ - devinst16.c \ - infparse.c \ - setupx_main.c \ - virtcopy.c - -SPEC_SRCS16 = setupx.spec - -RC_SRCS= setupapi.rc - - -# Global rules for building dlls -*-Makefile-*- -# -# Each individual makefile should define the following variables: -# MODULE : name of the main module being built -# EXTRALIBS : extra libraries to link in (optional) -# SPEC_SRCS16 : interface definition files for 16-bit dlls (optional) -# SUBSYSTEM : (optional) subsystem (for native dlls) -# -# plus all variables required by the global Make.rules.in -# - -DLLDEFS = -DLLFLAGS = -D_REENTRANT -DLLEXT = -DEFS = -D__WINESRC__ $(DLLDEFS) $(EXTRADEFS) -MAINSPEC = $(MODULE:%.dll=%).spec -SPEC_DEF = $(MAINSPEC).def -WIN16_FILES = $(SPEC_SRCS16:.spec=.spec.o) $(C_SRCS16:.c=.o) $(EXTRA_OBJS16) -ALL_OBJS = $(OBJS) $(MODULE).dbg.o -ALL_LIBS = $(LIBWINE) $(EXTRALIBS) $(LIBPORT) $(LDFLAGS) $(LIBS) -IMPORTLIBS = $(DELAYIMPORTS:%=$(DLLDIR)/lib%.$(IMPLIBEXT)) $(IMPORTS:%=$(DLLDIR)/lib%.$(IMPLIBEXT)) - -all: $(MODULE)$(DLLEXT) $(SUBDIRS) - - -# Global rules shared by all makefiles -*-Makefile-*- -# -# Each individual makefile must define the following variables: -# TOPSRCDIR : top-level source directory -# TOPOBJDIR : top-level object directory -# SRCDIR : source directory for this module -# MODULE : name of the module being built -# -# Each individual makefile may define the following additional variables: -# C_SRCS : C sources for the module -# C_SRCS16 : 16-bit C sources for the module -# RC_SRCS : resource source files -# EXTRA_SRCS : extra source files for make depend -# EXTRA_OBJS : extra object files -# IMPORTS : dlls to import -# DELAYIMPORTS : dlls to import in delayed mode -# SUBDIRS : subdirectories that contain a Makefile -# EXTRASUBDIRS : subdirectories that do not contain a Makefile -# INSTALLSUBDIRS : subdirectories to run make install/uninstall into - -# First some useful definitions - -SHELL = /bin/sh -CC = mingw32-gcc -CFLAGS = -g -O2 -CPPFLAGS = -LIBS = -BISON = bison -YACC = $(BISON) -y -LEX = flex -LEXLIB = -EXEEXT = .exe -OBJEXT = o -LIBEXT = dll -DLLEXT = -IMPLIBEXT = a -LDSHARED = -DLLTOOL = mingw32-dlltool -DLLWRAP = mingw32-dllwrap -AR = mingw32-ar rc -RANLIB = mingw32-ranlib -STRIP = mingw32-strip -WINDRES = mingw32-windres -LN = ln -LN_S = ln -s -TOOLSDIR = /usr/src/wine-tools/ -AS = mingw32-as -LD = mingw32-ld -LDFLAGS = -RM = rm -f -MV = mv -LINT = -LINTFLAGS = -FONTFORGE = fontforge -INCLUDES = -I$(SRCDIR) -I. -I$(TOPSRCDIR)/include -I$(TOPOBJDIR)/include $(EXTRAINCL) -EXTRACFLAGS = -Wall -pipe -fno-strength-reduce -mpreferred-stack-boundary=2 -fno-strict-aliasing -gstabs+ -Wpointer-arith -ALLCFLAGS = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS) -ALLLINTFLAGS = $(INCLUDES) $(DEFS) $(LINTFLAGS) -IDLFLAGS = $(INCLUDES) $(DEFS) $(EXTRAIDLFLAGS) -MKINSTALLDIRS= $(TOPSRCDIR)/tools/mkinstalldirs -m 755 -WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check -WINEWRAPPER = $(TOPSRCDIR)/tools/winewrapper -C2MAN = $(TOPSRCDIR)/tools/c2man.pl -RUNTEST = $(TOPSRCDIR)/tools/runtest -WINEBUILD = $(TOOLSDIR)/tools/winebuild/winebuild -MAKEDEP = $(TOOLSDIR)/tools/makedep -WRC = $(TOOLSDIR)/tools/wrc/wrc -BIN2RES = $(TOOLSDIR)/tools/bin2res -WMC = $(TOOLSDIR)/tools/wmc/wmc -WIDL = $(TOOLSDIR)/tools/widl/widl -WINEGCC = $(TOOLSDIR)/tools/winegcc/winegcc -SFNT2FNT = $(TOOLSDIR)/tools/sfnt2fnt -FNT2FON = $(TOOLSDIR)/tools/fnt2fon -RC = $(WRC) -RC16 = $(WRC) -RCFLAGS = --nostdinc $(INCLUDES) $(DEFS) $(EXTRARCFLAGS) -RC16FLAGS = -O res16 $(RCFLAGS) -LDPATH = LD_LIBRARY_PATH="$(TOOLSDIR)/libs/unicode:$$LD_LIBRARY_PATH" -DLLDIR = $(TOPOBJDIR)/dlls -LIBDIR = $(TOPOBJDIR)/libs -LIBPORT = -L$(TOPOBJDIR)/libs/port -lwine_port -LIBUNICODE = -L$(TOPOBJDIR)/libs/unicode -lwine_unicode -LIBWINE = -L$(TOPOBJDIR)/libs/wine -lwine - - - -# Installation infos - -INSTALL = /usr/bin/ginstall -c $(INSTALL_FLAGS) -INSTALL_PROGRAM = ${INSTALL} $(INSTALL_PROGRAM_FLAGS) -INSTALL_SCRIPT = ${INSTALL} $(INSTALL_SCRIPT_FLAGS) -INSTALL_DATA = ${INSTALL} -m 644 $(INSTALL_DATA_FLAGS) -prefix = /usr/local -exec_prefix = ${prefix} -bindir = ${exec_prefix}/bin -libdir = ${exec_prefix}/lib -datadir = ${prefix}/share -infodir = ${prefix}/info -mandir = ${prefix}/man -sysconfdir = ${prefix}/etc -includedir = ${prefix}/include/wine -dlldir = ${exec_prefix}/lib/wine -prog_manext = 1 -api_manext = 3w -conf_manext = 5 -CLEAN_FILES = *.o *.a *.so *.ln *.$(LIBEXT) \\\#*\\\# *~ *% .\\\#* *.bak *.orig *.rej \ - *.flc *.spec.c *.spec.def *.dbg.c *.tab.c *.tab.h lex.yy.c core - -OBJS = $(C_SRCS:.c=.o) $(EXTRA_OBJS) - -RCOBJS = $(RC_SRCS:.rc=.res.o) -LINTS = $(C_SRCS:.c=.ln) - -# Implicit rules - -.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.c .spec.def .idl .h .ok .sfd .ttf - -.c.o: - $(CC) -c $(ALLCFLAGS) -o $@ $< - -.s.o: - $(AS) -o $@ $< - -.mc.mc.rc: - $(LDPATH) $(WMC) -i -U -H /dev/null -o $@ $< - -.rc.res: - $(LDPATH) $(RC) $(RCFLAGS) -fo$@ $< - -.res.res.o: - $(WINDRES) -i $< -o $@ - -.spec.spec.c: - $(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $< - -.spec.spec.def: - $(WINEBUILD) -w $(DEFS) -o $@ --def $< - -.idl.h: - $(WIDL) $(IDLFLAGS) -h -H $@ $< - -.c.ln: - $(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 ) - -.c.ok: - $(RUNTEST) $(RUNTESTFLAGS) $< && touch $@ - -.sfd.ttf: - $(FONTFORGE) -script $(TOPSRCDIR)/fonts/genttf.ff $< - -# 'all' target first in case the enclosing Makefile didn't define any target - -all: Makefile - -filter: - @$(TOPSRCDIR)/tools/winapi/make_filter --make $(MAKE) all - -.PHONY: all filter - -# Rules for resources - -$(RC_BINARIES): $(BIN2RES) $(RC_BINSRC) - $(BIN2RES) -f -o $@ $(SRCDIR)/$(RC_BINSRC) - -$(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res): $(WRC) $(RC_BINARIES) - -# Rule for main module debug channels - -$(MODULE).dbg.c: $(C_SRCS) $(C_SRCS16) $(WINEBUILD) - $(WINEBUILD) $(DEFS) -o $@ --debug -C$(SRCDIR) $(C_SRCS) $(C_SRCS16) - -# Rules for makefile - -Makefile: Makefile.in $(TOPSRCDIR)/configure - @echo Makefile is older than $?, please rerun $(TOPSRCDIR)/configure - @exit 1 - -# Rule for linting - -$(MODULE).ln : $(LINTS) - if test "$(LINTS)" ; \ - then \ - $(LINT) $(ALLLINTFLAGS) -o$(MODULE) $(LINTS) ; \ - $(MV) llib-l$(MODULE).ln $(MODULE).ln ; \ - else \ - $(LINT) $(ALLLINTFLAGS) -C$(MODULE) /dev/null ; \ - fi - -lint:: $(MODULE).ln - -# Rules for Windows API checking - -winapi_check:: dummy - $(WINAPI_CHECK) $(WINAPI_CHECK_FLAGS) $(WINAPI_CHECK_EXTRA_FLAGS) . - -.PHONY: winapi_check - -# Rules for dependencies - -$(SUBDIRS:%=%/__depend__): dummy - cd `dirname $@` && $(MAKE) depend - -depend: $(IDL_SRCS:.idl=.h) $(SUBDIRS:%=%/__depend__) - $(MAKEDEP) $(INCLUDES) -C$(SRCDIR) $(C_SRCS) $(C_SRCS16) $(RC_SRCS) $(RC_SRCS16) $(MC_SRCS) $(IDL_SRCS) $(EXTRA_SRCS) - -.PHONY: depend $(SUBDIRS:%=%/__depend__) - -# Rules for cleaning - -$(SUBDIRS:%=%/__clean__): dummy - cd `dirname $@` && $(MAKE) clean - -$(SUBDIRS:%=%/__testclean__): dummy - cd `dirname $@` && $(MAKE) testclean - -$(EXTRASUBDIRS:%=%/__clean__): dummy - -cd `dirname $@` && $(RM) $(CLEAN_FILES) - -testclean:: $(SUBDIRS:%=%/__testclean__) - -clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__) - $(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(IDL_SRCS:.idl=.h) $(PROGRAMS) $(RC_BINARIES) - -.PHONY: clean testclean $(SUBDIRS:%=%/__clean__) $(SUBDIRS:%=%/__testclean__) $(EXTRASUBDIRS:%=%/__clean__) - -# Rules for installing - -$(SUBDIRS:%=%/__install__): dummy - cd `dirname $@` && $(MAKE) install - -$(SUBDIRS:%=%/__install-lib__): dummy - cd `dirname $@` && $(MAKE) install-lib - -$(SUBDIRS:%=%/__install-dev__): dummy - cd `dirname $@` && $(MAKE) install-dev - -$(SUBDIRS:%=%/__uninstall__): dummy - cd `dirname $@` && $(MAKE) uninstall - -install:: $(INSTALLSUBDIRS:%=%/__install__) - -uninstall:: $(INSTALLSUBDIRS:%=%/__uninstall__) - -.PHONY: install install-lib install-dev uninstall \ - $(SUBDIRS:%=%/__install__) $(SUBDIRS:%=%/__uninstall__) \ - $(SUBDIRS:%=%/__install-lib__) $(SUBDIRS:%=%/__install-dev__) - -# Rules for checking that no imports are missing - -$(SUBDIRS:%=%/__checklink__): dummy - @cd `dirname $@` && $(MAKE) checklink - -.PHONY: checklink $(SUBDIRS:%=%/__checklink__) - -# Rules for testing - -$(SUBDIRS:%=%/__test__): dummy - @cd `dirname $@` && $(MAKE) test - -$(SUBDIRS:%=%/__crosstest__): dummy - @cd `dirname $@` && $(MAKE) crosstest - -.PHONY: check test crosstest $(SUBDIRS:%=%/__test__) $(SUBDIRS:%=%/__crosstest__) - -# Misc. rules - -$(MC_SRCS:.mc=.mc.rc): $(WMC) - -$(IDL_SRCS:.idl=.h): $(WIDL) - -$(SUBDIRS): dummy - @cd $@ && $(MAKE) - -dummy: - -.PHONY: dummy $(SUBDIRS) - -# End of global rules - -# Rules for .so files - -$(MODULE).so: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) Makefile.in - $(WINEGCC) -B$(TOOLSDIR)/tools/winebuild -shared $(SRCDIR)/$(MAINSPEC) $(ALL_OBJS) $(RC_SRCS:.rc=.res) $(SUBSYSTEM:%=-Wb,--subsystem,%) -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(IMPORTS:%=-l%) $(ALL_LIBS) - -# Rules for .dll files - -$(MODULE): $(RCOBJS) $(OBJS) $(MODULE).dbg.o $(SPEC_DEF) $(IMPORTLIBS) Makefile.in - $(DLLWRAP) -k --def $(SPEC_DEF) -o $@ $(RCOBJS) $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(ALL_LIBS) - -$(SPEC_DEF): $(WINEBUILD) - -# Rules for checking that no imports are missing - -.PHONY: checklink16 $(WIN16_FILES:%=__checklink16__%) - -$(WIN16_FILES:%=__checklink16__%): checklink16 - -checklink16:: $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o dummy - $(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) -lm && $(RM) checklink $(MAINSPEC).c $(MAINSPEC).o - -checklink:: $(WIN16_FILES:%=__checklink16__%) - -# Rules for testing - -check test:: $(SUBDIRS:%=%/__test__) - -crosstest:: $(SUBDIRS:%=%/__crosstest__) - -# Rule to explicitly generate the .spec.c for debugging - -$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD) - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) - -# Rules for auto documentation - -man: $(C_SRCS) - $(C2MAN) -o $(TOPOBJDIR)/documentation/man$(api_manext) -R$(TOPOBJDIR) -S$(api_manext) $(INCLUDES) $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16) - -doc-html: $(C_SRCS) - $(C2MAN) -o $(TOPOBJDIR)/documentation/html -R$(TOPSRCDIR) $(INCLUDES) -Th $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16) - -doc-sgml: $(C_SRCS) - $(C2MAN) -o $(TOPOBJDIR)/documentation/api-guide -R$(TOPSRCDIR) $(INCLUDES) -Ts $(MAINSPEC:%=-w %) $(SPEC_SRCS16:%=-w %) $(C_SRCS) $(C_SRCS16) - -.PHONY: man doc-html doc-sgml - -# Rules for installation - -EXE_SPECS16 = $(SPEC_SRCS16:.exe.spec=.exe) -DRV_SPECS16 = $(EXE_SPECS16:.drv.spec=.drv) -ALL_SPECS16 = $(DRV_SPECS16:.spec=.dll) - -WIN16_INSTALL = $(ALL_SPECS16:%=_install_/%) - -.PHONY: install_lib $(ALL_SPECS16:%=_install_/%) $(ALL_SPECS16:%=_uninstall_/%) - -$(ALL_SPECS16:%=_install_/%): install_lib - cd $(dlldir) && $(RM) `basename $@`$(DLLEXT) && $(LN_S) $(MODULE)$(DLLEXT) `basename $@`$(DLLEXT) - -$(ALL_SPECS16:%=_uninstall_/%): dummy - $(RM) $(dlldir)/`basename $@`$(DLLEXT) - -install_lib: $(MODULE)$(DLLEXT) - $(MKINSTALLDIRS) $(dlldir) - $(INSTALL_PROGRAM) $(MODULE)$(DLLEXT) $(dlldir)/$(MODULE)$(DLLEXT) - -install:: install_lib - -uninstall:: $(ALL_SPECS16:%=_uninstall_/%) - $(RM) $(dlldir)/$(MODULE)$(DLLEXT) - -# Misc. rules - -$(SPEC_SRCS16:.spec=.spec.c): $(WINEBUILD) - -# End of global dll rules - -### Dependencies: diff --git a/reactos/lib/setupapi/Makefile.ros-template b/reactos/lib/setupapi/Makefile.ros-template new file mode 100644 index 00000000000..47cbad73413 --- /dev/null +++ b/reactos/lib/setupapi/Makefile.ros-template @@ -0,0 +1,21 @@ +# $Id: Makefile.ros-template 12852 2005-01-06 13:58:04Z mf $ + +TARGET_NAME = setupapi + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ -D__WINESRC__ + +TARGET_SDKLIBS = @IMPORTS@ wine.a ntdll.a wine_unicode.a + +TARGET_BASE = $(TARGET_BASE_LIB_SETUPAPI) + +TARGET_RC_SRCS = @RC_SRCS@ +TARGET_RC_BINSRC = @RC_BINSRC@ +TARGET_RC_BINARIES = @RC_BINARIES@ + +default: all + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/setupapi/devinst.c b/reactos/lib/setupapi/devinst.c index da423c9d504..645dbb92574 100644 --- a/reactos/lib/setupapi/devinst.c +++ b/reactos/lib/setupapi/devinst.c @@ -20,7 +20,7 @@ #include "config.h" #include "wine/port.h" - + #include #include "windef.h" @@ -38,6 +38,8 @@ #include "rpc.h" #include "rpcdce.h" +#include "setupapi_private.h" + WINE_DEFAULT_DEBUG_CHANNEL(setupapi); @@ -90,8 +92,26 @@ BOOL WINAPI SetupDiBuildClassInfoListExA( LPCSTR MachineName, PVOID Reserved) { - FIXME("\n"); - return FALSE; + LPWSTR MachineNameW = NULL; + BOOL bResult; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return FALSE; + } + + bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return bResult; } /*********************************************************************** @@ -237,9 +257,9 @@ BOOL WINAPI SetupDiClassGuidsFromNameA( DWORD ClassGuidListSize, PDWORD RequiredSize) { - return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); + return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); } /*********************************************************************** @@ -251,9 +271,9 @@ BOOL WINAPI SetupDiClassGuidsFromNameW( DWORD ClassGuidListSize, PDWORD RequiredSize) { - return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, - ClassGuidListSize, RequiredSize, - NULL, NULL); + return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, + ClassGuidListSize, RequiredSize, + NULL, NULL); } /*********************************************************************** @@ -267,8 +287,36 @@ BOOL WINAPI SetupDiClassGuidsFromNameExA( LPCSTR MachineName, PVOID Reserved) { - FIXME("\n"); - return FALSE; + LPWSTR ClassNameW = NULL; + LPWSTR MachineNameW = NULL; + BOOL bResult; + + FIXME("\n"); + + ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); + if (ClassNameW == NULL) + return FALSE; + + if (MachineNameW) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + { + MyFree(ClassNameW); + return FALSE; + } + } + + bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, + ClassGuidListSize, RequiredSize, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + MyFree(ClassNameW); + + return bResult; } /*********************************************************************** @@ -502,8 +550,25 @@ SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, PCSTR MachineName, PVOID Reserved) { - FIXME("\n"); - return (HDEVINFO)INVALID_HANDLE_VALUE; + LPWSTR MachineNameW = NULL; + HDEVINFO hDevInfo; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return (HDEVINFO)INVALID_HANDLE_VALUE; + } + + hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, + MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return hDevInfo; } /*********************************************************************** @@ -587,17 +652,10 @@ BOOL WINAPI SetupDiGetActualSectionToInstallW( PWSTR *Extension) { WCHAR szBuffer[MAX_PATH]; - OSVERSIONINFOW OsVersionInfo; DWORD dwLength; DWORD dwFullLength; LONG lLineCount = -1; - OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); - if (!GetVersionExW(&OsVersionInfo)) - { - return FALSE; - } - lstrcpyW(szBuffer, InfSectionName); dwLength = lstrlenW(szBuffer); @@ -1048,8 +1106,25 @@ HKEY WINAPI SetupDiOpenClassRegKeyExA( PCSTR MachineName, PVOID Reserved) { - FIXME("\n"); - return INVALID_HANDLE_VALUE; + PWSTR MachineNameW = NULL; + HKEY hKey; + + TRACE("\n"); + + if (MachineName) + { + MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); + if (MachineNameW == NULL) + return INVALID_HANDLE_VALUE; + } + + hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, + Flags, MachineNameW, Reserved); + + if (MachineNameW) + MyFree(MachineNameW); + + return hKey; } @@ -1125,7 +1200,7 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW( } /*********************************************************************** - * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) + * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) */ BOOL WINAPI SetupDiOpenDeviceInterfaceW( HDEVINFO DeviceInfoSet, diff --git a/reactos/lib/setupapi/misc.c b/reactos/lib/setupapi/misc.c index dfbe49bb047..218da19fd35 100644 --- a/reactos/lib/setupapi/misc.c +++ b/reactos/lib/setupapi/misc.c @@ -28,6 +28,12 @@ #include "setupapi.h" #include "wine/unicode.h" +#include "wine/debug.h" + +#include "setupapi_private.h" + + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); /************************************************************************** @@ -41,9 +47,9 @@ * RETURNS * None */ - VOID WINAPI MyFree(LPVOID lpMem) { + TRACE("%p\n", lpMem); HeapFree(GetProcessHeap(), 0, lpMem); } @@ -60,9 +66,9 @@ VOID WINAPI MyFree(LPVOID lpMem) * Success: pointer to allocated memory block * Failure: NULL */ - LPVOID WINAPI MyMalloc(DWORD dwSize) { + TRACE("%lu\n", dwSize); return HeapAlloc(GetProcessHeap(), 0, dwSize); } @@ -85,9 +91,10 @@ LPVOID WINAPI MyMalloc(DWORD dwSize) * If lpSrc is a NULL-pointer, then MyRealloc allocates a memory * block like MyMalloc. */ - LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize) { + TRACE("%p %lu\n", lpSrc, dwSize); + if (lpSrc == NULL) return HeapAlloc(GetProcessHeap(), 0, dwSize); @@ -110,11 +117,12 @@ LPVOID WINAPI MyRealloc(LPVOID lpSrc, DWORD dwSize) * NOTES * Call MyFree() to release the duplicated string. */ - LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc) { LPWSTR lpDst; + TRACE("%s\n", debugstr_w(lpSrc)); + lpDst = MyMalloc((lstrlenW(lpSrc) + 1) * sizeof(WCHAR)); if (lpDst == NULL) return NULL; @@ -145,7 +153,6 @@ LPWSTR WINAPI DuplicateString(LPCWSTR lpSrc) * NOTES * Use MyFree to release the lpData buffer. */ - LONG WINAPI QueryRegistryValue(HKEY hKey, LPCWSTR lpValueName, LPBYTE *lpData, @@ -154,6 +161,9 @@ LONG WINAPI QueryRegistryValue(HKEY hKey, { LONG lError; + TRACE("%lx %s %p %p %p\n", + hKey, debugstr_w(lpValueName), lpData, lpType, lpcbData); + /* Get required buffer size */ *lpcbData = 0; lError = RegQueryValueExW(hKey, lpValueName, 0, lpType, NULL, lpcbData); @@ -172,3 +182,322 @@ LONG WINAPI QueryRegistryValue(HKEY hKey, return lError; } + + +/************************************************************************** + * IsUserAdmin [SETUPAPI.@] + * + * Checks whether the current user is a member of the Administrators group. + * + * PARAMS + * None + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI IsUserAdmin(VOID) +{ + SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; + HANDLE hToken; + DWORD dwSize; + PTOKEN_GROUPS lpGroups; + PSID lpSid; + DWORD i; + BOOL bResult = FALSE; + + TRACE("\n"); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } + } + + lpGroups = MyMalloc(dwSize); + if (lpGroups == NULL) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) + { + MyFree(lpGroups); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + + if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &lpSid)) + { + MyFree(lpGroups); + return FALSE; + } + + for (i = 0; i < lpGroups->GroupCount; i++) + { + if (EqualSid(lpSid, &lpGroups->Groups[i].Sid)) + { + bResult = TRUE; + break; + } + } + + FreeSid(lpSid); + MyFree(lpGroups); + + return bResult; +} + + +/************************************************************************** + * MultiByteToUnicode [SETUPAPI.@] + * + * Converts a multi-byte string to a Unicode string. + * + * PARAMS + * lpMultiByteStr [I] Multi-byte string to be converted + * uCodePage [I] Code page + * + * RETURNS + * Success: pointer to the converted Unicode string + * Failure: NULL + * + * NOTE + * Use MyFree to release the returned Unicode string. + */ +LPWSTR WINAPI MultiByteToUnicode(LPCSTR lpMultiByteStr, UINT uCodePage) +{ + LPWSTR lpUnicodeStr; + int nLength; + + TRACE("%s %lu\n", debugstr_a(lpMultiByteStr), uCodePage); + + nLength = MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, + -1, NULL, 0); + if (nLength == 0) + return NULL; + + lpUnicodeStr = MyMalloc(nLength * sizeof(WCHAR)); + if (lpUnicodeStr == NULL) + return NULL; + + if (!MultiByteToWideChar(uCodePage, 0, lpMultiByteStr, + nLength, lpUnicodeStr, nLength)) + { + MyFree(lpUnicodeStr); + return NULL; + } + + return lpUnicodeStr; +} + + +/************************************************************************** + * UnicodeToMultiByte [SETUPAPI.@] + * + * Converts a Unicode string to a multi-byte string. + * + * PARAMS + * lpUnicodeStr [I] Unicode string to be converted + * uCodePage [I] Code page + * + * RETURNS + * Success: pointer to the converted multi-byte string + * Failure: NULL + * + * NOTE + * Use MyFree to release the returned multi-byte string. + */ +LPSTR WINAPI UnicodeToMultiByte(LPCWSTR lpUnicodeStr, UINT uCodePage) +{ + LPSTR lpMultiByteStr; + int nLength; + + TRACE("%s %lu\n", debugstr_w(lpUnicodeStr), uCodePage); + + nLength = WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, + NULL, 0, NULL, NULL); + if (nLength == 0) + return NULL; + + lpMultiByteStr = MyMalloc(nLength); + if (lpMultiByteStr == NULL) + return NULL; + + if (!WideCharToMultiByte(uCodePage, 0, lpUnicodeStr, -1, + lpMultiByteStr, nLength, NULL, NULL)) + { + MyFree(lpMultiByteStr); + return NULL; + } + + return lpMultiByteStr; +} + + +/************************************************************************** + * DoesUserHavePrivilege [SETUPAPI.@] + * + * Check whether the current user has got a given privilege. + * + * PARAMS + * lpPrivilegeName [I] Name of the privilege to be checked + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DoesUserHavePrivilege(LPCWSTR lpPrivilegeName) +{ + HANDLE hToken; + DWORD dwSize; + PTOKEN_PRIVILEGES lpPrivileges; + LUID PrivilegeLuid; + DWORD i; + BOOL bResult = FALSE; + + TRACE("%s\n", debugstr_w(lpPrivilegeName)); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return FALSE; + + if (!GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } + } + + lpPrivileges = MyMalloc(dwSize); + if (lpPrivileges == NULL) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenPrivileges, lpPrivileges, dwSize, &dwSize)) + { + MyFree(lpPrivileges); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + + if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, &PrivilegeLuid)) + { + MyFree(lpPrivileges); + return FALSE; + } + + for (i = 0; i < lpPrivileges->PrivilegeCount; i++) + { + if (lpPrivileges->Privileges[i].Luid.HighPart == PrivilegeLuid.HighPart && + lpPrivileges->Privileges[i].Luid.LowPart == PrivilegeLuid.LowPart) + { + bResult = TRUE; + } + } + + MyFree(lpPrivileges); + + return bResult; +} + + +/************************************************************************** + * EnablePrivilege [SETUPAPI.@] + * + * Enables or disables one of the current users privileges. + * + * PARAMS + * lpPrivilegeName [I] Name of the privilege to be changed + * bEnable [I] TRUE: Enables the privilege + * FALSE: Disables the privilege + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI EnablePrivilege(LPCWSTR lpPrivilegeName, BOOL bEnable) +{ + TOKEN_PRIVILEGES Privileges; + HANDLE hToken; + BOOL bResult; + + TRACE("%s %s\n", debugstr_w(lpPrivilegeName), bEnable ? "TRUE" : "FALSE"); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return FALSE; + + Privileges.PrivilegeCount = 1; + Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0; + + if (!LookupPrivilegeValueW(NULL, lpPrivilegeName, + &Privileges.Privileges[0].Luid)) + { + CloseHandle(hToken); + return FALSE; + } + + bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL); + + CloseHandle(hToken); + + return bResult; +} + + +BOOL WINAPI DelayedMove(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName) +{ + if (OsVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + return MoveFileExW(lpExistingFileName, lpNewFileName, + MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT); +} + + +BOOL WINAPI FileExists(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFileFindData) +{ + WIN32_FIND_DATAW FindData; + HANDLE hFind; + UINT uErrorMode; + DWORD dwError; + + uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); + + hFind = FindFirstFileW(lpFileName, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + { + dwError = GetLastError(); + SetErrorMode(uErrorMode); + SetLastError(dwError); + return FALSE; + } + + FindClose(hFind); + + if (lpFileFindData) + memcpy(lpFileFindData, &FindData, sizeof(WIN32_FIND_DATAW)); + + return TRUE; +} diff --git a/reactos/lib/setupapi/setupapi.spec b/reactos/lib/setupapi/setupapi.spec index 22a164c6716..10ed72a4980 100644 --- a/reactos/lib/setupapi/setupapi.spec +++ b/reactos/lib/setupapi/setupapi.spec @@ -97,8 +97,6 @@ @ stub CM_Get_Device_Interface_List_SizeW @ stub CM_Get_Device_Interface_List_Size_ExA @ stub CM_Get_Device_Interface_List_Size_ExW -@ stub CM_Request_Device_EjectA -@ stub CM_Request_Device_EjectW @ stub CM_Get_First_Log_Conf @ stub CM_Get_First_Log_Conf_Ex @ stub CM_Get_Global_State @@ -164,6 +162,8 @@ @ stub CM_Remove_SubTree_Ex @ stub CM_Remove_Unmarked_Children @ stub CM_Remove_Unmarked_Children_Ex +@ stub CM_Request_Device_EjectA +@ stub CM_Request_Device_EjectW @ stub CM_Request_Eject_PC @ stub CM_Reset_Children_Marks @ stub CM_Reset_Children_Marks_Ex @@ -194,14 +194,14 @@ @ stub CaptureStringArg @ stub CenterWindowRelativeToParent @ stub ConcatenatePaths -@ stub DelayedMove +@ stdcall DelayedMove(wstr wstr) @ stub DelimStringToMultiSz @ stub DestroyTextFileReadBuffer -@ stub DoesUserHavePrivilege +@ stdcall DoesUserHavePrivilege(wstr) @ stdcall DuplicateString(wstr) -@ stub EnablePrivilege +@ stdcall EnablePrivilege(wstr long) @ stub ExtensionPropSheetPageProc -@ stub FileExists +@ stdcall FileExists(wstr ptr) @ stub FreeStringArray @ stub GetCurrentDriverSigningPolicy @ stub GetNewInfName @@ -214,10 +214,10 @@ @ stdcall InstallHinfSectionW(long long wstr long) @ stub InstallStop @ stub InstallStopEx -@ stub IsUserAdmin +@ stdcall IsUserAdmin() @ stub LookUpStringInTable @ stub MemoryInitialize -@ stub MultiByteToUnicode +@ stdcall MultiByteToUnicode(str long) @ stub MultiSzFromSearchControl @ stdcall MyFree(ptr) @ stub MyGetFileTitle @@ -527,7 +527,7 @@ @ stub StringTableStringFromId @ stub StringTableTrim @ stub TakeOwnershipOfFile -@ stub UnicodeToMultiByte +@ stdcall UnicodeToMultiByte(wstr long) @ stub UnmapAndCloseFile @ stub VerifyCatalogFile @ stub VerifyFile diff --git a/reactos/lib/setupapi/setupapi.xml b/reactos/lib/setupapi/setupapi.xml index bab6a004fd3..7e0c2aa066d 100644 --- a/reactos/lib/setupapi/setupapi.xml +++ b/reactos/lib/setupapi/setupapi.xml @@ -24,6 +24,7 @@ dirid.c diskspace.c install.c + misc.c parser.c queue.c setupcab.c diff --git a/reactos/lib/setupapi/setupapi_private.h b/reactos/lib/setupapi/setupapi_private.h index 7cd40e4f146..80d1f5559c2 100644 --- a/reactos/lib/setupapi/setupapi_private.h +++ b/reactos/lib/setupapi/setupapi_private.h @@ -54,4 +54,6 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification, UINT_PTR, U #define _S_IWRITE 0x0080 #define _S_IREAD 0x0100 +extern OSVERSIONINFOW OsVersionInfo; + #endif /* __SETUPAPI_PRIVATE_H */ diff --git a/reactos/lib/setupapi/setupcab.c b/reactos/lib/setupapi/setupcab.c index 6fc3001ca49..9c1081337a9 100644 --- a/reactos/lib/setupapi/setupcab.c +++ b/reactos/lib/setupapi/setupcab.c @@ -39,11 +39,13 @@ #include "fdi.h" #include "wine/unicode.h" -#include "msvcrt/fcntl.h" -#include "msvcrt/share.h" +#include "fcntl.h" +#include "share.h" #include "wine/debug.h" +OSVERSIONINFOW OsVersionInfo; + static HINSTANCE CABINET_hInstance = 0; static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN, @@ -674,6 +676,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) switch (fdwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); + OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (!GetVersionExW(&OsVersionInfo)) + return FALSE; break; case DLL_PROCESS_DETACH: UnloadCABINETDll(); diff --git a/reactos/lib/shdocvw/shdocvw_main.c b/reactos/lib/shdocvw/shdocvw_main.c index 78d81ae1120..72a9b173cea 100644 --- a/reactos/lib/shdocvw/shdocvw_main.c +++ b/reactos/lib/shdocvw/shdocvw_main.c @@ -414,7 +414,6 @@ static BOOL SHDOCVW_TryLoadMozillaControl() SHDOCVW_TryDownloadMozillaControl(); bTried = TRUE; } - return TRUE; } /************************************************************************* diff --git a/reactos/lib/shell32/Makefile.in b/reactos/lib/shell32/Makefile.in index 393750a5cbc..36b71403ad8 100644 --- a/reactos/lib/shell32/Makefile.in +++ b/reactos/lib/shell32/Makefile.in @@ -1,92 +1,92 @@ -EXTRADEFS = -D_SHELL32_ -DCOM_NO_WINDOWS_H -TOPSRCDIR = @top_srcdir@ -TOPOBJDIR = ../.. -SRCDIR = @srcdir@ -VPATH = @srcdir@ -MODULE = shell32.dll -IMPORTS = shlwapi comctl32 user32 gdi32 advapi32 kernel32 -DELAYIMPORTS = ole32 -EXTRALIBS = -luuid $(LIBUNICODE) - -C_SRCS = \ - authors.c \ - autocomplete.c \ - brsfolder.c \ - changenotify.c \ - classes.c \ - clipboard.c \ - control.c \ - cpanelfolder.c \ - dataobject.c \ - debughlp.c \ - dialogs.c \ - dragdrophelper.c \ - enumidlist.c \ - folders.c \ - iconcache.c \ - memorystream.c \ - pidl.c \ - regsvr.c \ - shell32_main.c \ - shelllink.c \ - shellole.c \ - shellord.c \ - shellpath.c \ - shellreg.c \ - shellstring.c \ - shfldr_desktop.c \ - shfldr_fs.c \ - shfldr_mycomp.c \ - shlexec.c \ - shlfileop.c \ - shlfolder.c \ - shlfsbind.c \ - shlmenu.c \ - shlview.c \ - shpolicy.c \ - shv_bg_cmenu.c \ - shv_item_cmenu.c \ - ros-systray.c - -RC_SRCS = shres.rc -RC_BINSRC = shres.rc -RC_BINARIES = \ - cdrom.ico \ - desktop.ico \ - document.ico \ - drive.ico \ - floppy.ico \ - folder.ico \ - folder_open.ico \ - mycomputer.ico \ - netdrive.ico \ - netdrive2.ico \ - ramdisk.ico - -C_SRCS16 = shell.c -RC_SRCS16 = version16.rc -SPEC_SRCS16 = shell.spec - -SUBDIRS = tests - -@MAKE_DLL_RULES@ - -# Special rules for 16-bit resource files - -version16.res: version16.rc - $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc - -shell.spec.c: shell.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/shell.spec - -authors.c: $(TOPSRCDIR)/AUTHORS - (LC_ALL=C; export LC_ALL; echo 'const char * const SHELL_Authors[] = {' && \ - sed -e '1,2d' -e 's/\(.*\)/ \"\1\",/' $(TOPSRCDIR)/AUTHORS && \ - echo ' 0 };') >$@ || ($(RM) $@ && false) - -depend: authors.c - -clean:: - $(RM) authors.c - -### Dependencies: +EXTRADEFS = -D_SHELL32_ -DCOM_NO_WINDOWS_H +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = shell32.dll +IMPORTS = shlwapi comctl32 user32 gdi32 advapi32 kernel32 +DELAYIMPORTS = ole32 +EXTRALIBS = -luuid $(LIBUNICODE) + +C_SRCS = \ + authors.c \ + autocomplete.c \ + brsfolder.c \ + changenotify.c \ + classes.c \ + clipboard.c \ + control.c \ + cpanelfolder.c \ + dataobject.c \ + debughlp.c \ + dialogs.c \ + dragdrophelper.c \ + enumidlist.c \ + folders.c \ + iconcache.c \ + memorystream.c \ + pidl.c \ + regsvr.c \ + shell32_main.c \ + shelllink.c \ + shellole.c \ + shellord.c \ + shellpath.c \ + shellreg.c \ + shellstring.c \ + shfldr_desktop.c \ + shfldr_fs.c \ + shfldr_mycomp.c \ + shlexec.c \ + shlfileop.c \ + shlfolder.c \ + shlfsbind.c \ + shlmenu.c \ + shlview.c \ + shpolicy.c \ + shv_bg_cmenu.c \ + shv_item_cmenu.c \ + ros-systray.c + +RC_SRCS = shres.rc +RC_BINSRC = shres.rc +RC_BINARIES = \ + cdrom.ico \ + desktop.ico \ + document.ico \ + drive.ico \ + floppy.ico \ + folder.ico \ + folder_open.ico \ + mycomputer.ico \ + netdrive.ico \ + netdrive2.ico \ + ramdisk.ico + +C_SRCS16 = shell.c +RC_SRCS16 = version16.rc +SPEC_SRCS16 = shell.spec + +SUBDIRS = tests + +@MAKE_DLL_RULES@ + +# Special rules for 16-bit resource files + +version16.res: version16.rc + $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc + +shell.spec.c: shell.spec version16.res + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/shell.spec + +authors.c: $(TOPSRCDIR)/AUTHORS + (LC_ALL=C; export LC_ALL; echo 'const char * const SHELL_Authors[] = {' && \ + sed -e '1,2d' -e 's/\(.*\)/ \"\1\",/' $(TOPSRCDIR)/AUTHORS && \ + echo ' 0 };') >$@ || ($(RM) $@ && false) + +depend: authors.c + +clean:: + $(RM) authors.c + +### Dependencies: diff --git a/reactos/lib/shell32/Makefile.ros-template b/reactos/lib/shell32/Makefile.ros-template index 4321122536a..1268c4a1dde 100644 --- a/reactos/lib/shell32/Makefile.ros-template +++ b/reactos/lib/shell32/Makefile.ros-template @@ -1,30 +1,30 @@ -# $Id: Makefile.ros-template 11910 2004-12-03 23:37:44Z blight $ - -TARGET_NAME = shell32 - -TARGET_OBJECTS = @C_SRCS@ - -TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ - -TARGET_SDKLIBS = wine.a @IMPORTS@ ole32.a wine_uuid.a ntdll.a - -TARGET_BASE = $(TARGET_BASE_LIB_SHELL32) - -TARGET_RC_SRCS = @RC_SRCS@ -TARGET_RC_BINSRC = @RC_BINSRC@ -TARGET_RC_BINARIES = @RC_BINARIES@ - -TARGET_CLEAN = authors.c - -default: all - -authors.c: -ifeq ($(HOST),mingw32-linux) - echo 'const char * const SHELL_Authors[] = { "Copyright 1993-2005 WINE team", "Copyright 1998-2005 ReactOS team", 0 };' > authors.c -else - echo const char * const SHELL_Authors[] = { "Copyright 1993-2005 WINE team", "Copyright 1998-2005 ReactOS team", 0 }; > authors.c -endif - -DEP_OBJECTS = $(TARGET_OBJECTS) - -include $(TOOLS_PATH)/depend.mk +# $Id: Makefile.ros-template 11910 2004-12-03 23:37:44Z blight $ + +TARGET_NAME = shell32 + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ + +TARGET_SDKLIBS = wine.a @IMPORTS@ ole32.a wine_uuid.a ntdll.a + +TARGET_BASE = $(TARGET_BASE_LIB_SHELL32) + +TARGET_RC_SRCS = @RC_SRCS@ +TARGET_RC_BINSRC = @RC_BINSRC@ +TARGET_RC_BINARIES = @RC_BINARIES@ + +TARGET_CLEAN = authors.c + +default: all + +authors.c: +ifeq ($(HOST),mingw32-linux) + echo 'const char * const SHELL_Authors[] = { "Copyright 1993-2005 WINE team", "Copyright 1998-2005 ReactOS team", 0 };' > authors.c +else + echo const char * const SHELL_Authors[] = { "Copyright 1993-2005 WINE team", "Copyright 1998-2005 ReactOS team", 0 }; > authors.c +endif + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/shell32/autocomplete.c b/reactos/lib/shell32/autocomplete.c index bca20030cf6..93e2b1f0718 100644 --- a/reactos/lib/shell32/autocomplete.c +++ b/reactos/lib/shell32/autocomplete.c @@ -1,646 +1,644 @@ -/* - * AutoComplete interfaces implementation. - * - * Copyright 2004 Maxime Bellengé - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - Implemented: - - ACO_AUTOAPPEND style - - ACO_AUTOSUGGEST style - - ACO_UPDOWNKEYDROPSLIST style - - - Handle pwzsRegKeyPath and pwszQuickComplete in Init - - TODO: - - implement ACO_SEARCH style - - implement ACO_FILTERPREFIXES style - - implement ACO_USETAB style - - implement ACO_RTLREADING style - - */ -#include "config.h" - -#include -#include -#include - -#define COBJMACROS - -#include "wine/debug.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "undocshell.h" -#include "shlwapi.h" -#include "winerror.h" -#include "objbase.h" - -#include "pidl.h" -#include "shlguid.h" -#include "shlobj.h" -#include "shldisp.h" -#include "debughlp.h" - -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -typedef struct -{ - IAutoCompleteVtbl *lpVtbl; - IAutoComplete2Vtbl *lpvtblAutoComplete2; - DWORD ref; - BOOL enabled; - HWND hwndEdit; - HWND hwndListBox; - WNDPROC wpOrigEditProc; - WNDPROC wpOrigLBoxProc; - WCHAR *txtbackup; - WCHAR *quickComplete; - IEnumString *enumstr; - AUTOCOMPLETEOPTIONS options; -} IAutoCompleteImpl; - -static struct IAutoCompleteVtbl acvt; -static struct IAutoComplete2Vtbl ac2vt; - -#define _IAutoComplete2_Offset ((int)(&(((IAutoCompleteImpl*)0)->lpvtblAutoComplete2))) -#define _ICOM_THIS_From_IAutoComplete2(class, name) class* This = (class*)(((char*)name)-_IAutoComplete2_Offset); - -/* - converts This to a interface pointer -*/ -#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IAutoComplete2_(This) (IAutoComplete2*)&(This->lpvtblAutoComplete2) - -static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -/************************************************************************** - * IAutoComplete_Constructor - */ -HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) -{ - IAutoCompleteImpl *lpac; - - if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) - return CLASS_E_NOAGGREGATION; - - lpac = (IAutoCompleteImpl*)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, sizeof(IAutoCompleteImpl)); - if (!lpac) - return E_OUTOFMEMORY; - - lpac->ref = 1; - lpac->lpVtbl = &acvt; - lpac->lpvtblAutoComplete2 = &ac2vt; - lpac->enabled = TRUE; - lpac->enumstr = NULL; - lpac->options = ACO_AUTOAPPEND; - lpac->wpOrigEditProc = NULL; - lpac->hwndListBox = NULL; - lpac->txtbackup = NULL; - lpac->quickComplete = NULL; - - if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (lpac), riid, ppv))) { - IUnknown_Release (_IUnknown_ (lpac)); - return E_NOINTERFACE; - } - - TRACE("-- (%p)->\n",lpac); - - return S_OK; -} - -/************************************************************************** - * AutoComplete_QueryInterface - */ -static HRESULT WINAPI IAutoComplete_fnQueryInterface( - IAutoComplete * iface, - REFIID riid, - LPVOID *ppvObj) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, shdebugstr_guid(riid), ppvObj); - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IAutoComplete)) - { - *ppvObj = (IAutoComplete*)This; - } - else if(IsEqualIID(riid, &IID_IAutoComplete2)) - { - *ppvObj = _IAutoComplete2_ (This); - } - - if (*ppvObj) - { - IAutoComplete_AddRef((IAutoComplete*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/****************************************************************************** - * IAutoComplete_fnAddRef - */ -static ULONG WINAPI IAutoComplete_fnAddRef( - IAutoComplete * iface) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; - - TRACE("(%p)->(%lu)\n",This,This->ref); - return ++(This->ref); -} - -/****************************************************************************** - * IAutoComplete_fnRelease - */ -static ULONG WINAPI IAutoComplete_fnRelease( - IAutoComplete * iface) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; - - TRACE("(%p)->(%lu)\n",This,This->ref); - - if (!--(This->ref)) { - TRACE(" destroying IAutoComplete(%p)\n",This); - if (This->quickComplete) - HeapFree(GetProcessHeap(), 0, This->quickComplete); - if (This->txtbackup) - HeapFree(GetProcessHeap(), 0, This->txtbackup); - if (This->hwndListBox) - DestroyWindow(This->hwndListBox); - if (This->enumstr) - IEnumString_Release(This->enumstr); - HeapFree(GetProcessHeap(), 0, This); - return 0; - } - return This->ref; -} - -/****************************************************************************** - * IAutoComplete_fnEnable - */ -static HRESULT WINAPI IAutoComplete_fnEnable( - IAutoComplete * iface, - BOOL fEnable) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; - - HRESULT hr = S_OK; - - TRACE("(%p)->(%s)\n", This, (fEnable)?"true":"false"); - - This->enabled = fEnable; - - return hr; -} - -/****************************************************************************** - * IAutoComplete_fnInit - */ -static HRESULT WINAPI IAutoComplete_fnInit( - IAutoComplete * iface, - HWND hwndEdit, - IUnknown *punkACL, - LPCOLESTR pwzsRegKeyPath, - LPCOLESTR pwszQuickComplete) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; - static const WCHAR lbName[] = {'L','i','s','t','B','o','x',0}; - - TRACE("(%p)->(0x%08lx, %p, %s, %s)\n", - This, (long)hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); - - if (This->options & ACO_AUTOSUGGEST) TRACE(" ACO_AUTOSUGGEST\n"); - if (This->options & ACO_AUTOAPPEND) TRACE(" ACO_AUTOAPPEND\n"); - if (This->options & ACO_SEARCH) FIXME(" ACO_SEARCH not supported\n"); - if (This->options & ACO_FILTERPREFIXES) FIXME(" ACO_FILTERPREFIXES not supported\n"); - if (This->options & ACO_USETAB) FIXME(" ACO_USETAB not supported\n"); - if (This->options & ACO_UPDOWNKEYDROPSLIST) TRACE(" ACO_UPDOWNKEYDROPSLIST\n"); - if (This->options & ACO_RTLREADING) FIXME(" ACO_RTLREADING not supported\n"); - - This->hwndEdit = hwndEdit; - - if (!SUCCEEDED (IUnknown_QueryInterface (punkACL, &IID_IEnumString, (LPVOID*)&This->enumstr))) { - TRACE("No IEnumString interface\n"); - return E_NOINTERFACE; - } - - This->wpOrigEditProc = (WNDPROC) SetWindowLongPtrW( hwndEdit, GWLP_WNDPROC, (LONG_PTR) ACEditSubclassProc); - SetWindowLongPtrW( hwndEdit, GWLP_USERDATA, (LONG_PTR)This); - - if (This->options & ACO_AUTOSUGGEST) { - HWND hwndParent; - - hwndParent = GetParent(This->hwndEdit); - - /* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */ - This->hwndListBox = CreateWindowExW(0, lbName, NULL, - WS_BORDER | WS_CHILD | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - hwndParent, NULL, - (HINSTANCE)GetWindowLongPtrW( hwndParent, GWLP_HINSTANCE ), NULL); - - if (This->hwndListBox) { - This->wpOrigLBoxProc = (WNDPROC) SetWindowLongPtrW( This->hwndListBox, GWLP_WNDPROC, (LONG_PTR) ACLBoxSubclassProc); - SetWindowLongPtrW( This->hwndListBox, GWLP_USERDATA, (LONG_PTR)This); - } - } - - if (pwzsRegKeyPath) { - WCHAR *key; - WCHAR result[MAX_PATH]; - WCHAR *value; - HKEY hKey = 0; - LONG res; - LONG len; - - /* pwszRegKeyPath contains the key as well as the value, so we split */ - key = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlenW(pwzsRegKeyPath)+1)*sizeof(WCHAR)); - strcpyW(key, pwzsRegKeyPath); - value = strrchrW(key, '\\'); - *value = 0; - value++; - /* Now value contains the value and buffer the key */ - res = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ, &hKey); - if (res != ERROR_SUCCESS) { - /* if the key is not found, MSDN states we must seek in HKEY_LOCAL_MACHINE */ - res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey); - } - if (res == ERROR_SUCCESS) { - res = RegQueryValueW(hKey, value, result, &len); - if (res == ERROR_SUCCESS) { - This->quickComplete = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); - strcpyW(This->quickComplete, result); - } - RegCloseKey(hKey); - } - HeapFree(GetProcessHeap(), 0, key); - } - - if ((pwszQuickComplete) && (!This->quickComplete)) { - This->quickComplete = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlenW(pwszQuickComplete)+1)*sizeof(WCHAR)); - lstrcpyW(This->quickComplete, pwszQuickComplete); - } - - return S_OK; -} - -/************************************************************************** - * IAutoComplete_fnVTable - */ -static IAutoCompleteVtbl acvt = -{ - IAutoComplete_fnQueryInterface, - IAutoComplete_fnAddRef, - IAutoComplete_fnRelease, - IAutoComplete_fnInit, - IAutoComplete_fnEnable, -}; - -/************************************************************************** - * AutoComplete2_QueryInterface - */ -static HRESULT WINAPI IAutoComplete2_fnQueryInterface( - IAutoComplete2 * iface, - REFIID riid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - return IAutoComplete_QueryInterface((IAutoComplete*)This, riid, ppvObj); -} - -/****************************************************************************** - * IAutoComplete2_fnAddRef - */ -static ULONG WINAPI IAutoComplete2_fnAddRef( - IAutoComplete2 * iface) -{ - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl,iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IAutoComplete2_AddRef((IAutoComplete*)This); -} - -/****************************************************************************** - * IAutoComplete2_fnRelease - */ -static ULONG WINAPI IAutoComplete2_fnRelease( - IAutoComplete2 * iface) -{ - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl,iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IAutoComplete_Release((IAutoComplete*)This); -} - -/****************************************************************************** - * IAutoComplete2_fnEnable - */ -static HRESULT WINAPI IAutoComplete2_fnEnable( - IAutoComplete2 * iface, - BOOL fEnable) -{ - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); - - TRACE ("(%p)->(%s)\n", This, (fEnable)?"true":"false"); - - return IAutoComplete_Enable((IAutoComplete*)This, fEnable); -} - -/****************************************************************************** - * IAutoComplete2_fnInit - */ -static HRESULT WINAPI IAutoComplete2_fnInit( - IAutoComplete2 * iface, - HWND hwndEdit, - IUnknown *punkACL, - LPCOLESTR pwzsRegKeyPath, - LPCOLESTR pwszQuickComplete) -{ - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); - - TRACE("(%p)\n", This); - - return IAutoComplete_Init((IAutoComplete*)This, hwndEdit, punkACL, pwzsRegKeyPath, pwszQuickComplete); -} - -/************************************************************************** - * IAutoComplete_fnGetOptions - */ -static HRESULT WINAPI IAutoComplete2_fnGetOptions( - IAutoComplete2 * iface, - DWORD *pdwFlag) -{ - HRESULT hr = S_OK; - - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); - - TRACE("(%p) -> (%p)\n", This, pdwFlag); - - *pdwFlag = This->options; - - return hr; -} - -/************************************************************************** - * IAutoComplete_fnSetOptions - */ -static HRESULT WINAPI IAutoComplete2_fnSetOptions( - IAutoComplete2 * iface, - DWORD dwFlag) -{ - HRESULT hr = S_OK; - - _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); - - TRACE("(%p) -> (0x%lx)\n", This, dwFlag); - - This->options = dwFlag; - - return hr; -} - -/************************************************************************** - * IAutoComplete2_fnVTable - */ -static IAutoComplete2Vtbl ac2vt = -{ - IAutoComplete2_fnQueryInterface, - IAutoComplete2_fnAddRef, - IAutoComplete2_fnRelease, - IAutoComplete2_fnInit, - IAutoComplete2_fnEnable, - /* IAutoComplete2 */ - IAutoComplete2_fnSetOptions, - IAutoComplete2_fnGetOptions, -}; - -/* - Window procedure for autocompletion - */ -static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); - LPOLESTR strs; - HRESULT hr; - WCHAR hwndText[255]; - WCHAR *hwndQCText; - RECT r; - BOOL control, filled, displayall = FALSE; - int cpt, height, sel; - - if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case CB_SHOWDROPDOWN: - ShowWindow(This->hwndListBox, SW_HIDE); - break; - case WM_KILLFOCUS: - if ((This->options && ACO_AUTOSUGGEST) && - ((HWND)wParam != This->hwndListBox)) - { - ShowWindow(This->hwndListBox, SW_HIDE); - } - break; - case WM_KEYUP: - - GetWindowTextW( hwnd, (LPWSTR)hwndText, 255); - - switch(wParam) { - case VK_RETURN: - /* If quickComplete is set and control is pressed, replace the string */ - control = GetKeyState(VK_CONTROL) & 0x8000; - if (control && This->quickComplete) { - hwndQCText = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - (lstrlenW(This->quickComplete)+lstrlenW(hwndText))*sizeof(WCHAR)); - sel = sprintfW(hwndQCText, This->quickComplete, hwndText); - SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)hwndQCText); - SendMessageW(hwnd, EM_SETSEL, 0, sel); - HeapFree(GetProcessHeap(), 0, hwndQCText); - } - - ShowWindow(This->hwndListBox, SW_HIDE); - return 0; - case VK_LEFT: - case VK_RIGHT: - return 0; - case VK_UP: - case VK_DOWN: - /* Two cases here : - - if the listbox is not visible, displays it - with all the entries if the style ACO_UPDOWNKEYDROPSLIST - is present but does not select anything. - - if the listbox is visible, change the selection - */ - if ( (This->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST)) - && (!IsWindowVisible(This->hwndListBox) && (! *hwndText)) ) - { - /* We must dispays all the entries */ - displayall = TRUE; - } else { - if (IsWindowVisible(This->hwndListBox)) { - int count; - - count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0); - /* Change the selection */ - sel = SendMessageW(This->hwndListBox, LB_GETCURSEL, 0, 0); - if (wParam == VK_UP) - sel = ((sel-1)<0)?count-1:sel-1; - else - sel = ((sel+1)>= count)?-1:sel+1; - SendMessageW(This->hwndListBox, LB_SETCURSEL, sel, 0); - if (sel != -1) { - WCHAR *msg; - int len; - - len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, (LPARAM)NULL); - msg = (WCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len+1)*sizeof(WCHAR)); - SendMessageW(This->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg); - SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg); - SendMessageW(hwnd, EM_SETSEL, lstrlenW(msg), lstrlenW(msg)); - HeapFree(GetProcessHeap(), 0, msg); - } else { - SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)This->txtbackup); - SendMessageW(hwnd, EM_SETSEL, lstrlenW(This->txtbackup), lstrlenW(This->txtbackup)); - } - } - return 0; - } - break; - case VK_BACK: - case VK_DELETE: - if ((! *hwndText) && (This->options & ACO_AUTOSUGGEST)) { - ShowWindow(This->hwndListBox, SW_HIDE); - return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); - } - if (This->options & ACO_AUTOAPPEND) { - DWORD b; - SendMessageW(hwnd, EM_GETSEL, (WPARAM)&b, (LPARAM)NULL); - if (b>1) { - hwndText[b-1] = '\0'; - } else { - hwndText[0] = '\0'; - SetWindowTextW(hwnd, hwndText); - } - } - break; - default: - ; - } - - SendMessageW(This->hwndListBox, LB_RESETCONTENT, 0, 0); - - HeapFree(GetProcessHeap(), 0, This->txtbackup); - This->txtbackup = (WCHAR*) HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, (lstrlenW(hwndText)+1)*sizeof(WCHAR)); - lstrcpyW(This->txtbackup, hwndText); - - /* Returns if there is no text to search and we doesn't want to display all the entries */ - if ((!displayall) && (! *hwndText) ) - break; - - IEnumString_Reset(This->enumstr); - filled = FALSE; - for(cpt = 0;;) { - hr = IEnumString_Next(This->enumstr, 1, &strs, NULL); - if (hr != S_OK) - break; - - if ((LPWSTR)strstrW(strs, hwndText) == strs) { - - if (This->options & ACO_AUTOAPPEND) { - SetWindowTextW(hwnd, strs); - SendMessageW(hwnd, EM_SETSEL, lstrlenW(hwndText), lstrlenW(strs)); - break; - } - - if (This->options & ACO_AUTOSUGGEST) { - SendMessageW(This->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs); - filled = TRUE; - cpt++; - } - } - } - - if (This->options & ACO_AUTOSUGGEST) { - if (filled) { - height = SendMessageW(This->hwndListBox, LB_GETITEMHEIGHT, 0, 0); - SendMessageW(This->hwndListBox, LB_CARETOFF, 0, 0); - GetWindowRect(hwnd, &r); - SetParent(This->hwndListBox, HWND_DESKTOP); - /* It seems that Windows XP displays 7 lines at most - and otherwise displays a vertical scroll bar */ - SetWindowPos(This->hwndListBox, HWND_TOP, - r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)), - SWP_SHOWWINDOW ); - } else { - ShowWindow(This->hwndListBox, SW_HIDE); - } - } - - break; - default: - return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); - - } - - return 0; -} - -static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - IAutoCompleteImpl *This = (IAutoCompleteImpl *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); - WCHAR *msg; - int sel = -1, len; - - switch (uMsg) { - case WM_MOUSEMOVE: - sel = SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, lParam); - SendMessageW(hwnd, LB_SETCURSEL, (WPARAM)sel, (LPARAM)0); - break; - case WM_LBUTTONDOWN: - len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, (LPARAM)NULL); - msg = (WCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len+1)*sizeof(WCHAR)); - sel = (INT)SendMessageW(hwnd, LB_GETCURSEL, 0, 0); - SendMessageW(hwnd, LB_GETTEXT, sel, (LPARAM)msg); - SendMessageW(This->hwndEdit, WM_SETTEXT, 0, (LPARAM)msg); - SendMessageW(This->hwndEdit, EM_SETSEL, 0, lstrlenW(msg)); - ShowWindow(hwnd, SW_HIDE); - HeapFree(GetProcessHeap(), 0, msg); - break; - default: - return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); - } - return 0; -} +/* + * AutoComplete interfaces implementation. + * + * Copyright 2004 Maxime Bellengé + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + Implemented: + - ACO_AUTOAPPEND style + - ACO_AUTOSUGGEST style + - ACO_UPDOWNKEYDROPSLIST style + + - Handle pwzsRegKeyPath and pwszQuickComplete in Init + + TODO: + - implement ACO_SEARCH style + - implement ACO_FILTERPREFIXES style + - implement ACO_USETAB style + - implement ACO_RTLREADING style + + */ +#include "config.h" + +#include +#include +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "undocshell.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "pidl.h" +#include "shlguid.h" +#include "shlobj.h" +#include "shldisp.h" +#include "debughlp.h" + +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +typedef struct +{ + IAutoCompleteVtbl *lpVtbl; + IAutoComplete2Vtbl *lpvtblAutoComplete2; + DWORD ref; + BOOL enabled; + HWND hwndEdit; + HWND hwndListBox; + WNDPROC wpOrigEditProc; + WNDPROC wpOrigLBoxProc; + WCHAR *txtbackup; + WCHAR *quickComplete; + IEnumString *enumstr; + AUTOCOMPLETEOPTIONS options; +} IAutoCompleteImpl; + +static struct IAutoCompleteVtbl acvt; +static struct IAutoComplete2Vtbl ac2vt; + +#define _IAutoComplete2_Offset ((int)(&(((IAutoCompleteImpl*)0)->lpvtblAutoComplete2))) +#define _ICOM_THIS_From_IAutoComplete2(class, name) class* This = (class*)(((char*)name)-_IAutoComplete2_Offset); + +/* + converts This to a interface pointer +*/ +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IAutoComplete2_(This) (IAutoComplete2*)&(This->lpvtblAutoComplete2) + +static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/************************************************************************** + * IAutoComplete_Constructor + */ +HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) +{ + IAutoCompleteImpl *lpac; + + if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) + return CLASS_E_NOAGGREGATION; + + lpac = (IAutoCompleteImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IAutoCompleteImpl)); + if (!lpac) + return E_OUTOFMEMORY; + + lpac->ref = 1; + lpac->lpVtbl = &acvt; + lpac->lpvtblAutoComplete2 = &ac2vt; + lpac->enabled = TRUE; + lpac->enumstr = NULL; + lpac->options = ACO_AUTOAPPEND; + lpac->wpOrigEditProc = NULL; + lpac->hwndListBox = NULL; + lpac->txtbackup = NULL; + lpac->quickComplete = NULL; + + if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (lpac), riid, ppv))) { + IUnknown_Release (_IUnknown_ (lpac)); + return E_NOINTERFACE; + } + + TRACE("-- (%p)->\n",lpac); + + return S_OK; +} + +/************************************************************************** + * AutoComplete_QueryInterface + */ +static HRESULT WINAPI IAutoComplete_fnQueryInterface( + IAutoComplete * iface, + REFIID riid, + LPVOID *ppvObj) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, shdebugstr_guid(riid), ppvObj); + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IAutoComplete)) + { + *ppvObj = (IAutoComplete*)This; + } + else if(IsEqualIID(riid, &IID_IAutoComplete2)) + { + *ppvObj = _IAutoComplete2_ (This); + } + + if (*ppvObj) + { + IAutoComplete_AddRef((IAutoComplete*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/****************************************************************************** + * IAutoComplete_fnAddRef + */ +static ULONG WINAPI IAutoComplete_fnAddRef( + IAutoComplete * iface) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; + + TRACE("(%p)->(%lu)\n",This,This->ref); + return ++(This->ref); +} + +/****************************************************************************** + * IAutoComplete_fnRelease + */ +static ULONG WINAPI IAutoComplete_fnRelease( + IAutoComplete * iface) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; + + TRACE("(%p)->(%lu)\n",This,This->ref); + + if (!--(This->ref)) { + TRACE(" destroying IAutoComplete(%p)\n",This); + HeapFree(GetProcessHeap(), 0, This->quickComplete); + HeapFree(GetProcessHeap(), 0, This->txtbackup); + if (This->hwndListBox) + DestroyWindow(This->hwndListBox); + if (This->enumstr) + IEnumString_Release(This->enumstr); + HeapFree(GetProcessHeap(), 0, This); + return 0; + } + return This->ref; +} + +/****************************************************************************** + * IAutoComplete_fnEnable + */ +static HRESULT WINAPI IAutoComplete_fnEnable( + IAutoComplete * iface, + BOOL fEnable) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; + + HRESULT hr = S_OK; + + TRACE("(%p)->(%s)\n", This, (fEnable)?"true":"false"); + + This->enabled = fEnable; + + return hr; +} + +/****************************************************************************** + * IAutoComplete_fnInit + */ +static HRESULT WINAPI IAutoComplete_fnInit( + IAutoComplete * iface, + HWND hwndEdit, + IUnknown *punkACL, + LPCOLESTR pwzsRegKeyPath, + LPCOLESTR pwszQuickComplete) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; + static const WCHAR lbName[] = {'L','i','s','t','B','o','x',0}; + + TRACE("(%p)->(0x%08lx, %p, %s, %s)\n", + This, (long)hwndEdit, punkACL, debugstr_w(pwzsRegKeyPath), debugstr_w(pwszQuickComplete)); + + if (This->options & ACO_AUTOSUGGEST) TRACE(" ACO_AUTOSUGGEST\n"); + if (This->options & ACO_AUTOAPPEND) TRACE(" ACO_AUTOAPPEND\n"); + if (This->options & ACO_SEARCH) FIXME(" ACO_SEARCH not supported\n"); + if (This->options & ACO_FILTERPREFIXES) FIXME(" ACO_FILTERPREFIXES not supported\n"); + if (This->options & ACO_USETAB) FIXME(" ACO_USETAB not supported\n"); + if (This->options & ACO_UPDOWNKEYDROPSLIST) TRACE(" ACO_UPDOWNKEYDROPSLIST\n"); + if (This->options & ACO_RTLREADING) FIXME(" ACO_RTLREADING not supported\n"); + + This->hwndEdit = hwndEdit; + + if (!SUCCEEDED (IUnknown_QueryInterface (punkACL, &IID_IEnumString, (LPVOID*)&This->enumstr))) { + TRACE("No IEnumString interface\n"); + return E_NOINTERFACE; + } + + This->wpOrigEditProc = (WNDPROC) SetWindowLongPtrW( hwndEdit, GWLP_WNDPROC, (LONG_PTR) ACEditSubclassProc); + SetWindowLongPtrW( hwndEdit, GWLP_USERDATA, (LONG_PTR)This); + + if (This->options & ACO_AUTOSUGGEST) { + HWND hwndParent; + + hwndParent = GetParent(This->hwndEdit); + + /* FIXME : The listbox should be resizable with the mouse. WS_THICKFRAME looks ugly */ + This->hwndListBox = CreateWindowExW(0, lbName, NULL, + WS_BORDER | WS_CHILD | WS_VSCROLL | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hwndParent, NULL, + (HINSTANCE)GetWindowLongPtrW( hwndParent, GWLP_HINSTANCE ), NULL); + + if (This->hwndListBox) { + This->wpOrigLBoxProc = (WNDPROC) SetWindowLongPtrW( This->hwndListBox, GWLP_WNDPROC, (LONG_PTR) ACLBoxSubclassProc); + SetWindowLongPtrW( This->hwndListBox, GWLP_USERDATA, (LONG_PTR)This); + } + } + + if (pwzsRegKeyPath) { + WCHAR *key; + WCHAR result[MAX_PATH]; + WCHAR *value; + HKEY hKey = 0; + LONG res; + LONG len; + + /* pwszRegKeyPath contains the key as well as the value, so we split */ + key = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlenW(pwzsRegKeyPath)+1)*sizeof(WCHAR)); + strcpyW(key, pwzsRegKeyPath); + value = strrchrW(key, '\\'); + *value = 0; + value++; + /* Now value contains the value and buffer the key */ + res = RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_READ, &hKey); + if (res != ERROR_SUCCESS) { + /* if the key is not found, MSDN states we must seek in HKEY_LOCAL_MACHINE */ + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey); + } + if (res == ERROR_SUCCESS) { + res = RegQueryValueW(hKey, value, result, &len); + if (res == ERROR_SUCCESS) { + This->quickComplete = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); + strcpyW(This->quickComplete, result); + } + RegCloseKey(hKey); + } + HeapFree(GetProcessHeap(), 0, key); + } + + if ((pwszQuickComplete) && (!This->quickComplete)) { + This->quickComplete = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlenW(pwszQuickComplete)+1)*sizeof(WCHAR)); + lstrcpyW(This->quickComplete, pwszQuickComplete); + } + + return S_OK; +} + +/************************************************************************** + * IAutoComplete_fnVTable + */ +static IAutoCompleteVtbl acvt = +{ + IAutoComplete_fnQueryInterface, + IAutoComplete_fnAddRef, + IAutoComplete_fnRelease, + IAutoComplete_fnInit, + IAutoComplete_fnEnable, +}; + +/************************************************************************** + * AutoComplete2_QueryInterface + */ +static HRESULT WINAPI IAutoComplete2_fnQueryInterface( + IAutoComplete2 * iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + return IAutoComplete_QueryInterface((IAutoComplete*)This, riid, ppvObj); +} + +/****************************************************************************** + * IAutoComplete2_fnAddRef + */ +static ULONG WINAPI IAutoComplete2_fnAddRef( + IAutoComplete2 * iface) +{ + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl,iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IAutoComplete2_AddRef((IAutoComplete*)This); +} + +/****************************************************************************** + * IAutoComplete2_fnRelease + */ +static ULONG WINAPI IAutoComplete2_fnRelease( + IAutoComplete2 * iface) +{ + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl,iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IAutoComplete_Release((IAutoComplete*)This); +} + +/****************************************************************************** + * IAutoComplete2_fnEnable + */ +static HRESULT WINAPI IAutoComplete2_fnEnable( + IAutoComplete2 * iface, + BOOL fEnable) +{ + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); + + TRACE ("(%p)->(%s)\n", This, (fEnable)?"true":"false"); + + return IAutoComplete_Enable((IAutoComplete*)This, fEnable); +} + +/****************************************************************************** + * IAutoComplete2_fnInit + */ +static HRESULT WINAPI IAutoComplete2_fnInit( + IAutoComplete2 * iface, + HWND hwndEdit, + IUnknown *punkACL, + LPCOLESTR pwzsRegKeyPath, + LPCOLESTR pwszQuickComplete) +{ + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); + + TRACE("(%p)\n", This); + + return IAutoComplete_Init((IAutoComplete*)This, hwndEdit, punkACL, pwzsRegKeyPath, pwszQuickComplete); +} + +/************************************************************************** + * IAutoComplete_fnGetOptions + */ +static HRESULT WINAPI IAutoComplete2_fnGetOptions( + IAutoComplete2 * iface, + DWORD *pdwFlag) +{ + HRESULT hr = S_OK; + + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); + + TRACE("(%p) -> (%p)\n", This, pdwFlag); + + *pdwFlag = This->options; + + return hr; +} + +/************************************************************************** + * IAutoComplete_fnSetOptions + */ +static HRESULT WINAPI IAutoComplete2_fnSetOptions( + IAutoComplete2 * iface, + DWORD dwFlag) +{ + HRESULT hr = S_OK; + + _ICOM_THIS_From_IAutoComplete2(IAutoCompleteImpl, iface); + + TRACE("(%p) -> (0x%lx)\n", This, dwFlag); + + This->options = dwFlag; + + return hr; +} + +/************************************************************************** + * IAutoComplete2_fnVTable + */ +static IAutoComplete2Vtbl ac2vt = +{ + IAutoComplete2_fnQueryInterface, + IAutoComplete2_fnAddRef, + IAutoComplete2_fnRelease, + IAutoComplete2_fnInit, + IAutoComplete2_fnEnable, + /* IAutoComplete2 */ + IAutoComplete2_fnSetOptions, + IAutoComplete2_fnGetOptions, +}; + +/* + Window procedure for autocompletion + */ +static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); + LPOLESTR strs; + HRESULT hr; + WCHAR hwndText[255]; + WCHAR *hwndQCText; + RECT r; + BOOL control, filled, displayall = FALSE; + int cpt, height, sel; + + if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case CB_SHOWDROPDOWN: + ShowWindow(This->hwndListBox, SW_HIDE); + break; + case WM_KILLFOCUS: + if ((This->options && ACO_AUTOSUGGEST) && + ((HWND)wParam != This->hwndListBox)) + { + ShowWindow(This->hwndListBox, SW_HIDE); + } + break; + case WM_KEYUP: + + GetWindowTextW( hwnd, (LPWSTR)hwndText, 255); + + switch(wParam) { + case VK_RETURN: + /* If quickComplete is set and control is pressed, replace the string */ + control = GetKeyState(VK_CONTROL) & 0x8000; + if (control && This->quickComplete) { + hwndQCText = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + (lstrlenW(This->quickComplete)+lstrlenW(hwndText))*sizeof(WCHAR)); + sel = sprintfW(hwndQCText, This->quickComplete, hwndText); + SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)hwndQCText); + SendMessageW(hwnd, EM_SETSEL, 0, sel); + HeapFree(GetProcessHeap(), 0, hwndQCText); + } + + ShowWindow(This->hwndListBox, SW_HIDE); + return 0; + case VK_LEFT: + case VK_RIGHT: + return 0; + case VK_UP: + case VK_DOWN: + /* Two cases here : + - if the listbox is not visible, displays it + with all the entries if the style ACO_UPDOWNKEYDROPSLIST + is present but does not select anything. + - if the listbox is visible, change the selection + */ + if ( (This->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST)) + && (!IsWindowVisible(This->hwndListBox) && (! *hwndText)) ) + { + /* We must dispays all the entries */ + displayall = TRUE; + } else { + if (IsWindowVisible(This->hwndListBox)) { + int count; + + count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0); + /* Change the selection */ + sel = SendMessageW(This->hwndListBox, LB_GETCURSEL, 0, 0); + if (wParam == VK_UP) + sel = ((sel-1)<0)?count-1:sel-1; + else + sel = ((sel+1)>= count)?-1:sel+1; + SendMessageW(This->hwndListBox, LB_SETCURSEL, sel, 0); + if (sel != -1) { + WCHAR *msg; + int len; + + len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, (LPARAM)NULL); + msg = (WCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len+1)*sizeof(WCHAR)); + SendMessageW(This->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg); + SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg); + SendMessageW(hwnd, EM_SETSEL, lstrlenW(msg), lstrlenW(msg)); + HeapFree(GetProcessHeap(), 0, msg); + } else { + SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)This->txtbackup); + SendMessageW(hwnd, EM_SETSEL, lstrlenW(This->txtbackup), lstrlenW(This->txtbackup)); + } + } + return 0; + } + break; + case VK_BACK: + case VK_DELETE: + if ((! *hwndText) && (This->options & ACO_AUTOSUGGEST)) { + ShowWindow(This->hwndListBox, SW_HIDE); + return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); + } + if (This->options & ACO_AUTOAPPEND) { + DWORD b; + SendMessageW(hwnd, EM_GETSEL, (WPARAM)&b, (LPARAM)NULL); + if (b>1) { + hwndText[b-1] = '\0'; + } else { + hwndText[0] = '\0'; + SetWindowTextW(hwnd, hwndText); + } + } + break; + default: + ; + } + + SendMessageW(This->hwndListBox, LB_RESETCONTENT, 0, 0); + + HeapFree(GetProcessHeap(), 0, This->txtbackup); + This->txtbackup = (WCHAR*) HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, (lstrlenW(hwndText)+1)*sizeof(WCHAR)); + lstrcpyW(This->txtbackup, hwndText); + + /* Returns if there is no text to search and we doesn't want to display all the entries */ + if ((!displayall) && (! *hwndText) ) + break; + + IEnumString_Reset(This->enumstr); + filled = FALSE; + for(cpt = 0;;) { + hr = IEnumString_Next(This->enumstr, 1, &strs, NULL); + if (hr != S_OK) + break; + + if ((LPWSTR)strstrW(strs, hwndText) == strs) { + + if (This->options & ACO_AUTOAPPEND) { + SetWindowTextW(hwnd, strs); + SendMessageW(hwnd, EM_SETSEL, lstrlenW(hwndText), lstrlenW(strs)); + break; + } + + if (This->options & ACO_AUTOSUGGEST) { + SendMessageW(This->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs); + filled = TRUE; + cpt++; + } + } + } + + if (This->options & ACO_AUTOSUGGEST) { + if (filled) { + height = SendMessageW(This->hwndListBox, LB_GETITEMHEIGHT, 0, 0); + SendMessageW(This->hwndListBox, LB_CARETOFF, 0, 0); + GetWindowRect(hwnd, &r); + SetParent(This->hwndListBox, HWND_DESKTOP); + /* It seems that Windows XP displays 7 lines at most + and otherwise displays a vertical scroll bar */ + SetWindowPos(This->hwndListBox, HWND_TOP, + r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)), + SWP_SHOWWINDOW ); + } else { + ShowWindow(This->hwndListBox, SW_HIDE); + } + } + + break; + default: + return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam); + + } + + return 0; +} + +static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + IAutoCompleteImpl *This = (IAutoCompleteImpl *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); + WCHAR *msg; + int sel = -1, len; + + switch (uMsg) { + case WM_MOUSEMOVE: + sel = SendMessageW(hwnd, LB_ITEMFROMPOINT, 0, lParam); + SendMessageW(hwnd, LB_SETCURSEL, (WPARAM)sel, (LPARAM)0); + break; + case WM_LBUTTONDOWN: + len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, (LPARAM)NULL); + msg = (WCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len+1)*sizeof(WCHAR)); + sel = (INT)SendMessageW(hwnd, LB_GETCURSEL, 0, 0); + SendMessageW(hwnd, LB_GETTEXT, sel, (LPARAM)msg); + SendMessageW(This->hwndEdit, WM_SETTEXT, 0, (LPARAM)msg); + SendMessageW(This->hwndEdit, EM_SETSEL, 0, lstrlenW(msg)); + ShowWindow(hwnd, SW_HIDE); + HeapFree(GetProcessHeap(), 0, msg); + break; + default: + return CallWindowProcW(This->wpOrigLBoxProc, hwnd, uMsg, wParam, lParam); + } + return 0; +} diff --git a/reactos/lib/shell32/brsfolder.c b/reactos/lib/shell32/brsfolder.c index cfce80ce132..198c18d40f8 100644 --- a/reactos/lib/shell32/brsfolder.c +++ b/reactos/lib/shell32/brsfolder.c @@ -1,517 +1,517 @@ -/* - * Copyright 1999 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: - * - many memory leaks - * - many flags unimplemented - */ - -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "wine/debug.h" -#include "undocshell.h" -#include "shlguid.h" -#include "pidl.h" -#include "shell32_main.h" -#include "shellapi.h" -#include "shresdef.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -static HWND hwndTreeView; -static LPBROWSEINFOW lpBrowseInfo; -static LPITEMIDLIST pidlRet; - -static void FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent, IEnumIDList* lpe); -static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent); - -#define SUPPORTEDFLAGS (BIF_STATUSTEXT | \ - BIF_BROWSEFORCOMPUTER | \ - BIF_RETURNFSANCESTORS | \ - BIF_RETURNONLYFSDIRS | \ - BIF_BROWSEINCLUDEFILES) - -static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags) -{ - return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS : 0); -} - -static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) -{ - HIMAGELIST hImageList; - IShellFolder * lpsf; - HRESULT hr; - IEnumIDList * pEnumIL = NULL; - LPITEMIDLIST parentofroot; - parentofroot = ILClone(root); - ILRemoveLastID(parentofroot); - - hwndTreeView = GetDlgItem (hwndParent, IDD_TREEVIEW); - Shell_GetImageList(NULL, &hImageList); - - TRACE("dlg=%p tree=%p\n", hwndParent, hwndTreeView ); - - if (hImageList && hwndTreeView) - TreeView_SetImageList(hwndTreeView, hImageList, 0); - - if (_ILIsDesktop (root)) { - hr = SHGetDesktopFolder(&lpsf); - } else { - IShellFolder * lpsfdesktop; - - hr = SHGetDesktopFolder(&lpsfdesktop); - if (SUCCEEDED(hr)) { - hr = IShellFolder_BindToObject(lpsfdesktop, parentofroot, 0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf); - IShellFolder_Release(lpsfdesktop); - } - } - if (SUCCEEDED(hr)) - { - IShellFolder * pSFRoot; - if (_ILIsPidlSimple(root)) - { - pSFRoot = lpsf; - IShellFolder_AddRef(pSFRoot); - } - else - hr = IShellFolder_BindToObject(lpsf,ILFindLastID(root),0,&IID_IShellFolder,(LPVOID *)&pSFRoot); - if (SUCCEEDED(hr)) - { - hr = IShellFolder_EnumObjects( - pSFRoot, - hwndParent, - BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), - &pEnumIL); - IShellFolder_Release(pSFRoot); - } - } - - if (SUCCEEDED(hr) && hwndTreeView) - { - TreeView_DeleteAllItems(hwndTreeView); - TreeView_Expand(hwndTreeView, - InsertTreeViewItem(lpsf, _ILIsPidlSimple(root) ? root : ILFindLastID(root), parentofroot, pEnumIL, TVI_ROOT), - TVE_EXPAND); - } - - if (SUCCEEDED(hr)) - IShellFolder_Release(lpsf); - - TRACE("done\n"); -} - -static int GetIcon(LPITEMIDLIST lpi, UINT uFlags) -{ - SHFILEINFOW sfi; - SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags); - return sfi.iIcon; -} - -static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM) -{ - LPITEMIDLIST pidlDesktop = NULL; - - TRACE("%p %p\n",lpifq, lpTV_ITEM); - - if (!lpifq) - { - pidlDesktop = _ILCreateDesktop(); - lpifq = pidlDesktop; - } - - lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); - lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON); - - if (pidlDesktop) - ILFree(pidlDesktop); - - return; -} - -typedef struct tagID -{ - LPSHELLFOLDER lpsfParent; - LPITEMIDLIST lpi; - LPITEMIDLIST lpifq; - IEnumIDList* pEnumIL; -} TV_ITEMDATA, *LPTV_ITEMDATA; - -static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR lpFriendlyName) -{ - BOOL bSuccess=TRUE; - STRRET str; - - TRACE("%p %p %lx %p\n", lpsf, lpi, dwFlags, lpFriendlyName); - if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf, lpi, dwFlags, &str))) - { - if (FAILED(StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, lpi))) - { - bSuccess = FALSE; - } - } - else - bSuccess = FALSE; - - TRACE("-- %s\n", debugstr_w(lpFriendlyName)); - return bSuccess; -} - -static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent) -{ - TVITEMW tvi; - TVINSERTSTRUCTW tvins; - WCHAR szBuff[MAX_PATH]; - LPTV_ITEMDATA lptvid=0; - - tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; - - tvi.cChildren= pEnumIL ? 1 : 0; - tvi.mask |= TVIF_CHILDREN; - - if (!(lptvid = (LPTV_ITEMDATA)SHAlloc(sizeof(TV_ITEMDATA)))) - return NULL; - - if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff)) - return NULL; - - tvi.pszText = szBuff; - tvi.cchTextMax = MAX_PATH; - tvi.lParam = (LPARAM)lptvid; - - IShellFolder_AddRef(lpsf); - lptvid->lpsfParent = lpsf; - lptvid->lpi = ILClone(pidl); - lptvid->lpifq = pidlParent ? ILCombine(pidlParent, pidl) : ILClone(pidl); - lptvid->pEnumIL = pEnumIL; - GetNormalAndSelectedIcons(lptvid->lpifq, &tvi); - - tvins.u.item = tvi; - tvins.hInsertAfter = NULL; - tvins.hParent = hParent; - - return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins); -} - -static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hParent, IEnumIDList* lpe) -{ - HTREEITEM hPrev = 0; - LPITEMIDLIST pidlTemp = 0; - ULONG ulFetched; - HRESULT hr; - HWND hwnd=GetParent(hwndTreeView); - - TRACE("%p %p %x\n",lpsf, pidl, (INT)hParent); - SetCapture(GetParent(hwndTreeView)); - SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT)); - - while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)) - { - ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER; - IEnumIDList* pEnumIL = NULL; - IShellFolder* pSFChild = NULL; - IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulAttrs); - if (ulAttrs & SFGAO_FOLDER) - { - hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild); - if (SUCCEEDED(hr)) - { - hr = IShellFolder_EnumObjects(pSFChild, hwnd, BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumIL); - if (SUCCEEDED(hr)) - { - if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || FAILED(IEnumIDList_Reset(pEnumIL))) - { - IEnumIDList_Release(pEnumIL); - pEnumIL = NULL; - } - } - IShellFolder_Release(pSFChild); - } - } - - if (!(hPrev = InsertTreeViewItem(lpsf, pidlTemp, pidl, pEnumIL, hParent))) - goto Done; - SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */ - pidlTemp=NULL; - } - -Done: - ReleaseCapture(); - SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW)); - - if (pidlTemp) - SHFree(pidlTemp); -} - -static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type) -{ - LPPIDLDATA data = _ILGetDataPointer(pidl); - if (!data) - return FALSE; - return (data->type == type); -} - -static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid) -{ - LPCITEMIDLIST pidl = lptvid->lpi; - BOOL bEnabled = TRUE; - DWORD dwAttributes; - if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) && - !PIDLIsType(pidl, PT_COMP)) - bEnabled = FALSE; - if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS) - { - dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM; - if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || - !dwAttributes) - bEnabled = FALSE; - } - if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS) - { - dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM; - if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || - (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM))) - bEnabled = FALSE; - } - SendMessageW(hWndTree, BFFM_ENABLEOK, 0, (LPARAM)bEnabled); -} - -static LRESULT MsgNotify(HWND hWnd, UINT CtlID, LPNMHDR lpnmh) -{ - NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh; - LPTV_ITEMDATA lptvid; /* Long pointer to TreeView item data */ - IShellFolder * lpsf2=0; - - - TRACE("%p %x %p msg=%x\n", hWnd, CtlID, lpnmh, pnmtv->hdr.code); - - switch (pnmtv->hdr.idFrom) - { case IDD_TREEVIEW: - switch (pnmtv->hdr.code) - { - case TVN_DELETEITEMA: - case TVN_DELETEITEMW: - TRACE("TVN_DELETEITEMA/W\n"); - lptvid=(LPTV_ITEMDATA)pnmtv->itemOld.lParam; - IShellFolder_Release(lptvid->lpsfParent); - if (lptvid->pEnumIL) - IEnumIDList_Release(lptvid->pEnumIL); - SHFree(lptvid->lpi); - SHFree(lptvid->lpifq); - SHFree(lptvid); - break; - - case TVN_ITEMEXPANDINGA: - case TVN_ITEMEXPANDINGW: - { - TRACE("TVN_ITEMEXPANDINGA/W\n"); - if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) - break; - - lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam; - if (SUCCEEDED(IShellFolder_BindToObject(lptvid->lpsfParent, lptvid->lpi,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) - { FillTreeView( lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL); - } - TreeView_SortChildren(hwndTreeView, pnmtv->itemNew.hItem, FALSE); - } - break; - case TVN_SELCHANGEDA: - case TVN_SELCHANGEDW: - lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam; - pidlRet = lptvid->lpifq; - if (lpBrowseInfo->lpfn) - (lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, lpBrowseInfo->lParam); - BrsFolder_CheckValidSelection(hWnd, lptvid); - break; - - default: - WARN("unhandled (%d)\n", pnmtv->hdr.code); - break; - } - break; - - default: - break; - } - - return 0; -} - - -/************************************************************************* - * BrsFolderDlgProc32 (not an exported API function) - */ -static INT_PTR CALLBACK BrsFolderDlgProc(HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam ) -{ - TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam ); - - switch(msg) - { case WM_INITDIALOG: - pidlRet = NULL; - lpBrowseInfo = (LPBROWSEINFOW) lParam; - if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS) - FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS); - if (lpBrowseInfo->lpszTitle) { - SetWindowTextW(GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle); - } else { - ShowWindow(GetDlgItem(hWnd, IDD_TITLE), SW_HIDE); - } - if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)) - ShowWindow(GetDlgItem(hWnd, IDD_STATUS), SW_HIDE); - - InitializeTreeView(hWnd, lpBrowseInfo->pidlRoot); - - if (lpBrowseInfo->lpfn) - (lpBrowseInfo->lpfn)(hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam); - - return TRUE; - - case WM_NOTIFY: - MsgNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam); - break; - - case WM_COMMAND: - switch (wParam) - { case IDOK: - pdump ( pidlRet ); - if (lpBrowseInfo->pszDisplayName) - SHGetPathFromIDListW(pidlRet, lpBrowseInfo->pszDisplayName); - EndDialog(hWnd, (DWORD) ILClone(pidlRet)); - return TRUE; - - case IDCANCEL: - EndDialog(hWnd, 0); - return TRUE; - } - break; - case BFFM_SETSTATUSTEXTA: - TRACE("Set status %s\n", debugstr_a((LPSTR)lParam)); - SetWindowTextA(GetDlgItem(hWnd, IDD_STATUS), (LPSTR)lParam); - break; - case BFFM_SETSTATUSTEXTW: - TRACE("Set status %s\n", debugstr_w((LPWSTR)lParam)); - SetWindowTextW(GetDlgItem(hWnd, IDD_STATUS), (LPWSTR)lParam); - break; - case BFFM_ENABLEOK: - TRACE("Enable %ld\n", lParam); - EnableWindow(GetDlgItem(hWnd, 1), (lParam)?TRUE:FALSE); - break; - case BFFM_SETOKTEXT: /* unicode only */ - TRACE("Set OK text %s\n", debugstr_w((LPWSTR)wParam)); - SetWindowTextW(GetDlgItem(hWnd, 1), (LPWSTR)wParam); - break; - case BFFM_SETSELECTIONA: - if (wParam) - FIXME("Set selection %s\n", debugstr_a((LPSTR)lParam)); - else - FIXME("Set selection %p\n", (void*)lParam); - break; - case BFFM_SETSELECTIONW: - if (wParam) - FIXME("Set selection %s\n", debugstr_w((LPWSTR)lParam)); - else - FIXME("Set selection %p\n", (void*)lParam); - break; - case BFFM_SETEXPANDED: /* unicode only */ - if (wParam) - FIXME("Set expanded %s\n", debugstr_w((LPWSTR)lParam)); - else - FIXME("Set expanded %p\n", (void*)lParam); - break; - } - return FALSE; -} - -static const WCHAR swBrowseTempName[] = {'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0}; - -/************************************************************************* - * SHBrowseForFolderA [SHELL32.@] - * SHBrowseForFolder [SHELL32.@] - */ -LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi) -{ - BROWSEINFOW bi; - LPITEMIDLIST lpid; - INT len; - - TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi, - lpbi ? debugstr_a(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : NULL); - - if (!lpbi) - return NULL; - - bi.hwndOwner = lpbi->hwndOwner; - bi.pidlRoot = lpbi->pidlRoot; - if (lpbi->pszDisplayName) - { - /*lpbi->pszDisplayName is assumed to be MAX_PATH (MSDN) */ - bi.pszDisplayName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, MAX_PATH); - } - else - bi.pszDisplayName = NULL; - - if (lpbi->lpszTitle) - { - len = MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0); - bi.lpszTitle = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len); - } - else - bi.lpszTitle = NULL; - - bi.ulFlags = lpbi->ulFlags; - bi.lpfn = lpbi->lpfn; - bi.lParam = lpbi->lParam; - bi.iImage = lpbi->iImage; - lpid = (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, - swBrowseTempName, lpbi->hwndOwner, - BrsFolderDlgProc, (INT)&bi); - if (bi.pszDisplayName) - { - WideCharToMultiByte(CP_ACP, 0, bi.pszDisplayName, -1, lpbi->pszDisplayName, MAX_PATH, 0, NULL); - HeapFree(GetProcessHeap(), 0, bi.pszDisplayName); - } - if (bi.lpszTitle) - { - HeapFree(GetProcessHeap(), 0, (LPVOID)bi.lpszTitle); - } - lpbi->iImage = bi.iImage; - return lpid; -} - - -/************************************************************************* - * SHBrowseForFolderW [SHELL32.@] - */ -LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi) -{ - TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi, - lpbi ? debugstr_w(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : 0); - - if (!lpbi) - return NULL; - - return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, - swBrowseTempName, lpbi->hwndOwner, - BrsFolderDlgProc, (INT)lpbi); -} +/* + * Copyright 1999 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: + * - many memory leaks + * - many flags unimplemented + */ + +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "wine/debug.h" +#include "undocshell.h" +#include "shlguid.h" +#include "pidl.h" +#include "shell32_main.h" +#include "shellapi.h" +#include "shresdef.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +static HWND hwndTreeView; +static LPBROWSEINFOW lpBrowseInfo; +static LPITEMIDLIST pidlRet; + +static void FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent, IEnumIDList* lpe); +static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent); + +#define SUPPORTEDFLAGS (BIF_STATUSTEXT | \ + BIF_BROWSEFORCOMPUTER | \ + BIF_RETURNFSANCESTORS | \ + BIF_RETURNONLYFSDIRS | \ + BIF_BROWSEINCLUDEFILES) + +static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags) +{ + return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS : 0); +} + +static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root) +{ + HIMAGELIST hImageList; + IShellFolder * lpsf; + HRESULT hr; + IEnumIDList * pEnumIL = NULL; + LPITEMIDLIST parentofroot; + parentofroot = ILClone(root); + ILRemoveLastID(parentofroot); + + hwndTreeView = GetDlgItem (hwndParent, IDD_TREEVIEW); + Shell_GetImageList(NULL, &hImageList); + + TRACE("dlg=%p tree=%p\n", hwndParent, hwndTreeView ); + + if (hImageList && hwndTreeView) + TreeView_SetImageList(hwndTreeView, hImageList, 0); + + if (_ILIsDesktop (root)) { + hr = SHGetDesktopFolder(&lpsf); + } else { + IShellFolder * lpsfdesktop; + + hr = SHGetDesktopFolder(&lpsfdesktop); + if (SUCCEEDED(hr)) { + hr = IShellFolder_BindToObject(lpsfdesktop, parentofroot, 0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf); + IShellFolder_Release(lpsfdesktop); + } + } + if (SUCCEEDED(hr)) + { + IShellFolder * pSFRoot; + if (_ILIsPidlSimple(root)) + { + pSFRoot = lpsf; + IShellFolder_AddRef(pSFRoot); + } + else + hr = IShellFolder_BindToObject(lpsf,ILFindLastID(root),0,&IID_IShellFolder,(LPVOID *)&pSFRoot); + if (SUCCEEDED(hr)) + { + hr = IShellFolder_EnumObjects( + pSFRoot, + hwndParent, + BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), + &pEnumIL); + IShellFolder_Release(pSFRoot); + } + } + + if (SUCCEEDED(hr) && hwndTreeView) + { + TreeView_DeleteAllItems(hwndTreeView); + TreeView_Expand(hwndTreeView, + InsertTreeViewItem(lpsf, _ILIsPidlSimple(root) ? root : ILFindLastID(root), parentofroot, pEnumIL, TVI_ROOT), + TVE_EXPAND); + } + + if (SUCCEEDED(hr)) + IShellFolder_Release(lpsf); + + TRACE("done\n"); +} + +static int GetIcon(LPITEMIDLIST lpi, UINT uFlags) +{ + SHFILEINFOW sfi; + SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags); + return sfi.iIcon; +} + +static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM) +{ + LPITEMIDLIST pidlDesktop = NULL; + + TRACE("%p %p\n",lpifq, lpTV_ITEM); + + if (!lpifq) + { + pidlDesktop = _ILCreateDesktop(); + lpifq = pidlDesktop; + } + + lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON); + lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON); + + if (pidlDesktop) + ILFree(pidlDesktop); + + return; +} + +typedef struct tagID +{ + LPSHELLFOLDER lpsfParent; + LPITEMIDLIST lpi; + LPITEMIDLIST lpifq; + IEnumIDList* pEnumIL; +} TV_ITEMDATA, *LPTV_ITEMDATA; + +static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR lpFriendlyName) +{ + BOOL bSuccess=TRUE; + STRRET str; + + TRACE("%p %p %lx %p\n", lpsf, lpi, dwFlags, lpFriendlyName); + if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf, lpi, dwFlags, &str))) + { + if (FAILED(StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, lpi))) + { + bSuccess = FALSE; + } + } + else + bSuccess = FALSE; + + TRACE("-- %s\n", debugstr_w(lpFriendlyName)); + return bSuccess; +} + +static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent) +{ + TVITEMW tvi; + TVINSERTSTRUCTW tvins; + WCHAR szBuff[MAX_PATH]; + LPTV_ITEMDATA lptvid=0; + + tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + + tvi.cChildren= pEnumIL ? 1 : 0; + tvi.mask |= TVIF_CHILDREN; + + if (!(lptvid = (LPTV_ITEMDATA)SHAlloc(sizeof(TV_ITEMDATA)))) + return NULL; + + if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff)) + return NULL; + + tvi.pszText = szBuff; + tvi.cchTextMax = MAX_PATH; + tvi.lParam = (LPARAM)lptvid; + + IShellFolder_AddRef(lpsf); + lptvid->lpsfParent = lpsf; + lptvid->lpi = ILClone(pidl); + lptvid->lpifq = pidlParent ? ILCombine(pidlParent, pidl) : ILClone(pidl); + lptvid->pEnumIL = pEnumIL; + GetNormalAndSelectedIcons(lptvid->lpifq, &tvi); + + tvins.u.item = tvi; + tvins.hInsertAfter = NULL; + tvins.hParent = hParent; + + return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins); +} + +static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST pidl, HTREEITEM hParent, IEnumIDList* lpe) +{ + HTREEITEM hPrev = 0; + LPITEMIDLIST pidlTemp = 0; + ULONG ulFetched; + HRESULT hr; + HWND hwnd=GetParent(hwndTreeView); + + TRACE("%p %p %x\n",lpsf, pidl, (INT)hParent); + SetCapture(GetParent(hwndTreeView)); + SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT)); + + while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)) + { + ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER; + IEnumIDList* pEnumIL = NULL; + IShellFolder* pSFChild = NULL; + IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulAttrs); + if (ulAttrs & SFGAO_FOLDER) + { + hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild); + if (SUCCEEDED(hr)) + { + hr = IShellFolder_EnumObjects(pSFChild, hwnd, BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumIL); + if (SUCCEEDED(hr)) + { + if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || FAILED(IEnumIDList_Reset(pEnumIL))) + { + IEnumIDList_Release(pEnumIL); + pEnumIL = NULL; + } + } + IShellFolder_Release(pSFChild); + } + } + + if (!(hPrev = InsertTreeViewItem(lpsf, pidlTemp, pidl, pEnumIL, hParent))) + goto Done; + SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */ + pidlTemp=NULL; + } + +Done: + ReleaseCapture(); + SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW)); + + if (pidlTemp) + SHFree(pidlTemp); +} + +static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type) +{ + LPPIDLDATA data = _ILGetDataPointer(pidl); + if (!data) + return FALSE; + return (data->type == type); +} + +static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid) +{ + LPCITEMIDLIST pidl = lptvid->lpi; + BOOL bEnabled = TRUE; + DWORD dwAttributes; + if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) && + !PIDLIsType(pidl, PT_COMP)) + bEnabled = FALSE; + if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS) + { + dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM; + if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || + !dwAttributes) + bEnabled = FALSE; + } + if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS) + { + dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM; + if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || + (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM))) + bEnabled = FALSE; + } + SendMessageW(hWndTree, BFFM_ENABLEOK, 0, (LPARAM)bEnabled); +} + +static LRESULT MsgNotify(HWND hWnd, UINT CtlID, LPNMHDR lpnmh) +{ + NMTREEVIEWW *pnmtv = (NMTREEVIEWW *)lpnmh; + LPTV_ITEMDATA lptvid; /* Long pointer to TreeView item data */ + IShellFolder * lpsf2=0; + + + TRACE("%p %x %p msg=%x\n", hWnd, CtlID, lpnmh, pnmtv->hdr.code); + + switch (pnmtv->hdr.idFrom) + { case IDD_TREEVIEW: + switch (pnmtv->hdr.code) + { + case TVN_DELETEITEMA: + case TVN_DELETEITEMW: + TRACE("TVN_DELETEITEMA/W\n"); + lptvid=(LPTV_ITEMDATA)pnmtv->itemOld.lParam; + IShellFolder_Release(lptvid->lpsfParent); + if (lptvid->pEnumIL) + IEnumIDList_Release(lptvid->pEnumIL); + SHFree(lptvid->lpi); + SHFree(lptvid->lpifq); + SHFree(lptvid); + break; + + case TVN_ITEMEXPANDINGA: + case TVN_ITEMEXPANDINGW: + { + TRACE("TVN_ITEMEXPANDINGA/W\n"); + if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE)) + break; + + lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam; + if (SUCCEEDED(IShellFolder_BindToObject(lptvid->lpsfParent, lptvid->lpi,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) + { FillTreeView( lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, lptvid->pEnumIL); + } + /* My Computer is already sorted and trying to do a simple text + * sort will only mess things up */ + if (!_ILIsMyComputer(lptvid->lpi)) + TreeView_SortChildren(hwndTreeView, pnmtv->itemNew.hItem, FALSE); + } + break; + case TVN_SELCHANGEDA: + case TVN_SELCHANGEDW: + lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam; + pidlRet = lptvid->lpifq; + if (lpBrowseInfo->lpfn) + (lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, lpBrowseInfo->lParam); + BrsFolder_CheckValidSelection(hWnd, lptvid); + break; + + default: + WARN("unhandled (%d)\n", pnmtv->hdr.code); + break; + } + break; + + default: + break; + } + + return 0; +} + + +/************************************************************************* + * BrsFolderDlgProc32 (not an exported API function) + */ +static INT_PTR CALLBACK BrsFolderDlgProc(HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam ) +{ + TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd, msg, wParam, lParam ); + + switch(msg) + { case WM_INITDIALOG: + pidlRet = NULL; + lpBrowseInfo = (LPBROWSEINFOW) lParam; + if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS) + FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS); + if (lpBrowseInfo->lpszTitle) { + SetWindowTextW(GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle); + } else { + ShowWindow(GetDlgItem(hWnd, IDD_TITLE), SW_HIDE); + } + if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT)) + ShowWindow(GetDlgItem(hWnd, IDD_STATUS), SW_HIDE); + + InitializeTreeView(hWnd, lpBrowseInfo->pidlRoot); + + if (lpBrowseInfo->lpfn) + (lpBrowseInfo->lpfn)(hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam); + + return TRUE; + + case WM_NOTIFY: + MsgNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam); + break; + + case WM_COMMAND: + switch (wParam) + { case IDOK: + pdump ( pidlRet ); + if (lpBrowseInfo->pszDisplayName) + SHGetPathFromIDListW(pidlRet, lpBrowseInfo->pszDisplayName); + EndDialog(hWnd, (DWORD) ILClone(pidlRet)); + return TRUE; + + case IDCANCEL: + EndDialog(hWnd, 0); + return TRUE; + } + break; + case BFFM_SETSTATUSTEXTA: + TRACE("Set status %s\n", debugstr_a((LPSTR)lParam)); + SetWindowTextA(GetDlgItem(hWnd, IDD_STATUS), (LPSTR)lParam); + break; + case BFFM_SETSTATUSTEXTW: + TRACE("Set status %s\n", debugstr_w((LPWSTR)lParam)); + SetWindowTextW(GetDlgItem(hWnd, IDD_STATUS), (LPWSTR)lParam); + break; + case BFFM_ENABLEOK: + TRACE("Enable %ld\n", lParam); + EnableWindow(GetDlgItem(hWnd, 1), (lParam)?TRUE:FALSE); + break; + case BFFM_SETOKTEXT: /* unicode only */ + TRACE("Set OK text %s\n", debugstr_w((LPWSTR)wParam)); + SetWindowTextW(GetDlgItem(hWnd, 1), (LPWSTR)wParam); + break; + case BFFM_SETSELECTIONA: + if (wParam) + FIXME("Set selection %s\n", debugstr_a((LPSTR)lParam)); + else + FIXME("Set selection %p\n", (void*)lParam); + break; + case BFFM_SETSELECTIONW: + if (wParam) + FIXME("Set selection %s\n", debugstr_w((LPWSTR)lParam)); + else + FIXME("Set selection %p\n", (void*)lParam); + break; + case BFFM_SETEXPANDED: /* unicode only */ + if (wParam) + FIXME("Set expanded %s\n", debugstr_w((LPWSTR)lParam)); + else + FIXME("Set expanded %p\n", (void*)lParam); + break; + } + return FALSE; +} + +static const WCHAR swBrowseTempName[] = {'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0}; + +/************************************************************************* + * SHBrowseForFolderA [SHELL32.@] + * SHBrowseForFolder [SHELL32.@] + */ +LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi) +{ + BROWSEINFOW bi; + LPITEMIDLIST lpid; + INT len; + + TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi, + lpbi ? debugstr_a(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : NULL); + + if (!lpbi) + return NULL; + + bi.hwndOwner = lpbi->hwndOwner; + bi.pidlRoot = lpbi->pidlRoot; + if (lpbi->pszDisplayName) + { + /*lpbi->pszDisplayName is assumed to be MAX_PATH (MSDN) */ + bi.pszDisplayName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpbi->pszDisplayName, -1, bi.pszDisplayName, MAX_PATH); + } + else + bi.pszDisplayName = NULL; + + if (lpbi->lpszTitle) + { + len = MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, NULL, 0); + bi.lpszTitle = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpbi->lpszTitle, -1, (LPWSTR)bi.lpszTitle, len); + } + else + bi.lpszTitle = NULL; + + bi.ulFlags = lpbi->ulFlags; + bi.lpfn = lpbi->lpfn; + bi.lParam = lpbi->lParam; + bi.iImage = lpbi->iImage; + lpid = (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, + swBrowseTempName, lpbi->hwndOwner, + BrsFolderDlgProc, (INT)&bi); + if (bi.pszDisplayName) + { + WideCharToMultiByte(CP_ACP, 0, bi.pszDisplayName, -1, lpbi->pszDisplayName, MAX_PATH, 0, NULL); + HeapFree(GetProcessHeap(), 0, bi.pszDisplayName); + } + HeapFree(GetProcessHeap(), 0, (LPVOID)bi.lpszTitle); + lpbi->iImage = bi.iImage; + return lpid; +} + + +/************************************************************************* + * SHBrowseForFolderW [SHELL32.@] + */ +LPITEMIDLIST WINAPI SHBrowseForFolderW (LPBROWSEINFOW lpbi) +{ + TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi, + lpbi ? debugstr_w(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : 0); + + if (!lpbi) + return NULL; + + return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance, + swBrowseTempName, lpbi->hwndOwner, + BrsFolderDlgProc, (INT)lpbi); +} diff --git a/reactos/lib/shell32/changenotify.c b/reactos/lib/shell32/changenotify.c index e252cf44c31..36a699849b7 100644 --- a/reactos/lib/shell32/changenotify.c +++ b/reactos/lib/shell32/changenotify.c @@ -1,484 +1,480 @@ -/* - * shell change notification - * - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "windef.h" -#include "winbase.h" -#include "wine/debug.h" -#include "wingdi.h" -#include "pidl.h" -#include "shell32_main.h" -#include "undocshell.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -static CRITICAL_SECTION SHELL32_ChangenotifyCS; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &SHELL32_ChangenotifyCS, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { 0, (DWORD)(__FILE__ ": SHELL32_ChangenotifyCS") } -}; -static CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 }; - -typedef SHChangeNotifyEntry *LPNOTIFYREGISTER; - -/* internal list of notification clients (internal) */ -typedef struct _NOTIFICATIONLIST -{ - struct _NOTIFICATIONLIST *next; - struct _NOTIFICATIONLIST *prev; - HWND hwnd; /* window to notify */ - DWORD uMsg; /* message to send */ - LPNOTIFYREGISTER apidl; /* array of entries to watch*/ - UINT cidl; /* number of pidls in array */ - LONG wEventMask; /* subscribed events */ - LONG wSignalledEvent; /* event that occurred */ - DWORD dwFlags; /* client flags */ - LPCITEMIDLIST pidlSignaled; /*pidl of the path that caused the signal*/ - -} NOTIFICATIONLIST, *LPNOTIFICATIONLIST; - -static NOTIFICATIONLIST *head, *tail; - -#define SHCNE_NOITEMEVENTS ( \ - SHCNE_ASSOCCHANGED ) - -#define SHCNE_ONEITEMEVENTS ( \ - SHCNE_ATTRIBUTES | SHCNE_CREATE | SHCNE_DELETE | SHCNE_DRIVEADD | \ - SHCNE_DRIVEADDGUI | SHCNE_DRIVEREMOVED | SHCNE_FREESPACE | \ - SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_MKDIR | \ - SHCNE_NETSHARE | SHCNE_NETUNSHARE | SHCNE_RMDIR | \ - SHCNE_SERVERDISCONNECT | SHCNE_UPDATEDIR | SHCNE_UPDATEIMAGE ) - -#define SHCNE_TWOITEMEVENTS ( \ - SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEITEM ) - -/* for dumping events */ -static const char * DumpEvent( LONG event ) -{ - if( event == SHCNE_ALLEVENTS ) - return "SHCNE_ALLEVENTS"; -#define DUMPEV(x) ,( event & SHCNE_##x )? #x " " : "" - return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" - DUMPEV(RENAMEITEM) - DUMPEV(CREATE) - DUMPEV(DELETE) - DUMPEV(MKDIR) - DUMPEV(RMDIR) - DUMPEV(MEDIAINSERTED) - DUMPEV(MEDIAREMOVED) - DUMPEV(DRIVEREMOVED) - DUMPEV(DRIVEADD) - DUMPEV(NETSHARE) - DUMPEV(NETUNSHARE) - DUMPEV(ATTRIBUTES) - DUMPEV(UPDATEDIR) - DUMPEV(UPDATEITEM) - DUMPEV(SERVERDISCONNECT) - DUMPEV(UPDATEIMAGE) - DUMPEV(DRIVEADDGUI) - DUMPEV(RENAMEFOLDER) - DUMPEV(FREESPACE) - DUMPEV(EXTENDED_EVENT) - DUMPEV(ASSOCCHANGED) - DUMPEV(INTERRUPT) - ); -#undef DUMPEV -} - -static const char * NodeName(LPNOTIFICATIONLIST item) -{ - const char *str; - WCHAR path[MAX_PATH]; - - if(SHGetPathFromIDListW(item->apidl[0].pidl, path )) - str = wine_dbg_sprintf("%s", debugstr_w(path)); - else - str = wine_dbg_sprintf("" ); - return str; -} - -static void AddNode(LPNOTIFICATIONLIST item) -{ - TRACE("item %p\n", item ); - - /* link items */ - item->prev = tail; - item->next = NULL; - if( tail ) - tail->next = item; - else - head = item; - tail = item; -} - -static LPNOTIFICATIONLIST FindNode( HANDLE hitem ) -{ - LPNOTIFICATIONLIST ptr; - for( ptr = head; ptr; ptr = ptr->next ) - if( ptr == (LPNOTIFICATIONLIST) hitem ) - return ptr; - return NULL; -} - -static void DeleteNode(LPNOTIFICATIONLIST item) -{ - UINT i; - - TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next); - - /* remove item from list */ - if( item->prev ) - item->prev->next = item->next; - else - head = item->next; - if( item->next ) - item->next->prev = item->prev; - else - tail = item->prev; - - /* free the item */ - for (i=0; icidl; i++) - SHFree((LPITEMIDLIST)item->apidl[i].pidl); - SHFree(item->apidl); - SHFree(item); -} - -void InitChangeNotifications(void) -{ -} - -void FreeChangeNotifications(void) -{ - TRACE("\n"); - - EnterCriticalSection(&SHELL32_ChangenotifyCS); - - while( head ) - DeleteNode( head ); - - LeaveCriticalSection(&SHELL32_ChangenotifyCS); - - DeleteCriticalSection(&SHELL32_ChangenotifyCS); -} - -/************************************************************************* - * SHChangeNotifyRegister [SHELL32.2] - * - */ -ULONG WINAPI -SHChangeNotifyRegister( - HWND hwnd, - int fSources, - LONG wEventMask, - UINT uMsg, - int cItems, - SHChangeNotifyEntry *lpItems) -{ - LPNOTIFICATIONLIST item; - int i; - - item = SHAlloc(sizeof(NOTIFICATIONLIST)); - - TRACE("(%p,0x%08x,0x%08lx,0x%08x,%d,%p) item=%p\n", - hwnd, fSources, wEventMask, uMsg, cItems, lpItems, item); - - item->next = NULL; - item->prev = NULL; - item->cidl = cItems; - item->apidl = SHAlloc(sizeof(SHChangeNotifyEntry) * cItems); - for(i=0;iapidl[i].pidl = ILClone(lpItems[i].pidl); - item->apidl[i].fRecursive = lpItems[i].fRecursive; - } - item->hwnd = hwnd; - item->uMsg = uMsg; - item->wEventMask = wEventMask; - item->wSignalledEvent = 0; - item->dwFlags = fSources; - - TRACE("new node: %s\n", NodeName( item )); - - EnterCriticalSection(&SHELL32_ChangenotifyCS); - - AddNode(item); - - LeaveCriticalSection(&SHELL32_ChangenotifyCS); - - return (ULONG)item; -} - -/************************************************************************* - * SHChangeNotifyDeregister [SHELL32.4] - */ -BOOL WINAPI SHChangeNotifyDeregister(ULONG hNotify) -{ - LPNOTIFICATIONLIST node; - - TRACE("(0x%08lx)\n", hNotify); - - EnterCriticalSection(&SHELL32_ChangenotifyCS); - - node = FindNode((HANDLE)hNotify); - if( node ) - DeleteNode(node); - - LeaveCriticalSection(&SHELL32_ChangenotifyCS); - - return node?TRUE:FALSE; -} - -/************************************************************************* - * SHChangeNotifyUpdateEntryList [SHELL32.5] - */ -BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2, - DWORD unknown3, DWORD unknown4) -{ - FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", - unknown1, unknown2, unknown3, unknown4); - - return -1; -} - -static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL sub ) -{ - TRACE("%p %p %d\n", changed, watched, sub ); - if ( !watched ) - return FALSE; - if (ILIsEqual( watched, changed ) ) - return TRUE; - if( sub && ILIsParent( watched, changed, FALSE ) ) - return TRUE; - return FALSE; -} - -/************************************************************************* - * SHChangeNotify [SHELL32.@] - */ -void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) -{ - LPCITEMIDLIST Pidls[2]; - LPNOTIFICATIONLIST ptr; - UINT typeFlag = uFlags & SHCNF_TYPE; - - Pidls[0] = NULL; - Pidls[1] = NULL; - - TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId, uFlags, dwItem1, dwItem2); - - if( ( wEventId & SHCNE_NOITEMEVENTS ) && ( dwItem1 || dwItem2 ) ) - { - TRACE("dwItem1 and dwItem2 are not zero, but should be\n"); - dwItem1 = 0; - dwItem2 = 0; - return; - } - else if( ( wEventId & SHCNE_ONEITEMEVENTS ) && dwItem2 ) - { - TRACE("dwItem2 is not zero, but should be\n"); - dwItem2 = 0; - return; - } - - if( ( ( wEventId & SHCNE_NOITEMEVENTS ) && - ( wEventId & ~SHCNE_NOITEMEVENTS ) ) || - ( ( wEventId & SHCNE_ONEITEMEVENTS ) && - ( wEventId & ~SHCNE_ONEITEMEVENTS ) ) || - ( ( wEventId & SHCNE_TWOITEMEVENTS ) && - ( wEventId & ~SHCNE_TWOITEMEVENTS ) ) ) - { - WARN("mutually incompatible events listed\n"); - return; - } - - /* convert paths in IDLists*/ - switch (typeFlag) - { - case SHCNF_PATHA: - if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA((LPCSTR)dwItem1); - if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA((LPCSTR)dwItem2); - break; - case SHCNF_PATHW: - if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1); - if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2); - break; - case SHCNF_IDLIST: - Pidls[0] = (LPCITEMIDLIST)dwItem1; - Pidls[1] = (LPCITEMIDLIST)dwItem2; - break; - case SHCNF_PRINTERA: - case SHCNF_PRINTERW: - FIXME("SHChangeNotify with (uFlags & SHCNF_PRINTER)\n"); - return; - case SHCNF_DWORD: - default: - FIXME("unknown type %08x\n",typeFlag); - return; - } - - { - WCHAR path[MAX_PATH]; - - if( Pidls[0] && SHGetPathFromIDListW(Pidls[0], path )) - TRACE("notify %08lx on item1 = %s\n", wEventId, debugstr_w(path)); - - if( Pidls[1] && SHGetPathFromIDListW(Pidls[1], path )) - TRACE("notify %08lx on item2 = %s\n", wEventId, debugstr_w(path)); - } - - EnterCriticalSection(&SHELL32_ChangenotifyCS); - - /* loop through the list */ - for( ptr = head; ptr; ptr = ptr->next ) - { - BOOL notify; - DWORD i; - - notify = FALSE; - - TRACE("trying %p\n", ptr); - - for( i=0; (icidl) && !notify ; i++ ) - { - LPCITEMIDLIST pidl = ptr->apidl[i].pidl; - BOOL subtree = ptr->apidl[i].fRecursive; - - if (wEventId & ptr->wEventMask) - { - if( !pidl ) /* all ? */ - notify = TRUE; - else if( wEventId & SHCNE_NOITEMEVENTS ) - notify = TRUE; - else if( wEventId & ( SHCNE_ONEITEMEVENTS | SHCNE_TWOITEMEVENTS ) ) - notify = should_notify( Pidls[0], pidl, subtree ); - else if( wEventId & SHCNE_TWOITEMEVENTS ) - notify = should_notify( Pidls[1], pidl, subtree ); - } - } - - if( !notify ) - continue; - - ptr->pidlSignaled = ILClone(Pidls[0]); - - TRACE("notifying %s, event %s(%lx) before\n", NodeName( ptr ), DumpEvent( - wEventId ),wEventId ); - - ptr->wSignalledEvent |= wEventId; - - if (ptr->dwFlags & SHCNRF_NewDelivery) - SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM) ptr, (LPARAM) GetCurrentProcessId()); - else - SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)Pidls, wEventId); - - TRACE("notifying %s, event %s(%lx) after\n", NodeName( ptr ), DumpEvent( - wEventId ),wEventId ); - - } - TRACE("notify Done\n"); - LeaveCriticalSection(&SHELL32_ChangenotifyCS); - - /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */ - if ((typeFlag & SHCNF_PATHA) || (typeFlag & SHCNF_PRINTERA)) - { - if (Pidls[0]) SHFree((LPITEMIDLIST)Pidls[0]); - if (Pidls[1]) SHFree((LPITEMIDLIST)Pidls[1]); - } -} - -/************************************************************************* - * NTSHChangeNotifyRegister [SHELL32.640] - * NOTES - * Idlist is an array of structures and Count specifies how many items in the array - * (usually just one I think). - */ -DWORD WINAPI NTSHChangeNotifyRegister( - HWND hwnd, - LONG events1, - LONG events2, - DWORD msg, - int count, - SHChangeNotifyEntry *idlist) -{ - FIXME("(%p,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):semi stub.\n", - hwnd,events1,events2,msg,count,idlist); - - return (DWORD) SHChangeNotifyRegister(hwnd, events1, events2, msg, count, idlist); -} - -/************************************************************************* - * SHChangeNotification_Lock [SHELL32.644] - */ -HANDLE WINAPI SHChangeNotification_Lock( - HANDLE hChange, - DWORD dwProcessId, - LPITEMIDLIST **lppidls, - LPLONG lpwEventId) -{ - DWORD i; - LPNOTIFICATIONLIST node; - LPCITEMIDLIST *idlist; - - TRACE("%p %08lx %p %p\n", hChange, dwProcessId, lppidls, lpwEventId); - - /* EnterCriticalSection(&SHELL32_ChangenotifyCS); */ - - node = FindNode( hChange ); - if( node ) - { - idlist = SHAlloc( sizeof(LPCITEMIDLIST *) * node->cidl ); - for(i=0; icidl; i++) - idlist[i] = (LPCITEMIDLIST)node->pidlSignaled; - *lpwEventId = node->wSignalledEvent; - *lppidls = (LPITEMIDLIST*)idlist; - node->wSignalledEvent = 0; - } - else - ERR("Couldn't find %p\n", hChange ); - - /* LeaveCriticalSection(&SHELL32_ChangenotifyCS); */ - - return (HANDLE) node; -} - -/************************************************************************* - * SHChangeNotification_Unlock [SHELL32.645] - */ -BOOL WINAPI SHChangeNotification_Unlock ( HANDLE hLock) -{ - TRACE("\n"); - return 1; -} - -/************************************************************************* - * NTSHChangeNotifyDeregister [SHELL32.641] - */ -DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1) -{ - FIXME("(0x%08lx):semi stub.\n",x1); - - return SHChangeNotifyDeregister( x1 ); -} +/* + * shell change notification + * + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "wine/debug.h" +#include "wingdi.h" +#include "shell32_main.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +static CRITICAL_SECTION SHELL32_ChangenotifyCS; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &SHELL32_ChangenotifyCS, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": SHELL32_ChangenotifyCS") } +}; +static CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 }; + +typedef SHChangeNotifyEntry *LPNOTIFYREGISTER; + +/* internal list of notification clients (internal) */ +typedef struct _NOTIFICATIONLIST +{ + struct _NOTIFICATIONLIST *next; + struct _NOTIFICATIONLIST *prev; + HWND hwnd; /* window to notify */ + DWORD uMsg; /* message to send */ + LPNOTIFYREGISTER apidl; /* array of entries to watch*/ + UINT cidl; /* number of pidls in array */ + LONG wEventMask; /* subscribed events */ + LONG wSignalledEvent; /* event that occurred */ + DWORD dwFlags; /* client flags */ + LPCITEMIDLIST pidlSignaled; /*pidl of the path that caused the signal*/ + +} NOTIFICATIONLIST, *LPNOTIFICATIONLIST; + +static NOTIFICATIONLIST *head, *tail; + +#define SHCNE_NOITEMEVENTS ( \ + SHCNE_ASSOCCHANGED ) + +#define SHCNE_ONEITEMEVENTS ( \ + SHCNE_ATTRIBUTES | SHCNE_CREATE | SHCNE_DELETE | SHCNE_DRIVEADD | \ + SHCNE_DRIVEADDGUI | SHCNE_DRIVEREMOVED | SHCNE_FREESPACE | \ + SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_MKDIR | \ + SHCNE_NETSHARE | SHCNE_NETUNSHARE | SHCNE_RMDIR | \ + SHCNE_SERVERDISCONNECT | SHCNE_UPDATEDIR | SHCNE_UPDATEIMAGE ) + +#define SHCNE_TWOITEMEVENTS ( \ + SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEITEM ) + +/* for dumping events */ +static const char * DumpEvent( LONG event ) +{ + if( event == SHCNE_ALLEVENTS ) + return "SHCNE_ALLEVENTS"; +#define DUMPEV(x) ,( event & SHCNE_##x )? #x " " : "" + return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" + DUMPEV(RENAMEITEM) + DUMPEV(CREATE) + DUMPEV(DELETE) + DUMPEV(MKDIR) + DUMPEV(RMDIR) + DUMPEV(MEDIAINSERTED) + DUMPEV(MEDIAREMOVED) + DUMPEV(DRIVEREMOVED) + DUMPEV(DRIVEADD) + DUMPEV(NETSHARE) + DUMPEV(NETUNSHARE) + DUMPEV(ATTRIBUTES) + DUMPEV(UPDATEDIR) + DUMPEV(UPDATEITEM) + DUMPEV(SERVERDISCONNECT) + DUMPEV(UPDATEIMAGE) + DUMPEV(DRIVEADDGUI) + DUMPEV(RENAMEFOLDER) + DUMPEV(FREESPACE) + DUMPEV(EXTENDED_EVENT) + DUMPEV(ASSOCCHANGED) + DUMPEV(INTERRUPT) + ); +#undef DUMPEV +} + +static const char * NodeName(LPNOTIFICATIONLIST item) +{ + const char *str; + WCHAR path[MAX_PATH]; + + if(SHGetPathFromIDListW(item->apidl[0].pidl, path )) + str = wine_dbg_sprintf("%s", debugstr_w(path)); + else + str = wine_dbg_sprintf("" ); + return str; +} + +static void AddNode(LPNOTIFICATIONLIST item) +{ + TRACE("item %p\n", item ); + + /* link items */ + item->prev = tail; + item->next = NULL; + if( tail ) + tail->next = item; + else + head = item; + tail = item; +} + +static LPNOTIFICATIONLIST FindNode( HANDLE hitem ) +{ + LPNOTIFICATIONLIST ptr; + for( ptr = head; ptr; ptr = ptr->next ) + if( ptr == (LPNOTIFICATIONLIST) hitem ) + return ptr; + return NULL; +} + +static void DeleteNode(LPNOTIFICATIONLIST item) +{ + UINT i; + + TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next); + + /* remove item from list */ + if( item->prev ) + item->prev->next = item->next; + else + head = item->next; + if( item->next ) + item->next->prev = item->prev; + else + tail = item->prev; + + /* free the item */ + for (i=0; icidl; i++) + SHFree((LPITEMIDLIST)item->apidl[i].pidl); + SHFree(item->apidl); + SHFree(item); +} + +void InitChangeNotifications(void) +{ +} + +void FreeChangeNotifications(void) +{ + TRACE("\n"); + + EnterCriticalSection(&SHELL32_ChangenotifyCS); + + while( head ) + DeleteNode( head ); + + LeaveCriticalSection(&SHELL32_ChangenotifyCS); +} + +/************************************************************************* + * SHChangeNotifyRegister [SHELL32.2] + * + */ +ULONG WINAPI +SHChangeNotifyRegister( + HWND hwnd, + int fSources, + LONG wEventMask, + UINT uMsg, + int cItems, + SHChangeNotifyEntry *lpItems) +{ + LPNOTIFICATIONLIST item; + int i; + + item = SHAlloc(sizeof(NOTIFICATIONLIST)); + + TRACE("(%p,0x%08x,0x%08lx,0x%08x,%d,%p) item=%p\n", + hwnd, fSources, wEventMask, uMsg, cItems, lpItems, item); + + item->next = NULL; + item->prev = NULL; + item->cidl = cItems; + item->apidl = SHAlloc(sizeof(SHChangeNotifyEntry) * cItems); + for(i=0;iapidl[i].pidl = ILClone(lpItems[i].pidl); + item->apidl[i].fRecursive = lpItems[i].fRecursive; + } + item->hwnd = hwnd; + item->uMsg = uMsg; + item->wEventMask = wEventMask; + item->wSignalledEvent = 0; + item->dwFlags = fSources; + + TRACE("new node: %s\n", NodeName( item )); + + EnterCriticalSection(&SHELL32_ChangenotifyCS); + + AddNode(item); + + LeaveCriticalSection(&SHELL32_ChangenotifyCS); + + return (ULONG)item; +} + +/************************************************************************* + * SHChangeNotifyDeregister [SHELL32.4] + */ +BOOL WINAPI SHChangeNotifyDeregister(ULONG hNotify) +{ + LPNOTIFICATIONLIST node; + + TRACE("(0x%08lx)\n", hNotify); + + EnterCriticalSection(&SHELL32_ChangenotifyCS); + + node = FindNode((HANDLE)hNotify); + if( node ) + DeleteNode(node); + + LeaveCriticalSection(&SHELL32_ChangenotifyCS); + + return node?TRUE:FALSE; +} + +/************************************************************************* + * SHChangeNotifyUpdateEntryList [SHELL32.5] + */ +BOOL WINAPI SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2, + DWORD unknown3, DWORD unknown4) +{ + FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", + unknown1, unknown2, unknown3, unknown4); + + return -1; +} + +static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL sub ) +{ + TRACE("%p %p %d\n", changed, watched, sub ); + if ( !watched ) + return FALSE; + if (ILIsEqual( watched, changed ) ) + return TRUE; + if( sub && ILIsParent( watched, changed, FALSE ) ) + return TRUE; + return FALSE; +} + +/************************************************************************* + * SHChangeNotify [SHELL32.@] + */ +void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) +{ + LPCITEMIDLIST Pidls[2]; + LPNOTIFICATIONLIST ptr; + UINT typeFlag = uFlags & SHCNF_TYPE; + + Pidls[0] = NULL; + Pidls[1] = NULL; + + TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId, uFlags, dwItem1, dwItem2); + + if( ( wEventId & SHCNE_NOITEMEVENTS ) && ( dwItem1 || dwItem2 ) ) + { + TRACE("dwItem1 and dwItem2 are not zero, but should be\n"); + dwItem1 = 0; + dwItem2 = 0; + return; + } + else if( ( wEventId & SHCNE_ONEITEMEVENTS ) && dwItem2 ) + { + TRACE("dwItem2 is not zero, but should be\n"); + dwItem2 = 0; + return; + } + + if( ( ( wEventId & SHCNE_NOITEMEVENTS ) && + ( wEventId & ~SHCNE_NOITEMEVENTS ) ) || + ( ( wEventId & SHCNE_ONEITEMEVENTS ) && + ( wEventId & ~SHCNE_ONEITEMEVENTS ) ) || + ( ( wEventId & SHCNE_TWOITEMEVENTS ) && + ( wEventId & ~SHCNE_TWOITEMEVENTS ) ) ) + { + WARN("mutually incompatible events listed\n"); + return; + } + + /* convert paths in IDLists*/ + switch (typeFlag) + { + case SHCNF_PATHA: + if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA((LPCSTR)dwItem1); + if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA((LPCSTR)dwItem2); + break; + case SHCNF_PATHW: + if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1); + if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2); + break; + case SHCNF_IDLIST: + Pidls[0] = (LPCITEMIDLIST)dwItem1; + Pidls[1] = (LPCITEMIDLIST)dwItem2; + break; + case SHCNF_PRINTERA: + case SHCNF_PRINTERW: + FIXME("SHChangeNotify with (uFlags & SHCNF_PRINTER)\n"); + return; + case SHCNF_DWORD: + default: + FIXME("unknown type %08x\n",typeFlag); + return; + } + + { + WCHAR path[MAX_PATH]; + + if( Pidls[0] && SHGetPathFromIDListW(Pidls[0], path )) + TRACE("notify %08lx on item1 = %s\n", wEventId, debugstr_w(path)); + + if( Pidls[1] && SHGetPathFromIDListW(Pidls[1], path )) + TRACE("notify %08lx on item2 = %s\n", wEventId, debugstr_w(path)); + } + + EnterCriticalSection(&SHELL32_ChangenotifyCS); + + /* loop through the list */ + for( ptr = head; ptr; ptr = ptr->next ) + { + BOOL notify; + DWORD i; + + notify = FALSE; + + TRACE("trying %p\n", ptr); + + for( i=0; (icidl) && !notify ; i++ ) + { + LPCITEMIDLIST pidl = ptr->apidl[i].pidl; + BOOL subtree = ptr->apidl[i].fRecursive; + + if (wEventId & ptr->wEventMask) + { + if( !pidl ) /* all ? */ + notify = TRUE; + else if( wEventId & SHCNE_NOITEMEVENTS ) + notify = TRUE; + else if( wEventId & ( SHCNE_ONEITEMEVENTS | SHCNE_TWOITEMEVENTS ) ) + notify = should_notify( Pidls[0], pidl, subtree ); + else if( wEventId & SHCNE_TWOITEMEVENTS ) + notify = should_notify( Pidls[1], pidl, subtree ); + } + } + + if( !notify ) + continue; + + ptr->pidlSignaled = ILClone(Pidls[0]); + + TRACE("notifying %s, event %s(%lx) before\n", NodeName( ptr ), DumpEvent( + wEventId ),wEventId ); + + ptr->wSignalledEvent |= wEventId; + + if (ptr->dwFlags & SHCNRF_NewDelivery) + SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM) ptr, (LPARAM) GetCurrentProcessId()); + else + SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)Pidls, wEventId); + + TRACE("notifying %s, event %s(%lx) after\n", NodeName( ptr ), DumpEvent( + wEventId ),wEventId ); + + } + TRACE("notify Done\n"); + LeaveCriticalSection(&SHELL32_ChangenotifyCS); + + /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */ + if ((typeFlag & SHCNF_PATHA) || (typeFlag & SHCNF_PRINTERA)) + { + if (Pidls[0]) SHFree((LPITEMIDLIST)Pidls[0]); + if (Pidls[1]) SHFree((LPITEMIDLIST)Pidls[1]); + } +} + +/************************************************************************* + * NTSHChangeNotifyRegister [SHELL32.640] + * NOTES + * Idlist is an array of structures and Count specifies how many items in the array + * (usually just one I think). + */ +DWORD WINAPI NTSHChangeNotifyRegister( + HWND hwnd, + LONG events1, + LONG events2, + DWORD msg, + int count, + SHChangeNotifyEntry *idlist) +{ + FIXME("(%p,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):semi stub.\n", + hwnd,events1,events2,msg,count,idlist); + + return (DWORD) SHChangeNotifyRegister(hwnd, events1, events2, msg, count, idlist); +} + +/************************************************************************* + * SHChangeNotification_Lock [SHELL32.644] + */ +HANDLE WINAPI SHChangeNotification_Lock( + HANDLE hChange, + DWORD dwProcessId, + LPITEMIDLIST **lppidls, + LPLONG lpwEventId) +{ + DWORD i; + LPNOTIFICATIONLIST node; + LPCITEMIDLIST *idlist; + + TRACE("%p %08lx %p %p\n", hChange, dwProcessId, lppidls, lpwEventId); + + /* EnterCriticalSection(&SHELL32_ChangenotifyCS); */ + + node = FindNode( hChange ); + if( node ) + { + idlist = SHAlloc( sizeof(LPCITEMIDLIST *) * node->cidl ); + for(i=0; icidl; i++) + idlist[i] = (LPCITEMIDLIST)node->pidlSignaled; + *lpwEventId = node->wSignalledEvent; + *lppidls = (LPITEMIDLIST*)idlist; + node->wSignalledEvent = 0; + } + else + ERR("Couldn't find %p\n", hChange ); + + /* LeaveCriticalSection(&SHELL32_ChangenotifyCS); */ + + return (HANDLE) node; +} + +/************************************************************************* + * SHChangeNotification_Unlock [SHELL32.645] + */ +BOOL WINAPI SHChangeNotification_Unlock ( HANDLE hLock) +{ + TRACE("\n"); + return 1; +} + +/************************************************************************* + * NTSHChangeNotifyDeregister [SHELL32.641] + */ +DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1) +{ + FIXME("(0x%08lx):semi stub.\n",x1); + + return SHChangeNotifyDeregister( x1 ); +} diff --git a/reactos/lib/shell32/classes.c b/reactos/lib/shell32/classes.c index 9c56a5b557f..0e47f6f9fb4 100644 --- a/reactos/lib/shell32/classes.c +++ b/reactos/lib/shell32/classes.c @@ -1,380 +1,380 @@ -/* - * file type mapping - * (HKEY_CLASSES_ROOT - Stuff) - * - * Copyright 1998, 1999, 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include "wine/debug.h" -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "shlobj.h" -#include "shell32_main.h" -#include "shlguid.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -#define MAX_EXTENSION_LENGTH 20 - -BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, DWORD len, BOOL bPrependDot) -{ - HKEY hkey; - WCHAR szTemp[MAX_EXTENSION_LENGTH + 2]; - - TRACE("%s %p\n", debugstr_w(szExtension), debugstr_w(szFileType)); - - /* added because we do not want to have double dots */ - if (szExtension[0] == '.') - bPrependDot = 0; - - if (bPrependDot) - szTemp[0] = '.'; - - lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); - - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey)) - { - return FALSE; - } - - if (RegQueryValueW(hkey, NULL, szFileType, &len)) - { - RegCloseKey(hkey); - return FALSE; - } - - RegCloseKey(hkey); - - TRACE("--UE;\n} %s\n", debugstr_w(szFileType)); - - return TRUE; -} - -BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot) -{ - HKEY hkey; - char szTemp[MAX_EXTENSION_LENGTH + 2]; - - TRACE("%s %p\n", szExtension, szFileType); - - /* added because we do not want to have double dots */ - if (szExtension[0] == '.') - bPrependDot = 0; - - if (bPrependDot) - szTemp[0] = '.'; - - lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); - - if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey)) - { - return FALSE; - } - - if (RegQueryValueA(hkey, NULL, szFileType, &len)) - { - RegCloseKey(hkey); - return FALSE; - } - - RegCloseKey(hkey); - - TRACE("--UE;\n} %s\n", szFileType); - - return TRUE; -} - - -BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) -{ - static const WCHAR swShell[] = {'\\','s','h','e','l','l','\\',0}; - static const WCHAR swCommand[] = {'\\','c','o','m','m','a','n','d',0}; - BOOL ret = FALSE; - - TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest); - - if (szClass) - RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, 0x02000000, &hkeyClass); - - if (hkeyClass) - { - WCHAR sTemp[MAX_PATH]; - lstrcpyW(sTemp, swShell); - lstrcatW(sTemp, szVerb); - lstrcatW(sTemp, swCommand); - - ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); - - if (szClass) - RegCloseKey(hkeyClass); - } - - TRACE("-- %s\n", debugstr_w(szDest) ); - return ret; -} - -/*************************************************************************************** -* HCR_GetDefaultIcon [internal] -* -* Gets the icon for a filetype -*/ -static BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey) -{ - char xriid[50]; - sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - riid->Data1, riid->Data2, riid->Data3, - riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], - riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); - - TRACE("%s\n",xriid ); - - return !RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey); -} - -static BOOL HCR_RegGetDefaultIconW(HKEY hkey, LPWSTR szDest, DWORD len, LPDWORD dwNr) -{ - DWORD dwType; - WCHAR sTemp[MAX_PATH]; - WCHAR sNum[5]; - - if (!RegQueryValueExW(hkey, NULL, 0, &dwType, (LPBYTE)szDest, &len)) - { - if (dwType == REG_EXPAND_SZ) - { - ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH); - lstrcpynW(szDest, sTemp, len); - } - if (ParseFieldW (szDest, 2, sNum, 5)) - *dwNr = atoiW(sNum); - else - *dwNr=0; /* sometimes the icon number is missing */ - ParseFieldW (szDest, 1, szDest, len); - return TRUE; - } - return FALSE; -} - -static BOOL HCR_RegGetDefaultIconA(HKEY hkey, LPSTR szDest, DWORD len, LPDWORD dwNr) -{ - DWORD dwType; - char sTemp[MAX_PATH]; - char sNum[5]; - - if (!RegQueryValueExA(hkey, NULL, 0, &dwType, szDest, &len)) - { - if (dwType == REG_EXPAND_SZ) - { - ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH); - lstrcpynA(szDest, sTemp, len); - } - if (ParseFieldA (szDest, 2, sNum, 5)) - *dwNr=atoi(sNum); - else - *dwNr=0; /* sometimes the icon number is missing */ - ParseFieldA (szDest, 1, szDest, len); - return TRUE; - } - return FALSE; -} - -BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, LPDWORD dwNr) -{ - static const WCHAR swDefaultIcon[] = {'\\','D','e','f','a','u','l','t','I','c','o','n',0}; - HKEY hkey; - WCHAR sTemp[MAX_PATH]; - BOOL ret = FALSE; - - TRACE("%s\n",debugstr_w(szClass) ); - - lstrcpynW(sTemp, szClass, MAX_PATH); - lstrcatW(sTemp, swDefaultIcon); - - if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey)) - { - ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr); - RegCloseKey(hkey); - } - TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr ); - return ret; -} - -BOOL HCR_GetDefaultIconA(LPCSTR szClass, LPSTR szDest, DWORD len, LPDWORD dwNr) -{ - HKEY hkey; - char sTemp[MAX_PATH]; - BOOL ret = FALSE; - - TRACE("%s\n",szClass ); - - sprintf(sTemp, "%s\\DefaultIcon",szClass); - - if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey)) - { - ret = HCR_RegGetDefaultIconA(hkey, szDest, len, dwNr); - RegCloseKey(hkey); - } - TRACE("-- %s %li\n", szDest, *dwNr ); - return ret; -} - -BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, LPDWORD dwNr) -{ - HKEY hkey; - BOOL ret = FALSE; - - if (HCR_RegOpenClassIDKey(riid, &hkey)) - { - ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr); - RegCloseKey(hkey); - } - TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr ); - return ret; -} - -/*************************************************************************************** -* HCR_GetClassName [internal] -* -* Gets the name of a registered class -*/ -static const WCHAR swEmpty[] = {0}; - -BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len) -{ - HKEY hkey; - BOOL ret = FALSE; - DWORD buflen = len; - - szDest[0] = 0; - if (HCR_RegOpenClassIDKey(riid, &hkey)) - { - if (!RegQueryValueExW(hkey, swEmpty, 0, NULL, (LPBYTE)szDest, &len)) - { - ret = TRUE; - } - RegCloseKey(hkey); - } - - if (!ret || !szDest[0]) - { - if(IsEqualIID(riid, &CLSID_ShellDesktop)) - { - if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) - ret = TRUE; - } - else if (IsEqualIID(riid, &CLSID_MyComputer)) - { - if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) - ret = TRUE; - } - } - TRACE("-- %s\n", debugstr_w(szDest)); - return ret; -} - -BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len) -{ HKEY hkey; - BOOL ret = FALSE; - DWORD buflen = len; - - szDest[0] = 0; - if (HCR_RegOpenClassIDKey(riid, &hkey)) - { - if (!RegQueryValueExA(hkey,"",0,NULL,szDest,&len)) - { - ret = TRUE; - } - RegCloseKey(hkey); - } - - if (!ret || !szDest[0]) - { - if(IsEqualIID(riid, &CLSID_ShellDesktop)) - { - if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) - ret = TRUE; - } - else if (IsEqualIID(riid, &CLSID_MyComputer)) - { - if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) - ret = TRUE; - } - } - - TRACE("-- %s\n", szDest); - - return ret; -} - -/*************************************************************************************** -* HCR_GetFolderAttributes [internal] -* -* gets the folder attributes of a class -* -* FIXME -* verify the defaultvalue for *szDest -*/ -BOOL HCR_GetFolderAttributes (REFIID riid, LPDWORD szDest) -{ HKEY hkey; - char xriid[60]; - DWORD attributes; - DWORD len = 4; - - sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - riid->Data1, riid->Data2, riid->Data3, - riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], - riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); - TRACE("%s\n",xriid ); - - if (!szDest) return FALSE; - *szDest = SFGAO_FOLDER|SFGAO_FILESYSTEM; - - strcat (xriid, "\\ShellFolder"); - - if (RegOpenKeyExA(HKEY_CLASSES_ROOT,xriid,0,KEY_READ,&hkey)) - { - return FALSE; - } - - if (RegQueryValueExA(hkey,"Attributes",0,NULL,(LPBYTE)&attributes,&len)) - { - RegCloseKey(hkey); - return FALSE; - } - - RegCloseKey(hkey); - - TRACE("-- 0x%08lx\n", attributes); - - *szDest = attributes; - - return TRUE; -} +/* + * file type mapping + * (HKEY_CLASSES_ROOT - Stuff) + * + * Copyright 1998, 1999, 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include "wine/debug.h" +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "shlobj.h" +#include "shell32_main.h" +#include "shlguid.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +#define MAX_EXTENSION_LENGTH 20 + +BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, DWORD len, BOOL bPrependDot) +{ + HKEY hkey; + WCHAR szTemp[MAX_EXTENSION_LENGTH + 2]; + + TRACE("%s %p\n", debugstr_w(szExtension), debugstr_w(szFileType)); + + /* added because we do not want to have double dots */ + if (szExtension[0] == '.') + bPrependDot = 0; + + if (bPrependDot) + szTemp[0] = '.'; + + lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); + + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey)) + { + return FALSE; + } + + if (RegQueryValueW(hkey, NULL, szFileType, &len)) + { + RegCloseKey(hkey); + return FALSE; + } + + RegCloseKey(hkey); + + TRACE("--UE;\n} %s\n", debugstr_w(szFileType)); + + return TRUE; +} + +BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot) +{ + HKEY hkey; + char szTemp[MAX_EXTENSION_LENGTH + 2]; + + TRACE("%s %p\n", szExtension, szFileType); + + /* added because we do not want to have double dots */ + if (szExtension[0] == '.') + bPrependDot = 0; + + if (bPrependDot) + szTemp[0] = '.'; + + lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); + + if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, 0x02000000, &hkey)) + { + return FALSE; + } + + if (RegQueryValueA(hkey, NULL, szFileType, &len)) + { + RegCloseKey(hkey); + return FALSE; + } + + RegCloseKey(hkey); + + TRACE("--UE;\n} %s\n", szFileType); + + return TRUE; +} + + +BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) +{ + static const WCHAR swShell[] = {'\\','s','h','e','l','l','\\',0}; + static const WCHAR swCommand[] = {'\\','c','o','m','m','a','n','d',0}; + BOOL ret = FALSE; + + TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest); + + if (szClass) + RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, 0x02000000, &hkeyClass); + + if (hkeyClass) + { + WCHAR sTemp[MAX_PATH]; + lstrcpyW(sTemp, swShell); + lstrcatW(sTemp, szVerb); + lstrcatW(sTemp, swCommand); + + ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); + + if (szClass) + RegCloseKey(hkeyClass); + } + + TRACE("-- %s\n", debugstr_w(szDest) ); + return ret; +} + +/*************************************************************************************** +* HCR_GetDefaultIcon [internal] +* +* Gets the icon for a filetype +*/ +static BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey) +{ + char xriid[50]; + sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + riid->Data1, riid->Data2, riid->Data3, + riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], + riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); + + TRACE("%s\n",xriid ); + + return !RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey); +} + +static BOOL HCR_RegGetDefaultIconW(HKEY hkey, LPWSTR szDest, DWORD len, LPDWORD dwNr) +{ + DWORD dwType; + WCHAR sTemp[MAX_PATH]; + WCHAR sNum[5]; + + if (!RegQueryValueExW(hkey, NULL, 0, &dwType, (LPBYTE)szDest, &len)) + { + if (dwType == REG_EXPAND_SZ) + { + ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH); + lstrcpynW(szDest, sTemp, len); + } + if (ParseFieldW (szDest, 2, sNum, 5)) + *dwNr = atoiW(sNum); + else + *dwNr=0; /* sometimes the icon number is missing */ + ParseFieldW (szDest, 1, szDest, len); + return TRUE; + } + return FALSE; +} + +static BOOL HCR_RegGetDefaultIconA(HKEY hkey, LPSTR szDest, DWORD len, LPDWORD dwNr) +{ + DWORD dwType; + char sTemp[MAX_PATH]; + char sNum[5]; + + if (!RegQueryValueExA(hkey, NULL, 0, &dwType, szDest, &len)) + { + if (dwType == REG_EXPAND_SZ) + { + ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH); + lstrcpynA(szDest, sTemp, len); + } + if (ParseFieldA (szDest, 2, sNum, 5)) + *dwNr=atoi(sNum); + else + *dwNr=0; /* sometimes the icon number is missing */ + ParseFieldA (szDest, 1, szDest, len); + return TRUE; + } + return FALSE; +} + +BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, LPDWORD dwNr) +{ + static const WCHAR swDefaultIcon[] = {'\\','D','e','f','a','u','l','t','I','c','o','n',0}; + HKEY hkey; + WCHAR sTemp[MAX_PATH]; + BOOL ret = FALSE; + + TRACE("%s\n",debugstr_w(szClass) ); + + lstrcpynW(sTemp, szClass, MAX_PATH); + lstrcatW(sTemp, swDefaultIcon); + + if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey)) + { + ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr); + RegCloseKey(hkey); + } + TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr ); + return ret; +} + +BOOL HCR_GetDefaultIconA(LPCSTR szClass, LPSTR szDest, DWORD len, LPDWORD dwNr) +{ + HKEY hkey; + char sTemp[MAX_PATH]; + BOOL ret = FALSE; + + TRACE("%s\n",szClass ); + + sprintf(sTemp, "%s\\DefaultIcon",szClass); + + if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, 0x02000000, &hkey)) + { + ret = HCR_RegGetDefaultIconA(hkey, szDest, len, dwNr); + RegCloseKey(hkey); + } + TRACE("-- %s %li\n", szDest, *dwNr ); + return ret; +} + +BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, LPDWORD dwNr) +{ + HKEY hkey; + BOOL ret = FALSE; + + if (HCR_RegOpenClassIDKey(riid, &hkey)) + { + ret = HCR_RegGetDefaultIconW(hkey, szDest, len, dwNr); + RegCloseKey(hkey); + } + TRACE("-- %s %li\n", debugstr_w(szDest), *dwNr ); + return ret; +} + +/*************************************************************************************** +* HCR_GetClassName [internal] +* +* Gets the name of a registered class +*/ +static const WCHAR swEmpty[] = {0}; + +BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len) +{ + HKEY hkey; + BOOL ret = FALSE; + DWORD buflen = len; + + szDest[0] = 0; + if (HCR_RegOpenClassIDKey(riid, &hkey)) + { + if (!RegQueryValueExW(hkey, swEmpty, 0, NULL, (LPBYTE)szDest, &len)) + { + ret = TRUE; + } + RegCloseKey(hkey); + } + + if (!ret || !szDest[0]) + { + if(IsEqualIID(riid, &CLSID_ShellDesktop)) + { + if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) + ret = TRUE; + } + else if (IsEqualIID(riid, &CLSID_MyComputer)) + { + if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) + ret = TRUE; + } + } + TRACE("-- %s\n", debugstr_w(szDest)); + return ret; +} + +BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len) +{ HKEY hkey; + BOOL ret = FALSE; + DWORD buflen = len; + + szDest[0] = 0; + if (HCR_RegOpenClassIDKey(riid, &hkey)) + { + if (!RegQueryValueExA(hkey,"",0,NULL,szDest,&len)) + { + ret = TRUE; + } + RegCloseKey(hkey); + } + + if (!ret || !szDest[0]) + { + if(IsEqualIID(riid, &CLSID_ShellDesktop)) + { + if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) + ret = TRUE; + } + else if (IsEqualIID(riid, &CLSID_MyComputer)) + { + if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) + ret = TRUE; + } + } + + TRACE("-- %s\n", szDest); + + return ret; +} + +/*************************************************************************************** +* HCR_GetFolderAttributes [internal] +* +* gets the folder attributes of a class +* +* FIXME +* verify the defaultvalue for *szDest +*/ +BOOL HCR_GetFolderAttributes (REFIID riid, LPDWORD szDest) +{ HKEY hkey; + char xriid[60]; + DWORD attributes; + DWORD len = 4; + + sprintf( xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + riid->Data1, riid->Data2, riid->Data3, + riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], + riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); + TRACE("%s\n",xriid ); + + if (!szDest) return FALSE; + *szDest = SFGAO_FOLDER|SFGAO_FILESYSTEM; + + strcat (xriid, "\\ShellFolder"); + + if (RegOpenKeyExA(HKEY_CLASSES_ROOT,xriid,0,KEY_READ,&hkey)) + { + return FALSE; + } + + if (RegQueryValueExA(hkey,"Attributes",0,NULL,(LPBYTE)&attributes,&len)) + { + RegCloseKey(hkey); + return FALSE; + } + + RegCloseKey(hkey); + + TRACE("-- 0x%08lx\n", attributes); + + *szDest = attributes; + + return TRUE; +} diff --git a/reactos/lib/shell32/clipboard.c b/reactos/lib/shell32/clipboard.c index fe0d1bd20d7..71c929365b9 100644 --- a/reactos/lib/shell32/clipboard.c +++ b/reactos/lib/shell32/clipboard.c @@ -1,270 +1,270 @@ -/* - * clipboard helper functions - * - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES: - * - * For copy & paste functions within contextmenus does the shell use - * the OLE clipboard functions in combination with dataobjects. - * The OLE32.DLL gets loaded with LoadLibrary - * - * - a right mousebutton-copy sets the following formats: - * classic: - * Shell IDList Array - * Prefered Drop Effect - * Shell Object Offsets - * HDROP - * FileName - * ole: - * OlePrivateData (ClipboardDataObjectInterface) - * - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "pidl.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shlwapi.h" - -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************************************************************** - * RenderHDROP - * - * creates a CF_HDROP structure - */ -HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - UINT i; - int rootsize = 0,size = 0; - char szRootPath[MAX_PATH]; - char szFileName[MAX_PATH]; - HGLOBAL hGlobal; - DROPFILES *pDropFiles; - int offset; - - TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); - - /* get the size needed */ - size = sizeof(DROPFILES); - - SHGetPathFromIDListA(pidlRoot, szRootPath); - PathAddBackslashA(szRootPath); - rootsize = strlen(szRootPath); - - for (i=0; ipFiles = sizeof(DROPFILES); - pDropFiles->fWide = FALSE; - - offset = pDropFiles->pFiles; - strcpy(szFileName, szRootPath); - - for (i=0; icidl = cidl; - - /* root pidl */ - offset = sizeof(CIDA) + sizeof (UINT)*(cidl); - pcida->aoffset[0] = offset; /* first element */ - sizePidl = ILGetSize (pidlRoot); - memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl); - offset += sizePidl; - - for(i=0; iaoffset[i+1] = offset; - sizePidl = ILGetSize(apidl[i]); - memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl); - offset += sizePidl; - } - - GlobalUnlock(hGlobal); - return hGlobal; -} - -HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - FIXME("\n"); - return 0; -} - -HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - FIXME("\n"); - return 0; -} - -HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - FIXME("\n"); - return 0; -} - -HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - int size = 0; - char szTemp[MAX_PATH], *szFileName; - LPITEMIDLIST pidl; - HGLOBAL hGlobal; - HRESULT hr; - - TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); - - /* get path of combined pidl */ - pidl = ILCombine(pidlRoot, apidl[0]); - if (!pidl) - return 0; - - hr = SHELL_GetPathFromIDListA(pidl, szTemp, MAX_PATH); - SHFree(pidl); - if (FAILED(hr)) - return 0; - - size = strlen(szTemp) + 1; - - /* fill the structure */ - hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size); - if(!hGlobal) return hGlobal; - szFileName = (char *)GlobalLock(hGlobal); - memcpy(szFileName, szTemp, size); - GlobalUnlock(hGlobal); - - return hGlobal; -} - -HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) -{ - int size = 0; - WCHAR szTemp[MAX_PATH], *szFileName; - LPITEMIDLIST pidl; - HGLOBAL hGlobal; - HRESULT hr; - - TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); - - /* get path of combined pidl */ - pidl = ILCombine(pidlRoot, apidl[0]); - if (!pidl) - return 0; - - hr = SHELL_GetPathFromIDListW(pidl, szTemp, MAX_PATH); - SHFree(pidl); - if (FAILED(hr)) - return 0; - - size = (strlenW(szTemp)+1) * sizeof(WCHAR); - - /* fill the structure */ - hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size); - if(!hGlobal) return hGlobal; - szFileName = (WCHAR *)GlobalLock(hGlobal); - memcpy(szFileName, szTemp, size); - GlobalUnlock(hGlobal); - - return hGlobal; -} - -HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags) -{ - DWORD * pdwFlag; - HGLOBAL hGlobal; - - TRACE("(0x%08lx)\n", dwFlags); - - hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD)); - if(!hGlobal) return hGlobal; - pdwFlag = (DWORD*)GlobalLock(hGlobal); - *pdwFlag = dwFlags; - GlobalUnlock(hGlobal); - return hGlobal; -} - -/************************************************************************** - * IsDataInClipboard - * - * checks if there is something in the clipboard we can use - */ -BOOL IsDataInClipboard (HWND hwnd) -{ - BOOL ret = FALSE; - - if (OpenClipboard(hwnd)) - { - if (GetOpenClipboardWindow()) - { - ret = IsClipboardFormatAvailable(CF_TEXT); - } - CloseClipboard(); - } - return ret; -} +/* + * clipboard helper functions + * + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES: + * + * For copy & paste functions within contextmenus does the shell use + * the OLE clipboard functions in combination with dataobjects. + * The OLE32.DLL gets loaded with LoadLibrary + * + * - a right mousebutton-copy sets the following formats: + * classic: + * Shell IDList Array + * Prefered Drop Effect + * Shell Object Offsets + * HDROP + * FileName + * ole: + * OlePrivateData (ClipboardDataObjectInterface) + * + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shlwapi.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/************************************************************************** + * RenderHDROP + * + * creates a CF_HDROP structure + */ +HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + UINT i; + int rootsize = 0,size = 0; + char szRootPath[MAX_PATH]; + char szFileName[MAX_PATH]; + HGLOBAL hGlobal; + DROPFILES *pDropFiles; + int offset; + + TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); + + /* get the size needed */ + size = sizeof(DROPFILES); + + SHGetPathFromIDListA(pidlRoot, szRootPath); + PathAddBackslashA(szRootPath); + rootsize = strlen(szRootPath); + + for (i=0; ipFiles = sizeof(DROPFILES); + pDropFiles->fWide = FALSE; + + offset = pDropFiles->pFiles; + strcpy(szFileName, szRootPath); + + for (i=0; icidl = cidl; + + /* root pidl */ + offset = sizeof(CIDA) + sizeof (UINT)*(cidl); + pcida->aoffset[0] = offset; /* first element */ + sizePidl = ILGetSize (pidlRoot); + memcpy(((LPBYTE)pcida)+offset, pidlRoot, sizePidl); + offset += sizePidl; + + for(i=0; iaoffset[i+1] = offset; + sizePidl = ILGetSize(apidl[i]); + memcpy(((LPBYTE)pcida)+offset, apidl[i], sizePidl); + offset += sizePidl; + } + + GlobalUnlock(hGlobal); + return hGlobal; +} + +HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + FIXME("\n"); + return 0; +} + +HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + FIXME("\n"); + return 0; +} + +HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + FIXME("\n"); + return 0; +} + +HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + int size = 0; + char szTemp[MAX_PATH], *szFileName; + LPITEMIDLIST pidl; + HGLOBAL hGlobal; + HRESULT hr; + + TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); + + /* get path of combined pidl */ + pidl = ILCombine(pidlRoot, apidl[0]); + if (!pidl) + return 0; + + hr = SHELL_GetPathFromIDListA(pidl, szTemp, MAX_PATH); + SHFree(pidl); + if (FAILED(hr)) + return 0; + + size = strlen(szTemp) + 1; + + /* fill the structure */ + hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size); + if(!hGlobal) return hGlobal; + szFileName = (char *)GlobalLock(hGlobal); + memcpy(szFileName, szTemp, size); + GlobalUnlock(hGlobal); + + return hGlobal; +} + +HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) +{ + int size = 0; + WCHAR szTemp[MAX_PATH], *szFileName; + LPITEMIDLIST pidl; + HGLOBAL hGlobal; + HRESULT hr; + + TRACE("(%p,%p,%u)\n", pidlRoot, apidl, cidl); + + /* get path of combined pidl */ + pidl = ILCombine(pidlRoot, apidl[0]); + if (!pidl) + return 0; + + hr = SHELL_GetPathFromIDListW(pidl, szTemp, MAX_PATH); + SHFree(pidl); + if (FAILED(hr)) + return 0; + + size = (strlenW(szTemp)+1) * sizeof(WCHAR); + + /* fill the structure */ + hGlobal = GlobalAlloc(GHND|GMEM_SHARE, size); + if(!hGlobal) return hGlobal; + szFileName = (WCHAR *)GlobalLock(hGlobal); + memcpy(szFileName, szTemp, size); + GlobalUnlock(hGlobal); + + return hGlobal; +} + +HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags) +{ + DWORD * pdwFlag; + HGLOBAL hGlobal; + + TRACE("(0x%08lx)\n", dwFlags); + + hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD)); + if(!hGlobal) return hGlobal; + pdwFlag = (DWORD*)GlobalLock(hGlobal); + *pdwFlag = dwFlags; + GlobalUnlock(hGlobal); + return hGlobal; +} + +/************************************************************************** + * IsDataInClipboard + * + * checks if there is something in the clipboard we can use + */ +BOOL IsDataInClipboard (HWND hwnd) +{ + BOOL ret = FALSE; + + if (OpenClipboard(hwnd)) + { + if (GetOpenClipboardWindow()) + { + ret = IsClipboardFormatAvailable(CF_TEXT); + } + CloseClipboard(); + } + return ret; +} diff --git a/reactos/lib/shell32/control.c b/reactos/lib/shell32/control.c index 3d331d2185b..f0a07167e0f 100644 --- a/reactos/lib/shell32/control.c +++ b/reactos/lib/shell32/control.c @@ -1,499 +1,499 @@ -/* Control Panel management - * - * Copyright 2001 Eric Pouech - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "wine/winbase16.h" -#include "wownt32.h" -#include "wine/debug.h" -#include "cpl.h" -#include "wine/unicode.h" - -#define NO_SHLWAPI_REG -#include "shlwapi.h" - -#include "cpanel.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shlctrl); - -CPlApplet* Control_UnloadApplet(CPlApplet* applet) -{ - unsigned i; - CPlApplet* next; - - for (i = 0; i < applet->count; i++) { - if (!applet->info[i].dwSize) continue; - applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData); - } - if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L); - FreeLibrary(applet->hModule); - next = applet->next; - HeapFree(GetProcessHeap(), 0, applet); - return next; -} - -CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) -{ - CPlApplet* applet; - unsigned i; - CPLINFO info; - NEWCPLINFOW newinfo; - - if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) - return applet; - - applet->hWnd = hWnd; - - if (!(applet->hModule = LoadLibraryW(cmd))) { - WARN("Cannot load control panel applet %s\n", debugstr_w(cmd)); - goto theError; - } - if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) { - WARN("Not a valid control panel applet %s\n", debugstr_w(cmd)); - goto theError; - } - if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) { - WARN("Init of applet has failed\n"); - goto theError; - } - if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) { - WARN("No subprogram in applet\n"); - goto theError; - } - - applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet, - sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW)); - - for (i = 0; i < applet->count; i++) { - ZeroMemory(&newinfo, sizeof(newinfo)); - newinfo.dwSize = sizeof(NEWCPLINFOA); - applet->info[i].dwSize = sizeof(NEWCPLINFOW); - /* proc is supposed to return a null value upon success for - * CPL_INQUIRE and CPL_NEWINQUIRE - * However, real drivers don't seem to behave like this - * So, use introspection rather than return value - */ - applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo); - if (newinfo.hIcon == 0) { - applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info); - if (info.idIcon == 0 || info.idName == 0) { - WARN("Couldn't get info from sp %u\n", i); - applet->info[i].dwSize = 0; - } else { - /* convert the old data into the new structure */ - applet->info[i].dwFlags = 0; - applet->info[i].dwHelpContext = 0; - applet->info[i].lData = info.lData; - applet->info[i].hIcon = LoadIconW(applet->hModule, - MAKEINTRESOURCEW(info.idIcon)); - LoadStringW(applet->hModule, info.idName, - applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR)); - LoadStringW(applet->hModule, info.idInfo, - applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); - applet->info[i].szHelpFile[0] = '\0'; - } - } - else - { - CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize); - if (newinfo.dwSize != sizeof(NEWCPLINFOW)) - { - applet->info[i].dwSize = sizeof(NEWCPLINFOW); - MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szName, - sizeof(((LPNEWCPLINFOA)&newinfo)->szName) / sizeof(CHAR), - applet->info[i].szName, - sizeof(applet->info[i].szName) / sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szInfo, - sizeof(((LPNEWCPLINFOA)&newinfo)->szInfo) / sizeof(CHAR), - applet->info[i].szInfo, - sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szHelpFile, - sizeof(((LPNEWCPLINFOA)&newinfo)->szHelpFile) / sizeof(CHAR), - applet->info[i].szHelpFile, - sizeof(applet->info[i].szHelpFile) / sizeof(WCHAR)); - } - } - } - - applet->next = panel->first; - panel->first = applet; - - return applet; - - theError: - Control_UnloadApplet(applet); - return NULL; -} - -static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTA* cs) -{ - CPanel* panel = (CPanel*)cs->lpCreateParams; - - SetWindowLongA(hWnd, 0, (LPARAM)panel); - panel->status = 0; - panel->hWnd = hWnd; -} - -#define XICON 32 -#define XSTEP 128 -#define YICON 32 -#define YSTEP 64 - -static BOOL Control_Localize(const CPanel* panel, unsigned cx, unsigned cy, - CPlApplet** papplet, unsigned* psp) -{ - unsigned i, x = (XSTEP-XICON)/2, y = 0; - CPlApplet* applet; - RECT rc; - - GetClientRect(panel->hWnd, &rc); - for (applet = panel->first; applet; applet = applet->next) { - for (i = 0; i < applet->count; i++) { - if (!applet->info[i].dwSize) continue; - if (x + XSTEP >= rc.right - rc.left) { - x = (XSTEP-XICON)/2; - y += YSTEP; - } - if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) { - *papplet = applet; - *psp = i; - return TRUE; - } - x += XSTEP; - } - } - return FALSE; -} - -static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam) -{ - HDC hdc; - PAINTSTRUCT ps; - RECT rc, txtRect; - unsigned i, x = 0, y = 0; - CPlApplet* applet; - HGDIOBJ hOldFont; - - hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps); - hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT)); - GetClientRect(panel->hWnd, &rc); - for (applet = panel->first; applet; applet = applet->next) { - for (i = 0; i < applet->count; i++) { - if (x + XSTEP >= rc.right - rc.left) { - x = 0; - y += YSTEP; - } - if (!applet->info[i].dwSize) continue; - DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon); - txtRect.left = x; - txtRect.right = x + XSTEP; - txtRect.top = y + YICON; - txtRect.bottom = y + YSTEP; - DrawTextW(hdc, applet->info[i].szName, -1, &txtRect, - DT_CENTER | DT_VCENTER); - x += XSTEP; - } - } - SelectObject(hdc, hOldFont); - if (!wParam) EndPaint(panel->hWnd, &ps); - return 0; -} - -static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up) -{ - unsigned i; - CPlApplet* applet; - - if (Control_Localize(panel, LOWORD(lParam), HIWORD(lParam), &applet, &i)) { - if (up) { - if (panel->clkApplet == applet && panel->clkSP == i) { - applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData); - } - } else { - panel->clkApplet = applet; - panel->clkSP = i; - } - } - return 0; -} - -static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, - WPARAM lParam1, LPARAM lParam2) -{ - CPanel* panel = (CPanel*)GetWindowLongA(hWnd, 0); - - if (panel || wMsg == WM_CREATE) { - switch (wMsg) { - case WM_CREATE: - Control_WndProc_Create(hWnd, (CREATESTRUCTA*)lParam2); - return 0; - case WM_DESTROY: - { - CPlApplet* applet = panel->first; - while (applet) - applet = Control_UnloadApplet(applet); - } - PostQuitMessage(0); - break; - case WM_PAINT: - return Control_WndProc_Paint(panel, lParam1); - case WM_LBUTTONUP: - return Control_WndProc_LButton(panel, lParam2, TRUE); - case WM_LBUTTONDOWN: - return Control_WndProc_LButton(panel, lParam2, FALSE); -/* EPP case WM_COMMAND: */ -/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */ - } - } - - return DefWindowProcA(hWnd, wMsg, lParam1, lParam2); -} - -static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst) -{ - WNDCLASSA wc; - MSG msg; - const CHAR* appName = "Wine Control Panel"; - wc.style = CS_HREDRAW|CS_VREDRAW; - wc.lpfnWndProc = Control_WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = sizeof(CPlApplet*); - wc.hInstance = hInst; - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = GetStockObject(WHITE_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = "Shell_Control_WndClass"; - - if (!RegisterClassA(&wc)) return; - - CreateWindowExA(0, wc.lpszClassName, appName, - WS_OVERLAPPEDWINDOW | WS_VISIBLE, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hWnd, NULL, hInst, panel); - if (!panel->hWnd) return; - - if (!panel->first) { - /* FIXME appName & message should be localized */ - MessageBoxA(panel->hWnd, "Cannot load any applets", appName, MB_OK); - return; - } - - while (GetMessageA(&msg, panel->hWnd, 0, 0)) { - TranslateMessage(&msg); - DispatchMessageA(&msg); - } -} - -static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst) -{ - HANDLE h; - WIN32_FIND_DATAW fd; - WCHAR buffer[MAX_PATH]; - static const WCHAR wszAllCpl[] = {'*','.','c','p','l',0}; - WCHAR *p; - - GetSystemDirectoryW( buffer, MAX_PATH ); - p = buffer + strlenW(buffer); - *p++ = '\\'; - lstrcpyW(p, wszAllCpl); - - if ((h = FindFirstFileW(buffer, &fd)) != INVALID_HANDLE_VALUE) { - do { - lstrcpyW(p, fd.cFileName); - Control_LoadApplet(hWnd, buffer, panel); - } while (FindNextFileW(h, &fd)); - FindClose(h); - } - - Control_DoInterface(panel, hWnd, hInst); -} - -static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) - /* forms to parse: - * foo.cpl,@sp,str - * foo.cpl,@sp - * foo.cpl,,str - * foo.cpl @sp - * foo.cpl str - * "a path\foo.cpl" - */ -{ - LPWSTR buffer; - LPWSTR beg = NULL; - LPWSTR end; - WCHAR ch; - LPWSTR ptr; - unsigned sp = 0; - LPWSTR extraPmts = NULL; - int quoted = 0; - - buffer = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(wszCmd) + 1) * sizeof(*wszCmd)); - if (!buffer) return; - - end = lstrcpyW(buffer, wszCmd); - - for (;;) { - ch = *end; - if (ch == '"') quoted = !quoted; - if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { - *end = '\0'; - if (beg) { - if (*beg == '@') { - sp = atoiW(beg + 1); - } else if (*beg == '\0') { - sp = 0; - } else { - extraPmts = beg; - } - } - if (ch == '\0') break; - beg = end + 1; - if (ch == ' ') while (end[1] == ' ') end++; - } - end++; - } - while ((ptr = StrChrW(buffer, '"'))) - memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR)); - - TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp); - - Control_LoadApplet(hWnd, buffer, panel); - - if (panel->first) { - CPlApplet* applet = panel->first; - - assert(applet && applet->next == NULL); - if (sp >= applet->count) { - WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count); - sp = 0; - } - if (applet->info[sp].dwSize) { - if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts)) - applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData); - } - Control_UnloadApplet(applet); - } - HeapFree(GetProcessHeap(), 0, buffer); -} - -/************************************************************************* - * Control_RunDLLW [SHELL32.@] - * - */ -void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) -{ - CPanel panel; - - TRACE("(%p, %p, %s, 0x%08lx)\n", - hWnd, hInst, debugstr_w(cmd), nCmdShow); - - memset(&panel, 0, sizeof(panel)); - - if (!cmd || !*cmd) { - Control_DoWindow(&panel, hWnd, hInst); - } else { - Control_DoLaunch(&panel, hWnd, cmd); - } -} - -/************************************************************************* - * Control_RunDLLA [SHELL32.@] - * - */ -void WINAPI Control_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) -{ - DWORD len = MultiByteToWideChar(CP_ACP, 0, cmd, -1, NULL, 0 ); - LPWSTR wszCmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (wszCmd && MultiByteToWideChar(CP_ACP, 0, cmd, -1, wszCmd, len )) - { - Control_RunDLLW(hWnd, hInst, wszCmd, nCmdShow); - } - HeapFree(GetProcessHeap(), 0, wszCmd); -} - -/************************************************************************* - * Control_FillCache_RunDLLW [SHELL32.@] - * - */ -HRESULT WINAPI Control_FillCache_RunDLLW(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) -{ - FIXME("%p %p 0x%08lx 0x%08lx stub\n", hWnd, hModule, w, x); - return 0; -} - -/************************************************************************* - * Control_FillCache_RunDLLA [SHELL32.@] - * - */ -HRESULT WINAPI Control_FillCache_RunDLLA(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) -{ - return Control_FillCache_RunDLLW(hWnd, hModule, w, x); -} - - -/************************************************************************* - * RunDLL_CallEntry16 [SHELL32.122] - * the name is probably wrong - */ -void WINAPI RunDLL_CallEntry16( DWORD proc, HWND hwnd, HINSTANCE inst, - LPCSTR cmdline, INT cmdshow ) -{ -#if !defined(__CYGWIN__) && !defined (__MINGW32__) && !defined(_MSC_VER) - WORD args[5]; - SEGPTR cmdline_seg; - - TRACE( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n", - proc, hwnd, inst, debugstr_a(cmdline), cmdshow ); - - cmdline_seg = MapLS( cmdline ); - args[4] = HWND_16(hwnd); - args[3] = MapHModuleLS(inst); - args[2] = SELECTOROF(cmdline_seg); - args[1] = OFFSETOF(cmdline_seg); - args[0] = cmdshow; - WOWCallback16Ex( proc, WCB16_PASCAL, sizeof(args), args, NULL ); - UnMapLS( cmdline_seg ); -#else - FIXME( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n", - proc, hwnd, inst, debugstr_a(cmdline), cmdshow ); -#endif -} - -/************************************************************************* - * CallCPLEntry16 [SHELL32.166] - * - * called by desk.cpl on "Advanced" with: - * hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0 - * - */ -DWORD WINAPI CallCPLEntry16(HMODULE hMod, FARPROC pFunc, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6) -{ - FIXME("(%p, %p, %08lx, %08lx, %08lx, %08lx): stub.\n", hMod, pFunc, dw3, dw4, dw5, dw6); - return 0x0deadbee; -} +/* Control Panel management + * + * Copyright 2001 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "wine/winbase16.h" +#include "wownt32.h" +#include "wine/debug.h" +#include "cpl.h" +#include "wine/unicode.h" + +#define NO_SHLWAPI_REG +#include "shlwapi.h" + +#include "cpanel.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shlctrl); + +CPlApplet* Control_UnloadApplet(CPlApplet* applet) +{ + unsigned i; + CPlApplet* next; + + for (i = 0; i < applet->count; i++) { + if (!applet->info[i].dwSize) continue; + applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData); + } + if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L); + FreeLibrary(applet->hModule); + next = applet->next; + HeapFree(GetProcessHeap(), 0, applet); + return next; +} + +CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) +{ + CPlApplet* applet; + unsigned i; + CPLINFO info; + NEWCPLINFOW newinfo; + + if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) + return applet; + + applet->hWnd = hWnd; + + if (!(applet->hModule = LoadLibraryW(cmd))) { + WARN("Cannot load control panel applet %s\n", debugstr_w(cmd)); + goto theError; + } + if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) { + WARN("Not a valid control panel applet %s\n", debugstr_w(cmd)); + goto theError; + } + if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) { + WARN("Init of applet has failed\n"); + goto theError; + } + if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) { + WARN("No subprogram in applet\n"); + goto theError; + } + + applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet, + sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW)); + + for (i = 0; i < applet->count; i++) { + ZeroMemory(&newinfo, sizeof(newinfo)); + newinfo.dwSize = sizeof(NEWCPLINFOA); + applet->info[i].dwSize = sizeof(NEWCPLINFOW); + /* proc is supposed to return a null value upon success for + * CPL_INQUIRE and CPL_NEWINQUIRE + * However, real drivers don't seem to behave like this + * So, use introspection rather than return value + */ + applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo); + if (newinfo.hIcon == 0) { + applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info); + if (info.idIcon == 0 || info.idName == 0) { + WARN("Couldn't get info from sp %u\n", i); + applet->info[i].dwSize = 0; + } else { + /* convert the old data into the new structure */ + applet->info[i].dwFlags = 0; + applet->info[i].dwHelpContext = 0; + applet->info[i].lData = info.lData; + applet->info[i].hIcon = LoadIconW(applet->hModule, + MAKEINTRESOURCEW(info.idIcon)); + LoadStringW(applet->hModule, info.idName, + applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR)); + LoadStringW(applet->hModule, info.idInfo, + applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); + applet->info[i].szHelpFile[0] = '\0'; + } + } + else + { + CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize); + if (newinfo.dwSize != sizeof(NEWCPLINFOW)) + { + applet->info[i].dwSize = sizeof(NEWCPLINFOW); + MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szName, + sizeof(((LPNEWCPLINFOA)&newinfo)->szName) / sizeof(CHAR), + applet->info[i].szName, + sizeof(applet->info[i].szName) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szInfo, + sizeof(((LPNEWCPLINFOA)&newinfo)->szInfo) / sizeof(CHAR), + applet->info[i].szInfo, + sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ((LPNEWCPLINFOA)&newinfo)->szHelpFile, + sizeof(((LPNEWCPLINFOA)&newinfo)->szHelpFile) / sizeof(CHAR), + applet->info[i].szHelpFile, + sizeof(applet->info[i].szHelpFile) / sizeof(WCHAR)); + } + } + } + + applet->next = panel->first; + panel->first = applet; + + return applet; + + theError: + Control_UnloadApplet(applet); + return NULL; +} + +static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTA* cs) +{ + CPanel* panel = (CPanel*)cs->lpCreateParams; + + SetWindowLongA(hWnd, 0, (LPARAM)panel); + panel->status = 0; + panel->hWnd = hWnd; +} + +#define XICON 32 +#define XSTEP 128 +#define YICON 32 +#define YSTEP 64 + +static BOOL Control_Localize(const CPanel* panel, unsigned cx, unsigned cy, + CPlApplet** papplet, unsigned* psp) +{ + unsigned i, x = (XSTEP-XICON)/2, y = 0; + CPlApplet* applet; + RECT rc; + + GetClientRect(panel->hWnd, &rc); + for (applet = panel->first; applet; applet = applet->next) { + for (i = 0; i < applet->count; i++) { + if (!applet->info[i].dwSize) continue; + if (x + XSTEP >= rc.right - rc.left) { + x = (XSTEP-XICON)/2; + y += YSTEP; + } + if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) { + *papplet = applet; + *psp = i; + return TRUE; + } + x += XSTEP; + } + } + return FALSE; +} + +static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam) +{ + HDC hdc; + PAINTSTRUCT ps; + RECT rc, txtRect; + unsigned i, x = 0, y = 0; + CPlApplet* applet; + HGDIOBJ hOldFont; + + hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps); + hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT)); + GetClientRect(panel->hWnd, &rc); + for (applet = panel->first; applet; applet = applet->next) { + for (i = 0; i < applet->count; i++) { + if (x + XSTEP >= rc.right - rc.left) { + x = 0; + y += YSTEP; + } + if (!applet->info[i].dwSize) continue; + DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon); + txtRect.left = x; + txtRect.right = x + XSTEP; + txtRect.top = y + YICON; + txtRect.bottom = y + YSTEP; + DrawTextW(hdc, applet->info[i].szName, -1, &txtRect, + DT_CENTER | DT_VCENTER); + x += XSTEP; + } + } + SelectObject(hdc, hOldFont); + if (!wParam) EndPaint(panel->hWnd, &ps); + return 0; +} + +static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up) +{ + unsigned i; + CPlApplet* applet; + + if (Control_Localize(panel, LOWORD(lParam), HIWORD(lParam), &applet, &i)) { + if (up) { + if (panel->clkApplet == applet && panel->clkSP == i) { + applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData); + } + } else { + panel->clkApplet = applet; + panel->clkSP = i; + } + } + return 0; +} + +static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, + WPARAM lParam1, LPARAM lParam2) +{ + CPanel* panel = (CPanel*)GetWindowLongA(hWnd, 0); + + if (panel || wMsg == WM_CREATE) { + switch (wMsg) { + case WM_CREATE: + Control_WndProc_Create(hWnd, (CREATESTRUCTA*)lParam2); + return 0; + case WM_DESTROY: + { + CPlApplet* applet = panel->first; + while (applet) + applet = Control_UnloadApplet(applet); + } + PostQuitMessage(0); + break; + case WM_PAINT: + return Control_WndProc_Paint(panel, lParam1); + case WM_LBUTTONUP: + return Control_WndProc_LButton(panel, lParam2, TRUE); + case WM_LBUTTONDOWN: + return Control_WndProc_LButton(panel, lParam2, FALSE); +/* EPP case WM_COMMAND: */ +/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */ + } + } + + return DefWindowProcA(hWnd, wMsg, lParam1, lParam2); +} + +static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst) +{ + WNDCLASSA wc; + MSG msg; + const CHAR* appName = "Wine Control Panel"; + wc.style = CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = Control_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(CPlApplet*); + wc.hInstance = hInst; + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = "Shell_Control_WndClass"; + + if (!RegisterClassA(&wc)) return; + + CreateWindowExA(0, wc.lpszClassName, appName, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hWnd, NULL, hInst, panel); + if (!panel->hWnd) return; + + if (!panel->first) { + /* FIXME appName & message should be localized */ + MessageBoxA(panel->hWnd, "Cannot load any applets", appName, MB_OK); + return; + } + + while (GetMessageA(&msg, panel->hWnd, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } +} + +static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst) +{ + HANDLE h; + WIN32_FIND_DATAW fd; + WCHAR buffer[MAX_PATH]; + static const WCHAR wszAllCpl[] = {'*','.','c','p','l',0}; + WCHAR *p; + + GetSystemDirectoryW( buffer, MAX_PATH ); + p = buffer + strlenW(buffer); + *p++ = '\\'; + lstrcpyW(p, wszAllCpl); + + if ((h = FindFirstFileW(buffer, &fd)) != INVALID_HANDLE_VALUE) { + do { + lstrcpyW(p, fd.cFileName); + Control_LoadApplet(hWnd, buffer, panel); + } while (FindNextFileW(h, &fd)); + FindClose(h); + } + + Control_DoInterface(panel, hWnd, hInst); +} + +static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) + /* forms to parse: + * foo.cpl,@sp,str + * foo.cpl,@sp + * foo.cpl,,str + * foo.cpl @sp + * foo.cpl str + * "a path\foo.cpl" + */ +{ + LPWSTR buffer; + LPWSTR beg = NULL; + LPWSTR end; + WCHAR ch; + LPWSTR ptr; + unsigned sp = 0; + LPWSTR extraPmts = NULL; + int quoted = 0; + + buffer = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(wszCmd) + 1) * sizeof(*wszCmd)); + if (!buffer) return; + + end = lstrcpyW(buffer, wszCmd); + + for (;;) { + ch = *end; + if (ch == '"') quoted = !quoted; + if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { + *end = '\0'; + if (beg) { + if (*beg == '@') { + sp = atoiW(beg + 1); + } else if (*beg == '\0') { + sp = 0; + } else { + extraPmts = beg; + } + } + if (ch == '\0') break; + beg = end + 1; + if (ch == ' ') while (end[1] == ' ') end++; + } + end++; + } + while ((ptr = StrChrW(buffer, '"'))) + memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR)); + + TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp); + + Control_LoadApplet(hWnd, buffer, panel); + + if (panel->first) { + CPlApplet* applet = panel->first; + + assert(applet && applet->next == NULL); + if (sp >= applet->count) { + WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count); + sp = 0; + } + if (applet->info[sp].dwSize) { + if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts)) + applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData); + } + Control_UnloadApplet(applet); + } + HeapFree(GetProcessHeap(), 0, buffer); +} + +/************************************************************************* + * Control_RunDLLW [SHELL32.@] + * + */ +void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) +{ + CPanel panel; + + TRACE("(%p, %p, %s, 0x%08lx)\n", + hWnd, hInst, debugstr_w(cmd), nCmdShow); + + memset(&panel, 0, sizeof(panel)); + + if (!cmd || !*cmd) { + Control_DoWindow(&panel, hWnd, hInst); + } else { + Control_DoLaunch(&panel, hWnd, cmd); + } +} + +/************************************************************************* + * Control_RunDLLA [SHELL32.@] + * + */ +void WINAPI Control_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) +{ + DWORD len = MultiByteToWideChar(CP_ACP, 0, cmd, -1, NULL, 0 ); + LPWSTR wszCmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (wszCmd && MultiByteToWideChar(CP_ACP, 0, cmd, -1, wszCmd, len )) + { + Control_RunDLLW(hWnd, hInst, wszCmd, nCmdShow); + } + HeapFree(GetProcessHeap(), 0, wszCmd); +} + +/************************************************************************* + * Control_FillCache_RunDLLW [SHELL32.@] + * + */ +HRESULT WINAPI Control_FillCache_RunDLLW(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +{ + FIXME("%p %p 0x%08lx 0x%08lx stub\n", hWnd, hModule, w, x); + return 0; +} + +/************************************************************************* + * Control_FillCache_RunDLLA [SHELL32.@] + * + */ +HRESULT WINAPI Control_FillCache_RunDLLA(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +{ + return Control_FillCache_RunDLLW(hWnd, hModule, w, x); +} + + +/************************************************************************* + * RunDLL_CallEntry16 [SHELL32.122] + * the name is probably wrong + */ +void WINAPI RunDLL_CallEntry16( DWORD proc, HWND hwnd, HINSTANCE inst, + LPCSTR cmdline, INT cmdshow ) +{ +#if !defined(__CYGWIN__) && !defined (__MINGW32__) && !defined(_MSC_VER) + WORD args[5]; + SEGPTR cmdline_seg; + + TRACE( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n", + proc, hwnd, inst, debugstr_a(cmdline), cmdshow ); + + cmdline_seg = MapLS( cmdline ); + args[4] = HWND_16(hwnd); + args[3] = MapHModuleLS(inst); + args[2] = SELECTOROF(cmdline_seg); + args[1] = OFFSETOF(cmdline_seg); + args[0] = cmdshow; + WOWCallback16Ex( proc, WCB16_PASCAL, sizeof(args), args, NULL ); + UnMapLS( cmdline_seg ); +#else + FIXME( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n", + proc, hwnd, inst, debugstr_a(cmdline), cmdshow ); +#endif +} + +/************************************************************************* + * CallCPLEntry16 [SHELL32.166] + * + * called by desk.cpl on "Advanced" with: + * hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0 + * + */ +DWORD WINAPI CallCPLEntry16(HMODULE hMod, FARPROC pFunc, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6) +{ + FIXME("(%p, %p, %08lx, %08lx, %08lx, %08lx): stub.\n", hMod, pFunc, dw3, dw4, dw5, dw6); + return 0x0deadbee; +} diff --git a/reactos/lib/shell32/cpanel.h b/reactos/lib/shell32/cpanel.h index e0a65b9877f..aa6b49962b8 100644 --- a/reactos/lib/shell32/cpanel.h +++ b/reactos/lib/shell32/cpanel.h @@ -1,47 +1,47 @@ -/* Control Panel management - * - * Copyright 2001 Eric Pouech - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SHELL_CPANEL_H -#define __WINE_SHELL_CPANEL_H - -#include "cpl.h" - -typedef struct CPlApplet { - struct CPlApplet* next; /* linked list */ - HWND hWnd; - unsigned count; /* number of subprograms */ - HMODULE hModule; /* module of loaded applet */ - APPLET_PROC proc; /* entry point address */ - NEWCPLINFOW info[1]; /* array of count information. - * dwSize field is 0 if entry is invalid */ -} CPlApplet; - -typedef struct CPanel { - CPlApplet* first; /* linked list */ - HWND hWnd; - unsigned status; - CPlApplet* clkApplet; - unsigned clkSP; -} CPanel; - - -CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel); -CPlApplet* Control_UnloadApplet(CPlApplet* applet); - -#endif /* __WINE_SHELL_CPANEL_H */ +/* Control Panel management + * + * Copyright 2001 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELL_CPANEL_H +#define __WINE_SHELL_CPANEL_H + +#include "cpl.h" + +typedef struct CPlApplet { + struct CPlApplet* next; /* linked list */ + HWND hWnd; + unsigned count; /* number of subprograms */ + HMODULE hModule; /* module of loaded applet */ + APPLET_PROC proc; /* entry point address */ + NEWCPLINFOW info[1]; /* array of count information. + * dwSize field is 0 if entry is invalid */ +} CPlApplet; + +typedef struct CPanel { + CPlApplet* first; /* linked list */ + HWND hWnd; + unsigned status; + CPlApplet* clkApplet; + unsigned clkSP; +} CPanel; + + +CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel); +CPlApplet* Control_UnloadApplet(CPlApplet* applet); + +#endif /* __WINE_SHELL_CPANEL_H */ diff --git a/reactos/lib/shell32/cpanelfolder.c b/reactos/lib/shell32/cpanelfolder.c index dfb47454bd1..f20940390cb 100644 --- a/reactos/lib/shell32/cpanelfolder.c +++ b/reactos/lib/shell32/cpanelfolder.c @@ -1,1092 +1,1095 @@ -/* - * Control panel folder - * - * Copyright 2003 Martin Fuchs - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or(at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "ole2.h" -#include "shlguid.h" - -#include "cpanel.h" -#include "enumidlist.h" -#include "pidl.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "shellfolder.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/*********************************************************************** -* control panel implementation in shell namespace -*/ - -typedef struct { - IShellFolder2Vtbl *lpVtbl; - DWORD ref; - IPersistFolder2Vtbl *lpVtblPersistFolder2; - IShellExecuteHookWVtbl *lpVtblShellExecuteHookW; - IShellExecuteHookAVtbl *lpVtblShellExecuteHookA; - - IUnknown *pUnkOuter; /* used for aggregation */ - - /* both paths are parsible from the desktop */ - LPITEMIDLIST pidlRoot; /* absolute pidl */ - int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ -} ICPanelImpl; - -static IShellFolder2Vtbl vt_ShellFolder2; -static IPersistFolder2Vtbl vt_PersistFolder2; -static IShellExecuteHookWVtbl vt_ShellExecuteHookW; -static IShellExecuteHookAVtbl vt_ShellExecuteHookA; - -#define _IPersistFolder2_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblPersistFolder2))) -#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); - -#define IShellExecuteHookW_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookW))) -#define _ICOM_THIS_From_IShellExecuteHookW(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookW_Offset); - -#define IShellExecuteHookA_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookA))) -#define _ICOM_THIS_From_IShellExecuteHookA(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookA_Offset); - - -/* - converts This to a interface pointer -*/ -#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) -#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl) - -#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2) -#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2) -#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2) -#define _IShellExecuteHookW_(This) (IShellExecuteHookW*)&(This->lpVtblShellExecuteHookW) -#define _IShellExecuteHookA_(This) (IShellExecuteHookA*)&(This->lpVtblShellExecuteHookA) - -/*********************************************************************** -* IShellFolder [ControlPanel] implementation -*/ - -static shvheader ControlPanelSFHeader[] = { - {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/ - {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/ -}; - -#define CONROLPANELSHELLVIEWCOLUMNS 2 - -/************************************************************************** -* IControlPanel_Constructor -*/ -HRESULT WINAPI IControlPanel_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID * ppv) -{ - ICPanelImpl *sf; - - TRACE("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid(riid)); - - if (!ppv) - return E_POINTER; - if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) - return CLASS_E_NOAGGREGATION; - - sf = (ICPanelImpl *) LocalAlloc(GMEM_ZEROINIT, sizeof(ICPanelImpl)); - if (!sf) - return E_OUTOFMEMORY; - - sf->ref = 0; - sf->lpVtbl = &vt_ShellFolder2; - sf->lpVtblPersistFolder2 = &vt_PersistFolder2; - sf->lpVtblShellExecuteHookW = &vt_ShellExecuteHookW; - sf->lpVtblShellExecuteHookA = &vt_ShellExecuteHookA; - sf->pidlRoot = _ILCreateControlPanel(); /* my qualified pidl */ - sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf); - - if (!SUCCEEDED(IUnknown_QueryInterface(_IUnknown_(sf), riid, ppv))) { - IUnknown_Release(_IUnknown_(sf)); - return E_NOINTERFACE; - } - - TRACE("--(%p)\n", sf); - return S_OK; -} - -/************************************************************************** - * ISF_ControlPanel_fnQueryInterface - * - * NOTES supports not IPersist/IPersistFolder - */ -static HRESULT WINAPI ISF_ControlPanel_fnQueryInterface(IShellFolder2 * iface, REFIID riid, LPVOID * ppvObject) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)->(%s,%p)\n", This, shdebugstr_guid(riid), ppvObject); - - *ppvObject = NULL; - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IShellFolder) || IsEqualIID(riid, &IID_IShellFolder2)) - *ppvObject = This; - else if (IsEqualIID(riid, &IID_IPersist) || - IsEqualIID(riid, &IID_IPersistFolder) || IsEqualIID(riid, &IID_IPersistFolder2)) - *ppvObject = _IPersistFolder2_(This); - else if (IsEqualIID(riid, &IID_IShellExecuteHookW)) - *ppvObject = _IShellExecuteHookW_(This); - else if (IsEqualIID(riid, &IID_IShellExecuteHookA)) - *ppvObject = _IShellExecuteHookA_(This); - - if (*ppvObject) { - IUnknown_AddRef((IUnknown *)(*ppvObject)); - TRACE("-- Interface:(%p)->(%p)\n", ppvObject, *ppvObject); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI ISF_ControlPanel_fnAddRef(IShellFolder2 * iface) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return ++(This->ref); -} - -static ULONG WINAPI ISF_ControlPanel_fnRelease(IShellFolder2 * iface) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - if (!--(This->ref)) { - TRACE("-- destroying IShellFolder(%p)\n", This); - if (This->pidlRoot) - SHFree(This->pidlRoot); - LocalFree((HLOCAL) This); - return 0; - } - return This->ref; -} - -/************************************************************************** -* ISF_ControlPanel_fnParseDisplayName -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnParseDisplayName(IShellFolder2 * iface, - HWND hwndOwner, - LPBC pbc, - LPOLESTR lpszDisplayName, - DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - HRESULT hr = E_INVALIDARG; - - FIXME("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", - This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName), pchEaten, ppidl, pdwAttributes); - - *ppidl = 0; - if (pchEaten) - *pchEaten = 0; - - TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr); - - return hr; -} - -static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR name, LPCSTR displayName, - LPCSTR comment, int iconIdx) -{ - PIDLCPanelStruct *p; - LPITEMIDLIST pidl; - PIDLDATA tmp; - int size0 = (char*)&tmp.u.cpanel.szName-(char*)&tmp.u.cpanel; - int size = size0; - int l; - - tmp.type = PT_CPLAPPLET; - tmp.u.cpanel.dummy = 0; - tmp.u.cpanel.iconIdx = iconIdx; - - l = strlen(name); - size += l+1; - - tmp.u.cpanel.offsDispName = l+1; - l = strlen(displayName); - size += l+1; - - tmp.u.cpanel.offsComment = tmp.u.cpanel.offsDispName+1+l; - l = strlen(comment); - size += l+1; - - pidl = SHAlloc(size+4); - if (!pidl) - return NULL; - - pidl->mkid.cb = size+2; - memcpy(pidl->mkid.abID, &tmp, 2+size0); - - p = &((PIDLDATA*)pidl->mkid.abID)->u.cpanel; - strcpy(p->szName, name); - strcpy(p->szName+tmp.u.cpanel.offsDispName, displayName); - strcpy(p->szName+tmp.u.cpanel.offsComment, comment); - - *(WORD*)((char*)pidl+(size+2)) = 0; - - pcheck(pidl); - - return pidl; -} - -/************************************************************************** - * _ILGetCPanelPointer() - * gets a pointer to the control panel struct stored in the pidl - */ -static PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl) -{ - LPPIDLDATA pdata = _ILGetDataPointer(pidl); - - if (pdata && pdata->type==PT_CPLAPPLET) - return (PIDLCPanelStruct*)&(pdata->u.cpanel); - - return NULL; -} - - /************************************************************************** - * ISF_ControlPanel_fnEnumObjects - */ -static BOOL SHELL_RegisterCPanelApp(IEnumIDList* list, LPCSTR path) -{ - LPITEMIDLIST pidl; - CPlApplet* applet; - CPanel panel; - CPLINFO info; - unsigned i; - int iconIdx; - - char displayName[MAX_PATH]; - char comment[MAX_PATH]; - - WCHAR wpath[MAX_PATH]; - - MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); - - panel.first = NULL; - applet = Control_LoadApplet(0, wpath, &panel); - - if (applet) - { - for(i=0; icount; ++i) - { - WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0); - WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0); - - applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info); - - if (info.idIcon > 0) - iconIdx = -info.idIcon; /* negative icon index instead of icon number */ - else - iconIdx = 0; - - pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx); - - if (pidl) - AddToEnumList(list, pidl); - } - Control_UnloadApplet(applet); - } - return TRUE; -} - -static int SHELL_RegisterRegistryCPanelApps(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) -{ - char name[MAX_PATH]; - char value[MAX_PATH]; - HKEY hkey; - - int cnt = 0; - - if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) - { - int idx = 0; - - for(;; ++idx) - { - DWORD nameLen = MAX_PATH; - DWORD valueLen = MAX_PATH; - - if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS) - break; - - if (SHELL_RegisterCPanelApp(list, value)) - ++cnt; - } - RegCloseKey(hkey); - } - - return cnt; -} - -static int SHELL_RegisterCPanelFolders(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) -{ - char name[MAX_PATH]; - HKEY hkey; - - int cnt = 0; - - if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) - { - int idx = 0; - for(;; ++idx) - { - if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS) - break; - - if (*name == '{') - { - LPITEMIDLIST pidl = _ILCreateGuidFromStrA(name); - - if (pidl && AddToEnumList(list, pidl)) - ++cnt; - } - } - - RegCloseKey(hkey); - } - - return cnt; -} - -/************************************************************************** - * CreateCPanelEnumList() - */ -static BOOL CreateCPanelEnumList( - IEnumIDList * iface, - DWORD dwFlags) -{ - CHAR szPath[MAX_PATH]; - WIN32_FIND_DATAA wfd; - HANDLE hFile; - - TRACE("(%p)->(flags=0x%08lx) \n",iface,dwFlags); - - /* enumerate control panel folders folders */ - if (dwFlags & SHCONTF_FOLDERS) - SHELL_RegisterCPanelFolders(iface, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace"); - - /* enumerate the control panel applets */ - if (dwFlags & SHCONTF_NONFOLDERS) - { - LPSTR p; - - GetSystemDirectoryA(szPath, MAX_PATH); - p = PathAddBackslashA(szPath); - strcpy(p, "*.cpl"); - - TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",iface,debugstr_a(szPath)); - hFile = FindFirstFileA(szPath, &wfd); - - if (hFile != INVALID_HANDLE_VALUE) - { - do - { - if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) - continue; - - if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - strcpy(p, wfd.cFileName); - SHELL_RegisterCPanelApp((IEnumIDList*)iface, szPath); - } - } while(FindNextFileA(hFile, &wfd)); - FindClose(hFile); - } - - SHELL_RegisterRegistryCPanelApps((IEnumIDList*)iface, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); - SHELL_RegisterRegistryCPanelApps((IEnumIDList*)iface, HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); - } - return TRUE; -} - -/************************************************************************** -* ISF_ControlPanel_fnEnumObjects -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnEnumObjects(IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); - - *ppEnumIDList = IEnumIDList_Constructor(); - if (*ppEnumIDList) - CreateCPanelEnumList(*ppEnumIDList, dwFlags); - - TRACE("--(%p)->(new ID List: %p)\n", This, *ppEnumIDList); - - return(*ppEnumIDList) ? S_OK : E_OUTOFMEMORY; -} - -/************************************************************************** -* ISF_ControlPanel_fnBindToObject -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnBindToObject(IShellFolder2 * iface, LPCITEMIDLIST pidl, - LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); - - return SHELL32_BindToChild(This->pidlRoot, NULL, pidl, riid, ppvOut); -} - -/************************************************************************** -* ISF_ControlPanel_fnBindToStorage -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnBindToStorage(IShellFolder2 * iface, - LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); - - *ppvOut = NULL; - return E_NOTIMPL; -} - -/************************************************************************** -* ISF_ControlPanel_fnCompareIDs -*/ - -static HRESULT WINAPI -ISF_ControlPanel_fnCompareIDs(IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - int nReturn; - - TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); - nReturn = SHELL32_CompareIDs(_IShellFolder_(This), lParam, pidl1, pidl2); - TRACE("-- %i\n", nReturn); - return nReturn; -} - -/************************************************************************** -* ISF_ControlPanel_fnCreateViewObject -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnCreateViewObject(IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - LPSHELLVIEW pShellView; - HRESULT hr = E_INVALIDARG; - - TRACE("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid(riid), ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID(riid, &IID_IDropTarget)) { - WARN("IDropTarget not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID(riid, &IID_IContextMenu)) { - WARN("IContextMenu not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID(riid, &IID_IShellView)) { - pShellView = IShellView_Constructor((IShellFolder *) iface); - if (pShellView) { - hr = IShellView_QueryInterface(pShellView, riid, ppvOut); - IShellView_Release(pShellView); - } - } - } - TRACE("--(%p)->(interface=%p)\n", This, ppvOut); - return hr; -} - -/************************************************************************** -* ISF_ControlPanel_fnGetAttributesOf -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnGetAttributesOf(IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - HRESULT hr = S_OK; - - TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); - - if ((!cidl) ||(!apidl) ||(!rgfInOut)) - return E_INVALIDARG; - - if (*rgfInOut == 0) - *rgfInOut = ~0; - - while(cidl > 0 && *apidl) { - pdump(*apidl); - SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut); - apidl++; - cidl--; - } - - TRACE("-- result=0x%08lx\n", *rgfInOut); - return hr; -} - -/************************************************************************** -* ISF_ControlPanel_fnGetUIObjectOf -* -* PARAMETERS -* HWND hwndOwner, //[in ] Parent window for any output -* UINT cidl, //[in ] array size -* LPCITEMIDLIST* apidl, //[in ] simple pidl array -* REFIID riid, //[in ] Requested Interface -* UINT* prgfInOut, //[ ] reserved -* LPVOID* ppvObject) //[out] Resulting Interface -* -*/ -static HRESULT WINAPI -ISF_ControlPanel_fnGetUIObjectOf(IShellFolder2 * iface, - HWND hwndOwner, - UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - LPITEMIDLIST pidl; - IUnknown *pObj = NULL; - HRESULT hr = E_INVALIDARG; - - TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", - This, hwndOwner, cidl, apidl, shdebugstr_guid(riid), prgfInOut, ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID(riid, &IID_IContextMenu) &&(cidl >= 1)) { - pObj = (LPUNKNOWN) ISvItemCm_Constructor((IShellFolder *) iface, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1)) { - pObj = (LPUNKNOWN) IDataObject_Constructor(hwndOwner, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID(riid, &IID_IExtractIconA) &&(cidl == 1)) { - pidl = ILCombine(This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconA_Constructor(pidl); - SHFree(pidl); - hr = S_OK; - } else if (IsEqualIID(riid, &IID_IExtractIconW) &&(cidl == 1)) { - pidl = ILCombine(This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconW_Constructor(pidl); - SHFree(pidl); - hr = S_OK; - } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) - && (cidl == 1)) { - pidl = ILCombine(This->pidlRoot, apidl[0]); - hr = IShellLink_ConstructFromFile(NULL, riid, pidl,(LPVOID*)&pObj); - SHFree(pidl); - } else { - hr = E_NOINTERFACE; - } - - if (SUCCEEDED(hr) && !pObj) - hr = E_OUTOFMEMORY; - - *ppvOut = pObj; - } - TRACE("(%p)->hr=0x%08lx\n", This, hr); - return hr; -} - -/************************************************************************** -* ISF_ControlPanel_fnGetDisplayNameOf -*/ -static HRESULT WINAPI ISF_ControlPanel_fnGetDisplayNameOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - CHAR szPath[MAX_PATH*2]; - PIDLCPanelStruct* pcpanel; - - *szPath = '\0'; - - TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); - pdump(pidl); - - if (!pidl || !strRet) - return E_INVALIDARG; - - pcpanel = _ILGetCPanelPointer(pidl); - - if (pcpanel) { - lstrcpyA(szPath, pcpanel->szName+pcpanel->offsDispName); - - if (!(dwFlags & SHGDN_FORPARSING)) - FIXME("retrieve display name from control panel app\n"); - } - /* take names of special folders only if its only this folder */ - else if (_ILIsSpecialFolder(pidl)) { - BOOL bSimplePidl = _ILIsPidlSimple(pidl); - - if (bSimplePidl) { - _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */ - } else { - FIXME("special pidl\n"); - } - - if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */ - int len = 0; - - PathAddBackslashA(szPath); /*FIXME*/ - len = lstrlenA(szPath); - - if (!SUCCEEDED - (SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len))) - return E_OUTOFMEMORY; - } - } - - strRet->uType = STRRET_CSTR; - lstrcpynA(strRet->u.cStr, szPath, MAX_PATH); - - TRACE("--(%p)->(%s)\n", This, szPath); - return S_OK; -} - -/************************************************************************** -* ISF_ControlPanel_fnSetNameOf -* Changes the name of a file object or subfolder, possibly changing its item -* identifier in the process. -* -* PARAMETERS -* HWND hwndOwner, //[in ] Owner window for output -* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change -* LPCOLESTR lpszName, //[in ] the items new display name -* DWORD dwFlags, //[in ] SHGNO formatting flags -* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned -*/ -static HRESULT WINAPI ISF_ControlPanel_fnSetNameOf(IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ - LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut); - return E_FAIL; -} - -static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultSearchGUID(IShellFolder2 * iface, GUID * pguid) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - FIXME("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_ControlPanel_fnEnumSearches(IShellFolder2 * iface, IEnumExtraSearch ** ppenum) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - FIXME("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumn(IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)\n", This); - - if (pSort) *pSort = 0; - if (pDisplay) *pDisplay = 0; - return S_OK; -} -static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumnState(IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - TRACE("(%p)\n", This); - - if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG; - *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags; - return S_OK; -} -static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsEx(IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - FIXME("(%p)\n", This); - return E_NOTIMPL; -} - -static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - HRESULT hr; - - TRACE("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); - - if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - if (!pidl) { - psd->fmt = ControlPanelSFHeader[iColumn].fmt; - psd->cxChar = ControlPanelSFHeader[iColumn].cxChar; - psd->str.uType = STRRET_CSTR; - LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); - return S_OK; - } else { - psd->str.u.cStr[0] = 0x00; - psd->str.uType = STRRET_CSTR; - switch(iColumn) { - case 0: /* name */ - hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); - break; - case 1: /* comment */ - _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH); - break; - } - hr = S_OK; - } - - return hr; -} -static HRESULT WINAPI ISF_ControlPanel_fnMapColumnToSCID(IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - FIXME("(%p)\n", This); - return E_NOTIMPL; -} - -static IShellFolder2Vtbl vt_ShellFolder2 = -{ - - ISF_ControlPanel_fnQueryInterface, - ISF_ControlPanel_fnAddRef, - ISF_ControlPanel_fnRelease, - ISF_ControlPanel_fnParseDisplayName, - ISF_ControlPanel_fnEnumObjects, - ISF_ControlPanel_fnBindToObject, - ISF_ControlPanel_fnBindToStorage, - ISF_ControlPanel_fnCompareIDs, - ISF_ControlPanel_fnCreateViewObject, - ISF_ControlPanel_fnGetAttributesOf, - ISF_ControlPanel_fnGetUIObjectOf, - ISF_ControlPanel_fnGetDisplayNameOf, - ISF_ControlPanel_fnSetNameOf, - - /* ShellFolder2 */ - ISF_ControlPanel_fnGetDefaultSearchGUID, - ISF_ControlPanel_fnEnumSearches, - ISF_ControlPanel_fnGetDefaultColumn, - ISF_ControlPanel_fnGetDefaultColumnState, - ISF_ControlPanel_fnGetDetailsEx, - ISF_ControlPanel_fnGetDetailsOf, - ISF_ControlPanel_fnMapColumnToSCID -}; - -/************************************************************************ - * ICPanel_PersistFolder2_QueryInterface - */ -static HRESULT WINAPI ICPanel_PersistFolder2_QueryInterface(IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObject) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - - TRACE("(%p)\n", This); - - return IUnknown_QueryInterface(_IUnknown_(This), iid, ppvObject); -} - -/************************************************************************ - * ICPanel_PersistFolder2_AddRef - */ -static ULONG WINAPI ICPanel_PersistFolder2_AddRef(IPersistFolder2 * iface) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef(_IUnknown_(This)); -} - -/************************************************************************ - * ISFPersistFolder_Release - */ -static ULONG WINAPI ICPanel_PersistFolder2_Release(IPersistFolder2 * iface) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_Release(_IUnknown_(This)); -} - -/************************************************************************ - * ICPanel_PersistFolder2_GetClassID - */ -static HRESULT WINAPI ICPanel_PersistFolder2_GetClassID(IPersistFolder2 * iface, CLSID * lpClassId) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - - TRACE("(%p)\n", This); - - if (!lpClassId) - return E_POINTER; - *lpClassId = CLSID_ControlPanel; - - return S_OK; -} - -/************************************************************************ - * ICPanel_PersistFolder2_Initialize - * - * NOTES: it makes no sense to change the pidl - */ -static HRESULT WINAPI ICPanel_PersistFolder2_Initialize(IPersistFolder2 * iface, LPCITEMIDLIST pidl) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - TRACE("(%p)->(%p)\n", This, pidl); - return E_NOTIMPL; -} - -/************************************************************************** - * IPersistFolder2_fnGetCurFolder - */ -static HRESULT WINAPI ICPanel_PersistFolder2_GetCurFolder(IPersistFolder2 * iface, LPITEMIDLIST * pidl) -{ - _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); - - TRACE("(%p)->(%p)\n", This, pidl); - - if (!pidl) - return E_POINTER; - *pidl = ILClone(This->pidlRoot); - return S_OK; -} - -static IPersistFolder2Vtbl vt_PersistFolder2 = -{ - - ICPanel_PersistFolder2_QueryInterface, - ICPanel_PersistFolder2_AddRef, - ICPanel_PersistFolder2_Release, - ICPanel_PersistFolder2_GetClassID, - ICPanel_PersistFolder2_Initialize, - ICPanel_PersistFolder2_GetCurFolder -}; - -HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex) -{ - PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); - - if (!pcpanel) - return E_INVALIDARG; - - lstrcpyA(szIconFile, pcpanel->szName); - *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; - - return S_OK; -} - -HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex) -{ - PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); - - if (!pcpanel) - return E_INVALIDARG; - - MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax); - *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; - - return S_OK; -} - - -/************************************************************************** -* IShellExecuteHookW Implementation -*/ - -static HRESULT WINAPI IShellExecuteHookW_fnQueryInterface(IShellExecuteHookW* iface, REFIID riid, void** ppvObject) -{ - _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); -} - -static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnAddRef(IShellExecuteHookW* iface) -{ - _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef(This->pUnkOuter); -} - -static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnRelease(IShellExecuteHookW* iface) -{ - _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); - - TRACE("(%p)\n", This); - - return IUnknown_Release(This->pUnkOuter); -} - -static HRESULT WINAPI IShellExecuteHookW_fnExecute(IShellExecuteHookW* iface, LPSHELLEXECUTEINFOW psei) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - SHELLEXECUTEINFOW sei_tmp; - PIDLCPanelStruct* pcpanel; - WCHAR path[MAX_PATH]; - BOOL ret; - int l; - - TRACE("(%p)->execute(%p)\n", This, psei); - - if (!psei) - return E_INVALIDARG; - - pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); - - if (!pcpanel) - return E_INVALIDARG; - - path[0] = '\"'; - l = 1 + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, path+1, MAX_PATH); - - /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ - path[++l] = '"'; - path[++l] = ' '; - - MultiByteToWideChar(CP_ACP, 0, pcpanel->szName+pcpanel->offsDispName, -1, path+l, MAX_PATH); - - memcpy(&sei_tmp, psei, sizeof(sei_tmp)); - sei_tmp.lpFile = path; - sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; - - ret = ShellExecuteExW(&sei_tmp); - if (ret) - return S_OK; - else - return S_FALSE; -} - -static IShellExecuteHookWVtbl vt_ShellExecuteHookW = -{ - - IShellExecuteHookW_fnQueryInterface, - IShellExecuteHookW_fnAddRef, - IShellExecuteHookW_fnRelease, - - IShellExecuteHookW_fnExecute -}; - - -/************************************************************************** -* IShellExecuteHookA Implementation -*/ - -static HRESULT WINAPI IShellExecuteHookA_fnQueryInterface(IShellExecuteHookA* iface, REFIID riid, void** ppvObject) -{ - _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); -} - -static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnAddRef(IShellExecuteHookA* iface) -{ - _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); - - TRACE("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef(This->pUnkOuter); -} - -static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnRelease(IShellExecuteHookA* iface) -{ - _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); - - TRACE("(%p)\n", This); - - return IUnknown_Release(This->pUnkOuter); -} - -static HRESULT WINAPI IShellExecuteHookA_fnExecute(IShellExecuteHookA* iface, LPSHELLEXECUTEINFOA psei) -{ - ICPanelImpl *This = (ICPanelImpl *)iface; - - SHELLEXECUTEINFOA sei_tmp; - PIDLCPanelStruct* pcpanel; - char path[MAX_PATH]; - BOOL ret; - - TRACE("(%p)->execute(%p)\n", This, psei); - - if (!psei) - return E_INVALIDARG; - - pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); - - if (!pcpanel) - return E_INVALIDARG; - - path[0] = '\"'; - lstrcpyA(path+1, pcpanel->szName); - - /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ - lstrcatA(path, "\" "); - lstrcatA(path, pcpanel->szName+pcpanel->offsDispName); - - memcpy(&sei_tmp, psei, sizeof(sei_tmp)); - sei_tmp.lpFile = path; - sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; - - ret = ShellExecuteExA(&sei_tmp); - if (ret) - return S_OK; - else - return S_FALSE; -} - -static IShellExecuteHookAVtbl vt_ShellExecuteHookA = -{ - - IShellExecuteHookA_fnQueryInterface, - IShellExecuteHookA_fnAddRef, - IShellExecuteHookA_fnRelease, - - IShellExecuteHookA_fnExecute -}; +/* + * Control panel folder + * + * Copyright 2003 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or(at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "ole2.h" +#include "shlguid.h" + +#include "cpanel.h" +#include "enumidlist.h" +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/*********************************************************************** +* control panel implementation in shell namespace +*/ + +typedef struct { + IShellFolder2Vtbl *lpVtbl; + DWORD ref; + IPersistFolder2Vtbl *lpVtblPersistFolder2; + IShellExecuteHookWVtbl *lpVtblShellExecuteHookW; + IShellExecuteHookAVtbl *lpVtblShellExecuteHookA; + + IUnknown *pUnkOuter; /* used for aggregation */ + + /* both paths are parsible from the desktop */ + LPITEMIDLIST pidlRoot; /* absolute pidl */ + int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ +} ICPanelImpl; + +static IShellFolder2Vtbl vt_ShellFolder2; +static IPersistFolder2Vtbl vt_PersistFolder2; +static IShellExecuteHookWVtbl vt_ShellExecuteHookW; +static IShellExecuteHookAVtbl vt_ShellExecuteHookA; + +#define _IPersistFolder2_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblPersistFolder2))) +#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); + +#define IShellExecuteHookW_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookW))) +#define _ICOM_THIS_From_IShellExecuteHookW(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookW_Offset); + +#define IShellExecuteHookA_Offset ((int)(&(((ICPanelImpl*)0)->lpVtblShellExecuteHookA))) +#define _ICOM_THIS_From_IShellExecuteHookA(class, name) class* This = (class*)(((char*)name)-IShellExecuteHookA_Offset); + + +/* + converts This to a interface pointer +*/ +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) +#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl) + +#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2) +#define _IShellExecuteHookW_(This) (IShellExecuteHookW*)&(This->lpVtblShellExecuteHookW) +#define _IShellExecuteHookA_(This) (IShellExecuteHookA*)&(This->lpVtblShellExecuteHookA) + +/*********************************************************************** +* IShellFolder [ControlPanel] implementation +*/ + +static shvheader ControlPanelSFHeader[] = { + {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/ + {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/ +}; + +#define CONROLPANELSHELLVIEWCOLUMNS 2 + +/************************************************************************** +* IControlPanel_Constructor +*/ +HRESULT WINAPI IControlPanel_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID * ppv) +{ + ICPanelImpl *sf; + + TRACE("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid(riid)); + + if (!ppv) + return E_POINTER; + if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) + return CLASS_E_NOAGGREGATION; + + sf = (ICPanelImpl *) LocalAlloc(GMEM_ZEROINIT, sizeof(ICPanelImpl)); + if (!sf) + return E_OUTOFMEMORY; + + sf->ref = 0; + sf->lpVtbl = &vt_ShellFolder2; + sf->lpVtblPersistFolder2 = &vt_PersistFolder2; + sf->lpVtblShellExecuteHookW = &vt_ShellExecuteHookW; + sf->lpVtblShellExecuteHookA = &vt_ShellExecuteHookA; + sf->pidlRoot = _ILCreateControlPanel(); /* my qualified pidl */ + sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf); + + if (!SUCCEEDED(IUnknown_QueryInterface(_IUnknown_(sf), riid, ppv))) { + IUnknown_Release(_IUnknown_(sf)); + return E_NOINTERFACE; + } + + TRACE("--(%p)\n", sf); + return S_OK; +} + +/************************************************************************** + * ISF_ControlPanel_fnQueryInterface + * + * NOTES supports not IPersist/IPersistFolder + */ +static HRESULT WINAPI ISF_ControlPanel_fnQueryInterface(IShellFolder2 * iface, REFIID riid, LPVOID * ppvObject) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)->(%s,%p)\n", This, shdebugstr_guid(riid), ppvObject); + + *ppvObject = NULL; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IShellFolder) || IsEqualIID(riid, &IID_IShellFolder2)) + *ppvObject = This; + else if (IsEqualIID(riid, &IID_IPersist) || + IsEqualIID(riid, &IID_IPersistFolder) || IsEqualIID(riid, &IID_IPersistFolder2)) + *ppvObject = _IPersistFolder2_(This); + else if (IsEqualIID(riid, &IID_IShellExecuteHookW)) + *ppvObject = _IShellExecuteHookW_(This); + else if (IsEqualIID(riid, &IID_IShellExecuteHookA)) + *ppvObject = _IShellExecuteHookA_(This); + + if (*ppvObject) { + IUnknown_AddRef((IUnknown *)(*ppvObject)); + TRACE("-- Interface:(%p)->(%p)\n", ppvObject, *ppvObject); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ISF_ControlPanel_fnAddRef(IShellFolder2 * iface) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI ISF_ControlPanel_fnRelease(IShellFolder2 * iface) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE("-- destroying IShellFolder(%p)\n", This); + if (This->pidlRoot) + SHFree(This->pidlRoot); + LocalFree((HLOCAL) This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* ISF_ControlPanel_fnParseDisplayName +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnParseDisplayName(IShellFolder2 * iface, + HWND hwndOwner, + LPBC pbc, + LPOLESTR lpszDisplayName, + DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + HRESULT hr = E_INVALIDARG; + + FIXME("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", + This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName), pchEaten, ppidl, pdwAttributes); + + *ppidl = 0; + if (pchEaten) + *pchEaten = 0; + + TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr); + + return hr; +} + +static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR name, LPCSTR displayName, + LPCSTR comment, int iconIdx) +{ + PIDLCPanelStruct *p; + LPITEMIDLIST pidl; + PIDLDATA tmp; + int size0 = (char*)&tmp.u.cpanel.szName-(char*)&tmp.u.cpanel; + int size = size0; + int l; + + tmp.type = PT_CPLAPPLET; + tmp.u.cpanel.dummy = 0; + tmp.u.cpanel.iconIdx = iconIdx; + + l = strlen(name); + size += l+1; + + tmp.u.cpanel.offsDispName = l+1; + l = strlen(displayName); + size += l+1; + + tmp.u.cpanel.offsComment = tmp.u.cpanel.offsDispName+1+l; + l = strlen(comment); + size += l+1; + + pidl = SHAlloc(size+4); + if (!pidl) + return NULL; + + pidl->mkid.cb = size+2; + memcpy(pidl->mkid.abID, &tmp, 2+size0); + + p = &((PIDLDATA*)pidl->mkid.abID)->u.cpanel; + strcpy(p->szName, name); + strcpy(p->szName+tmp.u.cpanel.offsDispName, displayName); + strcpy(p->szName+tmp.u.cpanel.offsComment, comment); + + *(WORD*)((char*)pidl+(size+2)) = 0; + + pcheck(pidl); + + return pidl; +} + +/************************************************************************** + * _ILGetCPanelPointer() + * gets a pointer to the control panel struct stored in the pidl + */ +static PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata = _ILGetDataPointer(pidl); + + if (pdata && pdata->type==PT_CPLAPPLET) + return (PIDLCPanelStruct*)&(pdata->u.cpanel); + + return NULL; +} + + /************************************************************************** + * ISF_ControlPanel_fnEnumObjects + */ +static BOOL SHELL_RegisterCPanelApp(IEnumIDList* list, LPCSTR path) +{ + LPITEMIDLIST pidl; + CPlApplet* applet; + CPanel panel; + CPLINFO info; + unsigned i; + int iconIdx; + + char displayName[MAX_PATH]; + char comment[MAX_PATH]; + + WCHAR wpath[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); + + panel.first = NULL; + applet = Control_LoadApplet(0, wpath, &panel); + + if (applet) + { + for(i=0; icount; ++i) + { + WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0); + WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0); + + applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info); + + if (info.idIcon > 0) + iconIdx = -info.idIcon; /* negative icon index instead of icon number */ + else + iconIdx = 0; + + pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx); + + if (pidl) + AddToEnumList(list, pidl); + } + Control_UnloadApplet(applet); + } + return TRUE; +} + +static int SHELL_RegisterRegistryCPanelApps(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) +{ + char name[MAX_PATH]; + char value[MAX_PATH]; + HKEY hkey; + + int cnt = 0; + + if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) + { + int idx = 0; + + for(;; ++idx) + { + DWORD nameLen = MAX_PATH; + DWORD valueLen = MAX_PATH; + + if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS) + break; + + if (SHELL_RegisterCPanelApp(list, value)) + ++cnt; + } + RegCloseKey(hkey); + } + + return cnt; +} + +static int SHELL_RegisterCPanelFolders(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath) +{ + char name[MAX_PATH]; + HKEY hkey; + + int cnt = 0; + + if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS) + { + int idx = 0; + for(;; ++idx) + { + if (RegEnumKeyA(hkey, idx, name, MAX_PATH) != ERROR_SUCCESS) + break; + + if (*name == '{') + { + LPITEMIDLIST pidl = _ILCreateGuidFromStrA(name); + + if (pidl && AddToEnumList(list, pidl)) + ++cnt; + } + } + + RegCloseKey(hkey); + } + + return cnt; +} + +/************************************************************************** + * CreateCPanelEnumList() + */ +static BOOL CreateCPanelEnumList( + IEnumIDList * iface, + DWORD dwFlags) +{ + CHAR szPath[MAX_PATH]; + WIN32_FIND_DATAA wfd; + HANDLE hFile; + + TRACE("(%p)->(flags=0x%08lx) \n",iface,dwFlags); + + /* enumerate control panel folders folders */ + if (dwFlags & SHCONTF_FOLDERS) + SHELL_RegisterCPanelFolders(iface, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace"); + + /* enumerate the control panel applets */ + if (dwFlags & SHCONTF_NONFOLDERS) + { + LPSTR p; + + GetSystemDirectoryA(szPath, MAX_PATH); + p = PathAddBackslashA(szPath); + strcpy(p, "*.cpl"); + + TRACE("-- (%p)-> enumerate SHCONTF_NONFOLDERS of %s\n",iface,debugstr_a(szPath)); + hFile = FindFirstFileA(szPath, &wfd); + + if (hFile != INVALID_HANDLE_VALUE) + { + do + { + if (!(dwFlags & SHCONTF_INCLUDEHIDDEN) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) + continue; + + if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + strcpy(p, wfd.cFileName); + SHELL_RegisterCPanelApp((IEnumIDList*)iface, szPath); + } + } while(FindNextFileA(hFile, &wfd)); + FindClose(hFile); + } + + SHELL_RegisterRegistryCPanelApps((IEnumIDList*)iface, HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); + SHELL_RegisterRegistryCPanelApps((IEnumIDList*)iface, HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cpls"); + } + return TRUE; +} + +/************************************************************************** +* ISF_ControlPanel_fnEnumObjects +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnEnumObjects(IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); + + *ppEnumIDList = IEnumIDList_Constructor(); + if (*ppEnumIDList) + CreateCPanelEnumList(*ppEnumIDList, dwFlags); + + TRACE("--(%p)->(new ID List: %p)\n", This, *ppEnumIDList); + + return(*ppEnumIDList) ? S_OK : E_OUTOFMEMORY; +} + +/************************************************************************** +* ISF_ControlPanel_fnBindToObject +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnBindToObject(IShellFolder2 * iface, LPCITEMIDLIST pidl, + LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); + + return SHELL32_BindToChild(This->pidlRoot, NULL, pidl, riid, ppvOut); +} + +/************************************************************************** +* ISF_ControlPanel_fnBindToStorage +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnBindToStorage(IShellFolder2 * iface, + LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid(riid), ppvOut); + + *ppvOut = NULL; + return E_NOTIMPL; +} + +/************************************************************************** +* ISF_ControlPanel_fnCompareIDs +*/ + +static HRESULT WINAPI +ISF_ControlPanel_fnCompareIDs(IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + int nReturn; + + TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); + nReturn = SHELL32_CompareIDs(_IShellFolder_(This), lParam, pidl1, pidl2); + TRACE("-- %i\n", nReturn); + return nReturn; +} + +/************************************************************************** +* ISF_ControlPanel_fnCreateViewObject +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnCreateViewObject(IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + LPSHELLVIEW pShellView; + HRESULT hr = E_INVALIDARG; + + TRACE("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid(riid), ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID(riid, &IID_IDropTarget)) { + WARN("IDropTarget not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID(riid, &IID_IContextMenu)) { + WARN("IContextMenu not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID(riid, &IID_IShellView)) { + pShellView = IShellView_Constructor((IShellFolder *) iface); + if (pShellView) { + hr = IShellView_QueryInterface(pShellView, riid, ppvOut); + IShellView_Release(pShellView); + } + } + } + TRACE("--(%p)->(interface=%p)\n", This, ppvOut); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetAttributesOf +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnGetAttributesOf(IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + HRESULT hr = S_OK; + + TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + + if ((!cidl) ||(!apidl) ||(!rgfInOut)) + return E_INVALIDARG; + + if (*rgfInOut == 0) + *rgfInOut = ~0; + + while(cidl > 0 && *apidl) { + pdump(*apidl); + SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut); + apidl++; + cidl--; + } + + TRACE("-- result=0x%08lx\n", *rgfInOut); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetUIObjectOf +* +* PARAMETERS +* HWND hwndOwner, //[in ] Parent window for any output +* UINT cidl, //[in ] array size +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* REFIID riid, //[in ] Requested Interface +* UINT* prgfInOut, //[ ] reserved +* LPVOID* ppvObject) //[out] Resulting Interface +* +*/ +static HRESULT WINAPI +ISF_ControlPanel_fnGetUIObjectOf(IShellFolder2 * iface, + HWND hwndOwner, + UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + LPITEMIDLIST pidl; + IUnknown *pObj = NULL; + HRESULT hr = E_INVALIDARG; + + TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", + This, hwndOwner, cidl, apidl, shdebugstr_guid(riid), prgfInOut, ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID(riid, &IID_IContextMenu) &&(cidl >= 1)) { + pObj = (LPUNKNOWN) ISvItemCm_Constructor((IShellFolder *) iface, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1)) { + pObj = (LPUNKNOWN) IDataObject_Constructor(hwndOwner, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IExtractIconA) &&(cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconA_Constructor(pidl); + SHFree(pidl); + hr = S_OK; + } else if (IsEqualIID(riid, &IID_IExtractIconW) &&(cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconW_Constructor(pidl); + SHFree(pidl); + hr = S_OK; + } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) + && (cidl == 1)) { + pidl = ILCombine(This->pidlRoot, apidl[0]); + hr = IShellLink_ConstructFromFile(NULL, riid, pidl,(LPVOID*)&pObj); + SHFree(pidl); + } else { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr) && !pObj) + hr = E_OUTOFMEMORY; + + *ppvOut = pObj; + } + TRACE("(%p)->hr=0x%08lx\n", This, hr); + return hr; +} + +/************************************************************************** +* ISF_ControlPanel_fnGetDisplayNameOf +*/ +static HRESULT WINAPI ISF_ControlPanel_fnGetDisplayNameOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + CHAR szPath[MAX_PATH*2]; + PIDLCPanelStruct* pcpanel; + + *szPath = '\0'; + + TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); + pdump(pidl); + + if (!pidl || !strRet) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(pidl); + + if (pcpanel) { + lstrcpyA(szPath, pcpanel->szName+pcpanel->offsDispName); + + if (!(dwFlags & SHGDN_FORPARSING)) + FIXME("retrieve display name from control panel app\n"); + } + /* take names of special folders only if its only this folder */ + else if (_ILIsSpecialFolder(pidl)) { + BOOL bSimplePidl = _ILIsPidlSimple(pidl); + + if (bSimplePidl) { + _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */ + } else { + FIXME("special pidl\n"); + } + + if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */ + int len = 0; + + PathAddBackslashA(szPath); /*FIXME*/ + len = lstrlenA(szPath); + + if (!SUCCEEDED + (SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len))) + return E_OUTOFMEMORY; + } + } + + strRet->uType = STRRET_CSTR; + lstrcpynA(strRet->u.cStr, szPath, MAX_PATH); + + TRACE("--(%p)->(%s)\n", This, szPath); + return S_OK; +} + +/************************************************************************** +* ISF_ControlPanel_fnSetNameOf +* Changes the name of a file object or subfolder, possibly changing its item +* identifier in the process. +* +* PARAMETERS +* HWND hwndOwner, //[in ] Owner window for output +* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change +* LPCOLESTR lpszName, //[in ] the items new display name +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned +*/ +static HRESULT WINAPI ISF_ControlPanel_fnSetNameOf(IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ + LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + FIXME("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w(lpName), dwFlags, pPidlOut); + return E_FAIL; +} + +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultSearchGUID(IShellFolder2 * iface, GUID * pguid) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + FIXME("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_ControlPanel_fnEnumSearches(IShellFolder2 * iface, IEnumExtraSearch ** ppenum) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + FIXME("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumn(IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)\n", This); + + if (pSort) *pSort = 0; + if (pDisplay) *pDisplay = 0; + return S_OK; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDefaultColumnState(IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + TRACE("(%p)\n", This); + + if (!pcsFlags || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) return E_INVALIDARG; + *pcsFlags = ControlPanelSFHeader[iColumn].pcsFlags; + return S_OK; +} +static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsEx(IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + HRESULT hr; + + TRACE("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); + + if (!psd || iColumn >= CONROLPANELSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + if (!pidl) { + psd->fmt = ControlPanelSFHeader[iColumn].fmt; + psd->cxChar = ControlPanelSFHeader[iColumn].cxChar; + psd->str.uType = STRRET_CSTR; + LoadStringA(shell32_hInstance, ControlPanelSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); + return S_OK; + } else { + psd->str.u.cStr[0] = 0x00; + psd->str.uType = STRRET_CSTR; + switch(iColumn) { + case 0: /* name */ + hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); + break; + case 1: /* comment */ + _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH); + break; + } + hr = S_OK; + } + + return hr; +} +static HRESULT WINAPI ISF_ControlPanel_fnMapColumnToSCID(IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static IShellFolder2Vtbl vt_ShellFolder2 = +{ + + ISF_ControlPanel_fnQueryInterface, + ISF_ControlPanel_fnAddRef, + ISF_ControlPanel_fnRelease, + ISF_ControlPanel_fnParseDisplayName, + ISF_ControlPanel_fnEnumObjects, + ISF_ControlPanel_fnBindToObject, + ISF_ControlPanel_fnBindToStorage, + ISF_ControlPanel_fnCompareIDs, + ISF_ControlPanel_fnCreateViewObject, + ISF_ControlPanel_fnGetAttributesOf, + ISF_ControlPanel_fnGetUIObjectOf, + ISF_ControlPanel_fnGetDisplayNameOf, + ISF_ControlPanel_fnSetNameOf, + + /* ShellFolder2 */ + ISF_ControlPanel_fnGetDefaultSearchGUID, + ISF_ControlPanel_fnEnumSearches, + ISF_ControlPanel_fnGetDefaultColumn, + ISF_ControlPanel_fnGetDefaultColumnState, + ISF_ControlPanel_fnGetDetailsEx, + ISF_ControlPanel_fnGetDetailsOf, + ISF_ControlPanel_fnMapColumnToSCID +}; + +/************************************************************************ + * ICPanel_PersistFolder2_QueryInterface + */ +static HRESULT WINAPI ICPanel_PersistFolder2_QueryInterface(IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObject) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_QueryInterface(_IUnknown_(This), iid, ppvObject); +} + +/************************************************************************ + * ICPanel_PersistFolder2_AddRef + */ +static ULONG WINAPI ICPanel_PersistFolder2_AddRef(IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(_IUnknown_(This)); +} + +/************************************************************************ + * ISFPersistFolder_Release + */ +static ULONG WINAPI ICPanel_PersistFolder2_Release(IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_Release(_IUnknown_(This)); +} + +/************************************************************************ + * ICPanel_PersistFolder2_GetClassID + */ +static HRESULT WINAPI ICPanel_PersistFolder2_GetClassID(IPersistFolder2 * iface, CLSID * lpClassId) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + if (!lpClassId) + return E_POINTER; + *lpClassId = CLSID_ControlPanel; + + return S_OK; +} + +/************************************************************************ + * ICPanel_PersistFolder2_Initialize + * + * NOTES: it makes no sense to change the pidl + */ +static HRESULT WINAPI ICPanel_PersistFolder2_Initialize(IPersistFolder2 * iface, LPCITEMIDLIST pidl) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + TRACE("(%p)->(%p)\n", This, pidl); + return E_NOTIMPL; +} + +/************************************************************************** + * IPersistFolder2_fnGetCurFolder + */ +static HRESULT WINAPI ICPanel_PersistFolder2_GetCurFolder(IPersistFolder2 * iface, LPITEMIDLIST * pidl) +{ + _ICOM_THIS_From_IPersistFolder2(ICPanelImpl, iface); + + TRACE("(%p)->(%p)\n", This, pidl); + + if (!pidl) + return E_POINTER; + *pidl = ILClone(This->pidlRoot); + return S_OK; +} + +static IPersistFolder2Vtbl vt_PersistFolder2 = +{ + + ICPanel_PersistFolder2_QueryInterface, + ICPanel_PersistFolder2_AddRef, + ICPanel_PersistFolder2_Release, + ICPanel_PersistFolder2_GetClassID, + ICPanel_PersistFolder2_Initialize, + ICPanel_PersistFolder2_GetCurFolder +}; + +HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex) +{ + PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); + + if (!pcpanel) + return E_INVALIDARG; + + lstrcpyA(szIconFile, pcpanel->szName); + *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; + + return S_OK; +} + +HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex) +{ + PIDLCPanelStruct* pcpanel = _ILGetCPanelPointer(pidl); + + if (!pcpanel) + return E_INVALIDARG; + + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, szIconFile, cchMax); + *piIndex = pcpanel->iconIdx!=-1? pcpanel->iconIdx: 0; + + return S_OK; +} + + +/************************************************************************** +* IShellExecuteHookW Implementation +*/ + +static HRESULT WINAPI IShellExecuteHookW_fnQueryInterface(IShellExecuteHookW* iface, REFIID riid, void** ppvObject) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnAddRef(IShellExecuteHookW* iface) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(This->pUnkOuter); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookW_fnRelease(IShellExecuteHookW* iface) +{ + _ICOM_THIS_From_IShellExecuteHookW(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->pUnkOuter); +} + +static HRESULT WINAPI IShellExecuteHookW_fnExecute(IShellExecuteHookW* iface, LPSHELLEXECUTEINFOW psei) +{ + static const WCHAR wCplopen[] = {'c','p','l','o','p','e','n','\0'}; + ICPanelImpl *This = (ICPanelImpl *)iface; + + SHELLEXECUTEINFOW sei_tmp; + PIDLCPanelStruct* pcpanel; + WCHAR path[MAX_PATH]; + BOOL ret; + int l; + + TRACE("(%p)->execute(%p)\n", This, psei); + + if (!psei) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); + + if (!pcpanel) + return E_INVALIDARG; + + path[0] = '\"'; + /* Return value from MultiByteToWideChar includes terminating NUL, which + * compensates for the starting double quote we just put in */ + l = MultiByteToWideChar(CP_ACP, 0, pcpanel->szName, -1, path+1, MAX_PATH); + + /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ + path[l++] = '"'; + path[l++] = ' '; + + MultiByteToWideChar(CP_ACP, 0, pcpanel->szName+pcpanel->offsDispName, -1, path+l, MAX_PATH); + + memcpy(&sei_tmp, psei, sizeof(sei_tmp)); + sei_tmp.lpFile = path; + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + sei_tmp.lpVerb = wCplopen; + + ret = ShellExecuteExW(&sei_tmp); + if (ret) + return S_OK; + else + return S_FALSE; +} + +static IShellExecuteHookWVtbl vt_ShellExecuteHookW = +{ + + IShellExecuteHookW_fnQueryInterface, + IShellExecuteHookW_fnAddRef, + IShellExecuteHookW_fnRelease, + + IShellExecuteHookW_fnExecute +}; + + +/************************************************************************** +* IShellExecuteHookA Implementation +*/ + +static HRESULT WINAPI IShellExecuteHookA_fnQueryInterface(IShellExecuteHookA* iface, REFIID riid, void** ppvObject) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnAddRef(IShellExecuteHookA* iface) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef(This->pUnkOuter); +} + +static ULONG STDMETHODCALLTYPE IShellExecuteHookA_fnRelease(IShellExecuteHookA* iface) +{ + _ICOM_THIS_From_IShellExecuteHookA(ICPanelImpl, iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->pUnkOuter); +} + +static HRESULT WINAPI IShellExecuteHookA_fnExecute(IShellExecuteHookA* iface, LPSHELLEXECUTEINFOA psei) +{ + ICPanelImpl *This = (ICPanelImpl *)iface; + + SHELLEXECUTEINFOA sei_tmp; + PIDLCPanelStruct* pcpanel; + char path[MAX_PATH]; + BOOL ret; + + TRACE("(%p)->execute(%p)\n", This, psei); + + if (!psei) + return E_INVALIDARG; + + pcpanel = _ILGetCPanelPointer(ILFindLastID(psei->lpIDList)); + + if (!pcpanel) + return E_INVALIDARG; + + path[0] = '\"'; + lstrcpyA(path+1, pcpanel->szName); + + /* pass applet name to Control_RunDLL to distinguish between applets in one .cpl file */ + lstrcatA(path, "\" "); + lstrcatA(path, pcpanel->szName+pcpanel->offsDispName); + + memcpy(&sei_tmp, psei, sizeof(sei_tmp)); + sei_tmp.lpFile = path; + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + + ret = ShellExecuteExA(&sei_tmp); + if (ret) + return S_OK; + else + return S_FALSE; +} + +static IShellExecuteHookAVtbl vt_ShellExecuteHookA = +{ + + IShellExecuteHookA_fnQueryInterface, + IShellExecuteHookA_fnAddRef, + IShellExecuteHookA_fnRelease, + + IShellExecuteHookA_fnExecute +}; diff --git a/reactos/lib/shell32/dataobject.c b/reactos/lib/shell32/dataobject.c index e104e5abf2c..96adeb04a40 100644 --- a/reactos/lib/shell32/dataobject.c +++ b/reactos/lib/shell32/dataobject.c @@ -1,458 +1,458 @@ -/* - * IEnumFORMATETC, IDataObject - * - * selecting and droping objects within the shell and/or common dialogs - * - * Copyright 1998, 1999 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "winerror.h" -#include "shell32_main.h" -#include "wine/debug.h" -#include "undocshell.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/*********************************************************************** -* IEnumFORMATETC implementation -*/ - -typedef struct -{ - /* IUnknown fields */ - IEnumFORMATETCVtbl *lpVtbl; - DWORD ref; - /* IEnumFORMATETC fields */ - UINT posFmt; - UINT countFmt; - LPFORMATETC pFmt; -} IEnumFORMATETCImpl; - -static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj); -static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface); -static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface); -static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed); -static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt); -static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface); -static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum); - -static struct IEnumFORMATETCVtbl efvt = -{ - IEnumFORMATETC_fnQueryInterface, - IEnumFORMATETC_fnAddRef, - IEnumFORMATETC_fnRelease, - IEnumFORMATETC_fnNext, - IEnumFORMATETC_fnSkip, - IEnumFORMATETC_fnReset, - IEnumFORMATETC_fnClone -}; - -LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[]) -{ - IEnumFORMATETCImpl* ef; - DWORD size=cfmt * sizeof(FORMATETC); - - ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl)); - - if(ef) - { - ef->ref=1; - ef->lpVtbl=&efvt; - - ef->countFmt = cfmt; - ef->pFmt = SHAlloc (size); - - if (ef->pFmt) - { - memcpy(ef->pFmt, afmt, size); - } - } - - TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt); - return (LPENUMFORMATETC)ef; -} - -static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IEnumFORMATETC)) - { - *ppvObj = (IEnumFORMATETC*)This; - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)(*ppvObj)); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; - -} - -static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->(count=%lu)\n",This, This->ref); - return ++(This->ref); -} - -static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IEnumFORMATETC(%p)\n",This); - if (This->pFmt) - { - SHFree (This->pFmt); - } - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - UINT i; - - TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt); - - if(!This->pFmt)return S_FALSE; - if(!rgelt) return E_INVALIDARG; - if (pceltFethed) *pceltFethed = 0; - - for(i = 0; This->posFmt < This->countFmt && celt > i; i++) - { - *rgelt++ = This->pFmt[This->posFmt++]; - } - - if (pceltFethed) *pceltFethed = i; - - return ((i == celt) ? S_OK : S_FALSE); -} - -static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->(num=%lu)\n", This, celt); - - if((This->posFmt + celt) >= This->countFmt) return S_FALSE; - This->posFmt += celt; - return S_OK; -} - -static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->()\n", This); - - This->posFmt = 0; - return S_OK; -} - -static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum) -{ - IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; - TRACE("(%p)->(ppenum=%p)\n", This, ppenum); - - if (!ppenum) return E_INVALIDARG; - *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt); - if(*ppenum) - IEnumFORMATETC_fnSkip(*ppenum, This->posFmt); - return S_OK; -} - - -/*********************************************************************** -* IDataObject implementation -*/ - -/* number of supported formats */ -#define MAX_FORMATS 4 - -typedef struct -{ - /* IUnknown fields */ - IDataObjectVtbl *lpVtbl; - DWORD ref; - - /* IDataObject fields */ - LPITEMIDLIST pidl; - LPITEMIDLIST * apidl; - UINT cidl; - - FORMATETC pFormatEtc[MAX_FORMATS]; - UINT cfShellIDList; - UINT cfFileNameA; - UINT cfFileNameW; - -} IDataObjectImpl; - -static struct IDataObjectVtbl dtovt; - -/************************************************************************** -* IDataObject_Constructor -*/ -LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl) -{ - IDataObjectImpl* dto; - - dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl)); - - if (dto) - { - dto->ref = 1; - dto->lpVtbl = &dtovt; - dto->pidl = ILClone(pMyPidl); - dto->apidl = _ILCopyaPidl(apidl, cidl); - dto->cidl = cidl; - - dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); - dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); - dto->cfFileNameW = RegisterClipboardFormatA(CFSTR_FILENAMEW); - InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL); - InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL); - } - - TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl); - return (LPDATAOBJECT)dto; -} - -/*************************************************************************** -* IDataObject_QueryInterface -*/ -static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/ - { - *ppvObj = (IDataObject*)This; - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* IDataObject_AddRef -*/ -static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - TRACE("(%p)->(count=%lu)\n",This, This->ref); - return ++(This->ref); -} - -/************************************************************************** -* IDataObject_Release -*/ -static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IDataObject(%p)\n",This); - _ILFreeaPidl(This->apidl, This->cidl); - ILFree(This->pidl), - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -/************************************************************************** -* IDataObject_fnGetData -*/ -static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - - char szTemp[256]; - - szTemp[0]=0; - GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256); - TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp); - - if (pformatetcIn->cfFormat == This->cfShellIDList) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == CF_HDROP) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == This->cfFileNameA) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->u.hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl); - } - else if (pformatetcIn->cfFormat == This->cfFileNameW) - { - if (This->cidl < 1) return(E_UNEXPECTED); - pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl); - } - else - { - FIXME("-- expected clipformat not implemented\n"); - return (E_INVALIDARG); - } - if (pmedium->u.hGlobal) - { - pmedium->tymed = TYMED_HGLOBAL; - pmedium->pUnkForRelease = NULL; - return S_OK; - } - return E_OUTOFMEMORY; -} - -static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - UINT i; - - TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed); - - if(!(DVASPECT_CONTENT & pformatetc->dwAspect)) - return DV_E_DVASPECT; - - /* check our formats table what we have */ - for (i=0; ipFormatEtc[i].cfFormat == pformatetc->cfFormat) - && (This->pFormatEtc[i].tymed == pformatetc->tymed)) - { - return S_OK; - } - } - - return DV_E_TYMED; -} - -static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - - TRACE("(%p)->()\n", This); - *ppenumFormatEtc=NULL; - - /* only get data */ - if (DATADIR_GET == dwDirection) - { - *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc); - return (*ppenumFormatEtc) ? S_OK : E_FAIL; - } - - return E_NOTIMPL; -} - -static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise) -{ - IDataObjectImpl *This = (IDataObjectImpl *)iface; - FIXME("(%p)->()\n", This); - return E_NOTIMPL; -} - -static struct IDataObjectVtbl dtovt = -{ - IDataObject_fnQueryInterface, - IDataObject_fnAddRef, - IDataObject_fnRelease, - IDataObject_fnGetData, - IDataObject_fnGetDataHere, - IDataObject_fnQueryGetData, - IDataObject_fnGetCanonicalFormatEtc, - IDataObject_fnSetData, - IDataObject_fnEnumFormatEtc, - IDataObject_fnDAdvise, - IDataObject_fnDUnadvise, - IDataObject_fnEnumDAdvise -}; +/* + * IEnumFORMATETC, IDataObject + * + * selecting and droping objects within the shell and/or common dialogs + * + * Copyright 1998, 1999 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "wingdi.h" +#include "pidl.h" +#include "winerror.h" +#include "shell32_main.h" +#include "wine/debug.h" +#include "undocshell.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/*********************************************************************** +* IEnumFORMATETC implementation +*/ + +typedef struct +{ + /* IUnknown fields */ + IEnumFORMATETCVtbl *lpVtbl; + DWORD ref; + /* IEnumFORMATETC fields */ + UINT posFmt; + UINT countFmt; + LPFORMATETC pFmt; +} IEnumFORMATETCImpl; + +static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj); +static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface); +static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface); +static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed); +static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt); +static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface); +static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum); + +static struct IEnumFORMATETCVtbl efvt = +{ + IEnumFORMATETC_fnQueryInterface, + IEnumFORMATETC_fnAddRef, + IEnumFORMATETC_fnRelease, + IEnumFORMATETC_fnNext, + IEnumFORMATETC_fnSkip, + IEnumFORMATETC_fnReset, + IEnumFORMATETC_fnClone +}; + +LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[]) +{ + IEnumFORMATETCImpl* ef; + DWORD size=cfmt * sizeof(FORMATETC); + + ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl)); + + if(ef) + { + ef->ref=1; + ef->lpVtbl=&efvt; + + ef->countFmt = cfmt; + ef->pFmt = SHAlloc (size); + + if (ef->pFmt) + { + memcpy(ef->pFmt, afmt, size); + } + } + + TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt); + return (LPENUMFORMATETC)ef; +} + +static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IEnumFORMATETC)) + { + *ppvObj = (IEnumFORMATETC*)This; + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)(*ppvObj)); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; + +} + +static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->(count=%lu)\n",This, This->ref); + return ++(This->ref); +} + +static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IEnumFORMATETC(%p)\n",This); + if (This->pFmt) + { + SHFree (This->pFmt); + } + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + UINT i; + + TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt); + + if(!This->pFmt)return S_FALSE; + if(!rgelt) return E_INVALIDARG; + if (pceltFethed) *pceltFethed = 0; + + for(i = 0; This->posFmt < This->countFmt && celt > i; i++) + { + *rgelt++ = This->pFmt[This->posFmt++]; + } + + if (pceltFethed) *pceltFethed = i; + + return ((i == celt) ? S_OK : S_FALSE); +} + +static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->(num=%lu)\n", This, celt); + + if((This->posFmt + celt) >= This->countFmt) return S_FALSE; + This->posFmt += celt; + return S_OK; +} + +static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->()\n", This); + + This->posFmt = 0; + return S_OK; +} + +static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum) +{ + IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface; + TRACE("(%p)->(ppenum=%p)\n", This, ppenum); + + if (!ppenum) return E_INVALIDARG; + *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt); + if(*ppenum) + IEnumFORMATETC_fnSkip(*ppenum, This->posFmt); + return S_OK; +} + + +/*********************************************************************** +* IDataObject implementation +*/ + +/* number of supported formats */ +#define MAX_FORMATS 4 + +typedef struct +{ + /* IUnknown fields */ + IDataObjectVtbl *lpVtbl; + DWORD ref; + + /* IDataObject fields */ + LPITEMIDLIST pidl; + LPITEMIDLIST * apidl; + UINT cidl; + + FORMATETC pFormatEtc[MAX_FORMATS]; + UINT cfShellIDList; + UINT cfFileNameA; + UINT cfFileNameW; + +} IDataObjectImpl; + +static struct IDataObjectVtbl dtovt; + +/************************************************************************** +* IDataObject_Constructor +*/ +LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl) +{ + IDataObjectImpl* dto; + + dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl)); + + if (dto) + { + dto->ref = 1; + dto->lpVtbl = &dtovt; + dto->pidl = ILClone(pMyPidl); + dto->apidl = _ILCopyaPidl(apidl, cidl); + dto->cidl = cidl; + + dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); + dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); + dto->cfFileNameW = RegisterClipboardFormatA(CFSTR_FILENAMEW); + InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL); + } + + TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl); + return (LPDATAOBJECT)dto; +} + +/*************************************************************************** +* IDataObject_QueryInterface +*/ +static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/ + { + *ppvObj = (IDataObject*)This; + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** +* IDataObject_AddRef +*/ +static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + TRACE("(%p)->(count=%lu)\n",This, This->ref); + return ++(This->ref); +} + +/************************************************************************** +* IDataObject_Release +*/ +static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IDataObject(%p)\n",This); + _ILFreeaPidl(This->apidl, This->cidl); + ILFree(This->pidl), + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* IDataObject_fnGetData +*/ +static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + + char szTemp[256]; + + szTemp[0]=0; + GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256); + TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp); + + if (pformatetcIn->cfFormat == This->cfShellIDList) + { + if (This->cidl < 1) return(E_UNEXPECTED); + pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl); + } + else if (pformatetcIn->cfFormat == CF_HDROP) + { + if (This->cidl < 1) return(E_UNEXPECTED); + pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl); + } + else if (pformatetcIn->cfFormat == This->cfFileNameA) + { + if (This->cidl < 1) return(E_UNEXPECTED); + pmedium->u.hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl); + } + else if (pformatetcIn->cfFormat == This->cfFileNameW) + { + if (This->cidl < 1) return(E_UNEXPECTED); + pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl); + } + else + { + FIXME("-- expected clipformat not implemented\n"); + return (E_INVALIDARG); + } + if (pmedium->u.hGlobal) + { + pmedium->tymed = TYMED_HGLOBAL; + pmedium->pUnkForRelease = NULL; + return S_OK; + } + return E_OUTOFMEMORY; +} + +static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + UINT i; + + TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed); + + if(!(DVASPECT_CONTENT & pformatetc->dwAspect)) + return DV_E_DVASPECT; + + /* check our formats table what we have */ + for (i=0; ipFormatEtc[i].cfFormat == pformatetc->cfFormat) + && (This->pFormatEtc[i].tymed == pformatetc->tymed)) + { + return S_OK; + } + } + + return DV_E_TYMED; +} + +static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + + TRACE("(%p)->()\n", This); + *ppenumFormatEtc=NULL; + + /* only get data */ + if (DATADIR_GET == dwDirection) + { + *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc); + return (*ppenumFormatEtc) ? S_OK : E_FAIL; + } + + return E_NOTIMPL; +} + +static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise) +{ + IDataObjectImpl *This = (IDataObjectImpl *)iface; + FIXME("(%p)->()\n", This); + return E_NOTIMPL; +} + +static struct IDataObjectVtbl dtovt = +{ + IDataObject_fnQueryInterface, + IDataObject_fnAddRef, + IDataObject_fnRelease, + IDataObject_fnGetData, + IDataObject_fnGetDataHere, + IDataObject_fnQueryGetData, + IDataObject_fnGetCanonicalFormatEtc, + IDataObject_fnSetData, + IDataObject_fnEnumFormatEtc, + IDataObject_fnDAdvise, + IDataObject_fnDUnadvise, + IDataObject_fnEnumDAdvise +}; diff --git a/reactos/lib/shell32/debughlp.c b/reactos/lib/shell32/debughlp.c index fc43cbb9504..181410390f5 100644 --- a/reactos/lib/shell32/debughlp.c +++ b/reactos/lib/shell32/debughlp.c @@ -1,338 +1,338 @@ -/* - * Helper functions for debugging - * - * Copyright 1998, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "shlguid.h" -#include "shldisp.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "docobj.h" -#include "shell32_main.h" - - -WINE_DEFAULT_DEBUG_CHANNEL(pidl); - -static -LPITEMIDLIST _dbg_ILGetNext(LPCITEMIDLIST pidl) -{ - WORD len; - - if(pidl) - { - len = pidl->mkid.cb; - if (len) - { - return (LPITEMIDLIST) (((LPBYTE)pidl)+len); - } - } - return NULL; -} - -static -BOOL _dbg_ILIsDesktop(LPCITEMIDLIST pidl) -{ - return ( !pidl || (pidl && pidl->mkid.cb == 0x00) ); -} - -static -LPPIDLDATA _dbg_ILGetDataPointer(LPCITEMIDLIST pidl) -{ - if(pidl && pidl->mkid.cb != 0x00) - return (LPPIDLDATA) &(pidl->mkid.abID); - return NULL; -} - -static -LPSTR _dbg_ILGetTextPointer(LPCITEMIDLIST pidl) -{ - LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl); - - if (pdata) - { - switch (pdata->type) - { - case PT_GUID: - case PT_SHELLEXT: - case PT_YAGUID: - return NULL; - - case PT_DRIVE: - case PT_DRIVE1: - case PT_DRIVE2: - case PT_DRIVE3: - return (LPSTR)&(pdata->u.drive.szDriveName); - - case PT_FOLDER: - case PT_FOLDER1: - case PT_VALUE: - case PT_IESPECIAL1: - case PT_IESPECIAL2: - return (LPSTR)&(pdata->u.file.szNames); - - case PT_WORKGRP: - case PT_COMP: - case PT_NETWORK: - case PT_NETPROVIDER: - case PT_SHARE: - return (LPSTR)&(pdata->u.network.szNames); - } - } - return NULL; -} - -static -LPSTR _dbg_ILGetSTextPointer(LPCITEMIDLIST pidl) -{ - LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl); - - if (pdata) - { - switch (pdata->type) - { - case PT_FOLDER: - case PT_VALUE: - case PT_IESPECIAL1: - case PT_IESPECIAL2: - return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1); - - case PT_WORKGRP: - return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1); - } - } - return NULL; -} - -static -IID* _dbg_ILGetGUIDPointer(LPCITEMIDLIST pidl) -{ - LPPIDLDATA pdata =_ILGetDataPointer(pidl); - - if (pdata) - { - switch (pdata->type) - { - case PT_SHELLEXT: - case PT_GUID: - return &(pdata->u.guid.guid); - } - } - return NULL; -} - -static -DWORD _dbg_ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize) -{ - DWORD dwReturn=0; - LPSTR szSrc; - GUID const * riid; - char szTemp[MAX_PATH]; - - if (!pidl) return 0; - - if (szOut) - *szOut = 0; - - if (_dbg_ILIsDesktop(pidl)) - { - /* desktop */ - if (szOut) strncpy(szOut, "Desktop", uOutSize); - dwReturn = strlen ("Desktop"); - } - else if (( szSrc = _dbg_ILGetTextPointer(pidl) )) - { - /* filesystem */ - if (szOut) strncpy(szOut, szSrc, uOutSize); - dwReturn = strlen(szSrc); - } - else if (( riid = _dbg_ILGetGUIDPointer(pidl) )) - { - if (szOut) - sprintf( szOut, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - riid->Data1, riid->Data2, riid->Data3, - riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], - riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); - dwReturn = strlen (szTemp); - } - return dwReturn; -} - - - - -void pdump (LPCITEMIDLIST pidl) -{ - LPCITEMIDLIST pidltemp = pidl; - - if (!TRACE_ON(pidl)) return; - - if (! pidltemp) - { - MESSAGE ("-------- pidl=NULL (Desktop)\n"); - } - else - { - MESSAGE ("-------- pidl=%p\n", pidl); - if (pidltemp->mkid.cb) - { - do - { - DWORD dwAttrib = 0; - LPPIDLDATA pData = _dbg_ILGetDataPointer(pidltemp); - DWORD type = pData->type; - LPSTR szLongName = _dbg_ILGetTextPointer(pidltemp); - LPSTR szShortName = _dbg_ILGetSTextPointer(pidltemp); - char szName[MAX_PATH]; - - _dbg_ILSimpleGetText(pidltemp, szName, MAX_PATH); - if( PT_FOLDER == type || PT_VALUE == type) - dwAttrib = pData->u.file.uFileAttribs; - - MESSAGE ("[%p] size=%04u type=%lx attr=0x%08lx name=\"%s\" (%s,%s)\n", - pidltemp, pidltemp->mkid.cb,type,dwAttrib,szName,debugstr_a(szLongName), debugstr_a(szShortName)); - - pidltemp = _dbg_ILGetNext(pidltemp); - - } while (pidltemp->mkid.cb); - } - else - { - MESSAGE ("empty pidl (Desktop)\n"); - } - pcheck(pidl); - } -} -#define BYTES_PRINTED 32 -BOOL pcheck (LPCITEMIDLIST pidl) -{ - DWORD type, ret=TRUE; - LPCITEMIDLIST pidltemp = pidl; - - if (pidltemp && pidltemp->mkid.cb) - { do - { type = _dbg_ILGetDataPointer(pidltemp)->type; - switch (type) - { case PT_CPLAPPLET: - case PT_GUID: - case PT_SHELLEXT: - case PT_DRIVE: - case PT_DRIVE1: - case PT_DRIVE2: - case PT_DRIVE3: - case PT_FOLDER: - case PT_VALUE: - case PT_FOLDER1: - case PT_WORKGRP: - case PT_COMP: - case PT_NETPROVIDER: - case PT_NETWORK: - case PT_IESPECIAL1: - case PT_YAGUID: - case PT_IESPECIAL2: - case PT_SHARE: - break; - default: - { - char szTemp[BYTES_PRINTED*4 + 1]; - int i; - unsigned char c; - - memset(szTemp, ' ', BYTES_PRINTED*4 + 1); - for ( i = 0; (imkid.cb) && (i>4)>9)? (c>>4)+55 : (c>>4)+48; - szTemp[i*3+1] = ((0x0F&c)>9)? (0x0F&c)+55 : (0x0F&c)+48; - szTemp[i*3+2] = ' '; - szTemp[i+BYTES_PRINTED*3] = (c>=0x20 && c <=0x80) ? c : '.'; - } - szTemp[BYTES_PRINTED*4] = 0x00; - ERR("unknown IDLIST %p [%p] size=%u type=%lx\n%s\n",pidl, pidltemp, pidltemp->mkid.cb,type, szTemp); - ret = FALSE; - } - } - pidltemp = _dbg_ILGetNext(pidltemp); - } while (pidltemp->mkid.cb); - } - return ret; -} - -static char shdebugstr_buf1[100]; -static char shdebugstr_buf2[100]; -static char * shdebugstr_buf = shdebugstr_buf1; - -static struct { - REFIID riid; - char *name; -} InterfaceDesc[] = { - {&IID_IUnknown, "IID_IUnknown"}, - {&IID_IClassFactory, "IID_IClassFactory"}, - {&IID_IShellView, "IID_IShellView"}, - {&IID_IOleCommandTarget, "IID_IOleCommandTarget"}, - {&IID_IDropTarget, "IID_IDropTarget"}, - {&IID_IDropSource, "IID_IDropSource"}, - {&IID_IViewObject, "IID_IViewObject"}, - {&IID_IContextMenu, "IID_IContextMenu"}, - {&IID_IShellExtInit, "IID_IShellExtInit"}, - {&IID_IShellFolder, "IID_IShellFolder"}, - {&IID_IShellFolder2, "IID_IShellFolder2"}, - {&IID_IPersist, "IID_IPersist"}, - {&IID_IPersistFolder, "IID_IPersistFolder"}, - {&IID_IPersistFolder2, "IID_IPersistFolder2"}, - {&IID_IPersistFolder3, "IID_IPersistFolder3"}, - {&IID_IExtractIconA, "IID_IExtractIconA"}, - {&IID_IExtractIconW, "IID_IExtractIconW"}, - {&IID_IDataObject, "IID_IDataObject"}, - {&IID_IAutoComplete, "IID_IAutoComplete"}, - {&IID_IAutoComplete2, "IID_IAutoComplete2"}, - {NULL,NULL}}; - -const char * shdebugstr_guid( const struct _GUID *id ) -{ - int i; - char* name = NULL; - char clsidbuf[100]; - - shdebugstr_buf = (shdebugstr_buf == shdebugstr_buf1) ? shdebugstr_buf2 : shdebugstr_buf1; - - if (!id) { - strcpy (shdebugstr_buf, "(null)"); - } else { - for (i=0;InterfaceDesc[i].riid && !name;i++) { - if (IsEqualIID(InterfaceDesc[i].riid, id)) name = InterfaceDesc[i].name; - } - if (!name) { - if (HCR_GetClassNameA(id, clsidbuf, 100)) - name = clsidbuf; - } - - sprintf( shdebugstr_buf, "\n\t{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} (%s)", - id->Data1, id->Data2, id->Data3, - id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], - id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], name ? name : "unknown" ); - } - return shdebugstr_buf; -} +/* + * Helper functions for debugging + * + * Copyright 1998, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "windef.h" +#include "wingdi.h" +#include "pidl.h" +#include "shlguid.h" +#include "shldisp.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "docobj.h" +#include "shell32_main.h" + + +WINE_DEFAULT_DEBUG_CHANNEL(pidl); + +static +LPITEMIDLIST _dbg_ILGetNext(LPCITEMIDLIST pidl) +{ + WORD len; + + if(pidl) + { + len = pidl->mkid.cb; + if (len) + { + return (LPITEMIDLIST) (((LPBYTE)pidl)+len); + } + } + return NULL; +} + +static +BOOL _dbg_ILIsDesktop(LPCITEMIDLIST pidl) +{ + return ( !pidl || (pidl && pidl->mkid.cb == 0x00) ); +} + +static +LPPIDLDATA _dbg_ILGetDataPointer(LPCITEMIDLIST pidl) +{ + if(pidl && pidl->mkid.cb != 0x00) + return (LPPIDLDATA) &(pidl->mkid.abID); + return NULL; +} + +static +LPSTR _dbg_ILGetTextPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl); + + if (pdata) + { + switch (pdata->type) + { + case PT_GUID: + case PT_SHELLEXT: + case PT_YAGUID: + return NULL; + + case PT_DRIVE: + case PT_DRIVE1: + case PT_DRIVE2: + case PT_DRIVE3: + return (LPSTR)&(pdata->u.drive.szDriveName); + + case PT_FOLDER: + case PT_FOLDER1: + case PT_VALUE: + case PT_IESPECIAL1: + case PT_IESPECIAL2: + return (LPSTR)&(pdata->u.file.szNames); + + case PT_WORKGRP: + case PT_COMP: + case PT_NETWORK: + case PT_NETPROVIDER: + case PT_SHARE: + return (LPSTR)&(pdata->u.network.szNames); + } + } + return NULL; +} + +static +LPSTR _dbg_ILGetSTextPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata =_dbg_ILGetDataPointer(pidl); + + if (pdata) + { + switch (pdata->type) + { + case PT_FOLDER: + case PT_VALUE: + case PT_IESPECIAL1: + case PT_IESPECIAL2: + return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1); + + case PT_WORKGRP: + return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1); + } + } + return NULL; +} + +static +IID* _dbg_ILGetGUIDPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata =_ILGetDataPointer(pidl); + + if (pdata) + { + switch (pdata->type) + { + case PT_SHELLEXT: + case PT_GUID: + return &(pdata->u.guid.guid); + } + } + return NULL; +} + +static +DWORD _dbg_ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize) +{ + DWORD dwReturn=0; + LPSTR szSrc; + GUID const * riid; + char szTemp[MAX_PATH]; + + if (!pidl) return 0; + + if (szOut) + *szOut = 0; + + if (_dbg_ILIsDesktop(pidl)) + { + /* desktop */ + if (szOut) strncpy(szOut, "Desktop", uOutSize); + dwReturn = strlen ("Desktop"); + } + else if (( szSrc = _dbg_ILGetTextPointer(pidl) )) + { + /* filesystem */ + if (szOut) strncpy(szOut, szSrc, uOutSize); + dwReturn = strlen(szSrc); + } + else if (( riid = _dbg_ILGetGUIDPointer(pidl) )) + { + if (szOut) + sprintf( szOut, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + riid->Data1, riid->Data2, riid->Data3, + riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], + riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); + dwReturn = strlen (szTemp); + } + return dwReturn; +} + + + + +void pdump (LPCITEMIDLIST pidl) +{ + LPCITEMIDLIST pidltemp = pidl; + + if (!TRACE_ON(pidl)) return; + + if (! pidltemp) + { + MESSAGE ("-------- pidl=NULL (Desktop)\n"); + } + else + { + MESSAGE ("-------- pidl=%p\n", pidl); + if (pidltemp->mkid.cb) + { + do + { + DWORD dwAttrib = 0; + LPPIDLDATA pData = _dbg_ILGetDataPointer(pidltemp); + DWORD type = pData->type; + LPSTR szLongName = _dbg_ILGetTextPointer(pidltemp); + LPSTR szShortName = _dbg_ILGetSTextPointer(pidltemp); + char szName[MAX_PATH]; + + _dbg_ILSimpleGetText(pidltemp, szName, MAX_PATH); + if( PT_FOLDER == type || PT_VALUE == type) + dwAttrib = pData->u.file.uFileAttribs; + + MESSAGE ("[%p] size=%04u type=%lx attr=0x%08lx name=\"%s\" (%s,%s)\n", + pidltemp, pidltemp->mkid.cb,type,dwAttrib,szName,debugstr_a(szLongName), debugstr_a(szShortName)); + + pidltemp = _dbg_ILGetNext(pidltemp); + + } while (pidltemp->mkid.cb); + } + else + { + MESSAGE ("empty pidl (Desktop)\n"); + } + pcheck(pidl); + } +} +#define BYTES_PRINTED 32 +BOOL pcheck (LPCITEMIDLIST pidl) +{ + DWORD type, ret=TRUE; + LPCITEMIDLIST pidltemp = pidl; + + if (pidltemp && pidltemp->mkid.cb) + { do + { type = _dbg_ILGetDataPointer(pidltemp)->type; + switch (type) + { case PT_CPLAPPLET: + case PT_GUID: + case PT_SHELLEXT: + case PT_DRIVE: + case PT_DRIVE1: + case PT_DRIVE2: + case PT_DRIVE3: + case PT_FOLDER: + case PT_VALUE: + case PT_FOLDER1: + case PT_WORKGRP: + case PT_COMP: + case PT_NETPROVIDER: + case PT_NETWORK: + case PT_IESPECIAL1: + case PT_YAGUID: + case PT_IESPECIAL2: + case PT_SHARE: + break; + default: + { + char szTemp[BYTES_PRINTED*4 + 1]; + int i; + unsigned char c; + + memset(szTemp, ' ', BYTES_PRINTED*4 + 1); + for ( i = 0; (imkid.cb) && (i>4)>9)? (c>>4)+55 : (c>>4)+48; + szTemp[i*3+1] = ((0x0F&c)>9)? (0x0F&c)+55 : (0x0F&c)+48; + szTemp[i*3+2] = ' '; + szTemp[i+BYTES_PRINTED*3] = (c>=0x20 && c <=0x80) ? c : '.'; + } + szTemp[BYTES_PRINTED*4] = 0x00; + ERR("unknown IDLIST %p [%p] size=%u type=%lx\n%s\n",pidl, pidltemp, pidltemp->mkid.cb,type, szTemp); + ret = FALSE; + } + } + pidltemp = _dbg_ILGetNext(pidltemp); + } while (pidltemp->mkid.cb); + } + return ret; +} + +static char shdebugstr_buf1[100]; +static char shdebugstr_buf2[100]; +static char * shdebugstr_buf = shdebugstr_buf1; + +static struct { + REFIID riid; + char *name; +} InterfaceDesc[] = { + {&IID_IUnknown, "IID_IUnknown"}, + {&IID_IClassFactory, "IID_IClassFactory"}, + {&IID_IShellView, "IID_IShellView"}, + {&IID_IOleCommandTarget, "IID_IOleCommandTarget"}, + {&IID_IDropTarget, "IID_IDropTarget"}, + {&IID_IDropSource, "IID_IDropSource"}, + {&IID_IViewObject, "IID_IViewObject"}, + {&IID_IContextMenu, "IID_IContextMenu"}, + {&IID_IShellExtInit, "IID_IShellExtInit"}, + {&IID_IShellFolder, "IID_IShellFolder"}, + {&IID_IShellFolder2, "IID_IShellFolder2"}, + {&IID_IPersist, "IID_IPersist"}, + {&IID_IPersistFolder, "IID_IPersistFolder"}, + {&IID_IPersistFolder2, "IID_IPersistFolder2"}, + {&IID_IPersistFolder3, "IID_IPersistFolder3"}, + {&IID_IExtractIconA, "IID_IExtractIconA"}, + {&IID_IExtractIconW, "IID_IExtractIconW"}, + {&IID_IDataObject, "IID_IDataObject"}, + {&IID_IAutoComplete, "IID_IAutoComplete"}, + {&IID_IAutoComplete2, "IID_IAutoComplete2"}, + {NULL,NULL}}; + +const char * shdebugstr_guid( const struct _GUID *id ) +{ + int i; + char* name = NULL; + char clsidbuf[100]; + + shdebugstr_buf = (shdebugstr_buf == shdebugstr_buf1) ? shdebugstr_buf2 : shdebugstr_buf1; + + if (!id) { + strcpy (shdebugstr_buf, "(null)"); + } else { + for (i=0;InterfaceDesc[i].riid && !name;i++) { + if (IsEqualIID(InterfaceDesc[i].riid, id)) name = InterfaceDesc[i].name; + } + if (!name) { + if (HCR_GetClassNameA(id, clsidbuf, 100)) + name = clsidbuf; + } + + sprintf( shdebugstr_buf, "\n\t{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} (%s)", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7], name ? name : "unknown" ); + } + return shdebugstr_buf; +} diff --git a/reactos/lib/shell32/debughlp.h b/reactos/lib/shell32/debughlp.h index d3819ab4583..87166e38ef5 100644 --- a/reactos/lib/shell32/debughlp.h +++ b/reactos/lib/shell32/debughlp.h @@ -1,35 +1,35 @@ -/* - * Definitions for debugging - * - * Copyright 1998, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SHELL32_DEBUGHLP_H -#define __WINE_SHELL32_DEBUGHLP_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "shlobj.h" - -extern void pdump (LPCITEMIDLIST pidl); -extern BOOL pcheck (LPCITEMIDLIST pidl); -extern const char * shdebugstr_guid( const struct _GUID *id ); - -#endif /* __WINE_SHELL32_DEBUGHLP_H */ +/* + * Definitions for debugging + * + * Copyright 1998, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELL32_DEBUGHLP_H +#define __WINE_SHELL32_DEBUGHLP_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "shlobj.h" + +extern void pdump (LPCITEMIDLIST pidl); +extern BOOL pcheck (LPCITEMIDLIST pidl); +extern const char * shdebugstr_guid( const struct _GUID *id ); + +#endif /* __WINE_SHELL32_DEBUGHLP_H */ diff --git a/reactos/lib/shell32/dialogs.c b/reactos/lib/shell32/dialogs.c index d5a31bf86e6..522e005819d 100644 --- a/reactos/lib/shell32/dialogs.c +++ b/reactos/lib/shell32/dialogs.c @@ -1,446 +1,446 @@ -/* - * common shell dialogs - * - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" -#include "commdlg.h" -#include "wine/debug.h" - -#include "shellapi.h" -#include "shlobj.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "undocshell.h" - -typedef struct - { - HWND hwndOwner ; - HICON hIcon ; - LPCSTR lpstrDirectory ; - LPCSTR lpstrTitle ; - LPCSTR lpstrDescription ; - UINT uFlags ; - } RUNFILEDLGPARAMS ; - -typedef BOOL (*LPFNOFN) (OPENFILENAMEA *) ; - -WINE_DEFAULT_DEBUG_CHANNEL(shell); -INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ; -void FillList (HWND, char *) ; - - -/************************************************************************* - * PickIconDlg [SHELL32.62] - * - */ -BOOL WINAPI PickIconDlg( - HWND hwndOwner, - LPSTR lpstrFile, - DWORD nMaxFile, - LPDWORD lpdwIconIndex) -{ - FIXME("(%p,%s,%08lx,%p):stub.\n", - hwndOwner, lpstrFile, nMaxFile,lpdwIconIndex); - return 0xffffffff; -} - -/************************************************************************* - * RunFileDlg [SHELL32.61] - * - * NOTES - * Original name: RunFileDlg (exported by ordinal) - */ -void WINAPI RunFileDlg( - HWND hwndOwner, - HICON hIcon, - LPCSTR lpstrDirectory, - LPCSTR lpstrTitle, - LPCSTR lpstrDescription, - UINT uFlags) -{ - - RUNFILEDLGPARAMS rfdp; - HRSRC hRes; - LPVOID template; - TRACE("\n"); - - rfdp.hwndOwner = hwndOwner; - rfdp.hIcon = hIcon; - rfdp.lpstrDirectory = lpstrDirectory; - rfdp.lpstrTitle = lpstrTitle; - rfdp.lpstrDescription = lpstrDescription; - rfdp.uFlags = uFlags; - - if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_RUN_DLG", (LPSTR)RT_DIALOG))) - { - MessageBoxA (hwndOwner, "Couldn't find dialog.", "Nix", MB_OK) ; - return; - } - if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes))) - { - MessageBoxA (hwndOwner, "Couldn't load dialog.", "Nix", MB_OK) ; - return; - } - - DialogBoxIndirectParamA((HINSTANCE)GetWindowLongPtrW( hwndOwner, - GWLP_HINSTANCE ), - template, hwndOwner, RunDlgProc, (LPARAM)&rfdp); - -} - -/* Dialog procedure for RunFileDlg */ -INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) - { - int ic ; - char *psz, szMsg[256] ; - static RUNFILEDLGPARAMS *prfdp = NULL ; - - switch (message) - { - case WM_INITDIALOG : - prfdp = (RUNFILEDLGPARAMS *)lParam ; - SetWindowTextA (hwnd, prfdp->lpstrTitle) ; - SetClassLongA (hwnd, GCL_HICON, (LPARAM)prfdp->hIcon) ; - SendMessageA (GetDlgItem (hwnd, 12297), STM_SETICON, - (WPARAM)LoadIconA (NULL, (LPSTR)IDI_WINLOGO), 0); - FillList (GetDlgItem (hwnd, 12298), NULL) ; - SetFocus (GetDlgItem (hwnd, 12298)) ; - return TRUE ; - - case WM_COMMAND : - switch (LOWORD (wParam)) - { - case IDOK : - { - HWND htxt = NULL ; - if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298)))) - { - psz = HeapAlloc( GetProcessHeap(), 0, (ic + 2) ); - GetWindowTextA (htxt, psz, ic + 1) ; - - if (ShellExecuteA(NULL, "open", psz, NULL, NULL, SW_SHOWNORMAL) < (HINSTANCE)33) - { - char *pszSysMsg = NULL ; - FormatMessageA ( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError (), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&pszSysMsg, 0, NULL - ) ; - sprintf (szMsg, "Error: %s", pszSysMsg) ; - LocalFree ((HLOCAL)pszSysMsg) ; - MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ; - - HeapFree(GetProcessHeap(), 0, psz); - SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - return TRUE ; - } - FillList (htxt, psz) ; - HeapFree(GetProcessHeap(), 0, psz); - EndDialog (hwnd, 0) ; - } - } - - case IDCANCEL : - EndDialog (hwnd, 0) ; - return TRUE ; - - case 12288 : - { - HMODULE hComdlg = NULL ; - LPFNOFN ofnProc = NULL ; - static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ; - static OPENFILENAMEA ofn = - { - sizeof (OPENFILENAMEA), - NULL, - NULL, - "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0", - NULL, - 0, - 0, - szFName, - 1023, - szFileTitle, - 255, - (LPCSTR)szInitDir, - "Browse", - OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, - 0, - 0, - NULL, - 0, - (LPOFNHOOKPROC)NULL, - NULL - } ; - - ofn.hwndOwner = hwnd ; - - if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0))) - { - MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ; - return TRUE ; - } - - if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA"))) - { - MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ; - return TRUE ; - } - - ofnProc (&ofn) ; - - SetFocus (GetDlgItem (hwnd, IDOK)) ; - SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ; - SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - SetFocus (GetDlgItem (hwnd, IDOK)) ; - - FreeLibrary (hComdlg) ; - - return TRUE ; - } - } - return TRUE ; - } - return FALSE ; - } - -/* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */ -void FillList (HWND hCb, char *pszLatest) - { - HKEY hkey ; -/* char szDbgMsg[256] = "" ; */ - char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ; - DWORD icList = 0, icCmd = 0 ; - UINT Nix ; - - SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ; - - if (ERROR_SUCCESS != RegCreateKeyExA ( - HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", - 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL)) - MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ; - - RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ; - - if (icList > 0) - { - pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; - if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, pszList, &icList)) - MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ; - } - else - { - icList = 1 ; - pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; - pszList[0] = 0 ; - } - - for (Nix = 0 ; Nix < icList - 1 ; Nix++) - { - if (pszList[Nix] > cMax) - cMax = pszList[Nix] ; - - szIndex[0] = pszList[Nix] ; - - if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd)) - MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ; - if( pszCmd ) - pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ; - else - pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ; - if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, pszCmd, &icCmd)) - MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ; - - if (NULL != pszLatest) - { - if (!strcasecmp (pszCmd, pszLatest)) - { - /* - sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ; - MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; - */ - SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ; - SetWindowTextA (hCb, pszCmd) ; - SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - - cMatch = pszList[Nix] ; - memmove (&pszList[1], pszList, Nix) ; - pszList[0] = cMatch ; - continue ; - } - } - - if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest) - { - /* - sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ; - MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; - */ - SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ; - if (!Nix) - { - SetWindowTextA (hCb, pszCmd) ; - SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - } - - } - else - { - /* - sprintf (szDbgMsg, "Doing loop thing.\n") ; - MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; - */ - SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; - SetWindowTextA (hCb, pszLatest) ; - SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - - cMatch = pszList[Nix] ; - memmove (&pszList[1], pszList, Nix) ; - pszList[0] = cMatch ; - szIndex[0] = cMatch ; - RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ; - } - } - - if (!cMatch && NULL != pszLatest) - { - /* - sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ; - MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; - */ - SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; - SetWindowTextA (hCb, pszLatest) ; - SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; - - cMatch = ++cMax ; - if( pszList ) - pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ; - else - pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ; - memmove (&pszList[1], pszList, icList - 1) ; - pszList[0] = cMatch ; - szIndex[0] = cMatch ; - RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ; - } - - RegSetValueExA (hkey, "MRUList", 0, REG_SZ, pszList, strlen (pszList) + 1) ; - - HeapFree( GetProcessHeap(), 0, pszCmd) ; - HeapFree( GetProcessHeap(), 0, pszList) ; - } - - -/************************************************************************* - * ConfirmDialog [internal] - * - * Put up a confirm box, return TRUE if the user confirmed - */ -static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId) -{ - WCHAR Prompt[256]; - WCHAR Title[256]; - - LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR)); - LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR)); - return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES; -} - - -/************************************************************************* - * RestartDialogEx [SHELL32.730] - */ - -int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason) -{ - TRACE("(%p)\n", hWndOwner); - - /*FIXME: use uReason */ - - if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE)) - { - HANDLE hToken; - TOKEN_PRIVILEGES npr; - - /* enable shutdown privilege for current process */ - if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); - npr.PrivilegeCount = 1; - npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); - CloseHandle(hToken); - } - ExitWindowsEx(EWX_REBOOT, 0); - } - - return 0; -} - - -/************************************************************************* - * RestartDialog [SHELL32.59] - */ - -int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags) -{ - return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0); -} - - -/************************************************************************* - * ExitWindowsDialog [SHELL32.60] - * - * NOTES - * exported by ordinal - */ -void WINAPI ExitWindowsDialog (HWND hWndOwner) -{ - TRACE("(%p)\n", hWndOwner); - - if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE)) - { - HANDLE hToken; - TOKEN_PRIVILEGES npr; - - /* enable shutdown privilege for current process */ - if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); - npr.PrivilegeCount = 1; - npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); - CloseHandle(hToken); - } - ExitWindowsEx(EWX_SHUTDOWN, 0); - } -} +/* + * common shell dialogs + * + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" +#include "commdlg.h" +#include "wine/debug.h" + +#include "shellapi.h" +#include "shlobj.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "undocshell.h" + +typedef struct + { + HWND hwndOwner ; + HICON hIcon ; + LPCSTR lpstrDirectory ; + LPCSTR lpstrTitle ; + LPCSTR lpstrDescription ; + UINT uFlags ; + } RUNFILEDLGPARAMS ; + +typedef BOOL (*LPFNOFN) (OPENFILENAMEA *) ; + +WINE_DEFAULT_DEBUG_CHANNEL(shell); +INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ; +void FillList (HWND, char *) ; + + +/************************************************************************* + * PickIconDlg [SHELL32.62] + * + */ +BOOL WINAPI PickIconDlg( + HWND hwndOwner, + LPSTR lpstrFile, + DWORD nMaxFile, + LPDWORD lpdwIconIndex) +{ + FIXME("(%p,%s,%08lx,%p):stub.\n", + hwndOwner, lpstrFile, nMaxFile,lpdwIconIndex); + return 0xffffffff; +} + +/************************************************************************* + * RunFileDlg [SHELL32.61] + * + * NOTES + * Original name: RunFileDlg (exported by ordinal) + */ +void WINAPI RunFileDlg( + HWND hwndOwner, + HICON hIcon, + LPCSTR lpstrDirectory, + LPCSTR lpstrTitle, + LPCSTR lpstrDescription, + UINT uFlags) +{ + + RUNFILEDLGPARAMS rfdp; + HRSRC hRes; + LPVOID template; + TRACE("\n"); + + rfdp.hwndOwner = hwndOwner; + rfdp.hIcon = hIcon; + rfdp.lpstrDirectory = lpstrDirectory; + rfdp.lpstrTitle = lpstrTitle; + rfdp.lpstrDescription = lpstrDescription; + rfdp.uFlags = uFlags; + + if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_RUN_DLG", (LPSTR)RT_DIALOG))) + { + MessageBoxA (hwndOwner, "Couldn't find dialog.", "Nix", MB_OK) ; + return; + } + if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes))) + { + MessageBoxA (hwndOwner, "Couldn't load dialog.", "Nix", MB_OK) ; + return; + } + + DialogBoxIndirectParamA((HINSTANCE)GetWindowLongPtrW( hwndOwner, + GWLP_HINSTANCE ), + template, hwndOwner, RunDlgProc, (LPARAM)&rfdp); + +} + +/* Dialog procedure for RunFileDlg */ +INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + int ic ; + char *psz, szMsg[256] ; + static RUNFILEDLGPARAMS *prfdp = NULL ; + + switch (message) + { + case WM_INITDIALOG : + prfdp = (RUNFILEDLGPARAMS *)lParam ; + SetWindowTextA (hwnd, prfdp->lpstrTitle) ; + SetClassLongA (hwnd, GCL_HICON, (LPARAM)prfdp->hIcon) ; + SendMessageA (GetDlgItem (hwnd, 12297), STM_SETICON, + (WPARAM)LoadIconA (NULL, (LPSTR)IDI_WINLOGO), 0); + FillList (GetDlgItem (hwnd, 12298), NULL) ; + SetFocus (GetDlgItem (hwnd, 12298)) ; + return TRUE ; + + case WM_COMMAND : + switch (LOWORD (wParam)) + { + case IDOK : + { + HWND htxt = NULL ; + if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298)))) + { + psz = HeapAlloc( GetProcessHeap(), 0, (ic + 2) ); + GetWindowTextA (htxt, psz, ic + 1) ; + + if (ShellExecuteA(NULL, "open", psz, NULL, NULL, SW_SHOWNORMAL) < (HINSTANCE)33) + { + char *pszSysMsg = NULL ; + FormatMessageA ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError (), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&pszSysMsg, 0, NULL + ) ; + sprintf (szMsg, "Error: %s", pszSysMsg) ; + LocalFree ((HLOCAL)pszSysMsg) ; + MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ; + + HeapFree(GetProcessHeap(), 0, psz); + SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + return TRUE ; + } + FillList (htxt, psz) ; + HeapFree(GetProcessHeap(), 0, psz); + EndDialog (hwnd, 0) ; + } + } + + case IDCANCEL : + EndDialog (hwnd, 0) ; + return TRUE ; + + case 12288 : + { + HMODULE hComdlg = NULL ; + LPFNOFN ofnProc = NULL ; + static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ; + static OPENFILENAMEA ofn = + { + sizeof (OPENFILENAMEA), + NULL, + NULL, + "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0", + NULL, + 0, + 0, + szFName, + 1023, + szFileTitle, + 255, + (LPCSTR)szInitDir, + "Browse", + OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST, + 0, + 0, + NULL, + 0, + (LPOFNHOOKPROC)NULL, + NULL + } ; + + ofn.hwndOwner = hwnd ; + + if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0))) + { + MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ; + return TRUE ; + } + + if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA"))) + { + MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ; + return TRUE ; + } + + ofnProc (&ofn) ; + + SetFocus (GetDlgItem (hwnd, IDOK)) ; + SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ; + SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + SetFocus (GetDlgItem (hwnd, IDOK)) ; + + FreeLibrary (hComdlg) ; + + return TRUE ; + } + } + return TRUE ; + } + return FALSE ; + } + +/* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */ +void FillList (HWND hCb, char *pszLatest) + { + HKEY hkey ; +/* char szDbgMsg[256] = "" ; */ + char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ; + DWORD icList = 0, icCmd = 0 ; + UINT Nix ; + + SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ; + + if (ERROR_SUCCESS != RegCreateKeyExA ( + HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", + 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL)) + MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ; + + RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ; + + if (icList > 0) + { + pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; + if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, pszList, &icList)) + MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ; + } + else + { + icList = 1 ; + pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; + pszList[0] = 0 ; + } + + for (Nix = 0 ; Nix < icList - 1 ; Nix++) + { + if (pszList[Nix] > cMax) + cMax = pszList[Nix] ; + + szIndex[0] = pszList[Nix] ; + + if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd)) + MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ; + if( pszCmd ) + pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ; + else + pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ; + if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, pszCmd, &icCmd)) + MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ; + + if (NULL != pszLatest) + { + if (!strcasecmp (pszCmd, pszLatest)) + { + /* + sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ; + MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; + */ + SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ; + SetWindowTextA (hCb, pszCmd) ; + SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + + cMatch = pszList[Nix] ; + memmove (&pszList[1], pszList, Nix) ; + pszList[0] = cMatch ; + continue ; + } + } + + if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest) + { + /* + sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ; + MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; + */ + SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ; + if (!Nix) + { + SetWindowTextA (hCb, pszCmd) ; + SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + } + + } + else + { + /* + sprintf (szDbgMsg, "Doing loop thing.\n") ; + MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; + */ + SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; + SetWindowTextA (hCb, pszLatest) ; + SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + + cMatch = pszList[Nix] ; + memmove (&pszList[1], pszList, Nix) ; + pszList[0] = cMatch ; + szIndex[0] = cMatch ; + RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ; + } + } + + if (!cMatch && NULL != pszLatest) + { + /* + sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ; + MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; + */ + SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; + SetWindowTextA (hCb, pszLatest) ; + SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; + + cMatch = ++cMax ; + if( pszList ) + pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ; + else + pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ; + memmove (&pszList[1], pszList, icList - 1) ; + pszList[0] = cMatch ; + szIndex[0] = cMatch ; + RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ; + } + + RegSetValueExA (hkey, "MRUList", 0, REG_SZ, pszList, strlen (pszList) + 1) ; + + HeapFree( GetProcessHeap(), 0, pszCmd) ; + HeapFree( GetProcessHeap(), 0, pszList) ; + } + + +/************************************************************************* + * ConfirmDialog [internal] + * + * Put up a confirm box, return TRUE if the user confirmed + */ +static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId) +{ + WCHAR Prompt[256]; + WCHAR Title[256]; + + LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR)); + LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR)); + return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES; +} + + +/************************************************************************* + * RestartDialogEx [SHELL32.730] + */ + +int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason) +{ + TRACE("(%p)\n", hWndOwner); + + /*FIXME: use uReason */ + + if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE)) + { + HANDLE hToken; + TOKEN_PRIVILEGES npr; + + /* enable shutdown privilege for current process */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); + npr.PrivilegeCount = 1; + npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); + CloseHandle(hToken); + } + ExitWindowsEx(EWX_REBOOT, 0); + } + + return 0; +} + + +/************************************************************************* + * RestartDialog [SHELL32.59] + */ + +int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags) +{ + return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0); +} + + +/************************************************************************* + * ExitWindowsDialog [SHELL32.60] + * + * NOTES + * exported by ordinal + */ +void WINAPI ExitWindowsDialog (HWND hWndOwner) +{ + TRACE("(%p)\n", hWndOwner); + + if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE)) + { + HANDLE hToken; + TOKEN_PRIVILEGES npr; + + /* enable shutdown privilege for current process */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + { + LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); + npr.PrivilegeCount = 1; + npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); + CloseHandle(hToken); + } + ExitWindowsEx(EWX_SHUTDOWN, 0); + } +} diff --git a/reactos/lib/shell32/dragdrophelper.c b/reactos/lib/shell32/dragdrophelper.c index e298407674d..f8005708433 100644 --- a/reactos/lib/shell32/dragdrophelper.c +++ b/reactos/lib/shell32/dragdrophelper.c @@ -1,186 +1,186 @@ -/* - * file system folder - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "objbase.h" -#include "ole2.h" -#include "shlguid.h" -#include "shlobj.h" - -#include "wine/debug.h" -#include "debughlp.h" - -WINE_DEFAULT_DEBUG_CHANNEL (shell); - -/*********************************************************************** -* IDropTargetHelper implementation -*/ - -typedef struct { - IDropTargetHelperVtbl *lpVtbl; - DWORD ref; -} IDropTargetHelperImpl; - -static struct IDropTargetHelperVtbl vt_IDropTargetHelper; - -#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IDropTargetHelper_(This) (IDropTargetHelper*)&(This->lpVtbl) - -/************************************************************************** -* IDropTargetHelper_Constructor -*/ -HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) -{ - IDropTargetHelperImpl *dth; - - TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); - - if (!ppv) - return E_POINTER; - if (pUnkOuter) - return CLASS_E_NOAGGREGATION; - - dth = (IDropTargetHelperImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IDropTargetHelperImpl)); - if (!dth) return E_OUTOFMEMORY; - - dth->ref = 0; - dth->lpVtbl = &vt_IDropTargetHelper; - - if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (dth), riid, ppv))) { - IUnknown_Release (_IUnknown_ (dth)); - return E_NOINTERFACE; - } - - TRACE ("--(%p)\n", dth); - return S_OK; -} - -/************************************************************************** - * IDropTargetHelper_fnQueryInterface - */ -static HRESULT WINAPI IDropTargetHelper_fnQueryInterface (IDropTargetHelper * iface, REFIID riid, LPVOID * ppvObj) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - *ppvObj = NULL; - - if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDropTargetHelper)) { - *ppvObj = This; - } - - if (*ppvObj) { - IUnknown_AddRef ((IUnknown *) (*ppvObj)); - TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); - return S_OK; - } - FIXME ("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI IDropTargetHelper_fnAddRef (IDropTargetHelper * iface) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return ++(This->ref); -} - -static ULONG WINAPI IDropTargetHelper_fnRelease (IDropTargetHelper * iface) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - if (!--(This->ref)) { - TRACE("-- destroying (%p)\n", This); - LocalFree ((HLOCAL) This); - return 0; - } - return This->ref; -} - -static HRESULT WINAPI IDropTargetHelper_fnDragEnter ( - IDropTargetHelper * iface, - HWND hwndTarget, - IDataObject* pDataObject, - POINT* ppt, - DWORD dwEffect) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - FIXME ("(%p)->(%p %p %p 0x%08lx)\n", This,hwndTarget, pDataObject, ppt, dwEffect); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDropTargetHelper_fnDragLeave (IDropTargetHelper * iface) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - FIXME ("(%p)->()\n", This); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDropTargetHelper_fnDragOver (IDropTargetHelper * iface, POINT* ppt, DWORD dwEffect) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - FIXME ("(%p)->(%p 0x%08lx)\n", This, ppt, dwEffect); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDropTargetHelper_fnDrop (IDropTargetHelper * iface, IDataObject* pDataObject, POINT* ppt, DWORD dwEffect) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - FIXME ("(%p)->(%p %p 0x%08lx)\n", This, pDataObject, ppt, dwEffect); - return E_NOTIMPL; -} - -static HRESULT WINAPI IDropTargetHelper_fnShow (IDropTargetHelper * iface, BOOL fShow) -{ - IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; - FIXME ("(%p)->(%u)\n", This, fShow); - return E_NOTIMPL; -} - -static IDropTargetHelperVtbl vt_IDropTargetHelper = -{ - IDropTargetHelper_fnQueryInterface, - IDropTargetHelper_fnAddRef, - IDropTargetHelper_fnRelease, - IDropTargetHelper_fnDragEnter, - IDropTargetHelper_fnDragLeave, - IDropTargetHelper_fnDragOver, - IDropTargetHelper_fnDrop, - IDropTargetHelper_fnShow -}; +/* + * file system folder + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "objbase.h" +#include "ole2.h" +#include "shlguid.h" +#include "shlobj.h" + +#include "wine/debug.h" +#include "debughlp.h" + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +/*********************************************************************** +* IDropTargetHelper implementation +*/ + +typedef struct { + IDropTargetHelperVtbl *lpVtbl; + DWORD ref; +} IDropTargetHelperImpl; + +static struct IDropTargetHelperVtbl vt_IDropTargetHelper; + +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IDropTargetHelper_(This) (IDropTargetHelper*)&(This->lpVtbl) + +/************************************************************************** +* IDropTargetHelper_Constructor +*/ +HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) +{ + IDropTargetHelperImpl *dth; + + TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); + + if (!ppv) + return E_POINTER; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + dth = (IDropTargetHelperImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IDropTargetHelperImpl)); + if (!dth) return E_OUTOFMEMORY; + + dth->ref = 0; + dth->lpVtbl = &vt_IDropTargetHelper; + + if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (dth), riid, ppv))) { + IUnknown_Release (_IUnknown_ (dth)); + return E_NOINTERFACE; + } + + TRACE ("--(%p)\n", dth); + return S_OK; +} + +/************************************************************************** + * IDropTargetHelper_fnQueryInterface + */ +static HRESULT WINAPI IDropTargetHelper_fnQueryInterface (IDropTargetHelper * iface, REFIID riid, LPVOID * ppvObj) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + *ppvObj = NULL; + + if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDropTargetHelper)) { + *ppvObj = This; + } + + if (*ppvObj) { + IUnknown_AddRef ((IUnknown *) (*ppvObj)); + TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); + return S_OK; + } + FIXME ("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI IDropTargetHelper_fnAddRef (IDropTargetHelper * iface) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI IDropTargetHelper_fnRelease (IDropTargetHelper * iface) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE("-- destroying (%p)\n", This); + LocalFree ((HLOCAL) This); + return 0; + } + return This->ref; +} + +static HRESULT WINAPI IDropTargetHelper_fnDragEnter ( + IDropTargetHelper * iface, + HWND hwndTarget, + IDataObject* pDataObject, + POINT* ppt, + DWORD dwEffect) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + FIXME ("(%p)->(%p %p %p 0x%08lx)\n", This,hwndTarget, pDataObject, ppt, dwEffect); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDropTargetHelper_fnDragLeave (IDropTargetHelper * iface) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + FIXME ("(%p)->()\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDropTargetHelper_fnDragOver (IDropTargetHelper * iface, POINT* ppt, DWORD dwEffect) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + FIXME ("(%p)->(%p 0x%08lx)\n", This, ppt, dwEffect); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDropTargetHelper_fnDrop (IDropTargetHelper * iface, IDataObject* pDataObject, POINT* ppt, DWORD dwEffect) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + FIXME ("(%p)->(%p %p 0x%08lx)\n", This, pDataObject, ppt, dwEffect); + return E_NOTIMPL; +} + +static HRESULT WINAPI IDropTargetHelper_fnShow (IDropTargetHelper * iface, BOOL fShow) +{ + IDropTargetHelperImpl *This = (IDropTargetHelperImpl *)iface; + FIXME ("(%p)->(%u)\n", This, fShow); + return E_NOTIMPL; +} + +static IDropTargetHelperVtbl vt_IDropTargetHelper = +{ + IDropTargetHelper_fnQueryInterface, + IDropTargetHelper_fnAddRef, + IDropTargetHelper_fnRelease, + IDropTargetHelper_fnDragEnter, + IDropTargetHelper_fnDragLeave, + IDropTargetHelper_fnDragOver, + IDropTargetHelper_fnDrop, + IDropTargetHelper_fnShow +}; diff --git a/reactos/lib/shell32/enumidlist.c b/reactos/lib/shell32/enumidlist.c index ea45a23dbd9..31abedbcad7 100644 --- a/reactos/lib/shell32/enumidlist.c +++ b/reactos/lib/shell32/enumidlist.c @@ -1,376 +1,372 @@ -/* - * IEnumIDList - * - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#define COBJMACROS - -#include "wine/debug.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "undocshell.h" -#include "shlwapi.h" -#include "winerror.h" -#include "objbase.h" - -#include "pidl.h" -#include "shlguid.h" -#include "enumidlist.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -typedef struct tagENUMLIST -{ - struct tagENUMLIST *pNext; - LPITEMIDLIST pidl; - -} ENUMLIST, *LPENUMLIST; - -typedef struct -{ - IEnumIDListVtbl *lpVtbl; - DWORD ref; - LPENUMLIST mpFirst; - LPENUMLIST mpLast; - LPENUMLIST mpCurrent; - -} IEnumIDListImpl; - -static struct IEnumIDListVtbl eidlvt; - -/************************************************************************** - * AddToEnumList() - */ -BOOL AddToEnumList( - IEnumIDList * iface, - LPITEMIDLIST pidl) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - LPENUMLIST pNew; - - TRACE("(%p)->(pidl=%p)\n",This,pidl); - - if (!iface || !pidl) - return FALSE; - - pNew = (LPENUMLIST)SHAlloc(sizeof(ENUMLIST)); - if(pNew) - { - /*set the next pointer */ - pNew->pNext = NULL; - pNew->pidl = pidl; - - /*is This the first item in the list? */ - if(!This->mpFirst) - { - This->mpFirst = pNew; - This->mpCurrent = pNew; - } - - if(This->mpLast) - { - /*add the new item to the end of the list */ - This->mpLast->pNext = pNew; - } - - /*update the last item pointer */ - This->mpLast = pNew; - TRACE("-- (%p)->(first=%p, last=%p)\n",This,This->mpFirst,This->mpLast); - return TRUE; - } - return FALSE; -} - -/************************************************************************** - * CreateFolderEnumList() - */ -BOOL CreateFolderEnumList( - IEnumIDList *list, - LPCSTR lpszPath, - DWORD dwFlags) -{ - LPITEMIDLIST pidl=NULL; - WIN32_FIND_DATAA stffile; - HANDLE hFile; - CHAR szPath[MAX_PATH]; - BOOL succeeded = TRUE; - - TRACE("(%p)->(path=%s flags=0x%08lx) \n",list,debugstr_a(lpszPath),dwFlags); - - if(!lpszPath || !lpszPath[0]) return FALSE; - - strcpy(szPath, lpszPath); - PathAddBackslashA(szPath); - strcat(szPath,"*.*"); - - hFile = FindFirstFileA(szPath,&stffile); - if ( hFile != INVALID_HANDLE_VALUE ) - { - BOOL findFinished = FALSE; - - do - { - if ( !(stffile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - || (dwFlags & SHCONTF_INCLUDEHIDDEN) ) - { - if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && - dwFlags & SHCONTF_FOLDERS && - strcmp (stffile.cFileName, ".") && strcmp (stffile.cFileName, "..")) - { - pidl = _ILCreateFromFindDataA(&stffile); - succeeded = succeeded && AddToEnumList(list, pidl); - } - else if (!(stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - && dwFlags & SHCONTF_NONFOLDERS) - { - pidl = _ILCreateFromFindDataA(&stffile); - succeeded = succeeded && AddToEnumList(list, pidl); - } - } - if (succeeded) - { - if (!FindNextFileA(hFile, &stffile)) - { - if (GetLastError() == ERROR_NO_MORE_FILES) - findFinished = TRUE; - else - succeeded = FALSE; - } - } - } while (succeeded && !findFinished); - FindClose(hFile); - } - return succeeded; -} - -/************************************************************************** -* DeleteList() -*/ -static BOOL DeleteList( - IEnumIDList * iface) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - LPENUMLIST pDelete; - - TRACE("(%p)->()\n",This); - - while(This->mpFirst) - { pDelete = This->mpFirst; - This->mpFirst = pDelete->pNext; - SHFree(pDelete->pidl); - SHFree(pDelete); - } - This->mpFirst = This->mpLast = This->mpCurrent = NULL; - return TRUE; -} - -/************************************************************************** - * IEnumIDList_Folder_Constructor - * - */ - -IEnumIDList * IEnumIDList_Constructor(void) -{ - IEnumIDListImpl *lpeidl = (IEnumIDListImpl*)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, sizeof(IEnumIDListImpl)); - - if (lpeidl) - { - lpeidl->ref = 1; - lpeidl->lpVtbl = &eidlvt; - } - TRACE("-- (%p)->()\n",lpeidl); - - return (IEnumIDList*)lpeidl; -} - -/************************************************************************** - * EnumIDList_QueryInterface - */ -static HRESULT WINAPI IEnumIDList_fnQueryInterface( - IEnumIDList * iface, - REFIID riid, - LPVOID *ppvObj) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ - { *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/ - { *ppvObj = (IEnumIDList*)This; - } - - if(*ppvObj) - { IEnumIDList_AddRef((IEnumIDList*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/****************************************************************************** - * IEnumIDList_fnAddRef - */ -static ULONG WINAPI IEnumIDList_fnAddRef( - IEnumIDList * iface) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - TRACE("(%p)->(%lu)\n",This,This->ref); - return ++(This->ref); -} -/****************************************************************************** - * IEnumIDList_fnRelease - */ -static ULONG WINAPI IEnumIDList_fnRelease( - IEnumIDList * iface) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - TRACE("(%p)->(%lu)\n",This,This->ref); - - if (!--(This->ref)) { - TRACE(" destroying IEnumIDList(%p)\n",This); - DeleteList((IEnumIDList*)This); - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -/************************************************************************** - * IEnumIDList_fnNext - */ - -static HRESULT WINAPI IEnumIDList_fnNext( - IEnumIDList * iface, - ULONG celt, - LPITEMIDLIST * rgelt, - ULONG *pceltFetched) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - ULONG i; - HRESULT hr = S_OK; - LPITEMIDLIST temp; - - TRACE("(%p)->(%ld,%p, %p)\n",This,celt,rgelt,pceltFetched); - -/* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's - * subsystems actually use it (and so may a third party browser) - */ - if(pceltFetched) - *pceltFetched = 0; - - *rgelt=0; - - if(celt > 1 && !pceltFetched) - { return E_INVALIDARG; - } - - if(celt > 0 && !This->mpCurrent) - { return S_FALSE; - } - - for(i = 0; i < celt; i++) - { if(!(This->mpCurrent)) - break; - - temp = ILClone(This->mpCurrent->pidl); - rgelt[i] = temp; - This->mpCurrent = This->mpCurrent->pNext; - } - if(pceltFetched) - { *pceltFetched = i; - } - - return hr; -} - -/************************************************************************** -* IEnumIDList_fnSkip -*/ -static HRESULT WINAPI IEnumIDList_fnSkip( - IEnumIDList * iface,ULONG celt) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - DWORD dwIndex; - HRESULT hr = S_OK; - - TRACE("(%p)->(%lu)\n",This,celt); - - for(dwIndex = 0; dwIndex < celt; dwIndex++) - { if(!This->mpCurrent) - { hr = S_FALSE; - break; - } - This->mpCurrent = This->mpCurrent->pNext; - } - return hr; -} -/************************************************************************** -* IEnumIDList_fnReset -*/ -static HRESULT WINAPI IEnumIDList_fnReset( - IEnumIDList * iface) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - TRACE("(%p)\n",This); - This->mpCurrent = This->mpFirst; - return S_OK; -} -/************************************************************************** -* IEnumIDList_fnClone -*/ -static HRESULT WINAPI IEnumIDList_fnClone( - IEnumIDList * iface,LPENUMIDLIST * ppenum) -{ - IEnumIDListImpl *This = (IEnumIDListImpl *)iface; - - TRACE("(%p)->() to (%p)->() E_NOTIMPL\n",This,ppenum); - return E_NOTIMPL; -} - -/************************************************************************** - * IEnumIDList_fnVTable - */ -static IEnumIDListVtbl eidlvt = -{ - IEnumIDList_fnQueryInterface, - IEnumIDList_fnAddRef, - IEnumIDList_fnRelease, - IEnumIDList_fnNext, - IEnumIDList_fnSkip, - IEnumIDList_fnReset, - IEnumIDList_fnClone, -}; +/* + * IEnumIDList + * + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "shlwapi.h" + +#include "pidl.h" +#include "enumidlist.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +typedef struct tagENUMLIST +{ + struct tagENUMLIST *pNext; + LPITEMIDLIST pidl; + +} ENUMLIST, *LPENUMLIST; + +typedef struct +{ + IEnumIDListVtbl *lpVtbl; + DWORD ref; + LPENUMLIST mpFirst; + LPENUMLIST mpLast; + LPENUMLIST mpCurrent; + +} IEnumIDListImpl; + +static struct IEnumIDListVtbl eidlvt; + +/************************************************************************** + * AddToEnumList() + */ +BOOL AddToEnumList( + IEnumIDList * iface, + LPITEMIDLIST pidl) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + LPENUMLIST pNew; + + TRACE("(%p)->(pidl=%p)\n",This,pidl); + + if (!iface || !pidl) + return FALSE; + + pNew = (LPENUMLIST)SHAlloc(sizeof(ENUMLIST)); + if(pNew) + { + /*set the next pointer */ + pNew->pNext = NULL; + pNew->pidl = pidl; + + /*is This the first item in the list? */ + if(!This->mpFirst) + { + This->mpFirst = pNew; + This->mpCurrent = pNew; + } + + if(This->mpLast) + { + /*add the new item to the end of the list */ + This->mpLast->pNext = pNew; + } + + /*update the last item pointer */ + This->mpLast = pNew; + TRACE("-- (%p)->(first=%p, last=%p)\n",This,This->mpFirst,This->mpLast); + return TRUE; + } + return FALSE; +} + +/************************************************************************** + * CreateFolderEnumList() + */ +BOOL CreateFolderEnumList( + IEnumIDList *list, + LPCSTR lpszPath, + DWORD dwFlags) +{ + LPITEMIDLIST pidl=NULL; + WIN32_FIND_DATAA stffile; + HANDLE hFile; + CHAR szPath[MAX_PATH]; + BOOL succeeded = TRUE; + + TRACE("(%p)->(path=%s flags=0x%08lx) \n",list,debugstr_a(lpszPath),dwFlags); + + if(!lpszPath || !lpszPath[0]) return FALSE; + + strcpy(szPath, lpszPath); + PathAddBackslashA(szPath); + strcat(szPath,"*.*"); + + hFile = FindFirstFileA(szPath,&stffile); + if ( hFile != INVALID_HANDLE_VALUE ) + { + BOOL findFinished = FALSE; + + do + { + if ( !(stffile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + || (dwFlags & SHCONTF_INCLUDEHIDDEN) ) + { + if ( (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + dwFlags & SHCONTF_FOLDERS && + strcmp (stffile.cFileName, ".") && strcmp (stffile.cFileName, "..")) + { + pidl = _ILCreateFromFindDataA(&stffile); + succeeded = succeeded && AddToEnumList(list, pidl); + } + else if (!(stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + && dwFlags & SHCONTF_NONFOLDERS) + { + pidl = _ILCreateFromFindDataA(&stffile); + succeeded = succeeded && AddToEnumList(list, pidl); + } + } + if (succeeded) + { + if (!FindNextFileA(hFile, &stffile)) + { + if (GetLastError() == ERROR_NO_MORE_FILES) + findFinished = TRUE; + else + succeeded = FALSE; + } + } + } while (succeeded && !findFinished); + FindClose(hFile); + } + return succeeded; +} + +/************************************************************************** +* DeleteList() +*/ +static BOOL DeleteList( + IEnumIDList * iface) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + LPENUMLIST pDelete; + + TRACE("(%p)->()\n",This); + + while(This->mpFirst) + { pDelete = This->mpFirst; + This->mpFirst = pDelete->pNext; + SHFree(pDelete->pidl); + SHFree(pDelete); + } + This->mpFirst = This->mpLast = This->mpCurrent = NULL; + return TRUE; +} + +/************************************************************************** + * IEnumIDList_Folder_Constructor + * + */ + +IEnumIDList * IEnumIDList_Constructor(void) +{ + IEnumIDListImpl *lpeidl = (IEnumIDListImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IEnumIDListImpl)); + + if (lpeidl) + { + lpeidl->ref = 1; + lpeidl->lpVtbl = &eidlvt; + } + TRACE("-- (%p)->()\n",lpeidl); + + return (IEnumIDList*)lpeidl; +} + +/************************************************************************** + * EnumIDList_QueryInterface + */ +static HRESULT WINAPI IEnumIDList_fnQueryInterface( + IEnumIDList * iface, + REFIID riid, + LPVOID *ppvObj) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ + { *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IEnumIDList)) /*IEnumIDList*/ + { *ppvObj = (IEnumIDList*)This; + } + + if(*ppvObj) + { IEnumIDList_AddRef((IEnumIDList*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/****************************************************************************** + * IEnumIDList_fnAddRef + */ +static ULONG WINAPI IEnumIDList_fnAddRef( + IEnumIDList * iface) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + TRACE("(%p)->(%lu)\n",This,This->ref); + return ++(This->ref); +} +/****************************************************************************** + * IEnumIDList_fnRelease + */ +static ULONG WINAPI IEnumIDList_fnRelease( + IEnumIDList * iface) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + TRACE("(%p)->(%lu)\n",This,This->ref); + + if (!--(This->ref)) { + TRACE(" destroying IEnumIDList(%p)\n",This); + DeleteList((IEnumIDList*)This); + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +/************************************************************************** + * IEnumIDList_fnNext + */ + +static HRESULT WINAPI IEnumIDList_fnNext( + IEnumIDList * iface, + ULONG celt, + LPITEMIDLIST * rgelt, + ULONG *pceltFetched) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + ULONG i; + HRESULT hr = S_OK; + LPITEMIDLIST temp; + + TRACE("(%p)->(%ld,%p, %p)\n",This,celt,rgelt,pceltFetched); + +/* It is valid to leave pceltFetched NULL when celt is 1. Some of explorer's + * subsystems actually use it (and so may a third party browser) + */ + if(pceltFetched) + *pceltFetched = 0; + + *rgelt=0; + + if(celt > 1 && !pceltFetched) + { return E_INVALIDARG; + } + + if(celt > 0 && !This->mpCurrent) + { return S_FALSE; + } + + for(i = 0; i < celt; i++) + { if(!(This->mpCurrent)) + break; + + temp = ILClone(This->mpCurrent->pidl); + rgelt[i] = temp; + This->mpCurrent = This->mpCurrent->pNext; + } + if(pceltFetched) + { *pceltFetched = i; + } + + return hr; +} + +/************************************************************************** +* IEnumIDList_fnSkip +*/ +static HRESULT WINAPI IEnumIDList_fnSkip( + IEnumIDList * iface,ULONG celt) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + DWORD dwIndex; + HRESULT hr = S_OK; + + TRACE("(%p)->(%lu)\n",This,celt); + + for(dwIndex = 0; dwIndex < celt; dwIndex++) + { if(!This->mpCurrent) + { hr = S_FALSE; + break; + } + This->mpCurrent = This->mpCurrent->pNext; + } + return hr; +} +/************************************************************************** +* IEnumIDList_fnReset +*/ +static HRESULT WINAPI IEnumIDList_fnReset( + IEnumIDList * iface) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + TRACE("(%p)\n",This); + This->mpCurrent = This->mpFirst; + return S_OK; +} +/************************************************************************** +* IEnumIDList_fnClone +*/ +static HRESULT WINAPI IEnumIDList_fnClone( + IEnumIDList * iface,LPENUMIDLIST * ppenum) +{ + IEnumIDListImpl *This = (IEnumIDListImpl *)iface; + + TRACE("(%p)->() to (%p)->() E_NOTIMPL\n",This,ppenum); + return E_NOTIMPL; +} + +/************************************************************************** + * IEnumIDList_fnVTable + */ +static IEnumIDListVtbl eidlvt = +{ + IEnumIDList_fnQueryInterface, + IEnumIDList_fnAddRef, + IEnumIDList_fnRelease, + IEnumIDList_fnNext, + IEnumIDList_fnSkip, + IEnumIDList_fnReset, + IEnumIDList_fnClone, +}; diff --git a/reactos/lib/shell32/enumidlist.h b/reactos/lib/shell32/enumidlist.h index 4cb03721d8b..53b8b5ff111 100644 --- a/reactos/lib/shell32/enumidlist.h +++ b/reactos/lib/shell32/enumidlist.h @@ -1,30 +1,30 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __ENUMIDLIST_H__ -#define __ENUMIDLIST_H__ - -#include "shlobj.h" - -/* Creates an IEnumIDList; add LPITEMIDLISTs to it with AddToEnumList. */ -LPENUMIDLIST IEnumIDList_Constructor(void); -BOOL AddToEnumList(IEnumIDList *list, LPITEMIDLIST pidl); - -/* Enumerates the folders and/or files (depending on dwFlags) in lpszPath and - * adds them to the already-created list. - */ -BOOL CreateFolderEnumList(IEnumIDList *list, LPCSTR lpszPath, DWORD dwFlags); - -#endif /* ndef __ENUMIDLIST_H__ */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ENUMIDLIST_H__ +#define __ENUMIDLIST_H__ + +#include "shlobj.h" + +/* Creates an IEnumIDList; add LPITEMIDLISTs to it with AddToEnumList. */ +LPENUMIDLIST IEnumIDList_Constructor(void); +BOOL AddToEnumList(IEnumIDList *list, LPITEMIDLIST pidl); + +/* Enumerates the folders and/or files (depending on dwFlags) in lpszPath and + * adds them to the already-created list. + */ +BOOL CreateFolderEnumList(IEnumIDList *list, LPCSTR lpszPath, DWORD dwFlags); + +#endif /* ndef __ENUMIDLIST_H__ */ diff --git a/reactos/lib/shell32/folders.c b/reactos/lib/shell32/folders.c index c3664909942..7aa2e7485d5 100644 --- a/reactos/lib/shell32/folders.c +++ b/reactos/lib/shell32/folders.c @@ -1,560 +1,558 @@ -/* - * Copyright 1997 Marcus Meissner - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "objbase.h" -#include "undocshell.h" -#include "shlguid.h" -#include "winreg.h" -#include "shlwapi.h" - -#include "wine/debug.h" -#include "wine/unicode.h" - -#include "pidl.h" -#include "shell32_main.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/*********************************************************************** -* IExtractIconW implementation -*/ -typedef struct -{ - IExtractIconWVtbl *lpVtbl; - DWORD ref; - IPersistFileVtbl *lpvtblPersistFile; - IExtractIconAVtbl *lpvtblExtractIconA; - LPITEMIDLIST pidl; -} IExtractIconWImpl; - -static struct IExtractIconAVtbl eiavt; -static struct IExtractIconWVtbl eivt; -static struct IPersistFileVtbl pfvt; - -#define _IPersistFile_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblPersistFile))) -#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset); - -#define _IExtractIconA_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblExtractIconA))) -#define _ICOM_THIS_From_IExtractIconA(class, name) class* This = (class*)(((char*)name)-_IExtractIconA_Offset); - -/************************************************************************** -* IExtractIconW_Constructor -*/ -IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl) -{ - IExtractIconWImpl* ei; - - TRACE("%p\n", pidl); - - ei = (IExtractIconWImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IExtractIconWImpl)); - ei->ref=1; - ei->lpVtbl = &eivt; - ei->lpvtblPersistFile = &pfvt; - ei->lpvtblExtractIconA = &eiavt; - ei->pidl=ILClone(pidl); - - pdump(pidl); - - TRACE("(%p)\n", ei); - return (IExtractIconW *)ei; -} -/************************************************************************** - * IExtractIconW_QueryInterface - */ -static HRESULT WINAPI IExtractIconW_fnQueryInterface(IExtractIconW *iface, REFIID riid, LPVOID *ppvObj) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid(riid), ppvObj); - - *ppvObj = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ - { - *ppvObj = This; - } - else if (IsEqualIID(riid, &IID_IPersistFile)) /*IExtractIcon*/ - { - *ppvObj = (IPersistFile*)&(This->lpvtblPersistFile); - } - else if (IsEqualIID(riid, &IID_IExtractIconA)) /*IExtractIcon*/ - { - *ppvObj = (IExtractIconA*)&(This->lpvtblExtractIconA); - } - else if (IsEqualIID(riid, &IID_IExtractIconW)) /*IExtractIcon*/ - { - *ppvObj = (IExtractIconW*)This; - } - - if(*ppvObj) - { - IExtractIconW_AddRef((IExtractIconW*) *ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* IExtractIconW_AddRef -*/ -static ULONG WINAPI IExtractIconW_fnAddRef(IExtractIconW * iface) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This, This->ref ); - - return ++(This->ref); -} -/************************************************************************** -* IExtractIconW_Release -*/ -static ULONG WINAPI IExtractIconW_fnRelease(IExtractIconW * iface) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IExtractIcon(%p)\n",This); - SHFree(This->pidl); - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -static HRESULT getIconLocationForFolder(IExtractIconW *iface, UINT uFlags, - LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - DWORD dwNr; - WCHAR wszPath[MAX_PATH]; - WCHAR wszCLSIDValue[CHARS_IN_GUID]; - static const WCHAR shellClassInfo[] = { '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 }; - static const WCHAR iconFile[] = { 'I','c','o','n','F','i','l','e',0 }; - static const WCHAR clsid[] = { 'C','L','S','I','D',0 }; - static const WCHAR clsid2[] = { 'C','L','S','I','D','2',0 }; - static const WCHAR iconIndex[] = { 'I','c','o','n','I','n','d','e','x',0 }; - - if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconFile, - wszPath, MAX_PATH)) - { - WCHAR wszIconIndex[10]; - SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconIndex, - wszIconIndex, 10); - *piIndex = atoiW(wszIconIndex); - } - else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid, - wszCLSIDValue, CHARS_IN_GUID) && - HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - } - else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid2, - wszCLSIDValue, CHARS_IN_GUID) && - HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - } - else - { - static const WCHAR folder[] = { 'F','o','l','d','e','r',0 }; - - if (!HCR_GetDefaultIconW(folder, szIconFile, cchMax, &dwNr)) - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - dwNr = 3; - } - *piIndex = (uFlags & GIL_OPENICON) ? dwNr + 1 : dwNr; - } - return S_OK; -} - -WCHAR swShell32Name[MAX_PATH]; - -/************************************************************************** -* IExtractIconW_GetIconLocation -* -* mapping filetype to icon -*/ -static HRESULT WINAPI IExtractIconW_fnGetIconLocation( - IExtractIconW * iface, - UINT uFlags, /* GIL_ flags */ - LPWSTR szIconFile, - UINT cchMax, - int * piIndex, - UINT * pwFlags) /* returned GIL_ flags */ -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - char sTemp[MAX_PATH]; - DWORD dwNr; - GUID const * riid; - LPITEMIDLIST pSimplePidl = ILFindLastID(This->pidl); - - TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags); - - if (pwFlags) - *pwFlags = 0; - - if (_ILIsDesktop(pSimplePidl)) - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = 34; - } - - /* my computer and other shell extensions */ - else if ((riid = _ILGetGUIDPointer(pSimplePidl))) - { - static const WCHAR fmt[] = { 'C','L','S','I','D','\\', - '{','%','0','8','l','x','-','%','0','4','x','-','%','0','4','x','-', - '%','0','2','x','%','0','2','x','-','%','0','2','x', '%','0','2','x', - '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0 }; - WCHAR xriid[50]; - - sprintfW(xriid, fmt, - riid->Data1, riid->Data2, riid->Data3, - riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], - riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]); - - if (HCR_GetDefaultIconW(xriid, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - } - else - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = 15; - } - } - - else if (_ILIsDrive (pSimplePidl)) - { - static const WCHAR drive[] = { 'D','r','i','v','e',0 }; - - int icon_idx = -1; - - if (_ILGetDrive(pSimplePidl, sTemp, MAX_PATH)) - { - switch(GetDriveTypeA(sTemp)) - { - case DRIVE_REMOVABLE: icon_idx = 5; break; - case DRIVE_CDROM: icon_idx = 11; break; - case DRIVE_REMOTE: icon_idx = 9; break; - case DRIVE_RAMDISK: icon_idx = 12; break; - } - } - - if (icon_idx != -1) - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = icon_idx; - } - else - { - if (HCR_GetDefaultIconW(drive, szIconFile, cchMax, &dwNr)) - { - *piIndex = dwNr; - } - else - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = 8; - } - } - } - else if (_ILIsFolder (pSimplePidl)) - { - getIconLocationForFolder(iface, uFlags, szIconFile, cchMax, piIndex, - pwFlags); - } - else - { - BOOL found = FALSE; - - if (_ILIsCPanelStruct(pSimplePidl)) - { - if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl, szIconFile, cchMax, piIndex))) - found = TRUE; - } - else if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH)) - { - if (HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE) - && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &dwNr)) - { - if (!lstrcmpA("%1", sTemp)) /* icon is in the file */ - { - SHGetPathFromIDListW(This->pidl, szIconFile); - *piIndex = 0; - } - else - { - MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax); - *piIndex = dwNr; - } - - found = TRUE; - } - else if (!strcasecmp(sTemp, "lnkfile")) - { - /* extract icon from shell shortcut */ - IShellFolder* dsf; - IShellLinkW* psl; - - if (SUCCEEDED(SHGetDesktopFolder(&dsf))) - { - HRESULT hr = IShellFolder_GetUIObjectOf(dsf, NULL, 1, (LPCITEMIDLIST*)&This->pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl); - - if (SUCCEEDED(hr)) - { - hr = IShellLinkW_GetIconLocation(psl, szIconFile, MAX_PATH, piIndex); - - if (SUCCEEDED(hr) && *szIconFile) - found = TRUE; - - IShellLinkW_Release(psl); - } - - IShellFolder_Release(dsf); - } - } - } - - if (!found) /* default icon */ - { - lstrcpynW(szIconFile, swShell32Name, cchMax); - *piIndex = 0; - } - } - - TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex); - return NOERROR; -} - -/************************************************************************** -* IExtractIconW_Extract -*/ -static HRESULT WINAPI IExtractIconW_fnExtract(IExtractIconW * iface, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)iface; - - FIXME("(%p) (file=%p index=%u %p %p size=%u) semi-stub\n", This, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize); - - if (phiconLarge) - *phiconLarge = ImageList_GetIcon(ShellBigIconList, nIconIndex, ILD_TRANSPARENT); - - if (phiconSmall) - *phiconSmall = ImageList_GetIcon(ShellSmallIconList, nIconIndex, ILD_TRANSPARENT); - - return S_OK; -} - -static struct IExtractIconWVtbl eivt = -{ - IExtractIconW_fnQueryInterface, - IExtractIconW_fnAddRef, - IExtractIconW_fnRelease, - IExtractIconW_fnGetIconLocation, - IExtractIconW_fnExtract -}; - -/************************************************************************** -* IExtractIconA_Constructor -*/ -IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl) -{ - IExtractIconWImpl *This = (IExtractIconWImpl *)IExtractIconW_Constructor(pidl); - IExtractIconA *eia = (IExtractIconA *)&This->lpvtblExtractIconA; - - TRACE("(%p)->(%p)\n", This, eia); - return eia; -} -/************************************************************************** - * IExtractIconA_QueryInterface - */ -static HRESULT WINAPI IExtractIconA_fnQueryInterface(IExtractIconA * iface, REFIID riid, LPVOID *ppvObj) -{ - _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); - - return IExtractIconW_QueryInterface(This, riid, ppvObj); -} - -/************************************************************************** -* IExtractIconA_AddRef -*/ -static ULONG WINAPI IExtractIconA_fnAddRef(IExtractIconA * iface) -{ - _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); - - return IExtractIconW_AddRef(This); -} -/************************************************************************** -* IExtractIconA_Release -*/ -static ULONG WINAPI IExtractIconA_fnRelease(IExtractIconA * iface) -{ - _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); - - return IExtractIconW_AddRef(This); -} -/************************************************************************** -* IExtractIconA_GetIconLocation -* -* mapping filetype to icon -*/ -static HRESULT WINAPI IExtractIconA_fnGetIconLocation( - IExtractIconA * iface, - UINT uFlags, - LPSTR szIconFile, - UINT cchMax, - int * piIndex, - UINT * pwFlags) -{ - HRESULT ret; - LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR)); - _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); - - TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags); - - ret = IExtractIconW_GetIconLocation(This, uFlags, lpwstrFile, cchMax, piIndex, pwFlags); - WideCharToMultiByte(CP_ACP, 0, lpwstrFile, -1, szIconFile, cchMax, NULL, NULL); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - - TRACE("-- %s %x\n", szIconFile, *piIndex); - return ret; -} -/************************************************************************** -* IExtractIconA_Extract -*/ -static HRESULT WINAPI IExtractIconA_fnExtract(IExtractIconA * iface, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) -{ - HRESULT ret; - INT len = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0); - LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); - - TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", This, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize); - - MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwstrFile, len); - ret = IExtractIconW_Extract(This, lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIconSize); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - return ret; -} - -static struct IExtractIconAVtbl eiavt = -{ - IExtractIconA_fnQueryInterface, - IExtractIconA_fnAddRef, - IExtractIconA_fnRelease, - IExtractIconA_fnGetIconLocation, - IExtractIconA_fnExtract -}; - -/************************************************************************ - * IEIPersistFile_QueryInterface (IUnknown) - */ -static HRESULT WINAPI IEIPersistFile_fnQueryInterface( - IPersistFile *iface, - REFIID iid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); - - return IExtractIconW_QueryInterface(This, iid, ppvObj); -} - -/************************************************************************ - * IEIPersistFile_AddRef (IUnknown) - */ -static ULONG WINAPI IEIPersistFile_fnAddRef( - IPersistFile *iface) -{ - _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); - - return IExtractIconW_AddRef(This); -} - -/************************************************************************ - * IEIPersistFile_Release (IUnknown) - */ -static ULONG WINAPI IEIPersistFile_fnRelease( - IPersistFile *iface) -{ - _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); - - return IExtractIconW_Release(This); -} - -/************************************************************************ - * IEIPersistFile_GetClassID (IPersist) - */ -static HRESULT WINAPI IEIPersistFile_fnGetClassID( - IPersistFile *iface, - LPCLSID lpClassId) -{ - CLSID StdFolderID = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; - - if (lpClassId==NULL) - return E_POINTER; - - memcpy(lpClassId, &StdFolderID, sizeof(StdFolderID)); - - return S_OK; -} - -/************************************************************************ - * IEIPersistFile_Load (IPersistFile) - */ -static HRESULT WINAPI IEIPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode) -{ - _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); - FIXME("%p\n", This); - return E_NOTIMPL; - -} - -static struct IPersistFileVtbl pfvt = -{ - IEIPersistFile_fnQueryInterface, - IEIPersistFile_fnAddRef, - IEIPersistFile_fnRelease, - IEIPersistFile_fnGetClassID, - (void *) 0xdeadbeef /* IEIPersistFile_fnIsDirty */, - IEIPersistFile_fnLoad, - (void *) 0xdeadbeef /* IEIPersistFile_fnSave */, - (void *) 0xdeadbeef /* IEIPersistFile_fnSaveCompleted */, - (void *) 0xdeadbeef /* IEIPersistFile_fnGetCurFile */ -}; +/* + * Copyright 1997 Marcus Meissner + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "objbase.h" +#include "undocshell.h" +#include "shlguid.h" +#include "winreg.h" + +#include "wine/debug.h" + +#include "pidl.h" +#include "shell32_main.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/*********************************************************************** +* IExtractIconW implementation +*/ +typedef struct +{ + IExtractIconWVtbl *lpVtbl; + DWORD ref; + IPersistFileVtbl *lpvtblPersistFile; + IExtractIconAVtbl *lpvtblExtractIconA; + LPITEMIDLIST pidl; +} IExtractIconWImpl; + +static struct IExtractIconAVtbl eiavt; +static struct IExtractIconWVtbl eivt; +static struct IPersistFileVtbl pfvt; + +#define _IPersistFile_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblPersistFile))) +#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset); + +#define _IExtractIconA_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblExtractIconA))) +#define _ICOM_THIS_From_IExtractIconA(class, name) class* This = (class*)(((char*)name)-_IExtractIconA_Offset); + +/************************************************************************** +* IExtractIconW_Constructor +*/ +IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl) +{ + IExtractIconWImpl* ei; + + TRACE("%p\n", pidl); + + ei = (IExtractIconWImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IExtractIconWImpl)); + ei->ref=1; + ei->lpVtbl = &eivt; + ei->lpvtblPersistFile = &pfvt; + ei->lpvtblExtractIconA = &eiavt; + ei->pidl=ILClone(pidl); + + pdump(pidl); + + TRACE("(%p)\n", ei); + return (IExtractIconW *)ei; +} +/************************************************************************** + * IExtractIconW_QueryInterface + */ +static HRESULT WINAPI IExtractIconW_fnQueryInterface(IExtractIconW *iface, REFIID riid, LPVOID *ppvObj) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid(riid), ppvObj); + + *ppvObj = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/ + { + *ppvObj = This; + } + else if (IsEqualIID(riid, &IID_IPersistFile)) /*IExtractIcon*/ + { + *ppvObj = (IPersistFile*)&(This->lpvtblPersistFile); + } + else if (IsEqualIID(riid, &IID_IExtractIconA)) /*IExtractIcon*/ + { + *ppvObj = (IExtractIconA*)&(This->lpvtblExtractIconA); + } + else if (IsEqualIID(riid, &IID_IExtractIconW)) /*IExtractIcon*/ + { + *ppvObj = (IExtractIconW*)This; + } + + if(*ppvObj) + { + IExtractIconW_AddRef((IExtractIconW*) *ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** +* IExtractIconW_AddRef +*/ +static ULONG WINAPI IExtractIconW_fnAddRef(IExtractIconW * iface) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This, This->ref ); + + return ++(This->ref); +} +/************************************************************************** +* IExtractIconW_Release +*/ +static ULONG WINAPI IExtractIconW_fnRelease(IExtractIconW * iface) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IExtractIcon(%p)\n",This); + SHFree(This->pidl); + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +static HRESULT getIconLocationForFolder(IExtractIconW *iface, UINT uFlags, + LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + DWORD dwNr; + WCHAR wszPath[MAX_PATH]; + WCHAR wszCLSIDValue[CHARS_IN_GUID]; + static const WCHAR shellClassInfo[] = { '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 }; + static const WCHAR iconFile[] = { 'I','c','o','n','F','i','l','e',0 }; + static const WCHAR clsid[] = { 'C','L','S','I','D',0 }; + static const WCHAR clsid2[] = { 'C','L','S','I','D','2',0 }; + static const WCHAR iconIndex[] = { 'I','c','o','n','I','n','d','e','x',0 }; + + if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconFile, + wszPath, MAX_PATH)) + { + WCHAR wszIconIndex[10]; + SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, iconIndex, + wszIconIndex, 10); + *piIndex = atoiW(wszIconIndex); + } + else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else if (SHELL32_GetCustomFolderAttribute(This->pidl, shellClassInfo, clsid2, + wszCLSIDValue, CHARS_IN_GUID) && + HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else + { + static const WCHAR folder[] = { 'F','o','l','d','e','r',0 }; + + if (!HCR_GetDefaultIconW(folder, szIconFile, cchMax, &dwNr)) + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + dwNr = 3; + } + *piIndex = (uFlags & GIL_OPENICON) ? dwNr + 1 : dwNr; + } + return S_OK; +} + +WCHAR swShell32Name[MAX_PATH]; + +/************************************************************************** +* IExtractIconW_GetIconLocation +* +* mapping filetype to icon +*/ +static HRESULT WINAPI IExtractIconW_fnGetIconLocation( + IExtractIconW * iface, + UINT uFlags, /* GIL_ flags */ + LPWSTR szIconFile, + UINT cchMax, + int * piIndex, + UINT * pwFlags) /* returned GIL_ flags */ +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + + char sTemp[MAX_PATH]; + DWORD dwNr; + GUID const * riid; + LPITEMIDLIST pSimplePidl = ILFindLastID(This->pidl); + + TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags); + + if (pwFlags) + *pwFlags = 0; + + if (_ILIsDesktop(pSimplePidl)) + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + *piIndex = 34; + } + + /* my computer and other shell extensions */ + else if ((riid = _ILGetGUIDPointer(pSimplePidl))) + { + static const WCHAR fmt[] = { 'C','L','S','I','D','\\', + '{','%','0','8','l','x','-','%','0','4','x','-','%','0','4','x','-', + '%','0','2','x','%','0','2','x','-','%','0','2','x', '%','0','2','x', + '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0 }; + WCHAR xriid[50]; + + sprintfW(xriid, fmt, + riid->Data1, riid->Data2, riid->Data3, + riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], + riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]); + + if (HCR_GetDefaultIconW(xriid, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + *piIndex = 15; + } + } + + else if (_ILIsDrive (pSimplePidl)) + { + static const WCHAR drive[] = { 'D','r','i','v','e',0 }; + + int icon_idx = -1; + + if (_ILGetDrive(pSimplePidl, sTemp, MAX_PATH)) + { + switch(GetDriveTypeA(sTemp)) + { + case DRIVE_REMOVABLE: icon_idx = 5; break; + case DRIVE_CDROM: icon_idx = 11; break; + case DRIVE_REMOTE: icon_idx = 9; break; + case DRIVE_RAMDISK: icon_idx = 12; break; + } + } + + if (icon_idx != -1) + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + *piIndex = icon_idx; + } + else + { + if (HCR_GetDefaultIconW(drive, szIconFile, cchMax, &dwNr)) + { + *piIndex = dwNr; + } + else + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + *piIndex = 8; + } + } + } + else if (_ILIsFolder (pSimplePidl)) + { + getIconLocationForFolder(iface, uFlags, szIconFile, cchMax, piIndex, + pwFlags); + } + else + { + BOOL found = FALSE; + + if (_ILIsCPanelStruct(pSimplePidl)) + { + if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl, szIconFile, cchMax, piIndex))) + found = TRUE; + } + else if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH)) + { + if (HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE) + && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &dwNr)) + { + if (!lstrcmpA("%1", sTemp)) /* icon is in the file */ + { + SHGetPathFromIDListW(This->pidl, szIconFile); + *piIndex = 0; + } + else + { + MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax); + *piIndex = dwNr; + } + + found = TRUE; + } + else if (!strcasecmp(sTemp, "lnkfile")) + { + /* extract icon from shell shortcut */ + IShellFolder* dsf; + IShellLinkW* psl; + + if (SUCCEEDED(SHGetDesktopFolder(&dsf))) + { + HRESULT hr = IShellFolder_GetUIObjectOf(dsf, NULL, 1, (LPCITEMIDLIST*)&This->pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl); + + if (SUCCEEDED(hr)) + { + hr = IShellLinkW_GetIconLocation(psl, szIconFile, MAX_PATH, piIndex); + + if (SUCCEEDED(hr) && *szIconFile) + found = TRUE; + + IShellLinkW_Release(psl); + } + + IShellFolder_Release(dsf); + } + } + } + + if (!found) /* default icon */ + { + lstrcpynW(szIconFile, swShell32Name, cchMax); + *piIndex = 0; + } + } + + TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex); + return NOERROR; +} + +/************************************************************************** +* IExtractIconW_Extract +*/ +static HRESULT WINAPI IExtractIconW_fnExtract(IExtractIconW * iface, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)iface; + + FIXME("(%p) (file=%p index=%u %p %p size=%u) semi-stub\n", This, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize); + + if (phiconLarge) + *phiconLarge = ImageList_GetIcon(ShellBigIconList, nIconIndex, ILD_TRANSPARENT); + + if (phiconSmall) + *phiconSmall = ImageList_GetIcon(ShellSmallIconList, nIconIndex, ILD_TRANSPARENT); + + return S_OK; +} + +static struct IExtractIconWVtbl eivt = +{ + IExtractIconW_fnQueryInterface, + IExtractIconW_fnAddRef, + IExtractIconW_fnRelease, + IExtractIconW_fnGetIconLocation, + IExtractIconW_fnExtract +}; + +/************************************************************************** +* IExtractIconA_Constructor +*/ +IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl) +{ + IExtractIconWImpl *This = (IExtractIconWImpl *)IExtractIconW_Constructor(pidl); + IExtractIconA *eia = (IExtractIconA *)&This->lpvtblExtractIconA; + + TRACE("(%p)->(%p)\n", This, eia); + return eia; +} +/************************************************************************** + * IExtractIconA_QueryInterface + */ +static HRESULT WINAPI IExtractIconA_fnQueryInterface(IExtractIconA * iface, REFIID riid, LPVOID *ppvObj) +{ + _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); + + return IExtractIconW_QueryInterface(This, riid, ppvObj); +} + +/************************************************************************** +* IExtractIconA_AddRef +*/ +static ULONG WINAPI IExtractIconA_fnAddRef(IExtractIconA * iface) +{ + _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); + + return IExtractIconW_AddRef(This); +} +/************************************************************************** +* IExtractIconA_Release +*/ +static ULONG WINAPI IExtractIconA_fnRelease(IExtractIconA * iface) +{ + _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); + + return IExtractIconW_AddRef(This); +} +/************************************************************************** +* IExtractIconA_GetIconLocation +* +* mapping filetype to icon +*/ +static HRESULT WINAPI IExtractIconA_fnGetIconLocation( + IExtractIconA * iface, + UINT uFlags, + LPSTR szIconFile, + UINT cchMax, + int * piIndex, + UINT * pwFlags) +{ + HRESULT ret; + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR)); + _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); + + TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags); + + ret = IExtractIconW_GetIconLocation(This, uFlags, lpwstrFile, cchMax, piIndex, pwFlags); + WideCharToMultiByte(CP_ACP, 0, lpwstrFile, -1, szIconFile, cchMax, NULL, NULL); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + + TRACE("-- %s %x\n", szIconFile, *piIndex); + return ret; +} +/************************************************************************** +* IExtractIconA_Extract +*/ +static HRESULT WINAPI IExtractIconA_fnExtract(IExtractIconA * iface, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) +{ + HRESULT ret; + INT len = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0); + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface); + + TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", This, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize); + + MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwstrFile, len); + ret = IExtractIconW_Extract(This, lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIconSize); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + return ret; +} + +static struct IExtractIconAVtbl eiavt = +{ + IExtractIconA_fnQueryInterface, + IExtractIconA_fnAddRef, + IExtractIconA_fnRelease, + IExtractIconA_fnGetIconLocation, + IExtractIconA_fnExtract +}; + +/************************************************************************ + * IEIPersistFile_QueryInterface (IUnknown) + */ +static HRESULT WINAPI IEIPersistFile_fnQueryInterface( + IPersistFile *iface, + REFIID iid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); + + return IExtractIconW_QueryInterface(This, iid, ppvObj); +} + +/************************************************************************ + * IEIPersistFile_AddRef (IUnknown) + */ +static ULONG WINAPI IEIPersistFile_fnAddRef( + IPersistFile *iface) +{ + _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); + + return IExtractIconW_AddRef(This); +} + +/************************************************************************ + * IEIPersistFile_Release (IUnknown) + */ +static ULONG WINAPI IEIPersistFile_fnRelease( + IPersistFile *iface) +{ + _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); + + return IExtractIconW_Release(This); +} + +/************************************************************************ + * IEIPersistFile_GetClassID (IPersist) + */ +static HRESULT WINAPI IEIPersistFile_fnGetClassID( + IPersistFile *iface, + LPCLSID lpClassId) +{ + CLSID StdFolderID = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; + + if (lpClassId==NULL) + return E_POINTER; + + memcpy(lpClassId, &StdFolderID, sizeof(StdFolderID)); + + return S_OK; +} + +/************************************************************************ + * IEIPersistFile_Load (IPersistFile) + */ +static HRESULT WINAPI IEIPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode) +{ + _ICOM_THIS_From_IPersistFile(IExtractIconW, iface); + FIXME("%p\n", This); + return E_NOTIMPL; + +} + +static struct IPersistFileVtbl pfvt = +{ + IEIPersistFile_fnQueryInterface, + IEIPersistFile_fnAddRef, + IEIPersistFile_fnRelease, + IEIPersistFile_fnGetClassID, + (void *) 0xdeadbeef /* IEIPersistFile_fnIsDirty */, + IEIPersistFile_fnLoad, + (void *) 0xdeadbeef /* IEIPersistFile_fnSave */, + (void *) 0xdeadbeef /* IEIPersistFile_fnSaveCompleted */, + (void *) 0xdeadbeef /* IEIPersistFile_fnGetCurFile */ +}; diff --git a/reactos/lib/shell32/iconcache.c b/reactos/lib/shell32/iconcache.c index 68a941d5747..3ca829c2fbf 100644 --- a/reactos/lib/shell32/iconcache.c +++ b/reactos/lib/shell32/iconcache.c @@ -1,594 +1,598 @@ -/* - * shell icon cache (SIC) - * - * Copyright 1998, 1999 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winreg.h" -#include "wine/debug.h" - -#include "shellapi.h" -#include "objbase.h" -#include "shlguid.h" -#include "pidl.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "shlwapi.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/********************** THE ICON CACHE ********************************/ - -#define INVALID_INDEX -1 - -typedef struct -{ - LPWSTR sSourceFile; /* file (not path!) containing the icon */ - DWORD dwSourceIndex; /* index within the file, if it is a resoure ID it will be negated */ - DWORD dwListIndex; /* index within the iconlist */ - DWORD dwFlags; /* GIL_* flags */ - DWORD dwAccessTime; -} SIC_ENTRY, * LPSIC_ENTRY; - -static HDPA sic_hdpa = 0; - -static CRITICAL_SECTION SHELL32_SicCS; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &SHELL32_SicCS, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { 0, (DWORD)(__FILE__ ": SHELL32_SicCS") } -}; -static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 }; - -/***************************************************************************** - * SIC_CompareEntries - * - * NOTES - * Callback for DPA_Search - */ -static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam) -{ TRACE("%p %p %8lx\n", p1, p2, lparam); - - if (((LPSIC_ENTRY)p1)->dwSourceIndex != ((LPSIC_ENTRY)p2)->dwSourceIndex) /* first the faster one*/ - return 1; - - if (strcmpiW(((LPSIC_ENTRY)p1)->sSourceFile,((LPSIC_ENTRY)p2)->sSourceFile)) - return 1; - - return 0; -} -/***************************************************************************** - * SIC_IconAppend [internal] - * - * NOTES - * appends an icon pair to the end of the cache - */ -static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon) -{ LPSIC_ENTRY lpsice; - INT ret, index, index1; - WCHAR path[MAX_PATH]; - TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon); - - lpsice = (LPSIC_ENTRY) SHAlloc (sizeof (SIC_ENTRY)); - - GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL); - lpsice->sSourceFile = HeapAlloc( GetProcessHeap(), 0, (strlenW(path)+1)*sizeof(WCHAR) ); - strcpyW( lpsice->sSourceFile, path ); - - lpsice->dwSourceIndex = dwSourceIndex; - - EnterCriticalSection(&SHELL32_SicCS); - - index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice); - if ( INVALID_INDEX == index ) - { - HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile); - SHFree(lpsice); - ret = INVALID_INDEX; - } - else - { - index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon); - index1= ImageList_AddIcon (ShellBigIconList, hBigIcon); - - if (index!=index1) - { - FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1); - } - lpsice->dwListIndex = index; - ret = lpsice->dwListIndex; - } - - LeaveCriticalSection(&SHELL32_SicCS); - return ret; -} -/**************************************************************************** - * SIC_LoadIcon [internal] - * - * NOTES - * gets small/big icon by number from a file - */ -static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex) -{ HICON hiconLarge=0; - HICON hiconSmall=0; - -#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER) - static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL; - - if (!PrivateExtractIconExW) { - HMODULE hUser32 = GetModuleHandleA("user32"); - PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW"); - } - - if (PrivateExtractIconExW) - PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1); - else -#endif - { - PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0); - PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0); - } - - if ( !hiconLarge || !hiconSmall) - { - WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall); - return -1; - } - return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge); -} -/***************************************************************************** - * SIC_GetIconIndex [internal] - * - * Parameters - * sSourceFile [IN] filename of file containing the icon - * index [IN] index/resID (negated) in this file - * - * NOTES - * look in the cache for a proper icon. if not available the icon is taken - * from the file and cached - */ -INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex ) -{ - SIC_ENTRY sice; - INT ret, index = INVALID_INDEX; - WCHAR path[MAX_PATH]; - - TRACE("%s %i\n", debugstr_w(sSourceFile), dwSourceIndex); - - GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL); - sice.sSourceFile = path; - sice.dwSourceIndex = dwSourceIndex; - - EnterCriticalSection(&SHELL32_SicCS); - - if (NULL != DPA_GetPtr (sic_hdpa, 0)) - { - /* search linear from position 0*/ - index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, 0); - } - - if ( INVALID_INDEX == index ) - { - ret = SIC_LoadIcon (sSourceFile, dwSourceIndex); - } - else - { - TRACE("-- found\n"); - ret = ((LPSIC_ENTRY)DPA_GetPtr(sic_hdpa, index))->dwListIndex; - } - - LeaveCriticalSection(&SHELL32_SicCS); - return ret; -} -/***************************************************************************** - * SIC_Initialize [internal] - * - * NOTES - * hack to load the resources from the shell32.dll under a different dll name - * will be removed when the resource-compiler is ready - */ -BOOL SIC_Initialize(void) -{ - HICON hSm, hLg; - UINT index; - int cx_small, cy_small; - int cx_large, cy_large; - - cx_small = GetSystemMetrics(SM_CXSMICON); - cy_small = GetSystemMetrics(SM_CYSMICON); - cx_large = GetSystemMetrics(SM_CXICON); - cy_large = GetSystemMetrics(SM_CYICON); - - TRACE("\n"); - - if (sic_hdpa) /* already initialized?*/ - return TRUE; - - sic_hdpa = DPA_Create(16); - - if (!sic_hdpa) - { - return(FALSE); - } - - ShellSmallIconList = ImageList_Create(16,16,ILC_COLOR32|ILC_MASK,0,0x20); - ShellBigIconList = ImageList_Create(32,32,ILC_COLOR32|ILC_MASK,0,0x20); - - ImageList_SetBkColor(ShellSmallIconList, CLR_NONE); - ImageList_SetBkColor(ShellBigIconList, CLR_NONE); - - for (index=1; index<39; index++) - { - hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_small, cy_small, LR_SHARED); - hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_large, cy_large, LR_SHARED); - - if(!hSm) - { - hSm = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_small, cy_small, LR_SHARED); - hLg = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_large, cy_large, LR_SHARED); - } - SIC_IconAppend (swShell32Name, index, hSm, hLg); - } - - TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList); - - return TRUE; -} -/************************************************************************* - * SIC_Destroy - * - * frees the cache - */ -static INT CALLBACK sic_free( LPVOID ptr, LPVOID lparam ) -{ - HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY)ptr)->sSourceFile); - SHFree(ptr); - return TRUE; -} - -void SIC_Destroy(void) -{ - TRACE("\n"); - - EnterCriticalSection(&SHELL32_SicCS); - - if (sic_hdpa) DPA_DestroyCallback(sic_hdpa, sic_free, NULL ); - - sic_hdpa = NULL; - ImageList_Destroy(ShellSmallIconList); - ShellSmallIconList = 0; - ImageList_Destroy(ShellBigIconList); - ShellBigIconList = 0; - - LeaveCriticalSection(&SHELL32_SicCS); - DeleteCriticalSection(&SHELL32_SicCS); -} - -/************************************************************************* - * Shell_GetImageList [SHELL32.71] - * - * PARAMETERS - * imglist[1|2] [OUT] pointer which receives imagelist handles - * - */ -BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList) -{ TRACE("(%p,%p)\n",lpBigList,lpSmallList); - if (lpBigList) - { *lpBigList = ShellBigIconList; - } - if (lpSmallList) - { *lpSmallList = ShellSmallIconList; - } - - return TRUE; -} -/************************************************************************* - * PidlToSicIndex [INTERNAL] - * - * PARAMETERS - * sh [IN] IShellFolder - * pidl [IN] - * bBigIcon [IN] - * uFlags [IN] GIL_* - * pIndex [OUT] index within the SIC - * - */ -BOOL PidlToSicIndex ( - IShellFolder * sh, - LPCITEMIDLIST pidl, - BOOL bBigIcon, - UINT uFlags, - int * pIndex) -{ - IExtractIconW *ei; - WCHAR szIconFile[MAX_PATH]; /* file containing the icon */ - INT iSourceIndex; /* index or resID(negated) in this file */ - BOOL ret = FALSE; - UINT dwFlags = 0; - - TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small"); - - if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei))) - { - if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags))) - { - *pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex); - ret = TRUE; - } - IExtractIconW_Release(ei); - } - - if (INVALID_INDEX == *pIndex) /* default icon when failed */ - *pIndex = 0; - - return ret; - -} - -/************************************************************************* - * SHMapPIDLToSystemImageListIndex [SHELL32.77] - * - * PARAMETERS - * sh [IN] pointer to an instance of IShellFolder - * pidl [IN] - * pIndex [OUT][OPTIONAL] SIC index for big icon - * - */ -int WINAPI SHMapPIDLToSystemImageListIndex( - IShellFolder *sh, - LPCITEMIDLIST pidl, - int *pIndex) -{ - int Index; - - TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex); - pdump(pidl); - - if (pIndex) - if (!PidlToSicIndex ( sh, pidl, 1, 0, pIndex)) - *pIndex = -1; - - if (!PidlToSicIndex ( sh, pidl, 0, 0, &Index)) - return -1; - - return Index; -} - -/************************************************************************* - * Shell_GetCachedImageIndex [SHELL32.72] - * - */ -INT WINAPI Shell_GetCachedImageIndexA(LPCSTR szPath, INT nIndex, BOOL bSimulateDoc) -{ - INT ret, len; - LPWSTR szTemp; - - WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath), nIndex, bSimulateDoc); - - len = MultiByteToWideChar( CP_ACP, 0, szPath, -1, NULL, 0 ); - szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, szPath, -1, szTemp, len ); - - ret = SIC_GetIconIndex( szTemp, nIndex ); - - HeapFree( GetProcessHeap(), 0, szTemp ); - - return ret; -} - -INT WINAPI Shell_GetCachedImageIndexW(LPCWSTR szPath, INT nIndex, BOOL bSimulateDoc) -{ - WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath), nIndex, bSimulateDoc); - - return SIC_GetIconIndex(szPath, nIndex); -} - -INT WINAPI Shell_GetCachedImageIndexAW(LPCVOID szPath, INT nIndex, BOOL bSimulateDoc) -{ if( SHELL_OsIsUnicode()) - return Shell_GetCachedImageIndexW(szPath, nIndex, bSimulateDoc); - return Shell_GetCachedImageIndexA(szPath, nIndex, bSimulateDoc); -} - -/************************************************************************* - * ExtractIconEx [SHELL32.@] - */ -UINT WINAPI ExtractIconExAW(LPCVOID lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons) -{ if (SHELL_OsIsUnicode()) - return ExtractIconExW ( lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); - return ExtractIconExA ( lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); -} - -/************************************************************************* - * ExtractIconExW [SHELL32.@] - * RETURNS - * 0 no icon found - * -1 file is not valid - * or number of icons extracted - */ -UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons) -{ - /* get entry point of undocumented function PrivateExtractIconExW() in user32 */ -#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER) - static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL; - - if (!PrivateExtractIconExW) { - HMODULE hUser32 = GetModuleHandleA("user32"); - PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW"); - - if (!PrivateExtractIconExW) - return 0; - } -#endif - - TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile), nIconIndex, phiconLarge, phiconSmall, nIcons); - - return PrivateExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); -} - -/************************************************************************* - * ExtractIconExA [SHELL32.@] - */ -UINT WINAPI ExtractIconExA(LPCSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons) -{ - UINT ret; - INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0); - LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - - TRACE("%s %i %p %p %i\n", lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); - - MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len); - ret = ExtractIconExW (lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIcons); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - return ret; -} - -/************************************************************************* - * ExtractAssociatedIconA (SHELL32.@) - * - * Return icon for given file (either from file itself or from associated - * executable) and patch parameters if needed. - */ -HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon) -{ - HICON hIcon; - WORD wDummyIcon = 0; - - TRACE("\n"); - - if(lpiIcon == NULL) - lpiIcon = &wDummyIcon; - - hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon); - - if( hIcon < (HICON)2 ) - { if( hIcon == (HICON)1 ) /* no icons found in given file */ - { char tempPath[0x80]; - HINSTANCE uRet = FindExecutableA(lpIconPath,NULL,tempPath); - - if( uRet > (HINSTANCE)32 && tempPath[0] ) - { strcpy(lpIconPath,tempPath); - hIcon = ExtractIconA(hInst, lpIconPath, *lpiIcon); - if( hIcon > (HICON)2 ) - return hIcon; - } - else hIcon = 0; - } - - if( hIcon == (HICON)1 ) - *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */ - else - *lpiIcon = 6; /* generic icon - found nothing */ - - if (GetModuleFileNameA(hInst, lpIconPath, 0x80)) - { - /* terminate string (GetModuleFileName doesn't do if buffer is too small) */ - lpIconPath[0x80 - 1] = '\0'; - hIcon = LoadIconA( hInst, MAKEINTRESOURCEA(*lpiIcon)); - } - } - return hIcon; -} - -/************************************************************************* - * ExtractAssociatedIconExW (SHELL32.@) - * - * Return icon for given file (either from file itself or from associated - * executable) and patch parameters if needed. - */ -HICON WINAPI ExtractAssociatedIconExW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId) -{ - FIXME("%p %s %p %p): stub\n", hInst, debugstr_w(lpIconPath), lpiIconIdx, lpiIconId); - return 0; -} - -/************************************************************************* - * ExtractAssociatedIconExA (SHELL32.@) - * - * Return icon for given file (either from file itself or from associated - * executable) and patch parameters if needed. - */ -HICON WINAPI ExtractAssociatedIconExA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId) -{ - HICON ret; - INT len = MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, NULL, 0 ); - LPWSTR lpwstrFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); - - TRACE("%p %s %p %p)\n", hInst, lpIconPath, lpiIconIdx, lpiIconId); - - MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, lpwstrFile, len ); - ret = ExtractAssociatedIconExW(hInst, lpwstrFile, lpiIconIdx, lpiIconId); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - return ret; -} - - -/**************************************************************************** - * SHDefExtractIconW [SHELL32.@] - */ -HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, - HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize) -{ - UINT ret; - HICON hIcons[2]; - WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); - - ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, hIcons, NULL, 2, LR_DEFAULTCOLOR); - /* FIXME: deal with uFlags parameter which contains GIL_ flags */ - if (ret == 0xFFFFFFFF) - return E_FAIL; - if (ret > 0) { - *phiconLarge = hIcons[0]; - *phiconSmall = hIcons[1]; - return S_OK; - } - return S_FALSE; -} - -/**************************************************************************** - * SHDefExtractIconA [SHELL32.@] - */ -HRESULT WINAPI SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags, - HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize) -{ - HRESULT ret; - INT len = MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, NULL, 0); - LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - - TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); - - MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, lpwstrFile, len); - ret = SHDefExtractIconW(lpwstrFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - return ret; -} +/* + * shell icon cache (SIC) + * + * Copyright 1998, 1999 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "wine/debug.h" + +#include "shellapi.h" +#include "objbase.h" +#include "shlguid.h" +#include "pidl.h" +#include "shell32_main.h" +#include "undocshell.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/********************** THE ICON CACHE ********************************/ + +#define INVALID_INDEX -1 + +typedef struct +{ + LPWSTR sSourceFile; /* file (not path!) containing the icon */ + DWORD dwSourceIndex; /* index within the file, if it is a resoure ID it will be negated */ + DWORD dwListIndex; /* index within the iconlist */ + DWORD dwFlags; /* GIL_* flags */ + DWORD dwAccessTime; +} SIC_ENTRY, * LPSIC_ENTRY; + +static HDPA sic_hdpa = 0; + +static CRITICAL_SECTION SHELL32_SicCS; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &SHELL32_SicCS, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": SHELL32_SicCS") } +}; +static CRITICAL_SECTION SHELL32_SicCS = { &critsect_debug, -1, 0, 0, 0, 0 }; + +/***************************************************************************** + * SIC_CompareEntries + * + * NOTES + * Callback for DPA_Search + */ +static INT CALLBACK SIC_CompareEntries( LPVOID p1, LPVOID p2, LPARAM lparam) +{ TRACE("%p %p %8lx\n", p1, p2, lparam); + + if (((LPSIC_ENTRY)p1)->dwSourceIndex != ((LPSIC_ENTRY)p2)->dwSourceIndex) /* first the faster one*/ + return 1; + + if (strcmpiW(((LPSIC_ENTRY)p1)->sSourceFile,((LPSIC_ENTRY)p2)->sSourceFile)) + return 1; + + return 0; +} +/***************************************************************************** + * SIC_IconAppend [internal] + * + * NOTES + * appends an icon pair to the end of the cache + */ +static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon) +{ LPSIC_ENTRY lpsice; + INT ret, index, index1; + WCHAR path[MAX_PATH]; + TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon); + + lpsice = (LPSIC_ENTRY) SHAlloc (sizeof (SIC_ENTRY)); + + GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL); + lpsice->sSourceFile = HeapAlloc( GetProcessHeap(), 0, (strlenW(path)+1)*sizeof(WCHAR) ); + strcpyW( lpsice->sSourceFile, path ); + + lpsice->dwSourceIndex = dwSourceIndex; + + EnterCriticalSection(&SHELL32_SicCS); + + index = DPA_InsertPtr(sic_hdpa, 0x7fff, lpsice); + if ( INVALID_INDEX == index ) + { + HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile); + SHFree(lpsice); + ret = INVALID_INDEX; + } + else + { + index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon); + index1= ImageList_AddIcon (ShellBigIconList, hBigIcon); + + if (index!=index1) + { + FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1); + } + lpsice->dwListIndex = index; + ret = lpsice->dwListIndex; + } + + LeaveCriticalSection(&SHELL32_SicCS); + return ret; +} +/**************************************************************************** + * SIC_LoadIcon [internal] + * + * NOTES + * gets small/big icon by number from a file + */ +static INT SIC_LoadIcon (LPCWSTR sSourceFile, INT dwSourceIndex) +{ HICON hiconLarge=0; + HICON hiconSmall=0; + +#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER) + static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL; + + if (!PrivateExtractIconExW) { + HMODULE hUser32 = GetModuleHandleA("user32"); + PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW"); + } + + if (PrivateExtractIconExW) + PrivateExtractIconExW(sSourceFile, dwSourceIndex, &hiconLarge, &hiconSmall, 1); + else +#endif + { + PrivateExtractIconsW(sSourceFile, dwSourceIndex, 32, 32, &hiconLarge, NULL, 1, 0); + PrivateExtractIconsW(sSourceFile, dwSourceIndex, 16, 16, &hiconSmall, NULL, 1, 0); + } + + if ( !hiconLarge || !hiconSmall) + { + WARN("failure loading icon %i from %s (%p %p)\n", dwSourceIndex, debugstr_w(sSourceFile), hiconLarge, hiconSmall); + return -1; + } + return SIC_IconAppend (sSourceFile, dwSourceIndex, hiconSmall, hiconLarge); +} +/***************************************************************************** + * SIC_GetIconIndex [internal] + * + * Parameters + * sSourceFile [IN] filename of file containing the icon + * index [IN] index/resID (negated) in this file + * + * NOTES + * look in the cache for a proper icon. if not available the icon is taken + * from the file and cached + */ +INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex ) +{ + SIC_ENTRY sice; + INT ret, index = INVALID_INDEX; + WCHAR path[MAX_PATH]; + + TRACE("%s %i\n", debugstr_w(sSourceFile), dwSourceIndex); + + GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL); + sice.sSourceFile = path; + sice.dwSourceIndex = dwSourceIndex; + + EnterCriticalSection(&SHELL32_SicCS); + + if (NULL != DPA_GetPtr (sic_hdpa, 0)) + { + /* search linear from position 0*/ + index = DPA_Search (sic_hdpa, &sice, 0, SIC_CompareEntries, 0, 0); + } + + if ( INVALID_INDEX == index ) + { + ret = SIC_LoadIcon (sSourceFile, dwSourceIndex); + } + else + { + TRACE("-- found\n"); + ret = ((LPSIC_ENTRY)DPA_GetPtr(sic_hdpa, index))->dwListIndex; + } + + LeaveCriticalSection(&SHELL32_SicCS); + return ret; +} +/***************************************************************************** + * SIC_Initialize [internal] + * + * NOTES + * hack to load the resources from the shell32.dll under a different dll name + * will be removed when the resource-compiler is ready + */ +BOOL SIC_Initialize(void) +{ + HICON hSm, hLg; + UINT index; + int cx_small, cy_small; + int cx_large, cy_large; + + cx_small = GetSystemMetrics(SM_CXSMICON); + cy_small = GetSystemMetrics(SM_CYSMICON); + cx_large = GetSystemMetrics(SM_CXICON); + cy_large = GetSystemMetrics(SM_CYICON); + + TRACE("\n"); + + if (sic_hdpa) /* already initialized?*/ + return TRUE; + + sic_hdpa = DPA_Create(16); + + if (!sic_hdpa) + { + return(FALSE); + } + + ShellSmallIconList = ImageList_Create(16,16,ILC_COLOR32|ILC_MASK,0,0x20); + ShellBigIconList = ImageList_Create(32,32,ILC_COLOR32|ILC_MASK,0,0x20); + + ImageList_SetBkColor(ShellSmallIconList, CLR_NONE); + ImageList_SetBkColor(ShellBigIconList, CLR_NONE); + + for (index=1; index<39; index++) + { + hSm = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_small, cy_small, LR_SHARED); + hLg = (HICON)LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(index), IMAGE_ICON, cx_large, cy_large, LR_SHARED); + + if(!hSm) + { + hSm = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_small, cy_small, LR_SHARED); + hLg = LoadImageA(shell32_hInstance, MAKEINTRESOURCEA(1), IMAGE_ICON, cx_large, cy_large, LR_SHARED); + } + SIC_IconAppend (swShell32Name, index, hSm, hLg); + } + + TRACE("hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList); + + return TRUE; +} +/************************************************************************* + * SIC_Destroy + * + * frees the cache + */ +static INT CALLBACK sic_free( LPVOID ptr, LPVOID lparam ) +{ + HeapFree(GetProcessHeap(), 0, ((LPSIC_ENTRY)ptr)->sSourceFile); + SHFree(ptr); + return TRUE; +} + +void SIC_Destroy(void) +{ + TRACE("\n"); + + EnterCriticalSection(&SHELL32_SicCS); + + if (sic_hdpa) DPA_DestroyCallback(sic_hdpa, sic_free, NULL ); + + sic_hdpa = NULL; + ImageList_Destroy(ShellSmallIconList); + ShellSmallIconList = 0; + ImageList_Destroy(ShellBigIconList); + ShellBigIconList = 0; + + LeaveCriticalSection(&SHELL32_SicCS); +} + +/************************************************************************* + * Shell_GetImageList [SHELL32.71] + * + * PARAMETERS + * imglist[1|2] [OUT] pointer which receives imagelist handles + * + */ +BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList) +{ TRACE("(%p,%p)\n",lpBigList,lpSmallList); + if (lpBigList) + { *lpBigList = ShellBigIconList; + } + if (lpSmallList) + { *lpSmallList = ShellSmallIconList; + } + + return TRUE; +} +/************************************************************************* + * PidlToSicIndex [INTERNAL] + * + * PARAMETERS + * sh [IN] IShellFolder + * pidl [IN] + * bBigIcon [IN] + * uFlags [IN] GIL_* + * pIndex [OUT] index within the SIC + * + */ +BOOL PidlToSicIndex ( + IShellFolder * sh, + LPCITEMIDLIST pidl, + BOOL bBigIcon, + UINT uFlags, + int * pIndex) +{ + IExtractIconW *ei; + WCHAR szIconFile[MAX_PATH]; /* file containing the icon */ + INT iSourceIndex; /* index or resID(negated) in this file */ + BOOL ret = FALSE; + UINT dwFlags = 0; + + TRACE("sf=%p pidl=%p %s\n", sh, pidl, bBigIcon?"Big":"Small"); + + if (SUCCEEDED (IShellFolder_GetUIObjectOf(sh, 0, 1, &pidl, &IID_IExtractIconW, 0, (void **)&ei))) + { + if (SUCCEEDED(IExtractIconW_GetIconLocation(ei, uFlags, szIconFile, MAX_PATH, &iSourceIndex, &dwFlags))) + { + *pIndex = SIC_GetIconIndex(szIconFile, iSourceIndex); + ret = TRUE; + } + IExtractIconW_Release(ei); + } + + if (INVALID_INDEX == *pIndex) /* default icon when failed */ + *pIndex = 0; + + return ret; + +} + +/************************************************************************* + * SHMapPIDLToSystemImageListIndex [SHELL32.77] + * + * PARAMETERS + * sh [IN] pointer to an instance of IShellFolder + * pidl [IN] + * pIndex [OUT][OPTIONAL] SIC index for big icon + * + */ +int WINAPI SHMapPIDLToSystemImageListIndex( + IShellFolder *sh, + LPCITEMIDLIST pidl, + int *pIndex) +{ + int Index; + + TRACE("(SF=%p,pidl=%p,%p)\n",sh,pidl,pIndex); + pdump(pidl); + + if (pIndex) + if (!PidlToSicIndex ( sh, pidl, 1, 0, pIndex)) + *pIndex = -1; + + if (!PidlToSicIndex ( sh, pidl, 0, 0, &Index)) + return -1; + + return Index; +} + +/************************************************************************* + * Shell_GetCachedImageIndex [SHELL32.72] + * + */ +INT WINAPI Shell_GetCachedImageIndexA(LPCSTR szPath, INT nIndex, BOOL bSimulateDoc) +{ + INT ret, len; + LPWSTR szTemp; + + WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_a(szPath), nIndex, bSimulateDoc); + + len = MultiByteToWideChar( CP_ACP, 0, szPath, -1, NULL, 0 ); + szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, szPath, -1, szTemp, len ); + + ret = SIC_GetIconIndex( szTemp, nIndex ); + + HeapFree( GetProcessHeap(), 0, szTemp ); + + return ret; +} + +INT WINAPI Shell_GetCachedImageIndexW(LPCWSTR szPath, INT nIndex, BOOL bSimulateDoc) +{ + WARN("(%s,%08x,%08x) semi-stub.\n",debugstr_w(szPath), nIndex, bSimulateDoc); + + return SIC_GetIconIndex(szPath, nIndex); +} + +INT WINAPI Shell_GetCachedImageIndexAW(LPCVOID szPath, INT nIndex, BOOL bSimulateDoc) +{ if( SHELL_OsIsUnicode()) + return Shell_GetCachedImageIndexW(szPath, nIndex, bSimulateDoc); + return Shell_GetCachedImageIndexA(szPath, nIndex, bSimulateDoc); +} + +/************************************************************************* + * ExtractIconExW [SHELL32.@] + * RETURNS + * 0 no icon found + * -1 file is not valid + * or number of icons extracted + */ +UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons) +{ + /* get entry point of undocumented function PrivateExtractIconExW() in user32 */ +#if defined(__CYGWIN__) || defined (__MINGW32__) || defined(_MSC_VER) + static UINT (WINAPI*PrivateExtractIconExW)(LPCWSTR,int,HICON*,HICON*,UINT) = NULL; + + if (!PrivateExtractIconExW) { + HMODULE hUser32 = GetModuleHandleA("user32"); + PrivateExtractIconExW = (UINT(WINAPI*)(LPCWSTR,int,HICON*,HICON*,UINT)) GetProcAddress(hUser32, "PrivateExtractIconExW"); + + if (!PrivateExtractIconExW) + return 0; + } +#endif + + TRACE("%s %i %p %p %i\n", debugstr_w(lpszFile), nIconIndex, phiconLarge, phiconSmall, nIcons); + + return PrivateExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); +} + +/************************************************************************* + * ExtractIconExA [SHELL32.@] + */ +UINT WINAPI ExtractIconExA(LPCSTR lpszFile, INT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIcons) +{ + UINT ret = 0; + INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0); + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + TRACE("%s %i %p %p %i\n", lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons); + + if (lpwstrFile) + { + MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len); + ret = ExtractIconExW(lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIcons); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + } + return ret; +} + +/************************************************************************* + * ExtractAssociatedIconA (SHELL32.@) + * + * Return icon for given file (either from file itself or from associated + * executable) and patch parameters if needed. + */ +HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon) +{ + HICON hIcon = NULL; + INT len = MultiByteToWideChar(CP_ACP, 0, lpIconPath, -1, NULL, 0); + LPWSTR lpIconPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + TRACE("%p %s %p\n", hInst, debugstr_a(lpIconPath), lpiIcon); + + if (lpIconPathW) + { + MultiByteToWideChar(CP_ACP, 0, lpIconPath, -1, lpIconPathW, len); + hIcon = ExtractAssociatedIconW(hInst, lpIconPathW, lpiIcon); + HeapFree(GetProcessHeap(), 0, lpIconPathW); + } + return hIcon; +} + +HICON WINAPI ExtractAssociatedIconW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIcon) +{ + HICON hIcon = NULL; + WORD wDummyIcon = 0; + + TRACE("%p %s %p\n", hInst, debugstr_w(lpIconPath), lpiIcon); + + if(lpiIcon == NULL) + lpiIcon = &wDummyIcon; + + hIcon = ExtractIconW(hInst, lpIconPath, *lpiIcon); + + if( hIcon < (HICON)2 ) + { if( hIcon == (HICON)1 ) /* no icons found in given file */ + { WCHAR tempPath[MAX_PATH]; + HINSTANCE uRet = FindExecutableW(lpIconPath,NULL,tempPath); + + if( uRet > (HINSTANCE)32 && tempPath[0] ) + { lstrcpyW(lpIconPath,tempPath); + hIcon = ExtractIconW(hInst, lpIconPath, *lpiIcon); + if( hIcon > (HICON)2 ) + return hIcon; + } + } + + if( hIcon == (HICON)1 ) + *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */ + else + *lpiIcon = 6; /* generic icon - found nothing */ + + if (GetModuleFileNameW(hInst, lpIconPath, MAX_PATH)) + hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(*lpiIcon)); + } + return hIcon; +} + +/************************************************************************* + * ExtractAssociatedIconExW (SHELL32.@) + * + * Return icon for given file (either from file itself or from associated + * executable) and patch parameters if needed. + */ +HICON WINAPI ExtractAssociatedIconExW(HINSTANCE hInst, LPWSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId) +{ + FIXME("%p %s %p %p): stub\n", hInst, debugstr_w(lpIconPath), lpiIconIdx, lpiIconId); + return 0; +} + +/************************************************************************* + * ExtractAssociatedIconExA (SHELL32.@) + * + * Return icon for given file (either from file itself or from associated + * executable) and patch parameters if needed. + */ +HICON WINAPI ExtractAssociatedIconExA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIconIdx, LPWORD lpiIconId) +{ + HICON ret; + INT len = MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, NULL, 0 ); + LPWSTR lpwstrFile = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + + TRACE("%p %s %p %p)\n", hInst, lpIconPath, lpiIconIdx, lpiIconId); + + MultiByteToWideChar( CP_ACP, 0, lpIconPath, -1, lpwstrFile, len ); + ret = ExtractAssociatedIconExW(hInst, lpwstrFile, lpiIconIdx, lpiIconId); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + return ret; +} + + +/**************************************************************************** + * SHDefExtractIconW [SHELL32.@] + */ +HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, + HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize) +{ + UINT ret; + HICON hIcons[2]; + WARN("%s %d 0x%08x %p %p %d, semi-stub\n", debugstr_w(pszIconFile), iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); + + ret = PrivateExtractIconsW(pszIconFile, iIndex, nIconSize, nIconSize, hIcons, NULL, 2, LR_DEFAULTCOLOR); + /* FIXME: deal with uFlags parameter which contains GIL_ flags */ + if (ret == 0xFFFFFFFF) + return E_FAIL; + if (ret > 0) { + *phiconLarge = hIcons[0]; + *phiconSmall = hIcons[1]; + return S_OK; + } + return S_FALSE; +} + +/**************************************************************************** + * SHDefExtractIconA [SHELL32.@] + */ +HRESULT WINAPI SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags, + HICON* phiconLarge, HICON* phiconSmall, UINT nIconSize) +{ + HRESULT ret; + INT len = MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, NULL, 0); + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + TRACE("%s %d 0x%08x %p %p %d\n", pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); + + MultiByteToWideChar(CP_ACP, 0, pszIconFile, -1, lpwstrFile, len); + ret = SHDefExtractIconW(lpwstrFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + return ret; +} diff --git a/reactos/lib/shell32/makefile b/reactos/lib/shell32/makefile index 263de228b36..b48614a5ce0 100644 --- a/reactos/lib/shell32/makefile +++ b/reactos/lib/shell32/makefile @@ -1,9 +1,9 @@ -# $Id: makefile 7409 2004-01-02 19:49:47Z gvg $ - -PATH_TO_TOP = ../.. - -TARGET_TYPE = winedll - -include $(PATH_TO_TOP)/rules.mak - -include $(TOOLS_PATH)/helper.mk +# $Id: makefile 7409 2004-01-02 19:49:47Z gvg $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = winedll + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/lib/shell32/memorystream.c b/reactos/lib/shell32/memorystream.c index 33cd883cc4c..ff7ea0b00c8 100644 --- a/reactos/lib/shell32/memorystream.c +++ b/reactos/lib/shell32/memorystream.c @@ -1,296 +1,296 @@ -/* - * this class implements a pure IStream object - * and can be used for many purposes - * - * the main reason for implementing this was - * a cleaner implementation of IShellLink which - * needs to be able to load lnk's from a IStream - * interface so it was obvious to capsule the file - * access in a IStream to. - * - * Copyright 1999 Juergen Schmied - * Copyright 2003 Mike McCormack for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winuser.h" -#include "wingdi.h" -#include "shlobj.h" -#include "wine/debug.h" -#include "shell32_main.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -static const IStreamVtbl stvt; - -typedef struct -{ - const IStreamVtbl *lpvtst; - DWORD ref; - HANDLE handle; -} ISHFileStream; - -/************************************************************************** - * CreateStreamOnFile() - * - * similar to CreateStreamOnHGlobal - */ -HRESULT CreateStreamOnFile (LPCWSTR pszFilename, DWORD grfMode, IStream ** ppstm) -{ - ISHFileStream* fstr; - HANDLE handle; - DWORD access = GENERIC_READ, creat; - - if( grfMode & STGM_TRANSACTED ) - return E_INVALIDARG; - - if( grfMode & STGM_WRITE ) - access |= GENERIC_WRITE; - if( grfMode & STGM_READWRITE ) - access = GENERIC_WRITE | GENERIC_READ; - - if( grfMode & STGM_CREATE ) - creat = CREATE_ALWAYS; - else - creat = OPEN_EXISTING; - - TRACE("Opening %s\n", debugstr_w(pszFilename) ); - - handle = CreateFileW( pszFilename, access, FILE_SHARE_READ, NULL, creat, 0, NULL ); - if( handle == INVALID_HANDLE_VALUE ) - return HRESULT_FROM_WIN32(GetLastError()); - - fstr = (ISHFileStream*)HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY,sizeof(ISHFileStream)); - if( !fstr ) - return E_OUTOFMEMORY; - fstr->lpvtst=&stvt; - fstr->ref = 1; - fstr->handle = handle; - - (*ppstm) = (IStream*)fstr; - - return S_OK; -} - -/************************************************************************** -* IStream_fnQueryInterface -*/ -static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IStream)) - { - *ppvObj = This; - } - - if(*ppvObj) - { - IStream_AddRef((IStream*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* IStream_fnAddRef -*/ -static ULONG WINAPI IStream_fnAddRef(IStream *iface) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)->(count=%lu)\n",This, This->ref); - - return ++(This->ref); -} - -/************************************************************************** -* IStream_fnRelease -*/ -static ULONG WINAPI IStream_fnRelease(IStream *iface) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying SHFileStream (%p)\n",This); - CloseHandle(This->handle); - HeapFree(GetProcessHeap(),0,This); - } - return This->ref; -} - -static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead); - - if ( !pv ) - return STG_E_INVALIDPOINTER; - - if ( ! ReadFile( This->handle, pv, cb, pcbRead, NULL ) ) - return S_FALSE; - - return S_OK; -} - -static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten) -{ - DWORD dummy_count; - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - if( !pv ) - return STG_E_INVALIDPOINTER; - - /* WriteFile() doesn't allow to specify NULL as write count pointer */ - if (!pcbWritten) - pcbWritten = &dummy_count; - - if( ! WriteFile( This->handle, pv, cb, pcbWritten, NULL ) ) - return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) -{ - DWORD pos, newposlo, newposhi; - - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - pos = dlibMove.QuadPart; /* FIXME: truncates */ - newposhi = 0; - newposlo = SetFilePointer( This->handle, pos, &newposhi, dwOrigin ); - if( newposlo == INVALID_SET_FILE_POINTER ) - return E_FAIL; - - plibNewPosition->QuadPart = newposlo | ( (LONGLONG)newposhi<<32); - - return S_OK; -} - -static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - if( ! SetFilePointer( This->handle, libNewSize.QuadPart, NULL, FILE_BEGIN ) ) - return E_FAIL; - - if( ! SetEndOfFile( This->handle ) ) - return E_FAIL; - - return S_OK; -} -static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnRevert (IStream * iface) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm) -{ - ISHFileStream *This = (ISHFileStream *)iface; - - TRACE("(%p)\n",This); - - return E_NOTIMPL; -} - -static const IStreamVtbl stvt = -{ - IStream_fnQueryInterface, - IStream_fnAddRef, - IStream_fnRelease, - IStream_fnRead, - IStream_fnWrite, - IStream_fnSeek, - IStream_fnSetSize, - IStream_fnCopyTo, - IStream_fnCommit, - IStream_fnRevert, - IStream_fnLockRegion, - IStream_fnUnlockRegion, - IStream_fnStat, - IStream_fnClone - -}; +/* + * this class implements a pure IStream object + * and can be used for many purposes + * + * the main reason for implementing this was + * a cleaner implementation of IShellLink which + * needs to be able to load lnk's from a IStream + * interface so it was obvious to capsule the file + * access in a IStream to. + * + * Copyright 1999 Juergen Schmied + * Copyright 2003 Mike McCormack for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winuser.h" +#include "wingdi.h" +#include "shlobj.h" +#include "wine/debug.h" +#include "shell32_main.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +static const IStreamVtbl stvt; + +typedef struct +{ + const IStreamVtbl *lpvtst; + DWORD ref; + HANDLE handle; +} ISHFileStream; + +/************************************************************************** + * CreateStreamOnFile() + * + * similar to CreateStreamOnHGlobal + */ +HRESULT CreateStreamOnFile (LPCWSTR pszFilename, DWORD grfMode, IStream ** ppstm) +{ + ISHFileStream* fstr; + HANDLE handle; + DWORD access = GENERIC_READ, creat; + + if( grfMode & STGM_TRANSACTED ) + return E_INVALIDARG; + + if( grfMode & STGM_WRITE ) + access |= GENERIC_WRITE; + if( grfMode & STGM_READWRITE ) + access = GENERIC_WRITE | GENERIC_READ; + + if( grfMode & STGM_CREATE ) + creat = CREATE_ALWAYS; + else + creat = OPEN_EXISTING; + + TRACE("Opening %s\n", debugstr_w(pszFilename) ); + + handle = CreateFileW( pszFilename, access, FILE_SHARE_READ, NULL, creat, 0, NULL ); + if( handle == INVALID_HANDLE_VALUE ) + return HRESULT_FROM_WIN32(GetLastError()); + + fstr = (ISHFileStream*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY,sizeof(ISHFileStream)); + if( !fstr ) + return E_OUTOFMEMORY; + fstr->lpvtst=&stvt; + fstr->ref = 1; + fstr->handle = handle; + + (*ppstm) = (IStream*)fstr; + + return S_OK; +} + +/************************************************************************** +* IStream_fnQueryInterface +*/ +static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IStream)) + { + *ppvObj = This; + } + + if(*ppvObj) + { + IStream_AddRef((IStream*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** +* IStream_fnAddRef +*/ +static ULONG WINAPI IStream_fnAddRef(IStream *iface) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)->(count=%lu)\n",This, This->ref); + + return ++(This->ref); +} + +/************************************************************************** +* IStream_fnRelease +*/ +static ULONG WINAPI IStream_fnRelease(IStream *iface) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying SHFileStream (%p)\n",This); + CloseHandle(This->handle); + HeapFree(GetProcessHeap(),0,This); + } + return This->ref; +} + +static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead); + + if ( !pv ) + return STG_E_INVALIDPOINTER; + + if ( ! ReadFile( This->handle, pv, cb, pcbRead, NULL ) ) + return S_FALSE; + + return S_OK; +} + +static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten) +{ + DWORD dummy_count; + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + if( !pv ) + return STG_E_INVALIDPOINTER; + + /* WriteFile() doesn't allow to specify NULL as write count pointer */ + if (!pcbWritten) + pcbWritten = &dummy_count; + + if( ! WriteFile( This->handle, pv, cb, pcbWritten, NULL ) ) + return E_FAIL; + + return S_OK; +} + +static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) +{ + DWORD pos, newposlo, newposhi; + + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + pos = dlibMove.QuadPart; /* FIXME: truncates */ + newposhi = 0; + newposlo = SetFilePointer( This->handle, pos, &newposhi, dwOrigin ); + if( newposlo == INVALID_SET_FILE_POINTER ) + return E_FAIL; + + plibNewPosition->QuadPart = newposlo | ( (LONGLONG)newposhi<<32); + + return S_OK; +} + +static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + if( ! SetFilePointer( This->handle, libNewSize.QuadPart, NULL, FILE_BEGIN ) ) + return E_FAIL; + + if( ! SetEndOfFile( This->handle ) ) + return E_FAIL; + + return S_OK; +} +static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnRevert (IStream * iface) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm) +{ + ISHFileStream *This = (ISHFileStream *)iface; + + TRACE("(%p)\n",This); + + return E_NOTIMPL; +} + +static const IStreamVtbl stvt = +{ + IStream_fnQueryInterface, + IStream_fnAddRef, + IStream_fnRelease, + IStream_fnRead, + IStream_fnWrite, + IStream_fnSeek, + IStream_fnSetSize, + IStream_fnCopyTo, + IStream_fnCommit, + IStream_fnRevert, + IStream_fnLockRegion, + IStream_fnUnlockRegion, + IStream_fnStat, + IStream_fnClone + +}; diff --git a/reactos/lib/shell32/pidl.c b/reactos/lib/shell32/pidl.c index 9b32239bf33..f77343c7453 100644 --- a/reactos/lib/shell32/pidl.c +++ b/reactos/lib/shell32/pidl.c @@ -1,2233 +1,2220 @@ -/* - * pidl Handling - * - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * a pidl == NULL means desktop and is legal - * - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "objbase.h" -#include "shlguid.h" -#include "winerror.h" -#include "winnls.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shellapi.h" -#include "shlwapi.h" - -#include "pidl.h" -#include "debughlp.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(pidl); -WINE_DECLARE_DEBUG_CHANNEL(shell); - -/* from comctl32.dll */ -extern LPVOID WINAPI Alloc(INT); -extern BOOL WINAPI Free(LPVOID); - -/************************************************************************* - * ILGetDisplayNameEx [SHELL32.186] - * - * Retrieves the display name of an ItemIDList - * - * PARAMS - * psf [I] Shell Folder to start with, if NULL the desktop is used - * pidl [I] ItemIDList relativ to the psf to get the display name for - * path [O] Filled in with the display name, assumed to be at least MAX_PATH long - * type [I] Type of display name to retrieve - * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root - * 1 = SHGDN_NORMAL relative to the root folder - * 2 = SHGDN_INFOLDER relative to the root folder, only the last name - * - * RETURNS - * True if the display name could be retrieved successfully, False otherwise - */ -BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type) -{ - BOOL ret = FALSE; - WCHAR wPath[MAX_PATH]; - - TRACE("%p %p %p %ld\n", psf, pidl, path, type); - - if (!pidl || !path) - return FALSE; - - ret = ILGetDisplayNameExW(psf, pidl, wPath, type); - WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL); - TRACE("%p %p %s\n", psf, pidl, debugstr_a(path)); - - return ret; -} - -BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type) -{ - LPSHELLFOLDER psfParent, lsf = psf; - HRESULT ret = NO_ERROR; - LPCITEMIDLIST pidllast; - STRRET strret; - DWORD flag; - - TRACE("%p %p %p %ld\n", psf, pidl, path, type); - - if (!pidl || !path) - return FALSE; - - if (!lsf) - { - ret = SHGetDesktopFolder(&lsf); - if (FAILED(ret)) - return FALSE; - } - - if (type >= 0 && type <= 2) - { - switch (type) - { - case ILGDN_FORPARSING: - flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR; - break; - case ILGDN_NORMAL: - flag = SHGDN_NORMAL; - break; - case ILGDN_INFOLDER: - flag = SHGDN_INFOLDER; - break; - default: - FIXME("Unknown type parameter = %lx\n", type); - flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR; - break; - } - if (!*(const WORD*)pidl || type == ILGDN_FORPARSING) - { - ret = IShellFolder_GetDisplayNameOf(lsf, pidl, flag, &strret); - if (SUCCEEDED(ret)) - { - ret = StrRetToStrNW(path, MAX_PATH, &strret, pidl); - } - } - else - { - ret = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidllast); - if (SUCCEEDED(ret)) - { - ret = IShellFolder_GetDisplayNameOf(psfParent, pidllast, flag, &strret); - if (SUCCEEDED(ret)) - { - ret = StrRetToStrNW(path, MAX_PATH, &strret, pidllast); - } - IShellFolder_Release(psfParent); - } - } - } - - TRACE("%p %p %s\n", psf, pidl, debugstr_w(path)); - - if (!psf) - IShellFolder_Release(lsf); - return SUCCEEDED(ret); -} - -BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type) -{ - TRACE_(shell)("%p %p %p %ld\n", psf, pidl, path, type); - if (SHELL_OsIsUnicode()) - return ILGetDisplayNameExW(psf, pidl, path, type); - return ILGetDisplayNameExA(psf, pidl, path, type); -} - -/************************************************************************* - * ILGetDisplayName [SHELL32.15] - */ -BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path) -{ - TRACE_(shell)("%p %p\n", pidl, path); - if (SHELL_OsIsUnicode()) - return ILGetDisplayNameExW(NULL, pidl, path, ILGDN_FORPARSING); - return ILGetDisplayNameExA(NULL, pidl, path, ILGDN_FORPARSING); -} - -/************************************************************************* - * ILFindLastID [SHELL32.16] - * - * NOTES - * observed: pidl=Desktop return=pidl - */ -LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl) -{ - LPCITEMIDLIST pidlLast = pidl; - - TRACE("(pidl=%p)\n",pidl); - - if (!pidl) - return NULL; - - while (pidl->mkid.cb) - { - pidlLast = pidl; - pidl = ILGetNext(pidl); - } - return (LPITEMIDLIST)pidlLast; -} -/************************************************************************* - * ILRemoveLastID [SHELL32.17] - * - * NOTES - * when pidl=Desktop return=FALSE - */ -BOOL WINAPI ILRemoveLastID(LPITEMIDLIST pidl) -{ - TRACE_(shell)("pidl=%p\n",pidl); - - if (!pidl || !pidl->mkid.cb) - return 0; - ILFindLastID(pidl)->mkid.cb = 0; - return 1; -} - -/************************************************************************* - * ILClone [SHELL32.18] - * - * NOTES - * duplicate an idlist - */ -LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl) -{ DWORD len; - LPITEMIDLIST newpidl; - - if (!pidl) - return NULL; - - len = ILGetSize(pidl); - newpidl = (LPITEMIDLIST)SHAlloc(len); - if (newpidl) - memcpy(newpidl,pidl,len); - - TRACE("pidl=%p newpidl=%p\n",pidl, newpidl); - pdump(pidl); - - return newpidl; -} -/************************************************************************* - * ILCloneFirst [SHELL32.19] - * - * NOTES - * duplicates the first idlist of a complex pidl - */ -LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl) -{ DWORD len; - LPITEMIDLIST pidlNew = NULL; - - TRACE("pidl=%p \n",pidl); - pdump(pidl); - - if (pidl) - { - len = pidl->mkid.cb; - pidlNew = (LPITEMIDLIST) SHAlloc (len+2); - if (pidlNew) - { - memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */ - - if (len) - ILGetNext(pidlNew)->mkid.cb = 0x00; - } - } - TRACE("-- newpidl=%p\n",pidlNew); - - return pidlNew; -} - -/************************************************************************* - * ILLoadFromStream (SHELL32.26) - * - * NOTES - * the first two bytes are the len, the pidl is following then - */ -HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl) -{ WORD wLen = 0; - DWORD dwBytesRead; - HRESULT ret = E_FAIL; - - - TRACE_(shell)("%p %p\n", pStream , ppPidl); - - if (*ppPidl) - { SHFree(*ppPidl); - *ppPidl = NULL; - } - - IStream_AddRef (pStream); - - if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead))) - { - TRACE("PIDL length is %d\n", wLen); - if (wLen != 0) { - *ppPidl = SHAlloc (wLen); - if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead))) { - TRACE("Stream read OK\n"); - ret = S_OK; - } else { - WARN("reading pidl failed\n"); - SHFree(*ppPidl); - *ppPidl = NULL; - } - } else { - *ppPidl = NULL; - ret = S_OK; - } - } - - /* we are not yet fully compatible */ - if (*ppPidl && !pcheck(*ppPidl)) - { - WARN("Check failed\n"); - SHFree(*ppPidl); - *ppPidl = NULL; - } - - - IStream_Release (pStream); - TRACE("done\n"); - return ret; -} - -/************************************************************************* - * ILSaveToStream (SHELL32.27) - * - * NOTES - * the first two bytes are the len, the pidl is following then - */ -HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl) -{ - LPCITEMIDLIST pidl; - WORD wLen = 0; - HRESULT ret = E_FAIL; - - TRACE_(shell)("%p %p\n", pStream, pPidl); - - IStream_AddRef (pStream); - - pidl = pPidl; - while (pidl->mkid.cb) - { - wLen += sizeof(WORD) + pidl->mkid.cb; - pidl = ILGetNext(pidl); - } - - if (SUCCEEDED(IStream_Write(pStream, (LPVOID)&wLen, 2, NULL))) - { - if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL))) - { ret = S_OK; - } - } - IStream_Release (pStream); - - return ret; -} - -/************************************************************************* - * SHILCreateFromPath [SHELL32.28] - * - * Create an ItemIDList from a path - * - * PARAMS - * path [I] - * ppidl [O] - * attributes [I/O] requested attributes on call and actual attributes when - * the function returns - * - * RETURNS - * NO_ERROR if successful, or an OLE errer code otherwise - * - * NOTES - * Wrapper for IShellFolder_ParseDisplayName(). - */ -HRESULT WINAPI SHILCreateFromPathA(LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes) -{ - LPSHELLFOLDER sf; - WCHAR lpszDisplayName[MAX_PATH]; - DWORD pchEaten; - HRESULT ret = E_FAIL; - - TRACE_(shell)("%s %p 0x%08lx\n", path, ppidl, attributes ? *attributes : 0); - - if (!MultiByteToWideChar(CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH)) - lpszDisplayName[MAX_PATH-1] = 0; - - if (SUCCEEDED (SHGetDesktopFolder(&sf))) - { - ret = IShellFolder_ParseDisplayName(sf, 0, NULL, lpszDisplayName, &pchEaten, ppidl, attributes); - IShellFolder_Release(sf); - } - return ret; -} - -HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes) -{ - LPSHELLFOLDER sf; - DWORD pchEaten; - HRESULT ret = E_FAIL; - - TRACE_(shell)("%s %p 0x%08lx\n", debugstr_w(path), ppidl, attributes ? *attributes : 0); - - if (SUCCEEDED (SHGetDesktopFolder(&sf))) - { - ret = IShellFolder_ParseDisplayName(sf, 0, NULL, (LPWSTR)path, &pchEaten, ppidl, attributes); - IShellFolder_Release(sf); - } - return ret; -} - -HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes) -{ - if ( SHELL_OsIsUnicode()) - return SHILCreateFromPathW (path, ppidl, attributes); - return SHILCreateFromPathA (path, ppidl, attributes); -} - -/************************************************************************* - * SHCloneSpecialIDList [SHELL32.89] - * - * Create an ItemIDList to one of the special folders. - - * PARAMS - * hwndOwner [in] - * nFolder [in] CSIDL_xxxxx - * fCreate [in] Create folder if it does not exist - * - * RETURNS - * Success: The newly created pidl - * Failure: NULL, if inputs are invalid. - * - * NOTES - * exported by ordinal. - * Caller is responsible for deallocating the returned ItemIDList with the - * shells IMalloc interface, aka ILFree. - */ -LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner, DWORD nFolder, BOOL fCreate) -{ LPITEMIDLIST ppidl; - TRACE_(shell)("(hwnd=%p,csidl=0x%lx,%s).\n", hwndOwner, nFolder, fCreate ? "T" : "F"); - - if (fCreate) - nFolder |= CSIDL_FLAG_CREATE; - - SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl); - return ppidl; -} - -/************************************************************************* - * ILGlobalClone [SHELL32.20] - * - * Clones an ItemIDList using Alloc. - * - * PARAMS - * pidl [I] ItemIDList to clone - * - * RETURNS - * Newly allocated ItemIDList. - * - * NOTES - * exported by ordinal. - */ -LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl) -{ DWORD len; - LPITEMIDLIST newpidl; - - if (!pidl) - return NULL; - - len = ILGetSize(pidl); - newpidl = (LPITEMIDLIST)Alloc(len); - if (newpidl) - memcpy(newpidl,pidl,len); - - TRACE("pidl=%p newpidl=%p\n",pidl, newpidl); - pdump(pidl); - - return newpidl; -} - -/************************************************************************* - * ILIsEqual [SHELL32.21] - * - */ -BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - char szData1[MAX_PATH]; - char szData2[MAX_PATH]; - - LPCITEMIDLIST pidltemp1 = pidl1; - LPCITEMIDLIST pidltemp2 = pidl2; - - TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2); - - /* explorer reads from registry directly (StreamMRU), - so we can only check here */ - if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE; - - pdump (pidl1); - pdump (pidl2); - - if ( (!pidl1) || (!pidl2) ) return FALSE; - - while (pidltemp1->mkid.cb && pidltemp2->mkid.cb) - { - _ILSimpleGetText(pidltemp1, szData1, MAX_PATH); - _ILSimpleGetText(pidltemp2, szData2, MAX_PATH); - - if (strcasecmp ( szData1, szData2 )!=0 ) - return FALSE; - - pidltemp1 = ILGetNext(pidltemp1); - pidltemp2 = ILGetNext(pidltemp2); - } - - if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb) - { - return TRUE; - } - - return FALSE; -} -/************************************************************************* - * ILIsParent [SHELL32.23] - * - * Verifies that pidlParent is indeed the (immediate) parent of pidlChild. - * - * PARAMS - * pidlParent [I] - * pidlChild [I] - * bImmediate [I] only return true if the parent is the direct parent - * of the child - * - * RETURNS - * True if the parent ItemIDlist is a complete part of the child ItemIdList, - * False otherwise. - * - * NOTES - * parent = a/b, child = a/b/c -> true, c is in folder a/b - * child = a/b/c/d -> false if bImmediate is true, d is not in folder a/b - * child = a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b - */ -BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate) -{ - char szData1[MAX_PATH]; - char szData2[MAX_PATH]; - - LPCITEMIDLIST pParent = pidlParent; - LPCITEMIDLIST pChild = pidlChild; - - TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate); - - if (!pParent || !pChild) return FALSE; - - while (pParent->mkid.cb && pChild->mkid.cb) - { - _ILSimpleGetText(pParent, szData1, MAX_PATH); - _ILSimpleGetText(pChild, szData2, MAX_PATH); - - if (strcasecmp ( szData1, szData2 )!=0 ) - return FALSE; - - pParent = ILGetNext(pParent); - pChild = ILGetNext(pChild); - } - - if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */ - return FALSE; - - if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */ - return FALSE; - - return TRUE; -} - -/************************************************************************* - * ILFindChild [SHELL32.24] - * - * Compares elements from pidl1 and pidl2. - * - * PARAMS - * pidl1 [I] - * pidl2 [I] - * - * RETURNS - * pidl1 is desktop pidl2 - * pidl1 shorter pidl2 pointer to first different element of pidl2 - * if there was at least one equal element - * pidl2 shorter pidl1 0 - * pidl2 equal pidl1 pointer to last 0x00-element of pidl2 - * - * NOTES - * exported by ordinal. - */ -LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - char szData1[MAX_PATH]; - char szData2[MAX_PATH]; - - LPCITEMIDLIST pidltemp1 = pidl1; - LPCITEMIDLIST pidltemp2 = pidl2; - LPCITEMIDLIST ret=NULL; - - TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2); - - /* explorer reads from registry directly (StreamMRU), - so we can only check here */ - if ((!pcheck (pidl1)) || (!pcheck (pidl2))) - return FALSE; - - pdump (pidl1); - pdump (pidl2); - - if ( _ILIsDesktop(pidl1) ) - { - ret = pidl2; - } - else - { - while (pidltemp1->mkid.cb && pidltemp2->mkid.cb) - { - _ILSimpleGetText(pidltemp1, szData1, MAX_PATH); - _ILSimpleGetText(pidltemp2, szData2, MAX_PATH); - - if (strcasecmp(szData1,szData2)) - break; - - pidltemp1 = ILGetNext(pidltemp1); - pidltemp2 = ILGetNext(pidltemp2); - ret = pidltemp2; - } - - if (pidltemp1->mkid.cb) - { - ret = NULL; /* elements of pidl1 left*/ - } - } - TRACE_(shell)("--- %p\n", ret); - return (LPITEMIDLIST)ret; /* pidl 1 is shorter */ -} - -/************************************************************************* - * ILCombine [SHELL32.25] - * - * Concatenates two complex ItemIDLists. - * - * PARAMS - * pidl1 [I] first complex ItemIDLists - * pidl2 [I] complex ItemIDLists to append - * - * RETURNS - * if both pidl's == NULL NULL - * if pidl1 == NULL cloned pidl2 - * if pidl2 == NULL cloned pidl1 - * otherwise new pidl with pidl2 appended to pidl1 - * - * NOTES - * exported by ordinal. - * Does not destroy the passed in ItemIDLists! - */ -LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - DWORD len1,len2; - LPITEMIDLIST pidlNew; - - TRACE("pidl=%p pidl=%p\n",pidl1,pidl2); - - if(!pidl1 && !pidl2) return NULL; - - pdump (pidl1); - pdump (pidl2); - - if(!pidl1) - { - pidlNew = ILClone(pidl2); - return pidlNew; - } - - if(!pidl2) - { - pidlNew = ILClone(pidl1); - return pidlNew; - } - - len1 = ILGetSize(pidl1)-2; - len2 = ILGetSize(pidl2); - pidlNew = SHAlloc(len1+len2); - - if (pidlNew) - { - memcpy(pidlNew,pidl1,len1); - memcpy(((BYTE *)pidlNew)+len1,pidl2,len2); - } - - /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/ - return pidlNew; -} - -/************************************************************************* - * SHGetRealIDL [SHELL32.98] - * - * NOTES - */ -HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEMIDLIST *pidlReal) -{ - IDataObject* pDataObj; - HRESULT hr = IShellFolder_GetUIObjectOf(lpsf, 0, 1, &pidlSimple, &IID_IDataObject, 0, (LPVOID*)&pDataObj); - - if (SUCCEEDED(hr)) { - STGMEDIUM medium; - FORMATETC fmt; - - fmt.cfFormat = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); - fmt.ptd = NULL; - fmt.dwAspect = DVASPECT_CONTENT; - fmt.lindex = -1; - fmt.tymed = TYMED_HGLOBAL; - - hr = IDataObject_GetData(pDataObj, &fmt, &medium); - - IDataObject_Release(pDataObj); - - if (SUCCEEDED(hr)) { - /*assert(pida->cidl==1);*/ - LPIDA pida = (LPIDA)GlobalLock(medium.u.hGlobal); - - LPCITEMIDLIST pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]); - LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]); - - *pidlReal = ILCombine(pidl_folder, pidl_child); - - if (!*pidlReal) - hr = E_OUTOFMEMORY; - - GlobalUnlock(medium.u.hGlobal); - GlobalFree(medium.u.hGlobal); - } - } - - return hr; -} - -/************************************************************************* - * SHLogILFromFSIL [SHELL32.95] - * - * NOTES - * pild = CSIDL_DESKTOP ret = 0 - * pild = CSIDL_DRIVES ret = 0 - */ -LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl) -{ - FIXME("(pidl=%p)\n",pidl); - - pdump(pidl); - - return 0; -} - -/************************************************************************* - * ILGetSize [SHELL32.152] - * - * Gets the byte size of an ItemIDList including zero terminator - * - * PARAMS - * pidl [I] ItemIDList - * - * RETURNS - * size of pidl in bytes - * - * NOTES - * exported by ordinal - */ -UINT WINAPI ILGetSize(LPCITEMIDLIST pidl) -{ - LPCSHITEMID si = &(pidl->mkid); - UINT len=0; - - if (pidl) - { while (si->cb) - { len += si->cb; - si = (LPCSHITEMID)(((const BYTE*)si)+si->cb); - } - len += 2; - } - TRACE("pidl=%p size=%u\n",pidl, len); - return len; -} - -/************************************************************************* - * ILGetNext [SHELL32.153] - * - * Gets the next ItemID of an ItemIDList - * - * PARAMS - * pidl [I] ItemIDList - * - * RETURNS - * null -> null - * desktop -> null - * simple pidl -> pointer to 0x0000 element - * - * NOTES - * exported by ordinal. - */ -LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl) -{ - WORD len; - - TRACE("%p\n", pidl); - - if(pidl) - { - len = pidl->mkid.cb; - if (len) - { - pidl = (LPCITEMIDLIST) (((const BYTE*)pidl)+len); - TRACE("-- %p\n", pidl); - return (LPITEMIDLIST)pidl; - } - } - return NULL; -} - -/************************************************************************* - * ILAppend [SHELL32.154] - * - * Adds the single ItemID item to the ItemIDList indicated by pidl. - * If bEnd is FALSE, inserts the item in the front of the list, - * otherwise it adds the item to the end. (???) - * - * PARAMS - * pidl [I] ItemIDList to extend - * item [I] ItemID to prepend/append - * bEnd [I] Indicates if the item should be appended - * - * NOTES - * Destroys the passed in idlist! (???) - */ -LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl, LPCITEMIDLIST item, BOOL bEnd) -{ - LPITEMIDLIST idlRet; - - WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd); - - pdump (pidl); - pdump (item); - - if (_ILIsDesktop(pidl)) - { - idlRet = ILClone(item); - if (pidl) - SHFree (pidl); - return idlRet; - } - - if (bEnd) - { - idlRet = ILCombine(pidl, item); - } - else - { - idlRet = ILCombine(item, pidl); - } - - SHFree(pidl); - return idlRet; -} - -/************************************************************************* - * ILFree [SHELL32.155] - * - * Frees memory (if not NULL) allocated by SHMalloc allocator - * - * PARAMS - * pidl [I] - * - * NOTES - * exported by ordinal - */ -void WINAPI ILFree(LPITEMIDLIST pidl) -{ - TRACE("(pidl=%p)\n",pidl); - if(pidl) SHFree(pidl); -} - -/************************************************************************* - * ILGlobalFree [SHELL32.156] - * - * Frees memory (if not NULL) allocated by Alloc allocator - * - * PARAMS - * pidl [I] - * - * NOTES - * exported by ordinal. - */ -void WINAPI ILGlobalFree( LPITEMIDLIST pidl) -{ - TRACE("%p\n", pidl); - - if(!pidl) return; - Free(pidl); -} - -/************************************************************************* - * ILCreateFromPathA [SHELL32.189] - * - * Creates a complex ItemIDList from a path and returns it. - * - * PARAMS - * path [I] - * - * RETURNS - * the newly created complex ItemIDList or NULL if failed - * - * NOTES - * exported by ordinal. - */ - -LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path) -{ - LPITEMIDLIST pidlnew = NULL; - - TRACE_(shell)("%s\n", debugstr_a(path)); - - if (SUCCEEDED(SHILCreateFromPathA(path, &pidlnew, NULL))) - return pidlnew; - return NULL; -} - -/************************************************************************* - * ILCreateFromPathW [SHELL32.190] - */ -LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path) -{ - LPITEMIDLIST pidlnew = NULL; - - TRACE_(shell)("%s\n", debugstr_w(path)); - - if (SUCCEEDED(SHILCreateFromPathW(path, &pidlnew, NULL))) - return pidlnew; - return NULL; -} - -/************************************************************************* - * ILCreateFromPath [SHELL32.157] - */ -LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path) -{ - if ( SHELL_OsIsUnicode()) - return ILCreateFromPathW (path); - return ILCreateFromPathA (path); -} - -/************************************************************************* - * _ILParsePathW [internal] - * - * Creates an ItemIDList from a path and returns it. - * - * PARAMS - * path [I] path to parse and convert into an ItemIDList - * lpFindFile [I] pointer to buffer to initialize the FileSystem - * Bind Data object with - * bBindCtx [I] indicates to create a BindContext and assign a - * FileSystem Bind Data object - * ppidl [O] the newly create ItemIDList - * prgfInOut [I/O] requested attributes on input and actual - * attributes on return - * - * RETURNS - * NO_ERROR on success or an OLE error code - * - * NOTES - * If either lpFindFile is non-NULL or bBindCtx is TRUE, this function - * creates a BindContext object and assigns a FileSystem Bind Data object - * to it, passing the BindContext to IShellFolder_ParseDisplayName. Each - * IShellFolder uses that FileSystem Bind Data object of the BindContext - * to pass data about the current path element to the next object. This - * is used to avoid having to verify the current path element on disk, so - * that creating an ItemIDList from a non-existent path still can work. - */ -static HRESULT WINAPI _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile, - BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut) -{ - LPSHELLFOLDER pSF = NULL; - LPBC pBC = NULL; - HRESULT ret; - - TRACE("%s %p %d (%p)->%p (%p)->0x%lx\n", debugstr_w(path), lpFindFile, bBindCtx, - ppidl, ppidl ? *ppidl : NULL, - prgfInOut, prgfInOut ? *prgfInOut : 0); - - ret = SHGetDesktopFolder(&pSF); - if (FAILED(ret)) - { - return ret; - } - - if (lpFindFile || bBindCtx) - ret = IFileSystemBindData_Constructor(lpFindFile, &pBC); - - if (SUCCEEDED(ret)) - { - ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut); - } - - if (pBC) - { - IBindCtx_Release(pBC); - pBC = NULL; - } - - IShellFolder_Release(pSF); - - if (!SUCCEEDED(ret) && ppidl) - *ppidl = NULL; - - TRACE("%s %p 0x%lx\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0); - - return ret; -} - -/************************************************************************* - * SHSimpleIDListFromPath [SHELL32.162] - * - * Creates a simple ItemIDList from a path and returns it. This function - * does not fail on non-existent paths. - * - * PARAMS - * path [I] path to parse and convert into an ItemIDList - * - * RETURNS - * the newly created simple ItemIDList - * - * NOTES - * Simple in the name does not mean a relative ItemIDList but rather a - * fully qualified list, where only the file name is filled in and the - * directory flag for those ItemID elements this is known about, eg. - * it is not the last element in the ItemIDList or the actual directory - * exists on disk. - * exported by ordinal. - */ -LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath) -{ - LPITEMIDLIST pidl = NULL; - LPWSTR wPath = NULL; - int len; - - TRACE("%s\n", debugstr_a(lpszPath)); - - if (lpszPath) - { - len = MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, NULL, 0); - wPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, wPath, len); - } - - _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL); - - if (wPath) HeapFree(GetProcessHeap(), 0, wPath); - TRACE("%s %p\n", debugstr_a(lpszPath), pidl); - return pidl; -} - -LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath) -{ - LPITEMIDLIST pidl = NULL; - - TRACE("%s\n", debugstr_w(lpszPath)); - - _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL); - TRACE("%s %p\n", debugstr_w(lpszPath), pidl); - return pidl; -} - -LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath) -{ - if ( SHELL_OsIsUnicode()) - return SHSimpleIDListFromPathW (lpszPath); - return SHSimpleIDListFromPathA (lpszPath); -} - -/************************************************************************* - * SHGetDataFromIDListA [SHELL32.247] - * - * NOTES - * the pidl can be a simple one. since we can't get the path out of the pidl - * we have to take all data from the pidl - */ -HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len) -{ - TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len); - - pdump(pidl); - if (!psf || !dest ) return E_INVALIDARG; - - switch (nFormat) - { - case SHGDFIL_FINDDATA: - { - LPSTR filename, shortname; - WIN32_FIND_DATAA * pfd = dest; - - if (_ILIsDrive(pidl)) - return E_INVALIDARG; - - if (len < (int)sizeof(WIN32_FIND_DATAA)) return E_INVALIDARG; - - ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); - _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); - pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); - pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0); - - filename = _ILGetTextPointer(pidl); - shortname = _ILGetSTextPointer(pidl); - - if (filename) - lstrcpynA(pfd->cFileName, filename, MAX_PATH); - else - pfd->cFileName[0] = '\0'; - - if (shortname) - lstrcpynA(pfd->cAlternateFileName, shortname, MAX_PATH); - else - pfd->cAlternateFileName[0] = '\0'; - } - return NOERROR; - - case SHGDFIL_NETRESOURCE: - case SHGDFIL_DESCRIPTIONID: - FIXME_(shell)("SHGDFIL %i stub\n", nFormat); - break; - - default: - ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat); - } - - return E_INVALIDARG; -} - -/************************************************************************* - * SHGetDataFromIDListW [SHELL32.248] - * - */ -HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len) -{ - TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len); - - pdump(pidl); - - if (! psf || !dest ) return E_INVALIDARG; - - switch (nFormat) - { - case SHGDFIL_FINDDATA: - { - LPSTR filename, shortname; - WIN32_FIND_DATAW * pfd = dest; - - if (_ILIsDrive(pidl)) - return E_INVALIDARG; - - if (len < (int)sizeof(WIN32_FIND_DATAW)) return E_INVALIDARG; - - ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); - _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); - pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); - pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0); - - filename = _ILGetTextPointer(pidl); - shortname = _ILGetSTextPointer(pidl); - - if (!filename) - pfd->cFileName[0] = '\0'; - else if (!MultiByteToWideChar(CP_ACP, 0, filename, -1, pfd->cFileName, MAX_PATH)) - pfd->cFileName[MAX_PATH-1] = 0; - - if (!shortname) - pfd->cAlternateFileName[0] = '\0'; - else if (!MultiByteToWideChar(CP_ACP, 0, shortname, -1, pfd->cAlternateFileName, 14)) - pfd->cAlternateFileName[13] = 0; - } - return NOERROR; - case SHGDFIL_NETRESOURCE: - case SHGDFIL_DESCRIPTIONID: - FIXME_(shell)("SHGDFIL %i stub\n", nFormat); - break; - - default: - ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat); - } - - return E_INVALIDARG; -} - -/************************************************************************* - * SHELL_GetPathFromIDListA - */ -HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize) -{ - HRESULT hr = S_OK; - - pszPath[0]=0; - - /* One case is a PIDL rooted at desktop level */ - if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { - hr = SHGetSpecialFolderPathA(0, pszPath, CSIDL_DESKTOP, FALSE); - - if (SUCCEEDED(hr)) - PathAddBackslashA(pszPath); - } - /* The only other valid case is a item ID list beginning at "My Computer" */ - else if (_ILIsMyComputer(pidl)) - pidl = ILGetNext(pidl); - - if (SUCCEEDED(hr)) { - LPSTR txt; - - while(pidl && pidl->mkid.cb) { - if (_ILIsSpecialFolder(pidl)) - {hr = E_INVALIDARG; break;} - - txt = _ILGetTextPointer(pidl); - if (!txt) - {hr = E_INVALIDARG; break;} - - if (lstrlenA(txt) > pidl->mkid.cb) - ERR("pidl %p is borked\n",pidl); - - /* make sure there's enough space for the next segment */ - if ( (lstrlenA(txt) + lstrlenA(pszPath)) > uOutSize) - {hr = E_INVALIDARG; break;} - lstrcatA( pszPath, txt ); - - pidl = ILGetNext(pidl); - if (!pidl) - {hr = E_INVALIDARG; break;} - - if (!pidl->mkid.cb) { - /* We are at the end and successfully converted the complete PIDL. */ - break; - } - - if( (lstrlenA(pszPath) + 1) > uOutSize) - {hr = E_INVALIDARG; break;} - if (!PathAddBackslashA(pszPath)) - {hr = E_INVALIDARG; break;} - } - } else - hr = E_INVALIDARG; - - TRACE_(shell)("-- %s, 0x%08lx\n", pszPath, hr); - return hr; -} - -/************************************************************************* - * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220] - * - * PARAMETERS - * pidl, [IN] pidl - * pszPath [OUT] path - * - * RETURNS - * path from a passed PIDL. - * - * NOTES - * NULL returns FALSE - * desktop pidl gives path to desktop directory back - * special pidls returning FALSE - */ -BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath) -{ - HRESULT hr; - - TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); - pdump(pidl); - - if (!pidl) - return FALSE; - - hr = SHELL_GetPathFromIDListA(pidl, pszPath, MAX_PATH); - - return SUCCEEDED(hr); -} - -/************************************************************************* - * SHELL_GetPathFromIDListW - */ -HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize) -{ - HRESULT hr = S_OK; - UINT len; - - pszPath[0]=0; - - /* One case is a PIDL rooted at desktop level */ - if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { - hr = SHGetSpecialFolderPathW(0, pszPath, CSIDL_DESKTOP, FALSE); - - if (SUCCEEDED(hr)) - PathAddBackslashW(pszPath); - } - /* The only other valid case is a item ID list beginning at "My Computer" */ - else if (_ILIsMyComputer(pidl)) - pidl = ILGetNext(pidl); - - if (SUCCEEDED(hr)) { - LPSTR txt; - - while(pidl && pidl->mkid.cb) { - if (_ILIsSpecialFolder(pidl)) - {hr = E_INVALIDARG; break;} - - txt = _ILGetTextPointer(pidl); - if (!txt) - {hr = E_INVALIDARG; break;} - - if (lstrlenA(txt) > pidl->mkid.cb) - ERR("pidl %p is borked\n",pidl); - len = MultiByteToWideChar(CP_ACP, 0, txt, -1, NULL, 0); - if ( (lstrlenW(pszPath) + len) > uOutSize ) - {hr = E_INVALIDARG; break;} - - MultiByteToWideChar(CP_ACP, 0, txt, -1, - &pszPath[lstrlenW(pszPath)], len); - - pidl = ILGetNext(pidl); - if (!pidl) - {hr = E_INVALIDARG; break;} - - if (!pidl->mkid.cb) { - /* We are at the end and successfully converted the complete PIDL. */ - break; - } - - if ( (lstrlenW(pszPath) + 1) > uOutSize ) - {hr = E_INVALIDARG; break;} - if (!PathAddBackslashW(pszPath)) - {hr = E_INVALIDARG; break;} - } - } else - hr = E_INVALIDARG; - - TRACE_(shell)("-- %s, 0x%08lx\n", debugstr_w(pszPath), hr); - return hr; -} - -/************************************************************************* - * SHGetPathFromIDListW [SHELL32.@] - */ -BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath) -{ - HRESULT hr; - - TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath)); - pdump(pidl); - - if (!pidl) - return FALSE; - - hr = SHELL_GetPathFromIDListW(pidl, pszPath, MAX_PATH); - - TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr); - return SUCCEEDED(hr); -} - -/************************************************************************* - * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219] - */ -BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath) -{ - TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); - - if (SHELL_OsIsUnicode()) - return SHGetPathFromIDListW(pidl,pszPath); - return SHGetPathFromIDListA(pidl,pszPath); -} - -/************************************************************************* - * SHBindToParent [shell version 5.0] - */ -HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast) -{ - IShellFolder * psf; - LPITEMIDLIST pidlChild, pidlParent; - HRESULT hr=E_FAIL; - - TRACE_(shell)("pidl=%p\n", pidl); - pdump(pidl); - - *ppv = NULL; - if (ppidlLast) *ppidlLast = NULL; - - if (_ILIsPidlSimple(pidl)) - { - IShellFolder* desktop; - - /* we are on desktop level */ - hr = SHGetDesktopFolder(&desktop); - - if (SUCCEEDED(hr)) - { - hr = IShellFolder_QueryInterface(desktop, riid, ppv); - - if (SUCCEEDED(hr) && ppidlLast) - *ppidlLast = ILClone(pidl); - - IShellFolder_Release(desktop); - } - } - else - { - pidlChild = ILClone(ILFindLastID(pidl)); - pidlParent = ILClone(pidl); - ILRemoveLastID(pidlParent); - - hr = SHGetDesktopFolder(&psf); - - if (SUCCEEDED(hr)) - hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv); - - if (SUCCEEDED(hr) && ppidlLast) - *ppidlLast = pidlChild; - else - ILFree (pidlChild); - - SHFree (pidlParent); - if (psf) IShellFolder_Release(psf); - } - - - TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr); - return hr; -} - -/************************************************************************** - * - * internal functions - * - * ### 1. section creating pidls ### - * - ************************************************************************* - */ -LPITEMIDLIST _ILAlloc(PIDLTYPE type, size_t size) -{ - LPITEMIDLIST pidlOut = NULL; - - if((pidlOut = SHAlloc(size + 5))) - { - LPPIDLDATA pData; - LPITEMIDLIST pidlNext; - - ZeroMemory(pidlOut, size + 5); - pidlOut->mkid.cb = size + 3; - - if ((pData = _ILGetDataPointer(pidlOut))) - pData->type = type; - - if ((pidlNext = ILGetNext(pidlOut))) - pidlNext->mkid.cb = 0x00; - TRACE("-- (pidl=%p, size=%u)\n", pidlOut, size); - } - - return pidlOut; -} - -LPITEMIDLIST _ILCreateDesktop() -{ - LPITEMIDLIST ret; - - TRACE("()\n"); - ret = SHAlloc(2); - if (ret) - ret->mkid.cb = 0; - return ret; -} - -LPITEMIDLIST _ILCreateMyComputer() -{ TRACE("()\n"); - return _ILCreateGuid(PT_GUID, &CLSID_MyComputer); -} - -LPITEMIDLIST _ILCreateIExplore() -{ TRACE("()\n"); - return _ILCreateGuid(PT_GUID, &CLSID_Internet); -} - -LPITEMIDLIST _ILCreateControlPanel() -{ - LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL; - - TRACE("()\n"); - if (parent) - { - LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel); - - if (cpl) - { - ret = ILCombine(parent, cpl); - SHFree(cpl); - } - SHFree(parent); - } - return ret; -} - -LPITEMIDLIST _ILCreatePrinters() -{ - LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL; - - TRACE("()\n"); - if (parent) - { - LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, &CLSID_Printers); - - if (printers) - { - ret = ILCombine(parent, printers); - SHFree(printers); - } - SHFree(parent); - } - return ret; -} - -LPITEMIDLIST _ILCreateNetwork() -{ TRACE("()\n"); - return _ILCreateGuid(PT_GUID, &CLSID_NetworkPlaces); -} - -LPITEMIDLIST _ILCreateBitBucket() -{ TRACE("()\n"); - return _ILCreateGuid(PT_GUID, &CLSID_RecycleBin); -} - -LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid) -{ - LPITEMIDLIST pidlOut; - - if (type == PT_SHELLEXT || type == PT_GUID || type == PT_YAGUID) - { - pidlOut = _ILAlloc(type, sizeof(GUIDStruct)); - if (pidlOut) - { - LPPIDLDATA pData = _ILGetDataPointer(pidlOut); - - memcpy(&(pData->u.guid.guid), guid, sizeof(GUID)); - TRACE("-- create GUID-pidl %s\n", - debugstr_guid(&(pData->u.guid.guid))); - } - } - else - { - WARN("%d: invalid type for GUID\n", type); - pidlOut = NULL; - } - return pidlOut; -} - -LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID) -{ - IID iid; - - if (!SUCCEEDED(SHCLSIDFromStringA(szGUID, &iid))) - { - ERR("%s is not a GUID\n", szGUID); - return NULL; - } - return _ILCreateGuid(PT_GUID, &iid); -} - -LPITEMIDLIST _ILCreateFromFindDataA(WIN32_FIND_DATAA * stffile ) -{ - char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */ - char * pbuff = buff; - size_t len, len1; - LPITEMIDLIST pidl; - PIDLTYPE type; - - if (!stffile) - return NULL; - - TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName); - - /* prepare buffer with both names */ - len = strlen (stffile->cFileName) + 1; - memcpy (pbuff, stffile->cFileName, len); - pbuff += len; - - len1 = strlen (stffile->cAlternateFileName)+1; - memcpy (pbuff, stffile->cAlternateFileName, len1); - - type = (stffile->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? PT_FOLDER : - PT_VALUE; - /* FileStruct already has one byte for the first name, so use len - 1 in - * size calculation - */ - if ((pidl = _ILAlloc(type, sizeof(FileStruct) + (len - 1) + len1))) - { - LPPIDLDATA pData; - LPSTR pszDest; - - /* set attributes */ - if ((pData = _ILGetDataPointer(pidl))) - { - pData->type = type; - FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.file.uFileDate,&pData->u.file.uFileTime); - pData->u.file.dwFileSize = stffile->nFileSizeLow; - pData->u.file.uFileAttribs = (WORD)stffile->dwFileAttributes; - } - if ((pszDest = _ILGetTextPointer(pidl))) - { - memcpy(pszDest, buff, len + len1); - TRACE("-- create Value: %s\n",debugstr_a(pszDest)); - } - } - return pidl; -} - -HRESULT _ILCreateFromPathA(LPCSTR szPath, LPITEMIDLIST* ppidl) -{ - HANDLE hFile; - WIN32_FIND_DATAA stffile; - - if (!ppidl) - return E_INVALIDARG; - - hFile = FindFirstFileA(szPath, &stffile); - - if (hFile == INVALID_HANDLE_VALUE) - return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - - FindClose(hFile); - - *ppidl = _ILCreateFromFindDataA(&stffile); - - return *ppidl ? S_OK : E_OUTOFMEMORY; -} - -LPITEMIDLIST _ILCreateDrive(LPCWSTR lpszNew) -{ - WCHAR sTemp[4]; - LPITEMIDLIST pidlOut; - - sTemp[0]=toupperW(lpszNew[0]); - sTemp[1]=':'; - sTemp[2]='\\'; - sTemp[3]=0x00; - TRACE("(%s)\n",debugstr_w(sTemp)); - - if ((pidlOut = _ILAlloc(PT_DRIVE, sizeof(DriveStruct)))) - { - LPSTR pszDest; - - if ((pszDest = _ILGetTextPointer(pidlOut))) - { - WideCharToMultiByte(CP_ACP, 0, sTemp, sizeof(sTemp)/sizeof(WCHAR), pszDest, sizeof(sTemp)/sizeof(WCHAR), NULL, NULL); - TRACE("-- create Drive: %s\n", debugstr_a(pszDest)); - } - } - return pidlOut; -} - -/************************************************************************** - * _ILGetDrive() - * - * Gets the text for the drive eg. 'c:\' - * - * RETURNS - * strlen (lpszText) - */ -DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize) -{ TRACE("(%p,%p,%u)\n",pidl,pOut,uSize); - - if(_ILIsMyComputer(pidl)) - pidl = ILGetNext(pidl); - - if (pidl && _ILIsDrive(pidl)) - return _ILSimpleGetText(pidl, pOut, uSize); - - return 0; -} - -/************************************************************************** - * - * ### 2. section testing pidls ### - * - ************************************************************************** - * _ILIsDesktop() - * _ILIsMyComputer() - * _ILIsSpecialFolder() - * _ILIsDrive() - * _ILIsFolder() - * _ILIsValue() - * _ILIsPidlSimple() - */ -BOOL _ILIsDesktop(LPCITEMIDLIST pidl) -{ TRACE("(%p)\n",pidl); - return pidl && pidl->mkid.cb ? 0 : 1; -} - -BOOL _ILIsMyComputer(LPCITEMIDLIST pidl) -{ - REFIID iid = _ILGetGUIDPointer(pidl); - - TRACE("(%p)\n",pidl); - - if (iid) - return IsEqualIID(iid, &CLSID_MyComputer); - return FALSE; -} - -BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl) -{ - LPPIDLDATA lpPData = _ILGetDataPointer(pidl); - TRACE("(%p)\n",pidl); - return (pidl && ( (lpPData && (PT_GUID== lpPData->type || PT_SHELLEXT== lpPData->type)) || - (pidl && pidl->mkid.cb == 0x00) - )); -} - -BOOL _ILIsDrive(LPCITEMIDLIST pidl) -{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); - TRACE("(%p)\n",pidl); - return (pidl && lpPData && (PT_DRIVE == lpPData->type || - PT_DRIVE1 == lpPData->type || - PT_DRIVE2 == lpPData->type || - PT_DRIVE3 == lpPData->type)); -} - -BOOL _ILIsFolder(LPCITEMIDLIST pidl) -{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); - TRACE("(%p)\n",pidl); - return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type)); -} - -BOOL _ILIsValue(LPCITEMIDLIST pidl) -{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); - TRACE("(%p)\n",pidl); - return (pidl && lpPData && PT_VALUE == lpPData->type); -} - -BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl) -{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); - TRACE("(%p)\n",pidl); - return (pidl && lpPData && (lpPData->type == 0)); -} - -/************************************************************************** - * _ILIsPidlSimple - */ -BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl) -{ - BOOL ret = TRUE; - - if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */ - { - WORD len = pidl->mkid.cb; - LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((const BYTE*)pidl) + len ); - if (pidlnext->mkid.cb) - ret = FALSE; - } - - TRACE("%s\n", ret ? "Yes" : "No"); - return ret; -} - -/************************************************************************** - * - * ### 3. section getting values from pidls ### - */ - - /************************************************************************** - * _ILSimpleGetText - * - * gets the text for the first item in the pidl (eg. simple pidl) - * - * returns the length of the string - */ -DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize) -{ - DWORD dwReturn=0; - LPSTR szSrc; - GUID const * riid; - char szTemp[MAX_PATH]; - - TRACE("(%p %p %x)\n",pidl,szOut,uOutSize); - - if (!pidl) return 0; - - if (szOut) - *szOut = 0; - - if (_ILIsDesktop(pidl)) - { - /* desktop */ - if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH)) - { - if (szOut) - lstrcpynA(szOut, szTemp, uOutSize); - - dwReturn = strlen (szTemp); - } - } - else if (( szSrc = _ILGetTextPointer(pidl) )) - { - /* filesystem */ - if (szOut) - lstrcpynA(szOut, szSrc, uOutSize); - - dwReturn = strlen(szSrc); - } - else if (( riid = _ILGetGUIDPointer(pidl) )) - { - /* special folder */ - if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) ) - { - if (szOut) - lstrcpynA(szOut, szTemp, uOutSize); - - dwReturn = strlen (szTemp); - } - } - else - { - ERR("-- no text\n"); - } - - TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn); - return dwReturn; -} - - /************************************************************************** - * _ILSimpleGetTextW - * - * gets the text for the first item in the pidl (eg. simple pidl) - * - * returns the length of the string - */ -DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize) -{ - DWORD dwReturn; - char szTemp[MAX_PATH]; - - TRACE("(%p %p %x)\n",pidl,szOut,uOutSize); - - dwReturn = _ILSimpleGetText(pidl, szTemp, uOutSize); - - if (!MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szOut, MAX_PATH)) - *szOut = 0; - - TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_w(szOut),dwReturn); - return dwReturn; -} - -/************************************************************************** - * - * ### 4. getting pointers to parts of pidls ### - * - ************************************************************************** - * _ILGetDataPointer() - */ -LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl) -{ - if(pidl && pidl->mkid.cb != 0x00) - return (LPPIDLDATA) &(pidl->mkid.abID); - return NULL; -} - -/************************************************************************** - * _ILGetTextPointer() - * gets a pointer to the long filename string stored in the pidl - */ -LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl) -{/* TRACE(pidl,"(pidl%p)\n", pidl);*/ - - LPPIDLDATA pdata = _ILGetDataPointer(pidl); - - if (pdata) - { - switch (pdata->type) - { - case PT_GUID: - case PT_SHELLEXT: - case PT_YAGUID: - return NULL; - - case PT_DRIVE: - case PT_DRIVE1: - case PT_DRIVE2: - case PT_DRIVE3: - return (LPSTR)&(pdata->u.drive.szDriveName); - - case PT_FOLDER: - case PT_FOLDER1: - case PT_VALUE: - case PT_IESPECIAL1: - case PT_IESPECIAL2: - return (LPSTR)&(pdata->u.file.szNames); - - case PT_WORKGRP: - case PT_COMP: - case PT_NETWORK: - case PT_NETPROVIDER: - case PT_SHARE: - return (LPSTR)&(pdata->u.network.szNames); - } - } - return NULL; -} - -/************************************************************************** - * _ILGetSTextPointer() - * gets a pointer to the short filename string stored in the pidl - */ -LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl) -{/* TRACE(pidl,"(pidl%p)\n", pidl);*/ - - LPPIDLDATA pdata =_ILGetDataPointer(pidl); - - if (pdata) - { - switch (pdata->type) - { - case PT_FOLDER: - case PT_VALUE: - case PT_IESPECIAL1: - case PT_IESPECIAL2: - return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1); - - case PT_WORKGRP: - return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1); - } - } - return NULL; -} - -/************************************************************************** - * _ILGetGUIDPointer() - * - * returns reference to guid stored in some pidls - */ -IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl) -{ - LPPIDLDATA pdata =_ILGetDataPointer(pidl); - - TRACE("%p\n", pidl); - - if (pdata) - { - TRACE("pdata->type 0x%04x\n", pdata->type); - switch (pdata->type) - { - case PT_SHELLEXT: - case PT_GUID: - return &(pdata->u.guid.guid); - - default: - TRACE("Unknown pidl type 0x%04x\n", pdata->type); - break; - } - } - return NULL; -} - -/************************************************************************* - * _ILGetFileDateTime - * - * Given the ItemIdList, get the FileTime - * - * PARAMS - * pidl [I] The ItemIDList - * pFt [I] the resulted FILETIME of the file - * - * RETURNS - * True if Successful - * - * NOTES - * - */ -BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt) -{ - LPPIDLDATA pdata = _ILGetDataPointer(pidl); - - if(! pdata) return FALSE; - - switch (pdata->type) - { - case PT_FOLDER: - case PT_VALUE: - DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt); - break; - default: - return FALSE; - } - return TRUE; -} - -BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) -{ - FILETIME ft,lft; - SYSTEMTIME time; - BOOL ret; - - if (_ILGetFileDateTime( pidl, &ft )) { - FileTimeToLocalFileTime(&ft, &lft); - FileTimeToSystemTime (&lft, &time); - ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize); - } else { - pOut[0] = '\0'; - ret = FALSE; - } - return ret; - -} - -/************************************************************************* - * _ILGetFileSize - * - * Given the ItemIdList, get the FileSize - * - * PARAMS - * pidl [I] The ItemIDList - * pOut [I] The buffer to save the result - * uOutsize [I] The size of the buffer - * - * RETURNS - * The FileSize - * - * NOTES - * pOut can be null when no string is needed - * - */ -DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) -{ - LPPIDLDATA pdata = _ILGetDataPointer(pidl); - DWORD dwSize; - - if(! pdata) return 0; - - switch (pdata->type) - { - case PT_VALUE: - dwSize = pdata->u.file.dwFileSize; - if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize); - return dwSize; - } - if (pOut) *pOut = 0x00; - return 0; -} - -BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) -{ - char szTemp[MAX_PATH]; - const char * pPoint; - LPCITEMIDLIST pidlTemp=pidl; - - TRACE("pidl=%p\n",pidl); - - if (!pidl) return FALSE; - - pidlTemp = ILFindLastID(pidl); - - if (!_ILIsValue(pidlTemp)) return FALSE; - if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE; - - pPoint = PathFindExtensionA(szTemp); - - if (! *pPoint) return FALSE; - - pPoint++; - lstrcpynA(pOut, pPoint, uOutSize); - TRACE("%s\n",pOut); - - return TRUE; -} - -/************************************************************************* - * _ILGetFileType - * - * Given the ItemIdList, get the file type description - * - * PARAMS - * pidl [I] The ItemIDList (simple) - * pOut [I] The buffer to save the result - * uOutsize [I] The size of the buffer - * - * RETURNS - * nothing - * - * NOTES - * This function copies as much as possible into the buffer. - */ -void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) -{ - if(_ILIsValue(pidl)) - { - char sTemp[64]; - if(uOutSize > 0) - { - pOut[0] = 0; - } - if (_ILGetExtension (pidl, sTemp, 64)) - { - if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE) - && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE ))) - { - lstrcpynA (pOut, sTemp, uOutSize - 6); - strcat (pOut, "-file"); - } - } - } - else - { - lstrcpynA(pOut, "Folder", uOutSize); - } -} - -/************************************************************************* - * _ILGetFileAttributes - * - * Given the ItemIdList, get the Attrib string format - * - * PARAMS - * pidl [I] The ItemIDList - * pOut [I] The buffer to save the result - * uOutsize [I] The size of the Buffer - * - * RETURNS - * Attributes - * - * FIXME - * return value 0 in case of error is a valid return value - * - */ -DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) -{ - LPPIDLDATA pData = _ILGetDataPointer(pidl); - WORD wAttrib = 0; - int i; - - if(! pData) return 0; - - switch(pData->type) - { - case PT_FOLDER: - case PT_VALUE: - wAttrib = pData->u.file.uFileAttribs; - break; - } - - if(uOutSize >= 6) - { - i=0; - if(wAttrib & FILE_ATTRIBUTE_READONLY) - { - pOut[i++] = 'R'; - } - if(wAttrib & FILE_ATTRIBUTE_HIDDEN) - { - pOut[i++] = 'H'; - } - if(wAttrib & FILE_ATTRIBUTE_SYSTEM) - { - pOut[i++] = 'S'; - } - if(wAttrib & FILE_ATTRIBUTE_ARCHIVE) - { - pOut[i++] = 'A'; - } - if(wAttrib & FILE_ATTRIBUTE_COMPRESSED) - { - pOut[i++] = 'C'; - } - pOut[i] = 0x00; - } - return wAttrib; -} - -/************************************************************************* -* ILFreeaPidl -* -* free a aPidl struct -*/ -void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl) -{ - UINT i; - - if (apidl) - { - for (i = 0; i < cidl; i++) SHFree(apidl[i]); - SHFree(apidl); - } -} - -/************************************************************************* -* ILCopyaPidl -* -* copies an aPidl struct -*/ -LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl) -{ - UINT i; - LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST)); - if(!apidlsrc) return NULL; - - for (i = 0; i < cidl; i++) - apidldest[i] = ILClone(apidlsrc[i]); - - return apidldest; -} - -/************************************************************************* -* _ILCopyCidaToaPidl -* -* creates aPidl from CIDA -*/ -LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida) -{ - UINT i; - LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST)); - - if(!dst) return NULL; - - if (pidl) - *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]])); - - for (i = 0; i < cida->cidl; i++) - dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]])); - - return dst; -} +/* + * pidl Handling + * + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * a pidl == NULL means desktop and is legal + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "objbase.h" +#include "shlguid.h" +#include "winerror.h" +#include "winnls.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shellapi.h" +#include "shlwapi.h" + +#include "pidl.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(pidl); +WINE_DECLARE_DEBUG_CHANNEL(shell); + +/* from comctl32.dll */ +extern LPVOID WINAPI Alloc(INT); +extern BOOL WINAPI Free(LPVOID); + +/************************************************************************* + * ILGetDisplayNameEx [SHELL32.186] + * + * Retrieves the display name of an ItemIDList + * + * PARAMS + * psf [I] Shell Folder to start with, if NULL the desktop is used + * pidl [I] ItemIDList relativ to the psf to get the display name for + * path [O] Filled in with the display name, assumed to be at least MAX_PATH long + * type [I] Type of display name to retrieve + * 0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root + * 1 = SHGDN_NORMAL relative to the root folder + * 2 = SHGDN_INFOLDER relative to the root folder, only the last name + * + * RETURNS + * True if the display name could be retrieved successfully, False otherwise + */ +BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type) +{ + BOOL ret = FALSE; + WCHAR wPath[MAX_PATH]; + + TRACE("%p %p %p %ld\n", psf, pidl, path, type); + + if (!pidl || !path) + return FALSE; + + ret = ILGetDisplayNameExW(psf, pidl, wPath, type); + WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL); + TRACE("%p %p %s\n", psf, pidl, debugstr_a(path)); + + return ret; +} + +BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type) +{ + LPSHELLFOLDER psfParent, lsf = psf; + HRESULT ret = NO_ERROR; + LPCITEMIDLIST pidllast; + STRRET strret; + DWORD flag; + + TRACE("%p %p %p %ld\n", psf, pidl, path, type); + + if (!pidl || !path) + return FALSE; + + if (!lsf) + { + ret = SHGetDesktopFolder(&lsf); + if (FAILED(ret)) + return FALSE; + } + + if (type >= 0 && type <= 2) + { + switch (type) + { + case ILGDN_FORPARSING: + flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR; + break; + case ILGDN_NORMAL: + flag = SHGDN_NORMAL; + break; + case ILGDN_INFOLDER: + flag = SHGDN_INFOLDER; + break; + default: + FIXME("Unknown type parameter = %lx\n", type); + flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR; + break; + } + if (!*(const WORD*)pidl || type == ILGDN_FORPARSING) + { + ret = IShellFolder_GetDisplayNameOf(lsf, pidl, flag, &strret); + if (SUCCEEDED(ret)) + { + ret = StrRetToStrNW(path, MAX_PATH, &strret, pidl); + } + } + else + { + ret = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidllast); + if (SUCCEEDED(ret)) + { + ret = IShellFolder_GetDisplayNameOf(psfParent, pidllast, flag, &strret); + if (SUCCEEDED(ret)) + { + ret = StrRetToStrNW(path, MAX_PATH, &strret, pidllast); + } + IShellFolder_Release(psfParent); + } + } + } + + TRACE("%p %p %s\n", psf, pidl, debugstr_w(path)); + + if (!psf) + IShellFolder_Release(lsf); + return SUCCEEDED(ret); +} + +BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type) +{ + TRACE_(shell)("%p %p %p %ld\n", psf, pidl, path, type); + if (SHELL_OsIsUnicode()) + return ILGetDisplayNameExW(psf, pidl, path, type); + return ILGetDisplayNameExA(psf, pidl, path, type); +} + +/************************************************************************* + * ILGetDisplayName [SHELL32.15] + */ +BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path) +{ + TRACE_(shell)("%p %p\n", pidl, path); + if (SHELL_OsIsUnicode()) + return ILGetDisplayNameExW(NULL, pidl, path, ILGDN_FORPARSING); + return ILGetDisplayNameExA(NULL, pidl, path, ILGDN_FORPARSING); +} + +/************************************************************************* + * ILFindLastID [SHELL32.16] + * + * NOTES + * observed: pidl=Desktop return=pidl + */ +LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl) +{ + LPCITEMIDLIST pidlLast = pidl; + + TRACE("(pidl=%p)\n",pidl); + + if (!pidl) + return NULL; + + while (pidl->mkid.cb) + { + pidlLast = pidl; + pidl = ILGetNext(pidl); + } + return (LPITEMIDLIST)pidlLast; +} +/************************************************************************* + * ILRemoveLastID [SHELL32.17] + * + * NOTES + * when pidl=Desktop return=FALSE + */ +BOOL WINAPI ILRemoveLastID(LPITEMIDLIST pidl) +{ + TRACE_(shell)("pidl=%p\n",pidl); + + if (!pidl || !pidl->mkid.cb) + return 0; + ILFindLastID(pidl)->mkid.cb = 0; + return 1; +} + +/************************************************************************* + * ILClone [SHELL32.18] + * + * NOTES + * duplicate an idlist + */ +LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl) +{ DWORD len; + LPITEMIDLIST newpidl; + + if (!pidl) + return NULL; + + len = ILGetSize(pidl); + newpidl = (LPITEMIDLIST)SHAlloc(len); + if (newpidl) + memcpy(newpidl,pidl,len); + + TRACE("pidl=%p newpidl=%p\n",pidl, newpidl); + pdump(pidl); + + return newpidl; +} +/************************************************************************* + * ILCloneFirst [SHELL32.19] + * + * NOTES + * duplicates the first idlist of a complex pidl + */ +LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl) +{ DWORD len; + LPITEMIDLIST pidlNew = NULL; + + TRACE("pidl=%p \n",pidl); + pdump(pidl); + + if (pidl) + { + len = pidl->mkid.cb; + pidlNew = (LPITEMIDLIST) SHAlloc (len+2); + if (pidlNew) + { + memcpy(pidlNew,pidl,len+2); /* 2 -> mind a desktop pidl */ + + if (len) + ILGetNext(pidlNew)->mkid.cb = 0x00; + } + } + TRACE("-- newpidl=%p\n",pidlNew); + + return pidlNew; +} + +/************************************************************************* + * ILLoadFromStream (SHELL32.26) + * + * NOTES + * the first two bytes are the len, the pidl is following then + */ +HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl) +{ WORD wLen = 0; + DWORD dwBytesRead; + HRESULT ret = E_FAIL; + + + TRACE_(shell)("%p %p\n", pStream , ppPidl); + + if (*ppPidl) + { SHFree(*ppPidl); + *ppPidl = NULL; + } + + IStream_AddRef (pStream); + + if (SUCCEEDED(IStream_Read(pStream, (LPVOID)&wLen, 2, &dwBytesRead))) + { + TRACE("PIDL length is %d\n", wLen); + if (wLen != 0) { + *ppPidl = SHAlloc (wLen); + if (SUCCEEDED(IStream_Read(pStream, *ppPidl , wLen, &dwBytesRead))) { + TRACE("Stream read OK\n"); + ret = S_OK; + } else { + WARN("reading pidl failed\n"); + SHFree(*ppPidl); + *ppPidl = NULL; + } + } else { + *ppPidl = NULL; + ret = S_OK; + } + } + + /* we are not yet fully compatible */ + if (*ppPidl && !pcheck(*ppPidl)) + { + WARN("Check failed\n"); + SHFree(*ppPidl); + *ppPidl = NULL; + } + + + IStream_Release (pStream); + TRACE("done\n"); + return ret; +} + +/************************************************************************* + * ILSaveToStream (SHELL32.27) + * + * NOTES + * the first two bytes are the len, the pidl is following then + */ +HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl) +{ + LPCITEMIDLIST pidl; + WORD wLen = 0; + HRESULT ret = E_FAIL; + + TRACE_(shell)("%p %p\n", pStream, pPidl); + + IStream_AddRef (pStream); + + pidl = pPidl; + while (pidl->mkid.cb) + { + wLen += sizeof(WORD) + pidl->mkid.cb; + pidl = ILGetNext(pidl); + } + + if (SUCCEEDED(IStream_Write(pStream, (LPVOID)&wLen, 2, NULL))) + { + if (SUCCEEDED(IStream_Write(pStream, pPidl, wLen, NULL))) + { ret = S_OK; + } + } + IStream_Release (pStream); + + return ret; +} + +/************************************************************************* + * SHILCreateFromPath [SHELL32.28] + * + * Create an ItemIDList from a path + * + * PARAMS + * path [I] + * ppidl [O] + * attributes [I/O] requested attributes on call and actual attributes when + * the function returns + * + * RETURNS + * NO_ERROR if successful, or an OLE errer code otherwise + * + * NOTES + * Wrapper for IShellFolder_ParseDisplayName(). + */ +HRESULT WINAPI SHILCreateFromPathA(LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes) +{ + LPSHELLFOLDER sf; + WCHAR lpszDisplayName[MAX_PATH]; + DWORD pchEaten; + HRESULT ret = E_FAIL; + + TRACE_(shell)("%s %p 0x%08lx\n", path, ppidl, attributes ? *attributes : 0); + + if (!MultiByteToWideChar(CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH)) + lpszDisplayName[MAX_PATH-1] = 0; + + if (SUCCEEDED (SHGetDesktopFolder(&sf))) + { + ret = IShellFolder_ParseDisplayName(sf, 0, NULL, lpszDisplayName, &pchEaten, ppidl, attributes); + IShellFolder_Release(sf); + } + return ret; +} + +HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes) +{ + LPSHELLFOLDER sf; + DWORD pchEaten; + HRESULT ret = E_FAIL; + + TRACE_(shell)("%s %p 0x%08lx\n", debugstr_w(path), ppidl, attributes ? *attributes : 0); + + if (SUCCEEDED (SHGetDesktopFolder(&sf))) + { + ret = IShellFolder_ParseDisplayName(sf, 0, NULL, (LPWSTR)path, &pchEaten, ppidl, attributes); + IShellFolder_Release(sf); + } + return ret; +} + +HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes) +{ + if ( SHELL_OsIsUnicode()) + return SHILCreateFromPathW (path, ppidl, attributes); + return SHILCreateFromPathA (path, ppidl, attributes); +} + +/************************************************************************* + * SHCloneSpecialIDList [SHELL32.89] + * + * Create an ItemIDList to one of the special folders. + + * PARAMS + * hwndOwner [in] + * nFolder [in] CSIDL_xxxxx + * fCreate [in] Create folder if it does not exist + * + * RETURNS + * Success: The newly created pidl + * Failure: NULL, if inputs are invalid. + * + * NOTES + * exported by ordinal. + * Caller is responsible for deallocating the returned ItemIDList with the + * shells IMalloc interface, aka ILFree. + */ +LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner, DWORD nFolder, BOOL fCreate) +{ LPITEMIDLIST ppidl; + TRACE_(shell)("(hwnd=%p,csidl=0x%lx,%s).\n", hwndOwner, nFolder, fCreate ? "T" : "F"); + + if (fCreate) + nFolder |= CSIDL_FLAG_CREATE; + + SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl); + return ppidl; +} + +/************************************************************************* + * ILGlobalClone [SHELL32.20] + * + * Clones an ItemIDList using Alloc. + * + * PARAMS + * pidl [I] ItemIDList to clone + * + * RETURNS + * Newly allocated ItemIDList. + * + * NOTES + * exported by ordinal. + */ +LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl) +{ DWORD len; + LPITEMIDLIST newpidl; + + if (!pidl) + return NULL; + + len = ILGetSize(pidl); + newpidl = (LPITEMIDLIST)Alloc(len); + if (newpidl) + memcpy(newpidl,pidl,len); + + TRACE("pidl=%p newpidl=%p\n",pidl, newpidl); + pdump(pidl); + + return newpidl; +} + +/************************************************************************* + * ILIsEqual [SHELL32.21] + * + */ +BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + char szData1[MAX_PATH]; + char szData2[MAX_PATH]; + + LPCITEMIDLIST pidltemp1 = pidl1; + LPCITEMIDLIST pidltemp2 = pidl2; + + TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2); + + /* explorer reads from registry directly (StreamMRU), + so we can only check here */ + if ((!pcheck (pidl1)) || (!pcheck (pidl2))) return FALSE; + + pdump (pidl1); + pdump (pidl2); + + if ( (!pidl1) || (!pidl2) ) return FALSE; + + while (pidltemp1->mkid.cb && pidltemp2->mkid.cb) + { + _ILSimpleGetText(pidltemp1, szData1, MAX_PATH); + _ILSimpleGetText(pidltemp2, szData2, MAX_PATH); + + if (strcasecmp ( szData1, szData2 )!=0 ) + return FALSE; + + pidltemp1 = ILGetNext(pidltemp1); + pidltemp2 = ILGetNext(pidltemp2); + } + + if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb) + { + return TRUE; + } + + return FALSE; +} +/************************************************************************* + * ILIsParent [SHELL32.23] + * + * Verifies that pidlParent is indeed the (immediate) parent of pidlChild. + * + * PARAMS + * pidlParent [I] + * pidlChild [I] + * bImmediate [I] only return true if the parent is the direct parent + * of the child + * + * RETURNS + * True if the parent ItemIDlist is a complete part of the child ItemIdList, + * False otherwise. + * + * NOTES + * parent = a/b, child = a/b/c -> true, c is in folder a/b + * child = a/b/c/d -> false if bImmediate is true, d is not in folder a/b + * child = a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b + */ +BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate) +{ + char szData1[MAX_PATH]; + char szData2[MAX_PATH]; + + LPCITEMIDLIST pParent = pidlParent; + LPCITEMIDLIST pChild = pidlChild; + + TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate); + + if (!pParent || !pChild) return FALSE; + + while (pParent->mkid.cb && pChild->mkid.cb) + { + _ILSimpleGetText(pParent, szData1, MAX_PATH); + _ILSimpleGetText(pChild, szData2, MAX_PATH); + + if (strcasecmp ( szData1, szData2 )!=0 ) + return FALSE; + + pParent = ILGetNext(pParent); + pChild = ILGetNext(pChild); + } + + if ( pParent->mkid.cb || ! pChild->mkid.cb) /* child shorter or has equal length to parent */ + return FALSE; + + if ( ILGetNext(pChild)->mkid.cb && bImmediate) /* not immediate descent */ + return FALSE; + + return TRUE; +} + +/************************************************************************* + * ILFindChild [SHELL32.24] + * + * Compares elements from pidl1 and pidl2. + * + * PARAMS + * pidl1 [I] + * pidl2 [I] + * + * RETURNS + * pidl1 is desktop pidl2 + * pidl1 shorter pidl2 pointer to first different element of pidl2 + * if there was at least one equal element + * pidl2 shorter pidl1 0 + * pidl2 equal pidl1 pointer to last 0x00-element of pidl2 + * + * NOTES + * exported by ordinal. + */ +LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + char szData1[MAX_PATH]; + char szData2[MAX_PATH]; + + LPCITEMIDLIST pidltemp1 = pidl1; + LPCITEMIDLIST pidltemp2 = pidl2; + LPCITEMIDLIST ret=NULL; + + TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2); + + /* explorer reads from registry directly (StreamMRU), + so we can only check here */ + if ((!pcheck (pidl1)) || (!pcheck (pidl2))) + return FALSE; + + pdump (pidl1); + pdump (pidl2); + + if ( _ILIsDesktop(pidl1) ) + { + ret = pidl2; + } + else + { + while (pidltemp1->mkid.cb && pidltemp2->mkid.cb) + { + _ILSimpleGetText(pidltemp1, szData1, MAX_PATH); + _ILSimpleGetText(pidltemp2, szData2, MAX_PATH); + + if (strcasecmp(szData1,szData2)) + break; + + pidltemp1 = ILGetNext(pidltemp1); + pidltemp2 = ILGetNext(pidltemp2); + ret = pidltemp2; + } + + if (pidltemp1->mkid.cb) + { + ret = NULL; /* elements of pidl1 left*/ + } + } + TRACE_(shell)("--- %p\n", ret); + return (LPITEMIDLIST)ret; /* pidl 1 is shorter */ +} + +/************************************************************************* + * ILCombine [SHELL32.25] + * + * Concatenates two complex ItemIDLists. + * + * PARAMS + * pidl1 [I] first complex ItemIDLists + * pidl2 [I] complex ItemIDLists to append + * + * RETURNS + * if both pidl's == NULL NULL + * if pidl1 == NULL cloned pidl2 + * if pidl2 == NULL cloned pidl1 + * otherwise new pidl with pidl2 appended to pidl1 + * + * NOTES + * exported by ordinal. + * Does not destroy the passed in ItemIDLists! + */ +LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + DWORD len1,len2; + LPITEMIDLIST pidlNew; + + TRACE("pidl=%p pidl=%p\n",pidl1,pidl2); + + if(!pidl1 && !pidl2) return NULL; + + pdump (pidl1); + pdump (pidl2); + + if(!pidl1) + { + pidlNew = ILClone(pidl2); + return pidlNew; + } + + if(!pidl2) + { + pidlNew = ILClone(pidl1); + return pidlNew; + } + + len1 = ILGetSize(pidl1)-2; + len2 = ILGetSize(pidl2); + pidlNew = SHAlloc(len1+len2); + + if (pidlNew) + { + memcpy(pidlNew,pidl1,len1); + memcpy(((BYTE *)pidlNew)+len1,pidl2,len2); + } + + /* TRACE(pidl,"--new pidl=%p\n",pidlNew);*/ + return pidlNew; +} + +/************************************************************************* + * SHGetRealIDL [SHELL32.98] + * + * NOTES + */ +HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEMIDLIST *pidlReal) +{ + IDataObject* pDataObj; + HRESULT hr = IShellFolder_GetUIObjectOf(lpsf, 0, 1, &pidlSimple, &IID_IDataObject, 0, (LPVOID*)&pDataObj); + + if (SUCCEEDED(hr)) { + STGMEDIUM medium; + FORMATETC fmt; + + fmt.cfFormat = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_HGLOBAL; + + hr = IDataObject_GetData(pDataObj, &fmt, &medium); + + IDataObject_Release(pDataObj); + + if (SUCCEEDED(hr)) { + /*assert(pida->cidl==1);*/ + LPIDA pida = (LPIDA)GlobalLock(medium.u.hGlobal); + + LPCITEMIDLIST pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]); + LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]); + + *pidlReal = ILCombine(pidl_folder, pidl_child); + + if (!*pidlReal) + hr = E_OUTOFMEMORY; + + GlobalUnlock(medium.u.hGlobal); + GlobalFree(medium.u.hGlobal); + } + } + + return hr; +} + +/************************************************************************* + * SHLogILFromFSIL [SHELL32.95] + * + * NOTES + * pild = CSIDL_DESKTOP ret = 0 + * pild = CSIDL_DRIVES ret = 0 + */ +LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl) +{ + FIXME("(pidl=%p)\n",pidl); + + pdump(pidl); + + return 0; +} + +/************************************************************************* + * ILGetSize [SHELL32.152] + * + * Gets the byte size of an ItemIDList including zero terminator + * + * PARAMS + * pidl [I] ItemIDList + * + * RETURNS + * size of pidl in bytes + * + * NOTES + * exported by ordinal + */ +UINT WINAPI ILGetSize(LPCITEMIDLIST pidl) +{ + LPCSHITEMID si = &(pidl->mkid); + UINT len=0; + + if (pidl) + { while (si->cb) + { len += si->cb; + si = (LPCSHITEMID)(((const BYTE*)si)+si->cb); + } + len += 2; + } + TRACE("pidl=%p size=%u\n",pidl, len); + return len; +} + +/************************************************************************* + * ILGetNext [SHELL32.153] + * + * Gets the next ItemID of an ItemIDList + * + * PARAMS + * pidl [I] ItemIDList + * + * RETURNS + * null -> null + * desktop -> null + * simple pidl -> pointer to 0x0000 element + * + * NOTES + * exported by ordinal. + */ +LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl) +{ + WORD len; + + TRACE("%p\n", pidl); + + if(pidl) + { + len = pidl->mkid.cb; + if (len) + { + pidl = (LPCITEMIDLIST) (((const BYTE*)pidl)+len); + TRACE("-- %p\n", pidl); + return (LPITEMIDLIST)pidl; + } + } + return NULL; +} + +/************************************************************************* + * ILAppend [SHELL32.154] + * + * Adds the single ItemID item to the ItemIDList indicated by pidl. + * If bEnd is FALSE, inserts the item in the front of the list, + * otherwise it adds the item to the end. (???) + * + * PARAMS + * pidl [I] ItemIDList to extend + * item [I] ItemID to prepend/append + * bEnd [I] Indicates if the item should be appended + * + * NOTES + * Destroys the passed in idlist! (???) + */ +LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl, LPCITEMIDLIST item, BOOL bEnd) +{ + LPITEMIDLIST idlRet; + + WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n",pidl,item,bEnd); + + pdump (pidl); + pdump (item); + + if (_ILIsDesktop(pidl)) + { + idlRet = ILClone(item); + if (pidl) + SHFree (pidl); + return idlRet; + } + + if (bEnd) + { + idlRet = ILCombine(pidl, item); + } + else + { + idlRet = ILCombine(item, pidl); + } + + SHFree(pidl); + return idlRet; +} + +/************************************************************************* + * ILFree [SHELL32.155] + * + * Frees memory (if not NULL) allocated by SHMalloc allocator + * + * PARAMS + * pidl [I] + * + * NOTES + * exported by ordinal + */ +void WINAPI ILFree(LPITEMIDLIST pidl) +{ + TRACE("(pidl=%p)\n",pidl); + if(pidl) SHFree(pidl); +} + +/************************************************************************* + * ILGlobalFree [SHELL32.156] + * + * Frees memory (if not NULL) allocated by Alloc allocator + * + * PARAMS + * pidl [I] + * + * NOTES + * exported by ordinal. + */ +void WINAPI ILGlobalFree( LPITEMIDLIST pidl) +{ + TRACE("%p\n", pidl); + + if(!pidl) return; + Free(pidl); +} + +/************************************************************************* + * ILCreateFromPathA [SHELL32.189] + * + * Creates a complex ItemIDList from a path and returns it. + * + * PARAMS + * path [I] + * + * RETURNS + * the newly created complex ItemIDList or NULL if failed + * + * NOTES + * exported by ordinal. + */ + +LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path) +{ + LPITEMIDLIST pidlnew = NULL; + + TRACE_(shell)("%s\n", debugstr_a(path)); + + if (SUCCEEDED(SHILCreateFromPathA(path, &pidlnew, NULL))) + return pidlnew; + return NULL; +} + +/************************************************************************* + * ILCreateFromPathW [SHELL32.190] + */ +LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path) +{ + LPITEMIDLIST pidlnew = NULL; + + TRACE_(shell)("%s\n", debugstr_w(path)); + + if (SUCCEEDED(SHILCreateFromPathW(path, &pidlnew, NULL))) + return pidlnew; + return NULL; +} + +/************************************************************************* + * ILCreateFromPath [SHELL32.157] + */ +LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path) +{ + if ( SHELL_OsIsUnicode()) + return ILCreateFromPathW (path); + return ILCreateFromPathA (path); +} + +/************************************************************************* + * _ILParsePathW [internal] + * + * Creates an ItemIDList from a path and returns it. + * + * PARAMS + * path [I] path to parse and convert into an ItemIDList + * lpFindFile [I] pointer to buffer to initialize the FileSystem + * Bind Data object with + * bBindCtx [I] indicates to create a BindContext and assign a + * FileSystem Bind Data object + * ppidl [O] the newly create ItemIDList + * prgfInOut [I/O] requested attributes on input and actual + * attributes on return + * + * RETURNS + * NO_ERROR on success or an OLE error code + * + * NOTES + * If either lpFindFile is non-NULL or bBindCtx is TRUE, this function + * creates a BindContext object and assigns a FileSystem Bind Data object + * to it, passing the BindContext to IShellFolder_ParseDisplayName. Each + * IShellFolder uses that FileSystem Bind Data object of the BindContext + * to pass data about the current path element to the next object. This + * is used to avoid having to verify the current path element on disk, so + * that creating an ItemIDList from a non-existent path still can work. + */ +static HRESULT WINAPI _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile, + BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut) +{ + LPSHELLFOLDER pSF = NULL; + LPBC pBC = NULL; + HRESULT ret; + + TRACE("%s %p %d (%p)->%p (%p)->0x%lx\n", debugstr_w(path), lpFindFile, bBindCtx, + ppidl, ppidl ? *ppidl : NULL, + prgfInOut, prgfInOut ? *prgfInOut : 0); + + ret = SHGetDesktopFolder(&pSF); + if (FAILED(ret)) + { + return ret; + } + + if (lpFindFile || bBindCtx) + ret = IFileSystemBindData_Constructor(lpFindFile, &pBC); + + if (SUCCEEDED(ret)) + { + ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut); + } + + if (pBC) + { + IBindCtx_Release(pBC); + pBC = NULL; + } + + IShellFolder_Release(pSF); + + if (!SUCCEEDED(ret) && ppidl) + *ppidl = NULL; + + TRACE("%s %p 0x%lx\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0); + + return ret; +} + +/************************************************************************* + * SHSimpleIDListFromPath [SHELL32.162] + * + * Creates a simple ItemIDList from a path and returns it. This function + * does not fail on non-existent paths. + * + * PARAMS + * path [I] path to parse and convert into an ItemIDList + * + * RETURNS + * the newly created simple ItemIDList + * + * NOTES + * Simple in the name does not mean a relative ItemIDList but rather a + * fully qualified list, where only the file name is filled in and the + * directory flag for those ItemID elements this is known about, eg. + * it is not the last element in the ItemIDList or the actual directory + * exists on disk. + * exported by ordinal. + */ +LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath) +{ + LPITEMIDLIST pidl = NULL; + LPWSTR wPath = NULL; + int len; + + TRACE("%s\n", debugstr_a(lpszPath)); + + if (lpszPath) + { + len = MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, NULL, 0); + wPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, wPath, len); + } + + _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL); + + HeapFree(GetProcessHeap(), 0, wPath); + TRACE("%s %p\n", debugstr_a(lpszPath), pidl); + return pidl; +} + +LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath) +{ + LPITEMIDLIST pidl = NULL; + + TRACE("%s\n", debugstr_w(lpszPath)); + + _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL); + TRACE("%s %p\n", debugstr_w(lpszPath), pidl); + return pidl; +} + +LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath) +{ + if ( SHELL_OsIsUnicode()) + return SHSimpleIDListFromPathW (lpszPath); + return SHSimpleIDListFromPathA (lpszPath); +} + +/************************************************************************* + * SHGetDataFromIDListA [SHELL32.247] + * + * NOTES + * the pidl can be a simple one. since we can't get the path out of the pidl + * we have to take all data from the pidl + */ +HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len) +{ + TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len); + + pdump(pidl); + if (!psf || !dest ) return E_INVALIDARG; + + switch (nFormat) + { + case SHGDFIL_FINDDATA: + { + LPSTR filename, shortname; + WIN32_FIND_DATAA * pfd = dest; + + if (_ILIsDrive(pidl)) + return E_INVALIDARG; + + if (len < (int)sizeof(WIN32_FIND_DATAA)) return E_INVALIDARG; + + ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); + _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); + pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); + pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0); + + filename = _ILGetTextPointer(pidl); + shortname = _ILGetSTextPointer(pidl); + + if (filename) + lstrcpynA(pfd->cFileName, filename, MAX_PATH); + else + pfd->cFileName[0] = '\0'; + + if (shortname) + lstrcpynA(pfd->cAlternateFileName, shortname, MAX_PATH); + else + pfd->cAlternateFileName[0] = '\0'; + } + return NOERROR; + + case SHGDFIL_NETRESOURCE: + case SHGDFIL_DESCRIPTIONID: + FIXME_(shell)("SHGDFIL %i stub\n", nFormat); + break; + + default: + ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat); + } + + return E_INVALIDARG; +} + +/************************************************************************* + * SHGetDataFromIDListW [SHELL32.248] + * + */ +HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len) +{ + TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n",psf,pidl,nFormat,dest,len); + + pdump(pidl); + + if (! psf || !dest ) return E_INVALIDARG; + + switch (nFormat) + { + case SHGDFIL_FINDDATA: + { + LPSTR filename, shortname; + WIN32_FIND_DATAW * pfd = dest; + + if (_ILIsDrive(pidl)) + return E_INVALIDARG; + + if (len < (int)sizeof(WIN32_FIND_DATAW)) return E_INVALIDARG; + + ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); + _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); + pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); + pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0); + + filename = _ILGetTextPointer(pidl); + shortname = _ILGetSTextPointer(pidl); + + if (!filename) + pfd->cFileName[0] = '\0'; + else if (!MultiByteToWideChar(CP_ACP, 0, filename, -1, pfd->cFileName, MAX_PATH)) + pfd->cFileName[MAX_PATH-1] = 0; + + if (!shortname) + pfd->cAlternateFileName[0] = '\0'; + else if (!MultiByteToWideChar(CP_ACP, 0, shortname, -1, pfd->cAlternateFileName, 14)) + pfd->cAlternateFileName[13] = 0; + } + return NOERROR; + case SHGDFIL_NETRESOURCE: + case SHGDFIL_DESCRIPTIONID: + FIXME_(shell)("SHGDFIL %i stub\n", nFormat); + break; + + default: + ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat); + } + + return E_INVALIDARG; +} + +/************************************************************************* + * SHELL_GetPathFromIDListA + */ +HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize) +{ + HRESULT hr = S_OK; + + pszPath[0]=0; + + /* One case is a PIDL rooted at desktop level */ + if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { + hr = SHGetSpecialFolderPathA(0, pszPath, CSIDL_DESKTOP, FALSE); + + if (SUCCEEDED(hr)) + PathAddBackslashA(pszPath); + } + /* The only other valid case is a item ID list beginning at "My Computer" */ + else if (_ILIsMyComputer(pidl)) + pidl = ILGetNext(pidl); + + if (SUCCEEDED(hr)) { + LPSTR txt; + + while(pidl && pidl->mkid.cb) { + if (_ILIsSpecialFolder(pidl)) + {hr = E_INVALIDARG; break;} + + txt = _ILGetTextPointer(pidl); + if (!txt) + {hr = E_INVALIDARG; break;} + + if (lstrlenA(txt) > pidl->mkid.cb) + ERR("pidl %p is borked\n",pidl); + + /* make sure there's enough space for the next segment */ + if ( (lstrlenA(txt) + lstrlenA(pszPath)) > uOutSize) + {hr = E_INVALIDARG; break;} + lstrcatA( pszPath, txt ); + + pidl = ILGetNext(pidl); + if (!pidl) + {hr = E_INVALIDARG; break;} + + if (!pidl->mkid.cb) { + /* We are at the end and successfully converted the complete PIDL. */ + break; + } + + if( (lstrlenA(pszPath) + 1) > uOutSize) + {hr = E_INVALIDARG; break;} + if (!PathAddBackslashA(pszPath)) + {hr = E_INVALIDARG; break;} + } + } else + hr = E_INVALIDARG; + + TRACE_(shell)("-- %s, 0x%08lx\n", pszPath, hr); + return hr; +} + +/************************************************************************* + * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220] + * + * PARAMETERS + * pidl, [IN] pidl + * pszPath [OUT] path + * + * RETURNS + * path from a passed PIDL. + * + * NOTES + * NULL returns FALSE + * desktop pidl gives path to desktop directory back + * special pidls returning FALSE + */ +BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath) +{ + HRESULT hr; + + TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); + pdump(pidl); + + if (!pidl) + return FALSE; + + hr = SHELL_GetPathFromIDListA(pidl, pszPath, MAX_PATH); + + return SUCCEEDED(hr); +} + +/************************************************************************* + * SHELL_GetPathFromIDListW + */ +HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize) +{ + HRESULT hr = S_OK; + UINT len; + + pszPath[0]=0; + + /* One case is a PIDL rooted at desktop level */ + if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { + hr = SHGetSpecialFolderPathW(0, pszPath, CSIDL_DESKTOP, FALSE); + + if (SUCCEEDED(hr)) + PathAddBackslashW(pszPath); + } + /* The only other valid case is a item ID list beginning at "My Computer" */ + else if (_ILIsMyComputer(pidl)) + pidl = ILGetNext(pidl); + + if (SUCCEEDED(hr)) { + LPSTR txt; + + while(pidl && pidl->mkid.cb) { + if (_ILIsSpecialFolder(pidl)) + {hr = E_INVALIDARG; break;} + + txt = _ILGetTextPointer(pidl); + if (!txt) + {hr = E_INVALIDARG; break;} + + if (lstrlenA(txt) > pidl->mkid.cb) + ERR("pidl %p is borked\n",pidl); + len = MultiByteToWideChar(CP_ACP, 0, txt, -1, NULL, 0); + if ( (lstrlenW(pszPath) + len) > uOutSize ) + {hr = E_INVALIDARG; break;} + + MultiByteToWideChar(CP_ACP, 0, txt, -1, + &pszPath[lstrlenW(pszPath)], len); + + pidl = ILGetNext(pidl); + if (!pidl) + {hr = E_INVALIDARG; break;} + + if (!pidl->mkid.cb) { + /* We are at the end and successfully converted the complete PIDL. */ + break; + } + + if ( (lstrlenW(pszPath) + 1) > uOutSize ) + {hr = E_INVALIDARG; break;} + if (!PathAddBackslashW(pszPath)) + {hr = E_INVALIDARG; break;} + } + } else + hr = E_INVALIDARG; + + TRACE_(shell)("-- %s, 0x%08lx\n", debugstr_w(pszPath), hr); + return hr; +} + +/************************************************************************* + * SHGetPathFromIDListW [SHELL32.@] + */ +BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath) +{ + HRESULT hr; + + TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath)); + pdump(pidl); + + if (!pidl) + return FALSE; + + hr = SHELL_GetPathFromIDListW(pidl, pszPath, MAX_PATH); + + TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr); + return SUCCEEDED(hr); +} + +/************************************************************************* + * SHBindToParent [shell version 5.0] + */ +HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast) +{ + IShellFolder * psf; + LPITEMIDLIST pidlChild, pidlParent; + HRESULT hr=E_FAIL; + + TRACE_(shell)("pidl=%p\n", pidl); + pdump(pidl); + + *ppv = NULL; + if (ppidlLast) *ppidlLast = NULL; + + if (_ILIsPidlSimple(pidl)) + { + IShellFolder* desktop; + + /* we are on desktop level */ + hr = SHGetDesktopFolder(&desktop); + + if (SUCCEEDED(hr)) + { + hr = IShellFolder_QueryInterface(desktop, riid, ppv); + + if (SUCCEEDED(hr) && ppidlLast) + *ppidlLast = ILClone(pidl); + + IShellFolder_Release(desktop); + } + } + else + { + pidlChild = ILClone(ILFindLastID(pidl)); + pidlParent = ILClone(pidl); + ILRemoveLastID(pidlParent); + + hr = SHGetDesktopFolder(&psf); + + if (SUCCEEDED(hr)) + hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv); + + if (SUCCEEDED(hr) && ppidlLast) + *ppidlLast = pidlChild; + else + ILFree (pidlChild); + + SHFree (pidlParent); + if (psf) IShellFolder_Release(psf); + } + + + TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr); + return hr; +} + +/************************************************************************** + * + * internal functions + * + * ### 1. section creating pidls ### + * + ************************************************************************* + */ +LPITEMIDLIST _ILAlloc(PIDLTYPE type, size_t size) +{ + LPITEMIDLIST pidlOut = NULL; + + if((pidlOut = SHAlloc(size + 5))) + { + LPPIDLDATA pData; + LPITEMIDLIST pidlNext; + + ZeroMemory(pidlOut, size + 5); + pidlOut->mkid.cb = size + 3; + + if ((pData = _ILGetDataPointer(pidlOut))) + pData->type = type; + + if ((pidlNext = ILGetNext(pidlOut))) + pidlNext->mkid.cb = 0x00; + TRACE("-- (pidl=%p, size=%u)\n", pidlOut, size); + } + + return pidlOut; +} + +LPITEMIDLIST _ILCreateDesktop() +{ + LPITEMIDLIST ret; + + TRACE("()\n"); + ret = SHAlloc(2); + if (ret) + ret->mkid.cb = 0; + return ret; +} + +LPITEMIDLIST _ILCreateMyComputer() +{ TRACE("()\n"); + return _ILCreateGuid(PT_GUID, &CLSID_MyComputer); +} + +LPITEMIDLIST _ILCreateIExplore() +{ TRACE("()\n"); + return _ILCreateGuid(PT_GUID, &CLSID_Internet); +} + +LPITEMIDLIST _ILCreateControlPanel() +{ + LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL; + + TRACE("()\n"); + if (parent) + { + LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel); + + if (cpl) + { + ret = ILCombine(parent, cpl); + SHFree(cpl); + } + SHFree(parent); + } + return ret; +} + +LPITEMIDLIST _ILCreatePrinters() +{ + LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL; + + TRACE("()\n"); + if (parent) + { + LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, &CLSID_Printers); + + if (printers) + { + ret = ILCombine(parent, printers); + SHFree(printers); + } + SHFree(parent); + } + return ret; +} + +LPITEMIDLIST _ILCreateNetwork() +{ TRACE("()\n"); + return _ILCreateGuid(PT_GUID, &CLSID_NetworkPlaces); +} + +LPITEMIDLIST _ILCreateBitBucket() +{ TRACE("()\n"); + return _ILCreateGuid(PT_GUID, &CLSID_RecycleBin); +} + +LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid) +{ + LPITEMIDLIST pidlOut; + + if (type == PT_SHELLEXT || type == PT_GUID || type == PT_YAGUID) + { + pidlOut = _ILAlloc(type, sizeof(GUIDStruct)); + if (pidlOut) + { + LPPIDLDATA pData = _ILGetDataPointer(pidlOut); + + memcpy(&(pData->u.guid.guid), guid, sizeof(GUID)); + TRACE("-- create GUID-pidl %s\n", + debugstr_guid(&(pData->u.guid.guid))); + } + } + else + { + WARN("%d: invalid type for GUID\n", type); + pidlOut = NULL; + } + return pidlOut; +} + +LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID) +{ + IID iid; + + if (!SUCCEEDED(SHCLSIDFromStringA(szGUID, &iid))) + { + ERR("%s is not a GUID\n", szGUID); + return NULL; + } + return _ILCreateGuid(PT_GUID, &iid); +} + +LPITEMIDLIST _ILCreateFromFindDataA(WIN32_FIND_DATAA * stffile ) +{ + char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */ + char * pbuff = buff; + size_t len, len1; + LPITEMIDLIST pidl; + PIDLTYPE type; + + if (!stffile) + return NULL; + + TRACE("(%s, %s)\n",stffile->cAlternateFileName, stffile->cFileName); + + /* prepare buffer with both names */ + len = strlen (stffile->cFileName) + 1; + memcpy (pbuff, stffile->cFileName, len); + pbuff += len; + + len1 = strlen (stffile->cAlternateFileName)+1; + memcpy (pbuff, stffile->cAlternateFileName, len1); + + type = (stffile->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? PT_FOLDER : + PT_VALUE; + /* FileStruct already has one byte for the first name, so use len - 1 in + * size calculation + */ + if ((pidl = _ILAlloc(type, sizeof(FileStruct) + (len - 1) + len1))) + { + LPPIDLDATA pData; + LPSTR pszDest; + + /* set attributes */ + if ((pData = _ILGetDataPointer(pidl))) + { + pData->type = type; + FileTimeToDosDateTime(&(stffile->ftLastWriteTime),&pData->u.file.uFileDate,&pData->u.file.uFileTime); + pData->u.file.dwFileSize = stffile->nFileSizeLow; + pData->u.file.uFileAttribs = (WORD)stffile->dwFileAttributes; + } + if ((pszDest = _ILGetTextPointer(pidl))) + { + memcpy(pszDest, buff, len + len1); + TRACE("-- create Value: %s\n",debugstr_a(pszDest)); + } + } + return pidl; +} + +HRESULT _ILCreateFromPathA(LPCSTR szPath, LPITEMIDLIST* ppidl) +{ + HANDLE hFile; + WIN32_FIND_DATAA stffile; + + if (!ppidl) + return E_INVALIDARG; + + hFile = FindFirstFileA(szPath, &stffile); + + if (hFile == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + + FindClose(hFile); + + *ppidl = _ILCreateFromFindDataA(&stffile); + + return *ppidl ? S_OK : E_OUTOFMEMORY; +} + +LPITEMIDLIST _ILCreateDrive(LPCWSTR lpszNew) +{ + WCHAR sTemp[4]; + LPITEMIDLIST pidlOut; + + sTemp[0]=toupperW(lpszNew[0]); + sTemp[1]=':'; + sTemp[2]='\\'; + sTemp[3]=0x00; + TRACE("(%s)\n",debugstr_w(sTemp)); + + if ((pidlOut = _ILAlloc(PT_DRIVE, sizeof(DriveStruct)))) + { + LPSTR pszDest; + + if ((pszDest = _ILGetTextPointer(pidlOut))) + { + WideCharToMultiByte(CP_ACP, 0, sTemp, sizeof(sTemp)/sizeof(WCHAR), pszDest, sizeof(sTemp)/sizeof(WCHAR), NULL, NULL); + TRACE("-- create Drive: %s\n", debugstr_a(pszDest)); + } + } + return pidlOut; +} + +/************************************************************************** + * _ILGetDrive() + * + * Gets the text for the drive eg. 'c:\' + * + * RETURNS + * strlen (lpszText) + */ +DWORD _ILGetDrive(LPCITEMIDLIST pidl,LPSTR pOut, UINT uSize) +{ TRACE("(%p,%p,%u)\n",pidl,pOut,uSize); + + if(_ILIsMyComputer(pidl)) + pidl = ILGetNext(pidl); + + if (pidl && _ILIsDrive(pidl)) + return _ILSimpleGetText(pidl, pOut, uSize); + + return 0; +} + +/************************************************************************** + * + * ### 2. section testing pidls ### + * + ************************************************************************** + * _ILIsDesktop() + * _ILIsMyComputer() + * _ILIsSpecialFolder() + * _ILIsDrive() + * _ILIsFolder() + * _ILIsValue() + * _ILIsPidlSimple() + */ +BOOL _ILIsDesktop(LPCITEMIDLIST pidl) +{ TRACE("(%p)\n",pidl); + return pidl && pidl->mkid.cb ? 0 : 1; +} + +BOOL _ILIsMyComputer(LPCITEMIDLIST pidl) +{ + REFIID iid = _ILGetGUIDPointer(pidl); + + TRACE("(%p)\n",pidl); + + if (iid) + return IsEqualIID(iid, &CLSID_MyComputer); + return FALSE; +} + +BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl) +{ + LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && ( (lpPData && (PT_GUID== lpPData->type || PT_SHELLEXT== lpPData->type)) || + (pidl && pidl->mkid.cb == 0x00) + )); +} + +BOOL _ILIsDrive(LPCITEMIDLIST pidl) +{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && lpPData && (PT_DRIVE == lpPData->type || + PT_DRIVE1 == lpPData->type || + PT_DRIVE2 == lpPData->type || + PT_DRIVE3 == lpPData->type)); +} + +BOOL _ILIsFolder(LPCITEMIDLIST pidl) +{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type)); +} + +BOOL _ILIsValue(LPCITEMIDLIST pidl) +{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && lpPData && PT_VALUE == lpPData->type); +} + +BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl) +{ LPPIDLDATA lpPData = _ILGetDataPointer(pidl); + TRACE("(%p)\n",pidl); + return (pidl && lpPData && (lpPData->type == 0)); +} + +/************************************************************************** + * _ILIsPidlSimple + */ +BOOL _ILIsPidlSimple ( LPCITEMIDLIST pidl) +{ + BOOL ret = TRUE; + + if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */ + { + WORD len = pidl->mkid.cb; + LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((const BYTE*)pidl) + len ); + if (pidlnext->mkid.cb) + ret = FALSE; + } + + TRACE("%s\n", ret ? "Yes" : "No"); + return ret; +} + +/************************************************************************** + * + * ### 3. section getting values from pidls ### + */ + + /************************************************************************** + * _ILSimpleGetText + * + * gets the text for the first item in the pidl (eg. simple pidl) + * + * returns the length of the string + */ +DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize) +{ + DWORD dwReturn=0; + LPSTR szSrc; + GUID const * riid; + char szTemp[MAX_PATH]; + + TRACE("(%p %p %x)\n",pidl,szOut,uOutSize); + + if (!pidl) return 0; + + if (szOut) + *szOut = 0; + + if (_ILIsDesktop(pidl)) + { + /* desktop */ + if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH)) + { + if (szOut) + lstrcpynA(szOut, szTemp, uOutSize); + + dwReturn = strlen (szTemp); + } + } + else if (( szSrc = _ILGetTextPointer(pidl) )) + { + /* filesystem */ + if (szOut) + lstrcpynA(szOut, szSrc, uOutSize); + + dwReturn = strlen(szSrc); + } + else if (( riid = _ILGetGUIDPointer(pidl) )) + { + /* special folder */ + if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) ) + { + if (szOut) + lstrcpynA(szOut, szTemp, uOutSize); + + dwReturn = strlen (szTemp); + } + } + else + { + ERR("-- no text\n"); + } + + TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn); + return dwReturn; +} + + /************************************************************************** + * _ILSimpleGetTextW + * + * gets the text for the first item in the pidl (eg. simple pidl) + * + * returns the length of the string + */ +DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize) +{ + DWORD dwReturn; + char szTemp[MAX_PATH]; + + TRACE("(%p %p %x)\n",pidl,szOut,uOutSize); + + dwReturn = _ILSimpleGetText(pidl, szTemp, uOutSize); + + if (!MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szOut, MAX_PATH)) + *szOut = 0; + + TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_w(szOut),dwReturn); + return dwReturn; +} + +/************************************************************************** + * + * ### 4. getting pointers to parts of pidls ### + * + ************************************************************************** + * _ILGetDataPointer() + */ +LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl) +{ + if(pidl && pidl->mkid.cb != 0x00) + return (LPPIDLDATA) &(pidl->mkid.abID); + return NULL; +} + +/************************************************************************** + * _ILGetTextPointer() + * gets a pointer to the long filename string stored in the pidl + */ +LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl) +{/* TRACE(pidl,"(pidl%p)\n", pidl);*/ + + LPPIDLDATA pdata = _ILGetDataPointer(pidl); + + if (pdata) + { + switch (pdata->type) + { + case PT_GUID: + case PT_SHELLEXT: + case PT_YAGUID: + return NULL; + + case PT_DRIVE: + case PT_DRIVE1: + case PT_DRIVE2: + case PT_DRIVE3: + return (LPSTR)&(pdata->u.drive.szDriveName); + + case PT_FOLDER: + case PT_FOLDER1: + case PT_VALUE: + case PT_IESPECIAL1: + case PT_IESPECIAL2: + return (LPSTR)&(pdata->u.file.szNames); + + case PT_WORKGRP: + case PT_COMP: + case PT_NETWORK: + case PT_NETPROVIDER: + case PT_SHARE: + return (LPSTR)&(pdata->u.network.szNames); + } + } + return NULL; +} + +/************************************************************************** + * _ILGetSTextPointer() + * gets a pointer to the short filename string stored in the pidl + */ +LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl) +{/* TRACE(pidl,"(pidl%p)\n", pidl);*/ + + LPPIDLDATA pdata =_ILGetDataPointer(pidl); + + if (pdata) + { + switch (pdata->type) + { + case PT_FOLDER: + case PT_VALUE: + case PT_IESPECIAL1: + case PT_IESPECIAL2: + return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1); + + case PT_WORKGRP: + return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1); + } + } + return NULL; +} + +/************************************************************************** + * _ILGetGUIDPointer() + * + * returns reference to guid stored in some pidls + */ +IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl) +{ + LPPIDLDATA pdata =_ILGetDataPointer(pidl); + + TRACE("%p\n", pidl); + + if (pdata) + { + TRACE("pdata->type 0x%04x\n", pdata->type); + switch (pdata->type) + { + case PT_SHELLEXT: + case PT_GUID: + return &(pdata->u.guid.guid); + + default: + TRACE("Unknown pidl type 0x%04x\n", pdata->type); + break; + } + } + return NULL; +} + +/************************************************************************* + * _ILGetFileDateTime + * + * Given the ItemIdList, get the FileTime + * + * PARAMS + * pidl [I] The ItemIDList + * pFt [I] the resulted FILETIME of the file + * + * RETURNS + * True if Successful + * + * NOTES + * + */ +BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt) +{ + LPPIDLDATA pdata = _ILGetDataPointer(pidl); + + if(! pdata) return FALSE; + + switch (pdata->type) + { + case PT_FOLDER: + case PT_VALUE: + DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt); + break; + default: + return FALSE; + } + return TRUE; +} + +BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) +{ + FILETIME ft,lft; + SYSTEMTIME time; + BOOL ret; + + if (_ILGetFileDateTime( pidl, &ft )) { + FileTimeToLocalFileTime(&ft, &lft); + FileTimeToSystemTime (&lft, &time); + ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize); + } else { + pOut[0] = '\0'; + ret = FALSE; + } + return ret; + +} + +/************************************************************************* + * _ILGetFileSize + * + * Given the ItemIdList, get the FileSize + * + * PARAMS + * pidl [I] The ItemIDList + * pOut [I] The buffer to save the result + * uOutsize [I] The size of the buffer + * + * RETURNS + * The FileSize + * + * NOTES + * pOut can be null when no string is needed + * + */ +DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) +{ + LPPIDLDATA pdata = _ILGetDataPointer(pidl); + DWORD dwSize; + + if(! pdata) return 0; + + switch (pdata->type) + { + case PT_VALUE: + dwSize = pdata->u.file.dwFileSize; + if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize); + return dwSize; + } + if (pOut) *pOut = 0x00; + return 0; +} + +BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) +{ + char szTemp[MAX_PATH]; + const char * pPoint; + LPCITEMIDLIST pidlTemp=pidl; + + TRACE("pidl=%p\n",pidl); + + if (!pidl) return FALSE; + + pidlTemp = ILFindLastID(pidl); + + if (!_ILIsValue(pidlTemp)) return FALSE; + if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH)) return FALSE; + + pPoint = PathFindExtensionA(szTemp); + + if (! *pPoint) return FALSE; + + pPoint++; + lstrcpynA(pOut, pPoint, uOutSize); + TRACE("%s\n",pOut); + + return TRUE; +} + +/************************************************************************* + * _ILGetFileType + * + * Given the ItemIdList, get the file type description + * + * PARAMS + * pidl [I] The ItemIDList (simple) + * pOut [I] The buffer to save the result + * uOutsize [I] The size of the buffer + * + * RETURNS + * nothing + * + * NOTES + * This function copies as much as possible into the buffer. + */ +void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) +{ + if(_ILIsValue(pidl)) + { + char sTemp[64]; + if(uOutSize > 0) + { + pOut[0] = 0; + } + if (_ILGetExtension (pidl, sTemp, 64)) + { + if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE) + && HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE ))) + { + lstrcpynA (pOut, sTemp, uOutSize - 6); + strcat (pOut, "-file"); + } + } + } + else + { + lstrcpynA(pOut, "Folder", uOutSize); + } +} + +/************************************************************************* + * _ILGetFileAttributes + * + * Given the ItemIdList, get the Attrib string format + * + * PARAMS + * pidl [I] The ItemIDList + * pOut [I] The buffer to save the result + * uOutsize [I] The size of the Buffer + * + * RETURNS + * Attributes + * + * FIXME + * return value 0 in case of error is a valid return value + * + */ +DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize) +{ + LPPIDLDATA pData = _ILGetDataPointer(pidl); + WORD wAttrib = 0; + int i; + + if(! pData) return 0; + + switch(pData->type) + { + case PT_FOLDER: + case PT_VALUE: + wAttrib = pData->u.file.uFileAttribs; + break; + } + + if(uOutSize >= 6) + { + i=0; + if(wAttrib & FILE_ATTRIBUTE_READONLY) + { + pOut[i++] = 'R'; + } + if(wAttrib & FILE_ATTRIBUTE_HIDDEN) + { + pOut[i++] = 'H'; + } + if(wAttrib & FILE_ATTRIBUTE_SYSTEM) + { + pOut[i++] = 'S'; + } + if(wAttrib & FILE_ATTRIBUTE_ARCHIVE) + { + pOut[i++] = 'A'; + } + if(wAttrib & FILE_ATTRIBUTE_COMPRESSED) + { + pOut[i++] = 'C'; + } + pOut[i] = 0x00; + } + return wAttrib; +} + +/************************************************************************* +* ILFreeaPidl +* +* free a aPidl struct +*/ +void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl) +{ + UINT i; + + if (apidl) + { + for (i = 0; i < cidl; i++) SHFree(apidl[i]); + SHFree(apidl); + } +} + +/************************************************************************* +* ILCopyaPidl +* +* copies an aPidl struct +*/ +LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl) +{ + UINT i; + LPITEMIDLIST * apidldest = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST)); + if(!apidlsrc) return NULL; + + for (i = 0; i < cidl; i++) + apidldest[i] = ILClone(apidlsrc[i]); + + return apidldest; +} + +/************************************************************************* +* _ILCopyCidaToaPidl +* +* creates aPidl from CIDA +*/ +LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida) +{ + UINT i; + LPITEMIDLIST * dst = (LPITEMIDLIST*)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST)); + + if(!dst) return NULL; + + if (pidl) + *pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]])); + + for (i = 0; i < cida->cidl; i++) + dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]])); + + return dst; +} diff --git a/reactos/lib/shell32/pidl.h b/reactos/lib/shell32/pidl.h index 39584092d66..b28d217ff6b 100644 --- a/reactos/lib/shell32/pidl.h +++ b/reactos/lib/shell32/pidl.h @@ -1,253 +1,253 @@ -/* - * internal pidl functions - * - * Copyright 1998 Juergen Schmied - * Copyright 2004 Juan Lang - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES: - * - * DO NOT use this definitions outside the shell32.dll ! - * - * The contents of a pidl should never used from a application - * directly. - * - * Undocumented: - * MS says: the abID of SHITEMID should be treated as binary data and not - * be interpreted by applications. Applies to everyone but MS itself. - * Word95 interprets the contents of abID (Filesize/Date) so we have to go - * for binary compatibility here. - */ - -#ifndef __WINE_PIDL_H -#define __WINE_PIDL_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "shlobj.h" - -/* -* the pidl does cache fileattributes to speed up SHGetAttributes when -* displaying a big number of files. -* -* a pidl of NULL means the desktop -* -* The structure of the pidl seems to be a union. The first byte of the -* PIDLDATA desribes the type of pidl. -* -* object ! first byte / ! format ! living space -* ! size -* ---------------------------------------------------------------- -* my computer 0x1F/20 guid (2) (usual) -* network 0x1F guid -* bitbucket 0x1F guid -* drive 0x23/25 drive (usual) -* drive 0x25/25 drive (lnk/persistent) -* drive 0x29/25 drive -* shell extension 0x2E guid -* drive 0x2F drive (lnk/persistent) -* folder/file 0x30 folder/file (1) (lnk/persistent) -* folder 0x31 folder (usual) -* valueA 0x32 file (ANSI file name) -* valueW 0x34 file (Unicode file name) -* workgroup 0x41 network (3) -* computer 0x42 network (4) -* net provider 0x46 network -* whole network 0x47 network (5) -* MSITStore 0x61 htmlhlp (7) -* printers/ras connections 0x70 guid -* history/favorites 0xb1 file -* share 0xc3 network (6) -* -* guess: the persistent elements are non tracking -* -* (1) dummy byte is used, attributes are empty -* (2) IID_MyComputer = 20D04FE0L-3AEA-1069-A2D8-08002B30309D -* (3) two strings "workgroup" "Microsoft Network" -* (4) two strings "\\sirius" "Microsoft Network" -* (5) one string "Entire Network" -* (6) two strings "\\sirius\c" "Microsoft Network" -* (7) contains string "mk:@MSITStore:C:\path\file.chm::/path/filename.htm" -* GUID 871C5380-42A0-1069-A2EA-08002B30309D -*/ - -#define PT_CPLAPPLET 0x00 -#define PT_GUID 0x1F -#define PT_DRIVE 0x23 -#define PT_DRIVE2 0x25 -#define PT_DRIVE3 0x29 -#define PT_SHELLEXT 0x2E -#define PT_DRIVE1 0x2F -#define PT_FOLDER1 0x30 -#define PT_FOLDER 0x31 -#define PT_VALUE 0x32 -#define PT_WORKGRP 0x41 -#define PT_COMP 0x42 -#define PT_NETPROVIDER 0x46 -#define PT_NETWORK 0x47 -#define PT_IESPECIAL1 0x61 -#define PT_YAGUID 0x70 /* yet another guid.. */ -#define PT_IESPECIAL2 0xb1 -#define PT_SHARE 0xc3 - -#include "pshpack1.h" -typedef BYTE PIDLTYPE; - -typedef struct tagPIDLCPanelStruct -{ - BYTE dummy; /*01 is 0x00 */ - DWORD iconIdx; /*02 negative icon ID */ - WORD offsDispName; /*06*/ - WORD offsComment; /*08*/ - CHAR szName[1]; /*10*/ /* terminated by 0x00, followed by display name and comment string */ -} PIDLCPanelStruct; - -typedef struct tagGUIDStruct -{ - BYTE dummy; /* offset 01 is unknown */ - GUID guid; /* offset 02 */ -} GUIDStruct; - -typedef struct tagDriveStruct -{ - CHAR szDriveName[20]; /*01*/ - WORD unknown; /*21*/ -} DriveStruct; - -typedef struct tagFileStruct -{ - BYTE dummy; /*01 is 0x00 for files or dirs */ - DWORD dwFileSize; /*02*/ - WORD uFileDate; /*06*/ - WORD uFileTime; /*08*/ - WORD uFileAttribs; /*10*/ - CHAR szNames[1]; /*12*/ - /* Here are coming two strings. The first is the long name. - The second the dos name when needed or just 0x00 */ -} FileStruct; - -typedef struct tagPIDLDATA -{ PIDLTYPE type; /*00*/ - union - { - struct tagGUIDStruct guid; - struct tagDriveStruct drive; - struct tagFileStruct file; - struct - { WORD dummy; /*01*/ - CHAR szNames[1]; /*03*/ - } network; - struct - { WORD dummy; /*01*/ - DWORD dummy1; /*02*/ - CHAR szName[1]; /*06*/ /* terminated by 0x00 0x00 */ - } htmlhelp; - struct tagPIDLCPanelStruct cpanel; - }u; -} PIDLDATA, *LPPIDLDATA; -#include "poppack.h" - -/* - * getting special values from simple pidls - */ -DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); -DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize); -BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); -DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); -BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); -void _ILGetFileType (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); -DWORD _ILGetFileAttributes (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); - -BOOL _ILGetFileDateTime (LPCITEMIDLIST pidl, FILETIME *ft); -DWORD _ILGetDrive (LPCITEMIDLIST, LPSTR, UINT); - -/* - * testing simple pidls - */ -BOOL _ILIsDesktop (LPCITEMIDLIST pidl); -BOOL _ILIsMyComputer (LPCITEMIDLIST pidl); -BOOL _ILIsDrive (LPCITEMIDLIST pidl); -BOOL _ILIsFolder (LPCITEMIDLIST pidl); -BOOL _ILIsValue (LPCITEMIDLIST pidl); -BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl); -BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl); -BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl); - -/* - * simple pidls - */ - -/* Basic PIDL constructor. Allocates size + 5 bytes, where: - * - two bytes are SHITEMID.cb - * - one byte is PIDLDATA.type - * - two bytes are the NULL PIDL terminator - * Sets type of the returned PIDL to type. - */ -LPITEMIDLIST _ILAlloc(PIDLTYPE type, size_t size); - -/* Creates a PIDL with guid format and type type, which must be one of PT_GUID, - * PT_SHELLEXT, or PT_YAGUID. - */ -LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid); - -/* Like _ILCreateGuid, but using the string szGUID. */ -LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID); - -/* Commonly used PIDLs representing file system objects. */ -LPITEMIDLIST _ILCreateDesktop (void); -LPITEMIDLIST _ILCreateFromFindDataA(WIN32_FIND_DATAA *stffile); -HRESULT _ILCreateFromPathA (LPCSTR szPath, LPITEMIDLIST* ppidl); - -/* Other helpers */ -LPITEMIDLIST _ILCreateMyComputer (void); -LPITEMIDLIST _ILCreateIExplore (void); -LPITEMIDLIST _ILCreateControlPanel (void); -LPITEMIDLIST _ILCreatePrinters (void); -LPITEMIDLIST _ILCreateNetwork (void); -LPITEMIDLIST _ILCreateBitBucket (void); -LPITEMIDLIST _ILCreateDrive (LPCWSTR); - -/* - * helper functions (getting struct-pointer) - */ -LPPIDLDATA _ILGetDataPointer (LPCITEMIDLIST); -LPSTR _ILGetTextPointer (LPCITEMIDLIST); -LPSTR _ILGetSTextPointer (LPCITEMIDLIST); -IID *_ILGetGUIDPointer (LPCITEMIDLIST pidl); - -/* - * debug helper - */ -void pdump (LPCITEMIDLIST pidl); -BOOL pcheck (LPCITEMIDLIST pidl); - -/* - * aPidl helper - */ -void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl); -LPITEMIDLIST * _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl); -LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida); - -BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type); -BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type); - -HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize); -HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize); - -#endif +/* + * internal pidl functions + * + * Copyright 1998 Juergen Schmied + * Copyright 2004 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES: + * + * DO NOT use this definitions outside the shell32.dll ! + * + * The contents of a pidl should never used from a application + * directly. + * + * Undocumented: + * MS says: the abID of SHITEMID should be treated as binary data and not + * be interpreted by applications. Applies to everyone but MS itself. + * Word95 interprets the contents of abID (Filesize/Date) so we have to go + * for binary compatibility here. + */ + +#ifndef __WINE_PIDL_H +#define __WINE_PIDL_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "shlobj.h" + +/* +* the pidl does cache fileattributes to speed up SHGetAttributes when +* displaying a big number of files. +* +* a pidl of NULL means the desktop +* +* The structure of the pidl seems to be a union. The first byte of the +* PIDLDATA desribes the type of pidl. +* +* object ! first byte / ! format ! living space +* ! size +* ---------------------------------------------------------------- +* my computer 0x1F/20 guid (2) (usual) +* network 0x1F guid +* bitbucket 0x1F guid +* drive 0x23/25 drive (usual) +* drive 0x25/25 drive (lnk/persistent) +* drive 0x29/25 drive +* shell extension 0x2E guid +* drive 0x2F drive (lnk/persistent) +* folder/file 0x30 folder/file (1) (lnk/persistent) +* folder 0x31 folder (usual) +* valueA 0x32 file (ANSI file name) +* valueW 0x34 file (Unicode file name) +* workgroup 0x41 network (3) +* computer 0x42 network (4) +* net provider 0x46 network +* whole network 0x47 network (5) +* MSITStore 0x61 htmlhlp (7) +* printers/ras connections 0x70 guid +* history/favorites 0xb1 file +* share 0xc3 network (6) +* +* guess: the persistent elements are non tracking +* +* (1) dummy byte is used, attributes are empty +* (2) IID_MyComputer = 20D04FE0L-3AEA-1069-A2D8-08002B30309D +* (3) two strings "workgroup" "Microsoft Network" +* (4) two strings "\\sirius" "Microsoft Network" +* (5) one string "Entire Network" +* (6) two strings "\\sirius\c" "Microsoft Network" +* (7) contains string "mk:@MSITStore:C:\path\file.chm::/path/filename.htm" +* GUID 871C5380-42A0-1069-A2EA-08002B30309D +*/ + +#define PT_CPLAPPLET 0x00 +#define PT_GUID 0x1F +#define PT_DRIVE 0x23 +#define PT_DRIVE2 0x25 +#define PT_DRIVE3 0x29 +#define PT_SHELLEXT 0x2E +#define PT_DRIVE1 0x2F +#define PT_FOLDER1 0x30 +#define PT_FOLDER 0x31 +#define PT_VALUE 0x32 +#define PT_WORKGRP 0x41 +#define PT_COMP 0x42 +#define PT_NETPROVIDER 0x46 +#define PT_NETWORK 0x47 +#define PT_IESPECIAL1 0x61 +#define PT_YAGUID 0x70 /* yet another guid.. */ +#define PT_IESPECIAL2 0xb1 +#define PT_SHARE 0xc3 + +#include "pshpack1.h" +typedef BYTE PIDLTYPE; + +typedef struct tagPIDLCPanelStruct +{ + BYTE dummy; /*01 is 0x00 */ + DWORD iconIdx; /*02 negative icon ID */ + WORD offsDispName; /*06*/ + WORD offsComment; /*08*/ + CHAR szName[1]; /*10*/ /* terminated by 0x00, followed by display name and comment string */ +} PIDLCPanelStruct; + +typedef struct tagGUIDStruct +{ + BYTE dummy; /* offset 01 is unknown */ + GUID guid; /* offset 02 */ +} GUIDStruct; + +typedef struct tagDriveStruct +{ + CHAR szDriveName[20]; /*01*/ + WORD unknown; /*21*/ +} DriveStruct; + +typedef struct tagFileStruct +{ + BYTE dummy; /*01 is 0x00 for files or dirs */ + DWORD dwFileSize; /*02*/ + WORD uFileDate; /*06*/ + WORD uFileTime; /*08*/ + WORD uFileAttribs; /*10*/ + CHAR szNames[1]; /*12*/ + /* Here are coming two strings. The first is the long name. + The second the dos name when needed or just 0x00 */ +} FileStruct; + +typedef struct tagPIDLDATA +{ PIDLTYPE type; /*00*/ + union + { + struct tagGUIDStruct guid; + struct tagDriveStruct drive; + struct tagFileStruct file; + struct + { WORD dummy; /*01*/ + CHAR szNames[1]; /*03*/ + } network; + struct + { WORD dummy; /*01*/ + DWORD dummy1; /*02*/ + CHAR szName[1]; /*06*/ /* terminated by 0x00 0x00 */ + } htmlhelp; + struct tagPIDLCPanelStruct cpanel; + }u; +} PIDLDATA, *LPPIDLDATA; +#include "poppack.h" + +/* + * getting special values from simple pidls + */ +DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); +DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize); +BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); +DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); +BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); +void _ILGetFileType (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); +DWORD _ILGetFileAttributes (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize); + +BOOL _ILGetFileDateTime (LPCITEMIDLIST pidl, FILETIME *ft); +DWORD _ILGetDrive (LPCITEMIDLIST, LPSTR, UINT); + +/* + * testing simple pidls + */ +BOOL _ILIsDesktop (LPCITEMIDLIST pidl); +BOOL _ILIsMyComputer (LPCITEMIDLIST pidl); +BOOL _ILIsDrive (LPCITEMIDLIST pidl); +BOOL _ILIsFolder (LPCITEMIDLIST pidl); +BOOL _ILIsValue (LPCITEMIDLIST pidl); +BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl); +BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl); +BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl); + +/* + * simple pidls + */ + +/* Basic PIDL constructor. Allocates size + 5 bytes, where: + * - two bytes are SHITEMID.cb + * - one byte is PIDLDATA.type + * - two bytes are the NULL PIDL terminator + * Sets type of the returned PIDL to type. + */ +LPITEMIDLIST _ILAlloc(PIDLTYPE type, size_t size); + +/* Creates a PIDL with guid format and type type, which must be one of PT_GUID, + * PT_SHELLEXT, or PT_YAGUID. + */ +LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid); + +/* Like _ILCreateGuid, but using the string szGUID. */ +LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID); + +/* Commonly used PIDLs representing file system objects. */ +LPITEMIDLIST _ILCreateDesktop (void); +LPITEMIDLIST _ILCreateFromFindDataA(WIN32_FIND_DATAA *stffile); +HRESULT _ILCreateFromPathA (LPCSTR szPath, LPITEMIDLIST* ppidl); + +/* Other helpers */ +LPITEMIDLIST _ILCreateMyComputer (void); +LPITEMIDLIST _ILCreateIExplore (void); +LPITEMIDLIST _ILCreateControlPanel (void); +LPITEMIDLIST _ILCreatePrinters (void); +LPITEMIDLIST _ILCreateNetwork (void); +LPITEMIDLIST _ILCreateBitBucket (void); +LPITEMIDLIST _ILCreateDrive (LPCWSTR); + +/* + * helper functions (getting struct-pointer) + */ +LPPIDLDATA _ILGetDataPointer (LPCITEMIDLIST); +LPSTR _ILGetTextPointer (LPCITEMIDLIST); +LPSTR _ILGetSTextPointer (LPCITEMIDLIST); +IID *_ILGetGUIDPointer (LPCITEMIDLIST pidl); + +/* + * debug helper + */ +void pdump (LPCITEMIDLIST pidl); +BOOL pcheck (LPCITEMIDLIST pidl); + +/* + * aPidl helper + */ +void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl); +LPITEMIDLIST * _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl); +LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida); + +BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type); +BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type); + +HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize); +HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize); + +#endif diff --git a/reactos/lib/shell32/regsvr.c b/reactos/lib/shell32/regsvr.c index 78ee19b315f..accf46e5c87 100644 --- a/reactos/lib/shell32/regsvr.c +++ b/reactos/lib/shell32/regsvr.c @@ -1,540 +1,540 @@ -/* - * self-registerable dll functions for shell32.dll -* - * Copyright (C) 2003 John K. Hohm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winreg.h" -#include "winerror.h" - -#include "ole2.h" -#include "shlguid.h" -#include "shell32_main.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -/* - * Near the bottom of this file are the exported DllRegisterServer and - * DllUnregisterServer, which make all this worthwhile. - */ - -/*********************************************************************** - * interface for self-registering - */ -struct regsvr_interface -{ - IID const *iid; /* NULL for end of list */ - LPCSTR name; /* can be NULL to omit */ - IID const *base_iid; /* can be NULL to omit */ - int num_methods; /* can be <0 to omit */ - CLSID const *ps_clsid; /* can be NULL to omit */ - CLSID const *ps_clsid32; /* can be NULL to omit */ -}; - -static HRESULT register_interfaces(struct regsvr_interface const *list); -static HRESULT unregister_interfaces(struct regsvr_interface const *list); - -struct regsvr_coclass -{ - CLSID const *clsid; /* NULL for end of list */ - LPCSTR name; /* can be NULL to omit */ - LPCSTR ips; /* can be NULL to omit */ - LPCSTR ips32; /* can be NULL to omit */ - LPCSTR ips32_tmodel; /* can be NULL to omit */ - DWORD flags; - LPCSTR clsid_str; /* can be NULL to omit */ - LPCSTR progid; /* can be NULL to omit */ -}; - -/* flags for regsvr_coclass.flags */ -#define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001 - -static HRESULT register_coclasses(struct regsvr_coclass const *list); -static HRESULT unregister_coclasses(struct regsvr_coclass const *list); - -/*********************************************************************** - * static string constants - */ -static WCHAR const interface_keyname[10] = { - 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; -static WCHAR const base_ifa_keyname[14] = { - 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', - 'e', 0 }; -static WCHAR const num_methods_keyname[11] = { - 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; -static WCHAR const ps_clsid_keyname[15] = { - 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', - 'i', 'd', 0 }; -static WCHAR const ps_clsid32_keyname[17] = { - 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', - 'i', 'd', '3', '2', 0 }; -static WCHAR const clsid_keyname[6] = { - 'C', 'L', 'S', 'I', 'D', 0 }; -static WCHAR const ips_keyname[13] = { - 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', - 0 }; -static WCHAR const ips32_keyname[15] = { - 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', - '3', '2', 0 }; -static WCHAR const progid_keyname[7] = { - 'P', 'r', 'o', 'g', 'I', 'D', 0 }; -static WCHAR const shellex_keyname[8] = { - 's', 'h', 'e', 'l', 'l', 'e', 'x', 0 }; -static WCHAR const mcdm_keyname[21] = { - 'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f', - 'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 }; -static char const tmodel_valuename[] = "ThreadingModel"; - -/*********************************************************************** - * static helper functions - */ -static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid); -static LONG register_key_defvalueW(HKEY base, WCHAR const *name, - WCHAR const *value); -static LONG register_key_defvalueA(HKEY base, WCHAR const *name, - char const *value); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); - -/*********************************************************************** - * register_interfaces - */ -static HRESULT register_interfaces(struct regsvr_interface const *list) -{ - LONG res = ERROR_SUCCESS; - HKEY interface_key; - - res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &interface_key, NULL); - if (res != ERROR_SUCCESS) goto error_return; - - for (; res == ERROR_SUCCESS && list->iid; ++list) { - WCHAR buf[39]; - HKEY iid_key; - - StringFromGUID2(list->iid, buf, 39); - res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &iid_key, NULL); - if (res != ERROR_SUCCESS) goto error_close_interface_key; - - if (list->name) { - res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, - (CONST BYTE*)(list->name), - strlen(list->name) + 1); - if (res != ERROR_SUCCESS) goto error_close_iid_key; - } - - if (list->base_iid) { - register_key_guid(iid_key, base_ifa_keyname, list->base_iid); - if (res != ERROR_SUCCESS) goto error_close_iid_key; - } - - if (0 <= list->num_methods) { - static WCHAR const fmt[3] = { '%', 'd', 0 }; - HKEY key; - - res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &key, NULL); - if (res != ERROR_SUCCESS) goto error_close_iid_key; - - wsprintfW(buf, fmt, list->num_methods); - res = RegSetValueExW(key, NULL, 0, REG_SZ, - (CONST BYTE*)buf, - (lstrlenW(buf) + 1) * sizeof(WCHAR)); - RegCloseKey(key); - - if (res != ERROR_SUCCESS) goto error_close_iid_key; - } - - if (list->ps_clsid) { - register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); - if (res != ERROR_SUCCESS) goto error_close_iid_key; - } - - if (list->ps_clsid32) { - register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); - if (res != ERROR_SUCCESS) goto error_close_iid_key; - } - - error_close_iid_key: - RegCloseKey(iid_key); - } - -error_close_interface_key: - RegCloseKey(interface_key); -error_return: - return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; -} - -/*********************************************************************** - * unregister_interfaces - */ -static HRESULT unregister_interfaces(struct regsvr_interface const *list) -{ - LONG res = ERROR_SUCCESS; - HKEY interface_key; - - res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, - KEY_READ | KEY_WRITE, &interface_key); - if (res == ERROR_FILE_NOT_FOUND) return S_OK; - if (res != ERROR_SUCCESS) goto error_return; - - for (; res == ERROR_SUCCESS && list->iid; ++list) { - WCHAR buf[39]; - - StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); - } - - RegCloseKey(interface_key); -error_return: - return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; -} - -/*********************************************************************** - * register_coclasses - */ -static HRESULT register_coclasses(struct regsvr_coclass const *list) -{ - LONG res = ERROR_SUCCESS; - HKEY coclass_key; - - res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL); - if (res != ERROR_SUCCESS) goto error_return; - - for (; res == ERROR_SUCCESS && list->clsid; ++list) { - WCHAR buf[39]; - HKEY clsid_key; - - StringFromGUID2(list->clsid, buf, 39); - res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); - if (res != ERROR_SUCCESS) goto error_close_coclass_key; - - if (list->name) { - res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, - (CONST BYTE*)(list->name), - strlen(list->name) + 1); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - } - - if (list->ips) { - res = register_key_defvalueA(clsid_key, ips_keyname, list->ips); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - } - - if (list->ips32) { - HKEY ips32_key; - - res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, - &ips32_key, NULL); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - - res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ, - (CONST BYTE*)list->ips32, - lstrlenA(list->ips32) + 1); - if (res == ERROR_SUCCESS && list->ips32_tmodel) - res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ, - (CONST BYTE*)list->ips32_tmodel, - strlen(list->ips32_tmodel) + 1); - RegCloseKey(ips32_key); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - } - - if (list->flags & SHELLEX_MAYCHANGEDEFAULTMENU) { - HKEY shellex_key, mcdm_key; - - res = RegCreateKeyExW(clsid_key, shellex_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, - &shellex_key, NULL); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - res = RegCreateKeyExW(shellex_key, mcdm_keyname, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, - &mcdm_key, NULL); - RegCloseKey(shellex_key); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - RegCloseKey(mcdm_key); - } - - if (list->clsid_str) { - res = register_key_defvalueA(clsid_key, clsid_keyname, - list->clsid_str); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - } - - if (list->progid) { - HKEY progid_key; - - res = register_key_defvalueA(clsid_key, progid_keyname, - list->progid); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - - res = RegCreateKeyExA(HKEY_CLASSES_ROOT, list->progid, 0, - NULL, 0, KEY_READ | KEY_WRITE, NULL, - &progid_key, NULL); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - - res = register_key_defvalueW(progid_key, clsid_keyname, buf); - RegCloseKey(progid_key); - if (res != ERROR_SUCCESS) goto error_close_clsid_key; - } - - error_close_clsid_key: - RegCloseKey(clsid_key); - } - -error_close_coclass_key: - RegCloseKey(coclass_key); -error_return: - return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; -} - -/*********************************************************************** - * unregister_coclasses - */ -static HRESULT unregister_coclasses(struct regsvr_coclass const *list) -{ - LONG res = ERROR_SUCCESS; - HKEY coclass_key; - - res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, - KEY_READ | KEY_WRITE, &coclass_key); - if (res == ERROR_FILE_NOT_FOUND) return S_OK; - if (res != ERROR_SUCCESS) goto error_return; - - for (; res == ERROR_SUCCESS && list->clsid; ++list) { - WCHAR buf[39]; - - StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); - if (res != ERROR_SUCCESS) goto error_close_coclass_key; - - if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); - if (res != ERROR_SUCCESS) goto error_close_coclass_key; - } - } - -error_close_coclass_key: - RegCloseKey(coclass_key); -error_return: - return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; -} - -/*********************************************************************** - * regsvr_key_guid - */ -static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) -{ - WCHAR buf[39]; - - StringFromGUID2(guid, buf, 39); - return register_key_defvalueW(base, name, buf); -} - -/*********************************************************************** - * regsvr_key_defvalueW - */ -static LONG register_key_defvalueW( - HKEY base, - WCHAR const *name, - WCHAR const *value) -{ - LONG res; - HKEY key; - - res = RegCreateKeyExW(base, name, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &key, NULL); - if (res != ERROR_SUCCESS) return res; - res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value, - (lstrlenW(value) + 1) * sizeof(WCHAR)); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * regsvr_key_defvalueA - */ -static LONG register_key_defvalueA( - HKEY base, - WCHAR const *name, - char const *value) -{ - LONG res; - HKEY key; - - res = RegCreateKeyExW(base, name, 0, NULL, 0, - KEY_READ | KEY_WRITE, NULL, &key, NULL); - if (res != ERROR_SUCCESS) return res; - res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value, - lstrlenA(value) + 1); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * coclass list - */ -static GUID const CLSID_Desktop = { - 0x00021400, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; - -static GUID const CLSID_Shortcut = { - 0x00021401, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; - -static struct regsvr_coclass const coclass_list[] = { - { &CLSID_Desktop, - "Desktop", - NULL, - "shell32.dll", - "Apartment" - }, - { &CLSID_MyComputer, - "My Computer", - NULL, - "shell32.dll", - "Apartment" - }, - { &CLSID_Shortcut, - "Shortcut", - NULL, - "shell32.dll", - "Apartment", - SHELLEX_MAYCHANGEDEFAULTMENU - }, - { &CLSID_AutoComplete, - "AutoComplete", - NULL, - "shell32.dll", - "Apartment", - }, - { NULL } /* list terminator */ -}; - -/*********************************************************************** - * interface list - */ - -static struct regsvr_interface const interface_list[] = { - { NULL } /* list terminator */ -}; - -/*********************************************************************** - * DllRegisterServer (SHELL32.@) - */ -HRESULT WINAPI SHELL32_DllRegisterServer() -{ - HRESULT hr; - - TRACE("\n"); - - hr = register_coclasses(coclass_list); - if (SUCCEEDED(hr)) - hr = register_interfaces(interface_list); - if (SUCCEEDED(hr)) - hr = SHELL_RegisterShellFolders(); - return hr; -} - -/*********************************************************************** - * DllUnregisterServer (SHELL32.@) - */ -HRESULT WINAPI SHELL32_DllUnregisterServer() -{ - HRESULT hr; - - TRACE("\n"); - - hr = unregister_coclasses(coclass_list); - if (SUCCEEDED(hr)) - hr = unregister_interfaces(interface_list); - return hr; -} +/* + * self-registerable dll functions for shell32.dll +* + * Copyright (C) 2003 John K. Hohm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winerror.h" + +#include "ole2.h" +#include "shlguid.h" +#include "shell32_main.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +/* + * Near the bottom of this file are the exported DllRegisterServer and + * DllUnregisterServer, which make all this worthwhile. + */ + +/*********************************************************************** + * interface for self-registering + */ +struct regsvr_interface +{ + IID const *iid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + IID const *base_iid; /* can be NULL to omit */ + int num_methods; /* can be <0 to omit */ + CLSID const *ps_clsid; /* can be NULL to omit */ + CLSID const *ps_clsid32; /* can be NULL to omit */ +}; + +static HRESULT register_interfaces(struct regsvr_interface const *list); +static HRESULT unregister_interfaces(struct regsvr_interface const *list); + +struct regsvr_coclass +{ + CLSID const *clsid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + LPCSTR ips; /* can be NULL to omit */ + LPCSTR ips32; /* can be NULL to omit */ + LPCSTR ips32_tmodel; /* can be NULL to omit */ + DWORD flags; + LPCSTR clsid_str; /* can be NULL to omit */ + LPCSTR progid; /* can be NULL to omit */ +}; + +/* flags for regsvr_coclass.flags */ +#define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001 + +static HRESULT register_coclasses(struct regsvr_coclass const *list); +static HRESULT unregister_coclasses(struct regsvr_coclass const *list); + +/*********************************************************************** + * static string constants + */ +static WCHAR const interface_keyname[10] = { + 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; +static WCHAR const base_ifa_keyname[14] = { + 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', + 'e', 0 }; +static WCHAR const num_methods_keyname[11] = { + 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; +static WCHAR const ps_clsid_keyname[15] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', 0 }; +static WCHAR const ps_clsid32_keyname[17] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', '3', '2', 0 }; +static WCHAR const clsid_keyname[6] = { + 'C', 'L', 'S', 'I', 'D', 0 }; +static WCHAR const ips_keyname[13] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + 0 }; +static WCHAR const ips32_keyname[15] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + '3', '2', 0 }; +static WCHAR const progid_keyname[7] = { + 'P', 'r', 'o', 'g', 'I', 'D', 0 }; +static WCHAR const shellex_keyname[8] = { + 's', 'h', 'e', 'l', 'l', 'e', 'x', 0 }; +static WCHAR const mcdm_keyname[21] = { + 'M', 'a', 'y', 'C', 'h', 'a', 'n', 'g', 'e', 'D', 'e', 'f', + 'a', 'u', 'l', 't', 'M', 'e', 'n', 'u', 0 }; +static char const tmodel_valuename[] = "ThreadingModel"; + +/*********************************************************************** + * static helper functions + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid); +static LONG register_key_defvalueW(HKEY base, WCHAR const *name, + WCHAR const *value); +static LONG register_key_defvalueA(HKEY base, WCHAR const *name, + char const *value); +static LONG recursive_delete_key(HKEY key); +static LONG recursive_delete_keyA(HKEY base, char const *name); +static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); + +/*********************************************************************** + * register_interfaces + */ +static HRESULT register_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &interface_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + HKEY iid_key; + + StringFromGUID2(list->iid, buf, 39); + res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &iid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_interface_key; + + if (list->name) { + res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->base_iid) { + register_key_guid(iid_key, base_ifa_keyname, list->base_iid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (0 <= list->num_methods) { + static WCHAR const fmt[3] = { '%', 'd', 0 }; + HKEY key; + + res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + + wsprintfW(buf, fmt, list->num_methods); + res = RegSetValueExW(key, NULL, 0, REG_SZ, + (CONST BYTE*)buf, + (lstrlenW(buf) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid) { + register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid32) { + register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + error_close_iid_key: + RegCloseKey(iid_key); + } + +error_close_interface_key: + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_interfaces + */ +static HRESULT unregister_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, + KEY_READ | KEY_WRITE, &interface_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->iid, buf, 39); + res = recursive_delete_keyW(interface_key, buf); + } + + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * register_coclasses + */ +static HRESULT register_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + HKEY clsid_key; + + StringFromGUID2(list->clsid, buf, 39); + res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->name) { + res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips) { + res = register_key_defvalueA(clsid_key, ips_keyname, list->ips); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips32) { + HKEY ips32_key; + + res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, + &ips32_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ, + (CONST BYTE*)list->ips32, + lstrlenA(list->ips32) + 1); + if (res == ERROR_SUCCESS && list->ips32_tmodel) + res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ, + (CONST BYTE*)list->ips32_tmodel, + strlen(list->ips32_tmodel) + 1); + RegCloseKey(ips32_key); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->flags & SHELLEX_MAYCHANGEDEFAULTMENU) { + HKEY shellex_key, mcdm_key; + + res = RegCreateKeyExW(clsid_key, shellex_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, + &shellex_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + res = RegCreateKeyExW(shellex_key, mcdm_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, + &mcdm_key, NULL); + RegCloseKey(shellex_key); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + RegCloseKey(mcdm_key); + } + + if (list->clsid_str) { + res = register_key_defvalueA(clsid_key, clsid_keyname, + list->clsid_str); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->progid) { + HKEY progid_key; + + res = register_key_defvalueA(clsid_key, progid_keyname, + list->progid); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = RegCreateKeyExA(HKEY_CLASSES_ROOT, list->progid, 0, + NULL, 0, KEY_READ | KEY_WRITE, NULL, + &progid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = register_key_defvalueW(progid_key, clsid_keyname, buf); + RegCloseKey(progid_key); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + error_close_clsid_key: + RegCloseKey(clsid_key); + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_coclasses + */ +static HRESULT unregister_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, + KEY_READ | KEY_WRITE, &coclass_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->clsid, buf, 39); + res = recursive_delete_keyW(coclass_key, buf); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->progid) { + res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + } + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * regsvr_key_guid + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) +{ + WCHAR buf[39]; + + StringFromGUID2(guid, buf, 39); + return register_key_defvalueW(base, name, buf); +} + +/*********************************************************************** + * regsvr_key_defvalueW + */ +static LONG register_key_defvalueW( + HKEY base, + WCHAR const *name, + WCHAR const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + (lstrlenW(value) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * regsvr_key_defvalueA + */ +static LONG register_key_defvalueA( + HKEY base, + WCHAR const *name, + char const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + lstrlenA(value) + 1); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * recursive_delete_key + */ +static LONG recursive_delete_key(HKEY key) +{ + LONG res; + WCHAR subkey_name[MAX_PATH]; + DWORD cName; + HKEY subkey; + + for (;;) { + cName = sizeof(subkey_name) / sizeof(WCHAR); + res = RegEnumKeyExW(key, 0, subkey_name, &cName, + NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + res = ERROR_SUCCESS; /* presumably we're done enumerating */ + break; + } + res = RegOpenKeyExW(key, subkey_name, 0, + KEY_READ | KEY_WRITE, &subkey); + if (res == ERROR_FILE_NOT_FOUND) continue; + if (res != ERROR_SUCCESS) break; + + res = recursive_delete_key(subkey); + RegCloseKey(subkey); + if (res != ERROR_SUCCESS) break; + } + + if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); + return res; +} + +/*********************************************************************** + * recursive_delete_keyA + */ +static LONG recursive_delete_keyA(HKEY base, char const *name) +{ + LONG res; + HKEY key; + + res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); + if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; + if (res != ERROR_SUCCESS) return res; + res = recursive_delete_key(key); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * recursive_delete_keyW + */ +static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) +{ + LONG res; + HKEY key; + + res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); + if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; + if (res != ERROR_SUCCESS) return res; + res = recursive_delete_key(key); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * coclass list + */ +static GUID const CLSID_Desktop = { + 0x00021400, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; + +static GUID const CLSID_Shortcut = { + 0x00021401, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; + +static struct regsvr_coclass const coclass_list[] = { + { &CLSID_Desktop, + "Desktop", + NULL, + "shell32.dll", + "Apartment" + }, + { &CLSID_MyComputer, + "My Computer", + NULL, + "shell32.dll", + "Apartment" + }, + { &CLSID_Shortcut, + "Shortcut", + NULL, + "shell32.dll", + "Apartment", + SHELLEX_MAYCHANGEDEFAULTMENU + }, + { &CLSID_AutoComplete, + "AutoComplete", + NULL, + "shell32.dll", + "Apartment", + }, + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * interface list + */ + +static struct regsvr_interface const interface_list[] = { + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * DllRegisterServer (SHELL32.@) + */ +HRESULT WINAPI SHELL32_DllRegisterServer() +{ + HRESULT hr; + + TRACE("\n"); + + hr = register_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = register_interfaces(interface_list); + if (SUCCEEDED(hr)) + hr = SHELL_RegisterShellFolders(); + return hr; +} + +/*********************************************************************** + * DllUnregisterServer (SHELL32.@) + */ +HRESULT WINAPI SHELL32_DllUnregisterServer() +{ + HRESULT hr; + + TRACE("\n"); + + hr = unregister_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = unregister_interfaces(interface_list); + return hr; +} diff --git a/reactos/lib/shell32/ros-systray.c b/reactos/lib/shell32/ros-systray.c index 4bce51b1998..f8f418799b1 100644 --- a/reactos/lib/shell32/ros-systray.c +++ b/reactos/lib/shell32/ros-systray.c @@ -1,80 +1,80 @@ -/* - * Copyright 2004 Martin Fuchs - * - * Pass on icon notification messages to the systray implementation - * in the currently running shell. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "shellapi.h" - - - /* copy data structure for tray notifications */ -typedef struct TrayNotifyCDS_Dummy { - DWORD cookie; - DWORD notify_code; - DWORD nicon_data[1]; // placeholder for NOTIFYICONDATA structure -} TrayNotifyCDS_Dummy; - - /* The only difference between Shell_NotifyIconA and Shell_NotifyIconW is the call to SendMessageA/W. */ -static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, int nid_size, BOOL unicode) -{ - HWND hwnd; - COPYDATASTRUCT data; - - BOOL ret = FALSE; - int len = sizeof(TrayNotifyCDS_Dummy)-sizeof(DWORD)+nid_size; - - TrayNotifyCDS_Dummy* pnotify_data = (TrayNotifyCDS_Dummy*) alloca(len); - - pnotify_data->cookie = 1; - pnotify_data->notify_code = dwMessage; - memcpy(&pnotify_data->nicon_data, pnid, nid_size); - - data.dwData = 1; - data.cbData = len; - data.lpData = pnotify_data; - - for(hwnd=0; hwnd=FindWindowExW(0, hwnd, L"Shell_TrayWnd", NULL); ) - if ((unicode?SendMessageW:SendMessageA)(hwnd, WM_COPYDATA, (WPARAM)nid_hwnd, (LPARAM)&data)) - ret = TRUE; - - return ret; -} - - -/************************************************************************* - * Shell_NotifyIcon [SHELL32.296] - * Shell_NotifyIconA [SHELL32.297] - */ -BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid) -{ - return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, FALSE); -} - -/************************************************************************* - * Shell_NotifyIconW [SHELL32.298] - */ -BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid) -{ - return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, TRUE); -} +/* + * Copyright 2004 Martin Fuchs + * + * Pass on icon notification messages to the systray implementation + * in the currently running shell. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "shellapi.h" + + + /* copy data structure for tray notifications */ +typedef struct TrayNotifyCDS_Dummy { + DWORD cookie; + DWORD notify_code; + DWORD nicon_data[1]; // placeholder for NOTIFYICONDATA structure +} TrayNotifyCDS_Dummy; + + /* The only difference between Shell_NotifyIconA and Shell_NotifyIconW is the call to SendMessageA/W. */ +static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, int nid_size, BOOL unicode) +{ + HWND hwnd; + COPYDATASTRUCT data; + + BOOL ret = FALSE; + int len = sizeof(TrayNotifyCDS_Dummy)-sizeof(DWORD)+nid_size; + + TrayNotifyCDS_Dummy* pnotify_data = (TrayNotifyCDS_Dummy*) alloca(len); + + pnotify_data->cookie = 1; + pnotify_data->notify_code = dwMessage; + memcpy(&pnotify_data->nicon_data, pnid, nid_size); + + data.dwData = 1; + data.cbData = len; + data.lpData = pnotify_data; + + for(hwnd=0; hwnd=FindWindowExW(0, hwnd, L"Shell_TrayWnd", NULL); ) + if ((unicode?SendMessageW:SendMessageA)(hwnd, WM_COPYDATA, (WPARAM)nid_hwnd, (LPARAM)&data)) + ret = TRUE; + + return ret; +} + + +/************************************************************************* + * Shell_NotifyIcon [SHELL32.296] + * Shell_NotifyIconA [SHELL32.297] + */ +BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid) +{ + return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, FALSE); +} + +/************************************************************************* + * Shell_NotifyIconW [SHELL32.298] + */ +BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid) +{ + return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, TRUE); +} diff --git a/reactos/lib/shell32/shell.c b/reactos/lib/shell32/shell.c index ed2b07e7b96..b6307a7beea 100644 --- a/reactos/lib/shell32/shell.c +++ b/reactos/lib/shell32/shell.c @@ -1,659 +1,659 @@ -/* - * Shell Library Functions - * - * Copyright 1998 Marcus Meissner - * Copyright 2000 Juergen Schmied - * Copyright 2002 Eric Pouech - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "wownt32.h" -#include "dlgs.h" -#include "shellapi.h" -#include "winuser.h" -#include "wingdi.h" -#include "shlobj.h" -#include "shlwapi.h" -#include "ddeml.h" - -#include "wine/winbase16.h" -#include "wine/winuser16.h" -#include "shell32_main.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); -WINE_DECLARE_DEBUG_CHANNEL(exec); - - -typedef struct { /* structure for dropped files */ - WORD wSize; - POINT16 ptMousePos; - BOOL16 fInNonClientArea; - /* memory block with filenames follows */ -} DROPFILESTRUCT16, *LPDROPFILESTRUCT16; - -static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED"; -static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED"; -static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW"; - -static HWND SHELL_hWnd = 0; -static HHOOK SHELL_hHook = 0; -static UINT uMsgWndCreated = 0; -static UINT uMsgWndDestroyed = 0; -static UINT uMsgShellActivate = 0; -HINSTANCE16 SHELL_hInstance = 0; -HINSTANCE SHELL_hInstance32; -static int SHELL_Attach = 0; - -/*********************************************************************** - * DllEntryPoint [SHELL.101] - * - * Initialization code for shell.dll. Automatically loads the - * 32-bit shell32.dll to allow thunking up to 32-bit code. - * - * RETURNS - * Success: TRUE. Initialization completed successfully. - * Failure: FALSE. - */ -BOOL WINAPI SHELL_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, - WORD ds, WORD HeapSize, DWORD res1, WORD res2) -{ - TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", - Reason, hInst, ds, HeapSize, res1, res2); - - switch(Reason) - { - case DLL_PROCESS_ATTACH: - if (SHELL_Attach++) break; - SHELL_hInstance = hInst; - if(!SHELL_hInstance32) - { - if(!(SHELL_hInstance32 = LoadLibraryA("shell32.dll"))) - { - ERR("Could not load sibling shell32.dll\n"); - return FALSE; - } - } - break; - - case DLL_PROCESS_DETACH: - if(!--SHELL_Attach) - { - SHELL_hInstance = 0; - if(SHELL_hInstance32) - FreeLibrary(SHELL_hInstance32); - } - break; - } - return TRUE; -} - -/************************************************************************* - * DragAcceptFiles [SHELL.9] - */ -void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b) -{ - DragAcceptFiles(HWND_32(hWnd), b); -} - -/************************************************************************* - * DragQueryFile [SHELL.11] - */ -UINT16 WINAPI DragQueryFile16( - HDROP16 hDrop, - WORD wFile, - LPSTR lpszFile, - WORD wLength) -{ - LPSTR lpDrop; - UINT i = 0; - LPDROPFILESTRUCT16 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); - - TRACE("(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength); - - if(!lpDropFileStruct) goto end; - - lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize; - - while (i++ < wFile) - { - while (*lpDrop++); /* skip filename */ - if (!*lpDrop) - { - i = (wFile == 0xFFFF) ? i : 0; - goto end; - } - } - - i = strlen(lpDrop); - i++; - if (!lpszFile ) goto end; /* needed buffer size */ - i = (wLength > i) ? i : wLength; - lstrcpynA (lpszFile, lpDrop, i); -end: - GlobalUnlock16(hDrop); - return i; -} - -/************************************************************************* - * DragFinish [SHELL.12] - */ -void WINAPI DragFinish16(HDROP16 h) -{ - TRACE("\n"); - GlobalFree16((HGLOBAL16)h); -} - - -/************************************************************************* - * DragQueryPoint [SHELL.13] - */ -BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p) -{ - LPDROPFILESTRUCT16 lpDropFileStruct; - BOOL16 bRet; - TRACE("\n"); - lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); - - memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16)); - bRet = lpDropFileStruct->fInNonClientArea; - - GlobalUnlock16(hDrop); - return bRet; -} - -/************************************************************************* - * FindExecutable (SHELL.21) - */ -HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory, - LPSTR lpResult ) -{ return HINSTANCE_16(FindExecutableA( lpFile, lpDirectory, lpResult )); -} - -/************************************************************************* - * AboutDlgProc (SHELL.33) - */ -BOOL16 WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam, - LPARAM lParam ) -{ return (BOOL16)AboutDlgProc( HWND_32(hWnd), msg, wParam, lParam ); -} - - -/************************************************************************* - * ShellAbout (SHELL.22) - */ -BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff, - HICON16 hIcon ) -{ return ShellAboutA( HWND_32(hWnd), szApp, szOtherStuff, HICON_32(hIcon) ); -} - -/************************************************************************* - * InternalExtractIcon [SHELL.39] - * - * This abortion is called directly by Progman - */ -HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance, - LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n ) -{ - HGLOBAL16 hRet = 0; - HICON16 *RetPtr = NULL; - OFSTRUCT ofs; - - TRACE("(%04x,file %s,start %d,extract %d\n", - hInstance, lpszExeFileName, nIconIndex, n); - - if (!n) - return 0; - - hRet = GlobalAlloc16(GMEM_FIXED | GMEM_ZEROINIT, sizeof(*RetPtr) * n); - RetPtr = (HICON16*)GlobalLock16(hRet); - - if (nIconIndex == (UINT16)-1) /* get number of icons */ - { - RetPtr[0] = PrivateExtractIconsA(ofs.szPathName, 0, 0, 0, NULL, NULL, 0, LR_DEFAULTCOLOR); - } - else - { - UINT ret; - HICON *icons; - - icons = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*icons)); - ret = PrivateExtractIconsA(ofs.szPathName, nIconIndex, - GetSystemMetrics(SM_CXICON), - GetSystemMetrics(SM_CYICON), - icons, NULL, n, LR_DEFAULTCOLOR); - if ((ret != 0xffffffff) && ret) - { - int i; - for (i = 0; i < n; i++) RetPtr[i] = HICON_16(icons[i]); - } - else - { - GlobalFree16(hRet); - hRet = 0; - } - HeapFree(GetProcessHeap(), 0, icons); - } - return hRet; -} - -/************************************************************************* - * ExtractIcon (SHELL.34) - */ -HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName, - UINT16 nIconIndex ) -{ TRACE("\n"); - return HICON_16(ExtractIconA(HINSTANCE_32(hInstance), lpszExeFileName, nIconIndex)); -} - -/************************************************************************* - * ExtractIconEx (SHELL.40) - */ -HICON16 WINAPI ExtractIconEx16( - LPCSTR lpszFile, INT16 nIconIndex, HICON16 *phiconLarge, - HICON16 *phiconSmall, UINT16 nIcons -) { - HICON *ilarge,*ismall; - UINT16 ret; - int i; - - if (phiconLarge) - ilarge = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); - else - ilarge = NULL; - if (phiconSmall) - ismall = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); - else - ismall = NULL; - ret = HICON_16(ExtractIconExA(lpszFile,nIconIndex,ilarge,ismall,nIcons)); - if (ilarge) { - for (i=0;i 1 ) /* found key */ - { - LPSTR lpKey; - *lpend = '\0'; - lpKey = SHELL_FindString(lpEnv, lpstr+1); - if( lpKey ) /* found key value */ - { - int l = strlen(lpKey); - - if( l > length - (lpbstr - lpBuffer) - 1 ) - { - WARN("-- Env subst aborted - string too short\n"); - *lpend = '%'; - break; - } - strcpy(lpbstr, lpKey); - lpbstr += l; - } - else break; - *lpend = '%'; - lpstr = lpend + 1; - } - else break; /* back off and whine */ - - continue; - } - - *lpbstr++ = *lpstr++; - } - - *lpbstr = '\0'; - if( lpstr - str == strlen(str) ) - { - strncpy(str, lpBuffer, length); - length = 1; - } - else - length = 0; - - TRACE("-- return %s\n", str); - - OemToCharA(str,str); - HeapFree( GetProcessHeap(), 0, lpBuffer); - - /* Return str length in the LOWORD - * and 1 in HIWORD if subst was successful. - */ - return (DWORD)MAKELONG(strlen(str), length); -} - -/************************************************************************* - * SHELL_HookProc - * - * 32-bit version of the system-wide WH_SHELL hook. - */ -static LRESULT WINAPI SHELL_HookProc(INT code, WPARAM wParam, LPARAM lParam) -{ - TRACE("%i, %x, %08lx\n", code, wParam, lParam ); - - if (SHELL_hWnd) - { - switch( code ) - { - case HSHELL_WINDOWCREATED: - PostMessageA( SHELL_hWnd, uMsgWndCreated, wParam, 0 ); - break; - case HSHELL_WINDOWDESTROYED: - PostMessageA( SHELL_hWnd, uMsgWndDestroyed, wParam, 0 ); - break; - case HSHELL_ACTIVATESHELLWINDOW: - PostMessageA( SHELL_hWnd, uMsgShellActivate, wParam, 0 ); - break; - } - } - return CallNextHookEx( SHELL_hHook, code, wParam, lParam ); -} - -/************************************************************************* - * ShellHookProc [SHELL.103] - * System-wide WH_SHELL hook. - */ -LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam) -{ - return SHELL_HookProc( code, wParam, lParam ); -} - -/************************************************************************* - * RegisterShellHook [SHELL.102] - */ -BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction) -{ - TRACE("%04x [%u]\n", hWnd, uAction ); - - switch( uAction ) - { - case 2: /* register hWnd as a shell window */ - if( !SHELL_hHook ) - { - SHELL_hHook = SetWindowsHookExA( WH_SHELL, SHELL_HookProc, - GetModuleHandleA("shell32.dll"), 0 ); - if ( SHELL_hHook ) - { - uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated ); - uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed ); - uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate ); - } - else - WARN("-- unable to install ShellHookProc()!\n"); - } - - if ( SHELL_hHook ) - return ((SHELL_hWnd = HWND_32(hWnd)) != 0); - break; - - default: - WARN("-- unknown code %i\n", uAction ); - SHELL_hWnd = 0; /* just in case */ - } - return FALSE; -} - - -/*********************************************************************** - * DriveType (SHELL.262) - */ -UINT16 WINAPI DriveType16( UINT16 drive ) -{ - UINT ret; - char path[] = "A:\\"; - path[0] += drive; - ret = GetDriveTypeA(path); - switch(ret) /* some values are not supported in Win16 */ - { - case DRIVE_CDROM: - ret = DRIVE_REMOTE; - break; - case DRIVE_NO_ROOT_DIR: - ret = DRIVE_UNKNOWN; - break; - } - return ret; -} - - -/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by - * some programs. Do not remove those cases. -MM - */ -static inline void fix_win16_hkey( HKEY *hkey ) -{ - if (*hkey == 0 || *hkey == (HKEY)1) *hkey = HKEY_CLASSES_ROOT; -} - -/****************************************************************************** - * RegOpenKey [SHELL.1] - */ -DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, PHKEY retkey ) -{ - fix_win16_hkey( &hkey ); - return RegOpenKeyA( hkey, name, retkey ); -} - -/****************************************************************************** - * RegCreateKey [SHELL.2] - */ -DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, PHKEY retkey ) -{ - fix_win16_hkey( &hkey ); - return RegCreateKeyA( hkey, name, retkey ); -} - -/****************************************************************************** - * RegCloseKey [SHELL.3] - */ -DWORD WINAPI RegCloseKey16( HKEY hkey ) -{ - fix_win16_hkey( &hkey ); - return RegCloseKey( hkey ); -} - -/****************************************************************************** - * RegDeleteKey [SHELL.4] - */ -DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name ) -{ - fix_win16_hkey( &hkey ); - return RegDeleteKeyA( hkey, name ); -} - -/****************************************************************************** - * RegSetValue [SHELL.5] - */ -DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count ) -{ - fix_win16_hkey( &hkey ); - return RegSetValueA( hkey, name, type, data, count ); -} - -/****************************************************************************** - * RegQueryValue [SHELL.6] - * - * NOTES - * Is this HACK still applicable? - * - * HACK - * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just - * mask out the high 16 bit. This (not so much incidently) hopefully fixes - * Aldus FH4) - */ -DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count -) -{ - fix_win16_hkey( &hkey ); - if (count) *count &= 0xffff; - return RegQueryValueA( hkey, name, data, count ); -} - -/****************************************************************************** - * RegEnumKey [SHELL.7] - */ -DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len ) -{ - fix_win16_hkey( &hkey ); - return RegEnumKeyA( hkey, index, name, name_len ); -} - -/************************************************************************* - * SHELL_Execute16 [Internal] - */ -static UINT SHELL_Execute16(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, - LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) -{ - UINT ret; - char sCmd[MAX_PATH]; - WideCharToMultiByte(CP_ACP, 0, lpCmd, -1, sCmd, MAX_PATH, NULL, NULL); - ret = WinExec16(sCmd, (UINT16)psei->nShow); - psei_out->hInstApp = HINSTANCE_32(ret); - return ret; -} - -/************************************************************************* - * ShellExecute [SHELL.20] - */ -HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation, - LPCSTR lpFile, LPCSTR lpParameters, - LPCSTR lpDirectory, INT16 iShowCmd ) -{ - SHELLEXECUTEINFOW seiW; - WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL; - HANDLE hProcess = 0; - - seiW.lpVerb = lpOperation ? __SHCloneStrAtoW(&wVerb, lpOperation) : NULL; - seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL; - seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL; - seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL; - - seiW.cbSize = sizeof(seiW); - seiW.fMask = 0; - seiW.hwnd = HWND_32(hWnd); - seiW.nShow = iShowCmd; - seiW.lpIDList = 0; - seiW.lpClass = 0; - seiW.hkeyClass = 0; - seiW.dwHotKey = 0; - seiW.hProcess = hProcess; - - ShellExecuteExW32 (&seiW, SHELL_Execute16); - - if (wVerb) SHFree(wVerb); - if (wFile) SHFree(wFile); - if (wParameters) SHFree(wParameters); - if (wDirectory) SHFree(wDirectory); - - return HINSTANCE_16(seiW.hInstApp); -} +/* + * Shell Library Functions + * + * Copyright 1998 Marcus Meissner + * Copyright 2000 Juergen Schmied + * Copyright 2002 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" +#include "wownt32.h" +#include "dlgs.h" +#include "shellapi.h" +#include "winuser.h" +#include "wingdi.h" +#include "shlobj.h" +#include "shlwapi.h" +#include "ddeml.h" + +#include "wine/winbase16.h" +#include "wine/winuser16.h" +#include "shell32_main.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); +WINE_DECLARE_DEBUG_CHANNEL(exec); + + +typedef struct { /* structure for dropped files */ + WORD wSize; + POINT16 ptMousePos; + BOOL16 fInNonClientArea; + /* memory block with filenames follows */ +} DROPFILESTRUCT16, *LPDROPFILESTRUCT16; + +static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED"; +static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED"; +static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW"; + +static HWND SHELL_hWnd = 0; +static HHOOK SHELL_hHook = 0; +static UINT uMsgWndCreated = 0; +static UINT uMsgWndDestroyed = 0; +static UINT uMsgShellActivate = 0; +HINSTANCE16 SHELL_hInstance = 0; +HINSTANCE SHELL_hInstance32; +static int SHELL_Attach = 0; + +/*********************************************************************** + * DllEntryPoint [SHELL.101] + * + * Initialization code for shell.dll. Automatically loads the + * 32-bit shell32.dll to allow thunking up to 32-bit code. + * + * RETURNS + * Success: TRUE. Initialization completed successfully. + * Failure: FALSE. + */ +BOOL WINAPI SHELL_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, + WORD ds, WORD HeapSize, DWORD res1, WORD res2) +{ + TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", + Reason, hInst, ds, HeapSize, res1, res2); + + switch(Reason) + { + case DLL_PROCESS_ATTACH: + if (SHELL_Attach++) break; + SHELL_hInstance = hInst; + if(!SHELL_hInstance32) + { + if(!(SHELL_hInstance32 = LoadLibraryA("shell32.dll"))) + { + ERR("Could not load sibling shell32.dll\n"); + return FALSE; + } + } + break; + + case DLL_PROCESS_DETACH: + if(!--SHELL_Attach) + { + SHELL_hInstance = 0; + if(SHELL_hInstance32) + FreeLibrary(SHELL_hInstance32); + } + break; + } + return TRUE; +} + +/************************************************************************* + * DragAcceptFiles [SHELL.9] + */ +void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b) +{ + DragAcceptFiles(HWND_32(hWnd), b); +} + +/************************************************************************* + * DragQueryFile [SHELL.11] + */ +UINT16 WINAPI DragQueryFile16( + HDROP16 hDrop, + WORD wFile, + LPSTR lpszFile, + WORD wLength) +{ + LPSTR lpDrop; + UINT i = 0; + LPDROPFILESTRUCT16 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); + + TRACE("(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength); + + if(!lpDropFileStruct) goto end; + + lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize; + + while (i++ < wFile) + { + while (*lpDrop++); /* skip filename */ + if (!*lpDrop) + { + i = (wFile == 0xFFFF) ? i : 0; + goto end; + } + } + + i = strlen(lpDrop); + i++; + if (!lpszFile ) goto end; /* needed buffer size */ + i = (wLength > i) ? i : wLength; + lstrcpynA (lpszFile, lpDrop, i); +end: + GlobalUnlock16(hDrop); + return i; +} + +/************************************************************************* + * DragFinish [SHELL.12] + */ +void WINAPI DragFinish16(HDROP16 h) +{ + TRACE("\n"); + GlobalFree16((HGLOBAL16)h); +} + + +/************************************************************************* + * DragQueryPoint [SHELL.13] + */ +BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p) +{ + LPDROPFILESTRUCT16 lpDropFileStruct; + BOOL16 bRet; + TRACE("\n"); + lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); + + memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16)); + bRet = lpDropFileStruct->fInNonClientArea; + + GlobalUnlock16(hDrop); + return bRet; +} + +/************************************************************************* + * FindExecutable (SHELL.21) + */ +HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory, + LPSTR lpResult ) +{ return HINSTANCE_16(FindExecutableA( lpFile, lpDirectory, lpResult )); +} + +/************************************************************************* + * AboutDlgProc (SHELL.33) + */ +BOOL16 WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam, + LPARAM lParam ) +{ return (BOOL16)AboutDlgProc( HWND_32(hWnd), msg, wParam, lParam ); +} + + +/************************************************************************* + * ShellAbout (SHELL.22) + */ +BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff, + HICON16 hIcon ) +{ return ShellAboutA( HWND_32(hWnd), szApp, szOtherStuff, HICON_32(hIcon) ); +} + +/************************************************************************* + * InternalExtractIcon [SHELL.39] + * + * This abortion is called directly by Progman + */ +HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance, + LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n ) +{ + HGLOBAL16 hRet = 0; + HICON16 *RetPtr = NULL; + OFSTRUCT ofs; + + TRACE("(%04x,file %s,start %d,extract %d\n", + hInstance, lpszExeFileName, nIconIndex, n); + + if (!n) + return 0; + + hRet = GlobalAlloc16(GMEM_FIXED | GMEM_ZEROINIT, sizeof(*RetPtr) * n); + RetPtr = (HICON16*)GlobalLock16(hRet); + + if (nIconIndex == (UINT16)-1) /* get number of icons */ + { + RetPtr[0] = PrivateExtractIconsA(ofs.szPathName, 0, 0, 0, NULL, NULL, 0, LR_DEFAULTCOLOR); + } + else + { + UINT ret; + HICON *icons; + + icons = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*icons)); + ret = PrivateExtractIconsA(ofs.szPathName, nIconIndex, + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + icons, NULL, n, LR_DEFAULTCOLOR); + if ((ret != 0xffffffff) && ret) + { + int i; + for (i = 0; i < n; i++) RetPtr[i] = HICON_16(icons[i]); + } + else + { + GlobalFree16(hRet); + hRet = 0; + } + HeapFree(GetProcessHeap(), 0, icons); + } + return hRet; +} + +/************************************************************************* + * ExtractIcon (SHELL.34) + */ +HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName, + UINT16 nIconIndex ) +{ TRACE("\n"); + return HICON_16(ExtractIconA(HINSTANCE_32(hInstance), lpszExeFileName, nIconIndex)); +} + +/************************************************************************* + * ExtractIconEx (SHELL.40) + */ +HICON16 WINAPI ExtractIconEx16( + LPCSTR lpszFile, INT16 nIconIndex, HICON16 *phiconLarge, + HICON16 *phiconSmall, UINT16 nIcons +) { + HICON *ilarge,*ismall; + UINT16 ret; + int i; + + if (phiconLarge) + ilarge = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); + else + ilarge = NULL; + if (phiconSmall) + ismall = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); + else + ismall = NULL; + ret = HICON_16(ExtractIconExA(lpszFile,nIconIndex,ilarge,ismall,nIcons)); + if (ilarge) { + for (i=0;i 1 ) /* found key */ + { + LPSTR lpKey; + *lpend = '\0'; + lpKey = SHELL_FindString(lpEnv, lpstr+1); + if( lpKey ) /* found key value */ + { + int l = strlen(lpKey); + + if( l > length - (lpbstr - lpBuffer) - 1 ) + { + WARN("-- Env subst aborted - string too short\n"); + *lpend = '%'; + break; + } + strcpy(lpbstr, lpKey); + lpbstr += l; + } + else break; + *lpend = '%'; + lpstr = lpend + 1; + } + else break; /* back off and whine */ + + continue; + } + + *lpbstr++ = *lpstr++; + } + + *lpbstr = '\0'; + if( lpstr - str == strlen(str) ) + { + strncpy(str, lpBuffer, length); + length = 1; + } + else + length = 0; + + TRACE("-- return %s\n", str); + + OemToCharA(str,str); + HeapFree( GetProcessHeap(), 0, lpBuffer); + + /* Return str length in the LOWORD + * and 1 in HIWORD if subst was successful. + */ + return (DWORD)MAKELONG(strlen(str), length); +} + +/************************************************************************* + * SHELL_HookProc + * + * 32-bit version of the system-wide WH_SHELL hook. + */ +static LRESULT WINAPI SHELL_HookProc(INT code, WPARAM wParam, LPARAM lParam) +{ + TRACE("%i, %x, %08lx\n", code, wParam, lParam ); + + if (SHELL_hWnd) + { + switch( code ) + { + case HSHELL_WINDOWCREATED: + PostMessageA( SHELL_hWnd, uMsgWndCreated, wParam, 0 ); + break; + case HSHELL_WINDOWDESTROYED: + PostMessageA( SHELL_hWnd, uMsgWndDestroyed, wParam, 0 ); + break; + case HSHELL_ACTIVATESHELLWINDOW: + PostMessageA( SHELL_hWnd, uMsgShellActivate, wParam, 0 ); + break; + } + } + return CallNextHookEx( SHELL_hHook, code, wParam, lParam ); +} + +/************************************************************************* + * ShellHookProc [SHELL.103] + * System-wide WH_SHELL hook. + */ +LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam) +{ + return SHELL_HookProc( code, wParam, lParam ); +} + +/************************************************************************* + * RegisterShellHook [SHELL.102] + */ +BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction) +{ + TRACE("%04x [%u]\n", hWnd, uAction ); + + switch( uAction ) + { + case 2: /* register hWnd as a shell window */ + if( !SHELL_hHook ) + { + SHELL_hHook = SetWindowsHookExA( WH_SHELL, SHELL_HookProc, + GetModuleHandleA("shell32.dll"), 0 ); + if ( SHELL_hHook ) + { + uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated ); + uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed ); + uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate ); + } + else + WARN("-- unable to install ShellHookProc()!\n"); + } + + if ( SHELL_hHook ) + return ((SHELL_hWnd = HWND_32(hWnd)) != 0); + break; + + default: + WARN("-- unknown code %i\n", uAction ); + SHELL_hWnd = 0; /* just in case */ + } + return FALSE; +} + + +/*********************************************************************** + * DriveType (SHELL.262) + */ +UINT16 WINAPI DriveType16( UINT16 drive ) +{ + UINT ret; + char path[] = "A:\\"; + path[0] += drive; + ret = GetDriveTypeA(path); + switch(ret) /* some values are not supported in Win16 */ + { + case DRIVE_CDROM: + ret = DRIVE_REMOTE; + break; + case DRIVE_NO_ROOT_DIR: + ret = DRIVE_UNKNOWN; + break; + } + return ret; +} + + +/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by + * some programs. Do not remove those cases. -MM + */ +static inline void fix_win16_hkey( HKEY *hkey ) +{ + if (*hkey == 0 || *hkey == (HKEY)1) *hkey = HKEY_CLASSES_ROOT; +} + +/****************************************************************************** + * RegOpenKey [SHELL.1] + */ +DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, PHKEY retkey ) +{ + fix_win16_hkey( &hkey ); + return RegOpenKeyA( hkey, name, retkey ); +} + +/****************************************************************************** + * RegCreateKey [SHELL.2] + */ +DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, PHKEY retkey ) +{ + fix_win16_hkey( &hkey ); + return RegCreateKeyA( hkey, name, retkey ); +} + +/****************************************************************************** + * RegCloseKey [SHELL.3] + */ +DWORD WINAPI RegCloseKey16( HKEY hkey ) +{ + fix_win16_hkey( &hkey ); + return RegCloseKey( hkey ); +} + +/****************************************************************************** + * RegDeleteKey [SHELL.4] + */ +DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name ) +{ + fix_win16_hkey( &hkey ); + return RegDeleteKeyA( hkey, name ); +} + +/****************************************************************************** + * RegSetValue [SHELL.5] + */ +DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count ) +{ + fix_win16_hkey( &hkey ); + return RegSetValueA( hkey, name, type, data, count ); +} + +/****************************************************************************** + * RegQueryValue [SHELL.6] + * + * NOTES + * Is this HACK still applicable? + * + * HACK + * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just + * mask out the high 16 bit. This (not so much incidently) hopefully fixes + * Aldus FH4) + */ +DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count +) +{ + fix_win16_hkey( &hkey ); + if (count) *count &= 0xffff; + return RegQueryValueA( hkey, name, data, count ); +} + +/****************************************************************************** + * RegEnumKey [SHELL.7] + */ +DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len ) +{ + fix_win16_hkey( &hkey ); + return RegEnumKeyA( hkey, index, name, name_len ); +} + +/************************************************************************* + * SHELL_Execute16 [Internal] + */ +static UINT SHELL_Execute16(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, + LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) +{ + UINT ret; + char sCmd[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, lpCmd, -1, sCmd, MAX_PATH, NULL, NULL); + ret = WinExec16(sCmd, (UINT16)psei->nShow); + psei_out->hInstApp = HINSTANCE_32(ret); + return ret; +} + +/************************************************************************* + * ShellExecute [SHELL.20] + */ +HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation, + LPCSTR lpFile, LPCSTR lpParameters, + LPCSTR lpDirectory, INT16 iShowCmd ) +{ + SHELLEXECUTEINFOW seiW; + WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL; + HANDLE hProcess = 0; + + seiW.lpVerb = lpOperation ? __SHCloneStrAtoW(&wVerb, lpOperation) : NULL; + seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL; + seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL; + seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL; + + seiW.cbSize = sizeof(seiW); + seiW.fMask = 0; + seiW.hwnd = HWND_32(hWnd); + seiW.nShow = iShowCmd; + seiW.lpIDList = 0; + seiW.lpClass = 0; + seiW.hkeyClass = 0; + seiW.dwHotKey = 0; + seiW.hProcess = hProcess; + + ShellExecuteExW32 (&seiW, SHELL_Execute16); + + if (wVerb) SHFree(wVerb); + if (wFile) SHFree(wFile); + if (wParameters) SHFree(wParameters); + if (wDirectory) SHFree(wDirectory); + + return HINSTANCE_16(seiW.hInstApp); +} diff --git a/reactos/lib/shell32/shell.spec b/reactos/lib/shell32/shell.spec index ca3f8625b76..64c5574a891 100644 --- a/reactos/lib/shell32/shell.spec +++ b/reactos/lib/shell32/shell.spec @@ -1,45 +1,45 @@ - 1 pascal RegOpenKey(long str ptr) RegOpenKey16 - 2 pascal RegCreateKey(long str ptr) RegCreateKey16 - 3 pascal RegCloseKey(long) RegCloseKey16 - 4 pascal RegDeleteKey(long str) RegDeleteKey16 - 5 pascal RegSetValue(long str long str long) RegSetValue16 - 6 pascal RegQueryValue(long str ptr ptr) RegQueryValue16 - 7 pascal RegEnumKey(long long ptr long) RegEnumKey16 - 9 pascal -ret16 DragAcceptFiles(word word) DragAcceptFiles16 - 11 pascal -ret16 DragQueryFile(word s_word ptr s_word) DragQueryFile16 - 12 pascal -ret16 DragFinish(word) DragFinish16 - 13 pascal -ret16 DragQueryPoint(word ptr) DragQueryPoint16 - 20 pascal -ret16 ShellExecute(word str str str str s_word) ShellExecute16 - 21 pascal -ret16 FindExecutable(str str ptr) FindExecutable16 - 22 pascal -ret16 ShellAbout(word ptr ptr word) ShellAbout16 - 33 pascal -ret16 AboutDlgProc(word word word long) AboutDlgProc16 - 34 pascal -ret16 ExtractIcon(word str s_word) ExtractIcon16 - 36 pascal -ret16 ExtractAssociatedIcon(word ptr ptr) ExtractAssociatedIcon16 - 37 pascal DoEnvironmentSubst(ptr word) DoEnvironmentSubst16 - 38 pascal FindEnvironmentString(ptr) FindEnvironmentString16 - 39 pascal -ret16 InternalExtractIcon(word ptr s_word word) InternalExtractIcon16 - 40 pascal -ret16 ExtractIconEx(str word ptr ptr word) ExtractIconEx16 -# 98 stub SHL3216_THUNKDATA16 -# 99 stub SHL1632_THUNKDATA16 - -#100 4 0550 HERETHARBETYGARS exported, shared data -#101 8 010e FINDEXEDLGPROC exported, shared data -101 pascal DllEntryPoint(long word word word long word) SHELL_DllEntryPoint - -102 pascal -ret16 RegisterShellHook(word word) RegisterShellHook16 -103 pascal ShellHookProc(word word long) ShellHookProc16 - -157 stub RESTARTDIALOG -# 166 PICKICONDLG - -262 pascal -ret16 DriveType(long) DriveType16 - -# 263 SH16TO32DRIVEIOCTL -# 264 SH16TO32INT2526 -# 300 SHGETFILEINFO -# 400 SHFORMATDRIVE -401 stub SHCHECKDRIVE -# 402 _RUNDLLCHECKDRIVE - -# 8 WEP -#32 WCI + 1 pascal RegOpenKey(long str ptr) RegOpenKey16 + 2 pascal RegCreateKey(long str ptr) RegCreateKey16 + 3 pascal RegCloseKey(long) RegCloseKey16 + 4 pascal RegDeleteKey(long str) RegDeleteKey16 + 5 pascal RegSetValue(long str long str long) RegSetValue16 + 6 pascal RegQueryValue(long str ptr ptr) RegQueryValue16 + 7 pascal RegEnumKey(long long ptr long) RegEnumKey16 + 9 pascal -ret16 DragAcceptFiles(word word) DragAcceptFiles16 + 11 pascal -ret16 DragQueryFile(word s_word ptr s_word) DragQueryFile16 + 12 pascal -ret16 DragFinish(word) DragFinish16 + 13 pascal -ret16 DragQueryPoint(word ptr) DragQueryPoint16 + 20 pascal -ret16 ShellExecute(word str str str str s_word) ShellExecute16 + 21 pascal -ret16 FindExecutable(str str ptr) FindExecutable16 + 22 pascal -ret16 ShellAbout(word ptr ptr word) ShellAbout16 + 33 pascal -ret16 AboutDlgProc(word word word long) AboutDlgProc16 + 34 pascal -ret16 ExtractIcon(word str s_word) ExtractIcon16 + 36 pascal -ret16 ExtractAssociatedIcon(word ptr ptr) ExtractAssociatedIcon16 + 37 pascal DoEnvironmentSubst(ptr word) DoEnvironmentSubst16 + 38 pascal FindEnvironmentString(ptr) FindEnvironmentString16 + 39 pascal -ret16 InternalExtractIcon(word ptr s_word word) InternalExtractIcon16 + 40 pascal -ret16 ExtractIconEx(str word ptr ptr word) ExtractIconEx16 +# 98 stub SHL3216_THUNKDATA16 +# 99 stub SHL1632_THUNKDATA16 + +#100 4 0550 HERETHARBETYGARS exported, shared data +#101 8 010e FINDEXEDLGPROC exported, shared data +101 pascal DllEntryPoint(long word word word long word) SHELL_DllEntryPoint + +102 pascal -ret16 RegisterShellHook(word word) RegisterShellHook16 +103 pascal ShellHookProc(word word long) ShellHookProc16 + +157 stub RESTARTDIALOG +# 166 PICKICONDLG + +262 pascal -ret16 DriveType(long) DriveType16 + +# 263 SH16TO32DRIVEIOCTL +# 264 SH16TO32INT2526 +# 300 SHGETFILEINFO +# 400 SHFORMATDRIVE +401 stub SHCHECKDRIVE +# 402 _RUNDLLCHECKDRIVE + +# 8 WEP +#32 WCI diff --git a/reactos/lib/shell32/shell32.spec b/reactos/lib/shell32/shell32.spec index e7dc10f4d81..17e70984602 100644 --- a/reactos/lib/shell32/shell32.spec +++ b/reactos/lib/shell32/shell32.spec @@ -1,441 +1,441 @@ -# Functions exported by the Win95 shell32.dll -# (these need to have these exact ordinals, for some -# win95 and winNT dlls import shell32.dll by ordinal) -# This list was updated to dll version 4.72 - - 2 stdcall SHChangeNotifyRegister(long long long long long ptr) - 4 stdcall SHChangeNotifyDeregister (long) - 5 stdcall SHChangeNotifyUpdateEntryList (long long long long) - 9 stub PifMgr_OpenProperties - 10 stub PifMgr_GetProperties - 11 stub PifMgr_SetProperties - 13 stub PifMgr_CloseProperties - 15 stdcall ILGetDisplayName(ptr ptr) - 16 stdcall ILFindLastID(ptr) - 17 stdcall ILRemoveLastID(ptr) - 18 stdcall ILClone(ptr) - 19 stdcall ILCloneFirst (ptr) - 20 stdcall ILGlobalClone (ptr) - 21 stdcall ILIsEqual (ptr ptr) - 23 stdcall ILIsParent (ptr ptr long) - 24 stdcall ILFindChild (ptr ptr) - 25 stdcall ILCombine(ptr ptr) - 26 stdcall ILLoadFromStream (ptr ptr) - 27 stdcall ILSaveToStream(ptr ptr) - 28 stdcall SHILCreateFromPath(ptr ptr ptr) SHILCreateFromPathAW - 29 stdcall PathIsRoot(ptr) PathIsRootAW - 30 stdcall PathBuildRoot(ptr long) PathBuildRootAW - 31 stdcall PathFindExtension(ptr) PathFindExtensionAW - 32 stdcall PathAddBackslash(ptr) PathAddBackslashAW - 33 stdcall PathRemoveBlanks(ptr) PathRemoveBlanksAW - 34 stdcall PathFindFileName(ptr) PathFindFileNameAW - 35 stdcall PathRemoveFileSpec(ptr) PathRemoveFileSpecAW - 36 stdcall PathAppend(ptr ptr) PathAppendAW - 37 stdcall PathCombine(ptr ptr ptr) PathCombineAW - 38 stdcall PathStripPath(ptr)PathStripPathAW - 39 stdcall PathIsUNC (ptr) PathIsUNCAW - 40 stdcall PathIsRelative (ptr) PathIsRelativeAW - 41 stdcall IsLFNDriveA(str) - 42 stdcall IsLFNDriveW(wstr) - 43 stdcall PathIsExe (ptr) PathIsExeAW - 45 stdcall PathFileExists(ptr) PathFileExistsAW - 46 stdcall PathMatchSpec (ptr ptr) PathMatchSpecAW - 47 stdcall PathMakeUniqueName (ptr long ptr ptr ptr)PathMakeUniqueNameAW - 48 stdcall PathSetDlgItemPath (long long ptr) PathSetDlgItemPathAW - 49 stdcall PathQualify (ptr) PathQualifyAW - 50 stdcall PathStripToRoot (ptr) PathStripToRootAW - 51 stdcall PathResolve(str long long) PathResolveAW - 52 stdcall PathGetArgs(str) PathGetArgsAW - 53 stdcall DoEnvironmentSubst (long long) DoEnvironmentSubstAW - 54 stdcall DragAcceptFiles(long long) - 55 stdcall PathQuoteSpaces (ptr) PathQuoteSpacesAW - 56 stdcall PathUnquoteSpaces(str) PathUnquoteSpacesAW - 57 stdcall PathGetDriveNumber (str) PathGetDriveNumberAW - 58 stdcall ParseField(str long ptr long) ParseFieldAW - 59 stdcall RestartDialog(long wstr long) - 60 stdcall ExitWindowsDialog(long) - 61 stdcall RunFileDlg(long long long str str long) - 62 stdcall PickIconDlg(long long long long) - 63 stdcall GetFileNameFromBrowse(long long long long str str str) - 64 stdcall DriveType (long) - 65 stub InvalidateDriveType - 66 stdcall IsNetDrive(long) - 67 stdcall Shell_MergeMenus (long long long long long long) - 68 stdcall SHGetSetSettings(ptr long long) - 69 stub SHGetNetResource - 70 stdcall SHCreateDefClassObject(long long long long long) - 71 stdcall Shell_GetImageList(ptr ptr) - 72 stdcall Shell_GetCachedImageIndex(ptr ptr long) Shell_GetCachedImageIndexAW - 73 stdcall SHShellFolderView_Message(long long long) - 74 stdcall SHCreateStdEnumFmtEtc(long ptr ptr) - 75 stdcall PathYetAnotherMakeUniqueName(ptr wstr wstr wstr) - 76 stub DragQueryInfo - 77 stdcall SHMapPIDLToSystemImageListIndex(ptr ptr ptr) - 78 stdcall OleStrToStrN(str long wstr long) OleStrToStrNAW - 79 stdcall StrToOleStrN(wstr long str long) StrToOleStrNAW - 80 stdcall DragFinish(long) - 81 stdcall DragQueryFile(long long ptr long) DragQueryFileA - 82 stdcall DragQueryFileA(long long ptr long) - 83 stdcall CIDLData_CreateFromIDArray(ptr long ptr ptr) - 84 stub SHIsBadInterfacePtr - 85 stdcall OpenRegStream(long str str long) shlwapi.SHOpenRegStreamA - 86 stdcall SHRegisterDragDrop(long ptr) - 87 stdcall SHRevokeDragDrop(long) - 88 stdcall SHDoDragDrop(long ptr ptr long ptr) - 89 stdcall SHCloneSpecialIDList(long long long) - 90 stdcall SHFindFiles(ptr ptr) - 91 stub SHFindComputer - 92 stdcall PathGetShortPath (ptr) PathGetShortPathAW - 93 stdcall Win32CreateDirectory(wstr ptr) Win32CreateDirectoryAW - 94 stdcall Win32RemoveDirectory(wstr) Win32RemoveDirectoryAW - 95 stdcall SHLogILFromFSIL (ptr) - 96 stdcall StrRetToStrN (ptr long ptr ptr) StrRetToStrNAW - 97 stdcall SHWaitForFileToOpen (long long long) - 98 stdcall SHGetRealIDL (ptr ptr ptr) - 99 stdcall SetAppStartingCursor (long long) - 100 stdcall SHRestricted(long) - - 102 stdcall SHCoCreateInstance(wstr ptr long ptr ptr) - 103 stdcall SignalFileOpen(long) - 104 stdcall FileMenu_DeleteAllItems(long) - 105 stdcall FileMenu_DrawItem(long ptr) - 106 stdcall FileMenu_FindSubMenuByPidl(long ptr) - 107 stdcall FileMenu_GetLastSelectedItemPidls(long ptr ptr) - 108 stdcall FileMenu_HandleMenuChar(long long) - 109 stdcall FileMenu_InitMenuPopup (long) - 110 stdcall FileMenu_InsertUsingPidl (long long ptr long long ptr) - 111 stdcall FileMenu_Invalidate (long) - 112 stdcall FileMenu_MeasureItem(long ptr) - 113 stdcall FileMenu_ReplaceUsingPidl (long long ptr long ptr) - 114 stdcall FileMenu_Create (long long long long long) - 115 stdcall FileMenu_AppendItem (long ptr long long long long) FileMenu_AppendItemAW - 116 stdcall FileMenu_TrackPopupMenuEx (long long long long long long) - 117 stdcall FileMenu_DeleteItemByCmd(long long) - 118 stdcall FileMenu_Destroy (long) - 119 stdcall IsLFNDrive(ptr) IsLFNDriveAW - 120 stdcall FileMenu_AbortInitMenu () - 121 stdcall SHFlushClipboard () - 122 stdcall -noname RunDLL_CallEntry16(long long long str long) #name wrong? - 123 stdcall SHFreeUnusedLibraries () - 124 stdcall FileMenu_AppendFilesForPidl(long ptr long) - 125 stdcall FileMenu_AddFilesForPidl(long long long ptr long long ptr) - 126 stdcall SHOutOfMemoryMessageBox (long long long) - 127 stdcall SHWinHelp (long long long long) - 128 stdcall -private DllGetClassObject(long long ptr) SHELL32_DllGetClassObject - 129 stdcall DAD_AutoScroll(long ptr ptr) - 130 stdcall DAD_DragEnter(long) - 131 stdcall DAD_DragEnterEx(long long long) - 132 stdcall DAD_DragLeave() - 133 stdcall DragQueryFileW(long long ptr long) - 134 stdcall DAD_DragMove(long long) - 135 stdcall DragQueryPoint(long ptr) - 136 stdcall DAD_SetDragImage(long long) - 137 stdcall DAD_ShowDragImage (long) - 139 stub Desktop_UpdateBriefcaseOnEvent - 140 stdcall FileMenu_DeleteItemByIndex(long long) - 141 stdcall FileMenu_DeleteItemByFirstID(long long) - 142 stdcall FileMenu_DeleteSeparator(long) - 143 stdcall FileMenu_EnableItemByCmd(long long long) - 144 stdcall FileMenu_GetItemExtent (long long) - 145 stdcall PathFindOnPath (ptr ptr) PathFindOnPathAW - 146 stdcall RLBuildListOfPaths() - 147 stdcall SHCLSIDFromString(long long) SHCLSIDFromStringAW - 149 stdcall SHFind_InitMenuPopup(long long long long) - - 151 stdcall SHLoadOLE (long) - 152 stdcall ILGetSize(ptr) - 153 stdcall ILGetNext(ptr) - 154 stdcall ILAppend (long long long) - 155 stdcall ILFree (ptr) - 156 stdcall ILGlobalFree (ptr) - 157 stdcall ILCreateFromPath (ptr) ILCreateFromPathAW - 158 stdcall PathGetExtension(str long long) PathGetExtensionAW - 159 stdcall PathIsDirectory(ptr)PathIsDirectoryAW - 160 stub SHNetConnectionDialog - 161 stdcall SHRunControlPanel (long long) - 162 stdcall SHSimpleIDListFromPath (ptr) SHSimpleIDListFromPathAW - 163 stdcall StrToOleStr (wstr str) StrToOleStrAW - 164 stdcall Win32DeleteFile(str) Win32DeleteFileAW - 165 stdcall SHCreateDirectory(long ptr) - 166 stdcall CallCPLEntry16(long long long long long long) - 167 stdcall SHAddFromPropSheetExtArray(long long long) - 168 stdcall SHCreatePropSheetExtArray(long str long) - 169 stdcall SHDestroyPropSheetExtArray(long) - 170 stdcall SHReplaceFromPropSheetExtArray(long long long long) - 171 stdcall PathCleanupSpec(ptr ptr) - 172 stdcall SHCreateLinks(long str ptr long ptr) - 173 stdcall SHValidateUNC(long long long) - 174 stdcall SHCreateShellFolderViewEx (ptr ptr) - 175 stdcall SHGetSpecialFolderPath(long long long long) SHGetSpecialFolderPathAW - 176 stdcall SHSetInstanceExplorer (long) - 177 stub DAD_SetDragImageFromListView - 178 stub SHObjectProperties - 179 stub SHGetNewLinkInfoA - 180 stub SHGetNewLinkInfoW - 181 stdcall RegisterShellHook(long long) - 182 varargs ShellMessageBoxW(long long long str long) - 183 varargs ShellMessageBoxA(long long long str long) - 184 stdcall ArrangeWindows(long long long long long) - 185 stub SHHandleDiskFull - 186 stdcall ILGetDisplayNameEx(ptr ptr ptr long) - 187 stub ILGetPseudoNameW - 188 stdcall ShellDDEInit(long) - 189 stdcall ILCreateFromPathA(str) - 190 stdcall ILCreateFromPathW(wstr) - 191 stub SHUpdateImageA - 192 stdcall SHUpdateImageW(wstr long long long) - 193 stub SHHandleUpdateImage - 194 stub SHCreatePropSheetExtArrayEx - 195 stdcall SHFree(ptr) - 196 stdcall SHAlloc(long) - 197 stub SHGlobalDefect - 198 stdcall SHAbortInvokeCommand () - 199 stub SHGetFileIcon - 200 stub SHLocalAlloc - 201 stub SHLocalFree - 202 stub SHLocalReAlloc - 203 stub AddCommasW - 204 stub ShortSizeFormatW - 205 stub Printer_LoadIconsW - 206 stub Link_AddExtraDataSection - 207 stub Link_ReadExtraDataSection - 208 stub Link_RemoveExtraDataSection - 209 stub Int64ToString - 210 stub LargeIntegerToString - 211 stub Printers_GetPidl - 212 stub Printers_AddPrinterPropPages - 213 stub Printers_RegisterWindowW - 214 stub Printers_UnregisterWindow - 215 stub SHStartNetConnectionDialog - 243 stdcall @(long long) shell32_243 - 244 stdcall SHInitRestricted(ptr ptr) - 247 stdcall SHGetDataFromIDListA (ptr ptr long ptr long) - 248 stdcall SHGetDataFromIDListW (ptr ptr long ptr long) - 249 stdcall PathParseIconLocation (ptr) PathParseIconLocationAW - 250 stdcall PathRemoveExtension (ptr) PathRemoveExtensionAW - 251 stdcall PathRemoveArgs (ptr) PathRemoveArgsAW - 256 stdcall @(ptr ptr) SHELL32_256 - 271 stub SheChangeDirA - 272 stub SheChangeDirExA - 273 stub SheChangeDirExW - 274 stdcall SheChangeDirW(wstr) - 275 stub SheConvertPathW - 276 stub SheFullPathA - 277 stub SheFullPathW - 278 stub SheGetCurDrive - 279 stub SheGetDirA - 280 stub SheGetDirExW - 281 stdcall SheGetDirW (long long) - 282 stub SheGetPathOffsetW - 283 stub SheRemoveQuotesA - 284 stub SheRemoveQuotesW - 285 stub SheSetCurDrive - 286 stub SheShortenPathA - 287 stub SheShortenPathW - 288 stdcall ShellAboutA(long str str long) - 289 stdcall ShellAboutW(long wstr wstr long) - 290 stdcall ShellExecuteA(long str str str str long) - 291 stdcall ShellExecuteEx (long) ShellExecuteExAW - 292 stdcall ShellExecuteExA (long) - 293 stdcall ShellExecuteExW (long) - 294 stdcall ShellExecuteW (long wstr wstr wstr wstr long) - 296 stdcall Shell_NotifyIcon(long ptr) Shell_NotifyIconA - 297 stdcall Shell_NotifyIconA(long ptr) - 298 stdcall Shell_NotifyIconW(long ptr) - 299 stub Shl1632_ThunkData32 - 300 stub Shl3216_ThunkData32 - 301 stdcall StrChrA(str long) shlwapi.StrChrA - 302 stdcall StrChrIA(str long) shlwapi.StrChrIA - 303 stdcall StrChrIW(wstr long) shlwapi.StrChrIW - 304 stdcall StrChrW(wstr long) shlwapi.StrChrW - 305 stdcall StrCmpNA(str str long) shlwapi.StrCmpNA - 306 stdcall StrCmpNIA(str str long) shlwapi.StrCmpNIA - 307 stdcall StrCmpNIW(wstr wstr long) shlwapi.StrCmpNIW - 308 stdcall StrCmpNW(wstr wstr long) shlwapi.StrCmpNW - 309 stdcall StrCpyNA (ptr str long) lstrcpynA - 310 stdcall StrCpyNW(wstr wstr long) shlwapi.StrCpyNW - 311 stdcall StrNCmpA(str str long) shlwapi.StrCmpNA - 312 stdcall StrNCmpIA(str str long) shlwapi.StrCmpNIA - 313 stdcall StrNCmpIW(wstr wstr long) shlwapi.StrCmpNIW - 314 stdcall StrNCmpW(wstr wstr long) shlwapi.StrCmpNW - 315 stdcall StrNCpyA (ptr str long) lstrcpynA - 316 stdcall StrNCpyW(wstr wstr long) shlwapi.StrCpyNW - 317 stdcall StrRChrA(str str long) shlwapi.StrRChrA - 318 stdcall StrRChrIA(str str long) shlwapi.StrRChrIA - 319 stdcall StrRChrIW(str str long) shlwapi.StrRChrIW - 320 stdcall StrRChrW(wstr wstr long) shlwapi.StrRChrW - 321 stub StrRStrA - 322 stdcall StrRStrIA(str str str) shlwapi.StrRStrIA - 323 stdcall StrRStrIW(wstr wstr wstr) shlwapi.StrRStrIW - 324 stub StrRStrW - 325 stdcall StrStrA(str str) shlwapi.StrStrA - 326 stdcall StrStrIA(str str) shlwapi.StrStrIA - 327 stdcall StrStrIW(wstr wstr) shlwapi.StrStrIW - 328 stdcall StrStrW(wstr wstr) shlwapi.StrStrW - - 505 stdcall SHRegCloseKey (long) - 506 stdcall SHRegOpenKeyA (long str long) - 507 stdcall SHRegOpenKeyW (long wstr long) - 508 stub SHRegQueryValueA - 509 stdcall SHRegQueryValueExA(long str ptr ptr ptr ptr) - 510 stdcall SHRegQueryValueW (long long long long) - 511 stdcall SHRegQueryValueExW (long wstr ptr ptr ptr ptr) - 512 stdcall SHRegDeleteKeyW (long wstr) - - 520 stdcall -noname SHAllocShared (ptr long long) - 521 stdcall -noname SHLockShared (long long) - 522 stdcall -noname SHUnlockShared (ptr) - 523 stdcall -noname SHFreeShared (long long) - 524 stdcall RealDriveType (long long) - 525 stub RealDriveTypeFlags - - 640 stdcall NTSHChangeNotifyRegister (long long long long long long) - 641 stdcall NTSHChangeNotifyDeregister (long) - - 643 stub SHChangeNotifyReceive - 644 stdcall SHChangeNotification_Lock(long long ptr ptr) - 645 stdcall SHChangeNotification_Unlock(long) - 646 stub SHChangeRegistrationReceive - 647 stub ReceiveAddToRecentDocs - 648 stub SHWaitOp_Operate - - 650 stdcall PathIsSameRoot(ptr ptr)PathIsSameRootAW - -# nt40/win98 - 651 stdcall ReadCabinetState (long long) # OldReadCabinetState - 652 stdcall WriteCabinetState (long) - 653 stdcall PathProcessCommand (long long long long) PathProcessCommandAW - -# win98 - 654 stdcall @(long long)shell32_654 # ReadCabinetState@8 - 660 stdcall FileIconInit(long) - 680 stdcall IsUserAdmin() - -# >= NT5 - 714 stdcall @(ptr)SHELL32_714 # PathIsTemporaryW - 730 stdcall RestartDialogEx(long wstr long long) - -1217 stub FOOBAR1217 # no joke! This is the real name!! - -# -# version 4.0 (win95) -# _WIN32_IE >= 0x0200 -# -@ stdcall CheckEscapesA(str long) -@ stdcall CheckEscapesW(wstr long) -@ stdcall CommandLineToArgvW(wstr ptr) -@ stdcall Control_FillCache_RunDLL(long long long long) Control_FillCache_RunDLLA -@ stdcall Control_FillCache_RunDLLA(long long long long) -@ stdcall Control_FillCache_RunDLLW(long long long long) -@ stdcall Control_RunDLL(ptr ptr str long) Control_RunDLLA -@ stdcall Control_RunDLLA(ptr ptr str long) -@ stdcall Control_RunDLLW(ptr ptr wstr long) -@ stdcall -private DllCanUnloadNow() SHELL32_DllCanUnloadNow -@ stdcall DllInstall(long wstr)SHELL32_DllInstall -@ stdcall -private DllRegisterServer() SHELL32_DllRegisterServer -@ stdcall -private DllUnregisterServer() SHELL32_DllUnregisterServer -@ stdcall DoEnvironmentSubstA(str str) -@ stdcall DoEnvironmentSubstW(wstr wstr) -@ stub DragQueryFileAorW -@ stdcall DuplicateIcon(long long) -@ stdcall ExtractAssociatedIconA(long ptr long) -@ stdcall ExtractAssociatedIconExA(long str long long) -@ stdcall ExtractAssociatedIconExW(long wstr long long) -@ stub ExtractAssociatedIconW -@ stdcall ExtractIconA(long str long) -@ stdcall ExtractIconEx(ptr long ptr ptr long)ExtractIconExAW -@ stdcall ExtractIconExA(str long ptr ptr long) -@ stdcall ExtractIconExW(wstr long ptr ptr long) -@ stdcall ExtractIconW(long wstr long) -@ stub ExtractIconResInfoA -@ stub ExtractIconResInfoW -@ stub ExtractVersionResource16W -@ stub FindExeDlgProc -@ stdcall FindExecutableA(ptr ptr ptr) -@ stdcall FindExecutableW(wstr wstr wstr) -@ stdcall FreeIconList(long) -@ stub InternalExtractIconListA -@ stub InternalExtractIconListW -@ stub OpenAs_RunDLL -@ stub OpenAs_RunDLLA -@ stub OpenAs_RunDLLW -@ stub PrintersGetCommand_RunDLL -@ stub PrintersGetCommand_RunDLLA -@ stub PrintersGetCommand_RunDLLW -@ stub RealShellExecuteA -@ stub RealShellExecuteExA -@ stub RealShellExecuteExW -@ stub RealShellExecuteW -@ stub RegenerateUserEnvironment -@ stdcall SHAddToRecentDocs (long ptr) -@ stdcall SHAppBarMessage(long ptr) -@ stdcall SHBrowseForFolder(ptr) SHBrowseForFolderA -@ stdcall SHBrowseForFolderA(ptr) -@ stdcall SHBrowseForFolderW(ptr) -@ stdcall SHChangeNotify (long long ptr ptr) -@ stdcall SHCreateDirectoryExA(long str ptr) -@ stdcall SHCreateDirectoryExW(long wstr ptr) -@ stub ShellHookProc -@ stub SHEmptyRecycleBinA -@ stub SHEmptyRecycleBinW -@ stdcall SHFileOperation(ptr)SHFileOperationAW -@ stdcall SHFileOperationA(ptr) -@ stdcall SHFileOperationW(ptr) -@ stub SHFormatDrive -@ stdcall SHFreeNameMappings(ptr) -@ stdcall SHGetDesktopFolder(ptr) -@ stdcall SHGetFileInfo(ptr long ptr long long)SHGetFileInfoAW -@ stdcall SHGetFileInfoA(ptr long ptr long long) -@ stdcall SHGetFileInfoW(ptr long ptr long long) -@ stdcall SHGetInstanceExplorer(long) -@ stdcall SHGetMalloc(ptr) -@ stub SHGetNewLinkInfo -@ stdcall SHGetPathFromIDList(ptr ptr)SHGetPathFromIDListAW -@ stdcall SHGetPathFromIDListA(ptr ptr) -@ stdcall SHGetPathFromIDListW(ptr ptr) -@ stdcall SHGetSettings(ptr long) -@ stdcall SHGetSpecialFolderLocation(long long ptr) -@ stdcall SHHelpShortcuts_RunDLL(long long long long) -@ stub SHHelpShortcuts_RunDLLA -@ stub SHHelpShortcuts_RunDLLW -@ stdcall SHLoadInProc(long) -@ stub SHQueryRecycleBinA -@ stub SHQueryRecycleBinW -@ stub SHUpdateRecycleBinIcon -@ stub WOWShellExecute - -# -# version 4.70 (IE3.0) -# _WIN32_IE >= 0x0300 -# - -# -# version 4.71 (IE4.0) -# _WIN32_IE >= 0x0400 -# -@ stdcall DllGetVersion(ptr)SHELL32_DllGetVersion -@ stub SHGetFreeDiskSpace -@ stdcall SHGetSpecialFolderPathA(long ptr long long) -@ stdcall SHGetSpecialFolderPathW(long ptr long long) -# -# version 4.72 (IE4.01) -# _WIN32_IE >= 0x0401 -# no new exports -# - -# -# version 5.00 (Win2K) -# _WIN32_IE >= 0x0500 -# -@ stdcall SHBindToParent(ptr ptr ptr ptr) -@ stdcall SHGetDiskFreeSpaceA(str ptr ptr ptr) kernel32.GetDiskFreeSpaceExA -@ stdcall SHGetDiskFreeSpaceExA(str ptr ptr ptr) kernel32.GetDiskFreeSpaceExA -@ stdcall SHGetDiskFreeSpaceExW(wstr ptr ptr ptr) kernel32.GetDiskFreeSpaceExW -@ stdcall SHGetFolderPathA(long long long long ptr) -@ stdcall SHGetFolderPathW(long long long long ptr) -@ stdcall SHGetFolderLocation(long long long long ptr) - -# version 6.0 (WinXP) -# _WIN32_IE >= 0x600 -@ stdcall SHDefExtractIconA(str long long ptr ptr long) -@ stdcall SHDefExtractIconW(wstr long long ptr ptr long) +# Functions exported by the Win95 shell32.dll +# (these need to have these exact ordinals, for some +# win95 and winNT dlls import shell32.dll by ordinal) +# This list was updated to dll version 4.72 + + 2 stdcall SHChangeNotifyRegister(long long long long long ptr) + 4 stdcall SHChangeNotifyDeregister (long) + 5 stdcall SHChangeNotifyUpdateEntryList (long long long long) + 9 stub PifMgr_OpenProperties + 10 stub PifMgr_GetProperties + 11 stub PifMgr_SetProperties + 13 stub PifMgr_CloseProperties + 15 stdcall ILGetDisplayName(ptr ptr) + 16 stdcall ILFindLastID(ptr) + 17 stdcall ILRemoveLastID(ptr) + 18 stdcall ILClone(ptr) + 19 stdcall ILCloneFirst (ptr) + 20 stdcall ILGlobalClone (ptr) + 21 stdcall ILIsEqual (ptr ptr) + 23 stdcall ILIsParent (ptr ptr long) + 24 stdcall ILFindChild (ptr ptr) + 25 stdcall ILCombine(ptr ptr) + 26 stdcall ILLoadFromStream (ptr ptr) + 27 stdcall ILSaveToStream(ptr ptr) + 28 stdcall SHILCreateFromPath(ptr ptr ptr) SHILCreateFromPathAW + 29 stdcall PathIsRoot(ptr) PathIsRootAW + 30 stdcall PathBuildRoot(ptr long) PathBuildRootAW + 31 stdcall PathFindExtension(ptr) PathFindExtensionAW + 32 stdcall PathAddBackslash(ptr) PathAddBackslashAW + 33 stdcall PathRemoveBlanks(ptr) PathRemoveBlanksAW + 34 stdcall PathFindFileName(ptr) PathFindFileNameAW + 35 stdcall PathRemoveFileSpec(ptr) PathRemoveFileSpecAW + 36 stdcall PathAppend(ptr ptr) PathAppendAW + 37 stdcall PathCombine(ptr ptr ptr) PathCombineAW + 38 stdcall PathStripPath(ptr)PathStripPathAW + 39 stdcall PathIsUNC (ptr) PathIsUNCAW + 40 stdcall PathIsRelative (ptr) PathIsRelativeAW + 41 stdcall IsLFNDriveA(str) + 42 stdcall IsLFNDriveW(wstr) + 43 stdcall PathIsExe (ptr) PathIsExeAW + 45 stdcall PathFileExists(ptr) PathFileExistsAW + 46 stdcall PathMatchSpec (ptr ptr) PathMatchSpecAW + 47 stdcall PathMakeUniqueName (ptr long ptr ptr ptr)PathMakeUniqueNameAW + 48 stdcall PathSetDlgItemPath (long long ptr) PathSetDlgItemPathAW + 49 stdcall PathQualify (ptr) PathQualifyAW + 50 stdcall PathStripToRoot (ptr) PathStripToRootAW + 51 stdcall PathResolve(str long long) PathResolveAW + 52 stdcall PathGetArgs(str) PathGetArgsAW + 53 stdcall DoEnvironmentSubst (long long) DoEnvironmentSubstAW + 54 stdcall DragAcceptFiles(long long) + 55 stdcall PathQuoteSpaces (ptr) PathQuoteSpacesAW + 56 stdcall PathUnquoteSpaces(str) PathUnquoteSpacesAW + 57 stdcall PathGetDriveNumber (str) PathGetDriveNumberAW + 58 stdcall ParseField(str long ptr long) ParseFieldAW + 59 stdcall RestartDialog(long wstr long) + 60 stdcall ExitWindowsDialog(long) + 61 stdcall RunFileDlg(long long long str str long) + 62 stdcall PickIconDlg(long long long long) + 63 stdcall GetFileNameFromBrowse(long long long long str str str) + 64 stdcall DriveType (long) + 65 stub InvalidateDriveType + 66 stdcall IsNetDrive(long) + 67 stdcall Shell_MergeMenus (long long long long long long) + 68 stdcall SHGetSetSettings(ptr long long) + 69 stub SHGetNetResource + 70 stdcall SHCreateDefClassObject(long long long long long) + 71 stdcall Shell_GetImageList(ptr ptr) + 72 stdcall Shell_GetCachedImageIndex(ptr ptr long) Shell_GetCachedImageIndexAW + 73 stdcall SHShellFolderView_Message(long long long) + 74 stdcall SHCreateStdEnumFmtEtc(long ptr ptr) + 75 stdcall PathYetAnotherMakeUniqueName(ptr wstr wstr wstr) + 76 stub DragQueryInfo + 77 stdcall SHMapPIDLToSystemImageListIndex(ptr ptr ptr) + 78 stdcall OleStrToStrN(str long wstr long) OleStrToStrNAW + 79 stdcall StrToOleStrN(wstr long str long) StrToOleStrNAW + 80 stdcall DragFinish(long) + 81 stdcall DragQueryFile(long long ptr long) DragQueryFileA + 82 stdcall DragQueryFileA(long long ptr long) + 83 stdcall CIDLData_CreateFromIDArray(ptr long ptr ptr) + 84 stub SHIsBadInterfacePtr + 85 stdcall OpenRegStream(long str str long) shlwapi.SHOpenRegStreamA + 86 stdcall SHRegisterDragDrop(long ptr) + 87 stdcall SHRevokeDragDrop(long) + 88 stdcall SHDoDragDrop(long ptr ptr long ptr) + 89 stdcall SHCloneSpecialIDList(long long long) + 90 stdcall SHFindFiles(ptr ptr) + 91 stub SHFindComputer + 92 stdcall PathGetShortPath (ptr) PathGetShortPathAW + 93 stdcall Win32CreateDirectory(wstr ptr) Win32CreateDirectoryAW + 94 stdcall Win32RemoveDirectory(wstr) Win32RemoveDirectoryAW + 95 stdcall SHLogILFromFSIL (ptr) + 96 stdcall StrRetToStrN (ptr long ptr ptr) StrRetToStrNAW + 97 stdcall SHWaitForFileToOpen (long long long) + 98 stdcall SHGetRealIDL (ptr ptr ptr) + 99 stdcall SetAppStartingCursor (long long) + 100 stdcall SHRestricted(long) + + 102 stdcall SHCoCreateInstance(wstr ptr long ptr ptr) + 103 stdcall SignalFileOpen(long) + 104 stdcall FileMenu_DeleteAllItems(long) + 105 stdcall FileMenu_DrawItem(long ptr) + 106 stdcall FileMenu_FindSubMenuByPidl(long ptr) + 107 stdcall FileMenu_GetLastSelectedItemPidls(long ptr ptr) + 108 stdcall FileMenu_HandleMenuChar(long long) + 109 stdcall FileMenu_InitMenuPopup (long) + 110 stdcall FileMenu_InsertUsingPidl (long long ptr long long ptr) + 111 stdcall FileMenu_Invalidate (long) + 112 stdcall FileMenu_MeasureItem(long ptr) + 113 stdcall FileMenu_ReplaceUsingPidl (long long ptr long ptr) + 114 stdcall FileMenu_Create (long long long long long) + 115 stdcall FileMenu_AppendItem (long ptr long long long long) FileMenu_AppendItemAW + 116 stdcall FileMenu_TrackPopupMenuEx (long long long long long long) + 117 stdcall FileMenu_DeleteItemByCmd(long long) + 118 stdcall FileMenu_Destroy (long) + 119 stdcall IsLFNDrive(ptr) IsLFNDriveAW + 120 stdcall FileMenu_AbortInitMenu () + 121 stdcall SHFlushClipboard () + 122 stdcall -noname RunDLL_CallEntry16(long long long str long) #name wrong? + 123 stdcall SHFreeUnusedLibraries () + 124 stdcall FileMenu_AppendFilesForPidl(long ptr long) + 125 stdcall FileMenu_AddFilesForPidl(long long long ptr long long ptr) + 126 stdcall SHOutOfMemoryMessageBox (long long long) + 127 stdcall SHWinHelp (long long long long) + 128 stdcall -private DllGetClassObject(long long ptr) SHELL32_DllGetClassObject + 129 stdcall DAD_AutoScroll(long ptr ptr) + 130 stdcall DAD_DragEnter(long) + 131 stdcall DAD_DragEnterEx(long long long) + 132 stdcall DAD_DragLeave() + 133 stdcall DragQueryFileW(long long ptr long) + 134 stdcall DAD_DragMove(long long) + 135 stdcall DragQueryPoint(long ptr) + 136 stdcall DAD_SetDragImage(long long) + 137 stdcall DAD_ShowDragImage (long) + 139 stub Desktop_UpdateBriefcaseOnEvent + 140 stdcall FileMenu_DeleteItemByIndex(long long) + 141 stdcall FileMenu_DeleteItemByFirstID(long long) + 142 stdcall FileMenu_DeleteSeparator(long) + 143 stdcall FileMenu_EnableItemByCmd(long long long) + 144 stdcall FileMenu_GetItemExtent (long long) + 145 stdcall PathFindOnPath (ptr ptr) PathFindOnPathAW + 146 stdcall RLBuildListOfPaths() + 147 stdcall SHCLSIDFromString(long long) SHCLSIDFromStringAW + 149 stdcall SHFind_InitMenuPopup(long long long long) + + 151 stdcall SHLoadOLE (long) + 152 stdcall ILGetSize(ptr) + 153 stdcall ILGetNext(ptr) + 154 stdcall ILAppend (long long long) + 155 stdcall ILFree (ptr) + 156 stdcall ILGlobalFree (ptr) + 157 stdcall ILCreateFromPath (ptr) ILCreateFromPathAW + 158 stdcall PathGetExtension(str long long) PathGetExtensionAW + 159 stdcall PathIsDirectory(ptr)PathIsDirectoryAW + 160 stub SHNetConnectionDialog + 161 stdcall SHRunControlPanel (long long) + 162 stdcall SHSimpleIDListFromPath (ptr) SHSimpleIDListFromPathAW + 163 stdcall StrToOleStr (wstr str) StrToOleStrAW + 164 stdcall Win32DeleteFile(str) Win32DeleteFileAW + 165 stdcall SHCreateDirectory(long ptr) + 166 stdcall CallCPLEntry16(long long long long long long) + 167 stdcall SHAddFromPropSheetExtArray(long long long) + 168 stdcall SHCreatePropSheetExtArray(long str long) + 169 stdcall SHDestroyPropSheetExtArray(long) + 170 stdcall SHReplaceFromPropSheetExtArray(long long long long) + 171 stdcall PathCleanupSpec(ptr ptr) + 172 stdcall SHCreateLinks(long str ptr long ptr) + 173 stdcall SHValidateUNC(long long long) + 174 stdcall SHCreateShellFolderViewEx (ptr ptr) + 175 stdcall SHGetSpecialFolderPath(long long long long) SHGetSpecialFolderPathAW + 176 stdcall SHSetInstanceExplorer (long) + 177 stub DAD_SetDragImageFromListView + 178 stdcall SHObjectProperties(long long wstr wstr) + 179 stdcall SHGetNewLinkInfoA(str str ptr long long) + 180 stdcall SHGetNewLinkInfoW(wstr wstr ptr long long) + 181 stdcall RegisterShellHook(long long) + 182 varargs ShellMessageBoxW(long long long str long) + 183 varargs ShellMessageBoxA(long long long str long) + 184 stdcall ArrangeWindows(long long long long long) + 185 stub SHHandleDiskFull + 186 stdcall ILGetDisplayNameEx(ptr ptr ptr long) + 187 stub ILGetPseudoNameW + 188 stdcall ShellDDEInit(long) + 189 stdcall ILCreateFromPathA(str) + 190 stdcall ILCreateFromPathW(wstr) + 191 stdcall SHUpdateImageA(str long long long) + 192 stdcall SHUpdateImageW(wstr long long long) + 193 stdcall SHHandleUpdateImage(ptr) + 194 stub SHCreatePropSheetExtArrayEx + 195 stdcall SHFree(ptr) + 196 stdcall SHAlloc(long) + 197 stub SHGlobalDefect + 198 stdcall SHAbortInvokeCommand () + 199 stub SHGetFileIcon + 200 stub SHLocalAlloc + 201 stub SHLocalFree + 202 stub SHLocalReAlloc + 203 stub AddCommasW + 204 stub ShortSizeFormatW + 205 stub Printer_LoadIconsW + 206 stub Link_AddExtraDataSection + 207 stub Link_ReadExtraDataSection + 208 stub Link_RemoveExtraDataSection + 209 stub Int64ToString + 210 stub LargeIntegerToString + 211 stub Printers_GetPidl + 212 stub Printers_AddPrinterPropPages + 213 stub Printers_RegisterWindowW + 214 stub Printers_UnregisterWindow + 215 stdcall SHStartNetConnectionDialog(long str long) + 243 stdcall @(long long) shell32_243 + 244 stdcall SHInitRestricted(ptr ptr) + 247 stdcall SHGetDataFromIDListA (ptr ptr long ptr long) + 248 stdcall SHGetDataFromIDListW (ptr ptr long ptr long) + 249 stdcall PathParseIconLocation (ptr) PathParseIconLocationAW + 250 stdcall PathRemoveExtension (ptr) PathRemoveExtensionAW + 251 stdcall PathRemoveArgs (ptr) PathRemoveArgsAW + 256 stdcall @(ptr ptr) SHELL32_256 + 271 stub SheChangeDirA + 272 stub SheChangeDirExA + 273 stub SheChangeDirExW + 274 stdcall SheChangeDirW(wstr) + 275 stub SheConvertPathW + 276 stub SheFullPathA + 277 stub SheFullPathW + 278 stub SheGetCurDrive + 279 stub SheGetDirA + 280 stub SheGetDirExW + 281 stdcall SheGetDirW (long long) + 282 stub SheGetPathOffsetW + 283 stub SheRemoveQuotesA + 284 stub SheRemoveQuotesW + 285 stub SheSetCurDrive + 286 stub SheShortenPathA + 287 stub SheShortenPathW + 288 stdcall ShellAboutA(long str str long) + 289 stdcall ShellAboutW(long wstr wstr long) + 290 stdcall ShellExecuteA(long str str str str long) + 291 stdcall ShellExecuteEx (long) ShellExecuteExA + 292 stdcall ShellExecuteExA (long) + 293 stdcall ShellExecuteExW (long) + 294 stdcall ShellExecuteW (long wstr wstr wstr wstr long) + 296 stdcall Shell_NotifyIcon(long ptr) Shell_NotifyIconA + 297 stdcall Shell_NotifyIconA(long ptr) + 298 stdcall Shell_NotifyIconW(long ptr) +#299 stub Shl1632_ThunkData32 +#300 stub Shl3216_ThunkData32 + 301 stdcall StrChrA(str long) shlwapi.StrChrA + 302 stdcall StrChrIA(str long) shlwapi.StrChrIA + 303 stdcall StrChrIW(wstr long) shlwapi.StrChrIW + 304 stdcall StrChrW(wstr long) shlwapi.StrChrW + 305 stdcall StrCmpNA(str str long) shlwapi.StrCmpNA + 306 stdcall StrCmpNIA(str str long) shlwapi.StrCmpNIA + 307 stdcall StrCmpNIW(wstr wstr long) shlwapi.StrCmpNIW + 308 stdcall StrCmpNW(wstr wstr long) shlwapi.StrCmpNW + 309 stdcall StrCpyNA (ptr str long) lstrcpynA + 310 stdcall StrCpyNW(wstr wstr long) shlwapi.StrCpyNW + 311 stdcall StrNCmpA(str str long) shlwapi.StrCmpNA + 312 stdcall StrNCmpIA(str str long) shlwapi.StrCmpNIA + 313 stdcall StrNCmpIW(wstr wstr long) shlwapi.StrCmpNIW + 314 stdcall StrNCmpW(wstr wstr long) shlwapi.StrCmpNW + 315 stdcall StrNCpyA (ptr str long) lstrcpynA + 316 stdcall StrNCpyW(wstr wstr long) shlwapi.StrCpyNW + 317 stdcall StrRChrA(str str long) shlwapi.StrRChrA + 318 stdcall StrRChrIA(str str long) shlwapi.StrRChrIA + 319 stdcall StrRChrIW(str str long) shlwapi.StrRChrIW + 320 stdcall StrRChrW(wstr wstr long) shlwapi.StrRChrW + 321 stub StrRStrA + 322 stdcall StrRStrIA(str str str) shlwapi.StrRStrIA + 323 stdcall StrRStrIW(wstr wstr wstr) shlwapi.StrRStrIW + 324 stub StrRStrW + 325 stdcall StrStrA(str str) shlwapi.StrStrA + 326 stdcall StrStrIA(str str) shlwapi.StrStrIA + 327 stdcall StrStrIW(wstr wstr) shlwapi.StrStrIW + 328 stdcall StrStrW(wstr wstr) shlwapi.StrStrW + + 505 stdcall SHRegCloseKey (long) + 506 stdcall SHRegOpenKeyA (long str long) + 507 stdcall SHRegOpenKeyW (long wstr long) + 508 stub SHRegQueryValueA + 509 stdcall SHRegQueryValueExA(long str ptr ptr ptr ptr) + 510 stdcall SHRegQueryValueW (long long long long) + 511 stdcall SHRegQueryValueExW (long wstr ptr ptr ptr ptr) + 512 stdcall SHRegDeleteKeyW (long wstr) + + 520 stdcall -noname SHAllocShared (ptr long long) + 521 stdcall -noname SHLockShared (long long) + 522 stdcall -noname SHUnlockShared (ptr) + 523 stdcall -noname SHFreeShared (long long) + 524 stdcall RealDriveType (long long) + 525 stub RealDriveTypeFlags + + 640 stdcall NTSHChangeNotifyRegister (long long long long long long) + 641 stdcall NTSHChangeNotifyDeregister (long) + + 643 stub SHChangeNotifyReceive + 644 stdcall SHChangeNotification_Lock(long long ptr ptr) + 645 stdcall SHChangeNotification_Unlock(long) + 646 stub SHChangeRegistrationReceive + 647 stub ReceiveAddToRecentDocs + 648 stub SHWaitOp_Operate + + 650 stdcall PathIsSameRoot(ptr ptr)PathIsSameRootAW + +# nt40/win98 + 651 stdcall ReadCabinetState (long long) # OldReadCabinetState + 652 stdcall WriteCabinetState (long) + 653 stdcall PathProcessCommand (long long long long) PathProcessCommandAW + +# win98 + 654 stdcall @(long long)shell32_654 # ReadCabinetState@8 + 660 stdcall FileIconInit(long) + 680 stdcall IsUserAdmin() + +# >= NT5 + 714 stdcall @(ptr)SHELL32_714 # PathIsTemporaryW + 730 stdcall RestartDialogEx(long wstr long long) + +1217 stub FOOBAR1217 # no joke! This is the real name!! + +# +# version 4.0 (win95) +# _WIN32_IE >= 0x0200 +# +@ stdcall CheckEscapesA(str long) +@ stdcall CheckEscapesW(wstr long) +@ stdcall CommandLineToArgvW(wstr ptr) +@ stdcall Control_FillCache_RunDLL(long long long long) Control_FillCache_RunDLLA +@ stdcall Control_FillCache_RunDLLA(long long long long) +@ stdcall Control_FillCache_RunDLLW(long long long long) +@ stdcall Control_RunDLL(ptr ptr str long) Control_RunDLLA +@ stdcall Control_RunDLLA(ptr ptr str long) +@ stdcall Control_RunDLLW(ptr ptr wstr long) +@ stdcall -private DllCanUnloadNow() SHELL32_DllCanUnloadNow +@ stdcall DllInstall(long wstr)SHELL32_DllInstall +@ stdcall -private DllRegisterServer() SHELL32_DllRegisterServer +@ stdcall -private DllUnregisterServer() SHELL32_DllUnregisterServer +@ stdcall DoEnvironmentSubstA(str str) +@ stdcall DoEnvironmentSubstW(wstr wstr) +@ stub DragQueryFileAorW +@ stdcall DuplicateIcon(long long) +@ stdcall ExtractAssociatedIconA(long str ptr) +@ stdcall ExtractAssociatedIconExA(long str long long) +@ stdcall ExtractAssociatedIconExW(long wstr long long) +@ stdcall ExtractAssociatedIconW(long wstr ptr) +@ stdcall ExtractIconA(long str long) +@ stdcall ExtractIconEx(ptr long ptr ptr long) ExtractIconExA +@ stdcall ExtractIconExA(str long ptr ptr long) +@ stdcall ExtractIconExW(wstr long ptr ptr long) +@ stdcall ExtractIconW(long wstr long) +@ stub ExtractIconResInfoA +@ stub ExtractIconResInfoW +@ stub ExtractVersionResource16W +@ stub FindExeDlgProc +@ stdcall FindExecutableA(ptr ptr ptr) +@ stdcall FindExecutableW(wstr wstr wstr) +@ stdcall FreeIconList(long) +@ stub InternalExtractIconListA +@ stub InternalExtractIconListW +@ stub OpenAs_RunDLL +@ stub OpenAs_RunDLLA +@ stub OpenAs_RunDLLW +@ stub PrintersGetCommand_RunDLL +@ stub PrintersGetCommand_RunDLLA +@ stub PrintersGetCommand_RunDLLW +@ stub RealShellExecuteA +@ stub RealShellExecuteExA +@ stub RealShellExecuteExW +@ stub RealShellExecuteW +@ stub RegenerateUserEnvironment +@ stdcall SHAddToRecentDocs (long ptr) +@ stdcall SHAppBarMessage(long ptr) +@ stdcall SHBrowseForFolder(ptr) SHBrowseForFolderA +@ stdcall SHBrowseForFolderA(ptr) +@ stdcall SHBrowseForFolderW(ptr) +@ stdcall SHChangeNotify (long long ptr ptr) +@ stdcall SHCreateDirectoryExA(long str ptr) +@ stdcall SHCreateDirectoryExW(long wstr ptr) +@ stub ShellHookProc +@ stdcall SHEmptyRecycleBinA(long str long) +@ stdcall SHEmptyRecycleBinW(long wstr long) +@ stdcall SHFileOperation(ptr) SHFileOperationA +@ stdcall SHFileOperationA(ptr) +@ stdcall SHFileOperationW(ptr) +@ stdcall SHFormatDrive(long long long long) +@ stdcall SHFreeNameMappings(ptr) +@ stdcall SHGetDesktopFolder(ptr) +@ stdcall SHGetFileInfo(ptr long ptr long long) SHGetFileInfoA +@ stdcall SHGetFileInfoA(ptr long ptr long long) +@ stdcall SHGetFileInfoW(ptr long ptr long long) +@ stdcall SHGetInstanceExplorer(long) +@ stdcall SHGetMalloc(ptr) +@ stdcall SHGetNewLinkInfo(str str ptr long long) SHGetNewLinkInfoA +@ stdcall SHGetPathFromIDList(ptr ptr) SHGetPathFromIDListA +@ stdcall SHGetPathFromIDListA(ptr ptr) +@ stdcall SHGetPathFromIDListW(ptr ptr) +@ stdcall SHGetSettings(ptr long) +@ stdcall SHGetSpecialFolderLocation(long long ptr) +@ stdcall SHHelpShortcuts_RunDLL(long long long long) +@ stub SHHelpShortcuts_RunDLLA +@ stub SHHelpShortcuts_RunDLLW +@ stdcall SHLoadInProc(long) +@ stdcall SHQueryRecycleBinA(str ptr) +@ stdcall SHQueryRecycleBinW(wstr ptr) +@ stub SHUpdateRecycleBinIcon +@ stub WOWShellExecute + +# +# version 4.70 (IE3.0) +# _WIN32_IE >= 0x0300 +# + +# +# version 4.71 (IE4.0) +# _WIN32_IE >= 0x0400 +# +@ stdcall DllGetVersion(ptr)SHELL32_DllGetVersion +@ stub SHGetFreeDiskSpace +@ stdcall SHGetSpecialFolderPathA(long ptr long long) +@ stdcall SHGetSpecialFolderPathW(long ptr long long) +# +# version 4.72 (IE4.01) +# _WIN32_IE >= 0x0401 +# no new exports +# + +# +# version 5.00 (Win2K) +# _WIN32_IE >= 0x0500 +# +@ stdcall SHBindToParent(ptr ptr ptr ptr) +@ stdcall SHGetDiskFreeSpaceA(str ptr ptr ptr) kernel32.GetDiskFreeSpaceExA +@ stdcall SHGetDiskFreeSpaceExA(str ptr ptr ptr) kernel32.GetDiskFreeSpaceExA +@ stdcall SHGetDiskFreeSpaceExW(wstr ptr ptr ptr) kernel32.GetDiskFreeSpaceExW +@ stdcall SHGetFolderPathA(long long long long ptr) +@ stdcall SHGetFolderPathW(long long long long ptr) +@ stdcall SHGetFolderLocation(long long long long ptr) + +# version 6.0 (WinXP) +# _WIN32_IE >= 0x600 +@ stdcall SHDefExtractIconA(str long long ptr ptr long) +@ stdcall SHDefExtractIconW(wstr long long ptr ptr long) diff --git a/reactos/lib/shell32/shell32_Ca.rc b/reactos/lib/shell32/shell32_Ca.rc index fd2052766ba..05c172c6b5f 100644 --- a/reactos/lib/shell32/shell32_Ca.rc +++ b/reactos/lib/shell32/shell32_Ca.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CATALAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Quant a %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "D'Acord", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS ha estat construit per:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_CATALAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Quant a %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "D'Acord", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS ha estat construit per:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Cn.rc b/reactos/lib/shell32/shell32_Cn.rc index edc6be42ade..a305b79a83a 100644 --- a/reactos/lib/shell32/shell32_Cn.rc +++ b/reactos/lib/shell32/shell32_Cn.rc @@ -1,63 +1,63 @@ -/* - * Copyright 2002 Tisheng Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -#pragma code_page(936) - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "¹ØÓÚ %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "È·¶¨", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "ÊäÈë³ÌÐò£¬Ä¿Â¼£¬Îļþ»òÕßInternet×ÊÔ´Ãû£¬ReactOS½«ÎªÄú´ò¿ªËü¡£", 12289, 36, 11, 182, 18 - LTEXT "´ò¿ª(&O):", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "È·¶¨", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "È¡Ïû", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "ä¯ÀÀ(&B)...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* columns in the shellview */ -STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -BEGIN - IDS_SHV_COLUMN1 "Îļþ" - IDS_SHV_COLUMN2 "´óС" - IDS_SHV_COLUMN3 "ÀàÐÍ" - IDS_SHV_COLUMN4 "ÐÞ¸Ä" - IDS_SHV_COLUMN5 "ÊôÐÔ" - IDS_SHV_COLUMN6 "ʹÓÿռä" - IDS_SHV_COLUMN7 "Ê£Óà¿Õ¼ä" - IDS_SHV_COLUMN8 "Name" /*FIXME*/ - IDS_SHV_COLUMN9 "Comments" /*FIXME*/ -END - -#pragma code_page(default) +/* + * Copyright 2002 Tisheng Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +#pragma code_page(936) + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "¹ØÓÚ %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "È·¶¨", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "ÊäÈë³ÌÐò£¬Ä¿Â¼£¬Îļþ»òÕßInternet×ÊÔ´Ãû£¬ReactOS½«ÎªÄú´ò¿ªËü¡£", 12289, 36, 11, 182, 18 + LTEXT "´ò¿ª(&O):", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "È·¶¨", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "È¡Ïû", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "ä¯ÀÀ(&B)...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* columns in the shellview */ +STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +BEGIN + IDS_SHV_COLUMN1 "Îļþ" + IDS_SHV_COLUMN2 "´óС" + IDS_SHV_COLUMN3 "ÀàÐÍ" + IDS_SHV_COLUMN4 "ÐÞ¸Ä" + IDS_SHV_COLUMN5 "ÊôÐÔ" + IDS_SHV_COLUMN6 "ʹÓÿռä" + IDS_SHV_COLUMN7 "Ê£Óà¿Õ¼ä" + IDS_SHV_COLUMN8 "Name" /*FIXME*/ + IDS_SHV_COLUMN9 "Comments" /*FIXME*/ +END + +#pragma code_page(default) diff --git a/reactos/lib/shell32/shell32_Cs.rc b/reactos/lib/shell32/shell32_Cs.rc index 94313e85f0b..a45cab3ce70 100644 --- a/reactos/lib/shell32/shell32_Cs.rc +++ b/reactos/lib/shell32/shell32_Cs.rc @@ -1,181 +1,181 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2003 Filip Navara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Vedle sebe", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ikony", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Seznam", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Podrobnosti", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "Z&obrazit" - BEGIN - MENUITEM "&Vedle sebe", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ikony", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Seznam", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Podrobnosti", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Seøadit &ikony" - BEGIN - MENUITEM "Podle &Názvu", 0x30 /* column 0 */ - MENUITEM "Podle &Typu", 0x32 /* column 2 */ - MENUITEM "Podle &Velikosti", 0x31 /* ... */ - MENUITEM "Podle &Data", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Rovnat automaticky", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Zarovnat ikony", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "A&ktualizovat", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "V&ložit", FCIDM_SHVIEW_INSERT - MENUITEM "Vložit zást&upce", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "&Nový" - BEGIN - MENUITEM "Nová &složka", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Nový &zástupce", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "&Vlastnosti", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "P&rozkoumat", FCIDM_SHVIEW_EXPLORE - MENUITEM "O&tevøít", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "Vyj&mout", FCIDM_SHVIEW_CUT - MENUITEM "&Kopírovat", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Vytvoøit zástupc&e", FCIDM_SHVIEW_CREATELINK - MENUITEM "O&dstranit", FCIDM_SHVIEW_DELETE - MENUITEM "&Pøejmenovat", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Vlastnosti", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Procházet..." -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Storno", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "O aplikaci %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS je d¡lem:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Zadejte název programu, složky, dokumentu, nebo zdroje v síti Internet a ReactOS jej pro vás otevøe.", 12289, 36, 11, 182, 18 - LTEXT "&Otevøít:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Storno", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Procházet...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Plocha" - IDS_MYCOMPUTER "Tento poèítaè" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Vedle sebe" - IDS_VIEW_SMALL "&Ikony" - IDS_VIEW_LIST "&Seznam" - IDS_VIEW_DETAILS "&Podrobnosti" - IDS_SELECT "Vybrat" - IDS_OPEN "Otevøít" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Nelze vytvoøit novou složku protože pøistup byl odepøen." - IDS_CREATEFOLDER_CAPTION "Chyba pøi pokusu vytvoøit nový adresáø" - IDS_DELETEITEM_CAPTION "Potvrdit odstranìní souboru" - IDS_DELETEFOLDER_CAPTION "Potvrdit odstranìní adresáøe" - IDS_OVERWRITEFILE_CAPTION "Potvrdit pøepsání souboru" - IDS_DELETEITEM_TEXT "Opravdu chcete odstranit '%1'?" - IDS_DELETEMULTIPLE_TEXT "Opravdu chcete odstranit tìchto %1 položek?" - IDS_OVERWRITEFILE_TEXT "Pøejete si pøepsat soubor '%1'?" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Název" - IDS_SHV_COLUMN2 "Velikost" - IDS_SHV_COLUMN3 "Typ" - IDS_SHV_COLUMN4 "Zmìnìno" - IDS_SHV_COLUMN5 "Atributy" - IDS_SHV_COLUMN6 "Velikost" - IDS_SHV_COLUMN7 "Volné místo" - IDS_SHV_COLUMN8 "Jméno" - IDS_SHV_COLUMN9 "Komentáø" -END +/* + * Copyright 1998 Juergen Schmied + * Copyright 2003 Filip Navara + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Vedle sebe", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ikony", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Seznam", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Podrobnosti", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "Z&obrazit" + BEGIN + MENUITEM "&Vedle sebe", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ikony", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Seznam", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Podrobnosti", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Seøadit &ikony" + BEGIN + MENUITEM "Podle &Názvu", 0x30 /* column 0 */ + MENUITEM "Podle &Typu", 0x32 /* column 2 */ + MENUITEM "Podle &Velikosti", 0x31 /* ... */ + MENUITEM "Podle &Data", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Rovnat automaticky", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Zarovnat ikony", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "A&ktualizovat", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "V&ložit", FCIDM_SHVIEW_INSERT + MENUITEM "Vložit zást&upce", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "&Nový" + BEGIN + MENUITEM "Nová &složka", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Nový &zástupce", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "&Vlastnosti", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "P&rozkoumat", FCIDM_SHVIEW_EXPLORE + MENUITEM "O&tevøít", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "Vyj&mout", FCIDM_SHVIEW_CUT + MENUITEM "&Kopírovat", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Vytvoøit zástupc&e", FCIDM_SHVIEW_CREATELINK + MENUITEM "O&dstranit", FCIDM_SHVIEW_DELETE + MENUITEM "&Pøejmenovat", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Vlastnosti", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Procházet..." +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Storno", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "O aplikaci %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS je d¡lem:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Zadejte název programu, složky, dokumentu, nebo zdroje v síti Internet a ReactOS jej pro vás otevøe.", 12289, 36, 11, 182, 18 + LTEXT "&Otevøít:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Storno", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Procházet...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Plocha" + IDS_MYCOMPUTER "Tento poèítaè" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Vedle sebe" + IDS_VIEW_SMALL "&Ikony" + IDS_VIEW_LIST "&Seznam" + IDS_VIEW_DETAILS "&Podrobnosti" + IDS_SELECT "Vybrat" + IDS_OPEN "Otevøít" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Nelze vytvoøit novou složku protože pøistup byl odepøen." + IDS_CREATEFOLDER_CAPTION "Chyba pøi pokusu vytvoøit nový adresáø" + IDS_DELETEITEM_CAPTION "Potvrdit odstranìní souboru" + IDS_DELETEFOLDER_CAPTION "Potvrdit odstranìní adresáøe" + IDS_OVERWRITEFILE_CAPTION "Potvrdit pøepsání souboru" + IDS_DELETEITEM_TEXT "Opravdu chcete odstranit '%1'?" + IDS_DELETEMULTIPLE_TEXT "Opravdu chcete odstranit tìchto %1 položek?" + IDS_OVERWRITEFILE_TEXT "Pøejete si pøepsat soubor '%1'?" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Název" + IDS_SHV_COLUMN2 "Velikost" + IDS_SHV_COLUMN3 "Typ" + IDS_SHV_COLUMN4 "Zmìnìno" + IDS_SHV_COLUMN5 "Atributy" + IDS_SHV_COLUMN6 "Velikost" + IDS_SHV_COLUMN7 "Volné místo" + IDS_SHV_COLUMN8 "Jméno" + IDS_SHV_COLUMN9 "Komentáø" +END diff --git a/reactos/lib/shell32/shell32_Da.rc b/reactos/lib/shell32/shell32_Da.rc index aab26ff23c6..270cd1294cd 100644 --- a/reactos/lib/shell32/shell32_Da.rc +++ b/reactos/lib/shell32/shell32_Da.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_DANISH, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Om %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS havde ikke været mulig uden hjælp fra disse personer:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_DANISH, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Om %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS havde ikke været mulig uden hjælp fra disse personer:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_De.rc b/reactos/lib/shell32/shell32_De.rc index f544ddcff6e..0084189fc08 100644 --- a/reactos/lib/shell32/shell32_De.rc +++ b/reactos/lib/shell32/shell32_De.rc @@ -1,190 +1,190 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2004 Henning Gerhardt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Große Symbole", FCIDM_SHVIEW_BIGICON - MENUITEM "&Kleine Symbole", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Ansicht" - BEGIN - MENUITEM "&Große Symbole", FCIDM_SHVIEW_BIGICON - MENUITEM "&Kleine Symbole", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Symbole anordnen" - BEGIN - MENUITEM "Nach &Name", 0x30 /* column 0 */ - MENUITEM "Nach &Typ", 0x32 /* column 2 */ - MENUITEM "Nach &Größe", 0x31 /* ... */ - MENUITEM "Nach &Datum", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Automatisch anordnen", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Line up Icons", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Aktualisieren", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Einfügen", FCIDM_SHVIEW_INSERT - MENUITEM "Einfügen als Verweis", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Neu" - BEGIN - MENUITEM "Neues Ver&zeichnis", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Neuer Ver&weis", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "&Eigenschaften", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "E&rkunden", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Öffnen", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "&Ausschneiden", FCIDM_SHVIEW_CUT - MENUITEM "&Kopieren", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Erstelle Ver&weis", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Löschen", FCIDM_SHVIEW_DELETE - MENUITEM "&Umbenennen", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Eigenschaften", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Nach Verzeichnis durchsuchen" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Abbrechen", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Informationen über %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS wurde Ihnen zur Verfügung gestellt von:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Den Namen eines Programmes, eines Ordners, eines Dokumentes oder einer Internet Ressource eingeben, und ReactOS wird es für Sie öffnen", 12289, 36, 11, 182, 18 - LTEXT "&Öffnen:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Abbrechen", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Durchsuchen...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Desktop" - IDS_MYCOMPUTER "Arbeitsplatz" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Große Symbole" - IDS_VIEW_SMALL "&Kleine Symbole" - IDS_VIEW_LIST "&Liste" - IDS_VIEW_DETAILS "&Details" - IDS_SELECT "Auswählen" - IDS_OPEN "Öffnen" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert." - IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf" - IDS_DELETEITEM_CAPTION "Bestätigung: Datei löschen" - IDS_DELETEFOLDER_CAPTION "Bestätigung: Verzeichnis löschen" - IDS_DELETEITEM_TEXT "Sind Sie sich sicher, dass Sie die Datei '%1' löschen möchten ?" - IDS_DELETEMULTIPLE_TEXT "Sind Sie sich sicher, dass Sie diese %1 Dateien löschen möchten ?" - IDS_OVERWRITEFILE_TEXT "Möchten Sie, dass die Datei '%1' überschrieben wird ?" - IDS_OVERWRITEFILE_CAPTION "Bestätigung: Datei überschreiben" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Datei" - IDS_SHV_COLUMN2 "Größe" - IDS_SHV_COLUMN3 "Typ" - IDS_SHV_COLUMN4 "Geändert" - IDS_SHV_COLUMN5 "Attribute" - IDS_SHV_COLUMN6 "Gesamtgröße" - IDS_SHV_COLUMN7 "Freier Speicher" - IDS_SHV_COLUMN8 "Name" - IDS_SHV_COLUMN9 "Kommentar" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Neustarten" - IDS_RESTART_PROMPT "Möchten Sie, dass ein simulierter Windows Neustart durchgeführt wird ?" - IDS_SHUTDOWN_TITLE "Anhalten" - IDS_SHUTDOWN_PROMPT "Möchten Sie die aktuelle ReactOS Sitzung beenden ?" -} +/* + * Copyright 1998 Juergen Schmied + * Copyright 2004 Henning Gerhardt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Große Symbole", FCIDM_SHVIEW_BIGICON + MENUITEM "&Kleine Symbole", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Ansicht" + BEGIN + MENUITEM "&Große Symbole", FCIDM_SHVIEW_BIGICON + MENUITEM "&Kleine Symbole", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Symbole anordnen" + BEGIN + MENUITEM "Nach &Name", 0x30 /* column 0 */ + MENUITEM "Nach &Typ", 0x32 /* column 2 */ + MENUITEM "Nach &Größe", 0x31 /* ... */ + MENUITEM "Nach &Datum", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Automatisch anordnen", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Icons anordnen", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Aktualisieren", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Einfügen", FCIDM_SHVIEW_INSERT + MENUITEM "Einfügen als Verweis", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Neu" + BEGIN + MENUITEM "Neues Ver&zeichnis", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Neuer Ver&weis", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "&Eigenschaften", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "E&rkunden", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Öffnen", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "&Ausschneiden", FCIDM_SHVIEW_CUT + MENUITEM "&Kopieren", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Erstelle Ver&weis", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Löschen", FCIDM_SHVIEW_DELETE + MENUITEM "&Umbenennen", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Eigenschaften", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Nach Verzeichnis durchsuchen" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Abbrechen", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Informationen über %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS wurde Ihnen zur Verfügung gestellt von:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Den Namen eines Programmes, eines Ordners, eines Dokumentes oder einer Internet Ressource eingeben, und ReactOS wird es für Sie öffnen", 12289, 36, 11, 182, 18 + LTEXT "&Öffnen:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Abbrechen", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Durchsuchen...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Desktop" + IDS_MYCOMPUTER "Arbeitsplatz" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Große Symbole" + IDS_VIEW_SMALL "&Kleine Symbole" + IDS_VIEW_LIST "&Liste" + IDS_VIEW_DETAILS "&Details" + IDS_SELECT "Auswählen" + IDS_OPEN "Öffnen" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Es konnte kein neues Verzeichnis erstellt werden: Zugriff verweigert." + IDS_CREATEFOLDER_CAPTION "Es trat ein Fehler beim Erstellen eines neuen Verzeichnisses auf" + IDS_DELETEITEM_CAPTION "Bestätigung: Datei löschen" + IDS_DELETEFOLDER_CAPTION "Bestätigung: Verzeichnis löschen" + IDS_DELETEITEM_TEXT "Sind Sie sich sicher, dass Sie die Datei '%1' löschen möchten ?" + IDS_DELETEMULTIPLE_TEXT "Sind Sie sich sicher, dass Sie diese %1 Dateien löschen möchten ?" + IDS_OVERWRITEFILE_TEXT "Möchten Sie, dass die Datei '%1' überschrieben wird ?" + IDS_OVERWRITEFILE_CAPTION "Bestätigung: Datei überschreiben" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Datei" + IDS_SHV_COLUMN2 "Größe" + IDS_SHV_COLUMN3 "Typ" + IDS_SHV_COLUMN4 "Geändert" + IDS_SHV_COLUMN5 "Attribute" + IDS_SHV_COLUMN6 "Gesamtgröße" + IDS_SHV_COLUMN7 "Freier Speicher" + IDS_SHV_COLUMN8 "Name" + IDS_SHV_COLUMN9 "Kommentar" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Neustarten" + IDS_RESTART_PROMPT "Möchten Sie, dass ein simulierter Windows Neustart durchgeführt wird ?" + IDS_SHUTDOWN_TITLE "Anhalten" + IDS_SHUTDOWN_PROMPT "Möchten Sie die aktuelle ReactOS Sitzung beenden ?" +} diff --git a/reactos/lib/shell32/shell32_En.rc b/reactos/lib/shell32/shell32_En.rc index a4a5cd06e4e..8a21d1259f4 100644 --- a/reactos/lib/shell32/shell32_En.rc +++ b/reactos/lib/shell32/shell32_En.rc @@ -1,221 +1,221 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "Lar&ge Icons", FCIDM_SHVIEW_BIGICON - MENUITEM "S&mall Icons", FCIDM_SHVIEW_SMALLICON - MENUITEM "&List", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&View" - BEGIN - MENUITEM "Lar&ge Icons", FCIDM_SHVIEW_BIGICON - MENUITEM "S&mall Icons", FCIDM_SHVIEW_SMALLICON - MENUITEM "&List", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Arrange &Icons" - BEGIN - MENUITEM "By &Name", 0x30 /* column 0 */ - MENUITEM "By &Type", 0x32 /* column 2 */ - MENUITEM "By &Size", 0x31 /* ... */ - MENUITEM "By &Date", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Auto Arrange", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Line up Icons", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Refresh", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Paste", FCIDM_SHVIEW_INSERT - MENUITEM "Paste as Link", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "New" - BEGIN - MENUITEM "New &Folder", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "New &Link", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Properties", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "E&xplore", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Open", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "C&ut", FCIDM_SHVIEW_CUT - MENUITEM "&Copy", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Create &Link", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Delete", FCIDM_SHVIEW_DELETE - MENUITEM "&Rename", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Properties", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Browse for Folder" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancel", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "About %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Desktop" - IDS_MYCOMPUTER "My Computer" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "Lar&ge Icons" - IDS_VIEW_SMALL "S&mall Icons" - IDS_VIEW_LIST "&List" - IDS_VIEW_DETAILS "&Details" - IDS_SELECT "Select" - IDS_OPEN "Open" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Can not create new Folder: Permission denied." - IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" - IDS_DELETEITEM_CAPTION "Confirm file delete" - IDS_DELETEFOLDER_CAPTION "Confirm folder delete" - IDS_DELETEITEM_TEXT "Are you sure you want to delete '%1'?" - IDS_DELETEMULTIPLE_TEXT "Are you sure you want to delete these %1 items?" - IDS_OVERWRITEFILE_TEXT "OverWrite File %1?" - IDS_OVERWRITEFILE_CAPTION "Confirm File OverWrite" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "File" - IDS_SHV_COLUMN2 "Size" - IDS_SHV_COLUMN3 "Type" - IDS_SHV_COLUMN4 "Modified" - IDS_SHV_COLUMN5 "Attributes" - IDS_SHV_COLUMN6 "Size" - IDS_SHV_COLUMN7 "Size available" - IDS_SHV_COLUMN8 "Name" - IDS_SHV_COLUMN9 "Comments" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Restart" - IDS_RESTART_PROMPT "Do you want to restart the system?" - IDS_SHUTDOWN_TITLE "Shutdown" - IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" -} - -/* shell folder path default values */ -STRINGTABLE DISCARDABLE -{ - IDS_PROGRAMS "Start Menu\\Programs" - IDS_PERSONAL "My Documents" - IDS_FAVORITES "Favorites" - IDS_STARTUP "Start Menu\\Programs\\StartUp" - IDS_RECENT "Recent" - IDS_SENDTO "SendTo" - IDS_STARTMENU "Start Menu" - IDS_MYMUSIC "My Documents\\My Music" - IDS_MYVIDEO "My Documents\\My Video" - IDS_DESKTOPDIRECTORY "Desktop" - IDS_NETHOOD "NetHood" - IDS_TEMPLATES "Templates" - IDS_APPDATA "Application Data" - IDS_PRINTHOOD "PrintHood" - IDS_LOCAL_APPDATA "Local Settings\\Application Data" - IDS_INTERNET_CACHE "Temporary Internet Files" - IDS_COOKIES "Cookies" - IDS_HISTORY "History" - IDS_PROGRAM_FILES "Program Files" - IDS_MYPICTURES "My Documents\\My Pictures" - IDS_PROGRAM_FILES_COMMON "Program Files\\Common Files" - IDS_COMMON_DOCUMENTS "Documents" - IDS_ADMINTOOLS "Start Menu\\Programs\\Administrative Tools" - IDS_COMMON_MUSIC "Documents\\My Music" - IDS_COMMON_PICTURES "Documents\\My Pictures" - IDS_COMMON_VIDEO "Documents\\My Video" - IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Burning" -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "Lar&ge Icons", FCIDM_SHVIEW_BIGICON + MENUITEM "S&mall Icons", FCIDM_SHVIEW_SMALLICON + MENUITEM "&List", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&View" + BEGIN + MENUITEM "Lar&ge Icons", FCIDM_SHVIEW_BIGICON + MENUITEM "S&mall Icons", FCIDM_SHVIEW_SMALLICON + MENUITEM "&List", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Details", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Arrange &Icons" + BEGIN + MENUITEM "By &Name", 0x30 /* column 0 */ + MENUITEM "By &Type", 0x32 /* column 2 */ + MENUITEM "By &Size", 0x31 /* ... */ + MENUITEM "By &Date", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Auto Arrange", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Line up Icons", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Refresh", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Paste", FCIDM_SHVIEW_INSERT + MENUITEM "Paste as Link", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "New" + BEGIN + MENUITEM "New &Folder", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "New &Link", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Properties", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "E&xplore", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Open", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "C&ut", FCIDM_SHVIEW_CUT + MENUITEM "&Copy", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Create &Link", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Delete", FCIDM_SHVIEW_DELETE + MENUITEM "&Rename", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Properties", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Browse for Folder" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancel", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Desktop" + IDS_MYCOMPUTER "My Computer" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "Lar&ge Icons" + IDS_VIEW_SMALL "S&mall Icons" + IDS_VIEW_LIST "&List" + IDS_VIEW_DETAILS "&Details" + IDS_SELECT "Select" + IDS_OPEN "Open" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Can not create new Folder: Permission denied." + IDS_CREATEFOLDER_CAPTION "Error during creation of a new folder" + IDS_DELETEITEM_CAPTION "Confirm file delete" + IDS_DELETEFOLDER_CAPTION "Confirm folder delete" + IDS_DELETEITEM_TEXT "Are you sure you want to delete '%1'?" + IDS_DELETEMULTIPLE_TEXT "Are you sure you want to delete these %1 items?" + IDS_OVERWRITEFILE_TEXT "OverWrite File %1?" + IDS_OVERWRITEFILE_CAPTION "Confirm File OverWrite" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "File" + IDS_SHV_COLUMN2 "Size" + IDS_SHV_COLUMN3 "Type" + IDS_SHV_COLUMN4 "Modified" + IDS_SHV_COLUMN5 "Attributes" + IDS_SHV_COLUMN6 "Size" + IDS_SHV_COLUMN7 "Size available" + IDS_SHV_COLUMN8 "Name" + IDS_SHV_COLUMN9 "Comments" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Restart" + IDS_RESTART_PROMPT "Do you want to restart the system?" + IDS_SHUTDOWN_TITLE "Shutdown" + IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" +} + +/* shell folder path default values */ +STRINGTABLE DISCARDABLE +{ + IDS_PROGRAMS "Start Menu\\Programs" + IDS_PERSONAL "My Documents" + IDS_FAVORITES "Favorites" + IDS_STARTUP "Start Menu\\Programs\\StartUp" + IDS_RECENT "Recent" + IDS_SENDTO "SendTo" + IDS_STARTMENU "Start Menu" + IDS_MYMUSIC "My Documents\\My Music" + IDS_MYVIDEO "My Documents\\My Video" + IDS_DESKTOPDIRECTORY "Desktop" + IDS_NETHOOD "NetHood" + IDS_TEMPLATES "Templates" + IDS_APPDATA "Application Data" + IDS_PRINTHOOD "PrintHood" + IDS_LOCAL_APPDATA "Local Settings\\Application Data" + IDS_INTERNET_CACHE "Temporary Internet Files" + IDS_COOKIES "Cookies" + IDS_HISTORY "History" + IDS_PROGRAM_FILES "Program Files" + IDS_MYPICTURES "My Documents\\My Pictures" + IDS_PROGRAM_FILES_COMMON "Program Files\\Common Files" + IDS_COMMON_DOCUMENTS "Documents" + IDS_ADMINTOOLS "Start Menu\\Programs\\Administrative Tools" + IDS_COMMON_MUSIC "Documents\\My Music" + IDS_COMMON_PICTURES "Documents\\My Pictures" + IDS_COMMON_VIDEO "Documents\\My Video" + IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Burning" +} diff --git a/reactos/lib/shell32/shell32_Eo.rc b/reactos/lib/shell32/shell32_Eo.rc index ce4517770fa..7aa142477c8 100644 --- a/reactos/lib/shell32/shell32_Eo.rc +++ b/reactos/lib/shell32/shell32_Eo.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Pri %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "Enorde", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Pri %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "Enorde", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Es.rc b/reactos/lib/shell32/shell32_Es.rc index 6a89f694378..ec7bd2d9cf7 100644 --- a/reactos/lib/shell32/shell32_Es.rc +++ b/reactos/lib/shell32/shell32_Es.rc @@ -1,190 +1,222 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2003,2004 José Manuel Ferrer Ortiz - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "Iconos &grandes", FCIDM_SHVIEW_BIGICON - MENUITEM "Iconos &pequeños", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Detalles", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Ver" - BEGIN - MENUITEM "Iconos &grandes", FCIDM_SHVIEW_BIGICON - MENUITEM "Iconos &pequeños", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Detalles", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Ordenar &iconos" - BEGIN - MENUITEM "Por &nombre", 0x30 /* column 0 */ - MENUITEM "Por &tipo", 0x32 /* column 2 */ - MENUITEM "Por t&amaño", 0x31 /* ... */ - MENUITEM "Por &fecha", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Ordenar automáticamente", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Alinear iconos", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Actualizar", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Pegar", FCIDM_SHVIEW_INSERT - MENUITEM "Pegar acceso directo", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Nuevo" - BEGIN - MENUITEM "Nueva &carpeta", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Nuevo &acceso directo", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Propiedades", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "E&xplorar", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Abrir", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "C&ortar", FCIDM_SHVIEW_CUT - MENUITEM "&Copiar", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "C&rear acceso directo", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Eliminar", FCIDM_SHVIEW_DELETE - MENUITEM "Re&nombrar", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Propiedades", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Explorar carpeta" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "Aceptar", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancelar", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Acerca de %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "Aceptar", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS está disponible gracias a:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Introduzca el nombre de un programa, carpeta, documento o recurso de Internet, y ReactOS lo abrirá para usted.", 12289, 36, 11, 182, 18 - LTEXT "&Abrir:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "Aceptar", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancelar", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Examinar...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Escritorio" - IDS_MYCOMPUTER "Mi PC" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "Iconos &grandes" - IDS_VIEW_SMALL "Iconos &pequeños" - IDS_VIEW_LIST "&Lista" - IDS_VIEW_DETAILS "&Detalles" - IDS_SELECT "Seleccionar" - IDS_OPEN "Abrir" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "No se puede crear nueva carpeta: Permiso denegado." - IDS_CREATEFOLDER_CAPTION "Error durante la creación de una nueva carpeta" - IDS_DELETEITEM_CAPTION "Confirmar eliminación de archivo" - IDS_DELETEFOLDER_CAPTION "Confirmar eliminación de carpeta" - IDS_DELETEITEM_TEXT "¿Seguro que desea eliminar '%1'?" - IDS_DELETEMULTIPLE_TEXT "¿Seguro que desea eliminar estos %1 elementos?" - IDS_OVERWRITEFILE_TEXT "¿Sobreescribir el archivo '%1'?" - IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescritura de archivo" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Archivo" - IDS_SHV_COLUMN2 "Tamaño" - IDS_SHV_COLUMN3 "Tipo" - IDS_SHV_COLUMN4 "Modificado" - IDS_SHV_COLUMN5 "Atributos" - IDS_SHV_COLUMN6 "Tamaño" - IDS_SHV_COLUMN7 "Tamaño disponible" - IDS_SHV_COLUMN8 "Nombre" - IDS_SHV_COLUMN9 "Comentarios" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Reiniciar" - IDS_RESTART_PROMPT "¿Desea simular un reinicio de Windows?" - IDS_SHUTDOWN_TITLE "Apagar" - IDS_SHUTDOWN_PROMPT "¿Desea terminar su sesión ReactOS?" -} +/* + * Copyright 1998 Juergen Schmied + * Copyright 2003,2004 José Manuel Ferrer Ortiz + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "Iconos &grandes", FCIDM_SHVIEW_BIGICON + MENUITEM "Iconos &pequeños", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Detalles", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Ver" + BEGIN + MENUITEM "Iconos &grandes", FCIDM_SHVIEW_BIGICON + MENUITEM "Iconos &pequeños", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Detalles", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Ordenar &iconos" + BEGIN + MENUITEM "Por &nombre", 0x30 /* column 0 */ + MENUITEM "Por &tipo", 0x32 /* column 2 */ + MENUITEM "Por t&amaño", 0x31 /* ... */ + MENUITEM "Por &fecha", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Ordenar automáticamente", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Alinear iconos", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Actualizar", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Pegar", FCIDM_SHVIEW_INSERT + MENUITEM "Pegar acceso directo", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Nuevo" + BEGIN + MENUITEM "Nueva &carpeta", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Nuevo &acceso directo", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Propiedades", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "E&xplorar", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Abrir", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "C&ortar", FCIDM_SHVIEW_CUT + MENUITEM "&Copiar", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "C&rear acceso directo", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Eliminar", FCIDM_SHVIEW_DELETE + MENUITEM "Re&nombrar", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Propiedades", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Explorar carpeta" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "Aceptar", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancelar", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Acerca de %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "Aceptar", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS está disponible gracias a:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Introduzca el nombre de un programa, carpeta, documento o recurso de Internet, y ReactOS lo abrirá para usted.", 12289, 36, 11, 182, 18 + LTEXT "&Abrir:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "Aceptar", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancelar", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Examinar...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Escritorio" + IDS_MYCOMPUTER "Mi PC" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "Iconos &grandes" + IDS_VIEW_SMALL "Iconos &pequeños" + IDS_VIEW_LIST "&Lista" + IDS_VIEW_DETAILS "&Detalles" + IDS_SELECT "Seleccionar" + IDS_OPEN "Abrir" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "No se puede crear nueva carpeta: Permiso denegado." + IDS_CREATEFOLDER_CAPTION "Error durante la creación de una nueva carpeta" + IDS_DELETEITEM_CAPTION "Confirmar eliminación de archivo" + IDS_DELETEFOLDER_CAPTION "Confirmar eliminación de carpeta" + IDS_DELETEITEM_TEXT "¿Seguro que desea eliminar '%1'?" + IDS_DELETEMULTIPLE_TEXT "¿Seguro que desea eliminar estos %1 elementos?" + IDS_OVERWRITEFILE_TEXT "¿Sobreescribir el archivo '%1'?" + IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescritura de archivo" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Archivo" + IDS_SHV_COLUMN2 "Tamaño" + IDS_SHV_COLUMN3 "Tipo" + IDS_SHV_COLUMN4 "Modificado" + IDS_SHV_COLUMN5 "Atributos" + IDS_SHV_COLUMN6 "Tamaño" + IDS_SHV_COLUMN7 "Tamaño disponible" + IDS_SHV_COLUMN8 "Nombre" + IDS_SHV_COLUMN9 "Comentarios" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Reiniciar" + IDS_RESTART_PROMPT "¿Desea simular un reinicio de Windows?" + IDS_SHUTDOWN_TITLE "Apagar" + IDS_SHUTDOWN_PROMPT "¿Desea terminar su sesión ReactOS?" +} + +/* shell folder path default values */ +STRINGTABLE DISCARDABLE +{ + IDS_PROGRAMS "Menú Inicio\\Programas" + IDS_PERSONAL "Mis documentos" + IDS_FAVORITES "Favoritos" + IDS_STARTUP "Menú Inicio\\Programas\\Inicio" + IDS_RECENT "Recent" + IDS_SENDTO "SendTo" + IDS_STARTMENU "Menú Inicio" + IDS_MYMUSIC "Mis documentos\\Mi música" + IDS_MYVIDEO "Mis documentos\\Mis vídeos" + IDS_DESKTOPDIRECTORY "Escritorio" + IDS_NETHOOD "Entorno de red" + IDS_TEMPLATES "Templates" + IDS_APPDATA "Application Data" + IDS_PRINTHOOD "PrintHood" + IDS_LOCAL_APPDATA "Configuración local\\Datos de programa" + IDS_INTERNET_CACHE "Archivos temporales de Internet" + IDS_COOKIES "Cookies" + IDS_HISTORY "Historial" + IDS_PROGRAM_FILES "Archivos de programa" + IDS_MYPICTURES "Mis documentos\\Mis imágenes" + IDS_PROGRAM_FILES_COMMON "Archivos de programa\\Archivos comunes" + IDS_COMMON_DOCUMENTS "Documentos" + IDS_ADMINTOOLS "Menú Inicio\\Programas\\Accesorios\\Herramientas del sistema" + IDS_COMMON_MUSIC "Documentos\\Mi música" + IDS_COMMON_PICTURES "Documentos\\Mis imágenes" + IDS_COMMON_VIDEO "Documentos\\Mis vídeos" + IDS_CDBURN_AREA "Configuración local\\Datos de programa\\Microsoft\\CD Burning" +} diff --git a/reactos/lib/shell32/shell32_Fi.rc b/reactos/lib/shell32/shell32_Fi.rc index 709aed26e5f..c70d8a75034 100644 --- a/reactos/lib/shell32/shell32_Fi.rc +++ b/reactos/lib/shell32/shell32_Fi.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Tietoja: %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS:n tekijät:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Tietoja: %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS:n tekijät:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Fr.rc b/reactos/lib/shell32/shell32_Fr.rc index b8cdd92a794..ac8d6416ef7 100644 --- a/reactos/lib/shell32/shell32_Fr.rc +++ b/reactos/lib/shell32/shell32_Fr.rc @@ -1,224 +1,224 @@ -/* - * Shell32 - * French language support - * - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Grands icônes", FCIDM_SHVIEW_BIGICON - MENUITEM "&Petits icônes", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Détails", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Affichage" - BEGIN - MENUITEM "&Grands icônes", FCIDM_SHVIEW_BIGICON - MENUITEM "&Petits icônes", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Détails", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Trier les &icônes" - BEGIN - MENUITEM "Par &nom", 0x30 /* column 0 */ - MENUITEM "Par &type", 0x32 /* column 2 */ - MENUITEM "Par t&aille", 0x31 /* ... */ - MENUITEM "Par &date", 0x33 - MENUITEM SEPARATOR - MENUITEM "T&ri automatique", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Aligner les icônes", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Rafraîchir", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Coller", FCIDM_SHVIEW_INSERT - MENUITEM "Coller comme un lien", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Nouveau" - BEGIN - MENUITEM "Nouveau d&ossier", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Nouveau &lien", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Propriétés", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "E&xplorer", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Ouvrir", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "C&ouper", FCIDM_SHVIEW_CUT - MENUITEM "&Copier", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Créer un &lien", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Supprimer", FCIDM_SHVIEW_DELETE - MENUITEM "&Renommer", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Propriétés", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Parcourir" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Annuler", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "À propos de %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS est une réalisation de :", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Entrez le nom d'un programme, d'un dossier, d'un document ou d'une ressource Internet, et ReactOS l'ouvrira pour vous.", 12289, 36, 11, 182, 18 - LTEXT "&Ouvrir :", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Annuler", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Parcourir...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Bureau" - IDS_MYCOMPUTER "Poste de travail" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Grands icônes" - IDS_VIEW_SMALL "&Petits icônes" - IDS_VIEW_LIST "&Liste" - IDS_VIEW_DETAILS "&Détails" - IDS_SELECT "Sélectionner" - IDS_OPEN "Ouvrir" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Impossible de créer le nouveau dossier : permission refusée." - IDS_CREATEFOLDER_CAPTION "Erreur lors de la création du nouveau dossier" - IDS_DELETEITEM_CAPTION "Confirmer la suppression du fichier" - IDS_DELETEFOLDER_CAPTION "Confirmer la suppression du dossier" - IDS_DELETEITEM_TEXT "Êtes-vous sûr de vouloir supprimer '%1'?" - IDS_DELETEMULTIPLE_TEXT "Êtes-vous sût de vouloir supprimer ces %1 items ?" - IDS_OVERWRITEFILE_TEXT "Écraser le fichier %1?" - IDS_OVERWRITEFILE_CAPTION "Confirmer l'écrasement du fichier" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Fichier" - IDS_SHV_COLUMN2 "Taille" - IDS_SHV_COLUMN3 "Type" - IDS_SHV_COLUMN4 "Modifié" - IDS_SHV_COLUMN5 "Attributs" - IDS_SHV_COLUMN6 "Capacité" - IDS_SHV_COLUMN7 "Espace disponible" - IDS_SHV_COLUMN8 "Nom" - IDS_SHV_COLUMN9 "Commentaires" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Redémarrer" - IDS_RESTART_PROMPT "Voulez-vous simuler le redémarrage de Windows?" - IDS_SHUTDOWN_TITLE "Arrêter" - IDS_SHUTDOWN_PROMPT "Voulez-vous fermer la session ReactOS?" -} - -/* shell folder path default values */ -STRINGTABLE DISCARDABLE -{ - IDS_PROGRAMS "Menu Démarrer\\Programmes" - IDS_PERSONAL "Mes documents" - IDS_FAVORITES "Favoris" - IDS_STARTUP "Menu Démarrer\\Programmes\\Démarrage" - IDS_RECENT "Recent" - IDS_SENDTO "SendTo" - IDS_STARTMENU "Menu Démarrer" - IDS_MYMUSIC "Mes documents\\Ma musique" - IDS_MYVIDEO "Mes documents\\Mes vidéos" - IDS_DESKTOPDIRECTORY "Bureau" - IDS_NETHOOD "Voisinage Réseau" - IDS_TEMPLATES "Modèles" - IDS_APPDATA "Application Data" - IDS_PRINTHOOD "Voisinage d'impression" - IDS_LOCAL_APPDATA "Local Settings\\Application Data" - IDS_INTERNET_CACHE "Temporary Internet Files" - IDS_COOKIES "Cookies" - IDS_HISTORY "Historique" - IDS_PROGRAM_FILES "Program Files" - IDS_MYPICTURES "Mes documents\\Mes images" - IDS_PROGRAM_FILES_COMMON "Program Files\\Fichiers communs" - IDS_COMMON_DOCUMENTS "Documents" - IDS_ADMINTOOLS "Menu Démarrer\\Programmes\\Outils d'administration" - IDS_COMMON_MUSIC "Documents\\Ma musique" - IDS_COMMON_PICTURES "Documents\\Mes images" - IDS_COMMON_VIDEO "Documents\\Mes vidéos" - IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Burning" -} +/* + * Shell32 + * French language support + * + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Grands icônes", FCIDM_SHVIEW_BIGICON + MENUITEM "&Petits icônes", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Détails", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Affichage" + BEGIN + MENUITEM "&Grands icônes", FCIDM_SHVIEW_BIGICON + MENUITEM "&Petits icônes", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Liste", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Détails", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Trier les &icônes" + BEGIN + MENUITEM "Par &nom", 0x30 /* column 0 */ + MENUITEM "Par &type", 0x32 /* column 2 */ + MENUITEM "Par t&aille", 0x31 /* ... */ + MENUITEM "Par &date", 0x33 + MENUITEM SEPARATOR + MENUITEM "T&ri automatique", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Aligner les icônes", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Rafraîchir", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Coller", FCIDM_SHVIEW_INSERT + MENUITEM "Coller comme un lien", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Nouveau" + BEGIN + MENUITEM "Nouveau d&ossier", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Nouveau &lien", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Propriétés", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "E&xplorer", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Ouvrir", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "C&ouper", FCIDM_SHVIEW_CUT + MENUITEM "&Copier", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Créer un &lien", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Supprimer", FCIDM_SHVIEW_DELETE + MENUITEM "&Renommer", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Propriétés", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Parcourir" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Annuler", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "À propos de %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS est une réalisation de :", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Entrez le nom d'un programme, d'un dossier, d'un document ou d'une ressource Internet, et ReactOS l'ouvrira pour vous.", 12289, 36, 11, 182, 18 + LTEXT "&Ouvrir :", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Annuler", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Parcourir...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Bureau" + IDS_MYCOMPUTER "Poste de travail" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Grands icônes" + IDS_VIEW_SMALL "&Petits icônes" + IDS_VIEW_LIST "&Liste" + IDS_VIEW_DETAILS "&Détails" + IDS_SELECT "Sélectionner" + IDS_OPEN "Ouvrir" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Impossible de créer le nouveau dossier : permission refusée." + IDS_CREATEFOLDER_CAPTION "Erreur lors de la création du nouveau dossier" + IDS_DELETEITEM_CAPTION "Confirmer la suppression du fichier" + IDS_DELETEFOLDER_CAPTION "Confirmer la suppression du dossier" + IDS_DELETEITEM_TEXT "Êtes-vous sûr de vouloir supprimer '%1'?" + IDS_DELETEMULTIPLE_TEXT "Êtes-vous sût de vouloir supprimer ces %1 items ?" + IDS_OVERWRITEFILE_TEXT "Écraser le fichier %1?" + IDS_OVERWRITEFILE_CAPTION "Confirmer l'écrasement du fichier" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Fichier" + IDS_SHV_COLUMN2 "Taille" + IDS_SHV_COLUMN3 "Type" + IDS_SHV_COLUMN4 "Modifié" + IDS_SHV_COLUMN5 "Attributs" + IDS_SHV_COLUMN6 "Capacité" + IDS_SHV_COLUMN7 "Espace disponible" + IDS_SHV_COLUMN8 "Nom" + IDS_SHV_COLUMN9 "Commentaires" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Redémarrer" + IDS_RESTART_PROMPT "Voulez-vous simuler le redémarrage de Windows?" + IDS_SHUTDOWN_TITLE "Arrêter" + IDS_SHUTDOWN_PROMPT "Voulez-vous fermer la session ReactOS?" +} + +/* shell folder path default values */ +STRINGTABLE DISCARDABLE +{ + IDS_PROGRAMS "Menu Démarrer\\Programmes" + IDS_PERSONAL "Mes documents" + IDS_FAVORITES "Favoris" + IDS_STARTUP "Menu Démarrer\\Programmes\\Démarrage" + IDS_RECENT "Recent" + IDS_SENDTO "SendTo" + IDS_STARTMENU "Menu Démarrer" + IDS_MYMUSIC "Mes documents\\Ma musique" + IDS_MYVIDEO "Mes documents\\Mes vidéos" + IDS_DESKTOPDIRECTORY "Bureau" + IDS_NETHOOD "Voisinage Réseau" + IDS_TEMPLATES "Modèles" + IDS_APPDATA "Application Data" + IDS_PRINTHOOD "Voisinage d'impression" + IDS_LOCAL_APPDATA "Local Settings\\Application Data" + IDS_INTERNET_CACHE "Temporary Internet Files" + IDS_COOKIES "Cookies" + IDS_HISTORY "Historique" + IDS_PROGRAM_FILES "Program Files" + IDS_MYPICTURES "Mes documents\\Mes images" + IDS_PROGRAM_FILES_COMMON "Program Files\\Fichiers communs" + IDS_COMMON_DOCUMENTS "Documents" + IDS_ADMINTOOLS "Menu Démarrer\\Programmes\\Outils d'administration" + IDS_COMMON_MUSIC "Documents\\Ma musique" + IDS_COMMON_PICTURES "Documents\\Mes images" + IDS_COMMON_VIDEO "Documents\\Mes vidéos" + IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Burning" +} diff --git a/reactos/lib/shell32/shell32_Hu.rc b/reactos/lib/shell32/shell32_Hu.rc index 0de8dcfbc18..1a37e3d9741 100644 --- a/reactos/lib/shell32/shell32_Hu.rc +++ b/reactos/lib/shell32/shell32_Hu.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "A %s-rõl" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "A ReactOS-t írták:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "A %s-rõl" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "A ReactOS-t írták:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_It.rc b/reactos/lib/shell32/shell32_It.rc index 36ae5fb74c1..dbcf96fb9db 100644 --- a/reactos/lib/shell32/shell32_It.rc +++ b/reactos/lib/shell32/shell32_It.rc @@ -1,191 +1,191 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2003-2004 Puoti - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Icone Grandi", FCIDM_SHVIEW_BIGICON - MENUITEM "&Icone Piccole", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Dettagli", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Visualizza" - BEGIN - MENUITEM "&Icone Grandi", FCIDM_SHVIEW_BIGICON - MENUITEM "&Icone Piccole", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Dettagli", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Disponi &Icone" - BEGIN - MENUITEM "Per &Nome", 0x30 /* column 0 */ - MENUITEM "Per &Tipo", 0x32 /* column 2 */ - MENUITEM "Per &Dimensione", 0x31 /* ... */ - MENUITEM "Per &Data", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Disponi Automaticamente", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Allinea Icone", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Aggiorna", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Incolla", FCIDM_SHVIEW_INSERT - MENUITEM "Crea Collegamento", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Nuovo" - BEGIN - MENUITEM "Nuova &Cartella", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Nuovo &Collegamento", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Proprietà", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "E&splora", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Apri", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "&Taglia", FCIDM_SHVIEW_CUT - MENUITEM "&Copia", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "&Crea Collegamento", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Cancella", FCIDM_SHVIEW_DELETE - MENUITEM "&Rinomina", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Proprietà", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Sfoglia Cartella" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Annulla", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Informazioni su %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS è disponibile grazie a:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Digitare il nome del programma, della cartella, del documento o della risorsa internet, e ReactOS la aprirà.", 12289, 36, 11, 182, 18 - LTEXT "&Apri:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Annulla", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Esplora...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Desktop" - IDS_MYCOMPUTER "Risorse del Computer" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Icone Grandi" - IDS_VIEW_SMALL "I&cone Piccole" - IDS_VIEW_LIST "&Lista" - IDS_VIEW_DETAILS "&Dettagli" - IDS_SELECT "Selezione" - IDS_OPEN "Apri" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Impossibile creare la cartella: Accesso negato." - IDS_CREATEFOLDER_CAPTION "Errore durante la creazione della cartella" - IDS_DELETEITEM_CAPTION "Confermare la cancallazione del file" - IDS_DELETEFOLDER_CAPTION "Confermare la cancellazione della cartella" - IDS_DELETEITEM_TEXT "Sei sicuro di voler cancellare '%1'?" - IDS_DELETEMULTIPLE_TEXT "Sei sicuro di voler cancellare questi %1 elementi?" - IDS_OVERWRITEFILE_TEXT "Sovrascrivere il File %1?" - IDS_OVERWRITEFILE_CAPTION "Confermare la sovrascrizione del File" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "File" - IDS_SHV_COLUMN2 "Dimensione" - IDS_SHV_COLUMN3 "Tipo" - IDS_SHV_COLUMN4 "Modificato" - IDS_SHV_COLUMN5 "Attributi" - IDS_SHV_COLUMN6 "Dimensione" - IDS_SHV_COLUMN7 "Dimensione disponibile" - IDS_SHV_COLUMN8 "Nome" - IDS_SHV_COLUMN9 "Commenti" -END - - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Riavvia" - IDS_RESTART_PROMPT "Vuoi simulare un riavvio do Windows?" - IDS_SHUTDOWN_TITLE "Termina sessione" - IDS_SHUTDOWN_PROMPT "Vuoi terminare la sessione di ReactOS?" -} +/* + * Copyright 1998 Juergen Schmied + * Copyright 2003-2004 Puoti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Icone Grandi", FCIDM_SHVIEW_BIGICON + MENUITEM "&Icone Piccole", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Dettagli", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Visualizza" + BEGIN + MENUITEM "&Icone Grandi", FCIDM_SHVIEW_BIGICON + MENUITEM "&Icone Piccole", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Dettagli", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Disponi &Icone" + BEGIN + MENUITEM "Per &Nome", 0x30 /* column 0 */ + MENUITEM "Per &Tipo", 0x32 /* column 2 */ + MENUITEM "Per &Dimensione", 0x31 /* ... */ + MENUITEM "Per &Data", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Disponi Automaticamente", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Allinea Icone", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Aggiorna", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Incolla", FCIDM_SHVIEW_INSERT + MENUITEM "Crea Collegamento", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Nuovo" + BEGIN + MENUITEM "Nuova &Cartella", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Nuovo &Collegamento", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Proprietà", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "E&splora", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Apri", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "&Taglia", FCIDM_SHVIEW_CUT + MENUITEM "&Copia", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "&Crea Collegamento", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Cancella", FCIDM_SHVIEW_DELETE + MENUITEM "&Rinomina", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Proprietà", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Sfoglia Cartella" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Annulla", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Informazioni su %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS è disponibile grazie a:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Digitare il nome del programma, della cartella, del documento o della risorsa internet, e ReactOS la aprirà.", 12289, 36, 11, 182, 18 + LTEXT "&Apri:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Annulla", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Esplora...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Desktop" + IDS_MYCOMPUTER "Risorse del Computer" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Icone Grandi" + IDS_VIEW_SMALL "I&cone Piccole" + IDS_VIEW_LIST "&Lista" + IDS_VIEW_DETAILS "&Dettagli" + IDS_SELECT "Selezione" + IDS_OPEN "Apri" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Impossibile creare la cartella: Accesso negato." + IDS_CREATEFOLDER_CAPTION "Errore durante la creazione della cartella" + IDS_DELETEITEM_CAPTION "Confermare la cancallazione del file" + IDS_DELETEFOLDER_CAPTION "Confermare la cancellazione della cartella" + IDS_DELETEITEM_TEXT "Sei sicuro di voler cancellare '%1'?" + IDS_DELETEMULTIPLE_TEXT "Sei sicuro di voler cancellare questi %1 elementi?" + IDS_OVERWRITEFILE_TEXT "Sovrascrivere il File %1?" + IDS_OVERWRITEFILE_CAPTION "Confermare la sovrascrizione del File" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "File" + IDS_SHV_COLUMN2 "Dimensione" + IDS_SHV_COLUMN3 "Tipo" + IDS_SHV_COLUMN4 "Modificato" + IDS_SHV_COLUMN5 "Attributi" + IDS_SHV_COLUMN6 "Dimensione" + IDS_SHV_COLUMN7 "Dimensione disponibile" + IDS_SHV_COLUMN8 "Nome" + IDS_SHV_COLUMN9 "Commenti" +END + + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Riavvia" + IDS_RESTART_PROMPT "Vuoi simulare un riavvio do Windows?" + IDS_SHUTDOWN_TITLE "Termina sessione" + IDS_SHUTDOWN_PROMPT "Vuoi terminare la sessione di ReactOS?" +} diff --git a/reactos/lib/shell32/shell32_Ja.rc b/reactos/lib/shell32/shell32_Ja.rc index 90306a7e09b..963c1a18b1d 100644 --- a/reactos/lib/shell32/shell32_Ja.rc +++ b/reactos/lib/shell32/shell32_Ja.rc @@ -1,140 +1,140 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "‘å‚«‚ȱ²ºÝ(&G)", FCIDM_SHVIEW_BIGICON - MENUITEM "¬‚³‚ȱ²ºÝ(&M)", FCIDM_SHVIEW_SMALLICON - MENUITEM "ˆê——(&L)", FCIDM_SHVIEW_LISTVIEW - MENUITEM "Ú×(&D)", FCIDM_SHVIEW_REPORTVIEW -END - -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "•\\ަ(&V)" - BEGIN - MENUITEM "‘å‚«‚¢ƒAƒCƒRƒ“(&G)", FCIDM_SHVIEW_BIGICON - MENUITEM "¬‚³‚¢ƒAƒCƒRƒ“(&M)", FCIDM_SHVIEW_SMALLICON - MENUITEM "ˆê——(&L)", FCIDM_SHVIEW_LISTVIEW - MENUITEM "Ú×(&D)", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "ƒAƒCƒRƒ“‚Ì®—ñ(&I)" - BEGIN - MENUITEM "–¼‘O‡(&N)", 0x30 /* column 0 */ - MENUITEM "Ží—Þ‡(&T)", 0x32 /* column 2 */ - MENUITEM "ƒTƒCƒY‡(&S)", 0x31 /* ... */ - MENUITEM "“ú•t‡(&D)", 0x33 - MENUITEM SEPARATOR - MENUITEM "ƒAƒCƒRƒ“‚ÌŽ©“®®—ñ(&A)", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "“™ŠÔŠu‚É®—ñ", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "“\\‚è•t‚¯", FCIDM_SHVIEW_INSERT - MENUITEM "ƒVƒ‡[ƒgƒJƒbƒg‚Ì“\\‚è•t‚¯", FCIDM_SHVIEW_INSERTLINK - POPUP "V‹Kì¬" - BEGIN - MENUITEM "V‹KƒtƒHƒ‹ƒ_(&F)", 0x7053 - MENUITEM "V‹KƒVƒ‡[ƒgƒJƒbƒg(&L)", 0x7052 - MENUITEM SEPARATOR - END - MENUITEM "ƒvƒƒpƒeƒB", FCIDM_SHVIEW_PROPERTIES - END -END - -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "Ø‚èŽæ‚è(&U)", FCIDM_SHVIEW_CUT - MENUITEM "ƒRƒs[(&C)", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "ƒVƒ‡[ƒgƒJƒbƒg‚Ìì¬(&L)", 0x7051 - MENUITEM "íœ(&D)", FCIDM_SHVIEW_DELETE - MENUITEM "–¼‘O‚Ì•ÏX(&R)", 0x7050 - MENUITEM SEPARATOR - MENUITEM "ƒvƒƒpƒeƒB(&P)", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "ÃÞ½¸Ä¯Ìß" - IDS_MYCOMPUTER "ϲºÝËß­°À" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "‘å‚«‚¢ƒAƒCƒRƒ“(&G)" - IDS_VIEW_SMALL "¬‚³‚¢ƒAƒCƒRƒ“(&M)" - IDS_VIEW_LIST "ˆê——(&L)" - IDS_VIEW_DETAILS "Ú×(&D)" - IDS_SELECT "‘I‘ð" - IDS_OPEN "ŠJ‚­" -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "%s ‚ɂ‚¢‚Ä" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* columns in the shellview */ -STRINGTABLE DISCARDABLE -BEGIN - IDS_SHV_COLUMN1 "–¼‘O" - IDS_SHV_COLUMN2 "ƒTƒCƒY" - IDS_SHV_COLUMN3 "ƒtƒ@ƒCƒ‹‚ÌŽí—Þ" - IDS_SHV_COLUMN4 "XV“úŽž" - IDS_SHV_COLUMN5 "‘®«" - IDS_SHV_COLUMN6 "‡ŒvƒTƒCƒY" - IDS_SHV_COLUMN7 "‹ó‚«—e—Ê" - IDS_SHV_COLUMN8 "Name" /*FIXME*/ - IDS_SHV_COLUMN9 "Comments" /*FIXME*/ -END +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "‘å‚«‚ȱ²ºÝ(&G)", FCIDM_SHVIEW_BIGICON + MENUITEM "¬‚³‚ȱ²ºÝ(&M)", FCIDM_SHVIEW_SMALLICON + MENUITEM "ˆê——(&L)", FCIDM_SHVIEW_LISTVIEW + MENUITEM "Ú×(&D)", FCIDM_SHVIEW_REPORTVIEW +END + +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "•\\ަ(&V)" + BEGIN + MENUITEM "‘å‚«‚¢ƒAƒCƒRƒ“(&G)", FCIDM_SHVIEW_BIGICON + MENUITEM "¬‚³‚¢ƒAƒCƒRƒ“(&M)", FCIDM_SHVIEW_SMALLICON + MENUITEM "ˆê——(&L)", FCIDM_SHVIEW_LISTVIEW + MENUITEM "Ú×(&D)", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "ƒAƒCƒRƒ“‚Ì®—ñ(&I)" + BEGIN + MENUITEM "–¼‘O‡(&N)", 0x30 /* column 0 */ + MENUITEM "Ží—Þ‡(&T)", 0x32 /* column 2 */ + MENUITEM "ƒTƒCƒY‡(&S)", 0x31 /* ... */ + MENUITEM "“ú•t‡(&D)", 0x33 + MENUITEM SEPARATOR + MENUITEM "ƒAƒCƒRƒ“‚ÌŽ©“®®—ñ(&A)", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "“™ŠÔŠu‚É®—ñ", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "“\\‚è•t‚¯", FCIDM_SHVIEW_INSERT + MENUITEM "ƒVƒ‡[ƒgƒJƒbƒg‚Ì“\\‚è•t‚¯", FCIDM_SHVIEW_INSERTLINK + POPUP "V‹Kì¬" + BEGIN + MENUITEM "V‹KƒtƒHƒ‹ƒ_(&F)", 0x7053 + MENUITEM "V‹KƒVƒ‡[ƒgƒJƒbƒg(&L)", 0x7052 + MENUITEM SEPARATOR + END + MENUITEM "ƒvƒƒpƒeƒB", FCIDM_SHVIEW_PROPERTIES + END +END + +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "Ø‚èŽæ‚è(&U)", FCIDM_SHVIEW_CUT + MENUITEM "ƒRƒs[(&C)", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "ƒVƒ‡[ƒgƒJƒbƒg‚Ìì¬(&L)", 0x7051 + MENUITEM "íœ(&D)", FCIDM_SHVIEW_DELETE + MENUITEM "–¼‘O‚Ì•ÏX(&R)", 0x7050 + MENUITEM SEPARATOR + MENUITEM "ƒvƒƒpƒeƒB(&P)", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "ÃÞ½¸Ä¯Ìß" + IDS_MYCOMPUTER "ϲºÝËß­°À" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "‘å‚«‚¢ƒAƒCƒRƒ“(&G)" + IDS_VIEW_SMALL "¬‚³‚¢ƒAƒCƒRƒ“(&M)" + IDS_VIEW_LIST "ˆê——(&L)" + IDS_VIEW_DETAILS "Ú×(&D)" + IDS_SELECT "‘I‘ð" + IDS_OPEN "ŠJ‚­" +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "%s ‚ɂ‚¢‚Ä" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* columns in the shellview */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_SHV_COLUMN1 "–¼‘O" + IDS_SHV_COLUMN2 "ƒTƒCƒY" + IDS_SHV_COLUMN3 "ƒtƒ@ƒCƒ‹‚ÌŽí—Þ" + IDS_SHV_COLUMN4 "XV“úŽž" + IDS_SHV_COLUMN5 "‘®«" + IDS_SHV_COLUMN6 "‡ŒvƒTƒCƒY" + IDS_SHV_COLUMN7 "‹ó‚«—e—Ê" + IDS_SHV_COLUMN8 "Name" /*FIXME*/ + IDS_SHV_COLUMN9 "Comments" /*FIXME*/ +END diff --git a/reactos/lib/shell32/shell32_Ko.rc b/reactos/lib/shell32/shell32_Ko.rc index 11975eb7641..b536c38eb47 100644 --- a/reactos/lib/shell32/shell32_Ko.rc +++ b/reactos/lib/shell32/shell32_Ko.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "%s¿¡ °üÇÏ¿©" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "È®ÀÎ", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "%s¿¡ °üÇÏ¿©" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "È®ÀÎ", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Nl.rc b/reactos/lib/shell32/shell32_Nl.rc index 2e4975b791c..26f89165659 100644 --- a/reactos/lib/shell32/shell32_Nl.rc +++ b/reactos/lib/shell32/shell32_Nl.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Info %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS is geschreven door:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Info %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS is geschreven door:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_No.rc b/reactos/lib/shell32/shell32_No.rc index 5a3822f759e..e532f5d0761 100644 --- a/reactos/lib/shell32/shell32_No.rc +++ b/reactos/lib/shell32/shell32_No.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_NORWEGIAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Om %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_NORWEGIAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Om %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Pl.rc b/reactos/lib/shell32/shell32_Pl.rc index 75ba80550c5..371394e93b2 100644 --- a/reactos/lib/shell32/shell32_Pl.rc +++ b/reactos/lib/shell32/shell32_Pl.rc @@ -1,190 +1,190 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2004 Piotr Caban - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Du¿e Ikony", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ma³e Ikony", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Szczegó³y", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Widok" - BEGIN - MENUITEM "&Du¿e Ikony", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ma³e Ikony", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Szczegó³y", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Rozmieœæ &ikony wed³ug" - BEGIN - MENUITEM "&Nazwy", 0x30 /* column 0 */ - MENUITEM "&Typu", 0x32 /* column 2 */ - MENUITEM "&Wielkoœci", 0x31 /* ... */ - MENUITEM "&Daty", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Autorozmieszczanie", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "&Wyrównaj ikony", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "&Odœwierz", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "W&klej", FCIDM_SHVIEW_INSERT - MENUITEM "Wklej s&krót", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "&Nowy" - BEGIN - MENUITEM "&Folder", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "&Skrót", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "W³aœciwoœci", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Eksploruj", FCIDM_SHVIEW_EXPLORE - MENUITEM "&Otwórz", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "&Wytnij", FCIDM_SHVIEW_CUT - MENUITEM "&Kopiuj", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Utwórz &Skrót", FCIDM_SHVIEW_CREATELINK - MENUITEM "&Usuñ", FCIDM_SHVIEW_DELETE - MENUITEM "&Zmieñ nazwê", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "W³&aœciwoœci", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Wybierz folder" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Anuluj", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "O %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "Mo¿esz korzystaæ z ReactOS'a dziêki:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Wpisz nazwê programu, katalogu, dokumentu, a ReactOS otworzy go dla ciebie.", 12289, 36, 11, 182, 18 - LTEXT "&Otwórz:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Anuluj", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Przegl¹daj...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Pulpit" - IDS_MYCOMPUTER "Mój komputer" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Du¿e Ikony" - IDS_VIEW_SMALL "&Ma³e Ikony" - IDS_VIEW_LIST "&Lista" - IDS_VIEW_DETAILS "&Szczegó³y" - IDS_SELECT "Zaznacz" - IDS_OPEN "Otwórz" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Nie mogê utworzyæ nowego katalogu: Brak dostêpu." - IDS_CREATEFOLDER_CAPTION "B³¹d przy tworzeniu nowego katalogu." - IDS_DELETEITEM_CAPTION "PotwierdŸ usuniêcia pliku" - IDS_DELETEFOLDER_CAPTION "PotwierdŸ usuniêcie katalogu" - IDS_DELETEITEM_TEXT "Czy jesteœ pewien, ¿e chcesz usun¹æ '%1'?" - IDS_DELETEMULTIPLE_TEXT "Czy jesteœ pewien, ¿e chcesz usun¹æ te %1 pliki?" - IDS_OVERWRITEFILE_TEXT "Zast¹piæ plik %1?" - IDS_OVERWRITEFILE_CAPTION "PotwierdŸ zast¹pienie pliku" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Plik" - IDS_SHV_COLUMN2 "Wielkoœæ" - IDS_SHV_COLUMN3 "Typ" - IDS_SHV_COLUMN4 "Modyfikacja" - IDS_SHV_COLUMN5 "Atrybuty" - IDS_SHV_COLUMN6 "Wielkoœæ" - IDS_SHV_COLUMN7 "Dostêpna wielkoœæ" - IDS_SHV_COLUMN8 "Nazwa" - IDS_SHV_COLUMN9 "Komentarz" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Uruchom ponownie" - IDS_RESTART_PROMPT "Czy chcesz zasymulowaæ zrestartowanie Windowsa?" - IDS_SHUTDOWN_TITLE "Wy³¹cz" - IDS_SHUTDOWN_PROMPT "Czy chcesz wy³¹czyæ sesjê ReactOS'a?" -} +/* + * Copyright 1998 Juergen Schmied + * Copyright 2004 Piotr Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Du¿e Ikony", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ma³e Ikony", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Szczegó³y", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Widok" + BEGIN + MENUITEM "&Du¿e Ikony", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ma³e Ikony", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Szczegó³y", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Rozmieœæ &ikony wed³ug" + BEGIN + MENUITEM "&Nazwy", 0x30 /* column 0 */ + MENUITEM "&Typu", 0x32 /* column 2 */ + MENUITEM "&Wielkoœci", 0x31 /* ... */ + MENUITEM "&Daty", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Autorozmieszczanie", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "&Wyrównaj ikony", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "&Odœwierz", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "W&klej", FCIDM_SHVIEW_INSERT + MENUITEM "Wklej s&krót", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "&Nowy" + BEGIN + MENUITEM "&Folder", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "&Skrót", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "W³aœciwoœci", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Eksploruj", FCIDM_SHVIEW_EXPLORE + MENUITEM "&Otwórz", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "&Wytnij", FCIDM_SHVIEW_CUT + MENUITEM "&Kopiuj", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Utwórz &Skrót", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Usuñ", FCIDM_SHVIEW_DELETE + MENUITEM "&Zmieñ nazwê", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "W³&aœciwoœci", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Wybierz folder" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Anuluj", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "O %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "Mo¿esz korzystaæ z ReactOS'a dziêki:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Wpisz nazwê programu, katalogu, dokumentu, a ReactOS otworzy go dla ciebie.", 12289, 36, 11, 182, 18 + LTEXT "&Otwórz:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Anuluj", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Przegl¹daj...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Pulpit" + IDS_MYCOMPUTER "Mój komputer" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Du¿e Ikony" + IDS_VIEW_SMALL "&Ma³e Ikony" + IDS_VIEW_LIST "&Lista" + IDS_VIEW_DETAILS "&Szczegó³y" + IDS_SELECT "Zaznacz" + IDS_OPEN "Otwórz" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Nie mogê utworzyæ nowego katalogu: Brak dostêpu." + IDS_CREATEFOLDER_CAPTION "B³¹d przy tworzeniu nowego katalogu." + IDS_DELETEITEM_CAPTION "PotwierdŸ usuniêcia pliku" + IDS_DELETEFOLDER_CAPTION "PotwierdŸ usuniêcie katalogu" + IDS_DELETEITEM_TEXT "Czy jesteœ pewien, ¿e chcesz usun¹æ '%1'?" + IDS_DELETEMULTIPLE_TEXT "Czy jesteœ pewien, ¿e chcesz usun¹æ te %1 pliki?" + IDS_OVERWRITEFILE_TEXT "Zast¹piæ plik %1?" + IDS_OVERWRITEFILE_CAPTION "PotwierdŸ zast¹pienie pliku" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Plik" + IDS_SHV_COLUMN2 "Wielkoœæ" + IDS_SHV_COLUMN3 "Typ" + IDS_SHV_COLUMN4 "Modyfikacja" + IDS_SHV_COLUMN5 "Atrybuty" + IDS_SHV_COLUMN6 "Wielkoœæ" + IDS_SHV_COLUMN7 "Dostêpna wielkoœæ" + IDS_SHV_COLUMN8 "Nazwa" + IDS_SHV_COLUMN9 "Komentarz" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Uruchom ponownie" + IDS_RESTART_PROMPT "Czy chcesz zasymulowaæ zrestartowanie Windowsa?" + IDS_SHUTDOWN_TITLE "Wy³¹cz" + IDS_SHUTDOWN_PROMPT "Czy chcesz wy³¹czyæ sesjê ReactOS'a?" +} diff --git a/reactos/lib/shell32/shell32_Pt.rc b/reactos/lib/shell32/shell32_Pt.rc index 4ff1e595ec3..3ebdf5c22ce 100644 --- a/reactos/lib/shell32/shell32_Pt.rc +++ b/reactos/lib/shell32/shell32_Pt.rc @@ -1,190 +1,190 @@ -/* - * Copyright 1998 Juergen Schmied - * Copyright 2003 Marcelo Duarte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "Ícones &grandes", FCIDM_SHVIEW_BIGICON - MENUITEM "Ícones &pequenos", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Detalhes", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Exibir" - BEGIN - MENUITEM "Ícones &grandes", FCIDM_SHVIEW_BIGICON - MENUITEM "Ícones &pequenos", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Detalhes", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "O&rganizar ícones" - BEGIN - MENUITEM "Por &nome", 0x30 /* column 0 */ - MENUITEM "Por &tipo", 0x32 /* column 2 */ - MENUITEM "Por ta&manho", 0x31 /* ... */ - MENUITEM "Por &data", 0x33 - MENUITEM SEPARATOR - MENUITEM "Auto organi&zar", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Alin&har ícones", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "&Atualizar", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Co&lar", FCIDM_SHVIEW_INSERT - MENUITEM "Colar a&talho", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Novo" - BEGIN - MENUITEM "&Pasta", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "&Atalho", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Propriedades", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Explorar", FCIDM_SHVIEW_EXPLORE - MENUITEM "A&brir", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "C&ortar", FCIDM_SHVIEW_CUT - MENUITEM "&Copiar", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "Criar a&talho", FCIDM_SHVIEW_CREATELINK - MENUITEM "E&xcluir", FCIDM_SHVIEW_DELETE - MENUITEM "&Renomear", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Propriedades", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Procurar pasta" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "Cancelar", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Sobre %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS foi disponibilizado por:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Digite o nome do programa, pasta, documento, ou endereço Internet, que o ReactOS irá abrí-lo para você.", 12289, 36, 11, 182, 18 - LTEXT "&Abrir:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancelar", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Procurar...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Área de trabalho" - IDS_MYCOMPUTER "Meu computador" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "Ícones &grandes" - IDS_VIEW_SMALL "Ícones &pequenos" - IDS_VIEW_LIST "&Lista" - IDS_VIEW_DETAILS "&Detalhes" - IDS_SELECT "Selecionar" - IDS_OPEN "Abrir" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Não pode criar nova pasta: Permissão negada." - IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta" - IDS_DELETEITEM_CAPTION "Confirmar exclusão de arquivo" - IDS_DELETEFOLDER_CAPTION "Confirmar exclusão de pasta" - IDS_DELETEITEM_TEXT "Você tem certeza que deseja excluir '%1'?" - IDS_DELETEMULTIPLE_TEXT "Você tem certeza que deseja excluir estes %1 itens?" - IDS_OVERWRITEFILE_TEXT "Sobreescrever arquivo %1?" - IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescrever arquivo" -} - -/* colunas no shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Arquivo" - IDS_SHV_COLUMN2 "Tamanho" - IDS_SHV_COLUMN3 "Tipo" - IDS_SHV_COLUMN4 "Modificado" - IDS_SHV_COLUMN5 "Atributos" - IDS_SHV_COLUMN6 "Tamanho" - IDS_SHV_COLUMN7 "Disponível" - IDS_SHV_COLUMN8 "Nome" - IDS_SHV_COLUMN9 "Comentários" -END - -/* message box strings */ -STRINGTABLE DISCARDABLE -{ - IDS_RESTART_TITLE "Reiniciar" - IDS_RESTART_PROMPT "Você quer simular a reinicialização do Windows?" - IDS_SHUTDOWN_TITLE "Desligar" - IDS_SHUTDOWN_PROMPT "Você quer finalizar a sessão no ReactOS?" -} +/* + * Copyright 1998 Juergen Schmied + * Copyright 2003 Marcelo Duarte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "Ícones &grandes", FCIDM_SHVIEW_BIGICON + MENUITEM "Ícones &pequenos", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Detalhes", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Exibir" + BEGIN + MENUITEM "Ícones &grandes", FCIDM_SHVIEW_BIGICON + MENUITEM "Ícones &pequenos", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Lista", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Detalhes", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "O&rganizar ícones" + BEGIN + MENUITEM "Por &nome", 0x30 /* column 0 */ + MENUITEM "Por &tipo", 0x32 /* column 2 */ + MENUITEM "Por ta&manho", 0x31 /* ... */ + MENUITEM "Por &data", 0x33 + MENUITEM SEPARATOR + MENUITEM "Auto organi&zar", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Alin&har ícones", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "&Atualizar", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Co&lar", FCIDM_SHVIEW_INSERT + MENUITEM "Colar a&talho", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Novo" + BEGIN + MENUITEM "&Pasta", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "&Atalho", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Propriedades", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Explorar", FCIDM_SHVIEW_EXPLORE + MENUITEM "A&brir", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "C&ortar", FCIDM_SHVIEW_CUT + MENUITEM "&Copiar", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "Criar a&talho", FCIDM_SHVIEW_CREATELINK + MENUITEM "E&xcluir", FCIDM_SHVIEW_DELETE + MENUITEM "&Renomear", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Propriedades", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Procurar pasta" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancelar", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Sobre %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS foi disponibilizado por:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Digite o nome do programa, pasta, documento, ou endereço Internet, que o ReactOS irá abrí-lo para você.", 12289, 36, 11, 182, 18 + LTEXT "&Abrir:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancelar", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Procurar...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Área de trabalho" + IDS_MYCOMPUTER "Meu computador" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "Ícones &grandes" + IDS_VIEW_SMALL "Ícones &pequenos" + IDS_VIEW_LIST "&Lista" + IDS_VIEW_DETAILS "&Detalhes" + IDS_SELECT "Selecionar" + IDS_OPEN "Abrir" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Não pode criar nova pasta: Permissão negada." + IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta" + IDS_DELETEITEM_CAPTION "Confirmar exclusão de arquivo" + IDS_DELETEFOLDER_CAPTION "Confirmar exclusão de pasta" + IDS_DELETEITEM_TEXT "Você tem certeza que deseja excluir '%1'?" + IDS_DELETEMULTIPLE_TEXT "Você tem certeza que deseja excluir estes %1 itens?" + IDS_OVERWRITEFILE_TEXT "Sobreescrever arquivo %1?" + IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescrever arquivo" +} + +/* colunas no shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Arquivo" + IDS_SHV_COLUMN2 "Tamanho" + IDS_SHV_COLUMN3 "Tipo" + IDS_SHV_COLUMN4 "Modificado" + IDS_SHV_COLUMN5 "Atributos" + IDS_SHV_COLUMN6 "Tamanho" + IDS_SHV_COLUMN7 "Disponível" + IDS_SHV_COLUMN8 "Nome" + IDS_SHV_COLUMN9 "Comentários" +END + +/* message box strings */ +STRINGTABLE DISCARDABLE +{ + IDS_RESTART_TITLE "Reiniciar" + IDS_RESTART_PROMPT "Você quer simular a reinicialização do Windows?" + IDS_SHUTDOWN_TITLE "Desligar" + IDS_SHUTDOWN_PROMPT "Você quer finalizar a sessão no ReactOS?" +} diff --git a/reactos/lib/shell32/shell32_Ru.rc b/reactos/lib/shell32/shell32_Ru.rc index 3199802b5f5..8c6dcfc0acf 100644 --- a/reactos/lib/shell32/shell32_Ru.rc +++ b/reactos/lib/shell32/shell32_Ru.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Î %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "Ðàçðàáîò÷èêè ReactOS:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Ââåäèòå èìÿ ïðîãðàììû, ïàïêè, äîêóìåíòà èëè ðåñóðñ Èíòåðíåòà, è ReactOS îòêðîåò èõ.", 12289, 36, 11, 182, 18 - LTEXT "&Îòêðûòü:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Îòìåíà", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Îá&çîð...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Î %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "Ðàçðàáîò÷èêè ReactOS:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Ââåäèòå èìÿ ïðîãðàììû, ïàïêè, äîêóìåíòà èëè ðåñóðñ Èíòåðíåòà, è ReactOS îòêðîåò èõ.", 12289, 36, 11, 182, 18 + LTEXT "&Îòêðûòü:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Îòìåíà", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Îá&çîð...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Si.rc b/reactos/lib/shell32/shell32_Si.rc index 97c5387ffb2..66d1ba63025 100644 --- a/reactos/lib/shell32/shell32_Si.rc +++ b/reactos/lib/shell32/shell32_Si.rc @@ -1,60 +1,60 @@ -/* - * Copyright 2002-2003 Rok Mandeljc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "O %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "V redu", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS so ustvarili:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Vnesite ime programa, mape, dokumenta ali spletne strani, in ReactOS ga (jo) bo odprl.", 12289, 36, 11, 182, 18 - LTEXT "&Odpri:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "V redu", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Preklièi", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Pre&brskaj", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* columns in the shellview */ -STRINGTABLE LANGUAGE LANG_SLOVENIAN, SUBLANG_NEUTRAL -BEGIN - IDS_SHV_COLUMN1 "Datoteka" - IDS_SHV_COLUMN2 "Velikost" - IDS_SHV_COLUMN3 "Vrsta" - IDS_SHV_COLUMN4 "Spremenjena" - IDS_SHV_COLUMN5 "Atributi" - IDS_SHV_COLUMN6 "Toèna velikost" - IDS_SHV_COLUMN7 "Prosto" - IDS_SHV_COLUMN8 "Name" /*FIXME*/ - IDS_SHV_COLUMN9 "Comments" /*FIXME*/ -END +/* + * Copyright 2002-2003 Rok Mandeljc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "O %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "V redu", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS so ustvarili:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Vnesite ime programa, mape, dokumenta ali spletne strani, in ReactOS ga (jo) bo odprl.", 12289, 36, 11, 182, 18 + LTEXT "&Odpri:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "V redu", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Preklièi", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Pre&brskaj", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* columns in the shellview */ +STRINGTABLE LANGUAGE LANG_SLOVENIAN, SUBLANG_NEUTRAL +BEGIN + IDS_SHV_COLUMN1 "Datoteka" + IDS_SHV_COLUMN2 "Velikost" + IDS_SHV_COLUMN3 "Vrsta" + IDS_SHV_COLUMN4 "Spremenjena" + IDS_SHV_COLUMN5 "Atributi" + IDS_SHV_COLUMN6 "Toèna velikost" + IDS_SHV_COLUMN7 "Prosto" + IDS_SHV_COLUMN8 "Name" /*FIXME*/ + IDS_SHV_COLUMN9 "Comments" /*FIXME*/ +END diff --git a/reactos/lib/shell32/shell32_Sk.rc b/reactos/lib/shell32/shell32_Sk.rc index e6924503acc..d3392e82114 100644 --- a/reactos/lib/shell32/shell32_Sk.rc +++ b/reactos/lib/shell32/shell32_Sk.rc @@ -1,60 +1,60 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "O programe %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "Víno pre vás pripravili:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* columns in the shellview */ -STRINGTABLE LANGUAGE LANG_SLOVAK, SUBLANG_NEUTRAL -BEGIN - IDS_SHV_COLUMN1 "Súbor" - IDS_SHV_COLUMN2 "Ve¾kos" - IDS_SHV_COLUMN3 "Typ" - IDS_SHV_COLUMN4 "Modifikovaný" - IDS_SHV_COLUMN5 "Atribúty" - IDS_SHV_COLUMN6 "Ve¾kos" - IDS_SHV_COLUMN7 "Ve¾kos k dispozícii" - IDS_SHV_COLUMN8 "Name" /*FIXME*/ - IDS_SHV_COLUMN9 "Comments" /*FIXME*/ -END +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "O programe %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "Víno pre vás pripravili:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* columns in the shellview */ +STRINGTABLE LANGUAGE LANG_SLOVAK, SUBLANG_NEUTRAL +BEGIN + IDS_SHV_COLUMN1 "Súbor" + IDS_SHV_COLUMN2 "Ve¾kos" + IDS_SHV_COLUMN3 "Typ" + IDS_SHV_COLUMN4 "Modifikovaný" + IDS_SHV_COLUMN5 "Atribúty" + IDS_SHV_COLUMN6 "Ve¾kos" + IDS_SHV_COLUMN7 "Ve¾kos k dispozícii" + IDS_SHV_COLUMN8 "Name" /*FIXME*/ + IDS_SHV_COLUMN9 "Comments" /*FIXME*/ +END diff --git a/reactos/lib/shell32/shell32_Sv.rc b/reactos/lib/shell32/shell32_Sv.rc index c4853c28326..86102cc1055 100644 --- a/reactos/lib/shell32/shell32_Sv.rc +++ b/reactos/lib/shell32/shell32_Sv.rc @@ -1,46 +1,46 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Om %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS hade inte varit möjligt utan dessa personer:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Skriv namnet på ett program, en mapp eller ett dokument och ReactOS kommer att öppna det för dig.", 12289, 36, 11, 182, 18 - LTEXT "&Öppna:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Avbryt", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Bläddra...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Om %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS hade inte varit möjligt utan dessa personer:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Skriv namnet på ett program, en mapp eller ett dokument och ReactOS kommer att öppna det för dig.", 12289, 36, 11, 182, 18 + LTEXT "&Öppna:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Avbryt", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Bläddra...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Uk.rc b/reactos/lib/shell32/shell32_Uk.rc index b0cf021d21a..fbe7b5edc46 100644 --- a/reactos/lib/shell32/shell32_Uk.rc +++ b/reactos/lib/shell32/shell32_Uk.rc @@ -1,178 +1,178 @@ -/* - * Copyright 2004 Ilya Korniyko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -MENU_001 MENU DISCARDABLE -BEGIN - MENUITEM "&Âåëèê³ ²êîíêè", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ìàë³ ²êîíêè", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Ñïèñîê", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Ïîäðîáèö³", FCIDM_SHVIEW_REPORTVIEW -END - -/* - shellview background menu -*/ -MENU_002 MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - POPUP "&Âèãëÿä" - BEGIN - MENUITEM "&Âåëèê³ ²êîíêè", FCIDM_SHVIEW_BIGICON - MENUITEM "&Ìàë³ ²êîíêè", FCIDM_SHVIEW_SMALLICON - MENUITEM "&Ñïèñîê", FCIDM_SHVIEW_LISTVIEW - MENUITEM "&Ïîäðîáèö³", FCIDM_SHVIEW_REPORTVIEW - END - MENUITEM SEPARATOR - POPUP "Âïîðÿäêóâàòè &²êîíêè" - BEGIN - MENUITEM "Çà &Íàçâîþ", 0x30 /* column 0 */ - MENUITEM "Çà &Òèïîì", 0x32 /* column 2 */ - MENUITEM "Çà &Ðîçì³ðîì", 0x31 /* ... */ - MENUITEM "Çà &Äàòîþ", 0x33 - MENUITEM SEPARATOR - MENUITEM "&Àâòîìàòè÷íî", FCIDM_SHVIEW_AUTOARRANGE - END - MENUITEM "Âèð³âíÿòè ²êîíêè", FCIDM_SHVIEW_SNAPTOGRID - MENUITEM SEPARATOR - MENUITEM "Îíîâèòè", FCIDM_SHVIEW_REFRESH - MENUITEM SEPARATOR - MENUITEM "Âñòàâèòè", FCIDM_SHVIEW_INSERT - MENUITEM "Âñòàâèòè Ïîñèëàííÿ", FCIDM_SHVIEW_INSERTLINK - MENUITEM SEPARATOR - POPUP "Ñòâîðèòè" - BEGIN - MENUITEM "Íîâà &Òåêà", FCIDM_SHVIEW_NEWFOLDER - MENUITEM "Íîâå &Ïîñèëàííÿ", FCIDM_SHVIEW_NEWLINK - MENUITEM SEPARATOR - END - MENUITEM SEPARATOR - MENUITEM "Âëàñòèâîñò³", FCIDM_SHVIEW_PROPERTIES - END -END - -/* - shellview item menu -*/ -MENU_SHV_FILE MENU DISCARDABLE -BEGIN - POPUP "" - BEGIN - MENUITEM "&Ïðîâ³äíèê", FCIDM_SHVIEW_EXPLORE - MENUITEM "&³äêðèòè", FCIDM_SHVIEW_OPEN - MENUITEM SEPARATOR - MENUITEM "Âè&ð³çàòè", FCIDM_SHVIEW_CUT - MENUITEM "&Êîï³ÿ", FCIDM_SHVIEW_COPY - MENUITEM SEPARATOR - MENUITEM "&Ñòâîðèòè Ïîñèëàííÿ", FCIDM_SHVIEW_CREATELINK - MENUITEM "Âè&äàëèòè", FCIDM_SHVIEW_DELETE - MENUITEM "Ïåðå&éìåíóâàòè", FCIDM_SHVIEW_RENAME - MENUITEM SEPARATOR - MENUITEM "&Âëàñòèâîñò³", FCIDM_SHVIEW_PROPERTIES - END -END - -SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK -CAPTION "Îãëÿä äî òåêè" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP - PUSHBUTTON "³äì³íà", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP - LTEXT "", IDD_TITLE, 4, 4, 180, 12 - LTEXT "", IDD_STATUS, 4, 25, 180, 12 - CONTROL "", IDD_TREEVIEW, "SysTreeView32", - TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | - WS_BORDER | WS_TABSTOP, - 4, 40, 180, 120 -} - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Ïðî %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "Ðîçðîáíèêè ReactOS:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Ââåä³òü ³ì'ÿ ïðîãðàìè, òåêè, äîêóìåíòó ÷è ðåñóðñ ²íòåðíåòó, ³ ReactOS â³äêðèº ¿õ.", 12289, 36, 11, 182, 18 - LTEXT "&³äêðèòè:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "³äì³íà", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Îãëÿä...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* - special folders -*/ -STRINGTABLE DISCARDABLE -{ - IDS_DESKTOP "Ñò³ëüíèöÿ" - IDS_MYCOMPUTER "̳é Êîìï'þòåð" -} - -/* - context menus -*/ -STRINGTABLE DISCARDABLE -{ - IDS_VIEW_LARGE "&Âåëèê³ ²êîíêè" - IDS_VIEW_SMALL "&Ìàë³ ²êîíêè" - IDS_VIEW_LIST "&Ñïèñîê" - IDS_VIEW_DETAILS "&Ïîäðîáèö³" - IDS_SELECT "Âè&áðàòè" - IDS_OPEN "³&äêðèòè" -} - -STRINGTABLE DISCARDABLE -{ - IDS_CREATEFOLDER_DENIED "Íå âäàëîñÿ ñòâîðèòè íîâó òåêó: ³äìîâà ó äîñòóï³." - IDS_CREATEFOLDER_CAPTION "Ïîìèëêà ïðè ñòâîðåíí³ íîâî¿ òåêè" - IDS_DELETEITEM_CAPTION "ϳäòâåðäæåííÿ âèëó÷åííÿ ôàéëó" - IDS_DELETEFOLDER_CAPTION "ϳäòâåðäæåííÿ âèëó÷åííÿ òåêè" - IDS_DELETEITEM_TEXT "Âè âïåâíåí³, ùî õî÷åòå âèëó÷èòè '%1'?" - IDS_DELETEMULTIPLE_TEXT "Âè âïåâíåí³, ùî õî÷åòå âèëó÷èòè ö³ %1 åëåìåíòè(³â)?" - IDS_OVERWRITEFILE_TEXT "Ïåðåïèñàòè Ôàéë %1?" - IDS_OVERWRITEFILE_CAPTION "ϳäòâåðäæåííÿ Ïåðåçàïèñó Ôàéëó" -} - -/* columns in the shellview */ -STRINGTABLE -BEGIN - IDS_SHV_COLUMN1 "Ôàéë" - IDS_SHV_COLUMN2 "Ðîçì³ð" - IDS_SHV_COLUMN3 "Òèï" - IDS_SHV_COLUMN4 "Çì³íåíî" - IDS_SHV_COLUMN5 "Àòðèáóòè" - IDS_SHV_COLUMN6 "Ðîçì³ð" - IDS_SHV_COLUMN7 "³ëüíèé Ðîçì³ð" -END +/* + * Copyright 2004 Ilya Korniyko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT + +MENU_001 MENU DISCARDABLE +BEGIN + MENUITEM "&Âåëèê³ ²êîíêè", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ìàë³ ²êîíêè", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Ñïèñîê", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Ïîäðîáèö³", FCIDM_SHVIEW_REPORTVIEW +END + +/* + shellview background menu +*/ +MENU_002 MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&Âèãëÿä" + BEGIN + MENUITEM "&Âåëèê³ ²êîíêè", FCIDM_SHVIEW_BIGICON + MENUITEM "&Ìàë³ ²êîíêè", FCIDM_SHVIEW_SMALLICON + MENUITEM "&Ñïèñîê", FCIDM_SHVIEW_LISTVIEW + MENUITEM "&Ïîäðîáèö³", FCIDM_SHVIEW_REPORTVIEW + END + MENUITEM SEPARATOR + POPUP "Âïîðÿäêóâàòè &²êîíêè" + BEGIN + MENUITEM "Çà &Íàçâîþ", 0x30 /* column 0 */ + MENUITEM "Çà &Òèïîì", 0x32 /* column 2 */ + MENUITEM "Çà &Ðîçì³ðîì", 0x31 /* ... */ + MENUITEM "Çà &Äàòîþ", 0x33 + MENUITEM SEPARATOR + MENUITEM "&Àâòîìàòè÷íî", FCIDM_SHVIEW_AUTOARRANGE + END + MENUITEM "Âèð³âíÿòè ²êîíêè", FCIDM_SHVIEW_SNAPTOGRID + MENUITEM SEPARATOR + MENUITEM "Îíîâèòè", FCIDM_SHVIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "Âñòàâèòè", FCIDM_SHVIEW_INSERT + MENUITEM "Âñòàâèòè Ïîñèëàííÿ", FCIDM_SHVIEW_INSERTLINK + MENUITEM SEPARATOR + POPUP "Ñòâîðèòè" + BEGIN + MENUITEM "Íîâà &Òåêà", FCIDM_SHVIEW_NEWFOLDER + MENUITEM "Íîâå &Ïîñèëàííÿ", FCIDM_SHVIEW_NEWLINK + MENUITEM SEPARATOR + END + MENUITEM SEPARATOR + MENUITEM "Âëàñòèâîñò³", FCIDM_SHVIEW_PROPERTIES + END +END + +/* + shellview item menu +*/ +MENU_SHV_FILE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Ïðîâ³äíèê", FCIDM_SHVIEW_EXPLORE + MENUITEM "&³äêðèòè", FCIDM_SHVIEW_OPEN + MENUITEM SEPARATOR + MENUITEM "Âè&ð³çàòè", FCIDM_SHVIEW_CUT + MENUITEM "&Êîï³ÿ", FCIDM_SHVIEW_COPY + MENUITEM SEPARATOR + MENUITEM "&Ñòâîðèòè Ïîñèëàííÿ", FCIDM_SHVIEW_CREATELINK + MENUITEM "Âè&äàëèòè", FCIDM_SHVIEW_DELETE + MENUITEM "Ïåðå&éìåíóâàòè", FCIDM_SHVIEW_RENAME + MENUITEM SEPARATOR + MENUITEM "&Âëàñòèâîñò³", FCIDM_SHVIEW_PROPERTIES + END +END + +SHBRSFORFOLDER_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 188, 192 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_MODALFRAME | DS_SETFONT | DS_3DLOOK +CAPTION "Îãëÿä äî òåêè" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", 1, 80, 176, 50, 12, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "³äì³íà", 2, 134, 176, 50, 12, WS_GROUP | WS_TABSTOP + LTEXT "", IDD_TITLE, 4, 4, 180, 12 + LTEXT "", IDD_STATUS, 4, 25, 180, 12 + CONTROL "", IDD_TREEVIEW, "SysTreeView32", + TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | + WS_BORDER | WS_TABSTOP, + 4, 40, 180, 120 +} + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Ïðî %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "OK", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "Ðîçðîáíèêè ReactOS:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Ââåä³òü ³ì'ÿ ïðîãðàìè, òåêè, äîêóìåíòó ÷è ðåñóðñ ²íòåðíåòó, ³ ReactOS â³äêðèº ¿õ.", 12289, 36, 11, 182, 18 + LTEXT "&³äêðèòè:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "³äì³íà", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Îãëÿä...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* + special folders +*/ +STRINGTABLE DISCARDABLE +{ + IDS_DESKTOP "Ñò³ëüíèöÿ" + IDS_MYCOMPUTER "̳é Êîìï'þòåð" +} + +/* + context menus +*/ +STRINGTABLE DISCARDABLE +{ + IDS_VIEW_LARGE "&Âåëèê³ ²êîíêè" + IDS_VIEW_SMALL "&Ìàë³ ²êîíêè" + IDS_VIEW_LIST "&Ñïèñîê" + IDS_VIEW_DETAILS "&Ïîäðîáèö³" + IDS_SELECT "Âè&áðàòè" + IDS_OPEN "³&äêðèòè" +} + +STRINGTABLE DISCARDABLE +{ + IDS_CREATEFOLDER_DENIED "Íå âäàëîñÿ ñòâîðèòè íîâó òåêó: ³äìîâà ó äîñòóï³." + IDS_CREATEFOLDER_CAPTION "Ïîìèëêà ïðè ñòâîðåíí³ íîâî¿ òåêè" + IDS_DELETEITEM_CAPTION "ϳäòâåðäæåííÿ âèëó÷åííÿ ôàéëó" + IDS_DELETEFOLDER_CAPTION "ϳäòâåðäæåííÿ âèëó÷åííÿ òåêè" + IDS_DELETEITEM_TEXT "Âè âïåâíåí³, ùî õî÷åòå âèëó÷èòè '%1'?" + IDS_DELETEMULTIPLE_TEXT "Âè âïåâíåí³, ùî õî÷åòå âèëó÷èòè ö³ %1 åëåìåíòè(³â)?" + IDS_OVERWRITEFILE_TEXT "Ïåðåïèñàòè Ôàéë %1?" + IDS_OVERWRITEFILE_CAPTION "ϳäòâåðäæåííÿ Ïåðåçàïèñó Ôàéëó" +} + +/* columns in the shellview */ +STRINGTABLE +BEGIN + IDS_SHV_COLUMN1 "Ôàéë" + IDS_SHV_COLUMN2 "Ðîçì³ð" + IDS_SHV_COLUMN3 "Òèï" + IDS_SHV_COLUMN4 "Çì³íåíî" + IDS_SHV_COLUMN5 "Àòðèáóòè" + IDS_SHV_COLUMN6 "Ðîçì³ð" + IDS_SHV_COLUMN7 "³ëüíèé Ðîçì³ð" +END diff --git a/reactos/lib/shell32/shell32_Wa.rc b/reactos/lib/shell32/shell32_Wa.rc index 3984d4b4abf..3eff061b880 100644 --- a/reactos/lib/shell32/shell32_Wa.rc +++ b/reactos/lib/shell32/shell32_Wa.rc @@ -1,51 +1,51 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_WALON, SUBLANG_DEFAULT - -/* - * Si vos voloz aider avou li ratoûrnaedje des libes programes è walon, - * vos poloz scrîre a l' adresse emile - */ - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Å dfait di %s" -FONT 10, "MS Shell Dlg" -{ - DEFPUSHBUTTON "I Va", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 30, 10, 137, 10 - LTEXT "", 101, 30, 22, 137, 10 - LTEXT "ReactOS a estu fwait par:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_WALON, SUBLANG_DEFAULT + +/* + * Si vos voloz aider avou li ratoûrnaedje des libes programes è walon, + * vos poloz scrîre a l' adresse emile + */ + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Å dfait di %s" +FONT 10, "MS Shell Dlg" +{ + DEFPUSHBUTTON "I Va", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 30, 10, 137, 10 + LTEXT "", 101, 30, 22, 137, 10 + LTEXT "ReactOS a estu fwait par:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} diff --git a/reactos/lib/shell32/shell32_Zh.rc b/reactos/lib/shell32/shell32_Zh.rc index ddd8143f1e1..f6172531aa8 100644 --- a/reactos/lib/shell32/shell32_Zh.rc +++ b/reactos/lib/shell32/shell32_Zh.rc @@ -1,62 +1,62 @@ -/* - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL -#pragma code_page(936) /* FIXME: default for CHINESE_TRADITIONAL is 950 */ - -SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "êPì¶ %s" -FONT 8, "MS Shell Dlg" -{ - DEFPUSHBUTTON "´_¶¨", IDOK, 153, 133, 50, 12, WS_TABSTOP - LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER - ICON "", 1088, 10, 10, 14, 16 - LTEXT "", 100, 35, 10, 137, 10 - LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 -} - -SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "" -FONT 8, "MS Shell Dlg" -{ - ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE - LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 - LTEXT "&Open:", 12305, 7, 39, 24, 10 - CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 - DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP - PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP -} - -/* columns in the shellview */ -STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL -BEGIN - IDS_SHV_COLUMN1 "™n°¸" - IDS_SHV_COLUMN2 "´óС" - IDS_SHV_COLUMN3 "îÐÍ" - IDS_SHV_COLUMN4 "ÒÑÐÞ¸Ä" - IDS_SHV_COLUMN5 "ŒÙÐÔ" - IDS_SHV_COLUMN6 "ʹÓÿÕég" - IDS_SHV_COLUMN7 "Ê£ðN¿Õég" - IDS_SHV_COLUMN8 "Name" /*FIXME*/ - IDS_SHV_COLUMN9 "Comments" /*FIXME*/ -END - -#pragma code_page(default) +/* + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +#pragma code_page(936) /* FIXME: default for CHINESE_TRADITIONAL is 950 */ + +SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "êPì¶ %s" +FONT 8, "MS Shell Dlg" +{ + DEFPUSHBUTTON "´_¶¨", IDOK, 153, 133, 50, 12, WS_TABSTOP + LISTBOX 99, 8, 65, 137, 82, LBS_NOTIFY | WS_VSCROLL | WS_BORDER + ICON "", 1088, 10, 10, 14, 16 + LTEXT "", 100, 35, 10, 137, 10 + LTEXT "ReactOS was brought to you by:", 98, 8, 55, 137, 10 +} + +SHELL_RUN_DLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 227, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "" +FONT 8, "MS Shell Dlg" +{ + ICON "", 12297, 7, 11, 18, 20, WS_VISIBLE + LTEXT "Type the name of a program, folder, document, or Internet resource, and ReactOS will open it for you.", 12289, 36, 11, 182, 18 + LTEXT "&Open:", 12305, 7, 39, 24, 10 + CONTROL "", 12298, "COMBOBOX", WS_TABSTOP | WS_GROUP | WS_VSCROLL | WS_VISIBLE | CBS_DISABLENOSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWN, 36, 37, 183, 100 + DEFPUSHBUTTON "OK", IDOK, 62, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP + PUSHBUTTON "&Browse...", 12288, 170, 63, 50, 14, WS_TABSTOP +} + +/* columns in the shellview */ +STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +BEGIN + IDS_SHV_COLUMN1 "™n°¸" + IDS_SHV_COLUMN2 "´óС" + IDS_SHV_COLUMN3 "îÐÍ" + IDS_SHV_COLUMN4 "ÒÑÐÞ¸Ä" + IDS_SHV_COLUMN5 "ŒÙÐÔ" + IDS_SHV_COLUMN6 "ʹÓÿÕég" + IDS_SHV_COLUMN7 "Ê£ðN¿Õég" + IDS_SHV_COLUMN8 "Name" /*FIXME*/ + IDS_SHV_COLUMN9 "Comments" /*FIXME*/ +END + +#pragma code_page(default) diff --git a/reactos/lib/shell32/shell32_main.c b/reactos/lib/shell32/shell32_main.c index 16ab3d116f1..f107146a5ac 100644 --- a/reactos/lib/shell32/shell32_main.c +++ b/reactos/lib/shell32/shell32_main.c @@ -1,1000 +1,987 @@ -/* - * Shell basics - * - * Copyright 1998 Marcus Meissner - * Copyright 1998 Juergen Schmied (jsch) * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "dlgs.h" -#include "shellapi.h" -#include "winuser.h" -#include "wingdi.h" -#include "shlobj.h" -#include "shlguid.h" -#include "shlwapi.h" - -#include "undocshell.h" -#include "pidl.h" -#include "shell32_main.h" -#include "version.h" - -#include "wine/debug.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -extern const char * const SHELL_Authors[]; - -#define MORE_DEBUG 1 -/************************************************************************* - * CommandLineToArgvW [SHELL32.@] - * - * We must interpret the quotes in the command line to rebuild the argv - * array correctly: - * - arguments are separated by spaces or tabs - * - quotes serve as optional argument delimiters - * '"a b"' -> 'a b' - * - escaped quotes must be converted back to '"' - * '\"' -> '"' - * - an odd number of '\'s followed by '"' correspond to half that number - * of '\' followed by a '"' (extension of the above) - * '\\\"' -> '\"' - * '\\\\\"' -> '\\"' - * - an even number of '\'s followed by a '"' correspond to half that number - * of '\', plus a regular quote serving as an argument delimiter (which - * means it does not appear in the result) - * 'a\\"b c"' -> 'a\b c' - * 'a\\\\"b c"' -> 'a\\b c' - * - '\' that are not followed by a '"' are copied literally - * 'a\b' -> 'a\b' - * 'a\\b' -> 'a\\b' - * - * Note: - * '\t' == 0x0009 - * ' ' == 0x0020 - * '"' == 0x0022 - * '\\' == 0x005c - */ -LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) -{ - DWORD argc; - HGLOBAL hargv; - LPWSTR *argv; - LPCWSTR cs; - LPWSTR arg,s,d; - LPWSTR cmdline; - int in_quotes,bcount; - - if (*lpCmdline==0) { - /* Return the path to the executable */ - DWORD len, size=16; - - hargv=GlobalAlloc(size, 0); - argv=GlobalLock(hargv); - for (;;) { - len = GetModuleFileNameW(0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)); - if (!len) { - GlobalFree(hargv); - return NULL; - } - if (len < size) break; - size*=2; - hargv=GlobalReAlloc(hargv, size, 0); - argv=GlobalLock(hargv); - } - argv[0]=(LPWSTR)(argv+1); - if (numargs) - *numargs=2; - - return argv; - } - - /* to get a writeable copy */ - argc=0; - bcount=0; - in_quotes=0; - cs=lpCmdline; - while (1) { - if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) { - /* space */ - argc++; - /* skip the remaining spaces */ - while (*cs==0x0009 || *cs==0x0020) { - cs++; - } - if (*cs==0) - break; - bcount=0; - continue; - } else if (*cs==0x005c) { - /* '\', count them */ - bcount++; - } else if ((*cs==0x0022) && ((bcount & 1)==0)) { - /* unescaped '"' */ - in_quotes=!in_quotes; - bcount=0; - } else { - /* a regular character */ - bcount=0; - } - cs++; - } - /* Allocate in a single lump, the string array, and the strings that go with it. - * This way the caller can make a single GlobalFree call to free both, as per MSDN. - */ - hargv=GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR)); - argv=GlobalLock(hargv); - if (!argv) - return NULL; - cmdline=(LPWSTR)(argv+argc); - strcpyW(cmdline, lpCmdline); - - argc=0; - bcount=0; - in_quotes=0; - arg=d=s=cmdline; - while (*s) { - if ((*s==0x0009 || *s==0x0020) && !in_quotes) { - /* Close the argument and copy it */ - *d=0; - argv[argc++]=arg; - - /* skip the remaining spaces */ - do { - s++; - } while (*s==0x0009 || *s==0x0020); - - /* Start with a new argument */ - arg=d=s; - bcount=0; - } else if (*s==0x005c) { - /* '\\' */ - *d++=*s++; - bcount++; - } else if (*s==0x0022) { - /* '"' */ - if ((bcount & 1)==0) { - /* Preceeded by an even number of '\', this is half that - * number of '\', plus a quote which we erase. - */ - d-=bcount/2; - in_quotes=!in_quotes; - s++; - } else { - /* Preceeded by an odd number of '\', this is half that - * number of '\' followed by a '"' - */ - d=d-bcount/2-1; - *d++='"'; - s++; - } - bcount=0; - } else { - /* a regular character */ - *d++=*s++; - bcount=0; - } - } - if (*arg) { - *d='\0'; - argv[argc++]=arg; - } - if (numargs) - *numargs=argc; - - return argv; -} - -/************************************************************************* - * SHGetFileInfoA [SHELL32.@] - * - */ - -DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes, - SHFILEINFOW *psfi, UINT sizeofpsfi, - UINT flags ) -{ - WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH]; - int iIndex; - DWORD ret = TRUE, dwAttributes = 0; - IShellFolder * psfParent = NULL; - IExtractIconW * pei = NULL; - LPITEMIDLIST pidlLast = NULL, pidl = NULL; - HRESULT hr = S_OK; - BOOL IconNotYetLoaded=TRUE; - - TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n", - (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags); - - if ((flags & SHGFI_USEFILEATTRIBUTES) && (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL))) - return FALSE; - - /* windows initializes this values regardless of the flags */ - if (psfi != NULL) { - psfi->szDisplayName[0] = '\0'; - psfi->szTypeName[0] = '\0'; - psfi->iIcon = 0; - } - - if (!(flags & SHGFI_PIDL)){ - /* SHGitFileInfo should work with absolute and relative paths */ - if (PathIsRelativeW(path)){ - GetCurrentDirectoryW(MAX_PATH, szLocation); - PathCombineW(szFullPath, szLocation, path); - } else { - lstrcpynW(szFullPath, path, MAX_PATH); - } - } - - if (flags & SHGFI_EXETYPE) { - BOOL status = FALSE; - HANDLE hfile; - DWORD BinaryType; - IMAGE_DOS_HEADER mz_header; - IMAGE_NT_HEADERS nt; - DWORD len; - char magic[4]; - - if (flags != SHGFI_EXETYPE) return 0; - - status = GetBinaryTypeW (szFullPath, &BinaryType); - if (!status) return 0; - if ((BinaryType == SCS_DOS_BINARY) - || (BinaryType == SCS_PIF_BINARY)) return 0x4d5a; - - hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 ); - if ( hfile == INVALID_HANDLE_VALUE ) return 0; - - /* The next section is adapted from MODULE_GetBinaryType, as we need - * to examine the image header to get OS and version information. We - * know from calling GetBinaryTypeA that the image is valid and either - * an NE or PE, so much error handling can be omitted. - * Seek to the start of the file and read the header information. - */ - - SetFilePointer( hfile, 0, NULL, SEEK_SET ); - ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL ); - - SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); - ReadFile( hfile, magic, sizeof(magic), &len, NULL ); - if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE ) - { - SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); - ReadFile( hfile, &nt, sizeof(nt), &len, NULL ); - CloseHandle( hfile ); - if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { - return IMAGE_NT_SIGNATURE - | (nt.OptionalHeader.MajorSubsystemVersion << 24) - | (nt.OptionalHeader.MinorSubsystemVersion << 16); - } - return IMAGE_NT_SIGNATURE; - } - else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE ) - { - IMAGE_OS2_HEADER ne; - SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); - ReadFile( hfile, &ne, sizeof(ne), &len, NULL ); - CloseHandle( hfile ); - if (ne.ne_exetyp == 2) return IMAGE_OS2_SIGNATURE - | (ne.ne_expver << 16); - return 0; - } - CloseHandle( hfile ); - return 0; - } - - /* psfi is NULL normally to query EXE type. If it is NULL, none of the - * below makes sense anyway. Windows allows this and just returns FALSE */ - if (psfi == NULL) return FALSE; - - /* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES - * is not specified. - The pidl functions fail on not existing file names */ - - if (flags & SHGFI_PIDL) { - pidl = ILClone((LPCITEMIDLIST)path); - } else if (!(flags & SHGFI_USEFILEATTRIBUTES)) { - hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes); - } - - if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES)) - { - /* get the parent shellfolder */ - if (pidl) { - hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&pidlLast); - ILFree(pidl); - } else { - ERR("pidl is null!\n"); - return FALSE; - } - } - - /* get the attributes of the child */ - if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES)) - { - if (!(flags & SHGFI_ATTR_SPECIFIED)) - { - psfi->dwAttributes = 0xffffffff; - } - IShellFolder_GetAttributesOf(psfParent, 1, (LPCITEMIDLIST*)&pidlLast, &(psfi->dwAttributes)); - } - - /* get the displayname */ - if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME)) - { - if (flags & SHGFI_USEFILEATTRIBUTES) - { - lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath)); - } - else - { - STRRET str; - hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str); - StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast); - } - } - - /* get the type name */ - if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME)) - { - static const WCHAR szFile[] = { 'F','i','l','e',0 }; - static const WCHAR szDashFile[] = { '-','f','i','l','e',0 }; - if (!(flags & SHGFI_USEFILEATTRIBUTES)) - { - char ftype[80]; - _ILGetFileType(pidlLast, ftype, 80); - MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 ); - } - else - { - if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - strcatW (psfi->szTypeName, szFile); - else - { - WCHAR sTemp[64]; - lstrcpyW(sTemp,PathFindExtensionW(szFullPath)); - if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) - && HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE ))) - { - lstrcpynW (psfi->szTypeName, sTemp, 64); - strcatW (psfi->szTypeName, szDashFile); - } - } - } - } - - /* ### icons ###*/ - if (flags & SHGFI_LINKOVERLAY) - FIXME("set icon to link, stub\n"); - - if (flags & SHGFI_SELECTED) - FIXME("set icon to selected, stub\n"); - - if (flags & SHGFI_SHELLICONSIZE) - FIXME("set icon to shell size, stub\n"); - - /* get the iconlocation */ - if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) - { - UINT uDummy,uFlags; - hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconA, &uDummy, (LPVOID*)&pei); - - if (SUCCEEDED(hr)) - { - hr = IExtractIconW_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLocation, MAX_PATH, &iIndex, &uFlags); - psfi->iIcon = iIndex; - - if(uFlags != GIL_NOTFILENAME) - lstrcpyW (psfi->szDisplayName, szLocation); - else - ret = FALSE; - - IExtractIconA_Release(pei); - } - } - - /* get icon index (or load icon)*/ - if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX))) - { - - if (flags & SHGFI_USEFILEATTRIBUTES) - { - WCHAR sTemp [MAX_PATH]; - WCHAR * szExt; - DWORD dwNr=0; - - lstrcpynW(sTemp, szFullPath, MAX_PATH); - - if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - psfi->iIcon = 2; - else - { - static const WCHAR p1W[] = {'%','1',0}; - psfi->iIcon = 0; - szExt = (LPWSTR) PathFindExtensionW(sTemp); - if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) - && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &dwNr)) - { - if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */ - strcpyW(sTemp, szFullPath); - - if (flags & SHGFI_SYSICONINDEX) - { - psfi->iIcon = SIC_GetIconIndex(sTemp,dwNr); - if (psfi->iIcon == -1) psfi->iIcon = 0; - } - else - { - IconNotYetLoaded=FALSE; - PrivateExtractIconsW(sTemp,dwNr,(flags & SHGFI_SMALLICON) ? - GetSystemMetrics(SM_CXSMICON) : GetSystemMetrics(SM_CXICON), - (flags & SHGFI_SMALLICON) ? GetSystemMetrics(SM_CYSMICON) : - GetSystemMetrics(SM_CYICON), &psfi->hIcon,0,1,0); - psfi->iIcon = dwNr; - } - } - } - } - else - { - if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), - (flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon)))) - { - ret = FALSE; - } - } - if (ret) - { - ret = (DWORD) ((flags & SHGFI_SMALLICON) ? ShellSmallIconList : ShellBigIconList); - } - } - - /* icon handle */ - if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded) - psfi->hIcon = ImageList_GetIcon((flags & SHGFI_SMALLICON) ? ShellSmallIconList:ShellBigIconList, psfi->iIcon, ILD_NORMAL); - - if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3)) - FIXME("unknown attribute!\n"); - - if (psfParent) - IShellFolder_Release(psfParent); - - if (hr != S_OK) - ret = FALSE; - - if(pidlLast) SHFree(pidlLast); -#ifdef MORE_DEBUG - TRACE ("icon=%p index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n", - psfi->hIcon, psfi->iIcon, psfi->dwAttributes, debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret); -#endif - return ret; -} - -/************************************************************************* - * SHGetFileInfoW [SHELL32.@] - */ - -DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes, - SHFILEINFOA *psfi, UINT sizeofpsfi, - UINT flags ) -{ - INT len; - LPWSTR temppath; - DWORD ret; - SHFILEINFOW temppsfi; - - if (flags & SHGFI_PIDL) { - /* path contains a pidl */ - temppath = (LPWSTR) path; - } else { - len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); - temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len); - } - - if(psfi && (flags & SHGFI_ATTR_SPECIFIED)) - temppsfi.dwAttributes=psfi->dwAttributes; - - ret = SHGetFileInfoW(temppath, dwFileAttributes, (psfi == NULL)? NULL : &temppsfi, sizeof(temppsfi), flags); - - if (psfi) - { - if(flags & SHGFI_ICON) - psfi->hIcon=temppsfi.hIcon; - if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION)) - psfi->iIcon=temppsfi.iIcon; - if(flags & SHGFI_ATTRIBUTES) - psfi->dwAttributes=temppsfi.dwAttributes; - if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION)) - WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1, psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL); - if(flags & SHGFI_TYPENAME) - WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1, psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL); - } - if(!(flags & SHGFI_PIDL)) HeapFree(GetProcessHeap(), 0, temppath); - return ret; -} - -/************************************************************************* - * SHGetFileInfo [SHELL32.@] - */ -DWORD WINAPI SHGetFileInfoAW( - LPCVOID path, - DWORD dwFileAttributes, - LPVOID psfi, - UINT sizeofpsfi, - UINT flags) -{ - if(SHELL_OsIsUnicode()) - return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags ); - return SHGetFileInfoA(path, dwFileAttributes, psfi, sizeofpsfi, flags ); -} - -/************************************************************************* - * DuplicateIcon [SHELL32.@] - */ -HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon) -{ - ICONINFO IconInfo; - HICON hDupIcon = 0; - - TRACE("(%p, %p)\n", hInstance, hIcon); - - if(GetIconInfo(hIcon, &IconInfo)) - { - hDupIcon = CreateIconIndirect(&IconInfo); - - /* clean up hbmMask and hbmColor */ - DeleteObject(IconInfo.hbmMask); - DeleteObject(IconInfo.hbmColor); - } - - return hDupIcon; -} - -/************************************************************************* - * ExtractIconA [SHELL32.@] - */ -HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex) -{ - HICON ret; - INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0); - LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - - TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex); - - MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len); - ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex); - HeapFree(GetProcessHeap(), 0, lpwstrFile); - return ret; -} - -/************************************************************************* - * ExtractIconW [SHELL32.@] - */ -HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex) -{ - HICON hIcon = NULL; - UINT ret; - UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON); - - TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex); - - if (nIconIndex == 0xFFFFFFFF) { - ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR); - if (ret != 0xFFFFFFFF && ret) - return (HICON)ret; - return NULL; - } - else - ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR); - - if (ret == 0xFFFFFFFF) - return (HICON)1; - else if (ret > 0 && hIcon) - return hIcon; - return NULL; -} - -typedef struct -{ - LPCWSTR szApp; - LPCWSTR szOtherStuff; - HICON hIcon; - HFONT hFont; -} ABOUT_INFO; - -#define IDC_STATIC_TEXT1 100 -#define IDC_STATIC_TEXT2 101 -#define IDC_LISTBOX 99 -#define IDC_WINE_TEXT 98 - -#define DROP_FIELD_TOP (-15) -#define DROP_FIELD_HEIGHT 15 - -static BOOL __get_dropline( HWND hWnd, LPRECT lprect ) -{ HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT); - if( hWndCtl ) - { GetWindowRect( hWndCtl, lprect ); - MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 ); - lprect->bottom = (lprect->top += DROP_FIELD_TOP); - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * SHAppBarMessage [SHELL32.@] - */ -UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data) -{ - int width=data->rc.right - data->rc.left; - int height=data->rc.bottom - data->rc.top; - RECT rec=data->rc; - switch (msg) - { case ABM_GETSTATE: - return ABS_ALWAYSONTOP | ABS_AUTOHIDE; - case ABM_GETTASKBARPOS: - GetWindowRect(data->hWnd, &rec); - data->rc=rec; - return TRUE; - case ABM_ACTIVATE: - SetActiveWindow(data->hWnd); - return TRUE; - case ABM_GETAUTOHIDEBAR: - data->hWnd=GetActiveWindow(); - return TRUE; - case ABM_NEW: - SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top, - width,height,SWP_SHOWWINDOW); - return TRUE; - case ABM_QUERYPOS: - GetWindowRect(data->hWnd, &(data->rc)); - return TRUE; - case ABM_REMOVE: - FIXME("ABM_REMOVE broken\n"); - /* FIXME: this is wrong; should it be DestroyWindow instead? */ - /*CloseHandle(data->hWnd);*/ - return TRUE; - case ABM_SETAUTOHIDEBAR: - SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top, - width,height,SWP_SHOWWINDOW); - return TRUE; - case ABM_SETPOS: - data->uEdge=(ABE_RIGHT | ABE_LEFT); - SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top, - width,height,SWP_SHOWWINDOW); - return TRUE; - case ABM_WINDOWPOSCHANGED: - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * SHHelpShortcuts_RunDLL [SHELL32.@] - * - */ -DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4) -{ FIXME("(%lx, %lx, %lx, %lx) empty stub!\n", - dwArg1, dwArg2, dwArg3, dwArg4); - - return 0; -} - -/************************************************************************* - * SHLoadInProc [SHELL32.@] - * Create an instance of specified object class from within - * the shell process and release it immediately - */ - -HRESULT WINAPI SHLoadInProc (REFCLSID rclsid) -{ - void *ptr = NULL; - - TRACE("%s\n", debugstr_guid(rclsid)); - - CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr); - if(ptr) - { - IUnknown * pUnk = ptr; - IUnknown_Release(pUnk); - return NOERROR; - } - return DISP_E_MEMBERNOTFOUND; -} - -/************************************************************************* - * AboutDlgProc (internal) - */ -INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam ) -{ - HWND hWndCtl; - - TRACE("\n"); - - switch(msg) - { - case WM_INITDIALOG: - { - ABOUT_INFO *info = (ABOUT_INFO *)lParam; - WCHAR Template[512], AppTitle[512]; - - if (info) - { - const char* const *pstr = SHELL_Authors; - SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0); - GetWindowTextW( hWnd, Template, sizeof(Template)/sizeof(WCHAR) ); - sprintfW( AppTitle, Template, info->szApp ); - SetWindowTextW( hWnd, AppTitle ); - SetWindowTextW( GetDlgItem(hWnd, IDC_STATIC_TEXT1), info->szApp ); - SetWindowTextW( GetDlgItem(hWnd, IDC_STATIC_TEXT2), info->szOtherStuff ); - hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX); - SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 ); - SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 ); - while (*pstr) - { - WCHAR name[64]; - /* authors list is in iso-8859-1 format */ - MultiByteToWideChar( 28591, 0, *pstr, -1, name, sizeof(name)/sizeof(WCHAR) ); - SendMessageW( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)name ); - pstr++; - } - SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 ); - } - } - return 1; - - case WM_PAINT: - { RECT rect; - PAINTSTRUCT ps; - HDC hDC = BeginPaint( hWnd, &ps ); - - if( __get_dropline( hWnd, &rect ) ) { - SelectObject( hDC, GetStockObject( BLACK_PEN ) ); - MoveToEx( hDC, rect.left, rect.top, NULL ); - LineTo( hDC, rect.right, rect.bottom ); - } - EndPaint( hWnd, &ps ); - } - break; - - case WM_COMMAND: - if (wParam == IDOK || wParam == IDCANCEL) - { - EndDialog(hWnd, TRUE); - return TRUE; - } - break; - case WM_CLOSE: - EndDialog(hWnd, TRUE); - break; - } - - return 0; -} - - -/************************************************************************* - * ShellAboutA [SHELL32.288] - */ -BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon ) -{ - BOOL ret; - LPWSTR appW = NULL, otherW = NULL; - int len; - - if (szApp) - { - len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0); - appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len); - } - if (szOtherStuff) - { - len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0); - otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len); - } - - ret = ShellAboutW(hWnd, appW, otherW, hIcon); - - if (otherW) HeapFree(GetProcessHeap(), 0, otherW); - if (appW) HeapFree(GetProcessHeap(), 0, appW); - return ret; -} - - -/************************************************************************* - * ShellAboutW [SHELL32.289] - */ -BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff, - HICON hIcon ) -{ - ABOUT_INFO info; - LOGFONTW logFont; - HRSRC hRes; - LPVOID template; - BOOL bRet; - - TRACE("\n"); - - if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", (LPSTR)RT_DIALOG))) - return FALSE; - if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes))) - return FALSE; - info.szApp = szApp; - info.szOtherStuff = szOtherStuff; - info.hIcon = hIcon ? hIcon : LoadIconW( 0, (LPWSTR)IDI_WINLOGO ); - - SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 ); - info.hFont = CreateFontIndirectW( &logFont ); - - bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ), - template, hWnd, AboutDlgProc, (LPARAM)&info ); - DeleteObject(info.hFont); - return bRet; -} - -/************************************************************************* - * FreeIconList (SHELL32.@) - */ -void WINAPI FreeIconList( DWORD dw ) -{ FIXME("(%lx): stub\n",dw); -} - - -/************************************************************************* - * ShellDDEInit (SHELL32.@) - */ -void WINAPI ShellDDEInit(BOOL start) -{ - FIXME("stub: %d\n", start); -} - -/*********************************************************************** - * DllGetVersion [SHELL32.@] - * - * Retrieves version information of the 'SHELL32.DLL' - * - * PARAMS - * pdvi [O] pointer to version information structure. - * - * RETURNS - * Success: S_OK - * Failure: E_INVALIDARG - * - * NOTES - * Returns version of a shell32.dll from IE4.01 SP1. - */ - -HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi) -{ - /* FIXME: shouldn't these values come from the version resource? */ - if (pdvi->cbSize == sizeof(DLLVERSIONINFO) || - pdvi->cbSize == sizeof(DLLVERSIONINFO2)) - { - pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR; - pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR; - pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD; - pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID; - if (pdvi->cbSize == sizeof(DLLVERSIONINFO2)) - { - DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi; - - pdvi2->dwFlags = 0; - pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR, - WINE_FILEVERSION_MINOR, - WINE_FILEVERSION_BUILD, - WINE_FILEVERSION_PLATFORMID); - } - TRACE("%lu.%lu.%lu.%lu\n", - pdvi->dwMajorVersion, pdvi->dwMinorVersion, - pdvi->dwBuildNumber, pdvi->dwPlatformID); - return S_OK; - } - else - { - WARN("wrong DLLVERSIONINFO size from app\n"); - return E_INVALIDARG; - } -} -/************************************************************************* - * global variables of the shell32.dll - * all are once per process - * - */ -HINSTANCE shell32_hInstance = 0; -HIMAGELIST ShellSmallIconList = 0; -HIMAGELIST ShellBigIconList = 0; - - -/************************************************************************* - * SHELL32 DllMain - * - * NOTES - * calling oleinitialize here breaks sone apps. - */ - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) -{ - TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); - - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - shell32_hInstance = hinstDLL; - DisableThreadLibraryCalls(shell32_hInstance); - - /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */ - GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH); - swShell32Name[MAX_PATH - 1] = '\0'; - - InitCommonControlsEx(NULL); - - SIC_Initialize(); - InitChangeNotifications(); - break; - - case DLL_PROCESS_DETACH: - shell32_hInstance = 0; - SIC_Destroy(); - FreeChangeNotifications(); - break; - } - return TRUE; -} - -/************************************************************************* - * DllInstall [SHELL32.@] - * - * PARAMETERS - * - * BOOL bInstall - TRUE for install, FALSE for uninstall - * LPCWSTR pszCmdLine - command line (unused by shell32?) - */ - -HRESULT WINAPI SHELL32_DllInstall(BOOL bInstall, LPCWSTR cmdline) -{ - FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline)); - - return S_OK; /* indicate success */ -} - -/*********************************************************************** - * DllCanUnloadNow (SHELL32.@) - */ -HRESULT WINAPI SHELL32_DllCanUnloadNow(void) -{ - FIXME("(void): stub\n"); - - return S_FALSE; -} +/* + * Shell basics + * + * Copyright 1998 Marcus Meissner + * Copyright 1998 Juergen Schmied (jsch) * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" +#include "dlgs.h" +#include "shellapi.h" +#include "winuser.h" +#include "wingdi.h" +#include "shlobj.h" +#include "shlguid.h" +#include "shlwapi.h" + +#include "undocshell.h" +#include "pidl.h" +#include "shell32_main.h" +#include "version.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +extern const char * const SHELL_Authors[]; + +#define MORE_DEBUG 1 +/************************************************************************* + * CommandLineToArgvW [SHELL32.@] + * + * We must interpret the quotes in the command line to rebuild the argv + * array correctly: + * - arguments are separated by spaces or tabs + * - quotes serve as optional argument delimiters + * '"a b"' -> 'a b' + * - escaped quotes must be converted back to '"' + * '\"' -> '"' + * - an odd number of '\'s followed by '"' correspond to half that number + * of '\' followed by a '"' (extension of the above) + * '\\\"' -> '\"' + * '\\\\\"' -> '\\"' + * - an even number of '\'s followed by a '"' correspond to half that number + * of '\', plus a regular quote serving as an argument delimiter (which + * means it does not appear in the result) + * 'a\\"b c"' -> 'a\b c' + * 'a\\\\"b c"' -> 'a\\b c' + * - '\' that are not followed by a '"' are copied literally + * 'a\b' -> 'a\b' + * 'a\\b' -> 'a\\b' + * + * Note: + * '\t' == 0x0009 + * ' ' == 0x0020 + * '"' == 0x0022 + * '\\' == 0x005c + */ +LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) +{ + DWORD argc; + HGLOBAL hargv; + LPWSTR *argv; + LPCWSTR cs; + LPWSTR arg,s,d; + LPWSTR cmdline; + int in_quotes,bcount; + + if (*lpCmdline==0) { + /* Return the path to the executable */ + DWORD len, size=16; + + hargv=GlobalAlloc(size, 0); + argv=GlobalLock(hargv); + for (;;) { + len = GetModuleFileNameW(0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)); + if (!len) { + GlobalFree(hargv); + return NULL; + } + if (len < size) break; + size*=2; + hargv=GlobalReAlloc(hargv, size, 0); + argv=GlobalLock(hargv); + } + argv[0]=(LPWSTR)(argv+1); + if (numargs) + *numargs=2; + + return argv; + } + + /* to get a writeable copy */ + argc=0; + bcount=0; + in_quotes=0; + cs=lpCmdline; + while (1) { + if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) { + /* space */ + argc++; + /* skip the remaining spaces */ + while (*cs==0x0009 || *cs==0x0020) { + cs++; + } + if (*cs==0) + break; + bcount=0; + continue; + } else if (*cs==0x005c) { + /* '\', count them */ + bcount++; + } else if ((*cs==0x0022) && ((bcount & 1)==0)) { + /* unescaped '"' */ + in_quotes=!in_quotes; + bcount=0; + } else { + /* a regular character */ + bcount=0; + } + cs++; + } + /* Allocate in a single lump, the string array, and the strings that go with it. + * This way the caller can make a single GlobalFree call to free both, as per MSDN. + */ + hargv=GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR)); + argv=GlobalLock(hargv); + if (!argv) + return NULL; + cmdline=(LPWSTR)(argv+argc); + strcpyW(cmdline, lpCmdline); + + argc=0; + bcount=0; + in_quotes=0; + arg=d=s=cmdline; + while (*s) { + if ((*s==0x0009 || *s==0x0020) && !in_quotes) { + /* Close the argument and copy it */ + *d=0; + argv[argc++]=arg; + + /* skip the remaining spaces */ + do { + s++; + } while (*s==0x0009 || *s==0x0020); + + /* Start with a new argument */ + arg=d=s; + bcount=0; + } else if (*s==0x005c) { + /* '\\' */ + *d++=*s++; + bcount++; + } else if (*s==0x0022) { + /* '"' */ + if ((bcount & 1)==0) { + /* Preceeded by an even number of '\', this is half that + * number of '\', plus a quote which we erase. + */ + d-=bcount/2; + in_quotes=!in_quotes; + s++; + } else { + /* Preceeded by an odd number of '\', this is half that + * number of '\' followed by a '"' + */ + d=d-bcount/2-1; + *d++='"'; + s++; + } + bcount=0; + } else { + /* a regular character */ + *d++=*s++; + bcount=0; + } + } + if (*arg) { + *d='\0'; + argv[argc++]=arg; + } + if (numargs) + *numargs=argc; + + return argv; +} + +/************************************************************************* + * SHGetFileInfoA [SHELL32.@] + * + */ + +DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes, + SHFILEINFOW *psfi, UINT sizeofpsfi, + UINT flags ) +{ + WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH]; + int iIndex; + DWORD ret = TRUE, dwAttributes = 0; + IShellFolder * psfParent = NULL; + IExtractIconW * pei = NULL; + LPITEMIDLIST pidlLast = NULL, pidl = NULL; + HRESULT hr = S_OK; + BOOL IconNotYetLoaded=TRUE; + + TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n", + (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags); + + if ((flags & SHGFI_USEFILEATTRIBUTES) && (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL))) + return FALSE; + + /* windows initializes this values regardless of the flags */ + if (psfi != NULL) { + psfi->szDisplayName[0] = '\0'; + psfi->szTypeName[0] = '\0'; + psfi->iIcon = 0; + } + + if (!(flags & SHGFI_PIDL)){ + /* SHGitFileInfo should work with absolute and relative paths */ + if (PathIsRelativeW(path)){ + GetCurrentDirectoryW(MAX_PATH, szLocation); + PathCombineW(szFullPath, szLocation, path); + } else { + lstrcpynW(szFullPath, path, MAX_PATH); + } + } + + if (flags & SHGFI_EXETYPE) { + BOOL status = FALSE; + HANDLE hfile; + DWORD BinaryType; + IMAGE_DOS_HEADER mz_header; + IMAGE_NT_HEADERS nt; + DWORD len; + char magic[4]; + + if (flags != SHGFI_EXETYPE) return 0; + + status = GetBinaryTypeW (szFullPath, &BinaryType); + if (!status) return 0; + if ((BinaryType == SCS_DOS_BINARY) + || (BinaryType == SCS_PIF_BINARY)) return 0x4d5a; + + hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 ); + if ( hfile == INVALID_HANDLE_VALUE ) return 0; + + /* The next section is adapted from MODULE_GetBinaryType, as we need + * to examine the image header to get OS and version information. We + * know from calling GetBinaryTypeA that the image is valid and either + * an NE or PE, so much error handling can be omitted. + * Seek to the start of the file and read the header information. + */ + + SetFilePointer( hfile, 0, NULL, SEEK_SET ); + ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL ); + + SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); + ReadFile( hfile, magic, sizeof(magic), &len, NULL ); + if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE ) + { + SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); + ReadFile( hfile, &nt, sizeof(nt), &len, NULL ); + CloseHandle( hfile ); + if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { + return IMAGE_NT_SIGNATURE + | (nt.OptionalHeader.MajorSubsystemVersion << 24) + | (nt.OptionalHeader.MinorSubsystemVersion << 16); + } + return IMAGE_NT_SIGNATURE; + } + else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE ) + { + IMAGE_OS2_HEADER ne; + SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); + ReadFile( hfile, &ne, sizeof(ne), &len, NULL ); + CloseHandle( hfile ); + if (ne.ne_exetyp == 2) return IMAGE_OS2_SIGNATURE + | (ne.ne_expver << 16); + return 0; + } + CloseHandle( hfile ); + return 0; + } + + /* psfi is NULL normally to query EXE type. If it is NULL, none of the + * below makes sense anyway. Windows allows this and just returns FALSE */ + if (psfi == NULL) return FALSE; + + /* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES + * is not specified. + The pidl functions fail on not existing file names */ + + if (flags & SHGFI_PIDL) { + pidl = ILClone((LPCITEMIDLIST)path); + } else if (!(flags & SHGFI_USEFILEATTRIBUTES)) { + hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes); + } + + if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES)) + { + /* get the parent shellfolder */ + if (pidl) { + hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&pidlLast); + ILFree(pidl); + } else { + ERR("pidl is null!\n"); + return FALSE; + } + } + + /* get the attributes of the child */ + if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES)) + { + if (!(flags & SHGFI_ATTR_SPECIFIED)) + { + psfi->dwAttributes = 0xffffffff; + } + IShellFolder_GetAttributesOf(psfParent, 1, (LPCITEMIDLIST*)&pidlLast, &(psfi->dwAttributes)); + } + + /* get the displayname */ + if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME)) + { + if (flags & SHGFI_USEFILEATTRIBUTES) + { + lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath)); + } + else + { + STRRET str; + hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str); + StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast); + } + } + + /* get the type name */ + if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME)) + { + static const WCHAR szFile[] = { 'F','i','l','e',0 }; + static const WCHAR szDashFile[] = { '-','f','i','l','e',0 }; + if (!(flags & SHGFI_USEFILEATTRIBUTES)) + { + char ftype[80]; + _ILGetFileType(pidlLast, ftype, 80); + MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 ); + } + else + { + if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + strcatW (psfi->szTypeName, szFile); + else + { + WCHAR sTemp[64]; + lstrcpyW(sTemp,PathFindExtensionW(szFullPath)); + if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) + && HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE ))) + { + lstrcpynW (psfi->szTypeName, sTemp, 64); + strcatW (psfi->szTypeName, szDashFile); + } + } + } + } + + /* ### icons ###*/ + if (flags & SHGFI_LINKOVERLAY) + FIXME("set icon to link, stub\n"); + + if (flags & SHGFI_SELECTED) + FIXME("set icon to selected, stub\n"); + + if (flags & SHGFI_SHELLICONSIZE) + FIXME("set icon to shell size, stub\n"); + + /* get the iconlocation */ + if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) + { + UINT uDummy,uFlags; + hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconA, &uDummy, (LPVOID*)&pei); + + if (SUCCEEDED(hr)) + { + hr = IExtractIconW_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLocation, MAX_PATH, &iIndex, &uFlags); + psfi->iIcon = iIndex; + + if(uFlags != GIL_NOTFILENAME) + lstrcpyW (psfi->szDisplayName, szLocation); + else + ret = FALSE; + + IExtractIconA_Release(pei); + } + } + + /* get icon index (or load icon)*/ + if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX))) + { + + if (flags & SHGFI_USEFILEATTRIBUTES) + { + WCHAR sTemp [MAX_PATH]; + WCHAR * szExt; + DWORD dwNr=0; + + lstrcpynW(sTemp, szFullPath, MAX_PATH); + + if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + psfi->iIcon = 2; + else + { + static const WCHAR p1W[] = {'%','1',0}; + psfi->iIcon = 0; + szExt = (LPWSTR) PathFindExtensionW(sTemp); + if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) + && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &dwNr)) + { + if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */ + strcpyW(sTemp, szFullPath); + + if (flags & SHGFI_SYSICONINDEX) + { + psfi->iIcon = SIC_GetIconIndex(sTemp,dwNr); + if (psfi->iIcon == -1) psfi->iIcon = 0; + } + else + { + IconNotYetLoaded=FALSE; + PrivateExtractIconsW(sTemp,dwNr,(flags & SHGFI_SMALLICON) ? + GetSystemMetrics(SM_CXSMICON) : GetSystemMetrics(SM_CXICON), + (flags & SHGFI_SMALLICON) ? GetSystemMetrics(SM_CYSMICON) : + GetSystemMetrics(SM_CYICON), &psfi->hIcon,0,1,0); + psfi->iIcon = dwNr; + } + } + } + } + else + { + if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), + (flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon)))) + { + ret = FALSE; + } + } + if (ret) + { + ret = (DWORD) ((flags & SHGFI_SMALLICON) ? ShellSmallIconList : ShellBigIconList); + } + } + + /* icon handle */ + if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded) + psfi->hIcon = ImageList_GetIcon((flags & SHGFI_SMALLICON) ? ShellSmallIconList:ShellBigIconList, psfi->iIcon, ILD_NORMAL); + + if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3)) + FIXME("unknown attribute!\n"); + + if (psfParent) + IShellFolder_Release(psfParent); + + if (hr != S_OK) + ret = FALSE; + + if(pidlLast) SHFree(pidlLast); +#ifdef MORE_DEBUG + TRACE ("icon=%p index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n", + psfi->hIcon, psfi->iIcon, psfi->dwAttributes, debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret); +#endif + return ret; +} + +/************************************************************************* + * SHGetFileInfoW [SHELL32.@] + */ + +DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes, + SHFILEINFOA *psfi, UINT sizeofpsfi, + UINT flags ) +{ + INT len; + LPWSTR temppath; + DWORD ret; + SHFILEINFOW temppsfi; + + if (flags & SHGFI_PIDL) { + /* path contains a pidl */ + temppath = (LPWSTR) path; + } else { + len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); + temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len); + } + + if(psfi && (flags & SHGFI_ATTR_SPECIFIED)) + temppsfi.dwAttributes=psfi->dwAttributes; + + ret = SHGetFileInfoW(temppath, dwFileAttributes, (psfi == NULL)? NULL : &temppsfi, sizeof(temppsfi), flags); + + if (psfi) + { + if(flags & SHGFI_ICON) + psfi->hIcon=temppsfi.hIcon; + if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION)) + psfi->iIcon=temppsfi.iIcon; + if(flags & SHGFI_ATTRIBUTES) + psfi->dwAttributes=temppsfi.dwAttributes; + if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION)) + WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1, psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL); + if(flags & SHGFI_TYPENAME) + WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1, psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL); + } + if(!(flags & SHGFI_PIDL)) HeapFree(GetProcessHeap(), 0, temppath); + return ret; +} + +/************************************************************************* + * DuplicateIcon [SHELL32.@] + */ +HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon) +{ + ICONINFO IconInfo; + HICON hDupIcon = 0; + + TRACE("(%p, %p)\n", hInstance, hIcon); + + if(GetIconInfo(hIcon, &IconInfo)) + { + hDupIcon = CreateIconIndirect(&IconInfo); + + /* clean up hbmMask and hbmColor */ + DeleteObject(IconInfo.hbmMask); + DeleteObject(IconInfo.hbmColor); + } + + return hDupIcon; +} + +/************************************************************************* + * ExtractIconA [SHELL32.@] + */ +HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex) +{ + HICON ret; + INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0); + LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex); + + MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len); + ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex); + HeapFree(GetProcessHeap(), 0, lpwstrFile); + return ret; +} + +/************************************************************************* + * ExtractIconW [SHELL32.@] + */ +HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex) +{ + HICON hIcon = NULL; + UINT ret; + UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON); + + TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex); + + if (nIconIndex == 0xFFFFFFFF) { + ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR); + if (ret != 0xFFFFFFFF && ret) + return (HICON)ret; + return NULL; + } + else + ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR); + + if (ret == 0xFFFFFFFF) + return (HICON)1; + else if (ret > 0 && hIcon) + return hIcon; + return NULL; +} + +typedef struct +{ + LPCWSTR szApp; + LPCWSTR szOtherStuff; + HICON hIcon; + HFONT hFont; +} ABOUT_INFO; + +#define IDC_STATIC_TEXT1 100 +#define IDC_STATIC_TEXT2 101 +#define IDC_LISTBOX 99 +#define IDC_WINE_TEXT 98 + +#define DROP_FIELD_TOP (-15) +#define DROP_FIELD_HEIGHT 15 + +static BOOL __get_dropline( HWND hWnd, LPRECT lprect ) +{ HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT); + if( hWndCtl ) + { GetWindowRect( hWndCtl, lprect ); + MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 ); + lprect->bottom = (lprect->top += DROP_FIELD_TOP); + return TRUE; + } + return FALSE; +} + +/************************************************************************* + * SHAppBarMessage [SHELL32.@] + */ +UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data) +{ + int width=data->rc.right - data->rc.left; + int height=data->rc.bottom - data->rc.top; + RECT rec=data->rc; + switch (msg) + { case ABM_GETSTATE: + return ABS_ALWAYSONTOP | ABS_AUTOHIDE; + case ABM_GETTASKBARPOS: + GetWindowRect(data->hWnd, &rec); + data->rc=rec; + return TRUE; + case ABM_ACTIVATE: + SetActiveWindow(data->hWnd); + return TRUE; + case ABM_GETAUTOHIDEBAR: + data->hWnd=GetActiveWindow(); + return TRUE; + case ABM_NEW: + SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top, + width,height,SWP_SHOWWINDOW); + return TRUE; + case ABM_QUERYPOS: + GetWindowRect(data->hWnd, &(data->rc)); + return TRUE; + case ABM_REMOVE: + FIXME("ABM_REMOVE broken\n"); + /* FIXME: this is wrong; should it be DestroyWindow instead? */ + /*CloseHandle(data->hWnd);*/ + return TRUE; + case ABM_SETAUTOHIDEBAR: + SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top, + width,height,SWP_SHOWWINDOW); + return TRUE; + case ABM_SETPOS: + data->uEdge=(ABE_RIGHT | ABE_LEFT); + SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top, + width,height,SWP_SHOWWINDOW); + return TRUE; + case ABM_WINDOWPOSCHANGED: + return TRUE; + } + return FALSE; +} + +/************************************************************************* + * SHHelpShortcuts_RunDLL [SHELL32.@] + * + */ +DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4) +{ FIXME("(%lx, %lx, %lx, %lx) empty stub!\n", + dwArg1, dwArg2, dwArg3, dwArg4); + + return 0; +} + +/************************************************************************* + * SHLoadInProc [SHELL32.@] + * Create an instance of specified object class from within + * the shell process and release it immediately + */ + +HRESULT WINAPI SHLoadInProc (REFCLSID rclsid) +{ + void *ptr = NULL; + + TRACE("%s\n", debugstr_guid(rclsid)); + + CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr); + if(ptr) + { + IUnknown * pUnk = ptr; + IUnknown_Release(pUnk); + return NOERROR; + } + return DISP_E_MEMBERNOTFOUND; +} + +/************************************************************************* + * AboutDlgProc (internal) + */ +INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam ) +{ + HWND hWndCtl; + + TRACE("\n"); + + switch(msg) + { + case WM_INITDIALOG: + { + ABOUT_INFO *info = (ABOUT_INFO *)lParam; + WCHAR Template[512], AppTitle[512]; + + if (info) + { + const char* const *pstr = SHELL_Authors; + SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0); + GetWindowTextW( hWnd, Template, sizeof(Template)/sizeof(WCHAR) ); + sprintfW( AppTitle, Template, info->szApp ); + SetWindowTextW( hWnd, AppTitle ); + SetWindowTextW( GetDlgItem(hWnd, IDC_STATIC_TEXT1), info->szApp ); + SetWindowTextW( GetDlgItem(hWnd, IDC_STATIC_TEXT2), info->szOtherStuff ); + hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX); + SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 ); + SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 ); + while (*pstr) + { + WCHAR name[64]; + /* authors list is in iso-8859-1 format */ + MultiByteToWideChar( 28591, 0, *pstr, -1, name, sizeof(name)/sizeof(WCHAR) ); + SendMessageW( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)name ); + pstr++; + } + SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 ); + } + } + return 1; + + case WM_PAINT: + { RECT rect; + PAINTSTRUCT ps; + HDC hDC = BeginPaint( hWnd, &ps ); + + if( __get_dropline( hWnd, &rect ) ) { + SelectObject( hDC, GetStockObject( BLACK_PEN ) ); + MoveToEx( hDC, rect.left, rect.top, NULL ); + LineTo( hDC, rect.right, rect.bottom ); + } + EndPaint( hWnd, &ps ); + } + break; + + case WM_COMMAND: + if (wParam == IDOK || wParam == IDCANCEL) + { + EndDialog(hWnd, TRUE); + return TRUE; + } + break; + case WM_CLOSE: + EndDialog(hWnd, TRUE); + break; + } + + return 0; +} + + +/************************************************************************* + * ShellAboutA [SHELL32.288] + */ +BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon ) +{ + BOOL ret; + LPWSTR appW = NULL, otherW = NULL; + int len; + + if (szApp) + { + len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0); + appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len); + } + if (szOtherStuff) + { + len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0); + otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len); + } + + ret = ShellAboutW(hWnd, appW, otherW, hIcon); + + HeapFree(GetProcessHeap(), 0, otherW); + HeapFree(GetProcessHeap(), 0, appW); + return ret; +} + + +/************************************************************************* + * ShellAboutW [SHELL32.289] + */ +BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff, + HICON hIcon ) +{ + ABOUT_INFO info; + LOGFONTW logFont; + HRSRC hRes; + LPVOID template; + BOOL bRet; + static const WCHAR wszSHELL_ABOUT_MSGBOX[] = + {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0}; + + TRACE("\n"); + + if(!(hRes = FindResourceW(shell32_hInstance, wszSHELL_ABOUT_MSGBOX, (LPWSTR)RT_DIALOG))) + return FALSE; + if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes))) + return FALSE; + info.szApp = szApp; + info.szOtherStuff = szOtherStuff; + info.hIcon = hIcon ? hIcon : LoadIconW( 0, (LPWSTR)IDI_WINLOGO ); + + SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 ); + info.hFont = CreateFontIndirectW( &logFont ); + + bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ), + template, hWnd, AboutDlgProc, (LPARAM)&info ); + DeleteObject(info.hFont); + return bRet; +} + +/************************************************************************* + * FreeIconList (SHELL32.@) + */ +void WINAPI FreeIconList( DWORD dw ) +{ FIXME("(%lx): stub\n",dw); +} + + +/************************************************************************* + * ShellDDEInit (SHELL32.@) + */ +void WINAPI ShellDDEInit(BOOL start) +{ + FIXME("stub: %d\n", start); +} + +/*********************************************************************** + * DllGetVersion [SHELL32.@] + * + * Retrieves version information of the 'SHELL32.DLL' + * + * PARAMS + * pdvi [O] pointer to version information structure. + * + * RETURNS + * Success: S_OK + * Failure: E_INVALIDARG + * + * NOTES + * Returns version of a shell32.dll from IE4.01 SP1. + */ + +HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi) +{ + /* FIXME: shouldn't these values come from the version resource? */ + if (pdvi->cbSize == sizeof(DLLVERSIONINFO) || + pdvi->cbSize == sizeof(DLLVERSIONINFO2)) + { + pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR; + pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR; + pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD; + pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID; + if (pdvi->cbSize == sizeof(DLLVERSIONINFO2)) + { + DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi; + + pdvi2->dwFlags = 0; + pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR, + WINE_FILEVERSION_MINOR, + WINE_FILEVERSION_BUILD, + WINE_FILEVERSION_PLATFORMID); + } + TRACE("%lu.%lu.%lu.%lu\n", + pdvi->dwMajorVersion, pdvi->dwMinorVersion, + pdvi->dwBuildNumber, pdvi->dwPlatformID); + return S_OK; + } + else + { + WARN("wrong DLLVERSIONINFO size from app\n"); + return E_INVALIDARG; + } +} +/************************************************************************* + * global variables of the shell32.dll + * all are once per process + * + */ +HINSTANCE shell32_hInstance = 0; +HIMAGELIST ShellSmallIconList = 0; +HIMAGELIST ShellBigIconList = 0; + + +/************************************************************************* + * SHELL32 DllMain + * + * NOTES + * calling oleinitialize here breaks sone apps. + */ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + shell32_hInstance = hinstDLL; + DisableThreadLibraryCalls(shell32_hInstance); + + /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */ + GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH); + swShell32Name[MAX_PATH - 1] = '\0'; + + InitCommonControlsEx(NULL); + + SIC_Initialize(); + InitChangeNotifications(); + break; + + case DLL_PROCESS_DETACH: + shell32_hInstance = 0; + SIC_Destroy(); + FreeChangeNotifications(); + break; + } + return TRUE; +} + +/************************************************************************* + * DllInstall [SHELL32.@] + * + * PARAMETERS + * + * BOOL bInstall - TRUE for install, FALSE for uninstall + * LPCWSTR pszCmdLine - command line (unused by shell32?) + */ + +HRESULT WINAPI SHELL32_DllInstall(BOOL bInstall, LPCWSTR cmdline) +{ + FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline)); + + return S_OK; /* indicate success */ +} + +/*********************************************************************** + * DllCanUnloadNow (SHELL32.@) + */ +HRESULT WINAPI SHELL32_DllCanUnloadNow(void) +{ + FIXME("(void): stub\n"); + + return S_FALSE; +} diff --git a/reactos/lib/shell32/shell32_main.h b/reactos/lib/shell32/shell32_main.h index 378c621e408..f2e013e613d 100644 --- a/reactos/lib/shell32/shell32_main.h +++ b/reactos/lib/shell32/shell32_main.h @@ -1,226 +1,226 @@ -/* - * internal Shell32 Library definitions - * - * Copyright 1998 Marcus Meissner - * Copyright 1998 Juergen Schmied (jsch) * - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SHELL_MAIN_H -#define __WINE_SHELL_MAIN_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "objbase.h" -#include "docobj.h" -#include "undocshell.h" -#include "shlobj.h" -#include "shellapi.h" -#include "wine/windef16.h" -#include "wine/unicode.h" - -/******************************************* -* global SHELL32.DLL variables -*/ -extern HMODULE huser32; -extern HINSTANCE shell32_hInstance; -extern HIMAGELIST ShellSmallIconList; -extern HIMAGELIST ShellBigIconList; - -BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList); - -/* Iconcache */ -#define INVALID_INDEX -1 -BOOL SIC_Initialize(void); -void SIC_Destroy(void); -BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex); -INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex ); - -/* Classes Root */ -BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, DWORD len, BOOL bPrependDot); -BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ); -BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, LPDWORD dwNr); -BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, LPDWORD dwNr); -BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len); - -/* ANSI versions of above functions, supposed to go away as soon as they are not used anymore */ -BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot); -BOOL HCR_GetDefaultIconA(LPCSTR szClass, LPSTR szDest, DWORD len, LPDWORD dwNr); -BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len); - -BOOL HCR_GetFolderAttributes(REFIID riid, LPDWORD szDest); - -INT_PTR CALLBACK AboutDlgProc(HWND,UINT,WPARAM,LPARAM); -DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len); -DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len); - -/**************************************************************************** - * Class constructors - */ -LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPCITEMIDLIST myPidl, LPCITEMIDLIST * apidl, UINT cidl); -LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT, const FORMATETC []); - -LPCLASSFACTORY IClassFactory_Constructor(REFCLSID); -IContextMenu2 * ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *aPidls, UINT uItemCount); -IContextMenu2 * ISvBgCm_Constructor(LPSHELLFOLDER pSFParent); -LPSHELLVIEW IShellView_Constructor(LPSHELLFOLDER); - -HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI IShellLink_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI IShellLink_ConstructFromFile(IUnknown * pUnkOuter, REFIID riid, LPCITEMIDLIST pidl, LPVOID * ppv); -HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV); -HRESULT WINAPI IControlPanel_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); -HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex); -HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex); -HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); -HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); - -HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); - -LPEXTRACTICONA IExtractIconA_Constructor(LPCITEMIDLIST); -LPEXTRACTICONW IExtractIconW_Constructor(LPCITEMIDLIST); -HRESULT CreateStreamOnFile (LPCWSTR pszFilename, DWORD grfMode, IStream ** ppstm); - -/* FIXME: rename the functions when the shell32.dll has it's own exports namespace */ -HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv); -HRESULT WINAPI SHELL32_DllCanUnloadNow(void); - - -/* menu merging */ -#define MM_ADDSEPARATOR 0x00000001L -#define MM_SUBMENUSHAVEIDS 0x00000002L -HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags); - -/* initialisation for FORMATETC */ -#define InitFormatEtc(fe, cf, med) \ - {\ - (fe).cfFormat=cf;\ - (fe).dwAspect=DVASPECT_CONTENT;\ - (fe).ptd=NULL;\ - (fe).tymed=med;\ - (fe).lindex=-1;\ - }; - -#define KeyStateToDropEffect(kst)\ - (((kst) & MK_CONTROL) ?\ - (((kst) & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY):\ - DROPEFFECT_MOVE) - -HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); -HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags); - -/* Change Notification */ -void InitChangeNotifications(void); -void FreeChangeNotifications(void); - -/* file operation */ -#define ASK_DELETE_FILE 1 -#define ASK_DELETE_FOLDER 2 -#define ASK_DELETE_MULTIPLE_ITEM 3 -#define ASK_CREATE_FOLDER 4 -#define ASK_OVERWRITE_FILE 5 - -BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI); -BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI); -BOOL SHELL_ConfirmDialog(int nKindOfDialog, LPCSTR szDir); - -/* 16-bit functions */ -void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b); -UINT16 WINAPI DragQueryFile16(HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength); -void WINAPI DragFinish16(HDROP16 h); -BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p); -HINSTANCE16 WINAPI ShellExecute16(HWND16,LPCSTR,LPCSTR,LPCSTR,LPCSTR,INT16); -HICON16 WINAPI ExtractIcon16(HINSTANCE16,LPCSTR,UINT16); -HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16,LPSTR,LPWORD); -HICON16 WINAPI ExtractIconEx16 ( LPCSTR, INT16, HICON16 *, HICON16 *, UINT16 ); -HINSTANCE16 WINAPI FindExecutable16(LPCSTR,LPCSTR,LPSTR); -HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16,LPCSTR,UINT16,WORD); -BOOL16 WINAPI ShellAbout16(HWND16,LPCSTR,LPCSTR,HICON16); -BOOL16 WINAPI AboutDlgProc16(HWND16,UINT16,WPARAM16,LPARAM); - -inline static BOOL SHELL_OsIsUnicode(void) -{ - /* if high-bit of version is 0, we are emulating NT */ - return !(GetVersion() & 0x80000000); -} - -#define __SHFreeAndNil(ptr) \ - {\ - SHFree(*ptr); \ - *ptr = NULL; \ - }; -inline static void __SHCloneStrA(char ** target,const char * source) -{ - *target = SHAlloc(strlen(source)+1); - strcpy(*target, source); -} - -inline static void __SHCloneStrWtoA(char ** target, const WCHAR * source) -{ - int len = WideCharToMultiByte(CP_ACP, 0, source, -1, NULL, 0, NULL, NULL); - *target = SHAlloc(len); - WideCharToMultiByte(CP_ACP, 0, source, -1, *target, len, NULL, NULL); -} - -inline static void __SHCloneStrW(WCHAR ** target, const WCHAR * source) -{ - *target = SHAlloc( (strlenW(source)+1) * sizeof(WCHAR) ); - strcpyW(*target, source); -} - -inline static WCHAR * __SHCloneStrAtoW(WCHAR ** target, const char * source) -{ - int len = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0); - *target = SHAlloc(len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, source, -1, *target, len); - return *target; -} - -/* handle conversions */ -#define HICON_16(h32) (LOWORD(h32)) -#define HICON_32(h16) ((HICON)(ULONG_PTR)(h16)) -#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) -#define HINSTANCE_16(h32) (LOWORD(h32)) - -typedef UINT (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, - LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out); - -BOOL WINAPI ShellExecuteExW32(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc); - -UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, - LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args); - -extern WCHAR swShell32Name[MAX_PATH]; - -/* Default shell folder value registration */ -HRESULT SHELL_RegisterShellFolders(void); - -#endif +/* + * internal Shell32 Library definitions + * + * Copyright 1998 Marcus Meissner + * Copyright 1998 Juergen Schmied (jsch) * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELL_MAIN_H +#define __WINE_SHELL_MAIN_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "commctrl.h" +#include "objbase.h" +#include "docobj.h" +#include "undocshell.h" +#include "shlobj.h" +#include "shellapi.h" +#include "wine/windef16.h" +#include "wine/unicode.h" + +/******************************************* +* global SHELL32.DLL variables +*/ +extern HMODULE huser32; +extern HINSTANCE shell32_hInstance; +extern HIMAGELIST ShellSmallIconList; +extern HIMAGELIST ShellBigIconList; + +BOOL WINAPI Shell_GetImageList(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList); + +/* Iconcache */ +#define INVALID_INDEX -1 +BOOL SIC_Initialize(void); +void SIC_Destroy(void); +BOOL PidlToSicIndex (IShellFolder * sh, LPCITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, int * pIndex); +INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex ); + +/* Classes Root */ +BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, DWORD len, BOOL bPrependDot); +BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ); +BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, LPDWORD dwNr); +BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, LPDWORD dwNr); +BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len); + +/* ANSI versions of above functions, supposed to go away as soon as they are not used anymore */ +BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot); +BOOL HCR_GetDefaultIconA(LPCSTR szClass, LPSTR szDest, DWORD len, LPDWORD dwNr); +BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len); + +BOOL HCR_GetFolderAttributes(REFIID riid, LPDWORD szDest); + +INT_PTR CALLBACK AboutDlgProc(HWND,UINT,WPARAM,LPARAM); +DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len); +DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len); + +/**************************************************************************** + * Class constructors + */ +LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPCITEMIDLIST myPidl, LPCITEMIDLIST * apidl, UINT cidl); +LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT, const FORMATETC []); + +LPCLASSFACTORY IClassFactory_Constructor(REFCLSID); +IContextMenu2 * ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *aPidls, UINT uItemCount); +IContextMenu2 * ISvBgCm_Constructor(LPSHELLFOLDER pSFParent); +LPSHELLVIEW IShellView_Constructor(LPSHELLFOLDER); + +HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI IShellLink_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI IShellLink_ConstructFromFile(IUnknown * pUnkOuter, REFIID riid, LPCITEMIDLIST pidl, LPVOID * ppv); +HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV); +HRESULT WINAPI IControlPanel_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); +HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex); +HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex); +HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); +HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize); + +HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); + +LPEXTRACTICONA IExtractIconA_Constructor(LPCITEMIDLIST); +LPEXTRACTICONW IExtractIconW_Constructor(LPCITEMIDLIST); +HRESULT CreateStreamOnFile (LPCWSTR pszFilename, DWORD grfMode, IStream ** ppstm); + +/* FIXME: rename the functions when the shell32.dll has it's own exports namespace */ +HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv); +HRESULT WINAPI SHELL32_DllCanUnloadNow(void); + + +/* menu merging */ +#define MM_ADDSEPARATOR 0x00000001L +#define MM_SUBMENUSHAVEIDS 0x00000002L +HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags); + +/* initialisation for FORMATETC */ +#define InitFormatEtc(fe, cf, med) \ + {\ + (fe).cfFormat=cf;\ + (fe).dwAspect=DVASPECT_CONTENT;\ + (fe).ptd=NULL;\ + (fe).tymed=med;\ + (fe).lindex=-1;\ + }; + +#define KeyStateToDropEffect(kst)\ + (((kst) & MK_CONTROL) ?\ + (((kst) & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY):\ + DROPEFFECT_MOVE) + +HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderSHELLIDLISTOFFSET (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderFILECONTENTS (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderFILEDESCRIPTOR (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl); +HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags); + +/* Change Notification */ +void InitChangeNotifications(void); +void FreeChangeNotifications(void); + +/* file operation */ +#define ASK_DELETE_FILE 1 +#define ASK_DELETE_FOLDER 2 +#define ASK_DELETE_MULTIPLE_ITEM 3 +#define ASK_CREATE_FOLDER 4 +#define ASK_OVERWRITE_FILE 5 + +BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI); +BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI); +BOOL SHELL_ConfirmDialog(int nKindOfDialog, LPCSTR szDir); + +/* 16-bit functions */ +void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b); +UINT16 WINAPI DragQueryFile16(HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength); +void WINAPI DragFinish16(HDROP16 h); +BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p); +HINSTANCE16 WINAPI ShellExecute16(HWND16,LPCSTR,LPCSTR,LPCSTR,LPCSTR,INT16); +HICON16 WINAPI ExtractIcon16(HINSTANCE16,LPCSTR,UINT16); +HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16,LPSTR,LPWORD); +HICON16 WINAPI ExtractIconEx16 ( LPCSTR, INT16, HICON16 *, HICON16 *, UINT16 ); +HINSTANCE16 WINAPI FindExecutable16(LPCSTR,LPCSTR,LPSTR); +HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16,LPCSTR,UINT16,WORD); +BOOL16 WINAPI ShellAbout16(HWND16,LPCSTR,LPCSTR,HICON16); +BOOL16 WINAPI AboutDlgProc16(HWND16,UINT16,WPARAM16,LPARAM); + +inline static BOOL SHELL_OsIsUnicode(void) +{ + /* if high-bit of version is 0, we are emulating NT */ + return !(GetVersion() & 0x80000000); +} + +#define __SHFreeAndNil(ptr) \ + {\ + SHFree(*ptr); \ + *ptr = NULL; \ + }; +inline static void __SHCloneStrA(char ** target,const char * source) +{ + *target = SHAlloc(strlen(source)+1); + strcpy(*target, source); +} + +inline static void __SHCloneStrWtoA(char ** target, const WCHAR * source) +{ + int len = WideCharToMultiByte(CP_ACP, 0, source, -1, NULL, 0, NULL, NULL); + *target = SHAlloc(len); + WideCharToMultiByte(CP_ACP, 0, source, -1, *target, len, NULL, NULL); +} + +inline static void __SHCloneStrW(WCHAR ** target, const WCHAR * source) +{ + *target = SHAlloc( (strlenW(source)+1) * sizeof(WCHAR) ); + strcpyW(*target, source); +} + +inline static WCHAR * __SHCloneStrAtoW(WCHAR ** target, const char * source) +{ + int len = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0); + *target = SHAlloc(len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, source, -1, *target, len); + return *target; +} + +/* handle conversions */ +#define HICON_16(h32) (LOWORD(h32)) +#define HICON_32(h16) ((HICON)(ULONG_PTR)(h16)) +#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) +#define HINSTANCE_16(h32) (LOWORD(h32)) + +typedef UINT (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, + LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out); + +BOOL WINAPI ShellExecuteExW32(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc); + +UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, + LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args); + +extern WCHAR swShell32Name[MAX_PATH]; + +/* Default shell folder value registration */ +HRESULT SHELL_RegisterShellFolders(void); + +#endif diff --git a/reactos/lib/shell32/shell32_xx.rc b/reactos/lib/shell32/shell32_xx.rc index b99ea36cf70..9a40d049d51 100644 --- a/reactos/lib/shell32/shell32_xx.rc +++ b/reactos/lib/shell32/shell32_xx.rc @@ -1,20 +1,20 @@ -/* Language neutral resources. - * Icons and bitmaps should go in here. - * - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +/* Language neutral resources. + * Icons and bitmaps should go in here. + * + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/reactos/lib/shell32/shellfolder.h b/reactos/lib/shell32/shellfolder.h index ff29841d9d8..e222e15d841 100644 --- a/reactos/lib/shell32/shellfolder.h +++ b/reactos/lib/shell32/shellfolder.h @@ -1,68 +1,68 @@ -/* - * defines helperfunctions to manipulate the contents of a IShellFolder - * - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SHELLFOLDER_HELP_H -#define __WINE_SHELLFOLDER_HELP_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" - -#include "shlobj.h" - -/***************************************************************************** - * Predeclare the interfaces - */ -DEFINE_GUID(IID_ISFHelper, 0x1fe68efbL, 0x1874, 0x9812, 0x56, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - -/***************************************************************************** - * ISFHelper interface - */ - -#define INTERFACE ISFHelper -DECLARE_INTERFACE_(ISFHelper,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** ISFHelper methods ***/ - STDMETHOD(GetUniqueName)(THIS_ LPSTR lpName, UINT uLen) PURE; - STDMETHOD(AddFolder)(THIS_ HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut) PURE; - STDMETHOD(DeleteItems)(THIS_ UINT cidl, LPCITEMIDLIST * apidl) PURE; - STDMETHOD(CopyItems)(THIS_ IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) PURE; -}; -#undef INTERFACE - -#ifdef COBJMACROS -/*** IUnknown methods ***/ -#define ISFHelper_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) -#define ISFHelper_AddRef(p) (p)->lpVtbl->AddRef(p) -#define ISFHelper_Release(p) (p)->lpVtbl->Release(p) -/*** ISFHelper methods ***/ -#define ISFHelper_GetUniqueName(p,a,b) (p)->lpVtbl->GetUniqueName(p,a,b) -#define ISFHelper_AddFolder(p,a,b,c) (p)->lpVtbl->AddFolder(p,a,b,c) -#define ISFHelper_DeleteItems(p,a,b) (p)->lpVtbl->DeleteItems(p,a,b) -#define ISFHelper_CopyItems(p,a,b,c) (p)->lpVtbl->CopyItems(p,a,b,c) -#endif - -#endif /* __WINE_SHELLFOLDER_HELP_H */ +/* + * defines helperfunctions to manipulate the contents of a IShellFolder + * + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELLFOLDER_HELP_H +#define __WINE_SHELLFOLDER_HELP_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" + +#include "shlobj.h" + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_ISFHelper, 0x1fe68efbL, 0x1874, 0x9812, 0x56, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +/***************************************************************************** + * ISFHelper interface + */ + +#define INTERFACE ISFHelper +DECLARE_INTERFACE_(ISFHelper,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** ISFHelper methods ***/ + STDMETHOD(GetUniqueName)(THIS_ LPSTR lpName, UINT uLen) PURE; + STDMETHOD(AddFolder)(THIS_ HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut) PURE; + STDMETHOD(DeleteItems)(THIS_ UINT cidl, LPCITEMIDLIST * apidl) PURE; + STDMETHOD(CopyItems)(THIS_ IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) PURE; +}; +#undef INTERFACE + +#ifdef COBJMACROS +/*** IUnknown methods ***/ +#define ISFHelper_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define ISFHelper_AddRef(p) (p)->lpVtbl->AddRef(p) +#define ISFHelper_Release(p) (p)->lpVtbl->Release(p) +/*** ISFHelper methods ***/ +#define ISFHelper_GetUniqueName(p,a,b) (p)->lpVtbl->GetUniqueName(p,a,b) +#define ISFHelper_AddFolder(p,a,b,c) (p)->lpVtbl->AddFolder(p,a,b,c) +#define ISFHelper_DeleteItems(p,a,b) (p)->lpVtbl->DeleteItems(p,a,b) +#define ISFHelper_CopyItems(p,a,b,c) (p)->lpVtbl->CopyItems(p,a,b,c) +#endif + +#endif /* __WINE_SHELLFOLDER_HELP_H */ diff --git a/reactos/lib/shell32/shelllink.c b/reactos/lib/shell32/shelllink.c index fef4152f3c6..e0272646ecb 100644 --- a/reactos/lib/shell32/shelllink.c +++ b/reactos/lib/shell32/shelllink.c @@ -1,1825 +1,1802 @@ -/* - * - * Copyright 1997 Marcus Meissner - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * Nearly complete informations about the binary formats - * of .lnk files available at http://www.wotsit.org - * - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#define COBJMACROS - -#include "wine/debug.h" -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winreg.h" - -#include "winuser.h" -#include "wingdi.h" -#include "shlobj.h" -#include "undocshell.h" - -#include "pidl.h" -#include "shell32_main.h" -#include "shlguid.h" -#include "shlwapi.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/* link file formats */ - -/* flag1: lnk elements: simple link has 0x0B */ -#define SCF_PIDL 1 -#define SCF_NORMAL 2 -#define SCF_DESCRIPTION 4 -#define SCF_RELATIVE 8 -#define SCF_WORKDIR 0x10 -#define SCF_ARGS 0x20 -#define SCF_CUSTOMICON 0x40 -#define SCF_UNICODE 0x80 - -#include "pshpack1.h" - -typedef struct _LINK_HEADER -{ - DWORD dwSize; /* 0x00 size of the header - 0x4c */ - GUID MagicGuid; /* 0x04 is CLSID_ShellLink */ - DWORD dwFlags; /* 0x14 describes elements following */ - DWORD dwFileAttr; /* 0x18 attributes of the target file */ - FILETIME Time1; /* 0x1c */ - FILETIME Time2; /* 0x24 */ - FILETIME Time3; /* 0x2c */ - DWORD dwFileLength; /* 0x34 File length */ - DWORD nIcon; /* 0x38 icon number */ - DWORD fStartup; /* 0x3c startup type */ - DWORD wHotKey; /* 0x40 hotkey */ - DWORD Unknown5; /* 0x44 */ - DWORD Unknown6; /* 0x48 */ -} LINK_HEADER, * PLINK_HEADER; - -#define SHLINK_LOCAL 0 -#define SHLINK_REMOTE 1 - -typedef struct _LOCATION_INFO -{ - DWORD dwTotalSize; - DWORD dwHeaderSize; - DWORD dwFlags; - DWORD dwVolTableOfs; - DWORD dwLocalPathOfs; - DWORD dwNetworkVolTableOfs; - DWORD dwFinalPathOfs; -} LOCATION_INFO; - -typedef struct _LOCAL_VOLUME_INFO -{ - DWORD dwSize; - DWORD dwType; - DWORD dwVolSerial; - DWORD dwVolLabelOfs; -} LOCAL_VOLUME_INFO; - -#include "poppack.h" - -static IShellLinkAVtbl slvt; -static IShellLinkWVtbl slvtw; -static IPersistFileVtbl pfvt; -static IPersistStreamVtbl psvt; - -/* IShellLink Implementation */ - -typedef struct -{ - IShellLinkAVtbl *lpVtbl; - DWORD ref; - - IShellLinkWVtbl *lpvtblw; - IPersistFileVtbl *lpvtblPersistFile; - IPersistStreamVtbl *lpvtblPersistStream; - - /* data structures according to the informations in the link */ - LPITEMIDLIST pPidl; - WORD wHotKey; - SYSTEMTIME time1; - SYSTEMTIME time2; - SYSTEMTIME time3; - - DWORD iShowCmd; - LPWSTR sIcoPath; - INT iIcoNdx; - LPWSTR sPath; - LPWSTR sArgs; - LPWSTR sWorkDir; - LPWSTR sDescription; - LPWSTR sPathRel; - - BOOL bDirty; -} IShellLinkImpl; - -#define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw))) -#define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset) - -#define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile))) -#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset) - -#define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream))) -#define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset) - -static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath); - -/* strdup on the process heap */ -inline static LPWSTR HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str) -{ - INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - LPWSTR p = HeapAlloc( heap, flags, len*sizeof (WCHAR) ); - if( !p ) - return p; - MultiByteToWideChar( CP_ACP, 0, str, -1, p, len ); - return p; -} - - -/************************************************************************** - * IPersistFile_QueryInterface - */ -static HRESULT WINAPI IPersistFile_fnQueryInterface( - IPersistFile* iface, - REFIID riid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - - TRACE("(%p)\n",This); - - return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj); -} - -/****************************************************************************** - * IPersistFile_AddRef - */ -static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellLinkA_AddRef((IShellLinkA*)This); -} -/****************************************************************************** - * IPersistFile_Release - */ -static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellLinkA_Release((IShellLinkA*)This); -} - -static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile* iface, CLSID *pClassID) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - FIXME("(%p)\n",This); - return NOERROR; -} -static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile* iface) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - - TRACE("(%p)\n",This); - - if (This->bDirty) - return S_OK; - - return S_FALSE; -} -static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream; - HRESULT r; - IStream *stm; - - TRACE("(%p, %s)\n",This, debugstr_w(pszFileName)); - - r = CreateStreamOnFile(pszFileName, dwMode, &stm); - if( SUCCEEDED( r ) ) - { - r = IPersistStream_Load(StreamThis, stm); - ShellLink_UpdatePath(This->sPathRel, pszFileName, This->sWorkDir, &This->sPath); - IStream_Release( stm ); - This->bDirty = FALSE; - } - - return r; -} - -static BOOL StartLinkProcessor( LPCOLESTR szLink ) -{ - static const WCHAR szFormat[] = {'w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e', - ' ','-','r',' ','"','%','s','"',0 }; - LONG len; - LPWSTR buffer; - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - len = sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR); - buffer = HeapAlloc( GetProcessHeap(), 0, len ); - if( !buffer ) - return FALSE; - - wsprintfW( buffer, szFormat, szLink ); - - TRACE("starting %s\n",debugstr_w(buffer)); - - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - if (!CreateProcessW( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return FALSE; - - /* wait for a while to throttle the creation of linker processes */ - if( WAIT_OBJECT_0 != WaitForSingleObject( pi.hProcess, 10000 ) ) - WARN("Timed out waiting for shell linker\n"); - - CloseHandle( pi.hProcess ); - CloseHandle( pi.hThread ); - - return TRUE; -} - -static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream; - HRESULT r; - IStream *stm; - - TRACE("(%p)->(%s)\n",This,debugstr_w(pszFileName)); - - if (!pszFileName || !This->sPath) - return E_FAIL; - - r = CreateStreamOnFile(pszFileName, STGM_READWRITE | STGM_CREATE, &stm); - if( SUCCEEDED( r ) ) - { - r = IPersistStream_Save(StreamThis, stm, FALSE); - IStream_Release( stm ); - - if( SUCCEEDED( r ) ) - { - StartLinkProcessor( pszFileName ); - - This->bDirty = FALSE; - } - else - { - DeleteFileW( pszFileName ); - WARN("Failed to create shortcut %s\n", debugstr_w(pszFileName) ); - } - } - - return r; -} - -static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName)); - return NOERROR; -} -static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName) -{ - _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); - FIXME("(%p)\n",This); - return NOERROR; -} - -static IPersistFileVtbl pfvt = -{ - IPersistFile_fnQueryInterface, - IPersistFile_fnAddRef, - IPersistFile_fnRelease, - IPersistFile_fnGetClassID, - IPersistFile_fnIsDirty, - IPersistFile_fnLoad, - IPersistFile_fnSave, - IPersistFile_fnSaveCompleted, - IPersistFile_fnGetCurFile -}; - -/************************************************************************ - * IPersistStream_QueryInterface - */ -static HRESULT WINAPI IPersistStream_fnQueryInterface( - IPersistStream* iface, - REFIID riid, - VOID** ppvoid) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n",This); - - return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvoid); -} - -/************************************************************************ - * IPersistStream_Release - */ -static ULONG WINAPI IPersistStream_fnRelease( - IPersistStream* iface) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n",This); - - return IShellLinkA_Release((IShellLinkA*)This); -} - -/************************************************************************ - * IPersistStream_AddRef - */ -static ULONG WINAPI IPersistStream_fnAddRef( - IPersistStream* iface) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n",This); - - return IShellLinkA_AddRef((IShellLinkA*)This); -} - -/************************************************************************ - * IPersistStream_GetClassID - * - */ -static HRESULT WINAPI IPersistStream_fnGetClassID( - IPersistStream* iface, - CLSID* pClassID) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n", This); - - if (pClassID==0) - return E_POINTER; - -/* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */ - - return S_OK; -} - -/************************************************************************ - * IPersistStream_IsDirty (IPersistStream) - */ -static HRESULT WINAPI IPersistStream_fnIsDirty( - IPersistStream* iface) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n", This); - - return S_OK; -} - - -static HRESULT Stream_LoadString( IStream* stm, BOOL unicode, LPWSTR *pstr ) -{ - DWORD count; - USHORT len; - LPVOID temp; - LPWSTR str; - HRESULT r; - - TRACE("%p\n", stm); - - count = 0; - r = IStream_Read(stm, &len, sizeof(len), &count); - if ( FAILED (r) || ( count != sizeof(len) ) ) - return E_FAIL; - - if( unicode ) - len *= sizeof (WCHAR); - - TRACE("reading %d\n", len); - temp = HeapAlloc(GetProcessHeap(), 0, len+sizeof(WCHAR)); - if( !temp ) - return E_OUTOFMEMORY; - count = 0; - r = IStream_Read(stm, temp, len, &count); - if( FAILED (r) || ( count != len ) ) - { - HeapFree( GetProcessHeap(), 0, temp ); - return E_FAIL; - } - - TRACE("read %s\n", debugstr_an(temp,len)); - - /* convert to unicode if necessary */ - if( !unicode ) - { - count = MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, NULL, 0 ); - str = HeapAlloc( GetProcessHeap(), 0, (count+1)*sizeof (WCHAR) ); - if( str ) - MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, str, count ); - HeapFree( GetProcessHeap(), 0, temp ); - } - else - { - count /= 2; - str = (LPWSTR) temp; - } - str[count] = 0; - - *pstr = str; - - return S_OK; -} - -static HRESULT Stream_LoadLocation( IStream* stm ) -{ - DWORD size; - ULONG count; - HRESULT r; - LOCATION_INFO *loc; - - TRACE("%p\n",stm); - - r = IStream_Read( stm, &size, sizeof(size), &count ); - if( FAILED( r ) ) - return r; - if( count != sizeof(loc->dwTotalSize) ) - return E_FAIL; - - loc = HeapAlloc( GetProcessHeap(), 0, size ); - if( ! loc ) - return E_OUTOFMEMORY; - - r = IStream_Read( stm, &loc->dwHeaderSize, size-sizeof(size), &count ); - if( FAILED( r ) ) - goto end; - if( count != (size - sizeof(size)) ) - { - r = E_FAIL; - goto end; - } - loc->dwTotalSize = size; - - TRACE("Read %ld bytes\n",count); - - /* FIXME: do something useful with it */ - HeapFree( GetProcessHeap(), 0, loc ); - - return S_OK; -end: - HeapFree( GetProcessHeap(), 0, loc ); - return r; -} - -/************************************************************************ - * IPersistStream_Load (IPersistStream) - */ -static HRESULT WINAPI IPersistStream_fnLoad( - IPersistStream* iface, - IStream* stm) -{ - LINK_HEADER hdr; - ULONG dwBytesRead; - BOOL unicode; - WCHAR sTemp[MAX_PATH]; - HRESULT r; - - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)(%p)\n", This, stm); - - if( !stm ) - return STG_E_INVALIDPOINTER; - - dwBytesRead = 0; - r = IStream_Read(stm, &hdr, sizeof(hdr), &dwBytesRead); - if( FAILED( r ) ) - return r; - - if( dwBytesRead != sizeof(hdr)) - return E_FAIL; - if( hdr.dwSize != sizeof(hdr)) - return E_FAIL; - if( !IsEqualIID(&hdr.MagicGuid, &CLSID_ShellLink) ) - return E_FAIL; - - /* if( hdr.dwFlags & SCF_PIDL ) */ /* FIXME: seems to always have a PIDL */ - { - r = ILLoadFromStream( stm, &This->pPidl ); - if( FAILED( r ) ) - return r; - } - This->wHotKey = (WORD)hdr.wHotKey; - This->iIcoNdx = hdr.nIcon; - FileTimeToSystemTime (&hdr.Time1, &This->time1); - FileTimeToSystemTime (&hdr.Time2, &This->time2); - FileTimeToSystemTime (&hdr.Time3, &This->time3); -#if 1 - GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time1, NULL, sTemp, 256); - TRACE("-- time1: %s\n", debugstr_w(sTemp) ); - GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time2, NULL, sTemp, 256); - TRACE("-- time1: %s\n", debugstr_w(sTemp) ); - GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time3, NULL, sTemp, 256); - TRACE("-- time1: %s\n", debugstr_w(sTemp) ); - pdump (This->pPidl); -#endif - if( hdr.dwFlags & SCF_NORMAL ) - r = Stream_LoadLocation( stm ); - if( FAILED( r ) ) - goto end; - unicode = hdr.dwFlags & SCF_UNICODE; - if( hdr.dwFlags & SCF_DESCRIPTION ) - { - r = Stream_LoadString( stm, unicode, &This->sDescription ); - TRACE("Description -> %s\n",debugstr_w(This->sDescription)); - } - if( FAILED( r ) ) - goto end; - - if( hdr.dwFlags & SCF_RELATIVE ) - { - r = Stream_LoadString( stm, unicode, &This->sPathRel ); - TRACE("Relative Path-> %s\n",debugstr_w(This->sPathRel)); - } - if( FAILED( r ) ) - goto end; - - if( hdr.dwFlags & SCF_WORKDIR ) - { - r = Stream_LoadString( stm, unicode, &This->sWorkDir ); - TRACE("Working Dir -> %s\n",debugstr_w(This->sWorkDir)); - } - if( FAILED( r ) ) - goto end; - - if( hdr.dwFlags & SCF_ARGS ) - { - r = Stream_LoadString( stm, unicode, &This->sArgs ); - TRACE("Working Dir -> %s\n",debugstr_w(This->sArgs)); - } - if( FAILED( r ) ) - goto end; - - if( hdr.dwFlags & SCF_CUSTOMICON ) - { - r = Stream_LoadString( stm, unicode, &This->sIcoPath ); - TRACE("Icon file -> %s\n",debugstr_w(This->sIcoPath)); - } - if( FAILED( r ) ) - goto end; - - TRACE("OK\n"); - - pdump (This->pPidl); - - return S_OK; -end: - return r; -} - -/************************************************************************ - * Stream_WriteString - * - * Helper function for IPersistStream_Save. Writes a unicode string - * with terminating nul byte to a stream, preceded by the its length. - */ -static HRESULT Stream_WriteString( IStream* stm, LPCWSTR str ) -{ - USHORT len = lstrlenW( str ) + 1; - DWORD count; - HRESULT r; - - r = IStream_Write( stm, &len, sizeof(len), &count ); - if( FAILED( r ) ) - return r; - - len *= sizeof(WCHAR); - - r = IStream_Write( stm, str, len, &count ); - if( FAILED( r ) ) - return r; - - return S_OK; -} - -static HRESULT Stream_WriteLocationInfo( IStream* stm, LPCWSTR filename ) -{ - LOCATION_INFO loc; - ULONG count; - - FIXME("writing empty location info\n"); - - memset( &loc, 0, sizeof(loc) ); - loc.dwTotalSize = sizeof(loc) - sizeof(loc.dwTotalSize); - - /* FIXME: fill this in */ - - return IStream_Write( stm, &loc, loc.dwTotalSize, &count ); -} - -/************************************************************************ - * IPersistStream_Save (IPersistStream) - * - * FIXME: makes assumptions about byte order - */ -static HRESULT WINAPI IPersistStream_fnSave( - IPersistStream* iface, - IStream* stm, - BOOL fClearDirty) -{ - static const WCHAR wOpen[] = {'o','p','e','n',0}; - - LINK_HEADER header; - WCHAR exePath[MAX_PATH]; - ULONG count; - HRESULT r; - - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p) %p %x\n", This, stm, fClearDirty); - - *exePath = '\0'; - - if (This->sPath) - { - SHELL_FindExecutable(NULL, This->sPath, wOpen, exePath, MAX_PATH, NULL, NULL, NULL, NULL); - /* - * windows can create lnk files to executables that do not exist yet - * so if the executable does not exist the just trust the path they - * gave us - */ - if( !*exePath ) strcpyW(exePath,This->sPath); - } - - /* if there's no PIDL, generate one */ - if( ! This->pPidl ) This->pPidl = ILCreateFromPathW(exePath); - - memset(&header, 0, sizeof(header)); - header.dwSize = sizeof(header); - memcpy(&header.MagicGuid, &CLSID_ShellLink, sizeof(header.MagicGuid) ); - - header.wHotKey = This->wHotKey; - header.nIcon = This->iIcoNdx; - header.dwFlags = SCF_UNICODE; /* strings are in unicode */ - header.dwFlags |= SCF_NORMAL; /* how do we determine this ? */ - if( This->pPidl ) - header.dwFlags |= SCF_PIDL; - if( This->sDescription ) - header.dwFlags |= SCF_DESCRIPTION; - if( This->sWorkDir ) - header.dwFlags |= SCF_WORKDIR; - if( This->sArgs ) - header.dwFlags |= SCF_ARGS; - if( This->sIcoPath ) - header.dwFlags |= SCF_CUSTOMICON; - - SystemTimeToFileTime ( &This->time1, &header.Time1 ); - SystemTimeToFileTime ( &This->time2, &header.Time2 ); - SystemTimeToFileTime ( &This->time3, &header.Time3 ); - - /* write the Shortcut header */ - r = IStream_Write( stm, &header, sizeof(header), &count ); - if( FAILED( r ) ) - { - ERR("Write failed at %d\n",__LINE__); - return r; - } - - TRACE("Writing pidl \n"); - - /* write the PIDL to the shortcut */ - if( This->pPidl ) - { - r = ILSaveToStream( stm, This->pPidl ); - if( FAILED( r ) ) - { - ERR("Failed to write PIDL at %d\n",__LINE__); - return r; - } - } - - Stream_WriteLocationInfo( stm, exePath ); - - TRACE("Description = %s\n", debugstr_w(This->sDescription)); - if( This->sDescription ) - r = Stream_WriteString( stm, This->sDescription ); - - if( This->sPathRel ) - r = Stream_WriteString( stm, This->sPathRel ); - - if( This->sWorkDir ) - r = Stream_WriteString( stm, This->sWorkDir ); - - if( This->sArgs ) - r = Stream_WriteString( stm, This->sArgs ); - - if( This->sIcoPath ) - r = Stream_WriteString( stm, This->sIcoPath ); - - return S_OK; -} - -/************************************************************************ - * IPersistStream_GetSizeMax (IPersistStream) - */ -static HRESULT WINAPI IPersistStream_fnGetSizeMax( - IPersistStream* iface, - ULARGE_INTEGER* pcbSize) -{ - _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); - - TRACE("(%p)\n", This); - - return E_NOTIMPL; -} - -static IPersistStreamVtbl psvt = -{ - IPersistStream_fnQueryInterface, - IPersistStream_fnAddRef, - IPersistStream_fnRelease, - IPersistStream_fnGetClassID, - IPersistStream_fnIsDirty, - IPersistStream_fnLoad, - IPersistStream_fnSave, - IPersistStream_fnGetSizeMax -}; - -/************************************************************************** - * IShellLink_Constructor - */ -HRESULT WINAPI IShellLink_Constructor ( - IUnknown * pUnkOuter, - REFIID riid, - LPVOID * ppv) -{ - IShellLinkImpl * sl; - - TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid)); - - *ppv = NULL; - - if(pUnkOuter) return CLASS_E_NOAGGREGATION; - sl = (IShellLinkImpl *) LocalAlloc(GMEM_ZEROINIT,sizeof(IShellLinkImpl)); - if (!sl) return E_OUTOFMEMORY; - - sl->ref = 1; - sl->lpVtbl = &slvt; - sl->lpvtblw = &slvtw; - sl->lpvtblPersistFile = &pfvt; - sl->lpvtblPersistStream = &psvt; - sl->iShowCmd = SW_SHOWNORMAL; - sl->bDirty = FALSE; - - TRACE("(%p)->()\n",sl); - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IShellLinkA)) - *ppv = sl; - else if (IsEqualIID(riid, &IID_IShellLinkW)) - *ppv = &(sl->lpvtblw); - else { - LocalFree((HLOCAL)sl); - ERR("E_NOINTERFACE\n"); - return E_NOINTERFACE; - } - - return S_OK; -} - - -static BOOL SHELL_ExistsFileW(LPCWSTR path) -{ - HANDLE hfile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - - if (hfile != INVALID_HANDLE_VALUE) { - CloseHandle(hfile); - return TRUE; - } else - return FALSE; -} - -/************************************************************************** - * ShellLink_UpdatePath - * update absolute path in sPath using relative path in sPathRel - */ -static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath) -{ - if (!path || !psPath) - return E_INVALIDARG; - - if (!*psPath && sPathRel) { - WCHAR buffer[2*MAX_PATH], abs_path[2*MAX_PATH]; - LPWSTR final = NULL; - - /* first try if [directory of link file] + [relative path] finds an existing file */ - - GetFullPathNameW( path, MAX_PATH*2, buffer, &final ); - if( !final ) - final = buffer; - lstrcpyW(final, sPathRel); - - *abs_path = '\0'; - - if (SHELL_ExistsFileW(buffer)) { - if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final)) - lstrcpyW(abs_path, buffer); - } else { - /* try if [working directory] + [relative path] finds an existing file */ - if (sWorkDir) { - lstrcpyW(buffer, sWorkDir); - lstrcpyW(PathAddBackslashW(buffer), sPathRel); - - if (SHELL_ExistsFileW(buffer)) - if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final)) - lstrcpyW(abs_path, buffer); - } - } - - /* FIXME: This is even not enough - not all shell links can be resolved using this algorithm. */ - if (!*abs_path) - lstrcpyW(abs_path, sPathRel); - - *psPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(abs_path)+1)*sizeof(WCHAR)); - if (!*psPath) - return E_OUTOFMEMORY; - - lstrcpyW(*psPath, abs_path); - } - - return S_OK; -} - -/************************************************************************** - * IShellLink_ConstructFromFile - */ -HRESULT WINAPI IShellLink_ConstructFromFile ( - IUnknown* pUnkOuter, - REFIID riid, - LPCITEMIDLIST pidl, - LPVOID* ppv -) -{ - IShellLinkW* psl; - - HRESULT hr = IShellLink_Constructor(NULL, riid, (LPVOID*)&psl); - - if (SUCCEEDED(hr)) { - IPersistFile* ppf; - - *ppv = NULL; - - hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf); - - if (SUCCEEDED(hr)) { - WCHAR path[MAX_PATH]; - - if (SHGetPathFromIDListW(pidl, path)) - hr = IPersistFile_Load(ppf, path, 0); - else - hr = E_FAIL; - - if (SUCCEEDED(hr)) - *ppv = (IUnknown*) psl; - - IPersistFile_Release(ppf); - } - - if (!*ppv) - IShellLinkW_Release(psl); - } - - return hr; -} - -/************************************************************************** - * IShellLinkA_QueryInterface - */ -static HRESULT WINAPI IShellLinkA_fnQueryInterface( IShellLinkA * iface, REFIID riid, LPVOID *ppvObj) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid)); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IShellLinkA)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellLinkW)) - { - *ppvObj = (IShellLinkW *)&(This->lpvtblw); - } - else if(IsEqualIID(riid, &IID_IPersistFile)) - { - *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile); - } - else if(IsEqualIID(riid, &IID_IPersistStream)) - { - *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream); - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)(*ppvObj)); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} -/****************************************************************************** - * IShellLinkA_AddRef - */ -static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return ++(This->ref); -} -/****************************************************************************** - * IShellLinkA_Release - */ -static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - if (--(This->ref)) - return This->ref; - - TRACE("-- destroying IShellLink(%p)\n",This); - - if (This->sIcoPath) - HeapFree(GetProcessHeap(), 0, This->sIcoPath); - - if (This->sArgs) - HeapFree(GetProcessHeap(), 0, This->sArgs); - - if (This->sWorkDir) - HeapFree(GetProcessHeap(), 0, This->sWorkDir); - - if (This->sDescription) - HeapFree(GetProcessHeap(), 0, This->sDescription); - - if (This->sPath) - HeapFree(GetProcessHeap(),0,This->sPath); - - if (This->pPidl) - ILFree(This->pPidl); - - LocalFree((HANDLE)This); - - return 0; -} - -static HRESULT WINAPI IShellLinkA_fnGetPath(IShellLinkA * iface, LPSTR pszFile, - INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n", - This, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(This->sPath)); - - if( cchMaxPath ) - pszFile[0] = 0; - if (This->sPath) - WideCharToMultiByte( CP_ACP, 0, This->sPath, -1, - pszFile, cchMaxPath, NULL, NULL); - - if (pfd) FIXME("(%p): WIN32_FIND_DATA is not yet filled.\n", This); - - return NOERROR; -} - -static HRESULT WINAPI IShellLinkA_fnGetIDList(IShellLinkA * iface, LPITEMIDLIST * ppidl) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(ppidl=%p)\n",This, ppidl); - - *ppidl = ILClone(This->pPidl); - - return NOERROR; -} - -static HRESULT WINAPI IShellLinkA_fnSetIDList(IShellLinkA * iface, LPCITEMIDLIST pidl) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(pidl=%p)\n",This, pidl); - - if (This->pPidl) - ILFree(This->pPidl); - This->pPidl = ILClone (pidl); - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnGetDescription(IShellLinkA * iface, LPSTR pszName,INT cchMaxName) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName); - - if( cchMaxName ) - pszName[0] = 0; - if( This->sDescription ) - WideCharToMultiByte( CP_ACP, 0, This->sDescription, -1, - pszName, cchMaxName, NULL, NULL); - - return S_OK; -} -static HRESULT WINAPI IShellLinkA_fnSetDescription(IShellLinkA * iface, LPCSTR pszName) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(pName=%s)\n", This, pszName); - - if (This->sDescription) - HeapFree(GetProcessHeap(), 0, This->sDescription); - This->sDescription = HEAP_strdupAtoW( GetProcessHeap(), 0, pszName); - if ( !This->sDescription ) - return E_OUTOFMEMORY; - - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnGetWorkingDirectory(IShellLinkA * iface, LPSTR pszDir,INT cchMaxPath) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p len=%u)\n", This, pszDir, cchMaxPath); - - if( cchMaxPath ) - pszDir[0] = 0; - if( This->sWorkDir ) - WideCharToMultiByte( CP_ACP, 0, This->sWorkDir, -1, - pszDir, cchMaxPath, NULL, NULL); - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnSetWorkingDirectory(IShellLinkA * iface, LPCSTR pszDir) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(dir=%s)\n",This, pszDir); - - if (This->sWorkDir) - HeapFree(GetProcessHeap(), 0, This->sWorkDir); - This->sWorkDir = HEAP_strdupAtoW( GetProcessHeap(), 0, pszDir); - if ( !This->sWorkDir ) - return E_OUTOFMEMORY; - - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnGetArguments(IShellLinkA * iface, LPSTR pszArgs,INT cchMaxPath) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath); - - if( cchMaxPath ) - pszArgs[0] = 0; - if( This->sArgs ) - WideCharToMultiByte( CP_ACP, 0, This->sArgs, -1, - pszArgs, cchMaxPath, NULL, NULL); - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnSetArguments(IShellLinkA * iface, LPCSTR pszArgs) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(args=%s)\n",This, pszArgs); - - if (This->sArgs) - HeapFree(GetProcessHeap(), 0, This->sArgs); - This->sArgs = HEAP_strdupAtoW( GetProcessHeap(), 0, pszArgs); - if( !This->sArgs ) - return E_OUTOFMEMORY; - - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnGetHotkey(IShellLinkA * iface, WORD *pwHotkey) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey); - - *pwHotkey = This->wHotKey; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnSetHotkey(IShellLinkA * iface, WORD wHotkey) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(hotkey=%x)\n",This, wHotkey); - - This->wHotKey = wHotkey; - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnGetShowCmd(IShellLinkA * iface, INT *piShowCmd) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p)\n",This, piShowCmd); - *piShowCmd = This->iShowCmd; - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p) %d\n",This, iShowCmd); - - This->iShowCmd = iShowCmd; - This->bDirty = TRUE; - - return NOERROR; -} - -static HRESULT SHELL_PidlGeticonLocationA(IShellFolder* psf, LPITEMIDLIST pidl, LPSTR pszIconPath, int cchIconPath, int* piIcon) -{ - LPCITEMIDLIST pidlLast; - - HRESULT hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psf, &pidlLast); - - if (SUCCEEDED(hr)) { - IExtractIconA* pei; - - hr = IShellFolder_GetUIObjectOf(psf, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconA, NULL, (LPVOID*)&pei); - - if (SUCCEEDED(hr)) { - hr = IExtractIconA_GetIconLocation(pei, 0, pszIconPath, MAX_PATH, piIcon, NULL); - - IExtractIconA_Release(pei); - } - - IShellFolder_Release(psf); - } - - return hr; -} - -static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon); - - if (cchIconPath) - pszIconPath[0] = 0; - - if (This->sIcoPath) { - WideCharToMultiByte(CP_ACP, 0, This->sIcoPath, -1, pszIconPath, cchIconPath, NULL, NULL); - *piIcon = This->iIcoNdx; - return S_OK; - } - - if (This->pPidl || This->sPath) { - IShellFolder* pdsk; - - HRESULT hr = SHGetDesktopFolder(&pdsk); - - if (SUCCEEDED(hr)) { - /* first look for an icon using the PIDL (if present) */ - if (This->pPidl) - hr = SHELL_PidlGeticonLocationA(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); - else - hr = E_FAIL; - - /* if we couldn't find an icon yet, look for it using the file system path */ - if (FAILED(hr) && This->sPath) { - LPITEMIDLIST pidl; - - hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); - - if (SUCCEEDED(hr)) { - hr = SHELL_PidlGeticonLocationA(pdsk, pidl, pszIconPath, cchIconPath, piIcon); - - SHFree(pidl); - } - } - - IShellFolder_Release(pdsk); - } - - return hr; - } else - return E_FAIL; -} - -static HRESULT WINAPI IShellLinkA_fnSetIconLocation(IShellLinkA * iface, LPCSTR pszIconPath,INT iIcon) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - TRACE("(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon); - - if (This->sIcoPath) - HeapFree(GetProcessHeap(), 0, This->sIcoPath); - This->sIcoPath = HEAP_strdupAtoW(GetProcessHeap(), 0, pszIconPath); - if ( !This->sIcoPath ) - return E_OUTOFMEMORY; - - This->iIcoNdx = iIcon; - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR pszPathRel, DWORD dwReserved) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - FIXME("(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved); - - if (This->sPathRel) - HeapFree(GetProcessHeap(), 0, This->sPathRel); - This->sPathRel = HEAP_strdupAtoW(GetProcessHeap(), 0, pszPathRel); - This->bDirty = TRUE; - - return ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath); -} - -static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags) -{ - HRESULT hr = S_OK; - - IShellLinkImpl *This = (IShellLinkImpl *)iface; - - FIXME("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags); - - /*FIXME: use IResolveShellLink interface */ - - if (!This->sPath && This->pPidl) { - WCHAR buffer[MAX_PATH]; - - hr = SHELL_GetPathFromIDListW(This->pPidl, buffer, MAX_PATH); - - if (SUCCEEDED(hr) && *buffer) { - This->sPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(buffer)+1)*sizeof(WCHAR)); - if (!This->sPath) - return E_OUTOFMEMORY; - - lstrcpyW(This->sPath, buffer); - - This->bDirty = TRUE; - } else - hr = S_OK; /* don't report an error occurred while just caching information */ - } - - if (!This->sIcoPath && This->sPath) { - This->sIcoPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(This->sPath)+1)*sizeof(WCHAR)); - if (!This->sIcoPath) - return E_OUTOFMEMORY; - - lstrcpyW(This->sIcoPath, This->sPath); - This->iIcoNdx = 0; - - This->bDirty = TRUE; - } - - return hr; -} - -static HRESULT WINAPI IShellLinkA_fnSetPath(IShellLinkA * iface, LPCSTR pszFile) -{ - IShellLinkImpl *This = (IShellLinkImpl *)iface; - char buffer[MAX_PATH]; - LPSTR fname; - - TRACE("(%p)->(path=%s)\n",This, pszFile); - - if (!GetFullPathNameA(pszFile, MAX_PATH, buffer, &fname)) - return E_FAIL; - - if (This->sPath) - HeapFree(GetProcessHeap(), 0, This->sPath); - - This->sPath = HEAP_strdupAtoW(GetProcessHeap(), 0, buffer); - if( !This->sPath ) - return E_OUTOFMEMORY; - - This->bDirty = TRUE; - - return S_OK; -} - -/************************************************************************** -* IShellLink Implementation -*/ - -static IShellLinkAVtbl slvt = -{ - IShellLinkA_fnQueryInterface, - IShellLinkA_fnAddRef, - IShellLinkA_fnRelease, - IShellLinkA_fnGetPath, - IShellLinkA_fnGetIDList, - IShellLinkA_fnSetIDList, - IShellLinkA_fnGetDescription, - IShellLinkA_fnSetDescription, - IShellLinkA_fnGetWorkingDirectory, - IShellLinkA_fnSetWorkingDirectory, - IShellLinkA_fnGetArguments, - IShellLinkA_fnSetArguments, - IShellLinkA_fnGetHotkey, - IShellLinkA_fnSetHotkey, - IShellLinkA_fnGetShowCmd, - IShellLinkA_fnSetShowCmd, - IShellLinkA_fnGetIconLocation, - IShellLinkA_fnSetIconLocation, - IShellLinkA_fnSetRelativePath, - IShellLinkA_fnResolve, - IShellLinkA_fnSetPath -}; - - -/************************************************************************** - * IShellLinkW_fnQueryInterface - */ -static HRESULT WINAPI IShellLinkW_fnQueryInterface( - IShellLinkW * iface, REFIID riid, LPVOID *ppvObj) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj); -} - -/****************************************************************************** - * IShellLinkW_fnAddRef - */ -static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellLinkA_AddRef((IShellLinkA*)This); -} -/****************************************************************************** - * IShellLinkW_fnRelease - */ - -static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellLinkA_Release((IShellLinkA*)This); -} - -static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n", - This, pszFile, cchMaxPath, pfd, fFlags); - - if( cchMaxPath ) - pszFile[0] = 0; - if( This->sPath ) - lstrcpynW( pszFile, This->sPath, cchMaxPath ); - - if (pfd) FIXME("(%p): WIN32_FIND_DATA is not yet filled.\n", This); - - return NOERROR; -} - -static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(ppidl=%p)\n",This, ppidl); - - if( This->pPidl) - *ppidl = ILClone( This->pPidl ); - else - *ppidl = NULL; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(pidl=%p)\n",This, pidl); - - if( This->pPidl ) - ILFree( This->pPidl ); - This->pPidl = ILClone( pidl ); - if( !This->pPidl ) - return E_FAIL; - - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName); - - if( cchMaxName ) - pszName[0] = 0; - if( This->sDescription ) - lstrcpynW( pszName, This->sDescription, cchMaxName ); - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(desc=%s)\n",This, debugstr_w(pszName)); - - if (This->sDescription) - HeapFree(GetProcessHeap(), 0, This->sDescription); - This->sDescription = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( pszName )+1)*sizeof(WCHAR) ); - if ( !This->sDescription ) - return E_OUTOFMEMORY; - - lstrcpyW( This->sDescription, pszName ); - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p len %u)\n", This, pszDir, cchMaxPath); - - if( cchMaxPath ) - pszDir[0] = 0; - if( This->sWorkDir ) - lstrcpynW( pszDir, This->sWorkDir, cchMaxPath ); - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(dir=%s)\n",This, debugstr_w(pszDir)); - - if (This->sWorkDir) - HeapFree(GetProcessHeap(), 0, This->sWorkDir); - This->sWorkDir = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( pszDir )+1)*sizeof (WCHAR) ); - if ( !This->sWorkDir ) - return E_OUTOFMEMORY; - lstrcpyW( This->sWorkDir, pszDir ); - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath); - - if( cchMaxPath ) - pszArgs[0] = 0; - if( This->sArgs ) - lstrcpynW( pszArgs, This->sArgs, cchMaxPath ); - - return NOERROR; -} - -static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(args=%s)\n",This, debugstr_w(pszArgs)); - - if (This->sArgs) - HeapFree(GetProcessHeap(), 0, This->sArgs); - This->sArgs = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( pszArgs )+1)*sizeof (WCHAR) ); - if ( !This->sArgs ) - return E_OUTOFMEMORY; - lstrcpyW( This->sArgs, pszArgs ); - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p)\n",This, pwHotkey); - - *pwHotkey=This->wHotKey; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(hotkey=%x)\n",This, wHotkey); - - This->wHotKey = wHotkey; - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p)\n",This, piShowCmd); - - *piShowCmd = This->iShowCmd; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - This->iShowCmd = iShowCmd; - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT SHELL_PidlGeticonLocationW(IShellFolder* psf, LPITEMIDLIST pidl, LPWSTR pszIconPath, int cchIconPath, int* piIcon) -{ - LPCITEMIDLIST pidlLast; - - HRESULT hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psf, &pidlLast); - - if (SUCCEEDED(hr)) { - IExtractIconW* pei; - - hr = IShellFolder_GetUIObjectOf(psf, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW, NULL, (LPVOID*)&pei); - - if (SUCCEEDED(hr)) { - hr = IExtractIconW_GetIconLocation(pei, 0, pszIconPath, MAX_PATH, piIcon, NULL); - - IExtractIconW_Release(pei); - } - - IShellFolder_Release(psf); - } - - return hr; -} - -static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon); - - if (cchIconPath) - pszIconPath[0] = 0; - - if (This->sIcoPath) { - lstrcpynW(pszIconPath, This->sIcoPath, cchIconPath); - *piIcon = This->iIcoNdx; - return S_OK; - } - - if (This->pPidl || This->sPath) { - IShellFolder* pdsk; - - HRESULT hr = SHGetDesktopFolder(&pdsk); - - if (SUCCEEDED(hr)) { - /* first look for an icon using the PIDL (if present) */ - if (This->pPidl) - hr = SHELL_PidlGeticonLocationW(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); - else - hr = E_FAIL; - - /* if we couldn't find an icon yet, look for it using the file system path */ - if (FAILED(hr) && This->sPath) { - LPITEMIDLIST pidl; - - hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); - - if (SUCCEEDED(hr)) { - hr = SHELL_PidlGeticonLocationW(pdsk, pidl, pszIconPath, cchIconPath, piIcon); - - SHFree(pidl); - } - } - - IShellFolder_Release(pdsk); - } - - return hr; - } else - return E_FAIL; -} - -static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon); - - if (This->sIcoPath) - HeapFree(GetProcessHeap(), 0, This->sIcoPath); - This->sIcoPath = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( pszIconPath )+1)*sizeof (WCHAR) ); - if ( !This->sIcoPath ) - return E_OUTOFMEMORY; - lstrcpyW( This->sIcoPath, pszIconPath ); - - This->iIcoNdx = iIcon; - This->bDirty = TRUE; - - return S_OK; -} - -static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - TRACE("(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved); - - if (This->sPathRel) - HeapFree(GetProcessHeap(), 0, This->sPathRel); - This->sPathRel = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( pszPathRel )+1) * sizeof (WCHAR) ); - if ( !This->sPathRel ) - return E_OUTOFMEMORY; - lstrcpyW( This->sPathRel, pszPathRel ); - This->bDirty = TRUE; - - return ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath); -} - -static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags) -{ - HRESULT hr = S_OK; - - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - - FIXME("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags); - - /*FIXME: use IResolveShellLink interface */ - - if (!This->sPath && This->pPidl) { - WCHAR buffer[MAX_PATH]; - - hr = SHELL_GetPathFromIDListW(This->pPidl, buffer, MAX_PATH); - - if (SUCCEEDED(hr) && *buffer) { - This->sPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(buffer)+1)*sizeof(WCHAR)); - if (!This->sPath) - return E_OUTOFMEMORY; - - lstrcpyW(This->sPath, buffer); - - This->bDirty = TRUE; - } else - hr = S_OK; /* don't report an error occurred while just caching information */ - } - - if (!This->sIcoPath && This->sPath) { - This->sIcoPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(This->sPath)+1)*sizeof(WCHAR)); - if (!This->sIcoPath) - return E_OUTOFMEMORY; - - lstrcpyW(This->sIcoPath, This->sPath); - This->iIcoNdx = 0; - - This->bDirty = TRUE; - } - - return hr; -} - -static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile) -{ - _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); - WCHAR buffer[MAX_PATH]; - LPWSTR fname; - - TRACE("(%p)->(path=%s)\n",This, debugstr_w(pszFile)); - - if (!GetFullPathNameW(pszFile, MAX_PATH, buffer, &fname)) - return E_FAIL; - - if (This->sPath) - HeapFree(GetProcessHeap(), 0, This->sPath); - - This->sPath = HeapAlloc( GetProcessHeap(), 0, - (lstrlenW( buffer )+1) * sizeof (WCHAR) ); - if (!This->sPath) - return E_OUTOFMEMORY; - - lstrcpyW(This->sPath, buffer); - This->bDirty = TRUE; - - return S_OK; -} - -/************************************************************************** -* IShellLinkW Implementation -*/ - -static IShellLinkWVtbl slvtw = -{ - IShellLinkW_fnQueryInterface, - IShellLinkW_fnAddRef, - IShellLinkW_fnRelease, - IShellLinkW_fnGetPath, - IShellLinkW_fnGetIDList, - IShellLinkW_fnSetIDList, - IShellLinkW_fnGetDescription, - IShellLinkW_fnSetDescription, - IShellLinkW_fnGetWorkingDirectory, - IShellLinkW_fnSetWorkingDirectory, - IShellLinkW_fnGetArguments, - IShellLinkW_fnSetArguments, - IShellLinkW_fnGetHotkey, - IShellLinkW_fnSetHotkey, - IShellLinkW_fnGetShowCmd, - IShellLinkW_fnSetShowCmd, - IShellLinkW_fnGetIconLocation, - IShellLinkW_fnSetIconLocation, - IShellLinkW_fnSetRelativePath, - IShellLinkW_fnResolve, - IShellLinkW_fnSetPath -}; +/* + * + * Copyright 1997 Marcus Meissner + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * Nearly complete informations about the binary formats + * of .lnk files available at http://www.wotsit.org + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#define COBJMACROS + +#include "wine/debug.h" +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winreg.h" + +#include "winuser.h" +#include "wingdi.h" +#include "shlobj.h" +#include "undocshell.h" + +#include "pidl.h" +#include "shell32_main.h" +#include "shlguid.h" +#include "shlwapi.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/* link file formats */ + +/* flag1: lnk elements: simple link has 0x0B */ +#define SCF_PIDL 1 +#define SCF_NORMAL 2 +#define SCF_DESCRIPTION 4 +#define SCF_RELATIVE 8 +#define SCF_WORKDIR 0x10 +#define SCF_ARGS 0x20 +#define SCF_CUSTOMICON 0x40 +#define SCF_UNICODE 0x80 + +#include "pshpack1.h" + +typedef struct _LINK_HEADER +{ + DWORD dwSize; /* 0x00 size of the header - 0x4c */ + GUID MagicGuid; /* 0x04 is CLSID_ShellLink */ + DWORD dwFlags; /* 0x14 describes elements following */ + DWORD dwFileAttr; /* 0x18 attributes of the target file */ + FILETIME Time1; /* 0x1c */ + FILETIME Time2; /* 0x24 */ + FILETIME Time3; /* 0x2c */ + DWORD dwFileLength; /* 0x34 File length */ + DWORD nIcon; /* 0x38 icon number */ + DWORD fStartup; /* 0x3c startup type */ + DWORD wHotKey; /* 0x40 hotkey */ + DWORD Unknown5; /* 0x44 */ + DWORD Unknown6; /* 0x48 */ +} LINK_HEADER, * PLINK_HEADER; + +#define SHLINK_LOCAL 0 +#define SHLINK_REMOTE 1 + +typedef struct _LOCATION_INFO +{ + DWORD dwTotalSize; + DWORD dwHeaderSize; + DWORD dwFlags; + DWORD dwVolTableOfs; + DWORD dwLocalPathOfs; + DWORD dwNetworkVolTableOfs; + DWORD dwFinalPathOfs; +} LOCATION_INFO; + +typedef struct _LOCAL_VOLUME_INFO +{ + DWORD dwSize; + DWORD dwType; + DWORD dwVolSerial; + DWORD dwVolLabelOfs; +} LOCAL_VOLUME_INFO; + +#include "poppack.h" + +static IShellLinkAVtbl slvt; +static IShellLinkWVtbl slvtw; +static IPersistFileVtbl pfvt; +static IPersistStreamVtbl psvt; + +/* IShellLink Implementation */ + +typedef struct +{ + IShellLinkAVtbl *lpVtbl; + DWORD ref; + + IShellLinkWVtbl *lpvtblw; + IPersistFileVtbl *lpvtblPersistFile; + IPersistStreamVtbl *lpvtblPersistStream; + + /* data structures according to the informations in the link */ + LPITEMIDLIST pPidl; + WORD wHotKey; + SYSTEMTIME time1; + SYSTEMTIME time2; + SYSTEMTIME time3; + + DWORD iShowCmd; + LPWSTR sIcoPath; + INT iIcoNdx; + LPWSTR sPath; + LPWSTR sArgs; + LPWSTR sWorkDir; + LPWSTR sDescription; + LPWSTR sPathRel; + + BOOL bDirty; +} IShellLinkImpl; + +#define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw))) +#define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset) + +#define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile))) +#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset) + +#define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream))) +#define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset) + +static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath); + +/* strdup on the process heap */ +inline static LPWSTR HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str) +{ + INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + LPWSTR p = HeapAlloc( heap, flags, len*sizeof (WCHAR) ); + if( !p ) + return p; + MultiByteToWideChar( CP_ACP, 0, str, -1, p, len ); + return p; +} + + +/************************************************************************** + * IPersistFile_QueryInterface + */ +static HRESULT WINAPI IPersistFile_fnQueryInterface( + IPersistFile* iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + + TRACE("(%p)\n",This); + + return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj); +} + +/****************************************************************************** + * IPersistFile_AddRef + */ +static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellLinkA_AddRef((IShellLinkA*)This); +} +/****************************************************************************** + * IPersistFile_Release + */ +static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellLinkA_Release((IShellLinkA*)This); +} + +static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile* iface, CLSID *pClassID) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + FIXME("(%p)\n",This); + return NOERROR; +} +static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile* iface) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + + TRACE("(%p)\n",This); + + if (This->bDirty) + return S_OK; + + return S_FALSE; +} +static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream; + HRESULT r; + IStream *stm; + + TRACE("(%p, %s)\n",This, debugstr_w(pszFileName)); + + r = CreateStreamOnFile(pszFileName, dwMode, &stm); + if( SUCCEEDED( r ) ) + { + r = IPersistStream_Load(StreamThis, stm); + ShellLink_UpdatePath(This->sPathRel, pszFileName, This->sWorkDir, &This->sPath); + IStream_Release( stm ); + This->bDirty = FALSE; + } + + return r; +} + +static BOOL StartLinkProcessor( LPCOLESTR szLink ) +{ + static const WCHAR szFormat[] = {'w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e', + ' ','-','r',' ','"','%','s','"',0 }; + LONG len; + LPWSTR buffer; + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + len = sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR); + buffer = HeapAlloc( GetProcessHeap(), 0, len ); + if( !buffer ) + return FALSE; + + wsprintfW( buffer, szFormat, szLink ); + + TRACE("starting %s\n",debugstr_w(buffer)); + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (!CreateProcessW( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return FALSE; + + /* wait for a while to throttle the creation of linker processes */ + if( WAIT_OBJECT_0 != WaitForSingleObject( pi.hProcess, 10000 ) ) + WARN("Timed out waiting for shell linker\n"); + + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + return TRUE; +} + +static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + IPersistStream *StreamThis = (IPersistStream *)&This->lpvtblPersistStream; + HRESULT r; + IStream *stm; + + TRACE("(%p)->(%s)\n",This,debugstr_w(pszFileName)); + + if (!pszFileName || !This->sPath) + return E_FAIL; + + r = CreateStreamOnFile(pszFileName, STGM_READWRITE | STGM_CREATE, &stm); + if( SUCCEEDED( r ) ) + { + r = IPersistStream_Save(StreamThis, stm, FALSE); + IStream_Release( stm ); + + if( SUCCEEDED( r ) ) + { + StartLinkProcessor( pszFileName ); + + This->bDirty = FALSE; + } + else + { + DeleteFileW( pszFileName ); + WARN("Failed to create shortcut %s\n", debugstr_w(pszFileName) ); + } + } + + return r; +} + +static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName)); + return NOERROR; +} +static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName) +{ + _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface); + FIXME("(%p)\n",This); + return NOERROR; +} + +static IPersistFileVtbl pfvt = +{ + IPersistFile_fnQueryInterface, + IPersistFile_fnAddRef, + IPersistFile_fnRelease, + IPersistFile_fnGetClassID, + IPersistFile_fnIsDirty, + IPersistFile_fnLoad, + IPersistFile_fnSave, + IPersistFile_fnSaveCompleted, + IPersistFile_fnGetCurFile +}; + +/************************************************************************ + * IPersistStream_QueryInterface + */ +static HRESULT WINAPI IPersistStream_fnQueryInterface( + IPersistStream* iface, + REFIID riid, + VOID** ppvoid) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n",This); + + return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvoid); +} + +/************************************************************************ + * IPersistStream_Release + */ +static ULONG WINAPI IPersistStream_fnRelease( + IPersistStream* iface) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n",This); + + return IShellLinkA_Release((IShellLinkA*)This); +} + +/************************************************************************ + * IPersistStream_AddRef + */ +static ULONG WINAPI IPersistStream_fnAddRef( + IPersistStream* iface) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n",This); + + return IShellLinkA_AddRef((IShellLinkA*)This); +} + +/************************************************************************ + * IPersistStream_GetClassID + * + */ +static HRESULT WINAPI IPersistStream_fnGetClassID( + IPersistStream* iface, + CLSID* pClassID) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n", This); + + if (pClassID==0) + return E_POINTER; + +/* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */ + + return S_OK; +} + +/************************************************************************ + * IPersistStream_IsDirty (IPersistStream) + */ +static HRESULT WINAPI IPersistStream_fnIsDirty( + IPersistStream* iface) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n", This); + + return S_OK; +} + + +static HRESULT Stream_LoadString( IStream* stm, BOOL unicode, LPWSTR *pstr ) +{ + DWORD count; + USHORT len; + LPVOID temp; + LPWSTR str; + HRESULT r; + + TRACE("%p\n", stm); + + count = 0; + r = IStream_Read(stm, &len, sizeof(len), &count); + if ( FAILED (r) || ( count != sizeof(len) ) ) + return E_FAIL; + + if( unicode ) + len *= sizeof (WCHAR); + + TRACE("reading %d\n", len); + temp = HeapAlloc(GetProcessHeap(), 0, len+sizeof(WCHAR)); + if( !temp ) + return E_OUTOFMEMORY; + count = 0; + r = IStream_Read(stm, temp, len, &count); + if( FAILED (r) || ( count != len ) ) + { + HeapFree( GetProcessHeap(), 0, temp ); + return E_FAIL; + } + + TRACE("read %s\n", debugstr_an(temp,len)); + + /* convert to unicode if necessary */ + if( !unicode ) + { + count = MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, NULL, 0 ); + str = HeapAlloc( GetProcessHeap(), 0, (count+1)*sizeof (WCHAR) ); + if( str ) + MultiByteToWideChar( CP_ACP, 0, (LPSTR) temp, len, str, count ); + HeapFree( GetProcessHeap(), 0, temp ); + } + else + { + count /= 2; + str = (LPWSTR) temp; + } + str[count] = 0; + + *pstr = str; + + return S_OK; +} + +static HRESULT Stream_LoadLocation( IStream* stm ) +{ + DWORD size; + ULONG count; + HRESULT r; + LOCATION_INFO *loc; + + TRACE("%p\n",stm); + + r = IStream_Read( stm, &size, sizeof(size), &count ); + if( FAILED( r ) ) + return r; + if( count != sizeof(loc->dwTotalSize) ) + return E_FAIL; + + loc = HeapAlloc( GetProcessHeap(), 0, size ); + if( ! loc ) + return E_OUTOFMEMORY; + + r = IStream_Read( stm, &loc->dwHeaderSize, size-sizeof(size), &count ); + if( FAILED( r ) ) + goto end; + if( count != (size - sizeof(size)) ) + { + r = E_FAIL; + goto end; + } + loc->dwTotalSize = size; + + TRACE("Read %ld bytes\n",count); + + /* FIXME: do something useful with it */ + HeapFree( GetProcessHeap(), 0, loc ); + + return S_OK; +end: + HeapFree( GetProcessHeap(), 0, loc ); + return r; +} + +/************************************************************************ + * IPersistStream_Load (IPersistStream) + */ +static HRESULT WINAPI IPersistStream_fnLoad( + IPersistStream* iface, + IStream* stm) +{ + LINK_HEADER hdr; + ULONG dwBytesRead; + BOOL unicode; + WCHAR sTemp[MAX_PATH]; + HRESULT r; + + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)(%p)\n", This, stm); + + if( !stm ) + return STG_E_INVALIDPOINTER; + + dwBytesRead = 0; + r = IStream_Read(stm, &hdr, sizeof(hdr), &dwBytesRead); + if( FAILED( r ) ) + return r; + + if( dwBytesRead != sizeof(hdr)) + return E_FAIL; + if( hdr.dwSize != sizeof(hdr)) + return E_FAIL; + if( !IsEqualIID(&hdr.MagicGuid, &CLSID_ShellLink) ) + return E_FAIL; + + /* if( hdr.dwFlags & SCF_PIDL ) */ /* FIXME: seems to always have a PIDL */ + { + r = ILLoadFromStream( stm, &This->pPidl ); + if( FAILED( r ) ) + return r; + } + This->wHotKey = (WORD)hdr.wHotKey; + This->iIcoNdx = hdr.nIcon; + FileTimeToSystemTime (&hdr.Time1, &This->time1); + FileTimeToSystemTime (&hdr.Time2, &This->time2); + FileTimeToSystemTime (&hdr.Time3, &This->time3); +#if 1 + GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time1, NULL, sTemp, 256); + TRACE("-- time1: %s\n", debugstr_w(sTemp) ); + GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time2, NULL, sTemp, 256); + TRACE("-- time1: %s\n", debugstr_w(sTemp) ); + GetDateFormatW(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time3, NULL, sTemp, 256); + TRACE("-- time1: %s\n", debugstr_w(sTemp) ); + pdump (This->pPidl); +#endif + if( hdr.dwFlags & SCF_NORMAL ) + r = Stream_LoadLocation( stm ); + if( FAILED( r ) ) + goto end; + unicode = hdr.dwFlags & SCF_UNICODE; + if( hdr.dwFlags & SCF_DESCRIPTION ) + { + r = Stream_LoadString( stm, unicode, &This->sDescription ); + TRACE("Description -> %s\n",debugstr_w(This->sDescription)); + } + if( FAILED( r ) ) + goto end; + + if( hdr.dwFlags & SCF_RELATIVE ) + { + r = Stream_LoadString( stm, unicode, &This->sPathRel ); + TRACE("Relative Path-> %s\n",debugstr_w(This->sPathRel)); + } + if( FAILED( r ) ) + goto end; + + if( hdr.dwFlags & SCF_WORKDIR ) + { + r = Stream_LoadString( stm, unicode, &This->sWorkDir ); + TRACE("Working Dir -> %s\n",debugstr_w(This->sWorkDir)); + } + if( FAILED( r ) ) + goto end; + + if( hdr.dwFlags & SCF_ARGS ) + { + r = Stream_LoadString( stm, unicode, &This->sArgs ); + TRACE("Working Dir -> %s\n",debugstr_w(This->sArgs)); + } + if( FAILED( r ) ) + goto end; + + if( hdr.dwFlags & SCF_CUSTOMICON ) + { + r = Stream_LoadString( stm, unicode, &This->sIcoPath ); + TRACE("Icon file -> %s\n",debugstr_w(This->sIcoPath)); + } + if( FAILED( r ) ) + goto end; + + TRACE("OK\n"); + + pdump (This->pPidl); + + return S_OK; +end: + return r; +} + +/************************************************************************ + * Stream_WriteString + * + * Helper function for IPersistStream_Save. Writes a unicode string + * with terminating nul byte to a stream, preceded by the its length. + */ +static HRESULT Stream_WriteString( IStream* stm, LPCWSTR str ) +{ + USHORT len = lstrlenW( str ) + 1; + DWORD count; + HRESULT r; + + r = IStream_Write( stm, &len, sizeof(len), &count ); + if( FAILED( r ) ) + return r; + + len *= sizeof(WCHAR); + + r = IStream_Write( stm, str, len, &count ); + if( FAILED( r ) ) + return r; + + return S_OK; +} + +static HRESULT Stream_WriteLocationInfo( IStream* stm, LPCWSTR filename ) +{ + LOCATION_INFO loc; + ULONG count; + + FIXME("writing empty location info\n"); + + memset( &loc, 0, sizeof(loc) ); + loc.dwTotalSize = sizeof(loc) - sizeof(loc.dwTotalSize); + + /* FIXME: fill this in */ + + return IStream_Write( stm, &loc, loc.dwTotalSize, &count ); +} + +/************************************************************************ + * IPersistStream_Save (IPersistStream) + * + * FIXME: makes assumptions about byte order + */ +static HRESULT WINAPI IPersistStream_fnSave( + IPersistStream* iface, + IStream* stm, + BOOL fClearDirty) +{ + static const WCHAR wOpen[] = {'o','p','e','n',0}; + + LINK_HEADER header; + WCHAR exePath[MAX_PATH]; + ULONG count; + HRESULT r; + + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p) %p %x\n", This, stm, fClearDirty); + + *exePath = '\0'; + + if (This->sPath) + { + SHELL_FindExecutable(NULL, This->sPath, wOpen, exePath, MAX_PATH, NULL, NULL, NULL, NULL); + /* + * windows can create lnk files to executables that do not exist yet + * so if the executable does not exist the just trust the path they + * gave us + */ + if( !*exePath ) strcpyW(exePath,This->sPath); + } + + /* if there's no PIDL, generate one */ + if( ! This->pPidl ) This->pPidl = ILCreateFromPathW(exePath); + + memset(&header, 0, sizeof(header)); + header.dwSize = sizeof(header); + memcpy(&header.MagicGuid, &CLSID_ShellLink, sizeof(header.MagicGuid) ); + + header.wHotKey = This->wHotKey; + header.nIcon = This->iIcoNdx; + header.dwFlags = SCF_UNICODE; /* strings are in unicode */ + header.dwFlags |= SCF_NORMAL; /* how do we determine this ? */ + if( This->pPidl ) + header.dwFlags |= SCF_PIDL; + if( This->sDescription ) + header.dwFlags |= SCF_DESCRIPTION; + if( This->sWorkDir ) + header.dwFlags |= SCF_WORKDIR; + if( This->sArgs ) + header.dwFlags |= SCF_ARGS; + if( This->sIcoPath ) + header.dwFlags |= SCF_CUSTOMICON; + + SystemTimeToFileTime ( &This->time1, &header.Time1 ); + SystemTimeToFileTime ( &This->time2, &header.Time2 ); + SystemTimeToFileTime ( &This->time3, &header.Time3 ); + + /* write the Shortcut header */ + r = IStream_Write( stm, &header, sizeof(header), &count ); + if( FAILED( r ) ) + { + ERR("Write failed at %d\n",__LINE__); + return r; + } + + TRACE("Writing pidl \n"); + + /* write the PIDL to the shortcut */ + if( This->pPidl ) + { + r = ILSaveToStream( stm, This->pPidl ); + if( FAILED( r ) ) + { + ERR("Failed to write PIDL at %d\n",__LINE__); + return r; + } + } + + Stream_WriteLocationInfo( stm, exePath ); + + TRACE("Description = %s\n", debugstr_w(This->sDescription)); + if( This->sDescription ) + r = Stream_WriteString( stm, This->sDescription ); + + if( This->sPathRel ) + r = Stream_WriteString( stm, This->sPathRel ); + + if( This->sWorkDir ) + r = Stream_WriteString( stm, This->sWorkDir ); + + if( This->sArgs ) + r = Stream_WriteString( stm, This->sArgs ); + + if( This->sIcoPath ) + r = Stream_WriteString( stm, This->sIcoPath ); + + return S_OK; +} + +/************************************************************************ + * IPersistStream_GetSizeMax (IPersistStream) + */ +static HRESULT WINAPI IPersistStream_fnGetSizeMax( + IPersistStream* iface, + ULARGE_INTEGER* pcbSize) +{ + _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface); + + TRACE("(%p)\n", This); + + return E_NOTIMPL; +} + +static IPersistStreamVtbl psvt = +{ + IPersistStream_fnQueryInterface, + IPersistStream_fnAddRef, + IPersistStream_fnRelease, + IPersistStream_fnGetClassID, + IPersistStream_fnIsDirty, + IPersistStream_fnLoad, + IPersistStream_fnSave, + IPersistStream_fnGetSizeMax +}; + +/************************************************************************** + * IShellLink_Constructor + */ +HRESULT WINAPI IShellLink_Constructor ( + IUnknown * pUnkOuter, + REFIID riid, + LPVOID * ppv) +{ + IShellLinkImpl * sl; + + TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid)); + + *ppv = NULL; + + if(pUnkOuter) return CLASS_E_NOAGGREGATION; + sl = (IShellLinkImpl *) LocalAlloc(GMEM_ZEROINIT,sizeof(IShellLinkImpl)); + if (!sl) return E_OUTOFMEMORY; + + sl->ref = 1; + sl->lpVtbl = &slvt; + sl->lpvtblw = &slvtw; + sl->lpvtblPersistFile = &pfvt; + sl->lpvtblPersistStream = &psvt; + sl->iShowCmd = SW_SHOWNORMAL; + sl->bDirty = FALSE; + + TRACE("(%p)->()\n",sl); + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IShellLinkA)) + *ppv = sl; + else if (IsEqualIID(riid, &IID_IShellLinkW)) + *ppv = &(sl->lpvtblw); + else { + LocalFree((HLOCAL)sl); + ERR("E_NOINTERFACE\n"); + return E_NOINTERFACE; + } + + return S_OK; +} + + +static BOOL SHELL_ExistsFileW(LPCWSTR path) +{ + HANDLE hfile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hfile != INVALID_HANDLE_VALUE) { + CloseHandle(hfile); + return TRUE; + } else + return FALSE; +} + +/************************************************************************** + * ShellLink_UpdatePath + * update absolute path in sPath using relative path in sPathRel + */ +static HRESULT ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath) +{ + if (!path || !psPath) + return E_INVALIDARG; + + if (!*psPath && sPathRel) { + WCHAR buffer[2*MAX_PATH], abs_path[2*MAX_PATH]; + LPWSTR final = NULL; + + /* first try if [directory of link file] + [relative path] finds an existing file */ + + GetFullPathNameW( path, MAX_PATH*2, buffer, &final ); + if( !final ) + final = buffer; + lstrcpyW(final, sPathRel); + + *abs_path = '\0'; + + if (SHELL_ExistsFileW(buffer)) { + if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final)) + lstrcpyW(abs_path, buffer); + } else { + /* try if [working directory] + [relative path] finds an existing file */ + if (sWorkDir) { + lstrcpyW(buffer, sWorkDir); + lstrcpyW(PathAddBackslashW(buffer), sPathRel); + + if (SHELL_ExistsFileW(buffer)) + if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final)) + lstrcpyW(abs_path, buffer); + } + } + + /* FIXME: This is even not enough - not all shell links can be resolved using this algorithm. */ + if (!*abs_path) + lstrcpyW(abs_path, sPathRel); + + *psPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(abs_path)+1)*sizeof(WCHAR)); + if (!*psPath) + return E_OUTOFMEMORY; + + lstrcpyW(*psPath, abs_path); + } + + return S_OK; +} + +/************************************************************************** + * IShellLink_ConstructFromFile + */ +HRESULT WINAPI IShellLink_ConstructFromFile ( + IUnknown* pUnkOuter, + REFIID riid, + LPCITEMIDLIST pidl, + LPVOID* ppv +) +{ + IShellLinkW* psl; + + HRESULT hr = IShellLink_Constructor(NULL, riid, (LPVOID*)&psl); + + if (SUCCEEDED(hr)) { + IPersistFile* ppf; + + *ppv = NULL; + + hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf); + + if (SUCCEEDED(hr)) { + WCHAR path[MAX_PATH]; + + if (SHGetPathFromIDListW(pidl, path)) + hr = IPersistFile_Load(ppf, path, 0); + else + hr = E_FAIL; + + if (SUCCEEDED(hr)) + *ppv = (IUnknown*) psl; + + IPersistFile_Release(ppf); + } + + if (!*ppv) + IShellLinkW_Release(psl); + } + + return hr; +} + +/************************************************************************** + * IShellLinkA_QueryInterface + */ +static HRESULT WINAPI IShellLinkA_fnQueryInterface( IShellLinkA * iface, REFIID riid, LPVOID *ppvObj) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid)); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IShellLinkA)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IShellLinkW)) + { + *ppvObj = (IShellLinkW *)&(This->lpvtblw); + } + else if(IsEqualIID(riid, &IID_IPersistFile)) + { + *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile); + } + else if(IsEqualIID(riid, &IID_IPersistStream)) + { + *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream); + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)(*ppvObj)); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} +/****************************************************************************** + * IShellLinkA_AddRef + */ +static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return ++(This->ref); +} +/****************************************************************************** + * IShellLinkA_Release + */ +static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + if (--(This->ref)) + return This->ref; + + TRACE("-- destroying IShellLink(%p)\n",This); + + HeapFree(GetProcessHeap(), 0, This->sIcoPath); + HeapFree(GetProcessHeap(), 0, This->sArgs); + HeapFree(GetProcessHeap(), 0, This->sWorkDir); + HeapFree(GetProcessHeap(), 0, This->sDescription); + HeapFree(GetProcessHeap(),0,This->sPath); + + if (This->pPidl) + ILFree(This->pPidl); + + LocalFree((HANDLE)This); + + return 0; +} + +static HRESULT WINAPI IShellLinkA_fnGetPath(IShellLinkA * iface, LPSTR pszFile, + INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n", + This, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(This->sPath)); + + if( cchMaxPath ) + pszFile[0] = 0; + if (This->sPath) + WideCharToMultiByte( CP_ACP, 0, This->sPath, -1, + pszFile, cchMaxPath, NULL, NULL); + + if (pfd) FIXME("(%p): WIN32_FIND_DATA is not yet filled.\n", This); + + return NOERROR; +} + +static HRESULT WINAPI IShellLinkA_fnGetIDList(IShellLinkA * iface, LPITEMIDLIST * ppidl) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(ppidl=%p)\n",This, ppidl); + + *ppidl = ILClone(This->pPidl); + + return NOERROR; +} + +static HRESULT WINAPI IShellLinkA_fnSetIDList(IShellLinkA * iface, LPCITEMIDLIST pidl) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(pidl=%p)\n",This, pidl); + + if (This->pPidl) + ILFree(This->pPidl); + This->pPidl = ILClone (pidl); + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnGetDescription(IShellLinkA * iface, LPSTR pszName,INT cchMaxName) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName); + + if( cchMaxName ) + pszName[0] = 0; + if( This->sDescription ) + WideCharToMultiByte( CP_ACP, 0, This->sDescription, -1, + pszName, cchMaxName, NULL, NULL); + + return S_OK; +} +static HRESULT WINAPI IShellLinkA_fnSetDescription(IShellLinkA * iface, LPCSTR pszName) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(pName=%s)\n", This, pszName); + + HeapFree(GetProcessHeap(), 0, This->sDescription); + This->sDescription = HEAP_strdupAtoW( GetProcessHeap(), 0, pszName); + if ( !This->sDescription ) + return E_OUTOFMEMORY; + + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnGetWorkingDirectory(IShellLinkA * iface, LPSTR pszDir,INT cchMaxPath) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p len=%u)\n", This, pszDir, cchMaxPath); + + if( cchMaxPath ) + pszDir[0] = 0; + if( This->sWorkDir ) + WideCharToMultiByte( CP_ACP, 0, This->sWorkDir, -1, + pszDir, cchMaxPath, NULL, NULL); + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnSetWorkingDirectory(IShellLinkA * iface, LPCSTR pszDir) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(dir=%s)\n",This, pszDir); + + HeapFree(GetProcessHeap(), 0, This->sWorkDir); + This->sWorkDir = HEAP_strdupAtoW( GetProcessHeap(), 0, pszDir); + if ( !This->sWorkDir ) + return E_OUTOFMEMORY; + + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnGetArguments(IShellLinkA * iface, LPSTR pszArgs,INT cchMaxPath) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath); + + if( cchMaxPath ) + pszArgs[0] = 0; + if( This->sArgs ) + WideCharToMultiByte( CP_ACP, 0, This->sArgs, -1, + pszArgs, cchMaxPath, NULL, NULL); + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnSetArguments(IShellLinkA * iface, LPCSTR pszArgs) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(args=%s)\n",This, pszArgs); + + HeapFree(GetProcessHeap(), 0, This->sArgs); + This->sArgs = HEAP_strdupAtoW( GetProcessHeap(), 0, pszArgs); + if( !This->sArgs ) + return E_OUTOFMEMORY; + + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnGetHotkey(IShellLinkA * iface, WORD *pwHotkey) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey); + + *pwHotkey = This->wHotKey; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnSetHotkey(IShellLinkA * iface, WORD wHotkey) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(hotkey=%x)\n",This, wHotkey); + + This->wHotKey = wHotkey; + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnGetShowCmd(IShellLinkA * iface, INT *piShowCmd) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p)\n",This, piShowCmd); + *piShowCmd = This->iShowCmd; + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p) %d\n",This, iShowCmd); + + This->iShowCmd = iShowCmd; + This->bDirty = TRUE; + + return NOERROR; +} + +static HRESULT SHELL_PidlGeticonLocationA(IShellFolder* psf, LPITEMIDLIST pidl, LPSTR pszIconPath, int cchIconPath, int* piIcon) +{ + LPCITEMIDLIST pidlLast; + + HRESULT hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psf, &pidlLast); + + if (SUCCEEDED(hr)) { + IExtractIconA* pei; + + hr = IShellFolder_GetUIObjectOf(psf, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconA, NULL, (LPVOID*)&pei); + + if (SUCCEEDED(hr)) { + hr = IExtractIconA_GetIconLocation(pei, 0, pszIconPath, MAX_PATH, piIcon, NULL); + + IExtractIconA_Release(pei); + } + + IShellFolder_Release(psf); + } + + return hr; +} + +static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon); + + if (cchIconPath) + pszIconPath[0] = 0; + + if (This->sIcoPath) { + WideCharToMultiByte(CP_ACP, 0, This->sIcoPath, -1, pszIconPath, cchIconPath, NULL, NULL); + *piIcon = This->iIcoNdx; + return S_OK; + } + + if (This->pPidl || This->sPath) { + IShellFolder* pdsk; + + HRESULT hr = SHGetDesktopFolder(&pdsk); + + if (SUCCEEDED(hr)) { + /* first look for an icon using the PIDL (if present) */ + if (This->pPidl) + hr = SHELL_PidlGeticonLocationA(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); + else + hr = E_FAIL; + + /* if we couldn't find an icon yet, look for it using the file system path */ + if (FAILED(hr) && This->sPath) { + LPITEMIDLIST pidl; + + hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); + + if (SUCCEEDED(hr)) { + hr = SHELL_PidlGeticonLocationA(pdsk, pidl, pszIconPath, cchIconPath, piIcon); + + SHFree(pidl); + } + } + + IShellFolder_Release(pdsk); + } + + return hr; + } else + return E_FAIL; +} + +static HRESULT WINAPI IShellLinkA_fnSetIconLocation(IShellLinkA * iface, LPCSTR pszIconPath,INT iIcon) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + TRACE("(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon); + + HeapFree(GetProcessHeap(), 0, This->sIcoPath); + This->sIcoPath = HEAP_strdupAtoW(GetProcessHeap(), 0, pszIconPath); + if ( !This->sIcoPath ) + return E_OUTOFMEMORY; + + This->iIcoNdx = iIcon; + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR pszPathRel, DWORD dwReserved) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + FIXME("(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved); + + HeapFree(GetProcessHeap(), 0, This->sPathRel); + This->sPathRel = HEAP_strdupAtoW(GetProcessHeap(), 0, pszPathRel); + This->bDirty = TRUE; + + return ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath); +} + +static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags) +{ + HRESULT hr = S_OK; + + IShellLinkImpl *This = (IShellLinkImpl *)iface; + + FIXME("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags); + + /*FIXME: use IResolveShellLink interface */ + + if (!This->sPath && This->pPidl) { + WCHAR buffer[MAX_PATH]; + + hr = SHELL_GetPathFromIDListW(This->pPidl, buffer, MAX_PATH); + + if (SUCCEEDED(hr) && *buffer) { + This->sPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(buffer)+1)*sizeof(WCHAR)); + if (!This->sPath) + return E_OUTOFMEMORY; + + lstrcpyW(This->sPath, buffer); + + This->bDirty = TRUE; + } else + hr = S_OK; /* don't report an error occurred while just caching information */ + } + + if (!This->sIcoPath && This->sPath) { + This->sIcoPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(This->sPath)+1)*sizeof(WCHAR)); + if (!This->sIcoPath) + return E_OUTOFMEMORY; + + lstrcpyW(This->sIcoPath, This->sPath); + This->iIcoNdx = 0; + + This->bDirty = TRUE; + } + + return hr; +} + +static HRESULT WINAPI IShellLinkA_fnSetPath(IShellLinkA * iface, LPCSTR pszFile) +{ + IShellLinkImpl *This = (IShellLinkImpl *)iface; + char buffer[MAX_PATH]; + LPSTR fname; + + TRACE("(%p)->(path=%s)\n",This, pszFile); + + if (!GetFullPathNameA(pszFile, MAX_PATH, buffer, &fname)) + return E_FAIL; + + HeapFree(GetProcessHeap(), 0, This->sPath); + This->sPath = HEAP_strdupAtoW(GetProcessHeap(), 0, buffer); + if( !This->sPath ) + return E_OUTOFMEMORY; + + This->bDirty = TRUE; + + return S_OK; +} + +/************************************************************************** +* IShellLink Implementation +*/ + +static IShellLinkAVtbl slvt = +{ + IShellLinkA_fnQueryInterface, + IShellLinkA_fnAddRef, + IShellLinkA_fnRelease, + IShellLinkA_fnGetPath, + IShellLinkA_fnGetIDList, + IShellLinkA_fnSetIDList, + IShellLinkA_fnGetDescription, + IShellLinkA_fnSetDescription, + IShellLinkA_fnGetWorkingDirectory, + IShellLinkA_fnSetWorkingDirectory, + IShellLinkA_fnGetArguments, + IShellLinkA_fnSetArguments, + IShellLinkA_fnGetHotkey, + IShellLinkA_fnSetHotkey, + IShellLinkA_fnGetShowCmd, + IShellLinkA_fnSetShowCmd, + IShellLinkA_fnGetIconLocation, + IShellLinkA_fnSetIconLocation, + IShellLinkA_fnSetRelativePath, + IShellLinkA_fnResolve, + IShellLinkA_fnSetPath +}; + + +/************************************************************************** + * IShellLinkW_fnQueryInterface + */ +static HRESULT WINAPI IShellLinkW_fnQueryInterface( + IShellLinkW * iface, REFIID riid, LPVOID *ppvObj) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj); +} + +/****************************************************************************** + * IShellLinkW_fnAddRef + */ +static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellLinkA_AddRef((IShellLinkA*)This); +} +/****************************************************************************** + * IShellLinkW_fnRelease + */ + +static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellLinkA_Release((IShellLinkA*)This); +} + +static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n", + This, pszFile, cchMaxPath, pfd, fFlags); + + if( cchMaxPath ) + pszFile[0] = 0; + if( This->sPath ) + lstrcpynW( pszFile, This->sPath, cchMaxPath ); + + if (pfd) FIXME("(%p): WIN32_FIND_DATA is not yet filled.\n", This); + + return NOERROR; +} + +static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(ppidl=%p)\n",This, ppidl); + + if( This->pPidl) + *ppidl = ILClone( This->pPidl ); + else + *ppidl = NULL; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(pidl=%p)\n",This, pidl); + + if( This->pPidl ) + ILFree( This->pPidl ); + This->pPidl = ILClone( pidl ); + if( !This->pPidl ) + return E_FAIL; + + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p len=%u)\n",This, pszName, cchMaxName); + + if( cchMaxName ) + pszName[0] = 0; + if( This->sDescription ) + lstrcpynW( pszName, This->sDescription, cchMaxName ); + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(desc=%s)\n",This, debugstr_w(pszName)); + + HeapFree(GetProcessHeap(), 0, This->sDescription); + This->sDescription = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( pszName )+1)*sizeof(WCHAR) ); + if ( !This->sDescription ) + return E_OUTOFMEMORY; + + lstrcpyW( This->sDescription, pszName ); + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p len %u)\n", This, pszDir, cchMaxPath); + + if( cchMaxPath ) + pszDir[0] = 0; + if( This->sWorkDir ) + lstrcpynW( pszDir, This->sWorkDir, cchMaxPath ); + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(dir=%s)\n",This, debugstr_w(pszDir)); + + HeapFree(GetProcessHeap(), 0, This->sWorkDir); + This->sWorkDir = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( pszDir )+1)*sizeof (WCHAR) ); + if ( !This->sWorkDir ) + return E_OUTOFMEMORY; + lstrcpyW( This->sWorkDir, pszDir ); + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath); + + if( cchMaxPath ) + pszArgs[0] = 0; + if( This->sArgs ) + lstrcpynW( pszArgs, This->sArgs, cchMaxPath ); + + return NOERROR; +} + +static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(args=%s)\n",This, debugstr_w(pszArgs)); + + HeapFree(GetProcessHeap(), 0, This->sArgs); + This->sArgs = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( pszArgs )+1)*sizeof (WCHAR) ); + if ( !This->sArgs ) + return E_OUTOFMEMORY; + lstrcpyW( This->sArgs, pszArgs ); + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p)\n",This, pwHotkey); + + *pwHotkey=This->wHotKey; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(hotkey=%x)\n",This, wHotkey); + + This->wHotKey = wHotkey; + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p)\n",This, piShowCmd); + + *piShowCmd = This->iShowCmd; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + This->iShowCmd = iShowCmd; + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT SHELL_PidlGeticonLocationW(IShellFolder* psf, LPITEMIDLIST pidl, LPWSTR pszIconPath, int cchIconPath, int* piIcon) +{ + LPCITEMIDLIST pidlLast; + + HRESULT hr = SHBindToParent(pidl, &IID_IShellFolder, (LPVOID*)&psf, &pidlLast); + + if (SUCCEEDED(hr)) { + IExtractIconW* pei; + + hr = IShellFolder_GetUIObjectOf(psf, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW, NULL, (LPVOID*)&pei); + + if (SUCCEEDED(hr)) { + hr = IExtractIconW_GetIconLocation(pei, 0, pszIconPath, MAX_PATH, piIcon, NULL); + + IExtractIconW_Release(pei); + } + + IShellFolder_Release(psf); + } + + return hr; +} + +static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon); + + if (cchIconPath) + pszIconPath[0] = 0; + + if (This->sIcoPath) { + lstrcpynW(pszIconPath, This->sIcoPath, cchIconPath); + *piIcon = This->iIcoNdx; + return S_OK; + } + + if (This->pPidl || This->sPath) { + IShellFolder* pdsk; + + HRESULT hr = SHGetDesktopFolder(&pdsk); + + if (SUCCEEDED(hr)) { + /* first look for an icon using the PIDL (if present) */ + if (This->pPidl) + hr = SHELL_PidlGeticonLocationW(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); + else + hr = E_FAIL; + + /* if we couldn't find an icon yet, look for it using the file system path */ + if (FAILED(hr) && This->sPath) { + LPITEMIDLIST pidl; + + hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); + + if (SUCCEEDED(hr)) { + hr = SHELL_PidlGeticonLocationW(pdsk, pidl, pszIconPath, cchIconPath, piIcon); + + SHFree(pidl); + } + } + + IShellFolder_Release(pdsk); + } + + return hr; + } else + return E_FAIL; +} + +static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon); + + HeapFree(GetProcessHeap(), 0, This->sIcoPath); + This->sIcoPath = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( pszIconPath )+1)*sizeof (WCHAR) ); + if ( !This->sIcoPath ) + return E_OUTOFMEMORY; + lstrcpyW( This->sIcoPath, pszIconPath ); + + This->iIcoNdx = iIcon; + This->bDirty = TRUE; + + return S_OK; +} + +static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + TRACE("(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved); + + HeapFree(GetProcessHeap(), 0, This->sPathRel); + This->sPathRel = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( pszPathRel )+1) * sizeof (WCHAR) ); + if ( !This->sPathRel ) + return E_OUTOFMEMORY; + lstrcpyW( This->sPathRel, pszPathRel ); + This->bDirty = TRUE; + + return ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath); +} + +static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags) +{ + HRESULT hr = S_OK; + + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + + FIXME("(%p)->(hwnd=%p flags=%lx)\n",This, hwnd, fFlags); + + /*FIXME: use IResolveShellLink interface */ + + if (!This->sPath && This->pPidl) { + WCHAR buffer[MAX_PATH]; + + hr = SHELL_GetPathFromIDListW(This->pPidl, buffer, MAX_PATH); + + if (SUCCEEDED(hr) && *buffer) { + This->sPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(buffer)+1)*sizeof(WCHAR)); + if (!This->sPath) + return E_OUTOFMEMORY; + + lstrcpyW(This->sPath, buffer); + + This->bDirty = TRUE; + } else + hr = S_OK; /* don't report an error occurred while just caching information */ + } + + if (!This->sIcoPath && This->sPath) { + This->sIcoPath = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(This->sPath)+1)*sizeof(WCHAR)); + if (!This->sIcoPath) + return E_OUTOFMEMORY; + + lstrcpyW(This->sIcoPath, This->sPath); + This->iIcoNdx = 0; + + This->bDirty = TRUE; + } + + return hr; +} + +static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile) +{ + _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface); + WCHAR buffer[MAX_PATH]; + LPWSTR fname; + + TRACE("(%p)->(path=%s)\n",This, debugstr_w(pszFile)); + + if (!GetFullPathNameW(pszFile, MAX_PATH, buffer, &fname)) + return E_FAIL; + + HeapFree(GetProcessHeap(), 0, This->sPath); + This->sPath = HeapAlloc( GetProcessHeap(), 0, + (lstrlenW( buffer )+1) * sizeof (WCHAR) ); + if (!This->sPath) + return E_OUTOFMEMORY; + + lstrcpyW(This->sPath, buffer); + This->bDirty = TRUE; + + return S_OK; +} + +/************************************************************************** +* IShellLinkW Implementation +*/ + +static IShellLinkWVtbl slvtw = +{ + IShellLinkW_fnQueryInterface, + IShellLinkW_fnAddRef, + IShellLinkW_fnRelease, + IShellLinkW_fnGetPath, + IShellLinkW_fnGetIDList, + IShellLinkW_fnSetIDList, + IShellLinkW_fnGetDescription, + IShellLinkW_fnSetDescription, + IShellLinkW_fnGetWorkingDirectory, + IShellLinkW_fnSetWorkingDirectory, + IShellLinkW_fnGetArguments, + IShellLinkW_fnSetArguments, + IShellLinkW_fnGetHotkey, + IShellLinkW_fnSetHotkey, + IShellLinkW_fnGetShowCmd, + IShellLinkW_fnSetShowCmd, + IShellLinkW_fnGetIconLocation, + IShellLinkW_fnSetIconLocation, + IShellLinkW_fnSetRelativePath, + IShellLinkW_fnResolve, + IShellLinkW_fnSetPath +}; diff --git a/reactos/lib/shell32/shellole.c b/reactos/lib/shell32/shellole.c index c523ea6b53e..0167b16dc2f 100644 --- a/reactos/lib/shell32/shellole.c +++ b/reactos/lib/shell32/shellole.c @@ -1,802 +1,802 @@ -/* - * handling of SHELL32.DLL OLE-Objects - * - * Copyright 1997 Marcus Meissner - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "shellapi.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "shlguid.h" -#include "winreg.h" -#include "winerror.h" - -#include "undocshell.h" -#include "wine/unicode.h" -#include "shell32_main.h" - -#include "wine/debug.h" -#include "shlwapi.h" -#include "debughlp.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -extern HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); - -const WCHAR sShell32[12] = {'S','H','E','L','L','3','2','.','D','L','L','\0'}; -const WCHAR sOLE32[10] = {'O','L','E','3','2','.','D','L','L','\0'}; - -HINSTANCE hShellOle32 = 0; -/************************************************************************** - * Default ClassFactory types - */ -typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject); -IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst); - -/* this table contains all CLSID's of shell32 objects */ -struct { - REFIID riid; - LPFNCREATEINSTANCE lpfnCI; -} InterfaceTable[] = { - {&CLSID_ShellFSFolder, &IFSFolder_Constructor}, - {&CLSID_MyComputer, &ISF_MyComputer_Constructor}, - {&CLSID_ShellDesktop, &ISF_Desktop_Constructor}, - {&CLSID_ShellLink, &IShellLink_Constructor}, - {&CLSID_DragDropHelper, &IDropTargetHelper_Constructor}, - {&CLSID_ControlPanel, &IControlPanel_Constructor}, - {&CLSID_AutoComplete, &IAutoComplete_Constructor}, - {NULL,NULL} -}; - -/************************************************************************* - * SHCoCreateInstance [SHELL32.102] - * - * NOTES - * exported by ordinal - */ - -/* FIXME: this should be SHLWAPI.24 since we can't yet import by ordinal */ - -DWORD WINAPI __SHGUIDToStringW (REFGUID guid, LPWSTR str) -{ - WCHAR sFormat[52] = {'{','%','0','8','l','x','-','%','0','4', - 'x','-','%','0','4','x','-','%','0','2', - 'x','%','0','2','x','-','%','0','2','x', - '%','0','2','x','%','0','2','x','%','0', - '2','x','%','0','2','x','%','0','2','x', - '}','\0'}; - - return wsprintfW ( str, sFormat, - guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); - -} - -/************************************************************************/ - -HRESULT WINAPI SHCoCreateInstance( - LPCWSTR aclsid, - const CLSID *clsid, - LPUNKNOWN pUnkOuter, - REFIID refiid, - LPVOID *ppv) -{ - DWORD hres; - IID iid; - CLSID * myclsid = (CLSID*)clsid; - WCHAR sKeyName[MAX_PATH]; - const WCHAR sCLSID[7] = {'C','L','S','I','D','\\','\0'}; - WCHAR sClassID[60]; - const WCHAR sInProcServer32[16] ={'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2','\0'}; - const WCHAR sLoadWithoutCOM[15] ={'L','o','a','d','W','i','t','h','o','u','t','C','O','M','\0'}; - WCHAR sDllPath[MAX_PATH]; - HKEY hKey; - DWORD dwSize; - BOOLEAN bLoadFromShell32 = FALSE; - BOOLEAN bLoadWithoutCOM = FALSE; - IClassFactory * pcf = NULL; - - if(!ppv) return E_POINTER; - *ppv=NULL; - - /* if the clsid is a string, convert it */ - if (!clsid) - { - if (!aclsid) return REGDB_E_CLASSNOTREG; - SHCLSIDFromStringW(aclsid, &iid); - myclsid = &iid; - } - - TRACE("(%p,%s,unk:%p,%s,%p)\n", - aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv); - - /* we look up the dll path in the registry */ - __SHGUIDToStringW(myclsid, sClassID); - lstrcpyW(sKeyName, sCLSID); - lstrcatW(sKeyName, sClassID); - lstrcatW(sKeyName, sInProcServer32); - - if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey)) { - dwSize = sizeof(sDllPath); - SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize ); - - /* if a special registry key is set, we load a shell extension without help of OLE32 */ - bLoadWithoutCOM = (ERROR_SUCCESS == SHQueryValueExW(hKey, sLoadWithoutCOM, 0, 0, 0, 0)); - - /* if the com object is inside shell32, omit use of ole32 */ - bLoadFromShell32 = (0==lstrcmpiW( PathFindFileNameW(sDllPath), sShell32)); - - RegCloseKey (hKey); - } else { - /* since we can't find it in the registry we try internally */ - bLoadFromShell32 = TRUE; - } - - TRACE("WithoutCom=%u FromShell=%u\n", bLoadWithoutCOM, bLoadFromShell32); - - /* now we create a instance */ - if (bLoadFromShell32) { - if (! SUCCEEDED(SHELL32_DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) { - ERR("LoadFromShell failed for CLSID=%s\n", shdebugstr_guid(myclsid)); - } - } else if (bLoadWithoutCOM) { - - /* load a external dll without ole32 */ - HANDLE hLibrary; - typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv); - DllGetClassObjectFunc DllGetClassObject; - - if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) { - ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath)); - hres = E_ACCESSDENIED; - goto end; - } else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"))) { - ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(sDllPath)); - FreeLibrary( hLibrary ); - hres = E_ACCESSDENIED; - goto end; - } else if (! SUCCEEDED(hres = DllGetClassObject(myclsid, &IID_IClassFactory, (LPVOID*)&pcf))) { - TRACE("GetClassObject failed 0x%08lx\n", hres); - goto end; - } - - } else { - - /* load a external dll in the usual way */ - hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv); - goto end; - } - - /* here we should have a ClassFactory */ - if (!pcf) return E_ACCESSDENIED; - - hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv); - IClassFactory_Release(pcf); -end: - if(hres!=S_OK) - { - ERR("failed (0x%08lx) to create CLSID:%s IID:%s\n", - hres, shdebugstr_guid(myclsid), shdebugstr_guid(refiid)); - ERR("class not found in registry\n"); - } - - TRACE("-- instance: %p\n",*ppv); - return hres; -} - -/************************************************************************* - * DllGetClassObject [SHELL32.128] - */ -HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) -{ - HRESULT hres = E_OUTOFMEMORY; - IClassFactory * pcf = NULL; - int i; - - TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid)); - - if (!ppv) return E_INVALIDARG; - *ppv = NULL; - - /* search our internal interface table */ - for(i=0;InterfaceTable[i].riid;i++) { - if(IsEqualIID(InterfaceTable[i].riid, rclsid)) { - TRACE("index[%u]\n", i); - pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL); - } - } - - if (!pcf) { - FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid)); - return CLASS_E_CLASSNOTAVAILABLE; - } - - hres = IClassFactory_QueryInterface(pcf, iid, ppv); - IClassFactory_Release(pcf); - - TRACE("-- pointer to class factory: %p\n",*ppv); - return hres; -} - -/************************************************************************* - * SHCLSIDFromString [SHELL32.147] - * - * NOTES - * exported by ordinal - */ -DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id) -{ - WCHAR buffer[40]; - TRACE("(%p(%s) %p)\n", clsid, clsid, id); - if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) )) - return CO_E_CLASSSTRING; - return CLSIDFromString( buffer, id ); -} -DWORD WINAPI SHCLSIDFromStringW (LPCWSTR clsid, CLSID *id) -{ - TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id); - return CLSIDFromString((LPWSTR)clsid, id); -} -DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id) -{ - if (SHELL_OsIsUnicode()) - return SHCLSIDFromStringW (clsid, id); - return SHCLSIDFromStringA (clsid, id); -} - -/************************************************************************* - * Shell Memory Allocator - */ - -/* set the vtable later */ -static IMallocVtbl VT_Shell_IMalloc32; - -/* this is the static object instance */ -typedef struct { - IMallocVtbl *lpVtbl; - DWORD dummy; -} _ShellMalloc; - -static _ShellMalloc Shell_Malloc = { &VT_Shell_IMalloc32,1}; - -/* this is the global allocator of shell32 */ -static IMalloc * ShellTaskAllocator = NULL; - -/****************************************************************************** - * IShellMalloc_QueryInterface [VTABLE] - */ -static HRESULT WINAPI IShellMalloc_fnQueryInterface(LPMALLOC iface, REFIID refiid, LPVOID *obj) -{ - TRACE("(%s,%p)\n",shdebugstr_guid(refiid),obj); - if (IsEqualIID(refiid, &IID_IUnknown) || IsEqualIID(refiid, &IID_IMalloc)) { - *obj = (LPMALLOC) &Shell_Malloc; - return S_OK; - } - return E_NOINTERFACE; -} - -/****************************************************************************** - * IShellMalloc_AddRefRelease [VTABLE] - */ -static ULONG WINAPI IShellMalloc_fnAddRefRelease(LPMALLOC iface) -{ - return 1; -} - -/****************************************************************************** - * IShellMalloc_Alloc [VTABLE] - */ -static LPVOID WINAPI IShellMalloc_fnAlloc(LPMALLOC iface, DWORD cb) -{ - LPVOID addr; - - addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb); - TRACE("(%p,%ld);\n",addr,cb); - return addr; -} - -/****************************************************************************** - * IShellMalloc_Realloc [VTABLE] - */ -static LPVOID WINAPI IShellMalloc_fnRealloc(LPMALLOC iface, LPVOID pv, DWORD cb) -{ - LPVOID addr; - - if (pv) { - if (cb) { - addr = (LPVOID) LocalReAlloc((HANDLE) pv, cb, GMEM_ZEROINIT | GMEM_MOVEABLE); - } else { - LocalFree((HANDLE) pv); - addr = NULL; - } - } else { - if (cb) { - addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb); - } else { - addr = NULL; - } - } - - TRACE("(%p->%p,%ld)\n",pv,addr,cb); - return addr; -} - -/****************************************************************************** - * IShellMalloc_Free [VTABLE] - */ -static VOID WINAPI IShellMalloc_fnFree(LPMALLOC iface, LPVOID pv) -{ - TRACE("(%p)\n",pv); - LocalFree((HANDLE) pv); -} - -/****************************************************************************** - * IShellMalloc_GetSize [VTABLE] - */ -static DWORD WINAPI IShellMalloc_fnGetSize(LPMALLOC iface, LPVOID pv) -{ - DWORD cb = (DWORD) LocalSize((HANDLE)pv); - TRACE("(%p,%ld)\n", pv, cb); - return cb; -} - -/****************************************************************************** - * IShellMalloc_DidAlloc [VTABLE] - */ -static INT WINAPI IShellMalloc_fnDidAlloc(LPMALLOC iface, LPVOID pv) -{ - TRACE("(%p)\n",pv); - return -1; -} - -/****************************************************************************** - * IShellMalloc_HeapMinimize [VTABLE] - */ -static VOID WINAPI IShellMalloc_fnHeapMinimize(LPMALLOC iface) -{ - TRACE("()\n"); -} - -static IMallocVtbl VT_Shell_IMalloc32 = -{ - IShellMalloc_fnQueryInterface, - IShellMalloc_fnAddRefRelease, - IShellMalloc_fnAddRefRelease, - IShellMalloc_fnAlloc, - IShellMalloc_fnRealloc, - IShellMalloc_fnFree, - IShellMalloc_fnGetSize, - IShellMalloc_fnDidAlloc, - IShellMalloc_fnHeapMinimize -}; - -/************************************************************************* - * SHGetMalloc [SHELL32.@] - * - * Return the shell IMalloc interface. - * - * PARAMS - * lpmal [O] Destination for IMalloc interface. - * - * RETURNS - * Success: S_OK. lpmal contains the shells IMalloc interface. - * Failure. An HRESULT error code. - * - * NOTES - * This function will use CoGetMalloc() if OLE32.DLL is already loaded. - * If not it uses an internal implementation as a fallback. - */ -HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal) -{ - TRACE("(%p)\n", lpmal); - - if (!ShellTaskAllocator) - { - HMODULE hOle32 = GetModuleHandleA("OLE32.DLL"); - /* this is very suspect. we should not being using a different - * allocator from deallocator based on something undeterministic - * like whether ole32 is loaded. as it happens currently, they - * both map to the same allocator deep down, but this could - * change in the future. */ - if(hOle32) { - CoGetMalloc(MEMCTX_TASK, &ShellTaskAllocator); - TRACE("got ole32 IMalloc\n"); - } - if(!ShellTaskAllocator) { - ShellTaskAllocator = (IMalloc* ) &Shell_Malloc; - TRACE("use fallback allocator\n"); - } - } - *lpmal = ShellTaskAllocator; - return S_OK; -} - -/************************************************************************* - * SHAlloc [SHELL32.196] - * - * NOTES - * exported by ordinal - */ -LPVOID WINAPI SHAlloc(DWORD len) -{ - IMalloc * ppv; - LPBYTE ret; - - if (!ShellTaskAllocator) SHGetMalloc(&ppv); - - ret = (LPVOID) IMalloc_Alloc(ShellTaskAllocator, len); - TRACE("%lu bytes at %p\n",len, ret); - return (LPVOID)ret; -} - -/************************************************************************* - * SHFree [SHELL32.195] - * - * NOTES - * exported by ordinal - */ -void WINAPI SHFree(LPVOID pv) -{ - IMalloc * ppv; - - TRACE("%p\n",pv); - if (!ShellTaskAllocator) SHGetMalloc(&ppv); - IMalloc_Free(ShellTaskAllocator, pv); -} - -/************************************************************************* - * SHGetDesktopFolder [SHELL32.@] - */ -HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf) -{ - HRESULT hres = S_OK; - TRACE("\n"); - - if(!psf) return E_INVALIDARG; - *psf = NULL; - hres = ISF_Desktop_Constructor(NULL, &IID_IShellFolder,(LPVOID*)psf); - - TRACE("-- %p->(%p)\n",psf, *psf); - return hres; -} -/************************************************************************** - * Default ClassFactory Implementation - * - * SHCreateDefClassObject - * - * NOTES - * helper function for dll's without a own classfactory - * a generic classfactory is returned - * when the CreateInstance of the cf is called the callback is executed - */ - -typedef struct -{ - IClassFactoryVtbl *lpVtbl; - DWORD ref; - CLSID *rclsid; - LPFNCREATEINSTANCE lpfnCI; - const IID * riidInst; - ULONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */ -} IDefClFImpl; - -static IClassFactoryVtbl dclfvt; - -/************************************************************************** - * IDefClF_fnConstructor - */ - -IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst) -{ - IDefClFImpl* lpclf; - - lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl)); - lpclf->ref = 1; - lpclf->lpVtbl = &dclfvt; - lpclf->lpfnCI = lpfnCI; - lpclf->pcRefDll = pcRefDll; - - if (pcRefDll) InterlockedIncrement(pcRefDll); - lpclf->riidInst = riidInst; - - TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst)); - return (LPCLASSFACTORY)lpclf; -} -/************************************************************************** - * IDefClF_fnQueryInterface - */ -static HRESULT WINAPI IDefClF_fnQueryInterface( - LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj) -{ - IDefClFImpl *This = (IDefClFImpl *)iface; - - TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid)); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { - *ppvObj = This; - InterlockedIncrement(&This->ref); - return S_OK; - } - - TRACE("-- E_NOINTERFACE\n"); - return E_NOINTERFACE; -} -/****************************************************************************** - * IDefClF_fnAddRef - */ -static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface) -{ - IDefClFImpl *This = (IDefClFImpl *)iface; - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return InterlockedIncrement(&This->ref); -} -/****************************************************************************** - * IDefClF_fnRelease - */ -static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface) -{ - IDefClFImpl *This = (IDefClFImpl *)iface; - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - if (!InterlockedDecrement(&This->ref)) - { - if (This->pcRefDll) InterlockedDecrement(This->pcRefDll); - - TRACE("-- destroying IClassFactory(%p)\n",This); - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} -/****************************************************************************** - * IDefClF_fnCreateInstance - */ -static HRESULT WINAPI IDefClF_fnCreateInstance( - LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject) -{ - IDefClFImpl *This = (IDefClFImpl *)iface; - - TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject); - - *ppvObject = NULL; - - if ( This->riidInst==NULL || - IsEqualCLSID(riid, This->riidInst) || - IsEqualCLSID(riid, &IID_IUnknown) ) - { - return This->lpfnCI(pUnkOuter, riid, ppvObject); - } - - ERR("unknown IID requested %s\n",shdebugstr_guid(riid)); - return E_NOINTERFACE; -} -/****************************************************************************** - * IDefClF_fnLockServer - */ -static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock) -{ - IDefClFImpl *This = (IDefClFImpl *)iface; - TRACE("%p->(0x%x), not implemented\n",This, fLock); - return E_NOTIMPL; -} - -static IClassFactoryVtbl dclfvt = -{ - IDefClF_fnQueryInterface, - IDefClF_fnAddRef, - IDefClF_fnRelease, - IDefClF_fnCreateInstance, - IDefClF_fnLockServer -}; - -/****************************************************************************** - * SHCreateDefClassObject [SHELL32.70] - */ -HRESULT WINAPI SHCreateDefClassObject( - REFIID riid, - LPVOID* ppv, - LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */ - LPDWORD pcRefDll, /* [in/out] ref count of the dll */ - REFIID riidInst) /* [in] optional interface to the instance */ -{ - IClassFactory * pcf; - - TRACE("%s %p %p %p %s\n", - shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst)); - - if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE; - if (! (pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst))) return E_OUTOFMEMORY; - *ppv = pcf; - return NOERROR; -} - -/************************************************************************* - * DragAcceptFiles [SHELL32.54] - */ -void WINAPI DragAcceptFiles(HWND hWnd, BOOL b) -{ - LONG exstyle; - - if( !IsWindow(hWnd) ) return; - exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE); - if (b) - exstyle |= WS_EX_ACCEPTFILES; - else - exstyle &= ~WS_EX_ACCEPTFILES; - SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle); -} - -/************************************************************************* - * DragFinish [SHELL32.80] - */ -void WINAPI DragFinish(HDROP h) -{ - TRACE("\n"); - GlobalFree((HGLOBAL)h); -} - -/************************************************************************* - * DragQueryPoint [SHELL32.135] - */ -BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p) -{ - DROPFILES *lpDropFileStruct; - BOOL bRet; - - TRACE("\n"); - - lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); - - *p = lpDropFileStruct->pt; - bRet = lpDropFileStruct->fNC; - - GlobalUnlock(hDrop); - return bRet; -} - -/************************************************************************* - * DragQueryFile [SHELL32.81] - * DragQueryFileA [SHELL32.82] - */ -UINT WINAPI DragQueryFileA( - HDROP hDrop, - UINT lFile, - LPSTR lpszFile, - UINT lLength) -{ - LPSTR lpDrop; - UINT i = 0; - DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); - - TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength); - - if(!lpDropFileStruct) goto end; - - lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles; - - if(lpDropFileStruct->fWide == TRUE) { - LPWSTR lpszFileW = NULL; - - if(lpszFile) { - lpszFileW = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR)); - if(lpszFileW == NULL) { - goto end; - } - } - i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength); - - if(lpszFileW) { - WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL); - HeapFree(GetProcessHeap(), 0, lpszFileW); - } - goto end; - } - - while (i++ < lFile) - { - while (*lpDrop++); /* skip filename */ - if (!*lpDrop) - { - i = (lFile == 0xFFFFFFFF) ? i : 0; - goto end; - } - } - - i = strlen(lpDrop); - i++; - if (!lpszFile ) goto end; /* needed buffer size */ - i = (lLength > i) ? i : lLength; - lstrcpynA (lpszFile, lpDrop, i); -end: - GlobalUnlock(hDrop); - return i; -} - -/************************************************************************* - * DragQueryFileW [SHELL32.133] - */ -UINT WINAPI DragQueryFileW( - HDROP hDrop, - UINT lFile, - LPWSTR lpszwFile, - UINT lLength) -{ - LPWSTR lpwDrop; - UINT i = 0; - DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); - - TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength); - - if(!lpDropFileStruct) goto end; - - lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles); - - if(lpDropFileStruct->fWide == FALSE) { - LPSTR lpszFileA = NULL; - - if(lpszwFile) { - lpszFileA = (LPSTR) HeapAlloc(GetProcessHeap(), 0, lLength); - if(lpszFileA == NULL) { - goto end; - } - } - i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength); - - if(lpszFileA) { - MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength); - HeapFree(GetProcessHeap(), 0, lpszFileA); - } - goto end; - } - - i = 0; - while (i++ < lFile) - { - while (*lpwDrop++); /* skip filename */ - if (!*lpwDrop) - { - i = (lFile == 0xFFFFFFFF) ? i : 0; - goto end; - } - } - - i = strlenW(lpwDrop); - i++; - if ( !lpszwFile) goto end; /* needed buffer size */ - - i = (lLength > i) ? i : lLength; - lstrcpynW (lpszwFile, lpwDrop, i); -end: - GlobalUnlock(hDrop); - return i; -} +/* + * handling of SHELL32.DLL OLE-Objects + * + * Copyright 1997 Marcus Meissner + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "shellapi.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "shlguid.h" +#include "winreg.h" +#include "winerror.h" + +#include "undocshell.h" +#include "wine/unicode.h" +#include "shell32_main.h" + +#include "wine/debug.h" +#include "shlwapi.h" +#include "debughlp.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +extern HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); + +const WCHAR sShell32[12] = {'S','H','E','L','L','3','2','.','D','L','L','\0'}; +const WCHAR sOLE32[10] = {'O','L','E','3','2','.','D','L','L','\0'}; + +HINSTANCE hShellOle32 = 0; +/************************************************************************** + * Default ClassFactory types + */ +typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject); +IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst); + +/* this table contains all CLSID's of shell32 objects */ +struct { + REFIID riid; + LPFNCREATEINSTANCE lpfnCI; +} InterfaceTable[] = { + {&CLSID_ShellFSFolder, &IFSFolder_Constructor}, + {&CLSID_MyComputer, &ISF_MyComputer_Constructor}, + {&CLSID_ShellDesktop, &ISF_Desktop_Constructor}, + {&CLSID_ShellLink, &IShellLink_Constructor}, + {&CLSID_DragDropHelper, &IDropTargetHelper_Constructor}, + {&CLSID_ControlPanel, &IControlPanel_Constructor}, + {&CLSID_AutoComplete, &IAutoComplete_Constructor}, + {NULL,NULL} +}; + +/************************************************************************* + * SHCoCreateInstance [SHELL32.102] + * + * NOTES + * exported by ordinal + */ + +/* FIXME: this should be SHLWAPI.24 since we can't yet import by ordinal */ + +DWORD WINAPI __SHGUIDToStringW (REFGUID guid, LPWSTR str) +{ + WCHAR sFormat[52] = {'{','%','0','8','l','x','-','%','0','4', + 'x','-','%','0','4','x','-','%','0','2', + 'x','%','0','2','x','-','%','0','2','x', + '%','0','2','x','%','0','2','x','%','0', + '2','x','%','0','2','x','%','0','2','x', + '}','\0'}; + + return wsprintfW ( str, sFormat, + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); + +} + +/************************************************************************/ + +HRESULT WINAPI SHCoCreateInstance( + LPCWSTR aclsid, + const CLSID *clsid, + LPUNKNOWN pUnkOuter, + REFIID refiid, + LPVOID *ppv) +{ + DWORD hres; + IID iid; + CLSID * myclsid = (CLSID*)clsid; + WCHAR sKeyName[MAX_PATH]; + const WCHAR sCLSID[7] = {'C','L','S','I','D','\\','\0'}; + WCHAR sClassID[60]; + const WCHAR sInProcServer32[16] ={'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2','\0'}; + const WCHAR sLoadWithoutCOM[15] ={'L','o','a','d','W','i','t','h','o','u','t','C','O','M','\0'}; + WCHAR sDllPath[MAX_PATH]; + HKEY hKey; + DWORD dwSize; + BOOLEAN bLoadFromShell32 = FALSE; + BOOLEAN bLoadWithoutCOM = FALSE; + IClassFactory * pcf = NULL; + + if(!ppv) return E_POINTER; + *ppv=NULL; + + /* if the clsid is a string, convert it */ + if (!clsid) + { + if (!aclsid) return REGDB_E_CLASSNOTREG; + SHCLSIDFromStringW(aclsid, &iid); + myclsid = &iid; + } + + TRACE("(%p,%s,unk:%p,%s,%p)\n", + aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv); + + /* we look up the dll path in the registry */ + __SHGUIDToStringW(myclsid, sClassID); + lstrcpyW(sKeyName, sCLSID); + lstrcatW(sKeyName, sClassID); + lstrcatW(sKeyName, sInProcServer32); + + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey)) { + dwSize = sizeof(sDllPath); + SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize ); + + /* if a special registry key is set, we load a shell extension without help of OLE32 */ + bLoadWithoutCOM = (ERROR_SUCCESS == SHQueryValueExW(hKey, sLoadWithoutCOM, 0, 0, 0, 0)); + + /* if the com object is inside shell32, omit use of ole32 */ + bLoadFromShell32 = (0==lstrcmpiW( PathFindFileNameW(sDllPath), sShell32)); + + RegCloseKey (hKey); + } else { + /* since we can't find it in the registry we try internally */ + bLoadFromShell32 = TRUE; + } + + TRACE("WithoutCom=%u FromShell=%u\n", bLoadWithoutCOM, bLoadFromShell32); + + /* now we create a instance */ + if (bLoadFromShell32) { + if (! SUCCEEDED(SHELL32_DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) { + ERR("LoadFromShell failed for CLSID=%s\n", shdebugstr_guid(myclsid)); + } + } else if (bLoadWithoutCOM) { + + /* load a external dll without ole32 */ + HANDLE hLibrary; + typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv); + DllGetClassObjectFunc DllGetClassObject; + + if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) { + ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath)); + hres = E_ACCESSDENIED; + goto end; + } else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"))) { + ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(sDllPath)); + FreeLibrary( hLibrary ); + hres = E_ACCESSDENIED; + goto end; + } else if (! SUCCEEDED(hres = DllGetClassObject(myclsid, &IID_IClassFactory, (LPVOID*)&pcf))) { + TRACE("GetClassObject failed 0x%08lx\n", hres); + goto end; + } + + } else { + + /* load a external dll in the usual way */ + hres = CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv); + goto end; + } + + /* here we should have a ClassFactory */ + if (!pcf) return E_ACCESSDENIED; + + hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv); + IClassFactory_Release(pcf); +end: + if(hres!=S_OK) + { + ERR("failed (0x%08lx) to create CLSID:%s IID:%s\n", + hres, shdebugstr_guid(myclsid), shdebugstr_guid(refiid)); + ERR("class not found in registry\n"); + } + + TRACE("-- instance: %p\n",*ppv); + return hres; +} + +/************************************************************************* + * DllGetClassObject [SHELL32.128] + */ +HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +{ + HRESULT hres = E_OUTOFMEMORY; + IClassFactory * pcf = NULL; + int i; + + TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid)); + + if (!ppv) return E_INVALIDARG; + *ppv = NULL; + + /* search our internal interface table */ + for(i=0;InterfaceTable[i].riid;i++) { + if(IsEqualIID(InterfaceTable[i].riid, rclsid)) { + TRACE("index[%u]\n", i); + pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL); + } + } + + if (!pcf) { + FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + hres = IClassFactory_QueryInterface(pcf, iid, ppv); + IClassFactory_Release(pcf); + + TRACE("-- pointer to class factory: %p\n",*ppv); + return hres; +} + +/************************************************************************* + * SHCLSIDFromString [SHELL32.147] + * + * NOTES + * exported by ordinal + */ +DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id) +{ + WCHAR buffer[40]; + TRACE("(%p(%s) %p)\n", clsid, clsid, id); + if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) )) + return CO_E_CLASSSTRING; + return CLSIDFromString( buffer, id ); +} +DWORD WINAPI SHCLSIDFromStringW (LPCWSTR clsid, CLSID *id) +{ + TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id); + return CLSIDFromString((LPWSTR)clsid, id); +} +DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id) +{ + if (SHELL_OsIsUnicode()) + return SHCLSIDFromStringW (clsid, id); + return SHCLSIDFromStringA (clsid, id); +} + +/************************************************************************* + * Shell Memory Allocator + */ + +/* set the vtable later */ +static IMallocVtbl VT_Shell_IMalloc32; + +/* this is the static object instance */ +typedef struct { + IMallocVtbl *lpVtbl; + DWORD dummy; +} _ShellMalloc; + +static _ShellMalloc Shell_Malloc = { &VT_Shell_IMalloc32,1}; + +/* this is the global allocator of shell32 */ +static IMalloc * ShellTaskAllocator = NULL; + +/****************************************************************************** + * IShellMalloc_QueryInterface [VTABLE] + */ +static HRESULT WINAPI IShellMalloc_fnQueryInterface(LPMALLOC iface, REFIID refiid, LPVOID *obj) +{ + TRACE("(%s,%p)\n",shdebugstr_guid(refiid),obj); + if (IsEqualIID(refiid, &IID_IUnknown) || IsEqualIID(refiid, &IID_IMalloc)) { + *obj = (LPMALLOC) &Shell_Malloc; + return S_OK; + } + return E_NOINTERFACE; +} + +/****************************************************************************** + * IShellMalloc_AddRefRelease [VTABLE] + */ +static ULONG WINAPI IShellMalloc_fnAddRefRelease(LPMALLOC iface) +{ + return 1; +} + +/****************************************************************************** + * IShellMalloc_Alloc [VTABLE] + */ +static LPVOID WINAPI IShellMalloc_fnAlloc(LPMALLOC iface, DWORD cb) +{ + LPVOID addr; + + addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb); + TRACE("(%p,%ld);\n",addr,cb); + return addr; +} + +/****************************************************************************** + * IShellMalloc_Realloc [VTABLE] + */ +static LPVOID WINAPI IShellMalloc_fnRealloc(LPMALLOC iface, LPVOID pv, DWORD cb) +{ + LPVOID addr; + + if (pv) { + if (cb) { + addr = (LPVOID) LocalReAlloc((HANDLE) pv, cb, GMEM_ZEROINIT | GMEM_MOVEABLE); + } else { + LocalFree((HANDLE) pv); + addr = NULL; + } + } else { + if (cb) { + addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb); + } else { + addr = NULL; + } + } + + TRACE("(%p->%p,%ld)\n",pv,addr,cb); + return addr; +} + +/****************************************************************************** + * IShellMalloc_Free [VTABLE] + */ +static VOID WINAPI IShellMalloc_fnFree(LPMALLOC iface, LPVOID pv) +{ + TRACE("(%p)\n",pv); + LocalFree((HANDLE) pv); +} + +/****************************************************************************** + * IShellMalloc_GetSize [VTABLE] + */ +static DWORD WINAPI IShellMalloc_fnGetSize(LPMALLOC iface, LPVOID pv) +{ + DWORD cb = (DWORD) LocalSize((HANDLE)pv); + TRACE("(%p,%ld)\n", pv, cb); + return cb; +} + +/****************************************************************************** + * IShellMalloc_DidAlloc [VTABLE] + */ +static INT WINAPI IShellMalloc_fnDidAlloc(LPMALLOC iface, LPVOID pv) +{ + TRACE("(%p)\n",pv); + return -1; +} + +/****************************************************************************** + * IShellMalloc_HeapMinimize [VTABLE] + */ +static VOID WINAPI IShellMalloc_fnHeapMinimize(LPMALLOC iface) +{ + TRACE("()\n"); +} + +static IMallocVtbl VT_Shell_IMalloc32 = +{ + IShellMalloc_fnQueryInterface, + IShellMalloc_fnAddRefRelease, + IShellMalloc_fnAddRefRelease, + IShellMalloc_fnAlloc, + IShellMalloc_fnRealloc, + IShellMalloc_fnFree, + IShellMalloc_fnGetSize, + IShellMalloc_fnDidAlloc, + IShellMalloc_fnHeapMinimize +}; + +/************************************************************************* + * SHGetMalloc [SHELL32.@] + * + * Return the shell IMalloc interface. + * + * PARAMS + * lpmal [O] Destination for IMalloc interface. + * + * RETURNS + * Success: S_OK. lpmal contains the shells IMalloc interface. + * Failure. An HRESULT error code. + * + * NOTES + * This function will use CoGetMalloc() if OLE32.DLL is already loaded. + * If not it uses an internal implementation as a fallback. + */ +HRESULT WINAPI SHGetMalloc(LPMALLOC *lpmal) +{ + TRACE("(%p)\n", lpmal); + + if (!ShellTaskAllocator) + { + HMODULE hOle32 = GetModuleHandleA("OLE32.DLL"); + /* this is very suspect. we should not being using a different + * allocator from deallocator based on something undeterministic + * like whether ole32 is loaded. as it happens currently, they + * both map to the same allocator deep down, but this could + * change in the future. */ + if(hOle32) { + CoGetMalloc(MEMCTX_TASK, &ShellTaskAllocator); + TRACE("got ole32 IMalloc\n"); + } + if(!ShellTaskAllocator) { + ShellTaskAllocator = (IMalloc* ) &Shell_Malloc; + TRACE("use fallback allocator\n"); + } + } + *lpmal = ShellTaskAllocator; + return S_OK; +} + +/************************************************************************* + * SHAlloc [SHELL32.196] + * + * NOTES + * exported by ordinal + */ +LPVOID WINAPI SHAlloc(DWORD len) +{ + IMalloc * ppv; + LPBYTE ret; + + if (!ShellTaskAllocator) SHGetMalloc(&ppv); + + ret = (LPVOID) IMalloc_Alloc(ShellTaskAllocator, len); + TRACE("%lu bytes at %p\n",len, ret); + return (LPVOID)ret; +} + +/************************************************************************* + * SHFree [SHELL32.195] + * + * NOTES + * exported by ordinal + */ +void WINAPI SHFree(LPVOID pv) +{ + IMalloc * ppv; + + TRACE("%p\n",pv); + if (!ShellTaskAllocator) SHGetMalloc(&ppv); + IMalloc_Free(ShellTaskAllocator, pv); +} + +/************************************************************************* + * SHGetDesktopFolder [SHELL32.@] + */ +HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf) +{ + HRESULT hres = S_OK; + TRACE("\n"); + + if(!psf) return E_INVALIDARG; + *psf = NULL; + hres = ISF_Desktop_Constructor(NULL, &IID_IShellFolder,(LPVOID*)psf); + + TRACE("-- %p->(%p)\n",psf, *psf); + return hres; +} +/************************************************************************** + * Default ClassFactory Implementation + * + * SHCreateDefClassObject + * + * NOTES + * helper function for dll's without a own classfactory + * a generic classfactory is returned + * when the CreateInstance of the cf is called the callback is executed + */ + +typedef struct +{ + IClassFactoryVtbl *lpVtbl; + DWORD ref; + CLSID *rclsid; + LPFNCREATEINSTANCE lpfnCI; + const IID * riidInst; + ULONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */ +} IDefClFImpl; + +static IClassFactoryVtbl dclfvt; + +/************************************************************************** + * IDefClF_fnConstructor + */ + +IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst) +{ + IDefClFImpl* lpclf; + + lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl)); + lpclf->ref = 1; + lpclf->lpVtbl = &dclfvt; + lpclf->lpfnCI = lpfnCI; + lpclf->pcRefDll = pcRefDll; + + if (pcRefDll) InterlockedIncrement(pcRefDll); + lpclf->riidInst = riidInst; + + TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst)); + return (LPCLASSFACTORY)lpclf; +} +/************************************************************************** + * IDefClF_fnQueryInterface + */ +static HRESULT WINAPI IDefClF_fnQueryInterface( + LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj) +{ + IDefClFImpl *This = (IDefClFImpl *)iface; + + TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid)); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { + *ppvObj = This; + InterlockedIncrement(&This->ref); + return S_OK; + } + + TRACE("-- E_NOINTERFACE\n"); + return E_NOINTERFACE; +} +/****************************************************************************** + * IDefClF_fnAddRef + */ +static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface) +{ + IDefClFImpl *This = (IDefClFImpl *)iface; + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return InterlockedIncrement(&This->ref); +} +/****************************************************************************** + * IDefClF_fnRelease + */ +static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface) +{ + IDefClFImpl *This = (IDefClFImpl *)iface; + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + if (!InterlockedDecrement(&This->ref)) + { + if (This->pcRefDll) InterlockedDecrement(This->pcRefDll); + + TRACE("-- destroying IClassFactory(%p)\n",This); + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} +/****************************************************************************** + * IDefClF_fnCreateInstance + */ +static HRESULT WINAPI IDefClF_fnCreateInstance( + LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject) +{ + IDefClFImpl *This = (IDefClFImpl *)iface; + + TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject); + + *ppvObject = NULL; + + if ( This->riidInst==NULL || + IsEqualCLSID(riid, This->riidInst) || + IsEqualCLSID(riid, &IID_IUnknown) ) + { + return This->lpfnCI(pUnkOuter, riid, ppvObject); + } + + ERR("unknown IID requested %s\n",shdebugstr_guid(riid)); + return E_NOINTERFACE; +} +/****************************************************************************** + * IDefClF_fnLockServer + */ +static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock) +{ + IDefClFImpl *This = (IDefClFImpl *)iface; + TRACE("%p->(0x%x), not implemented\n",This, fLock); + return E_NOTIMPL; +} + +static IClassFactoryVtbl dclfvt = +{ + IDefClF_fnQueryInterface, + IDefClF_fnAddRef, + IDefClF_fnRelease, + IDefClF_fnCreateInstance, + IDefClF_fnLockServer +}; + +/****************************************************************************** + * SHCreateDefClassObject [SHELL32.70] + */ +HRESULT WINAPI SHCreateDefClassObject( + REFIID riid, + LPVOID* ppv, + LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */ + LPDWORD pcRefDll, /* [in/out] ref count of the dll */ + REFIID riidInst) /* [in] optional interface to the instance */ +{ + IClassFactory * pcf; + + TRACE("%s %p %p %p %s\n", + shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst)); + + if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE; + if (! (pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst))) return E_OUTOFMEMORY; + *ppv = pcf; + return NOERROR; +} + +/************************************************************************* + * DragAcceptFiles [SHELL32.54] + */ +void WINAPI DragAcceptFiles(HWND hWnd, BOOL b) +{ + LONG exstyle; + + if( !IsWindow(hWnd) ) return; + exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE); + if (b) + exstyle |= WS_EX_ACCEPTFILES; + else + exstyle &= ~WS_EX_ACCEPTFILES; + SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle); +} + +/************************************************************************* + * DragFinish [SHELL32.80] + */ +void WINAPI DragFinish(HDROP h) +{ + TRACE("\n"); + GlobalFree((HGLOBAL)h); +} + +/************************************************************************* + * DragQueryPoint [SHELL32.135] + */ +BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p) +{ + DROPFILES *lpDropFileStruct; + BOOL bRet; + + TRACE("\n"); + + lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); + + *p = lpDropFileStruct->pt; + bRet = lpDropFileStruct->fNC; + + GlobalUnlock(hDrop); + return bRet; +} + +/************************************************************************* + * DragQueryFile [SHELL32.81] + * DragQueryFileA [SHELL32.82] + */ +UINT WINAPI DragQueryFileA( + HDROP hDrop, + UINT lFile, + LPSTR lpszFile, + UINT lLength) +{ + LPSTR lpDrop; + UINT i = 0; + DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); + + TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength); + + if(!lpDropFileStruct) goto end; + + lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles; + + if(lpDropFileStruct->fWide) { + LPWSTR lpszFileW = NULL; + + if(lpszFile) { + lpszFileW = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR)); + if(lpszFileW == NULL) { + goto end; + } + } + i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength); + + if(lpszFileW) { + WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL); + HeapFree(GetProcessHeap(), 0, lpszFileW); + } + goto end; + } + + while (i++ < lFile) + { + while (*lpDrop++); /* skip filename */ + if (!*lpDrop) + { + i = (lFile == 0xFFFFFFFF) ? i : 0; + goto end; + } + } + + i = strlen(lpDrop); + i++; + if (!lpszFile ) goto end; /* needed buffer size */ + i = (lLength > i) ? i : lLength; + lstrcpynA (lpszFile, lpDrop, i); +end: + GlobalUnlock(hDrop); + return i; +} + +/************************************************************************* + * DragQueryFileW [SHELL32.133] + */ +UINT WINAPI DragQueryFileW( + HDROP hDrop, + UINT lFile, + LPWSTR lpszwFile, + UINT lLength) +{ + LPWSTR lpwDrop; + UINT i = 0; + DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop); + + TRACE("(%p, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength); + + if(!lpDropFileStruct) goto end; + + lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles); + + if(lpDropFileStruct->fWide == FALSE) { + LPSTR lpszFileA = NULL; + + if(lpszwFile) { + lpszFileA = (LPSTR) HeapAlloc(GetProcessHeap(), 0, lLength); + if(lpszFileA == NULL) { + goto end; + } + } + i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength); + + if(lpszFileA) { + MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength); + HeapFree(GetProcessHeap(), 0, lpszFileA); + } + goto end; + } + + i = 0; + while (i++ < lFile) + { + while (*lpwDrop++); /* skip filename */ + if (!*lpwDrop) + { + i = (lFile == 0xFFFFFFFF) ? i : 0; + goto end; + } + } + + i = strlenW(lpwDrop); + i++; + if ( !lpszwFile) goto end; /* needed buffer size */ + + i = (lLength > i) ? i : lLength; + lstrcpynW (lpszwFile, lpwDrop, i); +end: + GlobalUnlock(hDrop); + return i; +} diff --git a/reactos/lib/shell32/shellord.c b/reactos/lib/shell32/shellord.c index 87ded76318f..ad6261e510f 100644 --- a/reactos/lib/shell32/shellord.c +++ b/reactos/lib/shell32/shellord.c @@ -1,1550 +1,1635 @@ -/* - * The parameters of many functions changes between different OS versions - * (NT uses Unicode strings, 95 uses ASCII strings) - * - * Copyright 1997 Marcus Meissner - * 1998 Jürgen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "config.h" - -#include -#include -#include - -#define COBJMACROS - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wine/debug.h" -#include "winnls.h" - -#include "shellapi.h" -#include "objbase.h" -#include "shlguid.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "pidl.h" -#include "shlwapi.h" -#include "commdlg.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); -WINE_DECLARE_DEBUG_CHANNEL(pidl); - -/* FIXME: !!! move CREATEMRULIST and flags to header file !!! */ -/* !!! it is in both here and comctl32undoc.c !!! */ -typedef struct tagCREATEMRULIST -{ - DWORD cbSize; /* size of struct */ - DWORD nMaxItems; /* max no. of items in list */ - DWORD dwFlags; /* see below */ - HKEY hKey; /* root reg. key under which list is saved */ - LPCSTR lpszSubKey; /* reg. subkey */ - PROC lpfnCompare; /* item compare proc */ -} CREATEMRULISTA, *LPCREATEMRULISTA; - -/* dwFlags */ -#define MRUF_STRING_LIST 0 /* list will contain strings */ -#define MRUF_BINARY_LIST 1 /* list will contain binary data */ -#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */ - -extern HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml); -extern DWORD WINAPI FreeMRUList(HANDLE hMRUList); -extern INT WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData); -extern INT WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum); -extern INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize); - - -/* Get a function pointer from a DLL handle */ -#define GET_FUNC(func, module, name, fail) \ - do { \ - if (!func) { \ - if (!SHELL32_h##module && !(SHELL32_h##module = LoadLibraryA(#module ".dll"))) return fail; \ - func = (void*)GetProcAddress(SHELL32_h##module, name); \ - if (!func) return fail; \ - } \ - } while (0) - -/* Function pointers for GET_FUNC macro */ -static HMODULE SHELL32_hshlwapi=NULL; -static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD); -static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD); -static BOOL (WINAPI *pSHUnlockShared)(LPVOID); -static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD); - - -/************************************************************************* - * ParseFieldA [internal] - * - * copies a field from a ',' delimited string - * - * first field is nField = 1 - */ -DWORD WINAPI ParseFieldA( - LPCSTR src, - DWORD nField, - LPSTR dst, - DWORD len) -{ - WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n",debugstr_a(src),nField,dst,len); - - if (!src || !src[0] || !dst || !len) - return 0; - - /* skip n fields delimited by ',' */ - while (nField > 1) - { - if (*src=='\0') return FALSE; - if (*(src++)==',') nField--; - } - - /* copy part till the next ',' to dst */ - while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++); - - /* finalize the string */ - *dst=0x0; - - return TRUE; -} - -/************************************************************************* - * ParseFieldW [internal] - * - * copies a field from a ',' delimited string - * - * first field is nField = 1 - */ -DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) -{ - WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n", debugstr_w(src), nField, dst, len); - - if (!src || !src[0] || !dst || !len) - return 0; - - /* skip n fields delimited by ',' */ - while (nField > 1) - { - if (*src == 0x0) return FALSE; - if (*src++ == ',') nField--; - } - - /* copy part till the next ',' to dst */ - while ( *src != 0x0 && *src != ',' && (len--)>0 ) *(dst++) = *(src++); - - /* finalize the string */ - *dst = 0x0; - - return TRUE; -} - -/************************************************************************* - * ParseField [SHELL32.58] - */ -DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len) -{ - if (SHELL_OsIsUnicode()) - return ParseFieldW(src, nField, dst, len); - return ParseFieldA(src, nField, dst, len); -} - -/************************************************************************* - * GetFileNameFromBrowse [SHELL32.63] - * - */ -BOOL WINAPI GetFileNameFromBrowse( - HWND hwndOwner, - LPSTR lpstrFile, - DWORD nMaxFile, - LPCSTR lpstrInitialDir, - LPCSTR lpstrDefExt, - LPCSTR lpstrFilter, - LPCSTR lpstrTitle) -{ - HMODULE hmodule; - FARPROC pGetOpenFileNameA; - OPENFILENAMEA ofn; - BOOL ret; - - TRACE("%p, %s, %ld, %s, %s, %s, %s)\n", - hwndOwner, lpstrFile, nMaxFile, lpstrInitialDir, lpstrDefExt, - lpstrFilter, lpstrTitle); - - hmodule = LoadLibraryA("comdlg32.dll"); - if(!hmodule) return FALSE; - pGetOpenFileNameA = GetProcAddress(hmodule, "GetOpenFileNameA"); - if(!pGetOpenFileNameA) - { - FreeLibrary(hmodule); - return FALSE; - } - - memset(&ofn, 0, sizeof(ofn)); - - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = hwndOwner; - ofn.lpstrFilter = lpstrFilter; - ofn.lpstrFile = lpstrFile; - ofn.nMaxFile = nMaxFile; - ofn.lpstrInitialDir = lpstrInitialDir; - ofn.lpstrTitle = lpstrTitle; - ofn.lpstrDefExt = lpstrDefExt; - ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; - ret = pGetOpenFileNameA(&ofn); - - FreeLibrary(hmodule); - return ret; -} - -/************************************************************************* - * SHGetSetSettings [SHELL32.68] - */ -VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet) -{ - if(bSet) - { - FIXME("%p 0x%08lx TRUE\n", lpss, dwMask); - } - else - { - SHGetSettings((LPSHELLFLAGSTATE)lpss,dwMask); - } -} - -/************************************************************************* - * SHGetSettings [SHELL32.@] - * - * NOTES - * the registry path are for win98 (tested) - * and possibly are the same in nt40 - * - */ -VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask) -{ - HKEY hKey; - DWORD dwData; - DWORD dwDataSize = sizeof (DWORD); - - TRACE("(%p 0x%08lx)\n",lpsfs,dwMask); - - if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", - 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) - return; - - if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fShowExtensions = ((dwData == 0) ? 0 : 1); - - if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fShowInfoTip = ((dwData == 0) ? 0 : 1); - - if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fDontPrettyPath = ((dwData == 0) ? 0 : 1); - - if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fHideIcons = ((dwData == 0) ? 0 : 1); - - if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fMapNetDrvBtn = ((dwData == 0) ? 0 : 1); - - if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - lpsfs->fShowAttribCol = ((dwData == 0) ? 0 : 1); - - if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize)) - { if (dwData == 0) - { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; - if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; - } - else if (dwData == 1) - { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 1; - if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; - } - else if (dwData == 2) - { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; - if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 1; - } - } - RegCloseKey (hKey); - - TRACE("-- 0x%04x\n", *(WORD*)lpsfs); -} - -/************************************************************************* - * SHShellFolderView_Message [SHELL32.73] - * - * Send a message to an explorer cabinet window. - * - * PARAMS - * hwndCabinet [I] The window containing the shellview to communicate with - * dwMessage [I] The SFVM message to send - * dwParam [I] Message parameter - * - * RETURNS - * fixme. - * - * NOTES - * Message SFVM_REARRANGE = 1 - * - * This message gets sent when a column gets clicked to instruct the - * shell view to re-sort the item list. dwParam identifies the column - * that was clicked. - */ -LRESULT WINAPI SHShellFolderView_Message( - HWND hwndCabinet, - UINT uMessage, - LPARAM lParam) -{ - FIXME("%p %08x %08lx stub\n",hwndCabinet, uMessage, lParam); - return 0; -} - -/************************************************************************* - * RegisterShellHook [SHELL32.181] - * - * Register a shell hook. - * - * PARAMS - * hwnd [I] Window handle - * dwType [I] Type of hook. - * - * NOTES - * Exported by ordinal - */ -BOOL WINAPI RegisterShellHook( - HWND hWnd, - DWORD dwType) -{ - FIXME("(%p,0x%08lx):stub.\n",hWnd, dwType); - return TRUE; -} - -/************************************************************************* - * ShellMessageBoxW [SHELL32.182] - * - * See ShellMessageBoxA. - */ -int WINAPIV ShellMessageBoxW( - HINSTANCE hInstance, - HWND hWnd, - LPCWSTR lpText, - LPCWSTR lpCaption, - UINT uType, - ...) -{ - WCHAR szText[100],szTitle[100]; - LPCWSTR pszText = szText, pszTitle = szTitle, pszTemp; - va_list args; - int ret; - - va_start(args, uType); - /* wvsprintfA(buf,fmt, args); */ - - TRACE("(%08lx,%08lx,%p,%p,%08x)\n", - (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType); - - if (!HIWORD(lpCaption)) - LoadStringW(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)/sizeof(szTitle[0])); - else - pszTitle = lpCaption; - - if (!HIWORD(lpText)) - LoadStringW(hInstance, (DWORD)lpText, szText, sizeof(szText)/sizeof(szText[0])); - else - pszText = lpText; - - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, - pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args); - - va_end(args); - - ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType); - LocalFree((HLOCAL)pszTemp); - return ret; -} - -/************************************************************************* - * ShellMessageBoxA [SHELL32.183] - * - * Format and output an error message. - * - * PARAMS - * hInstance [I] Instance handle of message creator - * hWnd [I] Window handle of message creator - * lpText [I] Resource Id of title or LPSTR - * lpCaption [I] Resource Id of title or LPSTR - * uType [I] Type of error message - * - * RETURNS - * A return value from MessageBoxA(). - * - * NOTES - * Exported by ordinal - */ -int WINAPIV ShellMessageBoxA( - HINSTANCE hInstance, - HWND hWnd, - LPCSTR lpText, - LPCSTR lpCaption, - UINT uType, - ...) -{ - char szText[100],szTitle[100]; - LPCSTR pszText = szText, pszTitle = szTitle, pszTemp; - va_list args; - int ret; - - va_start(args, uType); - /* wvsprintfA(buf,fmt, args); */ - - TRACE("(%08lx,%08lx,%p,%p,%08x)\n", - (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType); - - if (!HIWORD(lpCaption)) - LoadStringA(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)); - else - pszTitle = lpCaption; - - if (!HIWORD(lpText)) - LoadStringA(hInstance, (DWORD)lpText, szText, sizeof(szText)); - else - pszText = lpText; - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, - pszText, 0, 0, (LPSTR)&pszTemp, 0, &args); - - va_end(args); - - ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType); - LocalFree((HLOCAL)pszTemp); - return ret; -} - -/************************************************************************* - * SHRegisterDragDrop [SHELL32.86] - * - * NOTES - * exported by ordinal - */ -HRESULT WINAPI SHRegisterDragDrop( - HWND hWnd, - LPDROPTARGET pDropTarget) -{ - FIXME("(%p,%p):stub.\n", hWnd, pDropTarget); - return RegisterDragDrop(hWnd, pDropTarget); -} - -/************************************************************************* - * SHRevokeDragDrop [SHELL32.87] - * - * NOTES - * exported by ordinal - */ -HRESULT WINAPI SHRevokeDragDrop(HWND hWnd) -{ - FIXME("(%p):stub.\n",hWnd); - return RevokeDragDrop(hWnd); -} - -/************************************************************************* - * SHDoDragDrop [SHELL32.88] - * - * NOTES - * exported by ordinal - */ -HRESULT WINAPI SHDoDragDrop( - HWND hWnd, - LPDATAOBJECT lpDataObject, - LPDROPSOURCE lpDropSource, - DWORD dwOKEffect, - LPDWORD pdwEffect) -{ - FIXME("(%p %p %p 0x%08lx %p):stub.\n", - hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect); - return DoDragDrop(lpDataObject, lpDropSource, dwOKEffect, pdwEffect); -} - -/************************************************************************* - * ArrangeWindows [SHELL32.184] - * - */ -WORD WINAPI ArrangeWindows( - HWND hwndParent, - DWORD dwReserved, - LPCRECT lpRect, - WORD cKids, - CONST HWND * lpKids) -{ - FIXME("(%p 0x%08lx %p 0x%04x %p):stub.\n", - hwndParent, dwReserved, lpRect, cKids, lpKids); - return 0; -} - -/************************************************************************* - * SignalFileOpen [SHELL32.103] - * - * NOTES - * exported by ordinal - */ -DWORD WINAPI -SignalFileOpen (DWORD dwParam1) -{ - FIXME("(0x%08lx):stub.\n", dwParam1); - - return 0; -} - -/************************************************************************* - * SHADD_get_policy - helper function for SHAddToRecentDocs - * - * PARAMETERS - * policy [IN] policy name (null termed string) to find - * type [OUT] ptr to DWORD to receive type - * buffer [OUT] ptr to area to hold data retrieved - * len [IN/OUT] ptr to DWORD holding size of buffer and getting - * length filled - * - * RETURNS - * result of the SHQueryValueEx call - */ -static INT SHADD_get_policy(LPSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len) -{ - HKEY Policy_basekey; - INT ret; - - /* Get the key for the policies location in the registry - */ - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &Policy_basekey)) { - - if (RegOpenKeyExA(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", - 0, KEY_READ, &Policy_basekey)) { - TRACE("No Explorer Policies location exists. Policy wanted=%s\n", - policy); - *len = 0; - return ERROR_FILE_NOT_FOUND; - } - } - - /* Retrieve the data if it exists - */ - ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len); - RegCloseKey(Policy_basekey); - return ret; -} - - -/************************************************************************* - * SHADD_compare_mru - helper function for SHAddToRecentDocs - * - * PARAMETERS - * data1 [IN] data being looked for - * data2 [IN] data in MRU - * cbdata [IN] length from FindMRUData call (not used) - * - * RETURNS - * position within MRU list that data was added. - */ -static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData) -{ - return lstrcmpiA(data1, data2); -} - -/************************************************************************* - * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs - * - * PARAMETERS - * mruhandle [IN] handle for created MRU list - * doc_name [IN] null termed pure doc name - * new_lnk_name [IN] null termed path and file name for .lnk file - * buffer [IN/OUT] 2048 byte area to consturct MRU data - * len [OUT] ptr to int to receive space used in buffer - * - * RETURNS - * position within MRU list that data was added. - */ -static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPSTR doc_name, LPSTR new_lnk_name, - LPSTR buffer, INT *len) -{ - LPSTR ptr; - INT wlen; - - /*FIXME: Document: - * RecentDocs MRU data structure seems to be: - * +0h document file name w/ terminating 0h - * +nh short int w/ size of remaining - * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown - * +n+4h 10 bytes zeros - unknown - * +n+eh shortcut file name w/ terminating 0h - * +n+e+nh 3 zero bytes - unknown - */ - - /* Create the MRU data structure for "RecentDocs" - */ - ptr = buffer; - lstrcpyA(ptr, doc_name); - ptr += (lstrlenA(buffer) + 1); - wlen= lstrlenA(new_lnk_name) + 1 + 12; - *((short int*)ptr) = wlen; - ptr += 2; /* step past the length */ - *(ptr++) = 0x30; /* unknown reason */ - *(ptr++) = 0; /* unknown, but can be 0x00, 0x01, 0x02 */ - memset(ptr, 0, 10); - ptr += 10; - lstrcpyA(ptr, new_lnk_name); - ptr += (lstrlenA(new_lnk_name) + 1); - memset(ptr, 0, 3); - ptr += 3; - *len = ptr - buffer; - - /* Add the new entry into the MRU list - */ - return AddMRUData(mruhandle, (LPCVOID)buffer, *len); -} - -/************************************************************************* - * SHAddToRecentDocs [SHELL32.@] - * - * PARAMETERS - * uFlags [IN] SHARD_PATH or SHARD_PIDL - * pv [IN] string or pidl, NULL clears the list - * - * NOTES - * exported by name - */ -void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv) -{ -/* If list is a string list lpfnCompare has the following prototype - * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2) - * for binary lists the prototype is - * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData) - * where cbData is the no. of bytes to compare. - * Need to check what return value means identical - 0? - */ - - - UINT olderrormode; - HKEY HCUbasekey; - CHAR doc_name[MAX_PATH]; - CHAR link_dir[MAX_PATH]; - CHAR new_lnk_filepath[MAX_PATH]; - CHAR new_lnk_name[MAX_PATH]; - IMalloc *ppM; - LPITEMIDLIST pidl; - HWND hwnd = 0; /* FIXME: get real window handle */ - INT ret; - DWORD data[64], datalen, type; - - /*FIXME: Document: - * RecentDocs MRU data structure seems to be: - * +0h document file name w/ terminating 0h - * +nh short int w/ size of remaining - * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown - * +n+4h 10 bytes zeros - unknown - * +n+eh shortcut file name w/ terminating 0h - * +n+e+nh 3 zero bytes - unknown - */ - - /* See if we need to do anything. - */ - datalen = 64; - ret=SHADD_get_policy( "NoRecentDocsHistory", &type, &data, &datalen); - if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) { - ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret); - return; - } - if (ret == ERROR_SUCCESS) { - if (!( (type == REG_DWORD) || - ((type == REG_BINARY) && (datalen == 4)) )) { - ERR("Error policy data for \"NoRecentDocsHistory\" not formated correctly, type=%ld, len=%ld\n", - type, datalen); - return; - } - - TRACE("policy value for NoRecentDocsHistory = %08lx\n", data[0]); - /* now test the actual policy value */ - if ( data[0] != 0) - return; - } - - /* Open key to where the necessary info is - */ - /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH) - * and the close should be done during the _DETACH. The resulting - * key is stored in the DLL global data. - */ - if (RegCreateKeyExA(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", - 0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) { - ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n"); - return; - } - - /* Get path to user's "Recent" directory - */ - if(SUCCEEDED(SHGetMalloc(&ppM))) { - if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT, - &pidl))) { - SHGetPathFromIDListA(pidl, link_dir); - IMalloc_Free(ppM, pidl); - } - else { - /* serious issues */ - link_dir[0] = 0; - ERR("serious issues 1\n"); - } - IMalloc_Release(ppM); - } - else { - /* serious issues */ - link_dir[0] = 0; - ERR("serious issues 2\n"); - } - TRACE("Users Recent dir %s\n", link_dir); - - /* If no input, then go clear the lists */ - if (!pv) { - /* clear user's Recent dir - */ - - /* FIXME: delete all files in "link_dir" - * - * while( more files ) { - * lstrcpyA(old_lnk_name, link_dir); - * PathAppendA(old_lnk_name, filenam); - * DeleteFileA(old_lnk_name); - * } - */ - FIXME("should delete all files in %s\\ \n", link_dir); - - /* clear MRU list - */ - /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against - * HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer - * and naturally it fails w/ rc=2. It should do it against - * HKEY_CURRENT_USER which is where it is stored, and where - * the MRU routines expect it!!!! - */ - RegDeleteKeyA(HCUbasekey, "RecentDocs"); - RegCloseKey(HCUbasekey); - return; - } - - /* Have data to add, the jobs to be done: - * 1. Add document to MRU list in registry "HKCU\Software\ - * Microsoft\Windows\CurrentVersion\Explorer\RecentDocs". - * 2. Add shortcut to document in the user's Recent directory - * (CSIDL_RECENT). - * 3. Add shortcut to Start menu's Documents submenu. - */ - - /* Get the pure document name from the input - */ - if (uFlags & SHARD_PIDL) { - SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name); - } - else { - lstrcpyA(doc_name, (LPCSTR) pv); - } - TRACE("full document name %s\n", doc_name); - PathStripPathA(doc_name); - TRACE("stripped document name %s\n", doc_name); - - - /* *** JOB 1: Update registry for ...\Explorer\RecentDocs list *** */ - - { /* on input needs: - * doc_name - pure file-spec, no path - * link_dir - path to the user's Recent directory - * HCUbasekey - key of ...Windows\CurrentVersion\Explorer" node - * creates: - * new_lnk_name- pure file-spec, no path for new .lnk file - * new_lnk_filepath - * - path and file name of new .lnk file - */ - CREATEMRULISTA mymru; - HANDLE mruhandle; - INT len, pos, bufused, err; - INT i; - DWORD attr; - CHAR buffer[2048]; - CHAR *ptr; - CHAR old_lnk_name[MAX_PATH]; - short int slen; - - mymru.cbSize = sizeof(CREATEMRULISTA); - mymru.nMaxItems = 15; - mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE; - mymru.hKey = HCUbasekey; - mymru.lpszSubKey = "RecentDocs"; - mymru.lpfnCompare = &SHADD_compare_mru; - mruhandle = CreateMRUListA(&mymru); - if (!mruhandle) { - /* MRU failed */ - ERR("MRU processing failed, handle zero\n"); - RegCloseKey(HCUbasekey); - return; - } - len = lstrlenA(doc_name); - pos = FindMRUData(mruhandle, doc_name, len, 0); - - /* Now get the MRU entry that will be replaced - * and delete the .lnk file for it - */ - if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos, - buffer, 2048)) != -1) { - ptr = buffer; - ptr += (lstrlenA(buffer) + 1); - slen = *((short int*)ptr); - ptr += 2; /* skip the length area */ - if (bufused >= slen + (ptr-buffer)) { - /* buffer size looks good */ - ptr += 12; /* get to string */ - len = bufused - (ptr-buffer); /* get length of buf remaining */ - if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) { - /* appears to be good string */ - lstrcpyA(old_lnk_name, link_dir); - PathAppendA(old_lnk_name, ptr); - if (!DeleteFileA(old_lnk_name)) { - if ((attr = GetFileAttributesA(old_lnk_name)) == INVALID_FILE_ATTRIBUTES) { - if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) { - ERR("Delete for %s failed, err=%d, attr=%08lx\n", - old_lnk_name, err, attr); - } - else { - TRACE("old .lnk file %s did not exist\n", - old_lnk_name); - } - } - else { - ERR("Delete for %s failed, attr=%08lx\n", - old_lnk_name, attr); - } - } - else { - TRACE("deleted old .lnk file %s\n", old_lnk_name); - } - } - } - } - - /* Create usable .lnk file name for the "Recent" directory - */ - wsprintfA(new_lnk_name, "%s.lnk", doc_name); - lstrcpyA(new_lnk_filepath, link_dir); - PathAppendA(new_lnk_filepath, new_lnk_name); - i = 1; - olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS); - while (GetFileAttributesA(new_lnk_filepath) != INVALID_FILE_ATTRIBUTES) { - i++; - wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i); - lstrcpyA(new_lnk_filepath, link_dir); - PathAppendA(new_lnk_filepath, new_lnk_name); - } - SetErrorMode(olderrormode); - TRACE("new shortcut will be %s\n", new_lnk_filepath); - - /* Now add the new MRU entry and data - */ - pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name, - buffer, &len); - FreeMRUList(mruhandle); - TRACE("Updated MRU list, new doc is position %d\n", pos); - } - - /* *** JOB 2: Create shortcut in user's "Recent" directory *** */ - - { /* on input needs: - * doc_name - pure file-spec, no path - * new_lnk_filepath - * - path and file name of new .lnk file - * uFlags[in] - flags on call to SHAddToRecentDocs - * pv[in] - document path/pidl on call to SHAddToRecentDocs - */ - IShellLinkA *psl = NULL; - IPersistFile *pPf = NULL; - HRESULT hres; - CHAR desc[MAX_PATH]; - WCHAR widelink[MAX_PATH]; - - CoInitialize(0); - - hres = CoCreateInstance( &CLSID_ShellLink, - NULL, - CLSCTX_INPROC_SERVER, - &IID_IShellLinkA, - (LPVOID )&psl); - if(SUCCEEDED(hres)) { - - hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile, - (LPVOID *)&pPf); - if(FAILED(hres)) { - /* bombed */ - ERR("failed QueryInterface for IPersistFile %08lx\n", hres); - goto fail; - } - - /* Set the document path or pidl */ - if (uFlags & SHARD_PIDL) { - hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv); - } else { - hres = IShellLinkA_SetPath(psl, (LPCSTR) pv); - } - if(FAILED(hres)) { - /* bombed */ - ERR("failed Set{IDList|Path} %08lx\n", hres); - goto fail; - } - - lstrcpyA(desc, "Shortcut to "); - lstrcatA(desc, doc_name); - hres = IShellLinkA_SetDescription(psl, desc); - if(FAILED(hres)) { - /* bombed */ - ERR("failed SetDescription %08lx\n", hres); - goto fail; - } - - MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1, - widelink, MAX_PATH); - /* create the short cut */ - hres = IPersistFile_Save(pPf, widelink, TRUE); - if(FAILED(hres)) { - /* bombed */ - ERR("failed IPersistFile::Save %08lx\n", hres); - IPersistFile_Release(pPf); - IShellLinkA_Release(psl); - goto fail; - } - hres = IPersistFile_SaveCompleted(pPf, widelink); - IPersistFile_Release(pPf); - IShellLinkA_Release(psl); - TRACE("shortcut %s has been created, result=%08lx\n", - new_lnk_filepath, hres); - } - else { - ERR("CoCreateInstance failed, hres=%08lx\n", hres); - } - } - - fail: - CoUninitialize(); - - /* all done */ - RegCloseKey(HCUbasekey); - return; -} - -/************************************************************************* - * SHCreateShellFolderViewEx [SHELL32.174] - * - * NOTES - * see IShellFolder::CreateViewObject - */ -HRESULT WINAPI SHCreateShellFolderViewEx( - LPCSFV psvcbi, /* [in] shelltemplate struct */ - IShellView **ppv) /* [out] IShellView pointer */ -{ - IShellView * psf; - HRESULT hRes; - - TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", - psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, - psvcbi->fvm, psvcbi->psvOuter); - - psf = IShellView_Constructor(psvcbi->pshf); - - if (!psf) - return E_OUTOFMEMORY; - - IShellView_AddRef(psf); - hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppv); - IShellView_Release(psf); - - return hRes; -} -/************************************************************************* - * SHWinHelp [SHELL32.127] - * - */ -HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z) -{ FIXME("0x%08lx 0x%08lx 0x%08lx 0x%08lx stub\n",v,w,x,z); - return 0; -} -/************************************************************************* - * SHRunControlPanel [SHELL32.161] - * - */ -HRESULT WINAPI SHRunControlPanel (DWORD x, DWORD z) -{ FIXME("0x%08lx 0x%08lx stub\n",x,z); - return 0; -} - -static LPUNKNOWN SHELL32_IExplorerInterface=0; -/************************************************************************* - * SHSetInstanceExplorer [SHELL32.176] - * - * NOTES - * Sets the interface - */ -HRESULT WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown) -{ TRACE("%p\n", lpUnknown); - SHELL32_IExplorerInterface = lpUnknown; - return (HRESULT) lpUnknown; -} -/************************************************************************* - * SHGetInstanceExplorer [SHELL32.@] - * - * NOTES - * gets the interface pointer of the explorer and a reference - */ -HRESULT WINAPI SHGetInstanceExplorer (LPUNKNOWN * lpUnknown) -{ TRACE("%p\n", lpUnknown); - - *lpUnknown = SHELL32_IExplorerInterface; - - if (!SHELL32_IExplorerInterface) - return E_FAIL; - - IUnknown_AddRef(SHELL32_IExplorerInterface); - return NOERROR; -} -/************************************************************************* - * SHFreeUnusedLibraries [SHELL32.123] - * - * NOTES - * exported by name - */ -void WINAPI SHFreeUnusedLibraries (void) -{ - FIXME("stub\n"); -} -/************************************************************************* - * DAD_AutoScroll [SHELL32.129] - * - */ -BOOL WINAPI DAD_AutoScroll(HWND hwnd, AUTO_SCROLL_DATA *samples, LPPOINT pt) -{ - FIXME("hwnd = %p %p %p\n",hwnd,samples,pt); - return 0; -} -/************************************************************************* - * DAD_DragEnter [SHELL32.130] - * - */ -BOOL WINAPI DAD_DragEnter(HWND hwnd) -{ - FIXME("hwnd = %p\n",hwnd); - return FALSE; -} -/************************************************************************* - * DAD_DragEnterEx [SHELL32.131] - * - */ -BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p) -{ - FIXME("hwnd = %p (%ld,%ld)\n",hwnd,p.x,p.y); - return FALSE; -} -/************************************************************************* - * DAD_DragMove [SHELL32.134] - * - */ -BOOL WINAPI DAD_DragMove(POINT p) -{ - FIXME("(%ld,%ld)\n",p.x,p.y); - return FALSE; -} -/************************************************************************* - * DAD_DragLeave [SHELL32.132] - * - */ -BOOL WINAPI DAD_DragLeave(VOID) -{ - FIXME("\n"); - return FALSE; -} -/************************************************************************* - * DAD_SetDragImage [SHELL32.136] - * - * NOTES - * exported by name - */ -BOOL WINAPI DAD_SetDragImage( - HIMAGELIST himlTrack, - LPPOINT lppt) -{ - FIXME("%p %p stub\n",himlTrack, lppt); - return 0; -} -/************************************************************************* - * DAD_ShowDragImage [SHELL32.137] - * - * NOTES - * exported by name - */ -BOOL WINAPI DAD_ShowDragImage(BOOL bShow) -{ - FIXME("0x%08x stub\n",bShow); - return 0; -} - -static const WCHAR szwCabLocation[] = { - 'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'E','x','p','l','o','r','e','r','\\', - 'C','a','b','i','n','e','t','S','t','a','t','e',0 -}; - -static const WCHAR szwSettings[] = { 'S','e','t','t','i','n','g','s',0 }; - -/************************************************************************* - * ReadCabinetState [SHELL32.651] NT 4.0 - * - */ -BOOL WINAPI ReadCabinetState(CABINETSTATE *cs, int length) -{ - HKEY hkey = 0; - DWORD type, r; - - TRACE("%p %d \n",cs,length); - - if( (cs == NULL) || (length < (int)sizeof(*cs)) ) - return FALSE; - - r = RegOpenKeyW( HKEY_CURRENT_USER, szwCabLocation, &hkey ); - if( r == ERROR_SUCCESS ) - { - type = REG_BINARY; - r = RegQueryValueExW( hkey, szwSettings, - NULL, &type, (LPBYTE)cs, (LPDWORD)&length ); - RegCloseKey( hkey ); - - } - - /* if we can't read from the registry, create default values */ - if ( (r != ERROR_SUCCESS) || (cs->cLength < sizeof(*cs)) || - (cs->cLength != length) ) - { - ERR("Initializing shell cabinet settings\n"); - memset(cs, 0, sizeof(*cs)); - cs->cLength = sizeof(*cs); - cs->nVersion = 2; - cs->fFullPathTitle = FALSE; - cs->fSaveLocalView = TRUE; - cs->fNotShell = FALSE; - cs->fSimpleDefault = TRUE; - cs->fDontShowDescBar = FALSE; - cs->fNewWindowMode = FALSE; - cs->fShowCompColor = FALSE; - cs->fDontPrettyNames = FALSE; - cs->fAdminsCreateCommonGroups = TRUE; - cs->fMenuEnumFilter = 96; - } - - return TRUE; -} - -/************************************************************************* - * WriteCabinetState [SHELL32.652] NT 4.0 - * - */ -BOOL WINAPI WriteCabinetState(CABINETSTATE *cs) -{ - DWORD r; - HKEY hkey = 0; - - TRACE("%p\n",cs); - - if( cs == NULL ) - return FALSE; - - r = RegCreateKeyExW( HKEY_CURRENT_USER, szwCabLocation, 0, - NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); - if( r == ERROR_SUCCESS ) - { - r = RegSetValueExW( hkey, szwSettings, 0, - REG_BINARY, (LPBYTE) cs, cs->cLength); - - RegCloseKey( hkey ); - } - - return (r==ERROR_SUCCESS); -} - -/************************************************************************* - * FileIconInit [SHELL32.660] - * - */ -BOOL WINAPI FileIconInit(BOOL bFullInit) -{ FIXME("(%s)\n", bFullInit ? "true" : "false"); - return 0; -} -/************************************************************************* - * IsUserAdmin [SHELL32.680] NT 4.0 - * - */ -HRESULT WINAPI IsUserAdmin(void) -{ FIXME("stub\n"); - return TRUE; -} - -/************************************************************************* - * SHAllocShared [SHELL32.520] - * - * See shlwapi.SHAllocShared - */ -HANDLE WINAPI SHAllocShared(LPVOID lpvData, DWORD dwSize, DWORD dwProcId) -{ - GET_FUNC(pSHAllocShared, shlwapi, (char*)7, NULL); - return pSHAllocShared(lpvData, dwSize, dwProcId); -} - -/************************************************************************* - * SHLockShared [SHELL32.521] - * - * See shlwapi.SHLockShared - */ -LPVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId) -{ - GET_FUNC(pSHLockShared, shlwapi, (char*)8, NULL); - return pSHLockShared(hShared, dwProcId); -} - -/************************************************************************* - * SHUnlockShared [SHELL32.522] - * - * See shlwapi.SHUnlockShared - */ -BOOL WINAPI SHUnlockShared(LPVOID lpView) -{ - GET_FUNC(pSHUnlockShared, shlwapi, (char*)9, FALSE); - return pSHUnlockShared(lpView); -} - -/************************************************************************* - * SHFreeShared [SHELL32.523] - * - * See shlwapi.SHFreeShared - */ -BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId) -{ - GET_FUNC(pSHFreeShared, shlwapi, (char*)10, FALSE); - return pSHFreeShared(hShared, dwProcId); -} - -/************************************************************************* - * SetAppStartingCursor [SHELL32.99] - */ -HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v) -{ FIXME("hwnd=%p 0x%04lx stub\n",u,v ); - return 0; -} -/************************************************************************* - * SHLoadOLE [SHELL32.151] - * - */ -HRESULT WINAPI SHLoadOLE(LPARAM lParam) -{ FIXME("0x%04lx stub\n",lParam); - return S_OK; -} -/************************************************************************* - * DriveType [SHELL32.64] - * - */ -HRESULT WINAPI DriveType(DWORD u) -{ FIXME("0x%04lx stub\n",u); - return 0; -} -/************************************************************************* - * SHAbortInvokeCommand [SHELL32.198] - * - */ -HRESULT WINAPI SHAbortInvokeCommand(void) -{ FIXME("stub\n"); - return 1; -} -/************************************************************************* - * SHOutOfMemoryMessageBox [SHELL32.126] - * - */ -int WINAPI SHOutOfMemoryMessageBox( - HWND hwndOwner, - LPCSTR lpCaption, - UINT uType) -{ - FIXME("%p %s 0x%08x stub\n",hwndOwner, lpCaption, uType); - return 0; -} -/************************************************************************* - * SHFlushClipboard [SHELL32.121] - * - */ -HRESULT WINAPI SHFlushClipboard(void) -{ FIXME("stub\n"); - return 1; -} - -/************************************************************************* - * SHWaitForFileToOpen [SHELL32.97] - * - */ -BOOL WINAPI SHWaitForFileToOpen( - LPCITEMIDLIST pidl, - DWORD dwFlags, - DWORD dwTimeout) -{ - FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout); - return 0; -} - -/************************************************************************ - * @ [SHELL32.654] - * - * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState) - * second one could be a size (0x0c). The size is the same as the structure saved to - * HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState - * I'm (js) guessing: this one is just ReadCabinetState ;-) - */ -HRESULT WINAPI shell32_654 (CABINETSTATE *cs, int length) -{ - TRACE("%p %d\n",cs,length); - return ReadCabinetState(cs,length); -} - -/************************************************************************ - * RLBuildListOfPaths [SHELL32.146] - * - * NOTES - * builds a DPA - */ -DWORD WINAPI RLBuildListOfPaths (void) -{ FIXME("stub\n"); - return 0; -} -/************************************************************************ - * SHValidateUNC [SHELL32.173] - * - */ -HRESULT WINAPI SHValidateUNC (DWORD x, DWORD y, DWORD z) -{ - FIXME("0x%08lx 0x%08lx 0x%08lx stub\n",x,y,z); - return 0; -} - -/************************************************************************ - * DoEnvironmentSubstA [SHELL32.@] - * - */ -HRESULT WINAPI DoEnvironmentSubstA(LPSTR x, LPSTR y) -{ - FIXME("(%s, %s) stub\n", debugstr_a(x), debugstr_a(y)); - return 0; -} - -/************************************************************************ - * DoEnvironmentSubstW [SHELL32.@] - * - */ -HRESULT WINAPI DoEnvironmentSubstW(LPWSTR x, LPWSTR y) -{ - FIXME("(%s, %s): stub\n", debugstr_w(x), debugstr_w(y)); - return 0; -} - -/************************************************************************ - * DoEnvironmentSubst [SHELL32.53] - * - */ -HRESULT WINAPI DoEnvironmentSubstAW(LPVOID x, LPVOID y) -{ - if (SHELL_OsIsUnicode()) - return DoEnvironmentSubstW(x, y); - return DoEnvironmentSubstA(x, y); -} - -/************************************************************************* - * @ [SHELL32.243] - * - * Win98+ by-ordinal routine. In Win98 this routine returns zero and - * does nothing else. Possibly this does something in NT or SHELL32 5.0? - * - */ - -BOOL WINAPI shell32_243(DWORD a, DWORD b) -{ - return FALSE; -} - -/************************************************************************* - * @ [SHELL32.714] - */ -DWORD WINAPI SHELL32_714(LPVOID x) -{ - FIXME("(%s)stub\n", debugstr_w(x)); - return 0; -} - -/************************************************************************* - * SHAddFromPropSheetExtArray [SHELL32.167] - */ -DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c) -{ - FIXME("(%08lx,%08lx,%08lx)stub\n", a, b, c); - return 0; -} - -/************************************************************************* - * SHCreatePropSheetExtArray [SHELL32.168] - */ -DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c) -{ - FIXME("(%08lx,%s,%08lx)stub\n", a, debugstr_a(b), c); - return 0; -} - -/************************************************************************* - * SHReplaceFromPropSheetExtArray [SHELL32.170] - */ -DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d) -{ - FIXME("(%08lx,%08lx,%08lx,%08lx)stub\n", a, b, c, d); - return 0; -} - -/************************************************************************* - * SHDestroyPropSheetExtArray [SHELL32.169] - */ -DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a) -{ - FIXME("(%08lx)stub\n", a); - return 0; -} - -/************************************************************************* - * CIDLData_CreateFromIDArray [SHELL32.83] - * - * Create IDataObject from PIDLs?? - */ -HRESULT WINAPI CIDLData_CreateFromIDArray( - LPCITEMIDLIST pidlFolder, - DWORD cpidlFiles, - LPCITEMIDLIST *lppidlFiles, - LPDATAOBJECT *ppdataObject) -{ - UINT i; - HWND hwnd = 0; /*FIXME: who should be hwnd of owner? set to desktop */ - - TRACE("(%p, %ld, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject); - if (TRACE_ON(pidl)) - { - pdump (pidlFolder); - for (i=0; i +#include +#include + +#define COBJMACROS + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wine/debug.h" +#include "winnls.h" + +#include "shellapi.h" +#include "objbase.h" +#include "shlguid.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "shell32_main.h" +#include "undocshell.h" +#include "pidl.h" +#include "shlwapi.h" +#include "commdlg.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); +WINE_DECLARE_DEBUG_CHANNEL(pidl); + +/* FIXME: !!! move CREATEMRULIST and flags to header file !!! */ +/* !!! it is in both here and comctl32undoc.c !!! */ +typedef struct tagCREATEMRULIST +{ + DWORD cbSize; /* size of struct */ + DWORD nMaxItems; /* max no. of items in list */ + DWORD dwFlags; /* see below */ + HKEY hKey; /* root reg. key under which list is saved */ + LPCSTR lpszSubKey; /* reg. subkey */ + PROC lpfnCompare; /* item compare proc */ +} CREATEMRULISTA, *LPCREATEMRULISTA; + +/* dwFlags */ +#define MRUF_STRING_LIST 0 /* list will contain strings */ +#define MRUF_BINARY_LIST 1 /* list will contain binary data */ +#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */ + +extern HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml); +extern DWORD WINAPI FreeMRUList(HANDLE hMRUList); +extern INT WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData); +extern INT WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum); +extern INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize); + + +/* Get a function pointer from a DLL handle */ +#define GET_FUNC(func, module, name, fail) \ + do { \ + if (!func) { \ + if (!SHELL32_h##module && !(SHELL32_h##module = LoadLibraryA(#module ".dll"))) return fail; \ + func = (void*)GetProcAddress(SHELL32_h##module, name); \ + if (!func) return fail; \ + } \ + } while (0) + +/* Function pointers for GET_FUNC macro */ +static HMODULE SHELL32_hshlwapi=NULL; +static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD); +static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD); +static BOOL (WINAPI *pSHUnlockShared)(LPVOID); +static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD); + + +/************************************************************************* + * ParseFieldA [internal] + * + * copies a field from a ',' delimited string + * + * first field is nField = 1 + */ +DWORD WINAPI ParseFieldA( + LPCSTR src, + DWORD nField, + LPSTR dst, + DWORD len) +{ + WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n",debugstr_a(src),nField,dst,len); + + if (!src || !src[0] || !dst || !len) + return 0; + + /* skip n fields delimited by ',' */ + while (nField > 1) + { + if (*src=='\0') return FALSE; + if (*(src++)==',') nField--; + } + + /* copy part till the next ',' to dst */ + while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++); + + /* finalize the string */ + *dst=0x0; + + return TRUE; +} + +/************************************************************************* + * ParseFieldW [internal] + * + * copies a field from a ',' delimited string + * + * first field is nField = 1 + */ +DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) +{ + WARN("(%s,0x%08lx,%p,%ld) semi-stub.\n", debugstr_w(src), nField, dst, len); + + if (!src || !src[0] || !dst || !len) + return 0; + + /* skip n fields delimited by ',' */ + while (nField > 1) + { + if (*src == 0x0) return FALSE; + if (*src++ == ',') nField--; + } + + /* copy part till the next ',' to dst */ + while ( *src != 0x0 && *src != ',' && (len--)>0 ) *(dst++) = *(src++); + + /* finalize the string */ + *dst = 0x0; + + return TRUE; +} + +/************************************************************************* + * ParseField [SHELL32.58] + */ +DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len) +{ + if (SHELL_OsIsUnicode()) + return ParseFieldW(src, nField, dst, len); + return ParseFieldA(src, nField, dst, len); +} + +/************************************************************************* + * GetFileNameFromBrowse [SHELL32.63] + * + */ +BOOL WINAPI GetFileNameFromBrowse( + HWND hwndOwner, + LPSTR lpstrFile, + DWORD nMaxFile, + LPCSTR lpstrInitialDir, + LPCSTR lpstrDefExt, + LPCSTR lpstrFilter, + LPCSTR lpstrTitle) +{ + HMODULE hmodule; + FARPROC pGetOpenFileNameA; + OPENFILENAMEA ofn; + BOOL ret; + + TRACE("%p, %s, %ld, %s, %s, %s, %s)\n", + hwndOwner, lpstrFile, nMaxFile, lpstrInitialDir, lpstrDefExt, + lpstrFilter, lpstrTitle); + + hmodule = LoadLibraryA("comdlg32.dll"); + if(!hmodule) return FALSE; + pGetOpenFileNameA = GetProcAddress(hmodule, "GetOpenFileNameA"); + if(!pGetOpenFileNameA) + { + FreeLibrary(hmodule); + return FALSE; + } + + memset(&ofn, 0, sizeof(ofn)); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hwndOwner; + ofn.lpstrFilter = lpstrFilter; + ofn.lpstrFile = lpstrFile; + ofn.nMaxFile = nMaxFile; + ofn.lpstrInitialDir = lpstrInitialDir; + ofn.lpstrTitle = lpstrTitle; + ofn.lpstrDefExt = lpstrDefExt; + ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; + ret = pGetOpenFileNameA(&ofn); + + FreeLibrary(hmodule); + return ret; +} + +/************************************************************************* + * SHGetSetSettings [SHELL32.68] + */ +VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet) +{ + if(bSet) + { + FIXME("%p 0x%08lx TRUE\n", lpss, dwMask); + } + else + { + SHGetSettings((LPSHELLFLAGSTATE)lpss,dwMask); + } +} + +/************************************************************************* + * SHGetSettings [SHELL32.@] + * + * NOTES + * the registry path are for win98 (tested) + * and possibly are the same in nt40 + * + */ +VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask) +{ + HKEY hKey; + DWORD dwData; + DWORD dwDataSize = sizeof (DWORD); + + TRACE("(%p 0x%08lx)\n",lpsfs,dwMask); + + if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) + return; + + if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fShowExtensions = ((dwData == 0) ? 0 : 1); + + if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fShowInfoTip = ((dwData == 0) ? 0 : 1); + + if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fDontPrettyPath = ((dwData == 0) ? 0 : 1); + + if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fHideIcons = ((dwData == 0) ? 0 : 1); + + if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fMapNetDrvBtn = ((dwData == 0) ? 0 : 1); + + if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + lpsfs->fShowAttribCol = ((dwData == 0) ? 0 : 1); + + if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize)) + { if (dwData == 0) + { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; + if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; + } + else if (dwData == 1) + { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 1; + if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; + } + else if (dwData == 2) + { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; + if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 1; + } + } + RegCloseKey (hKey); + + TRACE("-- 0x%04x\n", *(WORD*)lpsfs); +} + +/************************************************************************* + * SHShellFolderView_Message [SHELL32.73] + * + * Send a message to an explorer cabinet window. + * + * PARAMS + * hwndCabinet [I] The window containing the shellview to communicate with + * dwMessage [I] The SFVM message to send + * dwParam [I] Message parameter + * + * RETURNS + * fixme. + * + * NOTES + * Message SFVM_REARRANGE = 1 + * + * This message gets sent when a column gets clicked to instruct the + * shell view to re-sort the item list. dwParam identifies the column + * that was clicked. + */ +LRESULT WINAPI SHShellFolderView_Message( + HWND hwndCabinet, + UINT uMessage, + LPARAM lParam) +{ + FIXME("%p %08x %08lx stub\n",hwndCabinet, uMessage, lParam); + return 0; +} + +/************************************************************************* + * RegisterShellHook [SHELL32.181] + * + * Register a shell hook. + * + * PARAMS + * hwnd [I] Window handle + * dwType [I] Type of hook. + * + * NOTES + * Exported by ordinal + */ +BOOL WINAPI RegisterShellHook( + HWND hWnd, + DWORD dwType) +{ + FIXME("(%p,0x%08lx):stub.\n",hWnd, dwType); + return TRUE; +} + +/************************************************************************* + * ShellMessageBoxW [SHELL32.182] + * + * See ShellMessageBoxA. + */ +int WINAPIV ShellMessageBoxW( + HINSTANCE hInstance, + HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType, + ...) +{ + WCHAR szText[100],szTitle[100]; + LPCWSTR pszText = szText, pszTitle = szTitle, pszTemp; + va_list args; + int ret; + + va_start(args, uType); + /* wvsprintfA(buf,fmt, args); */ + + TRACE("(%08lx,%08lx,%p,%p,%08x)\n", + (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType); + + if (!HIWORD(lpCaption)) + LoadStringW(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)/sizeof(szTitle[0])); + else + pszTitle = lpCaption; + + if (!HIWORD(lpText)) + LoadStringW(hInstance, (DWORD)lpText, szText, sizeof(szText)/sizeof(szText[0])); + else + pszText = lpText; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args); + + va_end(args); + + ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType); + LocalFree((HLOCAL)pszTemp); + return ret; +} + +/************************************************************************* + * ShellMessageBoxA [SHELL32.183] + * + * Format and output an error message. + * + * PARAMS + * hInstance [I] Instance handle of message creator + * hWnd [I] Window handle of message creator + * lpText [I] Resource Id of title or LPSTR + * lpCaption [I] Resource Id of title or LPSTR + * uType [I] Type of error message + * + * RETURNS + * A return value from MessageBoxA(). + * + * NOTES + * Exported by ordinal + */ +int WINAPIV ShellMessageBoxA( + HINSTANCE hInstance, + HWND hWnd, + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType, + ...) +{ + char szText[100],szTitle[100]; + LPCSTR pszText = szText, pszTitle = szTitle, pszTemp; + va_list args; + int ret; + + va_start(args, uType); + /* wvsprintfA(buf,fmt, args); */ + + TRACE("(%08lx,%08lx,%p,%p,%08x)\n", + (DWORD)hInstance,(DWORD)hWnd,lpText,lpCaption,uType); + + if (!HIWORD(lpCaption)) + LoadStringA(hInstance, (DWORD)lpCaption, szTitle, sizeof(szTitle)); + else + pszTitle = lpCaption; + + if (!HIWORD(lpText)) + LoadStringA(hInstance, (DWORD)lpText, szText, sizeof(szText)); + else + pszText = lpText; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + pszText, 0, 0, (LPSTR)&pszTemp, 0, &args); + + va_end(args); + + ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType); + LocalFree((HLOCAL)pszTemp); + return ret; +} + +/************************************************************************* + * SHRegisterDragDrop [SHELL32.86] + * + * NOTES + * exported by ordinal + */ +HRESULT WINAPI SHRegisterDragDrop( + HWND hWnd, + LPDROPTARGET pDropTarget) +{ + FIXME("(%p,%p):stub.\n", hWnd, pDropTarget); + return RegisterDragDrop(hWnd, pDropTarget); +} + +/************************************************************************* + * SHRevokeDragDrop [SHELL32.87] + * + * NOTES + * exported by ordinal + */ +HRESULT WINAPI SHRevokeDragDrop(HWND hWnd) +{ + FIXME("(%p):stub.\n",hWnd); + return RevokeDragDrop(hWnd); +} + +/************************************************************************* + * SHDoDragDrop [SHELL32.88] + * + * NOTES + * exported by ordinal + */ +HRESULT WINAPI SHDoDragDrop( + HWND hWnd, + LPDATAOBJECT lpDataObject, + LPDROPSOURCE lpDropSource, + DWORD dwOKEffect, + LPDWORD pdwEffect) +{ + FIXME("(%p %p %p 0x%08lx %p):stub.\n", + hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect); + return DoDragDrop(lpDataObject, lpDropSource, dwOKEffect, pdwEffect); +} + +/************************************************************************* + * ArrangeWindows [SHELL32.184] + * + */ +WORD WINAPI ArrangeWindows( + HWND hwndParent, + DWORD dwReserved, + LPCRECT lpRect, + WORD cKids, + CONST HWND * lpKids) +{ + FIXME("(%p 0x%08lx %p 0x%04x %p):stub.\n", + hwndParent, dwReserved, lpRect, cKids, lpKids); + return 0; +} + +/************************************************************************* + * SignalFileOpen [SHELL32.103] + * + * NOTES + * exported by ordinal + */ +DWORD WINAPI +SignalFileOpen (DWORD dwParam1) +{ + FIXME("(0x%08lx):stub.\n", dwParam1); + + return 0; +} + +/************************************************************************* + * SHADD_get_policy - helper function for SHAddToRecentDocs + * + * PARAMETERS + * policy [IN] policy name (null termed string) to find + * type [OUT] ptr to DWORD to receive type + * buffer [OUT] ptr to area to hold data retrieved + * len [IN/OUT] ptr to DWORD holding size of buffer and getting + * length filled + * + * RETURNS + * result of the SHQueryValueEx call + */ +static INT SHADD_get_policy(LPSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len) +{ + HKEY Policy_basekey; + INT ret; + + /* Get the key for the policies location in the registry + */ + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", + 0, KEY_READ, &Policy_basekey)) { + + if (RegOpenKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", + 0, KEY_READ, &Policy_basekey)) { + TRACE("No Explorer Policies location exists. Policy wanted=%s\n", + policy); + *len = 0; + return ERROR_FILE_NOT_FOUND; + } + } + + /* Retrieve the data if it exists + */ + ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len); + RegCloseKey(Policy_basekey); + return ret; +} + + +/************************************************************************* + * SHADD_compare_mru - helper function for SHAddToRecentDocs + * + * PARAMETERS + * data1 [IN] data being looked for + * data2 [IN] data in MRU + * cbdata [IN] length from FindMRUData call (not used) + * + * RETURNS + * position within MRU list that data was added. + */ +static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData) +{ + return lstrcmpiA(data1, data2); +} + +/************************************************************************* + * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs + * + * PARAMETERS + * mruhandle [IN] handle for created MRU list + * doc_name [IN] null termed pure doc name + * new_lnk_name [IN] null termed path and file name for .lnk file + * buffer [IN/OUT] 2048 byte area to consturct MRU data + * len [OUT] ptr to int to receive space used in buffer + * + * RETURNS + * position within MRU list that data was added. + */ +static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPSTR doc_name, LPSTR new_lnk_name, + LPSTR buffer, INT *len) +{ + LPSTR ptr; + INT wlen; + + /*FIXME: Document: + * RecentDocs MRU data structure seems to be: + * +0h document file name w/ terminating 0h + * +nh short int w/ size of remaining + * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown + * +n+4h 10 bytes zeros - unknown + * +n+eh shortcut file name w/ terminating 0h + * +n+e+nh 3 zero bytes - unknown + */ + + /* Create the MRU data structure for "RecentDocs" + */ + ptr = buffer; + lstrcpyA(ptr, doc_name); + ptr += (lstrlenA(buffer) + 1); + wlen= lstrlenA(new_lnk_name) + 1 + 12; + *((short int*)ptr) = wlen; + ptr += 2; /* step past the length */ + *(ptr++) = 0x30; /* unknown reason */ + *(ptr++) = 0; /* unknown, but can be 0x00, 0x01, 0x02 */ + memset(ptr, 0, 10); + ptr += 10; + lstrcpyA(ptr, new_lnk_name); + ptr += (lstrlenA(new_lnk_name) + 1); + memset(ptr, 0, 3); + ptr += 3; + *len = ptr - buffer; + + /* Add the new entry into the MRU list + */ + return AddMRUData(mruhandle, (LPCVOID)buffer, *len); +} + +/************************************************************************* + * SHAddToRecentDocs [SHELL32.@] + * + * PARAMETERS + * uFlags [IN] SHARD_PATH or SHARD_PIDL + * pv [IN] string or pidl, NULL clears the list + * + * NOTES + * exported by name + */ +void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv) +{ +/* If list is a string list lpfnCompare has the following prototype + * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2) + * for binary lists the prototype is + * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData) + * where cbData is the no. of bytes to compare. + * Need to check what return value means identical - 0? + */ + + + UINT olderrormode; + HKEY HCUbasekey; + CHAR doc_name[MAX_PATH]; + CHAR link_dir[MAX_PATH]; + CHAR new_lnk_filepath[MAX_PATH]; + CHAR new_lnk_name[MAX_PATH]; + IMalloc *ppM; + LPITEMIDLIST pidl; + HWND hwnd = 0; /* FIXME: get real window handle */ + INT ret; + DWORD data[64], datalen, type; + + /*FIXME: Document: + * RecentDocs MRU data structure seems to be: + * +0h document file name w/ terminating 0h + * +nh short int w/ size of remaining + * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown + * +n+4h 10 bytes zeros - unknown + * +n+eh shortcut file name w/ terminating 0h + * +n+e+nh 3 zero bytes - unknown + */ + + /* See if we need to do anything. + */ + datalen = 64; + ret=SHADD_get_policy( "NoRecentDocsHistory", &type, &data, &datalen); + if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) { + ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret); + return; + } + if (ret == ERROR_SUCCESS) { + if (!( (type == REG_DWORD) || + ((type == REG_BINARY) && (datalen == 4)) )) { + ERR("Error policy data for \"NoRecentDocsHistory\" not formated correctly, type=%ld, len=%ld\n", + type, datalen); + return; + } + + TRACE("policy value for NoRecentDocsHistory = %08lx\n", data[0]); + /* now test the actual policy value */ + if ( data[0] != 0) + return; + } + + /* Open key to where the necessary info is + */ + /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH) + * and the close should be done during the _DETACH. The resulting + * key is stored in the DLL global data. + */ + if (RegCreateKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", + 0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) { + ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n"); + return; + } + + /* Get path to user's "Recent" directory + */ + if(SUCCEEDED(SHGetMalloc(&ppM))) { + if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT, + &pidl))) { + SHGetPathFromIDListA(pidl, link_dir); + IMalloc_Free(ppM, pidl); + } + else { + /* serious issues */ + link_dir[0] = 0; + ERR("serious issues 1\n"); + } + IMalloc_Release(ppM); + } + else { + /* serious issues */ + link_dir[0] = 0; + ERR("serious issues 2\n"); + } + TRACE("Users Recent dir %s\n", link_dir); + + /* If no input, then go clear the lists */ + if (!pv) { + /* clear user's Recent dir + */ + + /* FIXME: delete all files in "link_dir" + * + * while( more files ) { + * lstrcpyA(old_lnk_name, link_dir); + * PathAppendA(old_lnk_name, filenam); + * DeleteFileA(old_lnk_name); + * } + */ + FIXME("should delete all files in %s\\ \n", link_dir); + + /* clear MRU list + */ + /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against + * HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer + * and naturally it fails w/ rc=2. It should do it against + * HKEY_CURRENT_USER which is where it is stored, and where + * the MRU routines expect it!!!! + */ + RegDeleteKeyA(HCUbasekey, "RecentDocs"); + RegCloseKey(HCUbasekey); + return; + } + + /* Have data to add, the jobs to be done: + * 1. Add document to MRU list in registry "HKCU\Software\ + * Microsoft\Windows\CurrentVersion\Explorer\RecentDocs". + * 2. Add shortcut to document in the user's Recent directory + * (CSIDL_RECENT). + * 3. Add shortcut to Start menu's Documents submenu. + */ + + /* Get the pure document name from the input + */ + if (uFlags & SHARD_PIDL) { + SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name); + } + else { + lstrcpyA(doc_name, (LPCSTR) pv); + } + TRACE("full document name %s\n", doc_name); + PathStripPathA(doc_name); + TRACE("stripped document name %s\n", doc_name); + + + /* *** JOB 1: Update registry for ...\Explorer\RecentDocs list *** */ + + { /* on input needs: + * doc_name - pure file-spec, no path + * link_dir - path to the user's Recent directory + * HCUbasekey - key of ...Windows\CurrentVersion\Explorer" node + * creates: + * new_lnk_name- pure file-spec, no path for new .lnk file + * new_lnk_filepath + * - path and file name of new .lnk file + */ + CREATEMRULISTA mymru; + HANDLE mruhandle; + INT len, pos, bufused, err; + INT i; + DWORD attr; + CHAR buffer[2048]; + CHAR *ptr; + CHAR old_lnk_name[MAX_PATH]; + short int slen; + + mymru.cbSize = sizeof(CREATEMRULISTA); + mymru.nMaxItems = 15; + mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE; + mymru.hKey = HCUbasekey; + mymru.lpszSubKey = "RecentDocs"; + mymru.lpfnCompare = &SHADD_compare_mru; + mruhandle = CreateMRUListA(&mymru); + if (!mruhandle) { + /* MRU failed */ + ERR("MRU processing failed, handle zero\n"); + RegCloseKey(HCUbasekey); + return; + } + len = lstrlenA(doc_name); + pos = FindMRUData(mruhandle, doc_name, len, 0); + + /* Now get the MRU entry that will be replaced + * and delete the .lnk file for it + */ + if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos, + buffer, 2048)) != -1) { + ptr = buffer; + ptr += (lstrlenA(buffer) + 1); + slen = *((short int*)ptr); + ptr += 2; /* skip the length area */ + if (bufused >= slen + (ptr-buffer)) { + /* buffer size looks good */ + ptr += 12; /* get to string */ + len = bufused - (ptr-buffer); /* get length of buf remaining */ + if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) { + /* appears to be good string */ + lstrcpyA(old_lnk_name, link_dir); + PathAppendA(old_lnk_name, ptr); + if (!DeleteFileA(old_lnk_name)) { + if ((attr = GetFileAttributesA(old_lnk_name)) == INVALID_FILE_ATTRIBUTES) { + if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) { + ERR("Delete for %s failed, err=%d, attr=%08lx\n", + old_lnk_name, err, attr); + } + else { + TRACE("old .lnk file %s did not exist\n", + old_lnk_name); + } + } + else { + ERR("Delete for %s failed, attr=%08lx\n", + old_lnk_name, attr); + } + } + else { + TRACE("deleted old .lnk file %s\n", old_lnk_name); + } + } + } + } + + /* Create usable .lnk file name for the "Recent" directory + */ + wsprintfA(new_lnk_name, "%s.lnk", doc_name); + lstrcpyA(new_lnk_filepath, link_dir); + PathAppendA(new_lnk_filepath, new_lnk_name); + i = 1; + olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS); + while (GetFileAttributesA(new_lnk_filepath) != INVALID_FILE_ATTRIBUTES) { + i++; + wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i); + lstrcpyA(new_lnk_filepath, link_dir); + PathAppendA(new_lnk_filepath, new_lnk_name); + } + SetErrorMode(olderrormode); + TRACE("new shortcut will be %s\n", new_lnk_filepath); + + /* Now add the new MRU entry and data + */ + pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name, + buffer, &len); + FreeMRUList(mruhandle); + TRACE("Updated MRU list, new doc is position %d\n", pos); + } + + /* *** JOB 2: Create shortcut in user's "Recent" directory *** */ + + { /* on input needs: + * doc_name - pure file-spec, no path + * new_lnk_filepath + * - path and file name of new .lnk file + * uFlags[in] - flags on call to SHAddToRecentDocs + * pv[in] - document path/pidl on call to SHAddToRecentDocs + */ + IShellLinkA *psl = NULL; + IPersistFile *pPf = NULL; + HRESULT hres; + CHAR desc[MAX_PATH]; + WCHAR widelink[MAX_PATH]; + + CoInitialize(0); + + hres = CoCreateInstance( &CLSID_ShellLink, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IShellLinkA, + (LPVOID )&psl); + if(SUCCEEDED(hres)) { + + hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile, + (LPVOID *)&pPf); + if(FAILED(hres)) { + /* bombed */ + ERR("failed QueryInterface for IPersistFile %08lx\n", hres); + goto fail; + } + + /* Set the document path or pidl */ + if (uFlags & SHARD_PIDL) { + hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv); + } else { + hres = IShellLinkA_SetPath(psl, (LPCSTR) pv); + } + if(FAILED(hres)) { + /* bombed */ + ERR("failed Set{IDList|Path} %08lx\n", hres); + goto fail; + } + + lstrcpyA(desc, "Shortcut to "); + lstrcatA(desc, doc_name); + hres = IShellLinkA_SetDescription(psl, desc); + if(FAILED(hres)) { + /* bombed */ + ERR("failed SetDescription %08lx\n", hres); + goto fail; + } + + MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1, + widelink, MAX_PATH); + /* create the short cut */ + hres = IPersistFile_Save(pPf, widelink, TRUE); + if(FAILED(hres)) { + /* bombed */ + ERR("failed IPersistFile::Save %08lx\n", hres); + IPersistFile_Release(pPf); + IShellLinkA_Release(psl); + goto fail; + } + hres = IPersistFile_SaveCompleted(pPf, widelink); + IPersistFile_Release(pPf); + IShellLinkA_Release(psl); + TRACE("shortcut %s has been created, result=%08lx\n", + new_lnk_filepath, hres); + } + else { + ERR("CoCreateInstance failed, hres=%08lx\n", hres); + } + } + + fail: + CoUninitialize(); + + /* all done */ + RegCloseKey(HCUbasekey); + return; +} + +/************************************************************************* + * SHCreateShellFolderViewEx [SHELL32.174] + * + * NOTES + * see IShellFolder::CreateViewObject + */ +HRESULT WINAPI SHCreateShellFolderViewEx( + LPCSFV psvcbi, /* [in] shelltemplate struct */ + IShellView **ppv) /* [out] IShellView pointer */ +{ + IShellView * psf; + HRESULT hRes; + + TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", + psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, + psvcbi->fvm, psvcbi->psvOuter); + + psf = IShellView_Constructor(psvcbi->pshf); + + if (!psf) + return E_OUTOFMEMORY; + + IShellView_AddRef(psf); + hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppv); + IShellView_Release(psf); + + return hRes; +} +/************************************************************************* + * SHWinHelp [SHELL32.127] + * + */ +HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z) +{ FIXME("0x%08lx 0x%08lx 0x%08lx 0x%08lx stub\n",v,w,x,z); + return 0; +} +/************************************************************************* + * SHRunControlPanel [SHELL32.161] + * + */ +HRESULT WINAPI SHRunControlPanel (DWORD x, DWORD z) +{ FIXME("0x%08lx 0x%08lx stub\n",x,z); + return 0; +} + +static LPUNKNOWN SHELL32_IExplorerInterface=0; +/************************************************************************* + * SHSetInstanceExplorer [SHELL32.176] + * + * NOTES + * Sets the interface + */ +HRESULT WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown) +{ TRACE("%p\n", lpUnknown); + SHELL32_IExplorerInterface = lpUnknown; + return (HRESULT) lpUnknown; +} +/************************************************************************* + * SHGetInstanceExplorer [SHELL32.@] + * + * NOTES + * gets the interface pointer of the explorer and a reference + */ +HRESULT WINAPI SHGetInstanceExplorer (LPUNKNOWN * lpUnknown) +{ TRACE("%p\n", lpUnknown); + + *lpUnknown = SHELL32_IExplorerInterface; + + if (!SHELL32_IExplorerInterface) + return E_FAIL; + + IUnknown_AddRef(SHELL32_IExplorerInterface); + return NOERROR; +} +/************************************************************************* + * SHFreeUnusedLibraries [SHELL32.123] + * + * NOTES + * exported by name + */ +void WINAPI SHFreeUnusedLibraries (void) +{ + FIXME("stub\n"); +} +/************************************************************************* + * DAD_AutoScroll [SHELL32.129] + * + */ +BOOL WINAPI DAD_AutoScroll(HWND hwnd, AUTO_SCROLL_DATA *samples, LPPOINT pt) +{ + FIXME("hwnd = %p %p %p\n",hwnd,samples,pt); + return 0; +} +/************************************************************************* + * DAD_DragEnter [SHELL32.130] + * + */ +BOOL WINAPI DAD_DragEnter(HWND hwnd) +{ + FIXME("hwnd = %p\n",hwnd); + return FALSE; +} +/************************************************************************* + * DAD_DragEnterEx [SHELL32.131] + * + */ +BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p) +{ + FIXME("hwnd = %p (%ld,%ld)\n",hwnd,p.x,p.y); + return FALSE; +} +/************************************************************************* + * DAD_DragMove [SHELL32.134] + * + */ +BOOL WINAPI DAD_DragMove(POINT p) +{ + FIXME("(%ld,%ld)\n",p.x,p.y); + return FALSE; +} +/************************************************************************* + * DAD_DragLeave [SHELL32.132] + * + */ +BOOL WINAPI DAD_DragLeave(VOID) +{ + FIXME("\n"); + return FALSE; +} +/************************************************************************* + * DAD_SetDragImage [SHELL32.136] + * + * NOTES + * exported by name + */ +BOOL WINAPI DAD_SetDragImage( + HIMAGELIST himlTrack, + LPPOINT lppt) +{ + FIXME("%p %p stub\n",himlTrack, lppt); + return 0; +} +/************************************************************************* + * DAD_ShowDragImage [SHELL32.137] + * + * NOTES + * exported by name + */ +BOOL WINAPI DAD_ShowDragImage(BOOL bShow) +{ + FIXME("0x%08x stub\n",bShow); + return 0; +} + +static const WCHAR szwCabLocation[] = { + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'E','x','p','l','o','r','e','r','\\', + 'C','a','b','i','n','e','t','S','t','a','t','e',0 +}; + +static const WCHAR szwSettings[] = { 'S','e','t','t','i','n','g','s',0 }; + +/************************************************************************* + * ReadCabinetState [SHELL32.651] NT 4.0 + * + */ +BOOL WINAPI ReadCabinetState(CABINETSTATE *cs, int length) +{ + HKEY hkey = 0; + DWORD type, r; + + TRACE("%p %d \n",cs,length); + + if( (cs == NULL) || (length < (int)sizeof(*cs)) ) + return FALSE; + + r = RegOpenKeyW( HKEY_CURRENT_USER, szwCabLocation, &hkey ); + if( r == ERROR_SUCCESS ) + { + type = REG_BINARY; + r = RegQueryValueExW( hkey, szwSettings, + NULL, &type, (LPBYTE)cs, (LPDWORD)&length ); + RegCloseKey( hkey ); + + } + + /* if we can't read from the registry, create default values */ + if ( (r != ERROR_SUCCESS) || (cs->cLength < sizeof(*cs)) || + (cs->cLength != length) ) + { + ERR("Initializing shell cabinet settings\n"); + memset(cs, 0, sizeof(*cs)); + cs->cLength = sizeof(*cs); + cs->nVersion = 2; + cs->fFullPathTitle = FALSE; + cs->fSaveLocalView = TRUE; + cs->fNotShell = FALSE; + cs->fSimpleDefault = TRUE; + cs->fDontShowDescBar = FALSE; + cs->fNewWindowMode = FALSE; + cs->fShowCompColor = FALSE; + cs->fDontPrettyNames = FALSE; + cs->fAdminsCreateCommonGroups = TRUE; + cs->fMenuEnumFilter = 96; + } + + return TRUE; +} + +/************************************************************************* + * WriteCabinetState [SHELL32.652] NT 4.0 + * + */ +BOOL WINAPI WriteCabinetState(CABINETSTATE *cs) +{ + DWORD r; + HKEY hkey = 0; + + TRACE("%p\n",cs); + + if( cs == NULL ) + return FALSE; + + r = RegCreateKeyExW( HKEY_CURRENT_USER, szwCabLocation, 0, + NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); + if( r == ERROR_SUCCESS ) + { + r = RegSetValueExW( hkey, szwSettings, 0, + REG_BINARY, (LPBYTE) cs, cs->cLength); + + RegCloseKey( hkey ); + } + + return (r==ERROR_SUCCESS); +} + +/************************************************************************* + * FileIconInit [SHELL32.660] + * + */ +BOOL WINAPI FileIconInit(BOOL bFullInit) +{ FIXME("(%s)\n", bFullInit ? "true" : "false"); + return 0; +} +/************************************************************************* + * IsUserAdmin [SHELL32.680] NT 4.0 + * + */ +HRESULT WINAPI IsUserAdmin(void) +{ FIXME("stub\n"); + return TRUE; +} + +/************************************************************************* + * SHAllocShared [SHELL32.520] + * + * See shlwapi.SHAllocShared + */ +HANDLE WINAPI SHAllocShared(LPVOID lpvData, DWORD dwSize, DWORD dwProcId) +{ + GET_FUNC(pSHAllocShared, shlwapi, (char*)7, NULL); + return pSHAllocShared(lpvData, dwSize, dwProcId); +} + +/************************************************************************* + * SHLockShared [SHELL32.521] + * + * See shlwapi.SHLockShared + */ +LPVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId) +{ + GET_FUNC(pSHLockShared, shlwapi, (char*)8, NULL); + return pSHLockShared(hShared, dwProcId); +} + +/************************************************************************* + * SHUnlockShared [SHELL32.522] + * + * See shlwapi.SHUnlockShared + */ +BOOL WINAPI SHUnlockShared(LPVOID lpView) +{ + GET_FUNC(pSHUnlockShared, shlwapi, (char*)9, FALSE); + return pSHUnlockShared(lpView); +} + +/************************************************************************* + * SHFreeShared [SHELL32.523] + * + * See shlwapi.SHFreeShared + */ +BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId) +{ + GET_FUNC(pSHFreeShared, shlwapi, (char*)10, FALSE); + return pSHFreeShared(hShared, dwProcId); +} + +/************************************************************************* + * SetAppStartingCursor [SHELL32.99] + */ +HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v) +{ FIXME("hwnd=%p 0x%04lx stub\n",u,v ); + return 0; +} +/************************************************************************* + * SHLoadOLE [SHELL32.151] + * + */ +HRESULT WINAPI SHLoadOLE(LPARAM lParam) +{ FIXME("0x%04lx stub\n",lParam); + return S_OK; +} +/************************************************************************* + * DriveType [SHELL32.64] + * + */ +HRESULT WINAPI DriveType(DWORD u) +{ FIXME("0x%04lx stub\n",u); + return 0; +} +/************************************************************************* + * SHAbortInvokeCommand [SHELL32.198] + * + */ +HRESULT WINAPI SHAbortInvokeCommand(void) +{ FIXME("stub\n"); + return 1; +} +/************************************************************************* + * SHOutOfMemoryMessageBox [SHELL32.126] + * + */ +int WINAPI SHOutOfMemoryMessageBox( + HWND hwndOwner, + LPCSTR lpCaption, + UINT uType) +{ + FIXME("%p %s 0x%08x stub\n",hwndOwner, lpCaption, uType); + return 0; +} +/************************************************************************* + * SHFlushClipboard [SHELL32.121] + * + */ +HRESULT WINAPI SHFlushClipboard(void) +{ FIXME("stub\n"); + return 1; +} + +/************************************************************************* + * SHWaitForFileToOpen [SHELL32.97] + * + */ +BOOL WINAPI SHWaitForFileToOpen( + LPCITEMIDLIST pidl, + DWORD dwFlags, + DWORD dwTimeout) +{ + FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout); + return 0; +} + +/************************************************************************ + * @ [SHELL32.654] + * + * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState) + * second one could be a size (0x0c). The size is the same as the structure saved to + * HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState + * I'm (js) guessing: this one is just ReadCabinetState ;-) + */ +HRESULT WINAPI shell32_654 (CABINETSTATE *cs, int length) +{ + TRACE("%p %d\n",cs,length); + return ReadCabinetState(cs,length); +} + +/************************************************************************ + * RLBuildListOfPaths [SHELL32.146] + * + * NOTES + * builds a DPA + */ +DWORD WINAPI RLBuildListOfPaths (void) +{ FIXME("stub\n"); + return 0; +} +/************************************************************************ + * SHValidateUNC [SHELL32.173] + * + */ +HRESULT WINAPI SHValidateUNC (DWORD x, DWORD y, DWORD z) +{ + FIXME("0x%08lx 0x%08lx 0x%08lx stub\n",x,y,z); + return 0; +} + +/************************************************************************ + * DoEnvironmentSubstA [SHELL32.@] + * + */ +HRESULT WINAPI DoEnvironmentSubstA(LPSTR x, LPSTR y) +{ + FIXME("(%s, %s) stub\n", debugstr_a(x), debugstr_a(y)); + return 0; +} + +/************************************************************************ + * DoEnvironmentSubstW [SHELL32.@] + * + */ +HRESULT WINAPI DoEnvironmentSubstW(LPWSTR x, LPWSTR y) +{ + FIXME("(%s, %s): stub\n", debugstr_w(x), debugstr_w(y)); + return 0; +} + +/************************************************************************ + * DoEnvironmentSubst [SHELL32.53] + * + */ +HRESULT WINAPI DoEnvironmentSubstAW(LPVOID x, LPVOID y) +{ + if (SHELL_OsIsUnicode()) + return DoEnvironmentSubstW(x, y); + return DoEnvironmentSubstA(x, y); +} + +/************************************************************************* + * @ [SHELL32.243] + * + * Win98+ by-ordinal routine. In Win98 this routine returns zero and + * does nothing else. Possibly this does something in NT or SHELL32 5.0? + * + */ + +BOOL WINAPI shell32_243(DWORD a, DWORD b) +{ + return FALSE; +} + +/************************************************************************* + * @ [SHELL32.714] + */ +DWORD WINAPI SHELL32_714(LPVOID x) +{ + FIXME("(%s)stub\n", debugstr_w(x)); + return 0; +} + +/************************************************************************* + * SHAddFromPropSheetExtArray [SHELL32.167] + */ +DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c) +{ + FIXME("(%08lx,%08lx,%08lx)stub\n", a, b, c); + return 0; +} + +/************************************************************************* + * SHCreatePropSheetExtArray [SHELL32.168] + */ +DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c) +{ + FIXME("(%08lx,%s,%08lx)stub\n", a, debugstr_a(b), c); + return 0; +} + +/************************************************************************* + * SHReplaceFromPropSheetExtArray [SHELL32.170] + */ +DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d) +{ + FIXME("(%08lx,%08lx,%08lx,%08lx)stub\n", a, b, c, d); + return 0; +} + +/************************************************************************* + * SHDestroyPropSheetExtArray [SHELL32.169] + */ +DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a) +{ + FIXME("(%08lx)stub\n", a); + return 0; +} + +/************************************************************************* + * CIDLData_CreateFromIDArray [SHELL32.83] + * + * Create IDataObject from PIDLs?? + */ +HRESULT WINAPI CIDLData_CreateFromIDArray( + LPCITEMIDLIST pidlFolder, + DWORD cpidlFiles, + LPCITEMIDLIST *lppidlFiles, + LPDATAOBJECT *ppdataObject) +{ + UINT i; + HWND hwnd = 0; /*FIXME: who should be hwnd of owner? set to desktop */ + + TRACE("(%p, %ld, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject); + if (TRACE_ON(pidl)) + { + pdump (pidlFolder); + for (i=0; ii64Size = 0; + pSHQueryRBInfo->i64NumItems = 0; + + return S_OK; +} + +HRESULT WINAPI SHQueryRecycleBinW(LPCWSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) +{ + FIXME("%s, %p - stub\n", debugstr_w(pszRootPath), pSHQueryRBInfo); + + pSHQueryRBInfo->i64Size = 0; + pSHQueryRBInfo->i64NumItems = 0; + + return S_OK; +} diff --git a/reactos/lib/shell32/shellpath.c b/reactos/lib/shell32/shellpath.c index 012843b4011..f77a9bf10fe 100644 --- a/reactos/lib/shell32/shellpath.c +++ b/reactos/lib/shell32/shellpath.c @@ -1,2032 +1,2032 @@ -/* - * Path Functions - * - * Copyright 1998, 1999, 2000 Juergen Schmied - * Copyright 2004 Juan Lang - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES: - * - * Many of these functions are in SHLWAPI.DLL also - * - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include "wine/debug.h" -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "shlobj.h" -#include "shresdef.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "pidl.h" -#include "wine/unicode.h" -#include "shlwapi.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/* - ########## Combining and Constructing paths ########## -*/ - -/************************************************************************* - * PathAppend [SHELL32.36] - */ -BOOL WINAPI PathAppendAW( - LPVOID lpszPath1, - LPCVOID lpszPath2) -{ - if (SHELL_OsIsUnicode()) - return PathAppendW(lpszPath1, lpszPath2); - return PathAppendA(lpszPath1, lpszPath2); -} - -/************************************************************************* - * PathCombine [SHELL32.37] - */ -LPVOID WINAPI PathCombineAW( - LPVOID szDest, - LPCVOID lpszDir, - LPCVOID lpszFile) -{ - if (SHELL_OsIsUnicode()) - return PathCombineW( szDest, lpszDir, lpszFile ); - return PathCombineA( szDest, lpszDir, lpszFile ); -} - -/************************************************************************* - * PathAddBackslash [SHELL32.32] - */ -LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath) -{ - if(SHELL_OsIsUnicode()) - return PathAddBackslashW(lpszPath); - return PathAddBackslashA(lpszPath); -} - -/************************************************************************* - * PathBuildRoot [SHELL32.30] - */ -LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive) -{ - if(SHELL_OsIsUnicode()) - return PathBuildRootW(lpszPath, drive); - return PathBuildRootA(lpszPath, drive); -} - -/* - Extracting Component Parts -*/ - -/************************************************************************* - * PathFindFileName [SHELL32.34] - */ -LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath) -{ - if(SHELL_OsIsUnicode()) - return PathFindFileNameW(lpszPath); - return PathFindFileNameA(lpszPath); -} - -/************************************************************************* - * PathFindExtension [SHELL32.31] - */ -LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathFindExtensionW(lpszPath); - return PathFindExtensionA(lpszPath); - -} - -/************************************************************************* - * PathGetExtensionA [internal] - * - * NOTES - * exported by ordinal - * return value points to the first char after the dot - */ -static LPSTR PathGetExtensionA(LPCSTR lpszPath) -{ - TRACE("(%s)\n",lpszPath); - - lpszPath = PathFindExtensionA(lpszPath); - return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath); -} - -/************************************************************************* - * PathGetExtensionW [internal] - */ -static LPWSTR PathGetExtensionW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n",debugstr_w(lpszPath)); - - lpszPath = PathFindExtensionW(lpszPath); - return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath); -} - -/************************************************************************* - * PathGetExtension [SHELL32.158] - */ -LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath,DWORD void1, DWORD void2) -{ - if (SHELL_OsIsUnicode()) - return PathGetExtensionW(lpszPath); - return PathGetExtensionA(lpszPath); -} - -/************************************************************************* - * PathGetArgs [SHELL32.52] - */ -LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathGetArgsW(lpszPath); - return PathGetArgsA(lpszPath); -} - -/************************************************************************* - * PathGetDriveNumber [SHELL32.57] - */ -int WINAPI PathGetDriveNumberAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathGetDriveNumberW(lpszPath); - return PathGetDriveNumberA(lpszPath); -} - -/************************************************************************* - * PathRemoveFileSpec [SHELL32.35] - */ -BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathRemoveFileSpecW(lpszPath); - return PathRemoveFileSpecA(lpszPath); -} - -/************************************************************************* - * PathStripPath [SHELL32.38] - */ -void WINAPI PathStripPathAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - PathStripPathW(lpszPath); - else - PathStripPathA(lpszPath); -} - -/************************************************************************* - * PathStripToRoot [SHELL32.50] - */ -BOOL WINAPI PathStripToRootAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathStripToRootW(lpszPath); - return PathStripToRootA(lpszPath); -} - -/************************************************************************* - * PathRemoveArgs [SHELL32.251] - */ -void WINAPI PathRemoveArgsAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - PathRemoveArgsW(lpszPath); - else - PathRemoveArgsA(lpszPath); -} - -/************************************************************************* - * PathRemoveExtension [SHELL32.250] - */ -void WINAPI PathRemoveExtensionAW(LPVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - PathRemoveExtensionW(lpszPath); - else - PathRemoveExtensionA(lpszPath); -} - - -/* - Path Manipulations -*/ - -/************************************************************************* - * PathGetShortPathA [internal] - */ -static void PathGetShortPathA(LPSTR pszPath) -{ - CHAR path[MAX_PATH]; - - TRACE("%s\n", pszPath); - - if (GetShortPathNameA(pszPath, path, MAX_PATH)) - { - lstrcpyA(pszPath, path); - } -} - -/************************************************************************* - * PathGetShortPathW [internal] - */ -static void PathGetShortPathW(LPWSTR pszPath) -{ - WCHAR path[MAX_PATH]; - - TRACE("%s\n", debugstr_w(pszPath)); - - if (GetShortPathNameW(pszPath, path, MAX_PATH)) - { - lstrcpyW(pszPath, path); - } -} - -/************************************************************************* - * PathGetShortPath [SHELL32.92] - */ -VOID WINAPI PathGetShortPathAW(LPVOID pszPath) -{ - if(SHELL_OsIsUnicode()) - PathGetShortPathW(pszPath); - PathGetShortPathA(pszPath); -} - -/************************************************************************* - * PathRemoveBlanks [SHELL32.33] - */ -void WINAPI PathRemoveBlanksAW(LPVOID str) -{ - if(SHELL_OsIsUnicode()) - PathRemoveBlanksW(str); - else - PathRemoveBlanksA(str); -} - -/************************************************************************* - * PathQuoteSpaces [SHELL32.55] - */ -VOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath) -{ - if(SHELL_OsIsUnicode()) - PathQuoteSpacesW(lpszPath); - else - PathQuoteSpacesA(lpszPath); -} - -/************************************************************************* - * PathUnquoteSpaces [SHELL32.56] - */ -VOID WINAPI PathUnquoteSpacesAW(LPVOID str) -{ - if(SHELL_OsIsUnicode()) - PathUnquoteSpacesW(str); - else - PathUnquoteSpacesA(str); -} - -/************************************************************************* - * PathParseIconLocation [SHELL32.249] - */ -int WINAPI PathParseIconLocationAW (LPVOID lpszPath) -{ - if(SHELL_OsIsUnicode()) - return PathParseIconLocationW(lpszPath); - return PathParseIconLocationA(lpszPath); -} - -/* - ########## Path Testing ########## -*/ -/************************************************************************* - * PathIsUNC [SHELL32.39] - */ -BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathIsUNCW( lpszPath ); - return PathIsUNCA( lpszPath ); -} - -/************************************************************************* - * PathIsRelative [SHELL32.40] - */ -BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathIsRelativeW( lpszPath ); - return PathIsRelativeA( lpszPath ); -} - -/************************************************************************* - * PathIsRoot [SHELL32.29] - */ -BOOL WINAPI PathIsRootAW(LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathIsRootW(lpszPath); - return PathIsRootA(lpszPath); -} - -/************************************************************************* - * PathIsExeA [internal] - */ -static BOOL PathIsExeA (LPCSTR lpszPath) -{ - LPCSTR lpszExtension = PathGetExtensionA(lpszPath); - int i; - static const char * const lpszExtensions[] = - {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL }; - - TRACE("path=%s\n",lpszPath); - - for(i=0; lpszExtensions[i]; i++) - if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE; - - return FALSE; -} - -/************************************************************************* - * PathIsExeW [internal] - */ -static BOOL PathIsExeW (LPCWSTR lpszPath) -{ - LPCWSTR lpszExtension = PathGetExtensionW(lpszPath); - int i; - static const WCHAR lpszExtensions[][4] = - {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'}, - {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'}, - {'s','c','r','\0'}, {'\0'} }; - - TRACE("path=%s\n",debugstr_w(lpszPath)); - - for(i=0; lpszExtensions[i][0]; i++) - if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE; - - return FALSE; -} - -/************************************************************************* - * PathIsExe [SHELL32.43] - */ -BOOL WINAPI PathIsExeAW (LPCVOID path) -{ - if (SHELL_OsIsUnicode()) - return PathIsExeW (path); - return PathIsExeA(path); -} - -/************************************************************************* - * PathIsDirectory [SHELL32.159] - */ -BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathIsDirectoryW (lpszPath); - return PathIsDirectoryA (lpszPath); -} - -/************************************************************************* - * PathFileExists [SHELL32.45] - */ -BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return PathFileExistsW (lpszPath); - return PathFileExistsA (lpszPath); -} - -/************************************************************************* - * PathMatchSpec [SHELL32.46] - */ -BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask) -{ - if (SHELL_OsIsUnicode()) - return PathMatchSpecW( name, mask ); - return PathMatchSpecA( name, mask ); -} - -/************************************************************************* - * PathIsSameRoot [SHELL32.650] - */ -BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2) -{ - if (SHELL_OsIsUnicode()) - return PathIsSameRootW(lpszPath1, lpszPath2); - return PathIsSameRootA(lpszPath1, lpszPath2); -} - -/************************************************************************* - * IsLFNDriveA [SHELL32.41] - */ -BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath) -{ - DWORD fnlen; - - if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0)) - return FALSE; - return fnlen > 12; -} - -/************************************************************************* - * IsLFNDriveW [SHELL32.42] - */ -BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath) -{ - DWORD fnlen; - - if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0)) - return FALSE; - return fnlen > 12; -} - -/************************************************************************* - * IsLFNDrive [SHELL32.119] - */ -BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath) -{ - if (SHELL_OsIsUnicode()) - return IsLFNDriveW(lpszPath); - return IsLFNDriveA(lpszPath); -} - -/* - ########## Creating Something Unique ########## -*/ -/************************************************************************* - * PathMakeUniqueNameA [internal] - */ -BOOL WINAPI PathMakeUniqueNameA( - LPSTR lpszBuffer, - DWORD dwBuffSize, - LPCSTR lpszShortName, - LPCSTR lpszLongName, - LPCSTR lpszPathName) -{ - FIXME("%p %lu %s %s %s stub\n", - lpszBuffer, dwBuffSize, debugstr_a(lpszShortName), - debugstr_a(lpszLongName), debugstr_a(lpszPathName)); - return TRUE; -} - -/************************************************************************* - * PathMakeUniqueNameW [internal] - */ -BOOL WINAPI PathMakeUniqueNameW( - LPWSTR lpszBuffer, - DWORD dwBuffSize, - LPCWSTR lpszShortName, - LPCWSTR lpszLongName, - LPCWSTR lpszPathName) -{ - FIXME("%p %lu %s %s %s stub\n", - lpszBuffer, dwBuffSize, debugstr_w(lpszShortName), - debugstr_w(lpszLongName), debugstr_w(lpszPathName)); - return TRUE; -} - -/************************************************************************* - * PathMakeUniqueName [SHELL32.47] - */ -BOOL WINAPI PathMakeUniqueNameAW( - LPVOID lpszBuffer, - DWORD dwBuffSize, - LPCVOID lpszShortName, - LPCVOID lpszLongName, - LPCVOID lpszPathName) -{ - if (SHELL_OsIsUnicode()) - return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName); - return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName); -} - -/************************************************************************* - * PathYetAnotherMakeUniqueName [SHELL32.75] - * - * NOTES - * exported by ordinal - */ -BOOL WINAPI PathYetAnotherMakeUniqueName( - LPWSTR lpszBuffer, - LPCWSTR lpszPathName, - LPCWSTR lpszShortName, - LPCWSTR lpszLongName) -{ - FIXME("(%p, %s, %s ,%s):stub.\n", - lpszBuffer, debugstr_w(lpszPathName), debugstr_w(lpszShortName), debugstr_w(lpszLongName)); - return TRUE; -} - - -/* - ########## cleaning and resolving paths ########## - */ - -/************************************************************************* - * PathFindOnPath [SHELL32.145] - */ -BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs) -{ - if (SHELL_OsIsUnicode()) - return PathFindOnPathW(sFile, (LPCWSTR *)sOtherDirs); - return PathFindOnPathA(sFile, (LPCSTR *)sOtherDirs); -} - -/************************************************************************* - * PathCleanupSpec [SHELL32.171] - * - * lpszFile is changed in place. - */ -int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW ) -{ - int i = 0; - DWORD rc = 0; - int length = 0; - - if (SHELL_OsIsUnicode()) - { - LPWSTR p = lpszFileW; - - TRACE("Cleanup %s\n",debugstr_w(lpszFileW)); - - if (lpszPathW) - length = strlenW(lpszPathW); - - while (*p) - { - int gct = PathGetCharTypeW(*p); - if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR) - { - lpszFileW[i]='-'; - rc |= PCS_REPLACEDCHAR; - } - else - lpszFileW[i]=*p; - i++; - p++; - if (length + i == MAX_PATH) - { - rc |= PCS_FATAL | PCS_PATHTOOLONG; - break; - } - } - lpszFileW[i]=0; - } - else - { - LPSTR lpszFileA = (LPSTR)lpszFileW; - LPCSTR lpszPathA = (LPSTR)lpszPathW; - LPSTR p = lpszFileA; - - TRACE("Cleanup %s\n",debugstr_a(lpszFileA)); - - if (lpszPathA) - length = strlen(lpszPathA); - - while (*p) - { - int gct = PathGetCharTypeA(*p); - if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR) - { - lpszFileA[i]='-'; - rc |= PCS_REPLACEDCHAR; - } - else - lpszFileA[i]=*p; - i++; - p++; - if (length + i == MAX_PATH) - { - rc |= PCS_FATAL | PCS_PATHTOOLONG; - break; - } - } - lpszFileA[i]=0; - } - return rc; -} - -/************************************************************************* - * PathQualifyA [SHELL32] - */ -BOOL WINAPI PathQualifyA(LPCSTR pszPath) -{ - FIXME("%s\n",pszPath); - return 0; -} - -/************************************************************************* - * PathQualifyW [SHELL32] - */ -BOOL WINAPI PathQualifyW(LPCWSTR pszPath) -{ - FIXME("%s\n",debugstr_w(pszPath)); - return 0; -} - -/************************************************************************* - * PathQualify [SHELL32.49] - */ -BOOL WINAPI PathQualifyAW(LPCVOID pszPath) -{ - if (SHELL_OsIsUnicode()) - return PathQualifyW(pszPath); - return PathQualifyA(pszPath); -} - -/************************************************************************* - * PathResolveA [SHELL32.51] - */ -BOOL WINAPI PathResolveA( - LPSTR lpszPath, - LPCSTR *alpszPaths, - DWORD dwFlags) -{ - FIXME("(%s,%p,0x%08lx),stub!\n", - lpszPath, *alpszPaths, dwFlags); - return 0; -} - -/************************************************************************* - * PathResolveW [SHELL32] - */ -BOOL WINAPI PathResolveW( - LPWSTR lpszPath, - LPCWSTR *alpszPaths, - DWORD dwFlags) -{ - FIXME("(%s,%p,0x%08lx),stub!\n", - debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags); - return 0; -} - -/************************************************************************* - * PathResolve [SHELL32.51] - */ -BOOL WINAPI PathResolveAW( - LPVOID lpszPath, - LPCVOID *alpszPaths, - DWORD dwFlags) -{ - if (SHELL_OsIsUnicode()) - return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags); - return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags); -} - -/************************************************************************* -* PathProcessCommandA [SHELL32.653] -*/ -HRESULT WINAPI PathProcessCommandA ( - LPCSTR lpszPath, - LPSTR lpszBuff, - DWORD dwBuffSize, - DWORD dwFlags) -{ - FIXME("%s %p 0x%04lx 0x%04lx stub\n", - lpszPath, lpszBuff, dwBuffSize, dwFlags); - strcpy(lpszBuff, lpszPath); - return 0; -} - -/************************************************************************* -* PathProcessCommandW -*/ -HRESULT WINAPI PathProcessCommandW ( - LPCWSTR lpszPath, - LPWSTR lpszBuff, - DWORD dwBuffSize, - DWORD dwFlags) -{ - FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n", - debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags); - strcpyW(lpszBuff, lpszPath); - return 0; -} - -/************************************************************************* -* PathProcessCommand (SHELL32.653) -*/ -HRESULT WINAPI PathProcessCommandAW ( - LPCVOID lpszPath, - LPVOID lpszBuff, - DWORD dwBuffSize, - DWORD dwFlags) -{ - if (SHELL_OsIsUnicode()) - return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags); - return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags); -} - -/* - ########## special ########## -*/ - -/************************************************************************* - * PathSetDlgItemPath (SHELL32.48) - */ -VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath) -{ - if (SHELL_OsIsUnicode()) - PathSetDlgItemPathW(hDlg, id, pszPath); - else - PathSetDlgItemPathA(hDlg, id, pszPath); -} - -static const WCHAR szCurrentVersion[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0'}; -static const WCHAR Administrative_ToolsW[] = {'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'}; -static const WCHAR AppDataW[] = {'A','p','p','D','a','t','a','\0'}; -static const WCHAR CacheW[] = {'C','a','c','h','e','\0'}; -static const WCHAR CD_BurningW[] = {'C','D',' ','B','u','r','n','i','n','g','\0'}; -static const WCHAR Common_Administrative_ToolsW[] = {'C','o','m','m','o','n',' ','A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'}; -static const WCHAR Common_AppDataW[] = {'C','o','m','m','o','n',' ','A','p','p','D','a','t','a','\0'}; -static const WCHAR Common_DesktopW[] = {'C','o','m','m','o','n',' ','D','e','s','k','t','o','p','\0'}; -static const WCHAR Common_DocumentsW[] = {'C','o','m','m','o','n',' ','D','o','c','u','m','e','n','t','s','\0'}; -static const WCHAR CommonFilesDirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r','\0'}; -static const WCHAR CommonMusicW[] = {'C','o','m','m','o','n','M','u','s','i','c','\0'}; -static const WCHAR CommonPicturesW[] = {'C','o','m','m','o','n','P','i','c','t','u','r','e','s','\0'}; -static const WCHAR Common_ProgramsW[] = {'C','o','m','m','o','n',' ','P','r','o','g','r','a','m','s','\0'}; -static const WCHAR Common_StartUpW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t','U','p','\0'}; -static const WCHAR Common_Start_MenuW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t',' ','M','e','n','u','\0'}; -static const WCHAR Common_TemplatesW[] = {'C','o','m','m','o','n',' ','T','e','m','p','l','a','t','e','s','\0'}; -static const WCHAR CommonVideoW[] = {'C','o','m','m','o','n','V','i','d','e','o','\0'}; -static const WCHAR CookiesW[] = {'C','o','o','k','i','e','s','\0'}; -static const WCHAR DesktopW[] = {'D','e','s','k','t','o','p','\0'}; -static const WCHAR FavoritesW[] = {'F','a','v','o','r','i','t','e','s','\0'}; -static const WCHAR FontsW[] = {'F','o','n','t','s','\0'}; -static const WCHAR HistoryW[] = {'H','i','s','t','o','r','y','\0'}; -static const WCHAR Local_AppDataW[] = {'L','o','c','a','l',' ','A','p','p','D','a','t','a','\0'}; -static const WCHAR My_MusicW[] = {'M','y',' ','M','u','s','i','c','\0'}; -static const WCHAR My_PicturesW[] = {'M','y',' ','P','i','c','t','u','r','e','s','\0'}; -static const WCHAR My_VideoW[] = {'M','y',' ','V','i','d','e','o','\0'}; -static const WCHAR NetHoodW[] = {'N','e','t','H','o','o','d','\0'}; -static const WCHAR PersonalW[] = {'P','e','r','s','o','n','a','l','\0'}; -static const WCHAR PrintHoodW[] = {'P','r','i','n','t','H','o','o','d','\0'}; -static const WCHAR ProgramFilesDirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r','\0'}; -static const WCHAR ProgramsW[] = {'P','r','o','g','r','a','m','s','\0'}; -static const WCHAR RecentW[] = {'R','e','c','e','n','t','\0'}; -static const WCHAR ResourcesW[] = {'R','e','s','o','u','r','c','e','s','\0'}; -static const WCHAR SendToW[] = {'S','e','n','d','T','o','\0'}; -static const WCHAR StartUpW[] = {'S','t','a','r','t','U','p','\0'}; -static const WCHAR Start_MenuW[] = {'S','t','a','r','t',' ','M','e','n','u','\0'}; -static const WCHAR TemplatesW[] = {'T','e','m','p','l','a','t','e','s','\0'}; -static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t','\0'}; -static const WCHAR AllUsersProfileW[] = {'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%','\0'}; -static const WCHAR UserProfileW[] = {'%','U','S','E','R','P','R','O','F','I','L','E','%','\0'}; -static const WCHAR SystemDriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%','\0'}; -static const WCHAR ProfileListW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','r','o','f','i','l','e','L','i','s','t',0}; -static const WCHAR ProfilesDirectoryW[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0}; -static const WCHAR AllUsersProfileValueW[] = {'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e','\0'}; -static const WCHAR szSHFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'}; -static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'}; -/* This defaults to L"Documents and Settings" on Windows 2000/XP, but we're - * acting more Windows 9x-like for now. - */ -static const WCHAR szDefaultProfileDirW[] = {'w','i','n','d','o','w','s','\\','p','r','o','f','i','l','e','s','\0'}; -static const WCHAR AllUsersW[] = {'A','l','l',' ','U','s','e','r','s','\0'}; - -typedef enum _CSIDL_Type { - CSIDL_Type_User, - CSIDL_Type_AllUsers, - CSIDL_Type_CurrVer, - CSIDL_Type_Disallowed, - CSIDL_Type_NonExistent, - CSIDL_Type_WindowsPath, - CSIDL_Type_SystemPath, -} CSIDL_Type; - -typedef struct -{ - CSIDL_Type type; - LPCWSTR szValueName; - LPCWSTR szDefaultPath; /* fallback string or resource ID */ -} CSIDL_DATA; - -static const CSIDL_DATA CSIDL_Data[] = -{ - { /* 0x00 - CSIDL_DESKTOP */ - CSIDL_Type_User, - DesktopW, - MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY) - }, - { /* 0x01 - CSIDL_INTERNET */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x02 - CSIDL_PROGRAMS */ - CSIDL_Type_User, - ProgramsW, - MAKEINTRESOURCEW(IDS_PROGRAMS) - }, - { /* 0x03 - CSIDL_CONTROLS (.CPL files) */ - CSIDL_Type_SystemPath, - NULL, - NULL - }, - { /* 0x04 - CSIDL_PRINTERS */ - CSIDL_Type_SystemPath, - NULL, - NULL - }, - { /* 0x05 - CSIDL_PERSONAL */ - CSIDL_Type_User, - PersonalW, - MAKEINTRESOURCEW(IDS_PERSONAL) - }, - { /* 0x06 - CSIDL_FAVORITES */ - CSIDL_Type_User, - FavoritesW, - MAKEINTRESOURCEW(IDS_FAVORITES) - }, - { /* 0x07 - CSIDL_STARTUP */ - CSIDL_Type_User, - StartUpW, - MAKEINTRESOURCEW(IDS_STARTUP) - }, - { /* 0x08 - CSIDL_RECENT */ - CSIDL_Type_User, - RecentW, - MAKEINTRESOURCEW(IDS_RECENT) - }, - { /* 0x09 - CSIDL_SENDTO */ - CSIDL_Type_User, - SendToW, - MAKEINTRESOURCEW(IDS_SENDTO) - }, - { /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */ - CSIDL_Type_Disallowed, - NULL, - NULL, - }, - { /* 0x0b - CSIDL_STARTMENU */ - CSIDL_Type_User, - Start_MenuW, - MAKEINTRESOURCEW(IDS_STARTMENU) - }, - { /* 0x0c - CSIDL_MYDOCUMENTS */ - CSIDL_Type_Disallowed, /* matches WinXP--can't get its path */ - NULL, - NULL - }, - { /* 0x0d - CSIDL_MYMUSIC */ - CSIDL_Type_User, - My_MusicW, - MAKEINTRESOURCEW(IDS_MYMUSIC) - }, - { /* 0x0e - CSIDL_MYVIDEO */ - CSIDL_Type_User, - My_VideoW, - MAKEINTRESOURCEW(IDS_MYVIDEO) - }, - { /* 0x0f - unassigned */ - CSIDL_Type_Disallowed, - NULL, - NULL, - }, - { /* 0x10 - CSIDL_DESKTOPDIRECTORY */ - CSIDL_Type_User, - DesktopW, - MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY) - }, - { /* 0x11 - CSIDL_DRIVES */ - CSIDL_Type_Disallowed, - NULL, - NULL, - }, - { /* 0x12 - CSIDL_NETWORK */ - CSIDL_Type_Disallowed, - NULL, - NULL, - }, - { /* 0x13 - CSIDL_NETHOOD */ - CSIDL_Type_User, - NetHoodW, - MAKEINTRESOURCEW(IDS_NETHOOD) - }, - { /* 0x14 - CSIDL_FONTS */ - CSIDL_Type_WindowsPath, - NULL, - FontsW - }, - { /* 0x15 - CSIDL_TEMPLATES */ - CSIDL_Type_User, - TemplatesW, - MAKEINTRESOURCEW(IDS_TEMPLATES) - }, - { /* 0x16 - CSIDL_COMMON_STARTMENU */ - CSIDL_Type_AllUsers, - Common_Start_MenuW, - MAKEINTRESOURCEW(IDS_STARTMENU) - }, - { /* 0x17 - CSIDL_COMMON_PROGRAMS */ - CSIDL_Type_AllUsers, - Common_ProgramsW, - MAKEINTRESOURCEW(IDS_PROGRAMS) - }, - { /* 0x18 - CSIDL_COMMON_STARTUP */ - CSIDL_Type_AllUsers, - Common_StartUpW, - MAKEINTRESOURCEW(IDS_STARTUP) - }, - { /* 0x19 - CSIDL_COMMON_DESKTOPDIRECTORY */ - CSIDL_Type_AllUsers, - Common_DesktopW, - MAKEINTRESOURCEW(IDS_DESKTOP) - }, - { /* 0x1a - CSIDL_APPDATA */ - CSIDL_Type_User, - AppDataW, - MAKEINTRESOURCEW(IDS_APPDATA) - }, - { /* 0x1b - CSIDL_PRINTHOOD */ - CSIDL_Type_User, - PrintHoodW, - MAKEINTRESOURCEW(IDS_PRINTHOOD) - }, - { /* 0x1c - CSIDL_LOCAL_APPDATA */ - CSIDL_Type_User, - Local_AppDataW, - MAKEINTRESOURCEW(IDS_LOCAL_APPDATA) - }, - { /* 0x1d - CSIDL_ALTSTARTUP */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x1e - CSIDL_COMMON_ALTSTARTUP */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x1f - CSIDL_COMMON_FAVORITES */ - CSIDL_Type_AllUsers, - FavoritesW, - MAKEINTRESOURCEW(IDS_FAVORITES) - }, - { /* 0x20 - CSIDL_INTERNET_CACHE */ - CSIDL_Type_User, - CacheW, - MAKEINTRESOURCEW(IDS_INTERNET_CACHE) - }, - { /* 0x21 - CSIDL_COOKIES */ - CSIDL_Type_User, - CookiesW, - MAKEINTRESOURCEW(IDS_COOKIES) - }, - { /* 0x22 - CSIDL_HISTORY */ - CSIDL_Type_User, - HistoryW, - MAKEINTRESOURCEW(IDS_HISTORY) - }, - { /* 0x23 - CSIDL_COMMON_APPDATA */ - CSIDL_Type_AllUsers, - Common_AppDataW, - MAKEINTRESOURCEW(IDS_APPDATA) - }, - { /* 0x24 - CSIDL_WINDOWS */ - CSIDL_Type_WindowsPath, - NULL, - NULL - }, - { /* 0x25 - CSIDL_SYSTEM */ - CSIDL_Type_SystemPath, - NULL, - NULL - }, - { /* 0x26 - CSIDL_PROGRAM_FILES */ - CSIDL_Type_CurrVer, - ProgramFilesDirW, - MAKEINTRESOURCEW(IDS_PROGRAM_FILES) - }, - { /* 0x27 - CSIDL_MYPICTURES */ - CSIDL_Type_User, - My_PicturesW, - MAKEINTRESOURCEW(IDS_MYPICTURES) - }, - { /* 0x28 - CSIDL_PROFILE */ - CSIDL_Type_User, - NULL, - NULL - }, - { /* 0x29 - CSIDL_SYSTEMX86 */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x2a - CSIDL_PROGRAM_FILESX86 */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */ - CSIDL_Type_CurrVer, - CommonFilesDirW, - MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON) - }, - { /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x2d - CSIDL_COMMON_TEMPLATES */ - CSIDL_Type_AllUsers, - Common_TemplatesW, - MAKEINTRESOURCEW(IDS_TEMPLATES) - }, - { /* 0x2e - CSIDL_COMMON_DOCUMENTS */ - CSIDL_Type_AllUsers, - Common_DocumentsW, - MAKEINTRESOURCEW(IDS_COMMON_DOCUMENTS) - }, - { /* 0x2f - CSIDL_COMMON_ADMINTOOLS */ - CSIDL_Type_AllUsers, - Common_Administrative_ToolsW, - MAKEINTRESOURCEW(IDS_ADMINTOOLS) - }, - { /* 0x30 - CSIDL_ADMINTOOLS */ - CSIDL_Type_User, - Administrative_ToolsW, - MAKEINTRESOURCEW(IDS_ADMINTOOLS) - }, - { /* 0x31 - CSIDL_CONNECTIONS */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x32 - unassigned */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x33 - unassigned */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x34 - unassigned */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x35 - CSIDL_COMMON_MUSIC */ - CSIDL_Type_AllUsers, - CommonMusicW, - MAKEINTRESOURCEW(IDS_COMMON_MUSIC) - }, - { /* 0x36 - CSIDL_COMMON_PICTURES */ - CSIDL_Type_AllUsers, - CommonPicturesW, - MAKEINTRESOURCEW(IDS_COMMON_PICTURES) - }, - { /* 0x37 - CSIDL_COMMON_VIDEO */ - CSIDL_Type_AllUsers, - CommonVideoW, - MAKEINTRESOURCEW(IDS_COMMON_VIDEO) - }, - { /* 0x38 - CSIDL_RESOURCES */ - CSIDL_Type_WindowsPath, - NULL, - ResourcesW - }, - { /* 0x39 - CSIDL_RESOURCES_LOCALIZED */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x3a - CSIDL_COMMON_OEM_LINKS */ - CSIDL_Type_NonExistent, - NULL, - NULL - }, - { /* 0x3b - CSIDL_CDBURN_AREA */ - CSIDL_Type_User, - CD_BurningW, - MAKEINTRESOURCEW(IDS_CDBURN_AREA) - }, - { /* 0x3c unassigned */ - CSIDL_Type_Disallowed, - NULL, - NULL - }, - { /* 0x3d - CSIDL_COMPUTERSNEARME */ - CSIDL_Type_Disallowed, /* FIXME */ - NULL, - NULL - }, - { /* 0x3e - CSIDL_PROFILES */ - CSIDL_Type_Disallowed, /* oddly, this matches WinXP */ - NULL, - NULL - } -}; - -static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest); - -/* Gets the value named value from the registry key - * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders - * (or from rootKey\userPrefix\... if userPrefix is not NULL) into path, which - * is assumed to be MAX_PATH WCHARs in length. - * If it exists, expands the value and writes the expanded value to - * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders - * Returns successful error code if the value was retrieved from the registry, - * and a failure otherwise. - */ -static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix, - LPCWSTR value, LPWSTR path) -{ - HRESULT hr; - WCHAR shellFolderPath[MAX_PATH], userShellFolderPath[MAX_PATH]; - LPCWSTR pShellFolderPath, pUserShellFolderPath; - DWORD dwDisp, dwType, dwPathLen = MAX_PATH; - HKEY userShellFolderKey, shellFolderKey; - - TRACE("%p,%s,%s,%p\n",rootKey, debugstr_w(userPrefix), debugstr_w(value), - path); - - if (userPrefix) - { - strcpyW(shellFolderPath, userPrefix); - PathAddBackslashW(shellFolderPath); - strcatW(shellFolderPath, szSHFolders); - pShellFolderPath = shellFolderPath; - strcpyW(userShellFolderPath, userPrefix); - PathAddBackslashW(userShellFolderPath); - strcatW(userShellFolderPath, szSHUserFolders); - pUserShellFolderPath = userShellFolderPath; - } - else - { - pUserShellFolderPath = szSHUserFolders; - pShellFolderPath = szSHFolders; - } - - if (RegCreateKeyExW(rootKey, pShellFolderPath, 0, NULL, 0, KEY_ALL_ACCESS, - NULL, &shellFolderKey, &dwDisp)) - { - TRACE("Failed to create %s\n", debugstr_w(pShellFolderPath)); - return E_FAIL; - } - if (RegCreateKeyExW(rootKey, pUserShellFolderPath, 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &userShellFolderKey, &dwDisp)) - { - TRACE("Failed to create %s\n", - debugstr_w(pUserShellFolderPath)); - RegCloseKey(shellFolderKey); - return E_FAIL; - } - - if (!RegQueryValueExW(userShellFolderKey, value, NULL, &dwType, - (LPBYTE)path, &dwPathLen) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ)) - { - path[dwPathLen / sizeof(WCHAR)] = '\0'; - if (dwType == REG_EXPAND_SZ && path[0] == '%') - { - WCHAR szTemp[MAX_PATH]; - - _SHExpandEnvironmentStrings(path, szTemp); - strncpyW(path, szTemp, MAX_PATH); - } - RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path, - (strlenW(path) + 1) * sizeof(WCHAR)); - hr = S_OK; - } - else - hr = E_FAIL; - RegCloseKey(shellFolderKey); - RegCloseKey(userShellFolderKey); - TRACE("returning 0x%08lx\n", hr); - return hr; -} - -/* Gets a 'semi-expanded' default value of the CSIDL with index folder into - * pszPath, based on the entries in CSIDL_Data. By semi-expanded, I mean: - * - The entry's szDefaultPath may be either a string value or an integer - * resource identifier. In the latter case, the string value of the resource - * is written. - * - Depending on the entry's type, the path may begin with an (unexpanded) - * environment variable name. The caller is responsible for expanding - * environment strings if so desired. - * The types that are prepended with environment variables are: - * CSIDL_Type_User: %USERPROFILE% - * CSIDL_Type_AllUsers: %ALLUSERSPROFILE% - * CSIDL_Type_CurrVer: %SystemDrive% - * (Others might make sense too, but as yet are unneeded.) - * FIXME: there are two special cases for the default value: - * - the "My Documents" (CSIDL_PERSONAL) entry should be $HOME - * - the CSIDL_DESKTOP and CSIDL_DESKTOPDIRECTORY (which have the same path) - * should be $HOME/Desktop if it exists - * But, $HOME doesn't seem to be inherited into the Wine environment. I could - * use getenv, but this returns me a UNIX path, which may or may not be - * reachable from any currently mounted DOS drives. - */ -static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath) -{ - HRESULT hr; - WCHAR resourcePath[MAX_PATH]; - LPCWSTR pDefaultPath = NULL; - - TRACE("0x%02x,%p\n", folder, pszPath); - - if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) - return E_INVALIDARG; - if (!pszPath) - return E_INVALIDARG; - - if (CSIDL_Data[folder].szDefaultPath && - IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath)) - { - if (LoadStringW(shell32_hInstance, - (UINT)CSIDL_Data[folder].szDefaultPath, resourcePath, MAX_PATH)) - { - hr = S_OK; - pDefaultPath = resourcePath; - } - else - { - FIXME("LoadString failed, missing translation?\n"); - hr = E_FAIL; - } - } - else - { - hr = S_OK; - pDefaultPath = CSIDL_Data[folder].szDefaultPath; - } - if (SUCCEEDED(hr)) - { - switch (CSIDL_Data[folder].type) - { - case CSIDL_Type_User: - strcpyW(pszPath, UserProfileW); - break; - case CSIDL_Type_AllUsers: - strcpyW(pszPath, AllUsersProfileW); - break; - case CSIDL_Type_CurrVer: - strcpyW(pszPath, SystemDriveW); - break; - default: - ; /* no corresponding env. var, do nothing */ - } - if (pDefaultPath) - { - PathAddBackslashW(pszPath); - strcatW(pszPath, pDefaultPath); - } - } - TRACE("returning 0x%08lx\n", hr); - return hr; -} - -/* Gets the (unexpanded) value of the folder with index folder into pszPath. - * The folder's type is assumed to be CSIDL_Type_CurrVer. Its default value - * can be overridden in the HKLM\\szCurrentVersion key. - * If dwFlags has SHGFP_TYPE_DEFAULT set or if the value isn't overridden in - * the registry, uses _SHGetDefaultValue to get the value. - */ -static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder, - LPWSTR pszPath) -{ - HRESULT hr; - - TRACE("0x%08lx,0x%02x,%p\n", dwFlags, folder, pszPath); - - if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) - return E_INVALIDARG; - if (CSIDL_Data[folder].type != CSIDL_Type_CurrVer) - return E_INVALIDARG; - if (!pszPath) - return E_INVALIDARG; - - if (dwFlags & SHGFP_TYPE_DEFAULT) - hr = _SHGetDefaultValue(folder, pszPath); - else - { - HKEY hKey; - DWORD dwDisp; - - if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szCurrentVersion, 0, - NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp)) - hr = E_FAIL; - else - { - DWORD dwType, dwPathLen = MAX_PATH * sizeof(WCHAR); - - if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL, - &dwType, (LPBYTE)pszPath, &dwPathLen) || - (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) - { - hr = _SHGetDefaultValue(folder, pszPath); - dwType = REG_EXPAND_SZ; - RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType, - (LPBYTE)pszPath, (strlenW(pszPath)+1)*sizeof(WCHAR)); - } - else - { - pszPath[dwPathLen / sizeof(WCHAR)] = '\0'; - hr = S_OK; - } - RegCloseKey(hKey); - } - } - TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); - return hr; -} - -/* Gets the user's path (unexpanded) for the CSIDL with index folder: - * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it. Otherwise - * calls _SHGetUserShellFolderPath for it. Where it looks depends on hToken: - * - if hToken is -1, looks in HKEY_USERS\.Default - * - otherwise looks first in HKEY_CURRENT_USER, followed by HKEY_LOCAL_MACHINE - * if HKEY_CURRENT_USER doesn't contain any entries. If both fail, finally - * calls _SHGetDefaultValue for it. - */ -static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder, - LPWSTR pszPath) -{ - HRESULT hr; - - TRACE("%p,0x%08lx,0x%02x,%p\n", hToken, dwFlags, folder, pszPath); - - if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) - return E_INVALIDARG; - if (CSIDL_Data[folder].type != CSIDL_Type_User) - return E_INVALIDARG; - if (!pszPath) - return E_INVALIDARG; - - /* Only the current user and the default user are supported right now - * I'm afraid. - * FIXME: should be able to call GetTokenInformation on the token, - * then call ConvertSidToStringSidW on it to get the user prefix. - * But Wine's registry doesn't store user info by sid, it stores it - * by user name (and I don't know how to convert from a token to a - * user name). - */ - if (hToken != NULL && hToken != (HANDLE)-1) - { - FIXME("unsupported for user other than current or default\n"); - return E_FAIL; - } - - if (dwFlags & SHGFP_TYPE_DEFAULT) - hr = _SHGetDefaultValue(folder, pszPath); - else - { - LPCWSTR userPrefix = NULL; - HKEY hRootKey; - - if (hToken == (HANDLE)-1) - { - hRootKey = HKEY_USERS; - userPrefix = DefaultW; - } - else /* hToken == NULL, other values disallowed above */ - hRootKey = HKEY_CURRENT_USER; - hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, - CSIDL_Data[folder].szValueName, pszPath); - if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE) - hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, - CSIDL_Data[folder].szValueName, pszPath); - if (FAILED(hr)) - hr = _SHGetDefaultValue(folder, pszPath); - } - TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); - return hr; -} - -/* Gets the (unexpanded) path for the CSIDL with index folder. If dwFlags has - * SHGFP_TYPE_DEFAULT set, calls _SHGetDefaultValue. Otherwise calls - * _SHGetUserShellFolderPath for it, looking only in HKEY_LOCAL_MACHINE. - * If this fails, falls back to _SHGetDefaultValue. - */ -static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder, - LPWSTR pszPath) -{ - HRESULT hr; - - TRACE("0x%08lx,0x%02x,%p\n", dwFlags, folder, pszPath); - - if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) - return E_INVALIDARG; - if (CSIDL_Data[folder].type != CSIDL_Type_AllUsers) - return E_INVALIDARG; - if (!pszPath) - return E_INVALIDARG; - - if (dwFlags & SHGFP_TYPE_DEFAULT) - hr = _SHGetDefaultValue(folder, pszPath); - else - { - hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, - CSIDL_Data[folder].szValueName, pszPath); - if (FAILED(hr)) - hr = _SHGetDefaultValue(folder, pszPath); - } - TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); - return hr; -} - -static HRESULT _SHOpenProfilesKey(PHKEY pKey) -{ - LONG lRet; - DWORD disp; - - lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, NULL, 0, - KEY_ALL_ACCESS, NULL, pKey, &disp); - return HRESULT_FROM_WIN32(lRet); -} - -/* Reads the value named szValueName from the key profilesKey (assumed to be - * opened by _SHOpenProfilesKey) into szValue, which is assumed to be MAX_PATH - * WCHARs in length. If it doesn't exist, returns szDefault (and saves - * szDefault to the registry). - */ -static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName, - LPWSTR szValue, LPCWSTR szDefault) -{ - HRESULT hr; - DWORD type, dwPathLen = MAX_PATH * sizeof(WCHAR); - LONG lRet; - - TRACE("%p,%s,%p,%s\n", profilesKey, debugstr_w(szValueName), szValue, - debugstr_w(szDefault)); - lRet = RegQueryValueExW(profilesKey, szValueName, NULL, &type, - (LPBYTE)szValue, &dwPathLen); - if (!lRet && (type == REG_SZ || type == REG_EXPAND_SZ) && dwPathLen - && *szValue) - { - dwPathLen /= sizeof(WCHAR); - szValue[dwPathLen] = '\0'; - hr = S_OK; - } - else - { - /* Missing or invalid value, set a default */ - strncpyW(szValue, szDefault, MAX_PATH); - szValue[MAX_PATH - 1] = '\0'; - TRACE("Setting missing value %s to %s\n", debugstr_w(szValueName), - debugstr_w(szValue)); - lRet = RegSetValueExW(profilesKey, szValueName, 0, REG_EXPAND_SZ, - (LPBYTE)szValue, (strlenW(szValue) + 1) * sizeof(WCHAR)); - if (lRet) - hr = HRESULT_FROM_WIN32(lRet); - else - hr = S_OK; - } - TRACE("returning 0x%08lx (output value is %s)\n", hr, debugstr_w(szValue)); - return hr; -} - -/* From the original Wine source: - * - * Attempts to expand environment variables from szSrc into szDest, which is - * assumed to be MAX_PATH characters in length. Before referring to the - * environment, handles a few variables directly, because the environment - * variables may not be set when this is called (as during Wine's installation - * when default values are being written to the registry). - * The directly handled environment variables, and their source, are: - * - ALLUSERSPROFILE, USERPROFILE: reads from the registry - * - SystemDrive: uses GetSystemDirectoryW and uses the drive portion of its - * path - * If one of the directly handled environment variables is expanded, only - * expands a single variable, and only in the beginning of szSrc. - * - * That's fine for Wine, but it breaks in ReactOS where we have profile paths - * like "c:\documents and settings\Administrator.REACTOS". Anyway, we have the - * environment variables handy so we'll just use them instead of hacking around - */ -static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest) -{ - HRESULT hr; - WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 }; - - TRACE("%s, %p\n", debugstr_w(szSrc), szDest); - - if (!szSrc || !szDest) return E_INVALIDARG; - - /* short-circuit if there's nothing to expand */ - if (szSrc[0] != '%') - { - strcpyW(szDest, szSrc); - hr = S_OK; - goto end; - } - - *szDest = 0; - strcpyW(szTemp, szSrc); - while (SUCCEEDED(hr) && szTemp[0] == '%') - { - DWORD ret = ExpandEnvironmentStringsW(szSrc, szDest, MAX_PATH); - - if (ret > MAX_PATH) - hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - else if (ret == 0) - hr = HRESULT_FROM_WIN32(GetLastError()); - else - hr = S_OK; - if (SUCCEEDED(hr) && szDest[0] == '%') - strcpyW(szTemp, szDest); - else - { - /* terminate loop */ - szTemp[0] = '\0'; - } - } -end: - TRACE("returning 0x%08lx (input was %s, output is %s)\n", hr, - debugstr_w(szSrc), debugstr_w(szDest)); - return hr; -} - -/************************************************************************* - * SHGetFolderPathW [SHELL32.@] - * - * NOTES - * Converts nFolder to path. Most values can be overridden in either - * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders - * or in the same location in HKLM. - * The registry usage is explained by the following tech note: - * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36173.asp - * The "Shell Folders" registry key was used in NT4 and earlier systems. - * Beginning with Windows 2000, the "User Shell Folders" key is used, so - * changes made to it are made to the former key too. This synchronization is - * done on-demand: not until someone requests the value of one of these paths - * (by calling one of the SHGet functions) is the value synchronized. - * Furthermore, as explained here: - * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36276.asp - * the HKCU paths take precedence over the HKLM paths. - * - **********************************************************************/ -HRESULT WINAPI SHGetFolderPathW( - HWND hwndOwner, - int nFolder, - HANDLE hToken, - DWORD dwFlags, - LPWSTR pszPath) -{ - HRESULT hr; - WCHAR szBuildPath[MAX_PATH], szTemp[MAX_PATH]; - DWORD folder = nFolder & CSIDL_FOLDER_MASK; - CSIDL_Type type; - int ret; - - TRACE("%p,%p,nFolder=0x%04x\n", hwndOwner,pszPath,nFolder); - - /* Windows always NULL-terminates the resulting path regardless of success - * or failure, so do so first - */ - if (pszPath) - *pszPath = '\0'; - if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) - return E_INVALIDARG; - szTemp[0] = 0; - type = CSIDL_Data[folder].type; - switch (type) - { - case CSIDL_Type_Disallowed: - hr = E_INVALIDARG; - break; - case CSIDL_Type_NonExistent: - hr = S_FALSE; - break; - case CSIDL_Type_WindowsPath: - GetWindowsDirectoryW(szTemp, MAX_PATH); - if (CSIDL_Data[folder].szDefaultPath && - !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) && - *CSIDL_Data[folder].szDefaultPath) - { - PathAddBackslashW(szTemp); - strcatW(szTemp, CSIDL_Data[folder].szDefaultPath); - } - hr = S_OK; - break; - case CSIDL_Type_SystemPath: - GetSystemDirectoryW(szTemp, MAX_PATH); - if (CSIDL_Data[folder].szDefaultPath && - !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) && - *CSIDL_Data[folder].szDefaultPath) - { - PathAddBackslashW(szTemp); - strcatW(szTemp, CSIDL_Data[folder].szDefaultPath); - } - hr = S_OK; - break; - case CSIDL_Type_CurrVer: - hr = _SHGetCurrentVersionPath(dwFlags, folder, szTemp); - break; - case CSIDL_Type_User: - hr = _SHGetUserProfilePath(hToken, dwFlags, folder, szTemp); - break; - case CSIDL_Type_AllUsers: - hr = _SHGetAllUsersProfilePath(dwFlags, folder, szTemp); - break; - default: - FIXME("bogus type %d, please fix\n", type); - hr = E_INVALIDARG; - break; - } - - /* Expand environment strings if necessary */ - if (*szTemp == '%') - hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath); - else - strcpyW(szBuildPath, szTemp); - /* Copy the path if it's available before we might return */ - if (SUCCEEDED(hr) && pszPath) - strcpyW(pszPath, szBuildPath); - - if (FAILED(hr)) goto end; - - /* if we don't care about existing directories we are ready */ - if(nFolder & CSIDL_FLAG_DONT_VERIFY) goto end; - - if (PathFileExistsW(szBuildPath)) goto end; - - /* not existing but we are not allowed to create it. The return value - * is verified against shell32 version 6.0. - */ - if (!(nFolder & CSIDL_FLAG_CREATE)) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - goto end; - } - - /* create directory/directories */ - ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL); - if (ret && ret != ERROR_ALREADY_EXISTS) - { - ERR("Failed to create directory '%s'.\n", debugstr_w(szBuildPath)); - hr = E_FAIL; - goto end; - } - - TRACE("Created missing system directory '%s'\n", debugstr_w(szBuildPath)); -end: - TRACE("returning 0x%08lx (final path is %s)\n", hr, debugstr_w(szBuildPath)); - return hr; -} - -/************************************************************************* - * SHGetFolderPathA [SHELL32.@] - */ -HRESULT WINAPI SHGetFolderPathA( - HWND hwndOwner, - int nFolder, - HANDLE hToken, - DWORD dwFlags, - LPSTR pszPath) -{ - WCHAR szTemp[MAX_PATH]; - HRESULT hr; - - TRACE("%p,%p,nFolder=0x%04x\n",hwndOwner,pszPath,nFolder); - - if (pszPath) - *pszPath = '\0'; - hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, szTemp); - if (SUCCEEDED(hr) && pszPath) - WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL, - NULL); - - return hr; -} - -/* For each folder in folders, if its value has not been set in the registry, - * call _SHGetUserProfilePath or _SHGetAllUsersProfilePath (depending on the - * folder's type) to get the unexpanded value first. - * This will create the expanded value in the Shell Folders key, and - * return the unexpanded value. - * Write the unexpanded value to User Shell Folders, and query it with - * SHGetFolderPath to force the creation of the directory if it doesn't - * already exist. - */ -static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken, - LPCWSTR szUserShellFolderPath, const UINT folders[], UINT foldersLen) -{ - UINT i; - WCHAR path[MAX_PATH]; - HRESULT hr = S_OK; - HKEY hKey = NULL; - DWORD dwDisp, dwType, dwPathLen; - LONG ret; - - TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken, - debugstr_w(szUserShellFolderPath), folders, foldersLen); - - ret = RegCreateKeyExW(hRootKey, szUserShellFolderPath, 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &hKey, &dwDisp); - if (ret) - hr = HRESULT_FROM_WIN32(ret); - for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++) - { - dwPathLen = MAX_PATH * sizeof(WCHAR); - if (RegQueryValueExW(hKey, CSIDL_Data[folders[i]].szValueName, NULL, - &dwType, (LPBYTE)path, &dwPathLen) || (dwType != REG_SZ && - dwType != REG_EXPAND_SZ)) - { - *path = '\0'; - if (CSIDL_Data[folders[i]].type == CSIDL_Type_User) - _SHGetUserProfilePath(hToken, SHGFP_TYPE_DEFAULT, folders[i], - path); - else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers) - _SHGetAllUsersProfilePath(SHGFP_TYPE_DEFAULT, folders[i], path); - else - hr = E_FAIL; - if (*path) - { - ret = RegSetValueExW(hKey, CSIDL_Data[folders[i]].szValueName, - 0, REG_EXPAND_SZ, (LPBYTE)path, - (strlenW(path) + 1) * sizeof(WCHAR)); - if (ret) - hr = HRESULT_FROM_WIN32(ret); - else - hr = SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE, - hToken, SHGFP_TYPE_DEFAULT, NULL); - } - } - } - if (hKey) - RegCloseKey(hKey); - - TRACE("returning 0x%08lx\n", hr); - return hr; -} - -static HRESULT _SHRegisterUserShellFolders(BOOL bDefault) -{ - static const UINT folders[] = { - CSIDL_PROGRAMS, - CSIDL_PERSONAL, - CSIDL_FAVORITES, - CSIDL_STARTUP, - CSIDL_RECENT, - CSIDL_SENDTO, - CSIDL_STARTMENU, - CSIDL_DESKTOPDIRECTORY, - CSIDL_NETHOOD, - CSIDL_TEMPLATES, - CSIDL_PRINTHOOD, - CSIDL_COOKIES, - CSIDL_HISTORY, - }; - WCHAR userShellFolderPath[MAX_PATH]; - LPCWSTR pUserShellFolderPath; - HRESULT hr = S_OK; - HKEY hRootKey; - HANDLE hToken; - - TRACE("%s\n", bDefault ? "TRUE" : "FALSE"); - if (bDefault) - { - hToken = (HANDLE)-1; - hRootKey = HKEY_USERS; - strcpyW(userShellFolderPath, DefaultW); - PathAddBackslashW(userShellFolderPath); - strcatW(userShellFolderPath, szSHUserFolders); - pUserShellFolderPath = userShellFolderPath; - } - else - { - hToken = NULL; - hRootKey = HKEY_CURRENT_USER; - pUserShellFolderPath = szSHUserFolders; - } - - hr = _SHRegisterFolders(hRootKey, hToken, pUserShellFolderPath, - folders, sizeof(folders) / sizeof(folders[0])); - TRACE("returning 0x%08lx\n", hr); - return hr; -} - -static HRESULT _SHRegisterCommonShellFolders(void) -{ - static const UINT folders[] = { - CSIDL_COMMON_STARTMENU, - CSIDL_COMMON_PROGRAMS, - CSIDL_COMMON_STARTUP, - CSIDL_COMMON_DESKTOPDIRECTORY, - CSIDL_COMMON_FAVORITES, - CSIDL_COMMON_APPDATA, - CSIDL_COMMON_TEMPLATES, - CSIDL_COMMON_DOCUMENTS, - }; - HRESULT hr; - - TRACE("\n"); - hr = _SHRegisterFolders(HKEY_LOCAL_MACHINE, NULL, szSHUserFolders, - folders, sizeof(folders) / sizeof(folders[0])); - TRACE("returning 0x%08lx\n", hr); - return hr; -} - -/* Register the default values in the registry, as some apps seem to depend - * on their presence. The set registered was taken from Windows XP. - */ -HRESULT SHELL_RegisterShellFolders(void) -{ - HRESULT hr = _SHRegisterUserShellFolders(TRUE); - - if (SUCCEEDED(hr)) - hr = _SHRegisterUserShellFolders(FALSE); - if (SUCCEEDED(hr)) - hr = _SHRegisterCommonShellFolders(); - return hr; -} - -/************************************************************************* - * SHGetSpecialFolderPathA [SHELL32.@] - */ -BOOL WINAPI SHGetSpecialFolderPathA ( - HWND hwndOwner, - LPSTR szPath, - int nFolder, - BOOL bCreate) -{ - return (SHGetFolderPathA( - hwndOwner, - nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), - NULL, - 0, - szPath)) == S_OK ? TRUE : FALSE; -} - -/************************************************************************* - * SHGetSpecialFolderPathW - */ -BOOL WINAPI SHGetSpecialFolderPathW ( - HWND hwndOwner, - LPWSTR szPath, - int nFolder, - BOOL bCreate) -{ - return (SHGetFolderPathW( - hwndOwner, - nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), - NULL, - 0, - szPath)) == S_OK ? TRUE : FALSE; -} - -/************************************************************************* - * SHGetSpecialFolderPath (SHELL32.175) - */ -BOOL WINAPI SHGetSpecialFolderPathAW ( - HWND hwndOwner, - LPVOID szPath, - int nFolder, - BOOL bCreate) - -{ - if (SHELL_OsIsUnicode()) - return SHGetSpecialFolderPathW (hwndOwner, szPath, nFolder, bCreate); - return SHGetSpecialFolderPathA (hwndOwner, szPath, nFolder, bCreate); -} - -/************************************************************************* - * SHGetFolderLocation [SHELL32.@] - * - * NOTES - * Gets the folder locations from the registry and creates a pidl. - * Creates missing reg keys and directories. - * Mostly forwards to SHGetFolderPathW, but a few values of nFolder return - * virtual folders that are handled here. - * - * PARAMS - * hwndOwner [I] - * nFolder [I] CSIDL_xxxxx - * hToken [I] token representing user, or NULL for current user, or -1 for - * default user - * dwReserved [I] must be zero - * ppidl [O] PIDL of a special folder - * - * NOTES - */ -HRESULT WINAPI SHGetFolderLocation( - HWND hwndOwner, - int nFolder, - HANDLE hToken, - DWORD dwReserved, - LPITEMIDLIST *ppidl) -{ - HRESULT hr = E_INVALIDARG; - - TRACE("%p 0x%08x %p 0x%08lx %p\n", - hwndOwner, nFolder, hToken, dwReserved, ppidl); - - if (!ppidl) - return E_INVALIDARG; - if (dwReserved) - return E_INVALIDARG; - - /* The virtual folders' locations are not user-dependent */ - *ppidl = NULL; - switch (nFolder) - { - case CSIDL_DESKTOP: - *ppidl = _ILCreateDesktop(); - break; - - case CSIDL_INTERNET: - *ppidl = _ILCreateIExplore(); - break; - - case CSIDL_CONTROLS: - *ppidl = _ILCreateControlPanel(); - break; - - case CSIDL_PRINTERS: - *ppidl = _ILCreatePrinters(); - break; - - case CSIDL_FONTS: - FIXME("virtual font folder"); - break; - - case CSIDL_BITBUCKET: - *ppidl = _ILCreateBitBucket(); - break; - - case CSIDL_DRIVES: - *ppidl = _ILCreateMyComputer(); - break; - - case CSIDL_NETWORK: - *ppidl = _ILCreateNetwork(); - break; - - default: - { - WCHAR szPath[MAX_PATH]; - - hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, - SHGFP_TYPE_CURRENT, szPath); - if (SUCCEEDED(hr)) - { - DWORD attributes=0; - - TRACE("Value=%s\n", debugstr_w(szPath)); - hr = SHILCreateFromPathW(szPath, ppidl, &attributes); - } - else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - /* unlike SHGetFolderPath, SHGetFolderLocation in shell32 - * version 6.0 returns E_FAIL for non-existing paths - */ - hr = E_FAIL; - } - } - } - if(*ppidl) - hr = NOERROR; - - TRACE("-- (new pidl %p)\n",*ppidl); - return hr; -} - -/************************************************************************* - * SHGetSpecialFolderLocation [SHELL32.@] - * - * NOTES - * In NT5, SHGetSpecialFolderLocation needs the /Recent - * directory. - */ -HRESULT WINAPI SHGetSpecialFolderLocation( - HWND hwndOwner, - INT nFolder, - LPITEMIDLIST * ppidl) -{ - HRESULT hr = E_INVALIDARG; - - TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl); - - if (!ppidl) - return E_INVALIDARG; - - hr = SHGetFolderLocation(hwndOwner, nFolder, NULL, 0, ppidl); - return hr; -} +/* + * Path Functions + * + * Copyright 1998, 1999, 2000 Juergen Schmied + * Copyright 2004 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES: + * + * Many of these functions are in SHLWAPI.DLL also + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "shlobj.h" +#include "shresdef.h" +#include "shell32_main.h" +#include "undocshell.h" +#include "pidl.h" +#include "wine/unicode.h" +#include "shlwapi.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/* + ########## Combining and Constructing paths ########## +*/ + +/************************************************************************* + * PathAppend [SHELL32.36] + */ +BOOL WINAPI PathAppendAW( + LPVOID lpszPath1, + LPCVOID lpszPath2) +{ + if (SHELL_OsIsUnicode()) + return PathAppendW(lpszPath1, lpszPath2); + return PathAppendA(lpszPath1, lpszPath2); +} + +/************************************************************************* + * PathCombine [SHELL32.37] + */ +LPVOID WINAPI PathCombineAW( + LPVOID szDest, + LPCVOID lpszDir, + LPCVOID lpszFile) +{ + if (SHELL_OsIsUnicode()) + return PathCombineW( szDest, lpszDir, lpszFile ); + return PathCombineA( szDest, lpszDir, lpszFile ); +} + +/************************************************************************* + * PathAddBackslash [SHELL32.32] + */ +LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath) +{ + if(SHELL_OsIsUnicode()) + return PathAddBackslashW(lpszPath); + return PathAddBackslashA(lpszPath); +} + +/************************************************************************* + * PathBuildRoot [SHELL32.30] + */ +LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive) +{ + if(SHELL_OsIsUnicode()) + return PathBuildRootW(lpszPath, drive); + return PathBuildRootA(lpszPath, drive); +} + +/* + Extracting Component Parts +*/ + +/************************************************************************* + * PathFindFileName [SHELL32.34] + */ +LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath) +{ + if(SHELL_OsIsUnicode()) + return PathFindFileNameW(lpszPath); + return PathFindFileNameA(lpszPath); +} + +/************************************************************************* + * PathFindExtension [SHELL32.31] + */ +LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathFindExtensionW(lpszPath); + return PathFindExtensionA(lpszPath); + +} + +/************************************************************************* + * PathGetExtensionA [internal] + * + * NOTES + * exported by ordinal + * return value points to the first char after the dot + */ +static LPSTR PathGetExtensionA(LPCSTR lpszPath) +{ + TRACE("(%s)\n",lpszPath); + + lpszPath = PathFindExtensionA(lpszPath); + return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath); +} + +/************************************************************************* + * PathGetExtensionW [internal] + */ +static LPWSTR PathGetExtensionW(LPCWSTR lpszPath) +{ + TRACE("(%s)\n",debugstr_w(lpszPath)); + + lpszPath = PathFindExtensionW(lpszPath); + return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath); +} + +/************************************************************************* + * PathGetExtension [SHELL32.158] + */ +LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath,DWORD void1, DWORD void2) +{ + if (SHELL_OsIsUnicode()) + return PathGetExtensionW(lpszPath); + return PathGetExtensionA(lpszPath); +} + +/************************************************************************* + * PathGetArgs [SHELL32.52] + */ +LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathGetArgsW(lpszPath); + return PathGetArgsA(lpszPath); +} + +/************************************************************************* + * PathGetDriveNumber [SHELL32.57] + */ +int WINAPI PathGetDriveNumberAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathGetDriveNumberW(lpszPath); + return PathGetDriveNumberA(lpszPath); +} + +/************************************************************************* + * PathRemoveFileSpec [SHELL32.35] + */ +BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathRemoveFileSpecW(lpszPath); + return PathRemoveFileSpecA(lpszPath); +} + +/************************************************************************* + * PathStripPath [SHELL32.38] + */ +void WINAPI PathStripPathAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + PathStripPathW(lpszPath); + else + PathStripPathA(lpszPath); +} + +/************************************************************************* + * PathStripToRoot [SHELL32.50] + */ +BOOL WINAPI PathStripToRootAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathStripToRootW(lpszPath); + return PathStripToRootA(lpszPath); +} + +/************************************************************************* + * PathRemoveArgs [SHELL32.251] + */ +void WINAPI PathRemoveArgsAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + PathRemoveArgsW(lpszPath); + else + PathRemoveArgsA(lpszPath); +} + +/************************************************************************* + * PathRemoveExtension [SHELL32.250] + */ +void WINAPI PathRemoveExtensionAW(LPVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + PathRemoveExtensionW(lpszPath); + else + PathRemoveExtensionA(lpszPath); +} + + +/* + Path Manipulations +*/ + +/************************************************************************* + * PathGetShortPathA [internal] + */ +static void PathGetShortPathA(LPSTR pszPath) +{ + CHAR path[MAX_PATH]; + + TRACE("%s\n", pszPath); + + if (GetShortPathNameA(pszPath, path, MAX_PATH)) + { + lstrcpyA(pszPath, path); + } +} + +/************************************************************************* + * PathGetShortPathW [internal] + */ +static void PathGetShortPathW(LPWSTR pszPath) +{ + WCHAR path[MAX_PATH]; + + TRACE("%s\n", debugstr_w(pszPath)); + + if (GetShortPathNameW(pszPath, path, MAX_PATH)) + { + lstrcpyW(pszPath, path); + } +} + +/************************************************************************* + * PathGetShortPath [SHELL32.92] + */ +VOID WINAPI PathGetShortPathAW(LPVOID pszPath) +{ + if(SHELL_OsIsUnicode()) + PathGetShortPathW(pszPath); + PathGetShortPathA(pszPath); +} + +/************************************************************************* + * PathRemoveBlanks [SHELL32.33] + */ +void WINAPI PathRemoveBlanksAW(LPVOID str) +{ + if(SHELL_OsIsUnicode()) + PathRemoveBlanksW(str); + else + PathRemoveBlanksA(str); +} + +/************************************************************************* + * PathQuoteSpaces [SHELL32.55] + */ +VOID WINAPI PathQuoteSpacesAW (LPVOID lpszPath) +{ + if(SHELL_OsIsUnicode()) + PathQuoteSpacesW(lpszPath); + else + PathQuoteSpacesA(lpszPath); +} + +/************************************************************************* + * PathUnquoteSpaces [SHELL32.56] + */ +VOID WINAPI PathUnquoteSpacesAW(LPVOID str) +{ + if(SHELL_OsIsUnicode()) + PathUnquoteSpacesW(str); + else + PathUnquoteSpacesA(str); +} + +/************************************************************************* + * PathParseIconLocation [SHELL32.249] + */ +int WINAPI PathParseIconLocationAW (LPVOID lpszPath) +{ + if(SHELL_OsIsUnicode()) + return PathParseIconLocationW(lpszPath); + return PathParseIconLocationA(lpszPath); +} + +/* + ########## Path Testing ########## +*/ +/************************************************************************* + * PathIsUNC [SHELL32.39] + */ +BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathIsUNCW( lpszPath ); + return PathIsUNCA( lpszPath ); +} + +/************************************************************************* + * PathIsRelative [SHELL32.40] + */ +BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathIsRelativeW( lpszPath ); + return PathIsRelativeA( lpszPath ); +} + +/************************************************************************* + * PathIsRoot [SHELL32.29] + */ +BOOL WINAPI PathIsRootAW(LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathIsRootW(lpszPath); + return PathIsRootA(lpszPath); +} + +/************************************************************************* + * PathIsExeA [internal] + */ +static BOOL PathIsExeA (LPCSTR lpszPath) +{ + LPCSTR lpszExtension = PathGetExtensionA(lpszPath); + int i; + static const char * const lpszExtensions[] = + {"exe", "com", "pif", "cmd", "bat", "scf", "scr", NULL }; + + TRACE("path=%s\n",lpszPath); + + for(i=0; lpszExtensions[i]; i++) + if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE; + + return FALSE; +} + +/************************************************************************* + * PathIsExeW [internal] + */ +static BOOL PathIsExeW (LPCWSTR lpszPath) +{ + LPCWSTR lpszExtension = PathGetExtensionW(lpszPath); + int i; + static const WCHAR lpszExtensions[][4] = + {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','f','\0'}, + {'c','m','d','\0'}, {'b','a','t','\0'}, {'s','c','f','\0'}, + {'s','c','r','\0'}, {'\0'} }; + + TRACE("path=%s\n",debugstr_w(lpszPath)); + + for(i=0; lpszExtensions[i][0]; i++) + if (!strcmpiW(lpszExtension,lpszExtensions[i])) return TRUE; + + return FALSE; +} + +/************************************************************************* + * PathIsExe [SHELL32.43] + */ +BOOL WINAPI PathIsExeAW (LPCVOID path) +{ + if (SHELL_OsIsUnicode()) + return PathIsExeW (path); + return PathIsExeA(path); +} + +/************************************************************************* + * PathIsDirectory [SHELL32.159] + */ +BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathIsDirectoryW (lpszPath); + return PathIsDirectoryA (lpszPath); +} + +/************************************************************************* + * PathFileExists [SHELL32.45] + */ +BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return PathFileExistsW (lpszPath); + return PathFileExistsA (lpszPath); +} + +/************************************************************************* + * PathMatchSpec [SHELL32.46] + */ +BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask) +{ + if (SHELL_OsIsUnicode()) + return PathMatchSpecW( name, mask ); + return PathMatchSpecA( name, mask ); +} + +/************************************************************************* + * PathIsSameRoot [SHELL32.650] + */ +BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2) +{ + if (SHELL_OsIsUnicode()) + return PathIsSameRootW(lpszPath1, lpszPath2); + return PathIsSameRootA(lpszPath1, lpszPath2); +} + +/************************************************************************* + * IsLFNDriveA [SHELL32.41] + */ +BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath) +{ + DWORD fnlen; + + if (!GetVolumeInformationA(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0)) + return FALSE; + return fnlen > 12; +} + +/************************************************************************* + * IsLFNDriveW [SHELL32.42] + */ +BOOL WINAPI IsLFNDriveW(LPCWSTR lpszPath) +{ + DWORD fnlen; + + if (!GetVolumeInformationW(lpszPath, NULL, 0, NULL, &fnlen, NULL, NULL, 0)) + return FALSE; + return fnlen > 12; +} + +/************************************************************************* + * IsLFNDrive [SHELL32.119] + */ +BOOL WINAPI IsLFNDriveAW(LPCVOID lpszPath) +{ + if (SHELL_OsIsUnicode()) + return IsLFNDriveW(lpszPath); + return IsLFNDriveA(lpszPath); +} + +/* + ########## Creating Something Unique ########## +*/ +/************************************************************************* + * PathMakeUniqueNameA [internal] + */ +BOOL WINAPI PathMakeUniqueNameA( + LPSTR lpszBuffer, + DWORD dwBuffSize, + LPCSTR lpszShortName, + LPCSTR lpszLongName, + LPCSTR lpszPathName) +{ + FIXME("%p %lu %s %s %s stub\n", + lpszBuffer, dwBuffSize, debugstr_a(lpszShortName), + debugstr_a(lpszLongName), debugstr_a(lpszPathName)); + return TRUE; +} + +/************************************************************************* + * PathMakeUniqueNameW [internal] + */ +BOOL WINAPI PathMakeUniqueNameW( + LPWSTR lpszBuffer, + DWORD dwBuffSize, + LPCWSTR lpszShortName, + LPCWSTR lpszLongName, + LPCWSTR lpszPathName) +{ + FIXME("%p %lu %s %s %s stub\n", + lpszBuffer, dwBuffSize, debugstr_w(lpszShortName), + debugstr_w(lpszLongName), debugstr_w(lpszPathName)); + return TRUE; +} + +/************************************************************************* + * PathMakeUniqueName [SHELL32.47] + */ +BOOL WINAPI PathMakeUniqueNameAW( + LPVOID lpszBuffer, + DWORD dwBuffSize, + LPCVOID lpszShortName, + LPCVOID lpszLongName, + LPCVOID lpszPathName) +{ + if (SHELL_OsIsUnicode()) + return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName); + return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName); +} + +/************************************************************************* + * PathYetAnotherMakeUniqueName [SHELL32.75] + * + * NOTES + * exported by ordinal + */ +BOOL WINAPI PathYetAnotherMakeUniqueName( + LPWSTR lpszBuffer, + LPCWSTR lpszPathName, + LPCWSTR lpszShortName, + LPCWSTR lpszLongName) +{ + FIXME("(%p, %s, %s ,%s):stub.\n", + lpszBuffer, debugstr_w(lpszPathName), debugstr_w(lpszShortName), debugstr_w(lpszLongName)); + return TRUE; +} + + +/* + ########## cleaning and resolving paths ########## + */ + +/************************************************************************* + * PathFindOnPath [SHELL32.145] + */ +BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs) +{ + if (SHELL_OsIsUnicode()) + return PathFindOnPathW(sFile, (LPCWSTR *)sOtherDirs); + return PathFindOnPathA(sFile, (LPCSTR *)sOtherDirs); +} + +/************************************************************************* + * PathCleanupSpec [SHELL32.171] + * + * lpszFile is changed in place. + */ +int WINAPI PathCleanupSpec( LPCWSTR lpszPathW, LPWSTR lpszFileW ) +{ + int i = 0; + DWORD rc = 0; + int length = 0; + + if (SHELL_OsIsUnicode()) + { + LPWSTR p = lpszFileW; + + TRACE("Cleanup %s\n",debugstr_w(lpszFileW)); + + if (lpszPathW) + length = strlenW(lpszPathW); + + while (*p) + { + int gct = PathGetCharTypeW(*p); + if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR) + { + lpszFileW[i]='-'; + rc |= PCS_REPLACEDCHAR; + } + else + lpszFileW[i]=*p; + i++; + p++; + if (length + i == MAX_PATH) + { + rc |= PCS_FATAL | PCS_PATHTOOLONG; + break; + } + } + lpszFileW[i]=0; + } + else + { + LPSTR lpszFileA = (LPSTR)lpszFileW; + LPCSTR lpszPathA = (LPSTR)lpszPathW; + LPSTR p = lpszFileA; + + TRACE("Cleanup %s\n",debugstr_a(lpszFileA)); + + if (lpszPathA) + length = strlen(lpszPathA); + + while (*p) + { + int gct = PathGetCharTypeA(*p); + if (gct == GCT_INVALID || gct == GCT_WILD || gct == GCT_SEPARATOR) + { + lpszFileA[i]='-'; + rc |= PCS_REPLACEDCHAR; + } + else + lpszFileA[i]=*p; + i++; + p++; + if (length + i == MAX_PATH) + { + rc |= PCS_FATAL | PCS_PATHTOOLONG; + break; + } + } + lpszFileA[i]=0; + } + return rc; +} + +/************************************************************************* + * PathQualifyA [SHELL32] + */ +BOOL WINAPI PathQualifyA(LPCSTR pszPath) +{ + FIXME("%s\n",pszPath); + return 0; +} + +/************************************************************************* + * PathQualifyW [SHELL32] + */ +BOOL WINAPI PathQualifyW(LPCWSTR pszPath) +{ + FIXME("%s\n",debugstr_w(pszPath)); + return 0; +} + +/************************************************************************* + * PathQualify [SHELL32.49] + */ +BOOL WINAPI PathQualifyAW(LPCVOID pszPath) +{ + if (SHELL_OsIsUnicode()) + return PathQualifyW(pszPath); + return PathQualifyA(pszPath); +} + +/************************************************************************* + * PathResolveA [SHELL32.51] + */ +BOOL WINAPI PathResolveA( + LPSTR lpszPath, + LPCSTR *alpszPaths, + DWORD dwFlags) +{ + FIXME("(%s,%p,0x%08lx),stub!\n", + lpszPath, *alpszPaths, dwFlags); + return 0; +} + +/************************************************************************* + * PathResolveW [SHELL32] + */ +BOOL WINAPI PathResolveW( + LPWSTR lpszPath, + LPCWSTR *alpszPaths, + DWORD dwFlags) +{ + FIXME("(%s,%p,0x%08lx),stub!\n", + debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags); + return 0; +} + +/************************************************************************* + * PathResolve [SHELL32.51] + */ +BOOL WINAPI PathResolveAW( + LPVOID lpszPath, + LPCVOID *alpszPaths, + DWORD dwFlags) +{ + if (SHELL_OsIsUnicode()) + return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags); + return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags); +} + +/************************************************************************* +* PathProcessCommandA [SHELL32.653] +*/ +HRESULT WINAPI PathProcessCommandA ( + LPCSTR lpszPath, + LPSTR lpszBuff, + DWORD dwBuffSize, + DWORD dwFlags) +{ + FIXME("%s %p 0x%04lx 0x%04lx stub\n", + lpszPath, lpszBuff, dwBuffSize, dwFlags); + strcpy(lpszBuff, lpszPath); + return 0; +} + +/************************************************************************* +* PathProcessCommandW +*/ +HRESULT WINAPI PathProcessCommandW ( + LPCWSTR lpszPath, + LPWSTR lpszBuff, + DWORD dwBuffSize, + DWORD dwFlags) +{ + FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n", + debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags); + strcpyW(lpszBuff, lpszPath); + return 0; +} + +/************************************************************************* +* PathProcessCommand (SHELL32.653) +*/ +HRESULT WINAPI PathProcessCommandAW ( + LPCVOID lpszPath, + LPVOID lpszBuff, + DWORD dwBuffSize, + DWORD dwFlags) +{ + if (SHELL_OsIsUnicode()) + return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags); + return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags); +} + +/* + ########## special ########## +*/ + +/************************************************************************* + * PathSetDlgItemPath (SHELL32.48) + */ +VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath) +{ + if (SHELL_OsIsUnicode()) + PathSetDlgItemPathW(hDlg, id, pszPath); + else + PathSetDlgItemPathA(hDlg, id, pszPath); +} + +static const WCHAR szCurrentVersion[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0'}; +static const WCHAR Administrative_ToolsW[] = {'A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'}; +static const WCHAR AppDataW[] = {'A','p','p','D','a','t','a','\0'}; +static const WCHAR CacheW[] = {'C','a','c','h','e','\0'}; +static const WCHAR CD_BurningW[] = {'C','D',' ','B','u','r','n','i','n','g','\0'}; +static const WCHAR Common_Administrative_ToolsW[] = {'C','o','m','m','o','n',' ','A','d','m','i','n','i','s','t','r','a','t','i','v','e',' ','T','o','o','l','s','\0'}; +static const WCHAR Common_AppDataW[] = {'C','o','m','m','o','n',' ','A','p','p','D','a','t','a','\0'}; +static const WCHAR Common_DesktopW[] = {'C','o','m','m','o','n',' ','D','e','s','k','t','o','p','\0'}; +static const WCHAR Common_DocumentsW[] = {'C','o','m','m','o','n',' ','D','o','c','u','m','e','n','t','s','\0'}; +static const WCHAR CommonFilesDirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r','\0'}; +static const WCHAR CommonMusicW[] = {'C','o','m','m','o','n','M','u','s','i','c','\0'}; +static const WCHAR CommonPicturesW[] = {'C','o','m','m','o','n','P','i','c','t','u','r','e','s','\0'}; +static const WCHAR Common_ProgramsW[] = {'C','o','m','m','o','n',' ','P','r','o','g','r','a','m','s','\0'}; +static const WCHAR Common_StartUpW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t','U','p','\0'}; +static const WCHAR Common_Start_MenuW[] = {'C','o','m','m','o','n',' ','S','t','a','r','t',' ','M','e','n','u','\0'}; +static const WCHAR Common_TemplatesW[] = {'C','o','m','m','o','n',' ','T','e','m','p','l','a','t','e','s','\0'}; +static const WCHAR CommonVideoW[] = {'C','o','m','m','o','n','V','i','d','e','o','\0'}; +static const WCHAR CookiesW[] = {'C','o','o','k','i','e','s','\0'}; +static const WCHAR DesktopW[] = {'D','e','s','k','t','o','p','\0'}; +static const WCHAR FavoritesW[] = {'F','a','v','o','r','i','t','e','s','\0'}; +static const WCHAR FontsW[] = {'F','o','n','t','s','\0'}; +static const WCHAR HistoryW[] = {'H','i','s','t','o','r','y','\0'}; +static const WCHAR Local_AppDataW[] = {'L','o','c','a','l',' ','A','p','p','D','a','t','a','\0'}; +static const WCHAR My_MusicW[] = {'M','y',' ','M','u','s','i','c','\0'}; +static const WCHAR My_PicturesW[] = {'M','y',' ','P','i','c','t','u','r','e','s','\0'}; +static const WCHAR My_VideoW[] = {'M','y',' ','V','i','d','e','o','\0'}; +static const WCHAR NetHoodW[] = {'N','e','t','H','o','o','d','\0'}; +static const WCHAR PersonalW[] = {'P','e','r','s','o','n','a','l','\0'}; +static const WCHAR PrintHoodW[] = {'P','r','i','n','t','H','o','o','d','\0'}; +static const WCHAR ProgramFilesDirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r','\0'}; +static const WCHAR ProgramsW[] = {'P','r','o','g','r','a','m','s','\0'}; +static const WCHAR RecentW[] = {'R','e','c','e','n','t','\0'}; +static const WCHAR ResourcesW[] = {'R','e','s','o','u','r','c','e','s','\0'}; +static const WCHAR SendToW[] = {'S','e','n','d','T','o','\0'}; +static const WCHAR StartUpW[] = {'S','t','a','r','t','U','p','\0'}; +static const WCHAR Start_MenuW[] = {'S','t','a','r','t',' ','M','e','n','u','\0'}; +static const WCHAR TemplatesW[] = {'T','e','m','p','l','a','t','e','s','\0'}; +static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t','\0'}; +static const WCHAR AllUsersProfileW[] = {'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%','\0'}; +static const WCHAR UserProfileW[] = {'%','U','S','E','R','P','R','O','F','I','L','E','%','\0'}; +static const WCHAR SystemDriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%','\0'}; +static const WCHAR ProfileListW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','r','o','f','i','l','e','L','i','s','t',0}; +static const WCHAR ProfilesDirectoryW[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0}; +static const WCHAR AllUsersProfileValueW[] = {'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e','\0'}; +static const WCHAR szSHFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'}; +static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r',' ','S','h','e','l','l',' ','F','o','l','d','e','r','s','\0'}; +/* This defaults to L"Documents and Settings" on Windows 2000/XP, but we're + * acting more Windows 9x-like for now. + */ +static const WCHAR szDefaultProfileDirW[] = {'w','i','n','d','o','w','s','\\','p','r','o','f','i','l','e','s','\0'}; +static const WCHAR AllUsersW[] = {'A','l','l',' ','U','s','e','r','s','\0'}; + +typedef enum _CSIDL_Type { + CSIDL_Type_User, + CSIDL_Type_AllUsers, + CSIDL_Type_CurrVer, + CSIDL_Type_Disallowed, + CSIDL_Type_NonExistent, + CSIDL_Type_WindowsPath, + CSIDL_Type_SystemPath, +} CSIDL_Type; + +typedef struct +{ + CSIDL_Type type; + LPCWSTR szValueName; + LPCWSTR szDefaultPath; /* fallback string or resource ID */ +} CSIDL_DATA; + +static const CSIDL_DATA CSIDL_Data[] = +{ + { /* 0x00 - CSIDL_DESKTOP */ + CSIDL_Type_User, + DesktopW, + MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY) + }, + { /* 0x01 - CSIDL_INTERNET */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x02 - CSIDL_PROGRAMS */ + CSIDL_Type_User, + ProgramsW, + MAKEINTRESOURCEW(IDS_PROGRAMS) + }, + { /* 0x03 - CSIDL_CONTROLS (.CPL files) */ + CSIDL_Type_SystemPath, + NULL, + NULL + }, + { /* 0x04 - CSIDL_PRINTERS */ + CSIDL_Type_SystemPath, + NULL, + NULL + }, + { /* 0x05 - CSIDL_PERSONAL */ + CSIDL_Type_User, + PersonalW, + MAKEINTRESOURCEW(IDS_PERSONAL) + }, + { /* 0x06 - CSIDL_FAVORITES */ + CSIDL_Type_User, + FavoritesW, + MAKEINTRESOURCEW(IDS_FAVORITES) + }, + { /* 0x07 - CSIDL_STARTUP */ + CSIDL_Type_User, + StartUpW, + MAKEINTRESOURCEW(IDS_STARTUP) + }, + { /* 0x08 - CSIDL_RECENT */ + CSIDL_Type_User, + RecentW, + MAKEINTRESOURCEW(IDS_RECENT) + }, + { /* 0x09 - CSIDL_SENDTO */ + CSIDL_Type_User, + SendToW, + MAKEINTRESOURCEW(IDS_SENDTO) + }, + { /* 0x0a - CSIDL_BITBUCKET - Recycle Bin */ + CSIDL_Type_Disallowed, + NULL, + NULL, + }, + { /* 0x0b - CSIDL_STARTMENU */ + CSIDL_Type_User, + Start_MenuW, + MAKEINTRESOURCEW(IDS_STARTMENU) + }, + { /* 0x0c - CSIDL_MYDOCUMENTS */ + CSIDL_Type_Disallowed, /* matches WinXP--can't get its path */ + NULL, + NULL + }, + { /* 0x0d - CSIDL_MYMUSIC */ + CSIDL_Type_User, + My_MusicW, + MAKEINTRESOURCEW(IDS_MYMUSIC) + }, + { /* 0x0e - CSIDL_MYVIDEO */ + CSIDL_Type_User, + My_VideoW, + MAKEINTRESOURCEW(IDS_MYVIDEO) + }, + { /* 0x0f - unassigned */ + CSIDL_Type_Disallowed, + NULL, + NULL, + }, + { /* 0x10 - CSIDL_DESKTOPDIRECTORY */ + CSIDL_Type_User, + DesktopW, + MAKEINTRESOURCEW(IDS_DESKTOPDIRECTORY) + }, + { /* 0x11 - CSIDL_DRIVES */ + CSIDL_Type_Disallowed, + NULL, + NULL, + }, + { /* 0x12 - CSIDL_NETWORK */ + CSIDL_Type_Disallowed, + NULL, + NULL, + }, + { /* 0x13 - CSIDL_NETHOOD */ + CSIDL_Type_User, + NetHoodW, + MAKEINTRESOURCEW(IDS_NETHOOD) + }, + { /* 0x14 - CSIDL_FONTS */ + CSIDL_Type_WindowsPath, + NULL, + FontsW + }, + { /* 0x15 - CSIDL_TEMPLATES */ + CSIDL_Type_User, + TemplatesW, + MAKEINTRESOURCEW(IDS_TEMPLATES) + }, + { /* 0x16 - CSIDL_COMMON_STARTMENU */ + CSIDL_Type_AllUsers, + Common_Start_MenuW, + MAKEINTRESOURCEW(IDS_STARTMENU) + }, + { /* 0x17 - CSIDL_COMMON_PROGRAMS */ + CSIDL_Type_AllUsers, + Common_ProgramsW, + MAKEINTRESOURCEW(IDS_PROGRAMS) + }, + { /* 0x18 - CSIDL_COMMON_STARTUP */ + CSIDL_Type_AllUsers, + Common_StartUpW, + MAKEINTRESOURCEW(IDS_STARTUP) + }, + { /* 0x19 - CSIDL_COMMON_DESKTOPDIRECTORY */ + CSIDL_Type_AllUsers, + Common_DesktopW, + MAKEINTRESOURCEW(IDS_DESKTOP) + }, + { /* 0x1a - CSIDL_APPDATA */ + CSIDL_Type_User, + AppDataW, + MAKEINTRESOURCEW(IDS_APPDATA) + }, + { /* 0x1b - CSIDL_PRINTHOOD */ + CSIDL_Type_User, + PrintHoodW, + MAKEINTRESOURCEW(IDS_PRINTHOOD) + }, + { /* 0x1c - CSIDL_LOCAL_APPDATA */ + CSIDL_Type_User, + Local_AppDataW, + MAKEINTRESOURCEW(IDS_LOCAL_APPDATA) + }, + { /* 0x1d - CSIDL_ALTSTARTUP */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x1e - CSIDL_COMMON_ALTSTARTUP */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x1f - CSIDL_COMMON_FAVORITES */ + CSIDL_Type_AllUsers, + FavoritesW, + MAKEINTRESOURCEW(IDS_FAVORITES) + }, + { /* 0x20 - CSIDL_INTERNET_CACHE */ + CSIDL_Type_User, + CacheW, + MAKEINTRESOURCEW(IDS_INTERNET_CACHE) + }, + { /* 0x21 - CSIDL_COOKIES */ + CSIDL_Type_User, + CookiesW, + MAKEINTRESOURCEW(IDS_COOKIES) + }, + { /* 0x22 - CSIDL_HISTORY */ + CSIDL_Type_User, + HistoryW, + MAKEINTRESOURCEW(IDS_HISTORY) + }, + { /* 0x23 - CSIDL_COMMON_APPDATA */ + CSIDL_Type_AllUsers, + Common_AppDataW, + MAKEINTRESOURCEW(IDS_APPDATA) + }, + { /* 0x24 - CSIDL_WINDOWS */ + CSIDL_Type_WindowsPath, + NULL, + NULL + }, + { /* 0x25 - CSIDL_SYSTEM */ + CSIDL_Type_SystemPath, + NULL, + NULL + }, + { /* 0x26 - CSIDL_PROGRAM_FILES */ + CSIDL_Type_CurrVer, + ProgramFilesDirW, + MAKEINTRESOURCEW(IDS_PROGRAM_FILES) + }, + { /* 0x27 - CSIDL_MYPICTURES */ + CSIDL_Type_User, + My_PicturesW, + MAKEINTRESOURCEW(IDS_MYPICTURES) + }, + { /* 0x28 - CSIDL_PROFILE */ + CSIDL_Type_User, + NULL, + NULL + }, + { /* 0x29 - CSIDL_SYSTEMX86 */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x2a - CSIDL_PROGRAM_FILESX86 */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x2b - CSIDL_PROGRAM_FILES_COMMON */ + CSIDL_Type_CurrVer, + CommonFilesDirW, + MAKEINTRESOURCEW(IDS_PROGRAM_FILES_COMMON) + }, + { /* 0x2c - CSIDL_PROGRAM_FILES_COMMONX86 */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x2d - CSIDL_COMMON_TEMPLATES */ + CSIDL_Type_AllUsers, + Common_TemplatesW, + MAKEINTRESOURCEW(IDS_TEMPLATES) + }, + { /* 0x2e - CSIDL_COMMON_DOCUMENTS */ + CSIDL_Type_AllUsers, + Common_DocumentsW, + MAKEINTRESOURCEW(IDS_COMMON_DOCUMENTS) + }, + { /* 0x2f - CSIDL_COMMON_ADMINTOOLS */ + CSIDL_Type_AllUsers, + Common_Administrative_ToolsW, + MAKEINTRESOURCEW(IDS_ADMINTOOLS) + }, + { /* 0x30 - CSIDL_ADMINTOOLS */ + CSIDL_Type_User, + Administrative_ToolsW, + MAKEINTRESOURCEW(IDS_ADMINTOOLS) + }, + { /* 0x31 - CSIDL_CONNECTIONS */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x32 - unassigned */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x33 - unassigned */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x34 - unassigned */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x35 - CSIDL_COMMON_MUSIC */ + CSIDL_Type_AllUsers, + CommonMusicW, + MAKEINTRESOURCEW(IDS_COMMON_MUSIC) + }, + { /* 0x36 - CSIDL_COMMON_PICTURES */ + CSIDL_Type_AllUsers, + CommonPicturesW, + MAKEINTRESOURCEW(IDS_COMMON_PICTURES) + }, + { /* 0x37 - CSIDL_COMMON_VIDEO */ + CSIDL_Type_AllUsers, + CommonVideoW, + MAKEINTRESOURCEW(IDS_COMMON_VIDEO) + }, + { /* 0x38 - CSIDL_RESOURCES */ + CSIDL_Type_WindowsPath, + NULL, + ResourcesW + }, + { /* 0x39 - CSIDL_RESOURCES_LOCALIZED */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x3a - CSIDL_COMMON_OEM_LINKS */ + CSIDL_Type_NonExistent, + NULL, + NULL + }, + { /* 0x3b - CSIDL_CDBURN_AREA */ + CSIDL_Type_User, + CD_BurningW, + MAKEINTRESOURCEW(IDS_CDBURN_AREA) + }, + { /* 0x3c unassigned */ + CSIDL_Type_Disallowed, + NULL, + NULL + }, + { /* 0x3d - CSIDL_COMPUTERSNEARME */ + CSIDL_Type_Disallowed, /* FIXME */ + NULL, + NULL + }, + { /* 0x3e - CSIDL_PROFILES */ + CSIDL_Type_Disallowed, /* oddly, this matches WinXP */ + NULL, + NULL + } +}; + +static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest); + +/* Gets the value named value from the registry key + * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders + * (or from rootKey\userPrefix\... if userPrefix is not NULL) into path, which + * is assumed to be MAX_PATH WCHARs in length. + * If it exists, expands the value and writes the expanded value to + * rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders + * Returns successful error code if the value was retrieved from the registry, + * and a failure otherwise. + */ +static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix, + LPCWSTR value, LPWSTR path) +{ + HRESULT hr; + WCHAR shellFolderPath[MAX_PATH], userShellFolderPath[MAX_PATH]; + LPCWSTR pShellFolderPath, pUserShellFolderPath; + DWORD dwDisp, dwType, dwPathLen = MAX_PATH; + HKEY userShellFolderKey, shellFolderKey; + + TRACE("%p,%s,%s,%p\n",rootKey, debugstr_w(userPrefix), debugstr_w(value), + path); + + if (userPrefix) + { + strcpyW(shellFolderPath, userPrefix); + PathAddBackslashW(shellFolderPath); + strcatW(shellFolderPath, szSHFolders); + pShellFolderPath = shellFolderPath; + strcpyW(userShellFolderPath, userPrefix); + PathAddBackslashW(userShellFolderPath); + strcatW(userShellFolderPath, szSHUserFolders); + pUserShellFolderPath = userShellFolderPath; + } + else + { + pUserShellFolderPath = szSHUserFolders; + pShellFolderPath = szSHFolders; + } + + if (RegCreateKeyExW(rootKey, pShellFolderPath, 0, NULL, 0, KEY_ALL_ACCESS, + NULL, &shellFolderKey, &dwDisp)) + { + TRACE("Failed to create %s\n", debugstr_w(pShellFolderPath)); + return E_FAIL; + } + if (RegCreateKeyExW(rootKey, pUserShellFolderPath, 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &userShellFolderKey, &dwDisp)) + { + TRACE("Failed to create %s\n", + debugstr_w(pUserShellFolderPath)); + RegCloseKey(shellFolderKey); + return E_FAIL; + } + + if (!RegQueryValueExW(userShellFolderKey, value, NULL, &dwType, + (LPBYTE)path, &dwPathLen) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ)) + { + path[dwPathLen / sizeof(WCHAR)] = '\0'; + if (dwType == REG_EXPAND_SZ && path[0] == '%') + { + WCHAR szTemp[MAX_PATH]; + + _SHExpandEnvironmentStrings(path, szTemp); + strncpyW(path, szTemp, MAX_PATH); + } + RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path, + (strlenW(path) + 1) * sizeof(WCHAR)); + hr = S_OK; + } + else + hr = E_FAIL; + RegCloseKey(shellFolderKey); + RegCloseKey(userShellFolderKey); + TRACE("returning 0x%08lx\n", hr); + return hr; +} + +/* Gets a 'semi-expanded' default value of the CSIDL with index folder into + * pszPath, based on the entries in CSIDL_Data. By semi-expanded, I mean: + * - The entry's szDefaultPath may be either a string value or an integer + * resource identifier. In the latter case, the string value of the resource + * is written. + * - Depending on the entry's type, the path may begin with an (unexpanded) + * environment variable name. The caller is responsible for expanding + * environment strings if so desired. + * The types that are prepended with environment variables are: + * CSIDL_Type_User: %USERPROFILE% + * CSIDL_Type_AllUsers: %ALLUSERSPROFILE% + * CSIDL_Type_CurrVer: %SystemDrive% + * (Others might make sense too, but as yet are unneeded.) + * FIXME: there are two special cases for the default value: + * - the "My Documents" (CSIDL_PERSONAL) entry should be $HOME + * - the CSIDL_DESKTOP and CSIDL_DESKTOPDIRECTORY (which have the same path) + * should be $HOME/Desktop if it exists + * But, $HOME doesn't seem to be inherited into the Wine environment. I could + * use getenv, but this returns me a UNIX path, which may or may not be + * reachable from any currently mounted DOS drives. + */ +static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath) +{ + HRESULT hr; + WCHAR resourcePath[MAX_PATH]; + LPCWSTR pDefaultPath = NULL; + + TRACE("0x%02x,%p\n", folder, pszPath); + + if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) + return E_INVALIDARG; + if (!pszPath) + return E_INVALIDARG; + + if (CSIDL_Data[folder].szDefaultPath && + IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath)) + { + if (LoadStringW(shell32_hInstance, + (UINT)CSIDL_Data[folder].szDefaultPath, resourcePath, MAX_PATH)) + { + hr = S_OK; + pDefaultPath = resourcePath; + } + else + { + FIXME("LoadString failed, missing translation?\n"); + hr = E_FAIL; + } + } + else + { + hr = S_OK; + pDefaultPath = CSIDL_Data[folder].szDefaultPath; + } + if (SUCCEEDED(hr)) + { + switch (CSIDL_Data[folder].type) + { + case CSIDL_Type_User: + strcpyW(pszPath, UserProfileW); + break; + case CSIDL_Type_AllUsers: + strcpyW(pszPath, AllUsersProfileW); + break; + case CSIDL_Type_CurrVer: + strcpyW(pszPath, SystemDriveW); + break; + default: + ; /* no corresponding env. var, do nothing */ + } + if (pDefaultPath) + { + PathAddBackslashW(pszPath); + strcatW(pszPath, pDefaultPath); + } + } + TRACE("returning 0x%08lx\n", hr); + return hr; +} + +/* Gets the (unexpanded) value of the folder with index folder into pszPath. + * The folder's type is assumed to be CSIDL_Type_CurrVer. Its default value + * can be overridden in the HKLM\\szCurrentVersion key. + * If dwFlags has SHGFP_TYPE_DEFAULT set or if the value isn't overridden in + * the registry, uses _SHGetDefaultValue to get the value. + */ +static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder, + LPWSTR pszPath) +{ + HRESULT hr; + + TRACE("0x%08lx,0x%02x,%p\n", dwFlags, folder, pszPath); + + if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) + return E_INVALIDARG; + if (CSIDL_Data[folder].type != CSIDL_Type_CurrVer) + return E_INVALIDARG; + if (!pszPath) + return E_INVALIDARG; + + if (dwFlags & SHGFP_TYPE_DEFAULT) + hr = _SHGetDefaultValue(folder, pszPath); + else + { + HKEY hKey; + DWORD dwDisp; + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szCurrentVersion, 0, + NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp)) + hr = E_FAIL; + else + { + DWORD dwType, dwPathLen = MAX_PATH * sizeof(WCHAR); + + if (RegQueryValueExW(hKey, CSIDL_Data[folder].szValueName, NULL, + &dwType, (LPBYTE)pszPath, &dwPathLen) || + (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) + { + hr = _SHGetDefaultValue(folder, pszPath); + dwType = REG_EXPAND_SZ; + RegSetValueExW(hKey, CSIDL_Data[folder].szValueName, 0, dwType, + (LPBYTE)pszPath, (strlenW(pszPath)+1)*sizeof(WCHAR)); + } + else + { + pszPath[dwPathLen / sizeof(WCHAR)] = '\0'; + hr = S_OK; + } + RegCloseKey(hKey); + } + } + TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); + return hr; +} + +/* Gets the user's path (unexpanded) for the CSIDL with index folder: + * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it. Otherwise + * calls _SHGetUserShellFolderPath for it. Where it looks depends on hToken: + * - if hToken is -1, looks in HKEY_USERS\.Default + * - otherwise looks first in HKEY_CURRENT_USER, followed by HKEY_LOCAL_MACHINE + * if HKEY_CURRENT_USER doesn't contain any entries. If both fail, finally + * calls _SHGetDefaultValue for it. + */ +static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder, + LPWSTR pszPath) +{ + HRESULT hr; + + TRACE("%p,0x%08lx,0x%02x,%p\n", hToken, dwFlags, folder, pszPath); + + if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) + return E_INVALIDARG; + if (CSIDL_Data[folder].type != CSIDL_Type_User) + return E_INVALIDARG; + if (!pszPath) + return E_INVALIDARG; + + /* Only the current user and the default user are supported right now + * I'm afraid. + * FIXME: should be able to call GetTokenInformation on the token, + * then call ConvertSidToStringSidW on it to get the user prefix. + * But Wine's registry doesn't store user info by sid, it stores it + * by user name (and I don't know how to convert from a token to a + * user name). + */ + if (hToken != NULL && hToken != (HANDLE)-1) + { + FIXME("unsupported for user other than current or default\n"); + return E_FAIL; + } + + if (dwFlags & SHGFP_TYPE_DEFAULT) + hr = _SHGetDefaultValue(folder, pszPath); + else + { + LPCWSTR userPrefix = NULL; + HKEY hRootKey; + + if (hToken == (HANDLE)-1) + { + hRootKey = HKEY_USERS; + userPrefix = DefaultW; + } + else /* hToken == NULL, other values disallowed above */ + hRootKey = HKEY_CURRENT_USER; + hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, + CSIDL_Data[folder].szValueName, pszPath); + if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE) + hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, + CSIDL_Data[folder].szValueName, pszPath); + if (FAILED(hr)) + hr = _SHGetDefaultValue(folder, pszPath); + } + TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); + return hr; +} + +/* Gets the (unexpanded) path for the CSIDL with index folder. If dwFlags has + * SHGFP_TYPE_DEFAULT set, calls _SHGetDefaultValue. Otherwise calls + * _SHGetUserShellFolderPath for it, looking only in HKEY_LOCAL_MACHINE. + * If this fails, falls back to _SHGetDefaultValue. + */ +static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder, + LPWSTR pszPath) +{ + HRESULT hr; + + TRACE("0x%08lx,0x%02x,%p\n", dwFlags, folder, pszPath); + + if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) + return E_INVALIDARG; + if (CSIDL_Data[folder].type != CSIDL_Type_AllUsers) + return E_INVALIDARG; + if (!pszPath) + return E_INVALIDARG; + + if (dwFlags & SHGFP_TYPE_DEFAULT) + hr = _SHGetDefaultValue(folder, pszPath); + else + { + hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, + CSIDL_Data[folder].szValueName, pszPath); + if (FAILED(hr)) + hr = _SHGetDefaultValue(folder, pszPath); + } + TRACE("returning 0x%08lx (output path is %s)\n", hr, debugstr_w(pszPath)); + return hr; +} + +static HRESULT _SHOpenProfilesKey(PHKEY pKey) +{ + LONG lRet; + DWORD disp; + + lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, NULL, 0, + KEY_ALL_ACCESS, NULL, pKey, &disp); + return HRESULT_FROM_WIN32(lRet); +} + +/* Reads the value named szValueName from the key profilesKey (assumed to be + * opened by _SHOpenProfilesKey) into szValue, which is assumed to be MAX_PATH + * WCHARs in length. If it doesn't exist, returns szDefault (and saves + * szDefault to the registry). + */ +static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName, + LPWSTR szValue, LPCWSTR szDefault) +{ + HRESULT hr; + DWORD type, dwPathLen = MAX_PATH * sizeof(WCHAR); + LONG lRet; + + TRACE("%p,%s,%p,%s\n", profilesKey, debugstr_w(szValueName), szValue, + debugstr_w(szDefault)); + lRet = RegQueryValueExW(profilesKey, szValueName, NULL, &type, + (LPBYTE)szValue, &dwPathLen); + if (!lRet && (type == REG_SZ || type == REG_EXPAND_SZ) && dwPathLen + && *szValue) + { + dwPathLen /= sizeof(WCHAR); + szValue[dwPathLen] = '\0'; + hr = S_OK; + } + else + { + /* Missing or invalid value, set a default */ + strncpyW(szValue, szDefault, MAX_PATH); + szValue[MAX_PATH - 1] = '\0'; + TRACE("Setting missing value %s to %s\n", debugstr_w(szValueName), + debugstr_w(szValue)); + lRet = RegSetValueExW(profilesKey, szValueName, 0, REG_EXPAND_SZ, + (LPBYTE)szValue, (strlenW(szValue) + 1) * sizeof(WCHAR)); + if (lRet) + hr = HRESULT_FROM_WIN32(lRet); + else + hr = S_OK; + } + TRACE("returning 0x%08lx (output value is %s)\n", hr, debugstr_w(szValue)); + return hr; +} + +/* From the original Wine source: + * + * Attempts to expand environment variables from szSrc into szDest, which is + * assumed to be MAX_PATH characters in length. Before referring to the + * environment, handles a few variables directly, because the environment + * variables may not be set when this is called (as during Wine's installation + * when default values are being written to the registry). + * The directly handled environment variables, and their source, are: + * - ALLUSERSPROFILE, USERPROFILE: reads from the registry + * - SystemDrive: uses GetSystemDirectoryW and uses the drive portion of its + * path + * If one of the directly handled environment variables is expanded, only + * expands a single variable, and only in the beginning of szSrc. + * + * That's fine for Wine, but it breaks in ReactOS where we have profile paths + * like "c:\documents and settings\Administrator.REACTOS". Anyway, we have the + * environment variables handy so we'll just use them instead of hacking around + */ +static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest) +{ + HRESULT hr; + WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 }; + + TRACE("%s, %p\n", debugstr_w(szSrc), szDest); + + if (!szSrc || !szDest) return E_INVALIDARG; + + /* short-circuit if there's nothing to expand */ + if (szSrc[0] != '%') + { + strcpyW(szDest, szSrc); + hr = S_OK; + goto end; + } + + *szDest = 0; + strcpyW(szTemp, szSrc); + while (SUCCEEDED(hr) && szTemp[0] == '%') + { + DWORD ret = ExpandEnvironmentStringsW(szSrc, szDest, MAX_PATH); + + if (ret > MAX_PATH) + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + else if (ret == 0) + hr = HRESULT_FROM_WIN32(GetLastError()); + else + hr = S_OK; + if (SUCCEEDED(hr) && szDest[0] == '%') + strcpyW(szTemp, szDest); + else + { + /* terminate loop */ + szTemp[0] = '\0'; + } + } +end: + TRACE("returning 0x%08lx (input was %s, output is %s)\n", hr, + debugstr_w(szSrc), debugstr_w(szDest)); + return hr; +} + +/************************************************************************* + * SHGetFolderPathW [SHELL32.@] + * + * NOTES + * Converts nFolder to path. Most values can be overridden in either + * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders + * or in the same location in HKLM. + * The registry usage is explained by the following tech note: + * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36173.asp + * The "Shell Folders" registry key was used in NT4 and earlier systems. + * Beginning with Windows 2000, the "User Shell Folders" key is used, so + * changes made to it are made to the former key too. This synchronization is + * done on-demand: not until someone requests the value of one of these paths + * (by calling one of the SHGet functions) is the value synchronized. + * Furthermore, as explained here: + * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36276.asp + * the HKCU paths take precedence over the HKLM paths. + * + **********************************************************************/ +HRESULT WINAPI SHGetFolderPathW( + HWND hwndOwner, + int nFolder, + HANDLE hToken, + DWORD dwFlags, + LPWSTR pszPath) +{ + HRESULT hr; + WCHAR szBuildPath[MAX_PATH], szTemp[MAX_PATH]; + DWORD folder = nFolder & CSIDL_FOLDER_MASK; + CSIDL_Type type; + int ret; + + TRACE("%p,%p,nFolder=0x%04x\n", hwndOwner,pszPath,nFolder); + + /* Windows always NULL-terminates the resulting path regardless of success + * or failure, so do so first + */ + if (pszPath) + *pszPath = '\0'; + if (folder >= sizeof(CSIDL_Data) / sizeof(CSIDL_Data[0])) + return E_INVALIDARG; + szTemp[0] = 0; + type = CSIDL_Data[folder].type; + switch (type) + { + case CSIDL_Type_Disallowed: + hr = E_INVALIDARG; + break; + case CSIDL_Type_NonExistent: + hr = S_FALSE; + break; + case CSIDL_Type_WindowsPath: + GetWindowsDirectoryW(szTemp, MAX_PATH); + if (CSIDL_Data[folder].szDefaultPath && + !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) && + *CSIDL_Data[folder].szDefaultPath) + { + PathAddBackslashW(szTemp); + strcatW(szTemp, CSIDL_Data[folder].szDefaultPath); + } + hr = S_OK; + break; + case CSIDL_Type_SystemPath: + GetSystemDirectoryW(szTemp, MAX_PATH); + if (CSIDL_Data[folder].szDefaultPath && + !IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath) && + *CSIDL_Data[folder].szDefaultPath) + { + PathAddBackslashW(szTemp); + strcatW(szTemp, CSIDL_Data[folder].szDefaultPath); + } + hr = S_OK; + break; + case CSIDL_Type_CurrVer: + hr = _SHGetCurrentVersionPath(dwFlags, folder, szTemp); + break; + case CSIDL_Type_User: + hr = _SHGetUserProfilePath(hToken, dwFlags, folder, szTemp); + break; + case CSIDL_Type_AllUsers: + hr = _SHGetAllUsersProfilePath(dwFlags, folder, szTemp); + break; + default: + FIXME("bogus type %d, please fix\n", type); + hr = E_INVALIDARG; + break; + } + + /* Expand environment strings if necessary */ + if (*szTemp == '%') + hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath); + else + strcpyW(szBuildPath, szTemp); + /* Copy the path if it's available before we might return */ + if (SUCCEEDED(hr) && pszPath) + strcpyW(pszPath, szBuildPath); + + if (FAILED(hr)) goto end; + + /* if we don't care about existing directories we are ready */ + if(nFolder & CSIDL_FLAG_DONT_VERIFY) goto end; + + if (PathFileExistsW(szBuildPath)) goto end; + + /* not existing but we are not allowed to create it. The return value + * is verified against shell32 version 6.0. + */ + if (!(nFolder & CSIDL_FLAG_CREATE)) + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + goto end; + } + + /* create directory/directories */ + ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL); + if (ret && ret != ERROR_ALREADY_EXISTS) + { + ERR("Failed to create directory '%s'.\n", debugstr_w(szBuildPath)); + hr = E_FAIL; + goto end; + } + + TRACE("Created missing system directory '%s'\n", debugstr_w(szBuildPath)); +end: + TRACE("returning 0x%08lx (final path is %s)\n", hr, debugstr_w(szBuildPath)); + return hr; +} + +/************************************************************************* + * SHGetFolderPathA [SHELL32.@] + */ +HRESULT WINAPI SHGetFolderPathA( + HWND hwndOwner, + int nFolder, + HANDLE hToken, + DWORD dwFlags, + LPSTR pszPath) +{ + WCHAR szTemp[MAX_PATH]; + HRESULT hr; + + TRACE("%p,%p,nFolder=0x%04x\n",hwndOwner,pszPath,nFolder); + + if (pszPath) + *pszPath = '\0'; + hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, szTemp); + if (SUCCEEDED(hr) && pszPath) + WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL, + NULL); + + return hr; +} + +/* For each folder in folders, if its value has not been set in the registry, + * call _SHGetUserProfilePath or _SHGetAllUsersProfilePath (depending on the + * folder's type) to get the unexpanded value first. + * This will create the expanded value in the Shell Folders key, and + * return the unexpanded value. + * Write the unexpanded value to User Shell Folders, and query it with + * SHGetFolderPath to force the creation of the directory if it doesn't + * already exist. + */ +static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken, + LPCWSTR szUserShellFolderPath, const UINT folders[], UINT foldersLen) +{ + UINT i; + WCHAR path[MAX_PATH]; + HRESULT hr = S_OK; + HKEY hKey = NULL; + DWORD dwDisp, dwType, dwPathLen; + LONG ret; + + TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken, + debugstr_w(szUserShellFolderPath), folders, foldersLen); + + ret = RegCreateKeyExW(hRootKey, szUserShellFolderPath, 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &hKey, &dwDisp); + if (ret) + hr = HRESULT_FROM_WIN32(ret); + for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++) + { + dwPathLen = MAX_PATH * sizeof(WCHAR); + if (RegQueryValueExW(hKey, CSIDL_Data[folders[i]].szValueName, NULL, + &dwType, (LPBYTE)path, &dwPathLen) || (dwType != REG_SZ && + dwType != REG_EXPAND_SZ)) + { + *path = '\0'; + if (CSIDL_Data[folders[i]].type == CSIDL_Type_User) + _SHGetUserProfilePath(hToken, SHGFP_TYPE_DEFAULT, folders[i], + path); + else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers) + _SHGetAllUsersProfilePath(SHGFP_TYPE_DEFAULT, folders[i], path); + else + hr = E_FAIL; + if (*path) + { + ret = RegSetValueExW(hKey, CSIDL_Data[folders[i]].szValueName, + 0, REG_EXPAND_SZ, (LPBYTE)path, + (strlenW(path) + 1) * sizeof(WCHAR)); + if (ret) + hr = HRESULT_FROM_WIN32(ret); + else + hr = SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE, + hToken, SHGFP_TYPE_DEFAULT, NULL); + } + } + } + if (hKey) + RegCloseKey(hKey); + + TRACE("returning 0x%08lx\n", hr); + return hr; +} + +static HRESULT _SHRegisterUserShellFolders(BOOL bDefault) +{ + static const UINT folders[] = { + CSIDL_PROGRAMS, + CSIDL_PERSONAL, + CSIDL_FAVORITES, + CSIDL_STARTUP, + CSIDL_RECENT, + CSIDL_SENDTO, + CSIDL_STARTMENU, + CSIDL_DESKTOPDIRECTORY, + CSIDL_NETHOOD, + CSIDL_TEMPLATES, + CSIDL_PRINTHOOD, + CSIDL_COOKIES, + CSIDL_HISTORY, + }; + WCHAR userShellFolderPath[MAX_PATH]; + LPCWSTR pUserShellFolderPath; + HRESULT hr = S_OK; + HKEY hRootKey; + HANDLE hToken; + + TRACE("%s\n", bDefault ? "TRUE" : "FALSE"); + if (bDefault) + { + hToken = (HANDLE)-1; + hRootKey = HKEY_USERS; + strcpyW(userShellFolderPath, DefaultW); + PathAddBackslashW(userShellFolderPath); + strcatW(userShellFolderPath, szSHUserFolders); + pUserShellFolderPath = userShellFolderPath; + } + else + { + hToken = NULL; + hRootKey = HKEY_CURRENT_USER; + pUserShellFolderPath = szSHUserFolders; + } + + hr = _SHRegisterFolders(hRootKey, hToken, pUserShellFolderPath, + folders, sizeof(folders) / sizeof(folders[0])); + TRACE("returning 0x%08lx\n", hr); + return hr; +} + +static HRESULT _SHRegisterCommonShellFolders(void) +{ + static const UINT folders[] = { + CSIDL_COMMON_STARTMENU, + CSIDL_COMMON_PROGRAMS, + CSIDL_COMMON_STARTUP, + CSIDL_COMMON_DESKTOPDIRECTORY, + CSIDL_COMMON_FAVORITES, + CSIDL_COMMON_APPDATA, + CSIDL_COMMON_TEMPLATES, + CSIDL_COMMON_DOCUMENTS, + }; + HRESULT hr; + + TRACE("\n"); + hr = _SHRegisterFolders(HKEY_LOCAL_MACHINE, NULL, szSHUserFolders, + folders, sizeof(folders) / sizeof(folders[0])); + TRACE("returning 0x%08lx\n", hr); + return hr; +} + +/* Register the default values in the registry, as some apps seem to depend + * on their presence. The set registered was taken from Windows XP. + */ +HRESULT SHELL_RegisterShellFolders(void) +{ + HRESULT hr = _SHRegisterUserShellFolders(TRUE); + + if (SUCCEEDED(hr)) + hr = _SHRegisterUserShellFolders(FALSE); + if (SUCCEEDED(hr)) + hr = _SHRegisterCommonShellFolders(); + return hr; +} + +/************************************************************************* + * SHGetSpecialFolderPathA [SHELL32.@] + */ +BOOL WINAPI SHGetSpecialFolderPathA ( + HWND hwndOwner, + LPSTR szPath, + int nFolder, + BOOL bCreate) +{ + return (SHGetFolderPathA( + hwndOwner, + nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), + NULL, + 0, + szPath)) == S_OK ? TRUE : FALSE; +} + +/************************************************************************* + * SHGetSpecialFolderPathW + */ +BOOL WINAPI SHGetSpecialFolderPathW ( + HWND hwndOwner, + LPWSTR szPath, + int nFolder, + BOOL bCreate) +{ + return (SHGetFolderPathW( + hwndOwner, + nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0), + NULL, + 0, + szPath)) == S_OK ? TRUE : FALSE; +} + +/************************************************************************* + * SHGetSpecialFolderPath (SHELL32.175) + */ +BOOL WINAPI SHGetSpecialFolderPathAW ( + HWND hwndOwner, + LPVOID szPath, + int nFolder, + BOOL bCreate) + +{ + if (SHELL_OsIsUnicode()) + return SHGetSpecialFolderPathW (hwndOwner, szPath, nFolder, bCreate); + return SHGetSpecialFolderPathA (hwndOwner, szPath, nFolder, bCreate); +} + +/************************************************************************* + * SHGetFolderLocation [SHELL32.@] + * + * NOTES + * Gets the folder locations from the registry and creates a pidl. + * Creates missing reg keys and directories. + * Mostly forwards to SHGetFolderPathW, but a few values of nFolder return + * virtual folders that are handled here. + * + * PARAMS + * hwndOwner [I] + * nFolder [I] CSIDL_xxxxx + * hToken [I] token representing user, or NULL for current user, or -1 for + * default user + * dwReserved [I] must be zero + * ppidl [O] PIDL of a special folder + * + * NOTES + */ +HRESULT WINAPI SHGetFolderLocation( + HWND hwndOwner, + int nFolder, + HANDLE hToken, + DWORD dwReserved, + LPITEMIDLIST *ppidl) +{ + HRESULT hr = E_INVALIDARG; + + TRACE("%p 0x%08x %p 0x%08lx %p\n", + hwndOwner, nFolder, hToken, dwReserved, ppidl); + + if (!ppidl) + return E_INVALIDARG; + if (dwReserved) + return E_INVALIDARG; + + /* The virtual folders' locations are not user-dependent */ + *ppidl = NULL; + switch (nFolder) + { + case CSIDL_DESKTOP: + *ppidl = _ILCreateDesktop(); + break; + + case CSIDL_INTERNET: + *ppidl = _ILCreateIExplore(); + break; + + case CSIDL_CONTROLS: + *ppidl = _ILCreateControlPanel(); + break; + + case CSIDL_PRINTERS: + *ppidl = _ILCreatePrinters(); + break; + + case CSIDL_FONTS: + FIXME("virtual font folder"); + break; + + case CSIDL_BITBUCKET: + *ppidl = _ILCreateBitBucket(); + break; + + case CSIDL_DRIVES: + *ppidl = _ILCreateMyComputer(); + break; + + case CSIDL_NETWORK: + *ppidl = _ILCreateNetwork(); + break; + + default: + { + WCHAR szPath[MAX_PATH]; + + hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, + SHGFP_TYPE_CURRENT, szPath); + if (SUCCEEDED(hr)) + { + DWORD attributes=0; + + TRACE("Value=%s\n", debugstr_w(szPath)); + hr = SHILCreateFromPathW(szPath, ppidl, &attributes); + } + else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + /* unlike SHGetFolderPath, SHGetFolderLocation in shell32 + * version 6.0 returns E_FAIL for non-existing paths + */ + hr = E_FAIL; + } + } + } + if(*ppidl) + hr = NOERROR; + + TRACE("-- (new pidl %p)\n",*ppidl); + return hr; +} + +/************************************************************************* + * SHGetSpecialFolderLocation [SHELL32.@] + * + * NOTES + * In NT5, SHGetSpecialFolderLocation needs the /Recent + * directory. + */ +HRESULT WINAPI SHGetSpecialFolderLocation( + HWND hwndOwner, + INT nFolder, + LPITEMIDLIST * ppidl) +{ + HRESULT hr = E_INVALIDARG; + + TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl); + + if (!ppidl) + return E_INVALIDARG; + + hr = SHGetFolderLocation(hwndOwner, nFolder, NULL, 0, ppidl); + return hr; +} diff --git a/reactos/lib/shell32/shellreg.c b/reactos/lib/shell32/shellreg.c index 0fe7eb4b8be..700ab519d8f 100644 --- a/reactos/lib/shell32/shellreg.c +++ b/reactos/lib/shell32/shellreg.c @@ -1,154 +1,153 @@ -/* - * Shell Registry Access - * - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "shellapi.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "winerror.h" -#include "winreg.h" -#include "winnls.h" - -#include "undocshell.h" -#include "wine/winbase16.h" -#include "shell32_main.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************************************************************* - * SHRegOpenKeyA [SHELL32.506] - * - */ -HRESULT WINAPI SHRegOpenKeyA( - HKEY hKey, - LPSTR lpSubKey, - PHKEY phkResult) -{ - TRACE("(%p, %s, %p)\n", hKey, debugstr_a(lpSubKey), phkResult); - return RegOpenKeyA(hKey, lpSubKey, phkResult); -} - -/************************************************************************* - * SHRegOpenKeyW [SHELL32.507] NT 4.0 - * - */ -HRESULT WINAPI SHRegOpenKeyW ( - HKEY hkey, - LPCWSTR lpszSubKey, - PHKEY retkey) -{ - WARN("%p %s %p\n",hkey,debugstr_w(lpszSubKey),retkey); - return RegOpenKeyW( hkey, lpszSubKey, retkey ); -} - -/************************************************************************* - * SHRegQueryValueExA [SHELL32.509] - * - */ -HRESULT WINAPI SHRegQueryValueExA( - HKEY hkey, - LPSTR lpValueName, - LPDWORD lpReserved, - LPDWORD lpType, - LPBYTE lpData, - LPDWORD lpcbData) -{ - TRACE("%p %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData); - return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData); -} - -/************************************************************************* - * SHRegQueryValueW [SHELL32.510] NT4.0 - * - */ -HRESULT WINAPI SHRegQueryValueW( - HKEY hkey, - LPWSTR lpszSubKey, - LPWSTR lpszData, - LPDWORD lpcbData ) -{ - WARN("%p %s %p %p semi-stub\n", - hkey, debugstr_w(lpszSubKey), lpszData, lpcbData); - return RegQueryValueW( hkey, lpszSubKey, lpszData, lpcbData ); -} - -/************************************************************************* - * SHRegQueryValueExW [SHELL32.511] NT4.0 - * - * FIXME - * if the datatype REG_EXPAND_SZ then expand the string and change - * *pdwType to REG_SZ. - */ -HRESULT WINAPI SHRegQueryValueExW ( - HKEY hkey, - LPWSTR pszValue, - LPDWORD pdwReserved, - LPDWORD pdwType, - LPVOID pvData, - LPDWORD pcbData) -{ - DWORD ret; - WARN("%p %s %p %p %p %p semi-stub\n", - hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData); - ret = RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData); - return ret; -} - -/************************************************************************* - * SHRegDeleteKeyA [SHELL32.?] - */ -HRESULT WINAPI SHRegDeleteKeyA( - HKEY hkey, - LPCSTR pszSubKey) -{ - FIXME("hkey=%p, %s\n", hkey, debugstr_a(pszSubKey)); - return 0; -} - -/************************************************************************* - * SHRegDeleteKeyW [SHELL32.512] - */ -HRESULT WINAPI SHRegDeleteKeyW( - HKEY hkey, - LPCWSTR pszSubKey) -{ - FIXME("hkey=%p, %s\n", hkey, debugstr_w(pszSubKey)); - return 0; -} - -/************************************************************************* - * SHRegCloseKey [SHELL32.505] NT 4.0 - * - */ -HRESULT WINAPI SHRegCloseKey (HKEY hkey) -{ - TRACE("%p\n",hkey); - return RegCloseKey( hkey ); -} +/* + * Shell Registry Access + * + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "shellapi.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "winerror.h" +#include "winreg.h" +#include "winnls.h" + +#include "undocshell.h" +#include "wine/winbase16.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/************************************************************************* + * SHRegOpenKeyA [SHELL32.506] + * + */ +HRESULT WINAPI SHRegOpenKeyA( + HKEY hKey, + LPSTR lpSubKey, + PHKEY phkResult) +{ + TRACE("(%p, %s, %p)\n", hKey, debugstr_a(lpSubKey), phkResult); + return RegOpenKeyA(hKey, lpSubKey, phkResult); +} + +/************************************************************************* + * SHRegOpenKeyW [SHELL32.507] NT 4.0 + * + */ +HRESULT WINAPI SHRegOpenKeyW ( + HKEY hkey, + LPCWSTR lpszSubKey, + PHKEY retkey) +{ + WARN("%p %s %p\n",hkey,debugstr_w(lpszSubKey),retkey); + return RegOpenKeyW( hkey, lpszSubKey, retkey ); +} + +/************************************************************************* + * SHRegQueryValueExA [SHELL32.509] + * + */ +HRESULT WINAPI SHRegQueryValueExA( + HKEY hkey, + LPSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData) +{ + TRACE("%p %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData); + return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData); +} + +/************************************************************************* + * SHRegQueryValueW [SHELL32.510] NT4.0 + * + */ +HRESULT WINAPI SHRegQueryValueW( + HKEY hkey, + LPWSTR lpszSubKey, + LPWSTR lpszData, + LPDWORD lpcbData ) +{ + WARN("%p %s %p %p semi-stub\n", + hkey, debugstr_w(lpszSubKey), lpszData, lpcbData); + return RegQueryValueW( hkey, lpszSubKey, lpszData, lpcbData ); +} + +/************************************************************************* + * SHRegQueryValueExW [SHELL32.511] NT4.0 + * + * FIXME + * if the datatype REG_EXPAND_SZ then expand the string and change + * *pdwType to REG_SZ. + */ +HRESULT WINAPI SHRegQueryValueExW ( + HKEY hkey, + LPWSTR pszValue, + LPDWORD pdwReserved, + LPDWORD pdwType, + LPVOID pvData, + LPDWORD pcbData) +{ + DWORD ret; + WARN("%p %s %p %p %p %p semi-stub\n", + hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData); + ret = RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData); + return ret; +} + +/************************************************************************* + * SHRegDeleteKeyA [SHELL32.?] + */ +HRESULT WINAPI SHRegDeleteKeyA( + HKEY hkey, + LPCSTR pszSubKey) +{ + FIXME("hkey=%p, %s\n", hkey, debugstr_a(pszSubKey)); + return 0; +} + +/************************************************************************* + * SHRegDeleteKeyW [SHELL32.512] + */ +HRESULT WINAPI SHRegDeleteKeyW( + HKEY hkey, + LPCWSTR pszSubKey) +{ + FIXME("hkey=%p, %s\n", hkey, debugstr_w(pszSubKey)); + return 0; +} + +/************************************************************************* + * SHRegCloseKey [SHELL32.505] NT 4.0 + * + */ +HRESULT WINAPI SHRegCloseKey (HKEY hkey) +{ + TRACE("%p\n",hkey); + return RegCloseKey( hkey ); +} diff --git a/reactos/lib/shell32/shellstring.c b/reactos/lib/shell32/shellstring.c index abb25c32f5c..3581768d72d 100644 --- a/reactos/lib/shell32/shellstring.c +++ b/reactos/lib/shell32/shellstring.c @@ -1,286 +1,286 @@ -/* - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winreg.h" - -#include "shlobj.h" -#include "shellapi.h" -#include "shlwapi.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************* STRRET functions ****************************/ - -BOOL WINAPI StrRetToStrNA(LPSTR dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) -{ - TRACE("dest=%p len=0x%lx strret=%p(%s) pidl=%p\n", - dest,len,src, - (src->uType == STRRET_WSTR) ? "STRRET_WSTR" : - (src->uType == STRRET_CSTR) ? "STRRET_CSTR" : - (src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???", - pidl); - - if (!dest) - return FALSE; - - switch (src->uType) - { - case STRRET_WSTR: - WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, dest, len, NULL, NULL); - CoTaskMemFree(src->u.pOleStr); - break; - - case STRRET_CSTR: - lstrcpynA(dest, src->u.cStr, len); - break; - - case STRRET_OFFSET: - lstrcpynA(dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len); - break; - - default: - FIXME("unknown type!\n"); - if (len) *dest = '\0'; - return FALSE; - } - TRACE("-- %s\n", debugstr_a(dest) ); - return TRUE; -} - -/************************************************************************/ - -BOOL WINAPI StrRetToStrNW(LPWSTR dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) -{ - TRACE("dest=%p len=0x%lx strret=%p(%s) pidl=%p\n", - dest,len,src, - (src->uType == STRRET_WSTR) ? "STRRET_WSTR" : - (src->uType == STRRET_CSTR) ? "STRRET_CSTR" : - (src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???", - pidl); - - if (!dest) - return FALSE; - - switch (src->uType) - { - case STRRET_WSTR: - lstrcpynW(dest, src->u.pOleStr, len); - CoTaskMemFree(src->u.pOleStr); - break; - - case STRRET_CSTR: - if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len) - dest[len-1] = 0; - break; - - case STRRET_OFFSET: - if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1, dest, len ) && len) - dest[len-1] = 0; - break; - - default: - FIXME("unknown type!\n"); - if (len) *dest = '\0'; - return FALSE; - } - return TRUE; -} - - -/************************************************************************* - * StrRetToStrN [SHELL32.96] - * - * converts a STRRET to a normal string - * - * NOTES - * the pidl is for STRRET OFFSET - */ -BOOL WINAPI StrRetToStrNAW(LPVOID dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) -{ - if(SHELL_OsIsUnicode()) - return StrRetToStrNW(dest, len, src, pidl); - else - return StrRetToStrNA(dest, len, src, pidl); -} - -/************************* OLESTR functions ****************************/ - -/************************************************************************ - * StrToOleStr [SHELL32.163] - * - */ -int WINAPI StrToOleStrA (LPWSTR lpWideCharStr, LPCSTR lpMultiByteString) -{ - TRACE("(%p, %p %s)\n", - lpWideCharStr, lpMultiByteString, debugstr_a(lpMultiByteString)); - - return MultiByteToWideChar(0, 0, lpMultiByteString, -1, lpWideCharStr, MAX_PATH); - -} -int WINAPI StrToOleStrW (LPWSTR lpWideCharStr, LPCWSTR lpWString) -{ - TRACE("(%p, %p %s)\n", - lpWideCharStr, lpWString, debugstr_w(lpWString)); - - strcpyW (lpWideCharStr, lpWString ); - return strlenW(lpWideCharStr); -} - -BOOL WINAPI StrToOleStrAW (LPWSTR lpWideCharStr, LPCVOID lpString) -{ - if (SHELL_OsIsUnicode()) - return StrToOleStrW (lpWideCharStr, lpString); - return StrToOleStrA (lpWideCharStr, lpString); -} - -/************************************************************************* - * StrToOleStrN [SHELL32.79] - * lpMulti, nMulti, nWide [IN] - * lpWide [OUT] - */ -BOOL WINAPI StrToOleStrNA (LPWSTR lpWide, INT nWide, LPCSTR lpStrA, INT nStr) -{ - TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_an(lpStrA,nStr), nStr); - return MultiByteToWideChar (0, 0, lpStrA, nStr, lpWide, nWide); -} -BOOL WINAPI StrToOleStrNW (LPWSTR lpWide, INT nWide, LPCWSTR lpStrW, INT nStr) -{ - TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_wn(lpStrW, nStr), nStr); - - if (lstrcpynW (lpWide, lpStrW, nWide)) - { return lstrlenW (lpWide); - } - return 0; -} - -BOOL WINAPI StrToOleStrNAW (LPWSTR lpWide, INT nWide, LPCVOID lpStr, INT nStr) -{ - if (SHELL_OsIsUnicode()) - return StrToOleStrNW (lpWide, nWide, lpStr, nStr); - return StrToOleStrNA (lpWide, nWide, lpStr, nStr); -} - -/************************************************************************* - * OleStrToStrN [SHELL32.78] - */ -BOOL WINAPI OleStrToStrNA (LPSTR lpStr, INT nStr, LPCWSTR lpOle, INT nOle) -{ - TRACE("(%p, %x, %s, %x)\n", lpStr, nStr, debugstr_wn(lpOle,nOle), nOle); - return WideCharToMultiByte (0, 0, lpOle, nOle, lpStr, nStr, NULL, NULL); -} - -BOOL WINAPI OleStrToStrNW (LPWSTR lpwStr, INT nwStr, LPCWSTR lpOle, INT nOle) -{ - TRACE("(%p, %x, %s, %x)\n", lpwStr, nwStr, debugstr_wn(lpOle,nOle), nOle); - - if (lstrcpynW ( lpwStr, lpOle, nwStr)) - { return lstrlenW (lpwStr); - } - return 0; -} - -BOOL WINAPI OleStrToStrNAW (LPVOID lpOut, INT nOut, LPCVOID lpIn, INT nIn) -{ - if (SHELL_OsIsUnicode()) - return OleStrToStrNW (lpOut, nOut, lpIn, nIn); - return OleStrToStrNA (lpOut, nOut, lpIn, nIn); -} - - -/************************************************************************* - * CheckEscapesA [SHELL32.@] - * - * Checks a string for special characters which are not allowed in a path - * and encloses it in quotes if that is the case. - * - * PARAMS - * string [I/O] string to check and on return eventually quoted - * len [I] length of string - * - * RETURNS - * length of actual string - * - * NOTES - * Not really sure if this function returns actually a value at all. - */ -DWORD WINAPI CheckEscapesA( - LPSTR string, /* [I/O] string to check ??*/ - DWORD len) /* [I] is 0 */ -{ - LPWSTR wString; - DWORD ret = 0; - - TRACE("(%s %ld)\n", debugstr_a(string), len); - wString = (LPWSTR)LocalAlloc(LPTR, len * sizeof(WCHAR)); - if (wString) - { - MultiByteToWideChar(CP_ACP, 0, string, len, wString, len); - ret = CheckEscapesW(wString, len); - WideCharToMultiByte(CP_ACP, 0, wString, len, string, len, NULL, NULL); - LocalFree(wString); - } - return ret; -} - -static const WCHAR strEscapedChars[] = {' ','"',',',';','^',0}; - -/************************************************************************* - * CheckEscapesW [SHELL32.@] - * - * see CheckEscapesA - */ -DWORD WINAPI CheckEscapesW( - LPWSTR string, - DWORD len) -{ - DWORD size = lstrlenW(string); - LPWSTR s, d; - - TRACE("(%s %ld) stub\n", debugstr_w(string), len); - - if (StrPBrkW(string, strEscapedChars) && size + 2 <= len) - { - s = &string[size - 1]; - d = &string[size + 2]; - *d-- = 0; - *d-- = '"'; - for (;d > string;) - *d-- = *s--; - *d = '"'; - return size + 2; - } - return size; -} +/* + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winerror.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" + +#include "shlobj.h" +#include "shellapi.h" +#include "shlwapi.h" +#include "shell32_main.h" +#include "undocshell.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/************************* STRRET functions ****************************/ + +BOOL WINAPI StrRetToStrNA(LPSTR dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) +{ + TRACE("dest=%p len=0x%lx strret=%p(%s) pidl=%p\n", + dest,len,src, + (src->uType == STRRET_WSTR) ? "STRRET_WSTR" : + (src->uType == STRRET_CSTR) ? "STRRET_CSTR" : + (src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???", + pidl); + + if (!dest) + return FALSE; + + switch (src->uType) + { + case STRRET_WSTR: + WideCharToMultiByte(CP_ACP, 0, src->u.pOleStr, -1, dest, len, NULL, NULL); + CoTaskMemFree(src->u.pOleStr); + break; + + case STRRET_CSTR: + lstrcpynA(dest, src->u.cStr, len); + break; + + case STRRET_OFFSET: + lstrcpynA(dest, ((LPCSTR)&pidl->mkid)+src->u.uOffset, len); + break; + + default: + FIXME("unknown type!\n"); + if (len) *dest = '\0'; + return FALSE; + } + TRACE("-- %s\n", debugstr_a(dest) ); + return TRUE; +} + +/************************************************************************/ + +BOOL WINAPI StrRetToStrNW(LPWSTR dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) +{ + TRACE("dest=%p len=0x%lx strret=%p(%s) pidl=%p\n", + dest,len,src, + (src->uType == STRRET_WSTR) ? "STRRET_WSTR" : + (src->uType == STRRET_CSTR) ? "STRRET_CSTR" : + (src->uType == STRRET_OFFSET) ? "STRRET_OFFSET" : "STRRET_???", + pidl); + + if (!dest) + return FALSE; + + switch (src->uType) + { + case STRRET_WSTR: + lstrcpynW(dest, src->u.pOleStr, len); + CoTaskMemFree(src->u.pOleStr); + break; + + case STRRET_CSTR: + if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ) && len) + dest[len-1] = 0; + break; + + case STRRET_OFFSET: + if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1, dest, len ) && len) + dest[len-1] = 0; + break; + + default: + FIXME("unknown type!\n"); + if (len) *dest = '\0'; + return FALSE; + } + return TRUE; +} + + +/************************************************************************* + * StrRetToStrN [SHELL32.96] + * + * converts a STRRET to a normal string + * + * NOTES + * the pidl is for STRRET OFFSET + */ +BOOL WINAPI StrRetToStrNAW(LPVOID dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl) +{ + if(SHELL_OsIsUnicode()) + return StrRetToStrNW(dest, len, src, pidl); + else + return StrRetToStrNA(dest, len, src, pidl); +} + +/************************* OLESTR functions ****************************/ + +/************************************************************************ + * StrToOleStr [SHELL32.163] + * + */ +int WINAPI StrToOleStrA (LPWSTR lpWideCharStr, LPCSTR lpMultiByteString) +{ + TRACE("(%p, %p %s)\n", + lpWideCharStr, lpMultiByteString, debugstr_a(lpMultiByteString)); + + return MultiByteToWideChar(0, 0, lpMultiByteString, -1, lpWideCharStr, MAX_PATH); + +} +int WINAPI StrToOleStrW (LPWSTR lpWideCharStr, LPCWSTR lpWString) +{ + TRACE("(%p, %p %s)\n", + lpWideCharStr, lpWString, debugstr_w(lpWString)); + + strcpyW (lpWideCharStr, lpWString ); + return strlenW(lpWideCharStr); +} + +BOOL WINAPI StrToOleStrAW (LPWSTR lpWideCharStr, LPCVOID lpString) +{ + if (SHELL_OsIsUnicode()) + return StrToOleStrW (lpWideCharStr, lpString); + return StrToOleStrA (lpWideCharStr, lpString); +} + +/************************************************************************* + * StrToOleStrN [SHELL32.79] + * lpMulti, nMulti, nWide [IN] + * lpWide [OUT] + */ +BOOL WINAPI StrToOleStrNA (LPWSTR lpWide, INT nWide, LPCSTR lpStrA, INT nStr) +{ + TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_an(lpStrA,nStr), nStr); + return MultiByteToWideChar (0, 0, lpStrA, nStr, lpWide, nWide); +} +BOOL WINAPI StrToOleStrNW (LPWSTR lpWide, INT nWide, LPCWSTR lpStrW, INT nStr) +{ + TRACE("(%p, %x, %s, %x)\n", lpWide, nWide, debugstr_wn(lpStrW, nStr), nStr); + + if (lstrcpynW (lpWide, lpStrW, nWide)) + { return lstrlenW (lpWide); + } + return 0; +} + +BOOL WINAPI StrToOleStrNAW (LPWSTR lpWide, INT nWide, LPCVOID lpStr, INT nStr) +{ + if (SHELL_OsIsUnicode()) + return StrToOleStrNW (lpWide, nWide, lpStr, nStr); + return StrToOleStrNA (lpWide, nWide, lpStr, nStr); +} + +/************************************************************************* + * OleStrToStrN [SHELL32.78] + */ +BOOL WINAPI OleStrToStrNA (LPSTR lpStr, INT nStr, LPCWSTR lpOle, INT nOle) +{ + TRACE("(%p, %x, %s, %x)\n", lpStr, nStr, debugstr_wn(lpOle,nOle), nOle); + return WideCharToMultiByte (0, 0, lpOle, nOle, lpStr, nStr, NULL, NULL); +} + +BOOL WINAPI OleStrToStrNW (LPWSTR lpwStr, INT nwStr, LPCWSTR lpOle, INT nOle) +{ + TRACE("(%p, %x, %s, %x)\n", lpwStr, nwStr, debugstr_wn(lpOle,nOle), nOle); + + if (lstrcpynW ( lpwStr, lpOle, nwStr)) + { return lstrlenW (lpwStr); + } + return 0; +} + +BOOL WINAPI OleStrToStrNAW (LPVOID lpOut, INT nOut, LPCVOID lpIn, INT nIn) +{ + if (SHELL_OsIsUnicode()) + return OleStrToStrNW (lpOut, nOut, lpIn, nIn); + return OleStrToStrNA (lpOut, nOut, lpIn, nIn); +} + + +/************************************************************************* + * CheckEscapesA [SHELL32.@] + * + * Checks a string for special characters which are not allowed in a path + * and encloses it in quotes if that is the case. + * + * PARAMS + * string [I/O] string to check and on return eventually quoted + * len [I] length of string + * + * RETURNS + * length of actual string + * + * NOTES + * Not really sure if this function returns actually a value at all. + */ +DWORD WINAPI CheckEscapesA( + LPSTR string, /* [I/O] string to check ??*/ + DWORD len) /* [I] is 0 */ +{ + LPWSTR wString; + DWORD ret = 0; + + TRACE("(%s %ld)\n", debugstr_a(string), len); + wString = (LPWSTR)LocalAlloc(LPTR, len * sizeof(WCHAR)); + if (wString) + { + MultiByteToWideChar(CP_ACP, 0, string, len, wString, len); + ret = CheckEscapesW(wString, len); + WideCharToMultiByte(CP_ACP, 0, wString, len, string, len, NULL, NULL); + LocalFree(wString); + } + return ret; +} + +static const WCHAR strEscapedChars[] = {' ','"',',',';','^',0}; + +/************************************************************************* + * CheckEscapesW [SHELL32.@] + * + * see CheckEscapesA + */ +DWORD WINAPI CheckEscapesW( + LPWSTR string, + DWORD len) +{ + DWORD size = lstrlenW(string); + LPWSTR s, d; + + TRACE("(%s %ld) stub\n", debugstr_w(string), len); + + if (StrPBrkW(string, strEscapedChars) && size + 2 <= len) + { + s = &string[size - 1]; + d = &string[size + 2]; + *d-- = 0; + *d-- = '"'; + for (;d > string;) + *d-- = *s--; + *d = '"'; + return size + 2; + } + return size; +} diff --git a/reactos/lib/shell32/shfldr.h b/reactos/lib/shell32/shfldr.h index f78026da8f9..5666f0d7cc3 100644 --- a/reactos/lib/shell32/shfldr.h +++ b/reactos/lib/shell32/shfldr.h @@ -1,58 +1,58 @@ - -/* - * Virtual Folder - * common definitions - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define CHARS_IN_GUID 39 - -typedef struct { - int colnameid; - int pcsFlags; - int fmt; - int cxChar; -} shvheader; - -#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00) -#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF) - -BOOL SHELL32_GetCustomFolderAttribute (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, LPWSTR pwszValue, DWORD cchValue); - -LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); -HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, - LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); -HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes); -HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, - DWORD dwOutLen); - -HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, - LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); - -HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); - -static inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) -{ - return sprintf(str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); -} - -void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags); + +/* + * Virtual Folder + * common definitions + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CHARS_IN_GUID 39 + +typedef struct { + int colnameid; + int pcsFlags; + int fmt; + int cxChar; +} shvheader; + +#define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00) +#define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF) + +BOOL SHELL32_GetCustomFolderAttribute (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, LPWSTR pwszValue, DWORD cchValue); + +LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); +HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, + LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); +HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes); +HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, + DWORD dwOutLen); + +HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, + LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); + +HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); + +static inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) +{ + return sprintf(str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); +} + +void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags); diff --git a/reactos/lib/shell32/shfldr_desktop.c b/reactos/lib/shell32/shfldr_desktop.c index 57180471467..66b4e8c5d16 100644 --- a/reactos/lib/shell32/shfldr_desktop.c +++ b/reactos/lib/shell32/shfldr_desktop.c @@ -1,739 +1,739 @@ - -/* - * Virtual Desktop Folder - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "ole2.h" -#include "shlguid.h" - -#include "enumidlist.h" -#include "pidl.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "shellfolder.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL (shell); - -/*********************************************************************** -* Desktopfolder implementation -*/ - -typedef struct { - IShellFolder2Vtbl *lpVtbl; - DWORD ref; - - CLSID *pclsid; - - /* both paths are parsible from the desktop */ - LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ - LPITEMIDLIST pidlRoot; /* absolute pidl */ - - int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ - - UINT cfShellIDList; /* clipboardformat for IDropTarget */ - BOOL fAcceptFmt; /* flag for pending Drop */ -} IGenericSFImpl; - -#define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl) -#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) - -static struct IShellFolder2Vtbl vt_MCFldr_ShellFolder2; - -static shvheader DesktopSFHeader[] = { - {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, - {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}, - {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5} -}; - -#define DESKTOPSHELLVIEWCOLUMNS 5 - -/************************************************************************** -* ISF_Desktop_Constructor -*/ -HRESULT WINAPI ISF_Desktop_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) -{ - IGenericSFImpl *sf; - char szMyPath[MAX_PATH]; - - TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); - - if (!ppv) - return E_POINTER; - if (pUnkOuter) - return CLASS_E_NOAGGREGATION; - - if (!SHGetSpecialFolderPathA (0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE)) - return E_UNEXPECTED; - - sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); - if (!sf) - return E_OUTOFMEMORY; - - sf->ref = 0; - sf->lpVtbl = &vt_MCFldr_ShellFolder2; - sf->pidlRoot = _ILCreateDesktop (); /* my qualified pidl */ - sf->sPathTarget = SHAlloc (strlen (szMyPath) + 1); - lstrcpyA (sf->sPathTarget, szMyPath); - - if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { - IUnknown_Release (_IUnknown_ (sf)); - return E_NOINTERFACE; - } - - TRACE ("--(%p)\n", sf); - return S_OK; -} - -/************************************************************************** - * ISF_Desktop_fnQueryInterface - * - * NOTES supports not IPersist/IPersistFolder - */ -static HRESULT WINAPI ISF_Desktop_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - *ppvObj = NULL; - - if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IShellFolder) - || IsEqualIID (riid, &IID_IShellFolder2)) { - *ppvObj = This; - } - - if (*ppvObj) { - IUnknown_AddRef ((IUnknown *) (*ppvObj)); - TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); - return S_OK; - } - TRACE ("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return ++(This->ref); -} - -static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - if (!--(This->ref)) { - TRACE ("-- destroying IShellFolder(%p)\n", This); - if (This->pidlRoot) - SHFree (This->pidlRoot); - if (This->sPathTarget) - SHFree (This->sPathTarget); - LocalFree ((HLOCAL) This); - return 0; - } - return This->ref; -} - -/************************************************************************** -* ISF_Desktop_fnParseDisplayName -* -* NOTES -* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds -* to MyComputer -*/ -static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface, - HWND hwndOwner, - LPBC pbc, - LPOLESTR lpszDisplayName, - DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - WCHAR szElement[MAX_PATH]; - LPCWSTR szNext = NULL; - LPITEMIDLIST pidlTemp = NULL; - HRESULT hr = S_OK; - char szPath[MAX_PATH]; - DWORD len; - CLSID clsid; - - TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", - This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); - - if (!lpszDisplayName || !ppidl) - return E_INVALIDARG; - - *ppidl = 0; - - if (pchEaten) - *pchEaten = 0; /* strange but like the original */ - - if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') { - szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - TRACE ("-- element: %s\n", debugstr_w (szElement)); - SHCLSIDFromStringW (szElement + 2, &clsid); - pidlTemp = _ILCreateGuid (PT_GUID, &clsid); - } else if (PathGetDriveNumberW (lpszDisplayName) >= 0) { - /* it's a filesystem path with a drive. Let MyComputer parse it */ - pidlTemp = _ILCreateMyComputer (); - szNext = lpszDisplayName; - } else if (PathIsUNCW(lpszDisplayName)) { - pidlTemp = _ILCreateNetwork(); - szNext = lpszDisplayName; - } else { - /* it's a filesystem path on the desktop. Let a FSFolder parse it */ - - if (*lpszDisplayName) { - /* build a complete path to create a simple pidl */ - lstrcpyA(szPath, This->sPathTarget); - PathAddBackslashA(szPath); - len = lstrlenA(szPath); - WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1, szPath + len, MAX_PATH - len, NULL, NULL); - hr = _ILCreateFromPathA(szPath, &pidlTemp); - } else { - pidlTemp = _ILCreateMyComputer(); - } - - szNext = NULL; - } - - if (SUCCEEDED(hr) && pidlTemp) { - if (szNext && *szNext) { - hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); - } else { - if (pdwAttributes && *pdwAttributes) { - hr = SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); - } - } - } - - *ppidl = pidlTemp; - - TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr); - - return hr; -} - -/************************************************************************** - * CreateDesktopEnumList() - */ -static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) -{ - BOOL ret = TRUE; - char szPath[MAX_PATH]; - - TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags); - - /*enumerate the root folders */ - if(dwFlags & SHCONTF_FOLDERS) - { - HKEY hkey; - - /*create the pidl for This item */ - ret = AddToEnumList(list, _ILCreateMyComputer()); - - if (ret && !RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\desktop\\NameSpace", - 0, KEY_READ, &hkey)) - { - char iid[50]; - int i=0; - BOOL moreKeys = TRUE; - - while (ret && moreKeys) - { - DWORD size = sizeof (iid); - LONG apiRet = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL, - NULL); - - if (ERROR_SUCCESS == apiRet) - { - ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid)); - i++; - } - else if (ERROR_NO_MORE_ITEMS == apiRet) - moreKeys = FALSE; - else - ret = FALSE; - } - RegCloseKey(hkey); - } - } - - /*enumerate the elements in %windir%\desktop */ - SHGetSpecialFolderPathA(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); - ret = ret && CreateFolderEnumList(list, szPath, dwFlags); - - return ret; -} - -/************************************************************************** -* ISF_Desktop_fnEnumObjects -*/ -static HRESULT WINAPI ISF_Desktop_fnEnumObjects (IShellFolder2 * iface, - HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); - - *ppEnumIDList = IEnumIDList_Constructor(); - if (*ppEnumIDList) - CreateDesktopEnumList(*ppEnumIDList, dwFlags); - - TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); - - return *ppEnumIDList ? S_OK : E_OUTOFMEMORY; -} - -/************************************************************************** -* ISF_Desktop_fnBindToObject -*/ -static HRESULT WINAPI ISF_Desktop_fnBindToObject (IShellFolder2 * iface, - LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); - - return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut); -} - -/************************************************************************** -* ISF_Desktop_fnBindToStorage -*/ -static HRESULT WINAPI ISF_Desktop_fnBindToStorage (IShellFolder2 * iface, - LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); - - *ppvOut = NULL; - return E_NOTIMPL; -} - -/************************************************************************** -* ISF_Desktop_fnCompareIDs -*/ - -static HRESULT WINAPI ISF_Desktop_fnCompareIDs (IShellFolder2 * iface, - LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - int nReturn; - - TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); - nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); - TRACE ("-- %i\n", nReturn); - return nReturn; -} - -/************************************************************************** -* ISF_Desktop_fnCreateViewObject -*/ -static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface, - HWND hwndOwner, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - LPSHELLVIEW pShellView; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IDropTarget)) { - WARN ("IDropTarget not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID (riid, &IID_IContextMenu)) { - WARN ("IContextMenu not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID (riid, &IID_IShellView)) { - pShellView = IShellView_Constructor ((IShellFolder *) iface); - if (pShellView) { - hr = IShellView_QueryInterface (pShellView, riid, ppvOut); - IShellView_Release (pShellView); - } - } - } - TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); - return hr; -} - -/************************************************************************** -* ISF_Desktop_fnGetAttributesOf -*/ -static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface, - UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - HRESULT hr = S_OK; - - TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); - - if ((!cidl) || (!apidl) || (!rgfInOut)) - return E_INVALIDARG; - - if (*rgfInOut == 0) - *rgfInOut = ~0; - - while (cidl > 0 && *apidl) { - pdump (*apidl); - SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); - apidl++; - cidl--; - } - - TRACE ("-- result=0x%08lx\n", *rgfInOut); - - return hr; -} - -/************************************************************************** -* ISF_Desktop_fnGetUIObjectOf -* -* PARAMETERS -* HWND hwndOwner, //[in ] Parent window for any output -* UINT cidl, //[in ] array size -* LPCITEMIDLIST* apidl, //[in ] simple pidl array -* REFIID riid, //[in ] Requested Interface -* UINT* prgfInOut, //[ ] reserved -* LPVOID* ppvObject) //[out] Resulting Interface -* -*/ -static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface, - HWND hwndOwner, - UINT cidl, - LPCITEMIDLIST * apidl, - REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - LPITEMIDLIST pidl; - IUnknown *pObj = NULL; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", - This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IContextMenu)) { - pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { - pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { - hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); - } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) - && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); - SHFree (pidl); - } else { - hr = E_NOINTERFACE; - } - - if (SUCCEEDED(hr) && !pObj) - hr = E_OUTOFMEMORY; - - *ppvOut = pObj; - } - TRACE ("(%p)->hr=0x%08lx\n", This, hr); - return hr; -} - -/************************************************************************** -* ISF_Desktop_fnGetDisplayNameOf -* -* NOTES -* special case: pidl = null gives desktop-name back -*/ -static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface, - LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - CHAR szPath[MAX_PATH]; - GUID const *clsid; - HRESULT hr = S_OK; - - *szPath = '\0'; - - TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); - pdump (pidl); - - if (!strRet) - return E_INVALIDARG; - - if (_ILIsDesktop (pidl)) { - if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)) { - lstrcpyA (szPath, This->sPathTarget); - } else { - HCR_GetClassNameA(&CLSID_ShellDesktop, szPath, MAX_PATH); - } - } else if (_ILIsPidlSimple (pidl)) { - if ((clsid = _ILGetGUIDPointer (pidl))) { - if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) { - int bWantsForParsing; - - /* - * we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in - * CLSID\\{...}\\shellfolder exists - * exception: the MyComputer folder has this keys not but like any filesystem backed - * folder it needs these behaviour - */ - if (IsEqualIID (clsid, &CLSID_MyComputer)) { - bWantsForParsing = 1; - } else { - /* get the "WantsFORPARSING" flag from the registry */ - char szRegPath[100]; - - lstrcpyA (szRegPath, "CLSID\\"); - SHELL32_GUIDToStringA (clsid, &szRegPath[6]); - lstrcatA (szRegPath, "\\shellfolder"); - bWantsForParsing = - (ERROR_SUCCESS == - SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL)); - } - - if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) { - /* we need the filesystem path to the destination folder. Only the folder itself can know it */ - hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); - } else { - /* parsing name like ::{...} */ - lstrcpyA (szPath, "::"); - SHELL32_GUIDToStringA (clsid, &szPath[2]); - } - } else { - /* user friendly name */ - HCR_GetClassNameA (clsid, szPath, MAX_PATH); - } - } else { - /* file system folder */ - _ILSimpleGetText (pidl, szPath, MAX_PATH); - - if (!_ILIsFolder(pidl)) - SHELL_FS_ProcessDisplayFilename(szPath, dwFlags); - } - } else { - /* a complex pidl, let the subfolder do the work */ - hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); - } - - if (SUCCEEDED (hr)) { - strRet->uType = STRRET_CSTR; - lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); - } - - TRACE ("-- (%p)->(%s,0x%08lx)\n", This, szPath, hr); - return hr; -} - -/************************************************************************** -* ISF_Desktop_fnSetNameOf -* Changes the name of a file object or subfolder, possibly changing its item -* identifier in the process. -* -* PARAMETERS -* HWND hwndOwner, //[in ] Owner window for output -* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change -* LPCOLESTR lpszName, //[in ] the items new display name -* DWORD dwFlags, //[in ] SHGNO formatting flags -* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned -*/ -static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ - LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); - - return E_FAIL; -} - -static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_Desktop_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn (IShellFolder2 * iface, - DWORD dwRes, ULONG * pSort, ULONG * pDisplay) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)\n", This); - - if (pSort) - *pSort = 0; - if (pDisplay) - *pDisplay = 0; - - return S_OK; -} -static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)\n", This); - - if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - *pcsFlags = DesktopSFHeader[iColumn].pcsFlags; - - return S_OK; -} -static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx (IShellFolder2 * iface, - LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface, - LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - HRESULT hr = E_FAIL; - - TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); - - if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - if (!pidl) { - psd->fmt = DesktopSFHeader[iColumn].fmt; - psd->cxChar = DesktopSFHeader[iColumn].cxChar; - psd->str.uType = STRRET_CSTR; - LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); - return S_OK; - } else { - /* the data from the pidl */ - switch (iColumn) { - case 0: /* name */ - hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); - break; - case 1: /* size */ - _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 2: /* type */ - _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 3: /* date */ - _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 4: /* attributes */ - _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); - break; - } - hr = S_OK; - psd->str.uType = STRRET_CSTR; - } - - return hr; -} -static HRESULT WINAPI ISF_Desktop_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} - -static IShellFolder2Vtbl vt_MCFldr_ShellFolder2 = -{ - ISF_Desktop_fnQueryInterface, - ISF_Desktop_fnAddRef, - ISF_Desktop_fnRelease, - ISF_Desktop_fnParseDisplayName, - ISF_Desktop_fnEnumObjects, - ISF_Desktop_fnBindToObject, - ISF_Desktop_fnBindToStorage, - ISF_Desktop_fnCompareIDs, - ISF_Desktop_fnCreateViewObject, - ISF_Desktop_fnGetAttributesOf, - ISF_Desktop_fnGetUIObjectOf, - ISF_Desktop_fnGetDisplayNameOf, - ISF_Desktop_fnSetNameOf, - /* ShellFolder2 */ - ISF_Desktop_fnGetDefaultSearchGUID, - ISF_Desktop_fnEnumSearches, - ISF_Desktop_fnGetDefaultColumn, - ISF_Desktop_fnGetDefaultColumnState, - ISF_Desktop_fnGetDetailsEx, - ISF_Desktop_fnGetDetailsOf, - ISF_Desktop_fnMapColumnToSCID}; + +/* + * Virtual Desktop Folder + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "ole2.h" +#include "shlguid.h" + +#include "enumidlist.h" +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "shellfolder.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +/*********************************************************************** +* Desktopfolder implementation +*/ + +typedef struct { + IShellFolder2Vtbl *lpVtbl; + DWORD ref; + + CLSID *pclsid; + + /* both paths are parsible from the desktop */ + LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ + LPITEMIDLIST pidlRoot; /* absolute pidl */ + + int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ + + UINT cfShellIDList; /* clipboardformat for IDropTarget */ + BOOL fAcceptFmt; /* flag for pending Drop */ +} IGenericSFImpl; + +#define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl) +#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) + +static struct IShellFolder2Vtbl vt_MCFldr_ShellFolder2; + +static shvheader DesktopSFHeader[] = { + {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, + {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}, + {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5} +}; + +#define DESKTOPSHELLVIEWCOLUMNS 5 + +/************************************************************************** +* ISF_Desktop_Constructor +*/ +HRESULT WINAPI ISF_Desktop_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) +{ + IGenericSFImpl *sf; + char szMyPath[MAX_PATH]; + + TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); + + if (!ppv) + return E_POINTER; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + if (!SHGetSpecialFolderPathA (0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE)) + return E_UNEXPECTED; + + sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); + if (!sf) + return E_OUTOFMEMORY; + + sf->ref = 0; + sf->lpVtbl = &vt_MCFldr_ShellFolder2; + sf->pidlRoot = _ILCreateDesktop (); /* my qualified pidl */ + sf->sPathTarget = SHAlloc (strlen (szMyPath) + 1); + lstrcpyA (sf->sPathTarget, szMyPath); + + if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { + IUnknown_Release (_IUnknown_ (sf)); + return E_NOINTERFACE; + } + + TRACE ("--(%p)\n", sf); + return S_OK; +} + +/************************************************************************** + * ISF_Desktop_fnQueryInterface + * + * NOTES supports not IPersist/IPersistFolder + */ +static HRESULT WINAPI ISF_Desktop_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + *ppvObj = NULL; + + if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IShellFolder) + || IsEqualIID (riid, &IID_IShellFolder2)) { + *ppvObj = This; + } + + if (*ppvObj) { + IUnknown_AddRef ((IUnknown *) (*ppvObj)); + TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); + return S_OK; + } + TRACE ("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE ("-- destroying IShellFolder(%p)\n", This); + if (This->pidlRoot) + SHFree (This->pidlRoot); + if (This->sPathTarget) + SHFree (This->sPathTarget); + LocalFree ((HLOCAL) This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* ISF_Desktop_fnParseDisplayName +* +* NOTES +* "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds +* to MyComputer +*/ +static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface, + HWND hwndOwner, + LPBC pbc, + LPOLESTR lpszDisplayName, + DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + WCHAR szElement[MAX_PATH]; + LPCWSTR szNext = NULL; + LPITEMIDLIST pidlTemp = NULL; + HRESULT hr = S_OK; + char szPath[MAX_PATH]; + DWORD len; + CLSID clsid; + + TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", + This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); + + if (!lpszDisplayName || !ppidl) + return E_INVALIDARG; + + *ppidl = 0; + + if (pchEaten) + *pchEaten = 0; /* strange but like the original */ + + if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') { + szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); + TRACE ("-- element: %s\n", debugstr_w (szElement)); + SHCLSIDFromStringW (szElement + 2, &clsid); + pidlTemp = _ILCreateGuid (PT_GUID, &clsid); + } else if (PathGetDriveNumberW (lpszDisplayName) >= 0) { + /* it's a filesystem path with a drive. Let MyComputer parse it */ + pidlTemp = _ILCreateMyComputer (); + szNext = lpszDisplayName; + } else if (PathIsUNCW(lpszDisplayName)) { + pidlTemp = _ILCreateNetwork(); + szNext = lpszDisplayName; + } else { + /* it's a filesystem path on the desktop. Let a FSFolder parse it */ + + if (*lpszDisplayName) { + /* build a complete path to create a simple pidl */ + lstrcpyA(szPath, This->sPathTarget); + PathAddBackslashA(szPath); + len = lstrlenA(szPath); + WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1, szPath + len, MAX_PATH - len, NULL, NULL); + hr = _ILCreateFromPathA(szPath, &pidlTemp); + } else { + pidlTemp = _ILCreateMyComputer(); + } + + szNext = NULL; + } + + if (SUCCEEDED(hr) && pidlTemp) { + if (szNext && *szNext) { + hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); + } else { + if (pdwAttributes && *pdwAttributes) { + hr = SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); + } + } + } + + *ppidl = pidlTemp; + + TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr); + + return hr; +} + +/************************************************************************** + * CreateDesktopEnumList() + */ +static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) +{ + BOOL ret = TRUE; + char szPath[MAX_PATH]; + + TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags); + + /*enumerate the root folders */ + if(dwFlags & SHCONTF_FOLDERS) + { + HKEY hkey; + + /*create the pidl for This item */ + ret = AddToEnumList(list, _ILCreateMyComputer()); + + if (ret && !RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\desktop\\NameSpace", + 0, KEY_READ, &hkey)) + { + char iid[50]; + int i=0; + BOOL moreKeys = TRUE; + + while (ret && moreKeys) + { + DWORD size = sizeof (iid); + LONG apiRet = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL, + NULL); + + if (ERROR_SUCCESS == apiRet) + { + ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid)); + i++; + } + else if (ERROR_NO_MORE_ITEMS == apiRet) + moreKeys = FALSE; + else + ret = FALSE; + } + RegCloseKey(hkey); + } + } + + /*enumerate the elements in %windir%\desktop */ + SHGetSpecialFolderPathA(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); + ret = ret && CreateFolderEnumList(list, szPath, dwFlags); + + return ret; +} + +/************************************************************************** +* ISF_Desktop_fnEnumObjects +*/ +static HRESULT WINAPI ISF_Desktop_fnEnumObjects (IShellFolder2 * iface, + HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); + + *ppEnumIDList = IEnumIDList_Constructor(); + if (*ppEnumIDList) + CreateDesktopEnumList(*ppEnumIDList, dwFlags); + + TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); + + return *ppEnumIDList ? S_OK : E_OUTOFMEMORY; +} + +/************************************************************************** +* ISF_Desktop_fnBindToObject +*/ +static HRESULT WINAPI ISF_Desktop_fnBindToObject (IShellFolder2 * iface, + LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); + + return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut); +} + +/************************************************************************** +* ISF_Desktop_fnBindToStorage +*/ +static HRESULT WINAPI ISF_Desktop_fnBindToStorage (IShellFolder2 * iface, + LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); + + *ppvOut = NULL; + return E_NOTIMPL; +} + +/************************************************************************** +* ISF_Desktop_fnCompareIDs +*/ + +static HRESULT WINAPI ISF_Desktop_fnCompareIDs (IShellFolder2 * iface, + LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + int nReturn; + + TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); + nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); + TRACE ("-- %i\n", nReturn); + return nReturn; +} + +/************************************************************************** +* ISF_Desktop_fnCreateViewObject +*/ +static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface, + HWND hwndOwner, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + LPSHELLVIEW pShellView; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IDropTarget)) { + WARN ("IDropTarget not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID (riid, &IID_IContextMenu)) { + WARN ("IContextMenu not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID (riid, &IID_IShellView)) { + pShellView = IShellView_Constructor ((IShellFolder *) iface); + if (pShellView) { + hr = IShellView_QueryInterface (pShellView, riid, ppvOut); + IShellView_Release (pShellView); + } + } + } + TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); + return hr; +} + +/************************************************************************** +* ISF_Desktop_fnGetAttributesOf +*/ +static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface, + UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + HRESULT hr = S_OK; + + TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + + if ((!cidl) || (!apidl) || (!rgfInOut)) + return E_INVALIDARG; + + if (*rgfInOut == 0) + *rgfInOut = ~0; + + while (cidl > 0 && *apidl) { + pdump (*apidl); + SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); + apidl++; + cidl--; + } + + TRACE ("-- result=0x%08lx\n", *rgfInOut); + + return hr; +} + +/************************************************************************** +* ISF_Desktop_fnGetUIObjectOf +* +* PARAMETERS +* HWND hwndOwner, //[in ] Parent window for any output +* UINT cidl, //[in ] array size +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* REFIID riid, //[in ] Requested Interface +* UINT* prgfInOut, //[ ] reserved +* LPVOID* ppvObject) //[out] Resulting Interface +* +*/ +static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface, + HWND hwndOwner, + UINT cidl, + LPCITEMIDLIST * apidl, + REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + LPITEMIDLIST pidl; + IUnknown *pObj = NULL; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", + This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IContextMenu)) { + pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { + pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { + hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); + } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) + && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); + SHFree (pidl); + } else { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr) && !pObj) + hr = E_OUTOFMEMORY; + + *ppvOut = pObj; + } + TRACE ("(%p)->hr=0x%08lx\n", This, hr); + return hr; +} + +/************************************************************************** +* ISF_Desktop_fnGetDisplayNameOf +* +* NOTES +* special case: pidl = null gives desktop-name back +*/ +static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface, + LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + CHAR szPath[MAX_PATH]; + GUID const *clsid; + HRESULT hr = S_OK; + + *szPath = '\0'; + + TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); + pdump (pidl); + + if (!strRet) + return E_INVALIDARG; + + if (_ILIsDesktop (pidl)) { + if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)) { + lstrcpyA (szPath, This->sPathTarget); + } else { + HCR_GetClassNameA(&CLSID_ShellDesktop, szPath, MAX_PATH); + } + } else if (_ILIsPidlSimple (pidl)) { + if ((clsid = _ILGetGUIDPointer (pidl))) { + if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) { + int bWantsForParsing; + + /* + * we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in + * CLSID\\{...}\\shellfolder exists + * exception: the MyComputer folder has this keys not but like any filesystem backed + * folder it needs these behaviour + */ + if (IsEqualIID (clsid, &CLSID_MyComputer)) { + bWantsForParsing = 1; + } else { + /* get the "WantsFORPARSING" flag from the registry */ + char szRegPath[100]; + + lstrcpyA (szRegPath, "CLSID\\"); + SHELL32_GUIDToStringA (clsid, &szRegPath[6]); + lstrcatA (szRegPath, "\\shellfolder"); + bWantsForParsing = + (ERROR_SUCCESS == + SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL)); + } + + if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) { + /* we need the filesystem path to the destination folder. Only the folder itself can know it */ + hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); + } else { + /* parsing name like ::{...} */ + lstrcpyA (szPath, "::"); + SHELL32_GUIDToStringA (clsid, &szPath[2]); + } + } else { + /* user friendly name */ + HCR_GetClassNameA (clsid, szPath, MAX_PATH); + } + } else { + /* file system folder */ + _ILSimpleGetText (pidl, szPath, MAX_PATH); + + if (!_ILIsFolder(pidl)) + SHELL_FS_ProcessDisplayFilename(szPath, dwFlags); + } + } else { + /* a complex pidl, let the subfolder do the work */ + hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); + } + + if (SUCCEEDED (hr)) { + strRet->uType = STRRET_CSTR; + lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); + } + + TRACE ("-- (%p)->(%s,0x%08lx)\n", This, szPath, hr); + return hr; +} + +/************************************************************************** +* ISF_Desktop_fnSetNameOf +* Changes the name of a file object or subfolder, possibly changing its item +* identifier in the process. +* +* PARAMETERS +* HWND hwndOwner, //[in ] Owner window for output +* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change +* LPCOLESTR lpszName, //[in ] the items new display name +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned +*/ +static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ + LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); + + return E_FAIL; +} + +static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_Desktop_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn (IShellFolder2 * iface, + DWORD dwRes, ULONG * pSort, ULONG * pDisplay) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)\n", This); + + if (pSort) + *pSort = 0; + if (pDisplay) + *pDisplay = 0; + + return S_OK; +} +static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)\n", This); + + if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + *pcsFlags = DesktopSFHeader[iColumn].pcsFlags; + + return S_OK; +} +static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx (IShellFolder2 * iface, + LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface, + LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + HRESULT hr = E_FAIL; + + TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); + + if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + if (!pidl) { + psd->fmt = DesktopSFHeader[iColumn].fmt; + psd->cxChar = DesktopSFHeader[iColumn].cxChar; + psd->str.uType = STRRET_CSTR; + LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); + return S_OK; + } else { + /* the data from the pidl */ + switch (iColumn) { + case 0: /* name */ + hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); + break; + case 1: /* size */ + _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 2: /* type */ + _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 3: /* date */ + _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 4: /* attributes */ + _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); + break; + } + hr = S_OK; + psd->str.uType = STRRET_CSTR; + } + + return hr; +} +static HRESULT WINAPI ISF_Desktop_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} + +static IShellFolder2Vtbl vt_MCFldr_ShellFolder2 = +{ + ISF_Desktop_fnQueryInterface, + ISF_Desktop_fnAddRef, + ISF_Desktop_fnRelease, + ISF_Desktop_fnParseDisplayName, + ISF_Desktop_fnEnumObjects, + ISF_Desktop_fnBindToObject, + ISF_Desktop_fnBindToStorage, + ISF_Desktop_fnCompareIDs, + ISF_Desktop_fnCreateViewObject, + ISF_Desktop_fnGetAttributesOf, + ISF_Desktop_fnGetUIObjectOf, + ISF_Desktop_fnGetDisplayNameOf, + ISF_Desktop_fnSetNameOf, + /* ShellFolder2 */ + ISF_Desktop_fnGetDefaultSearchGUID, + ISF_Desktop_fnEnumSearches, + ISF_Desktop_fnGetDefaultColumn, + ISF_Desktop_fnGetDefaultColumnState, + ISF_Desktop_fnGetDetailsEx, + ISF_Desktop_fnGetDetailsOf, + ISF_Desktop_fnMapColumnToSCID}; diff --git a/reactos/lib/shell32/shfldr_fs.c b/reactos/lib/shell32/shfldr_fs.c index d7ef8381b43..858628540a4 100644 --- a/reactos/lib/shell32/shfldr_fs.c +++ b/reactos/lib/shell32/shfldr_fs.c @@ -1,1399 +1,1399 @@ - -/* - * file system folder - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "ole2.h" -#include "shlguid.h" - -#include "enumidlist.h" -#include "pidl.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "shellfolder.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL (shell); - -/*********************************************************************** -* IShellFolder implementation -*/ - -typedef struct { - IUnknownVtbl *lpVtbl; - DWORD ref; - IShellFolder2Vtbl *lpvtblShellFolder; - IPersistFolder3Vtbl *lpvtblPersistFolder3; - IDropTargetVtbl *lpvtblDropTarget; - ISFHelperVtbl *lpvtblSFHelper; - - IUnknown *pUnkOuter; /* used for aggregation */ - - CLSID *pclsid; - - /* both paths are parsible from the desktop */ - LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ - - LPITEMIDLIST pidlRoot; /* absolute pidl */ - - int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ - - UINT cfShellIDList; /* clipboardformat for IDropTarget */ - BOOL fAcceptFmt; /* flag for pending Drop */ -} IGenericSFImpl; - -static struct IUnknownVtbl unkvt; -static struct IShellFolder2Vtbl sfvt; -static struct IPersistFolder3Vtbl vt_FSFldr_PersistFolder3; /* IPersistFolder3 for a FS_Folder */ -static struct IDropTargetVtbl dtvt; -static struct ISFHelperVtbl shvt; - -#define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder))) -#define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset); - -#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3))) -#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); - -#define _IPersistFolder3_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3))) -#define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder3_Offset); - -#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget))) -#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); - -#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper))) -#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset); - -/* - converts This to a interface pointer -*/ -#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder) -#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder) -#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder3) -#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder3) -#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3) -#define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3) -#define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget) -#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper) - -/************************************************************************** -* registers clipboardformat once -*/ -static void SF_RegisterClipFmt (IGenericSFImpl * This) -{ - TRACE ("(%p)\n", This); - - if (!This->cfShellIDList) { - This->cfShellIDList = RegisterClipboardFormatA (CFSTR_SHELLIDLIST); - } -} - -/************************************************************************** -* we need a separate IUnknown to handle aggregation -* (inner IUnknown) -*/ -static HRESULT WINAPI IUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppvObj) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - *ppvObj = NULL; - - if (IsEqualIID (riid, &IID_IUnknown)) - *ppvObj = _IUnknown_ (This); - else if (IsEqualIID (riid, &IID_IShellFolder)) - *ppvObj = _IShellFolder_ (This); - else if (IsEqualIID (riid, &IID_IShellFolder2)) - *ppvObj = _IShellFolder_ (This); - else if (IsEqualIID (riid, &IID_IPersist)) - *ppvObj = _IPersist_ (This); - else if (IsEqualIID (riid, &IID_IPersistFolder)) - *ppvObj = _IPersistFolder_ (This); - else if (IsEqualIID (riid, &IID_IPersistFolder2)) - *ppvObj = _IPersistFolder2_ (This); - else if (IsEqualIID (riid, &IID_IPersistFolder3)) - *ppvObj = _IPersistFolder3_ (This); - else if (IsEqualIID (riid, &IID_ISFHelper)) - *ppvObj = _ISFHelper_ (This); - else if (IsEqualIID (riid, &IID_IDropTarget)) { - *ppvObj = _IDropTarget_ (This); - SF_RegisterClipFmt (This); - } - - if (*ppvObj) { - IUnknown_AddRef ((IUnknown *) (*ppvObj)); - TRACE ("-- Interface = %p\n", *ppvObj); - return S_OK; - } - TRACE ("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return ++(This->ref); -} - -static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - if (!--(This->ref)) { - TRACE ("-- destroying IShellFolder(%p)\n", This); - - if (This->pidlRoot) - SHFree (This->pidlRoot); - if (This->sPathTarget) - SHFree (This->sPathTarget); - LocalFree ((HLOCAL) This); - return 0; - } - return This->ref; -} - -static IUnknownVtbl unkvt = -{ - IUnknown_fnQueryInterface, - IUnknown_fnAddRef, - IUnknown_fnRelease, -}; - -static shvheader GenericSFHeader[] = { - {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, - {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}, - {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5} -}; - -#define GENERICSHELLVIEWCOLUMNS 5 - -/************************************************************************** -* IFSFolder_Constructor -* -* NOTES -* creating undocumented ShellFS_Folder as part of an aggregation -* {F3364BA0-65B9-11CE-A9BA-00AA004AE837} -* -*/ -HRESULT WINAPI IFSFolder_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) -{ - IGenericSFImpl *sf; - - TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); - - if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) - return CLASS_E_NOAGGREGATION; - sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); - if (!sf) - return E_OUTOFMEMORY; - - sf->ref = 0; - sf->lpVtbl = &unkvt; - sf->lpvtblShellFolder = &sfvt; - sf->lpvtblPersistFolder3 = &vt_FSFldr_PersistFolder3; - sf->lpvtblDropTarget = &dtvt; - sf->lpvtblSFHelper = &shvt; - sf->pclsid = (CLSID *) & CLSID_ShellFSFolder; - sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf); - - if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { - IUnknown_Release (_IUnknown_ (sf)); - return E_NOINTERFACE; - } - - TRACE ("--%p\n", *ppv); - return S_OK; -} - -/************************************************************************** - * IShellFolder_fnQueryInterface - * - * PARAMETERS - * REFIID riid [in ] Requested InterfaceID - * LPVOID* ppvObject [out] Interface* to hold the result - */ -static HRESULT WINAPI IShellFolder_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); -} - -/************************************************************************** -* IShellFolder_AddRef -*/ - -static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef (This->pUnkOuter); -} - -/************************************************************************** - * IShellFolder_fnRelease - */ -static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_Release (This->pUnkOuter); -} - -/************************************************************************** -* IShellFolder_ParseDisplayName {SHELL32} -* -* Parse a display name. -* -* PARAMS -* hwndOwner [in] Parent window for any message's -* pbc [in] optional FileSystemBindData context -* lpszDisplayName [in] Unicode displayname. -* pchEaten [out] (unicode) characters processed -* ppidl [out] complex pidl to item -* pdwAttributes [out] items attributes -* -* NOTES -* Every folder tries to parse only its own (the leftmost) pidl and creates a -* subfolder to evaluate the remaining parts. -* Now we can parse into namespaces implemented by shell extensions -* -* Behaviour on win98: lpszDisplayName=NULL -> crash -* lpszDisplayName="" -> returns mycoputer-pidl -* -* FIXME -* pdwAttributes is not set -* pchEaten is not set like in windows -*/ -static HRESULT WINAPI -IShellFolder_fnParseDisplayName (IShellFolder2 * iface, - HWND hwndOwner, - LPBC pbc, - LPOLESTR lpszDisplayName, - DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - HRESULT hr = E_INVALIDARG; - LPCWSTR szNext = NULL; - WCHAR szElement[MAX_PATH]; - CHAR szPath[MAX_PATH]; - LPITEMIDLIST pidlTemp = NULL; - DWORD len; - - TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", - This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); - - if (!lpszDisplayName || !ppidl) - return E_INVALIDARG; - - if (pchEaten) - *pchEaten = 0; /* strange but like the original */ - - if (*lpszDisplayName) { - /* get the next element */ - szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - - /* build the full pathname to the element */ - lstrcpyA(szPath, This->sPathTarget); - PathAddBackslashA(szPath); - len = lstrlenA(szPath); - WideCharToMultiByte(CP_ACP, 0, szElement, -1, szPath + len, MAX_PATH - len, NULL, NULL); - - /* get the pidl */ - hr = _ILCreateFromPathA(szPath, &pidlTemp); - - if (SUCCEEDED(hr)) { - if (szNext && *szNext) { - /* try to analyse the next element */ - hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); - } else { - /* it's the last element */ - if (pdwAttributes && *pdwAttributes) { - hr = SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); - } - } - } - } - - if (SUCCEEDED(hr)) - *ppidl = pidlTemp; - else - *ppidl = NULL; - - TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl ? *ppidl : 0, hr); - - return hr; -} - -/************************************************************************** -* IShellFolder_fnEnumObjects -* PARAMETERS -* HWND hwndOwner, //[in ] Parent Window -* DWORD grfFlags, //[in ] SHCONTF enumeration mask -* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface -*/ -static HRESULT WINAPI -IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); - - *ppEnumIDList = IEnumIDList_Constructor(); - if (*ppEnumIDList) - CreateFolderEnumList(*ppEnumIDList, This->sPathTarget, dwFlags); - - TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); - - return *ppEnumIDList ? S_OK : E_OUTOFMEMORY; -} - -/************************************************************************** -* IShellFolder_fnBindToObject -* PARAMETERS -* LPCITEMIDLIST pidl, //[in ] relative pidl to open -* LPBC pbc, //[in ] optional FileSystemBindData context -* REFIID riid, //[in ] Initial Interface -* LPVOID* ppvObject //[out] Interface* -*/ -static HRESULT WINAPI -IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, LPVOID * ppvOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbc, shdebugstr_guid (riid), ppvOut); - - return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut); -} - -/************************************************************************** -* IShellFolder_fnBindToStorage -* PARAMETERS -* LPCITEMIDLIST pidl, //[in ] complex pidl to store -* LPBC pbc, //[in ] reserved -* REFIID riid, //[in ] Initial storage interface -* LPVOID* ppvObject //[out] Interface* returned -*/ -static HRESULT WINAPI -IShellFolder_fnBindToStorage (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); - - *ppvOut = NULL; - return E_NOTIMPL; -} - -/************************************************************************** -* IShellFolder_fnCompareIDs -*/ - -static HRESULT WINAPI -IShellFolder_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - int nReturn; - - TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); - nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); - TRACE ("-- %i\n", nReturn); - return nReturn; -} - -/************************************************************************** -* IShellFolder_fnCreateViewObject -*/ -static HRESULT WINAPI -IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - LPSHELLVIEW pShellView; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IDropTarget)) { - hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, ppvOut); - } else if (IsEqualIID (riid, &IID_IContextMenu)) { - FIXME ("IContextMenu not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID (riid, &IID_IShellView)) { - pShellView = IShellView_Constructor ((IShellFolder *) iface); - if (pShellView) { - hr = IShellView_QueryInterface (pShellView, riid, ppvOut); - IShellView_Release (pShellView); - } - } - } - TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); - return hr; -} - -/************************************************************************** -* IShellFolder_fnGetAttributesOf -* -* PARAMETERS -* UINT cidl, //[in ] num elements in pidl array -* LPCITEMIDLIST* apidl, //[in ] simple pidl array -* ULONG* rgfInOut) //[out] result array -* -*/ -static HRESULT WINAPI -IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - HRESULT hr = S_OK; - - TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); - - if ((!cidl) || (!apidl) || (!rgfInOut)) - return E_INVALIDARG; - - if (*rgfInOut == 0) - *rgfInOut = ~0; - - while (cidl > 0 && *apidl) { - pdump (*apidl); - SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); - apidl++; - cidl--; - } - - TRACE ("-- result=0x%08lx\n", *rgfInOut); - - return hr; -} - -/************************************************************************** -* IShellFolder_fnGetUIObjectOf -* -* PARAMETERS -* HWND hwndOwner, //[in ] Parent window for any output -* UINT cidl, //[in ] array size -* LPCITEMIDLIST* apidl, //[in ] simple pidl array -* REFIID riid, //[in ] Requested Interface -* UINT* prgfInOut, //[ ] reserved -* LPVOID* ppvObject) //[out] Resulting Interface -* -* NOTES -* This function gets asked to return "view objects" for one or more (multiple select) -* items: -* The viewobject typically is an COM object with one of the following interfaces: -* IExtractIcon,IDataObject,IContextMenu -* In order to support icon positions in the default Listview your DataObject -* must implement the SetData method (in addition to GetData :) - the shell passes -* a barely documented "Icon positions" structure to SetData when the drag starts, -* and GetData's it if the drop is in another explorer window that needs the positions. -*/ -static HRESULT WINAPI -IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface, - HWND hwndOwner, - UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - LPITEMIDLIST pidl; - IUnknown *pObj = NULL; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", - This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { - pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { - pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { - hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); - } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) - && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); - SHFree (pidl); - } else { - hr = E_NOINTERFACE; - } - - if (SUCCEEDED(hr) && !pObj) - hr = E_OUTOFMEMORY; - - *ppvOut = pObj; - } - TRACE ("(%p)->hr=0x%08lx\n", This, hr); - return hr; -} - -void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags) -{ - /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */ - if (!(dwFlags & SHGDN_FORPARSING) && - ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) { - HKEY hKey; - DWORD dwData; - DWORD dwDataSize = sizeof (DWORD); - BOOL doHide = FALSE; /* The default value is FALSE (win98 at least) */ - - if (!RegCreateKeyExA (HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", - 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) { - if (!RegQueryValueExA (hKey, "HideFileExt", 0, 0, (LPBYTE) & dwData, &dwDataSize)) - doHide = dwData; - - RegCloseKey (hKey); - } - - if (!doHide) { - LPSTR ext = PathFindExtensionA(szPath); - - if (ext) { - HKEY hkey; - char classname[MAX_PATH]; - LONG classlen = MAX_PATH; - - if (!RegQueryValueA(HKEY_CLASSES_ROOT, ext, classname, &classlen)) - if (!RegOpenKeyA(HKEY_CLASSES_ROOT, classname, &hkey)) { - if (!RegQueryValueExA(hkey, "NeverShowExt", 0, NULL, NULL, NULL)) - doHide = TRUE; - - RegCloseKey(hkey); - } - } - } - - if (doHide && szPath[0] != '.') - PathRemoveExtensionA (szPath); - } -} - -/************************************************************************** -* IShellFolder_fnGetDisplayNameOf -* Retrieves the display name for the specified file object or subfolder -* -* PARAMETERS -* LPCITEMIDLIST pidl, //[in ] complex pidl to item -* DWORD dwFlags, //[in ] SHGNO formatting flags -* LPSTRRET lpName) //[out] Returned display name -* -* FIXME -* if the name is in the pidl the ret value should be a STRRET_OFFSET -*/ - -static HRESULT WINAPI -IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - CHAR szPath[MAX_PATH]; - int len = 0; - BOOL bSimplePidl; - - *szPath = '\0'; - - TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); - pdump (pidl); - - if (!pidl || !strRet) - return E_INVALIDARG; - - bSimplePidl = _ILIsPidlSimple (pidl); - - /* take names of special folders only if its only this folder */ - if (_ILIsSpecialFolder (pidl)) { - if (bSimplePidl) { - _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ - } else { - FIXME ("special pidl\n"); - } - } else { - if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathTarget) { - lstrcpyA (szPath, This->sPathTarget); /* get path to root */ - PathAddBackslashA (szPath); - len = lstrlenA (szPath); - } - _ILSimpleGetText (pidl, szPath + len, MAX_PATH - len); /* append my own path */ - - if (!_ILIsFolder(pidl)) - SHELL_FS_ProcessDisplayFilename(szPath, dwFlags); - } - - if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */ - PathAddBackslashA (szPath); - len = lstrlenA (szPath); - - if (!SUCCEEDED - (SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len))) - return E_OUTOFMEMORY; - } - strRet->uType = STRRET_CSTR; - lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); - - TRACE ("-- (%p)->(%s)\n", This, szPath); - return S_OK; -} - -/************************************************************************** -* IShellFolder_fnSetNameOf -* Changes the name of a file object or subfolder, possibly changing its item -* identifier in the process. -* -* PARAMETERS -* HWND hwndOwner, //[in ] Owner window for output -* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change -* LPCOLESTR lpszName, //[in ] the items new display name -* DWORD dwFlags, //[in ] SHGNO formatting flags -* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned -*/ -static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ - LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - char szSrc[MAX_PATH], - szDest[MAX_PATH]; - int len; - BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); - - TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); - - /* build source path */ - if (dwFlags & SHGDN_INFOLDER) { - strcpy (szSrc, This->sPathTarget); - PathAddBackslashA (szSrc); - len = strlen (szSrc); - _ILSimpleGetText (pidl, szSrc + len, MAX_PATH - len); - } else { - /* FIXME: Can this work with a simple PIDL? */ - SHGetPathFromIDListA (pidl, szSrc); - } - - /* build destination path */ - strcpy (szDest, This->sPathTarget); - PathAddBackslashA (szDest); - len = strlen (szDest); - WideCharToMultiByte (CP_ACP, 0, lpName, -1, szDest + len, MAX_PATH - len, NULL, NULL); - szDest[MAX_PATH - 1] = 0; - TRACE ("src=%s dest=%s\n", szSrc, szDest); - if (MoveFileA (szSrc, szDest)) { - HRESULT hr = S_OK; - - if (pPidlOut) - hr = _ILCreateFromPathA(szDest, pPidlOut); - - SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest); - - return hr; - } - - return E_FAIL; -} - -static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI IShellFolder_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI -IShellFolder_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)\n", This); - - if (pSort) - *pSort = 0; - if (pDisplay) - *pDisplay = 0; - - return S_OK; -} -static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - - TRACE ("(%p)\n", This); - - if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - *pcsFlags = GenericSFHeader[iColumn].pcsFlags; - - return S_OK; -} -static HRESULT WINAPI -IShellFolder_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - FIXME ("(%p)\n", This); - - return E_NOTIMPL; -} -static HRESULT WINAPI -IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - HRESULT hr = E_FAIL; - - TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); - - if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - if (!pidl) { - /* the header titles */ - psd->fmt = GenericSFHeader[iColumn].fmt; - psd->cxChar = GenericSFHeader[iColumn].cxChar; - psd->str.uType = STRRET_CSTR; - LoadStringA (shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); - return S_OK; - } else { - /* the data from the pidl */ - switch (iColumn) { - case 0: /* name */ - hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); - break; - case 1: /* size */ - _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 2: /* type */ - _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 3: /* date */ - _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 4: /* attributes */ - _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); - break; - } - hr = S_OK; - psd->str.uType = STRRET_CSTR; - } - - return hr; -} -static HRESULT WINAPI IShellFolder_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) -{ - _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} - -static IShellFolder2Vtbl sfvt = -{ - IShellFolder_fnQueryInterface, - IShellFolder_fnAddRef, - IShellFolder_fnRelease, - IShellFolder_fnParseDisplayName, - IShellFolder_fnEnumObjects, - IShellFolder_fnBindToObject, - IShellFolder_fnBindToStorage, - IShellFolder_fnCompareIDs, - IShellFolder_fnCreateViewObject, - IShellFolder_fnGetAttributesOf, - IShellFolder_fnGetUIObjectOf, - IShellFolder_fnGetDisplayNameOf, - IShellFolder_fnSetNameOf, - /* ShellFolder2 */ - IShellFolder_fnGetDefaultSearchGUID, - IShellFolder_fnEnumSearches, - IShellFolder_fnGetDefaultColumn, - IShellFolder_fnGetDefaultColumnState, - IShellFolder_fnGetDetailsEx, - IShellFolder_fnGetDetailsOf, - IShellFolder_fnMapColumnToSCID -}; - -/**************************************************************************** - * ISFHelper for IShellFolder implementation - */ - -static HRESULT WINAPI ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); -} - -static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef (This->pUnkOuter); -} - -static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_Release (This->pUnkOuter); -} - -/**************************************************************************** - * ISFHelper_fnAddFolder - * - * creates a unique folder name - */ - -static HRESULT WINAPI ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) - IEnumIDList *penum; - HRESULT hr; - char szText[MAX_PATH]; - char *szNewFolder = "New Folder"; - - TRACE ("(%p)(%s %u)\n", This, lpName, uLen); - - if (uLen < strlen (szNewFolder) + 4) - return E_POINTER; - - strcpy (lpName, szNewFolder); - - hr = IShellFolder_fnEnumObjects (_IShellFolder2_ (This), 0, - SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); - if (penum) { - LPITEMIDLIST pidl; - DWORD dwFetched; - int i = 1; - - next:IEnumIDList_Reset (penum); - while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && dwFetched) { - _ILSimpleGetText (pidl, szText, MAX_PATH); - if (0 == strcasecmp (szText, lpName)) { - sprintf (lpName, "%s %d", szNewFolder, i++); - if (i > 99) { - hr = E_FAIL; - break; - } - goto next; - } - } - - IEnumIDList_Release (penum); - } - return hr; -} - -/**************************************************************************** - * ISFHelper_fnAddFolder - * - * adds a new folder. - */ - -static HRESULT WINAPI ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) - char lpstrNewDir[MAX_PATH]; - DWORD bRes; - HRESULT hres = E_FAIL; - - TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut); - - strcpy (lpstrNewDir, This->sPathTarget); - PathAppendA(lpstrNewDir, lpName); - - bRes = CreateDirectoryA (lpstrNewDir, NULL); - if (bRes) { - SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHA, lpstrNewDir, NULL); - - hres = S_OK; - - if (ppidlOut) - hres = _ILCreateFromPathA(lpstrNewDir, ppidlOut); - } else { - char lpstrText[128 + MAX_PATH]; - char lpstrTempText[128]; - char lpstrCaption[256]; - - /* Cannot Create folder because of permissions */ - LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof (lpstrTempText)); - LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof (lpstrCaption)); - sprintf (lpstrText, lpstrTempText, lpstrNewDir); - MessageBoxA (hwnd, lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION); - } - - return hres; -} - -/**************************************************************************** - * ISFHelper_fnDeleteItems - * - * deletes items in folder - */ -static HRESULT WINAPI ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) -{ - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) - UINT i; - char szPath[MAX_PATH]; - BOOL bConfirm = TRUE; - - TRACE ("(%p)(%u %p)\n", This, cidl, apidl); - - /* deleting multiple items so give a slightly different warning */ - if (cidl != 1) { - char tmp[8]; - - snprintf (tmp, sizeof (tmp), "%d", cidl); - if (!SHELL_ConfirmDialog(ASK_DELETE_MULTIPLE_ITEM, tmp)) - return E_FAIL; - bConfirm = FALSE; - } - - for (i = 0; i < cidl; i++) { - strcpy (szPath, This->sPathTarget); - PathAddBackslashA (szPath); - _ILSimpleGetText (apidl[i], szPath + strlen (szPath), MAX_PATH); - - if (_ILIsFolder (apidl[i])) { - LPITEMIDLIST pidl; - - TRACE ("delete %s\n", szPath); - if (!SHELL_DeleteDirectoryA (szPath, bConfirm)) { - TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm); - return E_FAIL; - } - pidl = ILCombine (This->pidlRoot, apidl[i]); - SHChangeNotify (SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL); - SHFree (pidl); - } else if (_ILIsValue (apidl[i])) { - LPITEMIDLIST pidl; - - TRACE ("delete %s\n", szPath); - if (!SHELL_DeleteFileA (szPath, bConfirm)) { - TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm); - return E_FAIL; - } - pidl = ILCombine (This->pidlRoot, apidl[i]); - SHChangeNotify (SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL); - SHFree (pidl); - } - - } - return S_OK; -} - -/**************************************************************************** - * ISFHelper_fnCopyItems - * - * copies items to this folder - */ -static HRESULT WINAPI -ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) -{ - UINT i; - IPersistFolder2 *ppf2 = NULL; - char szSrcPath[MAX_PATH], - szDstPath[MAX_PATH]; - - _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); - - TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl); - - IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2); - if (ppf2) { - LPITEMIDLIST pidl; - - if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) { - for (i = 0; i < cidl; i++) { - SHGetPathFromIDListA (pidl, szSrcPath); - PathAddBackslashA (szSrcPath); - _ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath), MAX_PATH); - - strcpy (szDstPath, This->sPathTarget); - PathAddBackslashA (szDstPath); - _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH); - MESSAGE ("would copy %s to %s\n", szSrcPath, szDstPath); - } - SHFree (pidl); - } - IPersistFolder2_Release (ppf2); - } - return S_OK; -} - -static ISFHelperVtbl shvt = -{ - ISFHelper_fnQueryInterface, - ISFHelper_fnAddRef, - ISFHelper_fnRelease, - ISFHelper_fnGetUniqueName, - ISFHelper_fnAddFolder, - ISFHelper_fnDeleteItems, - ISFHelper_fnCopyItems -}; - -/************************************************************************ - * IFSFldr_PersistFolder3_QueryInterface - * - */ -static HRESULT WINAPI IFSFldr_PersistFolder3_QueryInterface (IPersistFolder3 * iface, REFIID iid, LPVOID * ppvObj) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_QueryInterface (This->pUnkOuter, iid, ppvObj); -} - -/************************************************************************ - * IFSFldr_PersistFolder3_AddRef - * - */ -static ULONG WINAPI IFSFldr_PersistFolder3_AddRef (IPersistFolder3 * iface) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef (This->pUnkOuter); -} - -/************************************************************************ - * IFSFldr_PersistFolder3_Release - * - */ -static ULONG WINAPI IFSFldr_PersistFolder3_Release (IPersistFolder3 * iface) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_Release (This->pUnkOuter); -} - -/************************************************************************ - * IFSFldr_PersistFolder3_GetClassID - */ -static HRESULT WINAPI IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - if (!lpClassId) - return E_POINTER; - *lpClassId = *This->pclsid; - - return S_OK; -} - -/************************************************************************ - * IFSFldr_PersistFolder3_Initialize - * - * NOTES - * sPathTarget is not set. Don't know how to handle in a non rooted environment. - */ -static HRESULT WINAPI IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl) -{ - char sTemp[MAX_PATH]; - - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)->(%p)\n", This, pidl); - - if (This->pidlRoot) - SHFree (This->pidlRoot); /* free the old pidl */ - This->pidlRoot = ILClone (pidl); /* set my pidl */ - - if (This->sPathTarget) - SHFree (This->sPathTarget); - - /* set my path */ - if (SHGetPathFromIDListA (pidl, sTemp)) { - This->sPathTarget = SHAlloc (strlen (sTemp) + 1); - strcpy (This->sPathTarget, sTemp); - } - - TRACE ("--(%p)->(%s)\n", This, This->sPathTarget); - return S_OK; -} - -/************************************************************************** - * IFSFldr_PersistFolder3_GetCurFolder - */ -static HRESULT WINAPI IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3 * iface, LPITEMIDLIST * pidl) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)->(%p)\n", This, pidl); - - if (!pidl) return E_POINTER; - *pidl = ILClone (This->pidlRoot); - return S_OK; -} - -/************************************************************************** - * IFSFldr_PersistFolder3_InitializeEx - * - * FIXME: errorhandling - */ -static HRESULT WINAPI -IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface, - IBindCtx * pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO * ppfti) -{ - char sTemp[MAX_PATH]; - - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - - TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti); - if (ppfti) - TRACE ("--%p %s %s 0x%08lx 0x%08x\n", - ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName), - debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl); - - pdump (pidlRoot); - if (ppfti && ppfti->pidlTargetFolder) - pdump (ppfti->pidlTargetFolder); - - if (This->pidlRoot) - __SHFreeAndNil (&This->pidlRoot); /* free the old */ - if (This->sPathTarget) - __SHFreeAndNil (&This->sPathTarget); - - /* - * Root path and pidl - */ - This->pidlRoot = ILClone (pidlRoot); - - /* - * the target folder is spezified in csidl OR pidlTargetFolder OR szTargetParsingName - */ - if (ppfti) { - if (ppfti->csidl != -1) { - if (SHGetSpecialFolderPathA (0, sTemp, ppfti->csidl, ppfti->csidl & CSIDL_FLAG_CREATE)) { - __SHCloneStrA (&This->sPathTarget, sTemp); - } - } else if (ppfti->szTargetParsingName[0]) { - __SHCloneStrWtoA (&This->sPathTarget, ppfti->szTargetParsingName); - } else if (ppfti->pidlTargetFolder) { - if (SHGetPathFromIDListA (ppfti->pidlTargetFolder, sTemp)) { - __SHCloneStrA (&This->sPathTarget, sTemp); - } - } - } - - TRACE ("--(%p)->(target=%s)\n", This, debugstr_a (This->sPathTarget)); - pdump (This->pidlRoot); - return (This->sPathTarget) ? S_OK : E_FAIL; -} - -static HRESULT WINAPI -IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3 * iface, PERSIST_FOLDER_TARGET_INFO * ppfti) -{ - _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); - FIXME ("(%p)->(%p)\n", This, ppfti); - ZeroMemory (ppfti, sizeof (ppfti)); - return E_NOTIMPL; -} - -static IPersistFolder3Vtbl vt_FSFldr_PersistFolder3 = -{ - IFSFldr_PersistFolder3_QueryInterface, - IFSFldr_PersistFolder3_AddRef, - IFSFldr_PersistFolder3_Release, - IFSFldr_PersistFolder3_GetClassID, - IFSFldr_PersistFolder3_Initialize, - IFSFldr_PersistFolder3_fnGetCurFolder, - IFSFldr_PersistFolder3_InitializeEx, - IFSFldr_PersistFolder3_GetFolderTargetInfo -}; - -/**************************************************************************** - * ISFDropTarget implementation - */ -static BOOL ISFDropTarget_QueryDrop (IDropTarget * iface, DWORD dwKeyState, LPDWORD pdwEffect) -{ - DWORD dwEffect = *pdwEffect; - - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - *pdwEffect = DROPEFFECT_NONE; - - if (This->fAcceptFmt) { /* Does our interpretation of the keystate ... */ - *pdwEffect = KeyStateToDropEffect (dwKeyState); - - /* ... matches the desired effect ? */ - if (dwEffect & *pdwEffect) { - return TRUE; - } - } - return FALSE; -} - -static HRESULT WINAPI ISFDropTarget_QueryInterface (IDropTarget * iface, REFIID riid, LPVOID * ppvObj) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); -} - -static ULONG WINAPI ISFDropTarget_AddRef (IDropTarget * iface) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_AddRef (This->pUnkOuter); -} - -static ULONG WINAPI ISFDropTarget_Release (IDropTarget * iface) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_Release (This->pUnkOuter); -} - -static HRESULT WINAPI -ISFDropTarget_DragEnter (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) -{ - FORMATETC fmt; - - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)->(DataObject=%p)\n", This, pDataObject); - - InitFormatEtc (fmt, This->cfShellIDList, TYMED_HGLOBAL); - - This->fAcceptFmt = (S_OK == IDataObject_QueryGetData (pDataObject, &fmt)) ? TRUE : FALSE; - - ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect); - - return S_OK; -} - -static HRESULT WINAPI ISFDropTarget_DragOver (IDropTarget * iface, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - if (!pdwEffect) - return E_INVALIDARG; - - ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect); - - return S_OK; -} - -static HRESULT WINAPI ISFDropTarget_DragLeave (IDropTarget * iface) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - This->fAcceptFmt = FALSE; - - return S_OK; -} - -static HRESULT WINAPI -ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) -{ - _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); - - FIXME ("(%p) object dropped\n", This); - - return E_NOTIMPL; -} - -static struct IDropTargetVtbl dtvt = { - ISFDropTarget_QueryInterface, - ISFDropTarget_AddRef, - ISFDropTarget_Release, - ISFDropTarget_DragEnter, - ISFDropTarget_DragOver, - ISFDropTarget_DragLeave, - ISFDropTarget_Drop -}; + +/* + * file system folder + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "ole2.h" +#include "shlguid.h" + +#include "enumidlist.h" +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "shellfolder.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +/*********************************************************************** +* IShellFolder implementation +*/ + +typedef struct { + IUnknownVtbl *lpVtbl; + DWORD ref; + IShellFolder2Vtbl *lpvtblShellFolder; + IPersistFolder3Vtbl *lpvtblPersistFolder3; + IDropTargetVtbl *lpvtblDropTarget; + ISFHelperVtbl *lpvtblSFHelper; + + IUnknown *pUnkOuter; /* used for aggregation */ + + CLSID *pclsid; + + /* both paths are parsible from the desktop */ + LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ + + LPITEMIDLIST pidlRoot; /* absolute pidl */ + + int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ + + UINT cfShellIDList; /* clipboardformat for IDropTarget */ + BOOL fAcceptFmt; /* flag for pending Drop */ +} IGenericSFImpl; + +static struct IUnknownVtbl unkvt; +static struct IShellFolder2Vtbl sfvt; +static struct IPersistFolder3Vtbl vt_FSFldr_PersistFolder3; /* IPersistFolder3 for a FS_Folder */ +static struct IDropTargetVtbl dtvt; +static struct ISFHelperVtbl shvt; + +#define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder))) +#define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset); + +#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3))) +#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); + +#define _IPersistFolder3_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3))) +#define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder3_Offset); + +#define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget))) +#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); + +#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper))) +#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset); + +/* + converts This to a interface pointer +*/ +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder) +#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder) +#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder3) +#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder3) +#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3) +#define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3) +#define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget) +#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper) + +/************************************************************************** +* registers clipboardformat once +*/ +static void SF_RegisterClipFmt (IGenericSFImpl * This) +{ + TRACE ("(%p)\n", This); + + if (!This->cfShellIDList) { + This->cfShellIDList = RegisterClipboardFormatA (CFSTR_SHELLIDLIST); + } +} + +/************************************************************************** +* we need a separate IUnknown to handle aggregation +* (inner IUnknown) +*/ +static HRESULT WINAPI IUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppvObj) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + *ppvObj = NULL; + + if (IsEqualIID (riid, &IID_IUnknown)) + *ppvObj = _IUnknown_ (This); + else if (IsEqualIID (riid, &IID_IShellFolder)) + *ppvObj = _IShellFolder_ (This); + else if (IsEqualIID (riid, &IID_IShellFolder2)) + *ppvObj = _IShellFolder_ (This); + else if (IsEqualIID (riid, &IID_IPersist)) + *ppvObj = _IPersist_ (This); + else if (IsEqualIID (riid, &IID_IPersistFolder)) + *ppvObj = _IPersistFolder_ (This); + else if (IsEqualIID (riid, &IID_IPersistFolder2)) + *ppvObj = _IPersistFolder2_ (This); + else if (IsEqualIID (riid, &IID_IPersistFolder3)) + *ppvObj = _IPersistFolder3_ (This); + else if (IsEqualIID (riid, &IID_ISFHelper)) + *ppvObj = _ISFHelper_ (This); + else if (IsEqualIID (riid, &IID_IDropTarget)) { + *ppvObj = _IDropTarget_ (This); + SF_RegisterClipFmt (This); + } + + if (*ppvObj) { + IUnknown_AddRef ((IUnknown *) (*ppvObj)); + TRACE ("-- Interface = %p\n", *ppvObj); + return S_OK; + } + TRACE ("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE ("-- destroying IShellFolder(%p)\n", This); + + if (This->pidlRoot) + SHFree (This->pidlRoot); + if (This->sPathTarget) + SHFree (This->sPathTarget); + LocalFree ((HLOCAL) This); + return 0; + } + return This->ref; +} + +static IUnknownVtbl unkvt = +{ + IUnknown_fnQueryInterface, + IUnknown_fnAddRef, + IUnknown_fnRelease, +}; + +static shvheader GenericSFHeader[] = { + {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, + {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}, + {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5} +}; + +#define GENERICSHELLVIEWCOLUMNS 5 + +/************************************************************************** +* IFSFolder_Constructor +* +* NOTES +* creating undocumented ShellFS_Folder as part of an aggregation +* {F3364BA0-65B9-11CE-A9BA-00AA004AE837} +* +*/ +HRESULT WINAPI IFSFolder_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) +{ + IGenericSFImpl *sf; + + TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); + + if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown)) + return CLASS_E_NOAGGREGATION; + sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); + if (!sf) + return E_OUTOFMEMORY; + + sf->ref = 0; + sf->lpVtbl = &unkvt; + sf->lpvtblShellFolder = &sfvt; + sf->lpvtblPersistFolder3 = &vt_FSFldr_PersistFolder3; + sf->lpvtblDropTarget = &dtvt; + sf->lpvtblSFHelper = &shvt; + sf->pclsid = (CLSID *) & CLSID_ShellFSFolder; + sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf); + + if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { + IUnknown_Release (_IUnknown_ (sf)); + return E_NOINTERFACE; + } + + TRACE ("--%p\n", *ppv); + return S_OK; +} + +/************************************************************************** + * IShellFolder_fnQueryInterface + * + * PARAMETERS + * REFIID riid [in ] Requested InterfaceID + * LPVOID* ppvObject [out] Interface* to hold the result + */ +static HRESULT WINAPI IShellFolder_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); +} + +/************************************************************************** +* IShellFolder_AddRef +*/ + +static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef (This->pUnkOuter); +} + +/************************************************************************** + * IShellFolder_fnRelease + */ +static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_Release (This->pUnkOuter); +} + +/************************************************************************** +* IShellFolder_ParseDisplayName {SHELL32} +* +* Parse a display name. +* +* PARAMS +* hwndOwner [in] Parent window for any message's +* pbc [in] optional FileSystemBindData context +* lpszDisplayName [in] Unicode displayname. +* pchEaten [out] (unicode) characters processed +* ppidl [out] complex pidl to item +* pdwAttributes [out] items attributes +* +* NOTES +* Every folder tries to parse only its own (the leftmost) pidl and creates a +* subfolder to evaluate the remaining parts. +* Now we can parse into namespaces implemented by shell extensions +* +* Behaviour on win98: lpszDisplayName=NULL -> crash +* lpszDisplayName="" -> returns mycoputer-pidl +* +* FIXME +* pdwAttributes is not set +* pchEaten is not set like in windows +*/ +static HRESULT WINAPI +IShellFolder_fnParseDisplayName (IShellFolder2 * iface, + HWND hwndOwner, + LPBC pbc, + LPOLESTR lpszDisplayName, + DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + HRESULT hr = E_INVALIDARG; + LPCWSTR szNext = NULL; + WCHAR szElement[MAX_PATH]; + CHAR szPath[MAX_PATH]; + LPITEMIDLIST pidlTemp = NULL; + DWORD len; + + TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", + This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); + + if (!lpszDisplayName || !ppidl) + return E_INVALIDARG; + + if (pchEaten) + *pchEaten = 0; /* strange but like the original */ + + if (*lpszDisplayName) { + /* get the next element */ + szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); + + /* build the full pathname to the element */ + lstrcpyA(szPath, This->sPathTarget); + PathAddBackslashA(szPath); + len = lstrlenA(szPath); + WideCharToMultiByte(CP_ACP, 0, szElement, -1, szPath + len, MAX_PATH - len, NULL, NULL); + + /* get the pidl */ + hr = _ILCreateFromPathA(szPath, &pidlTemp); + + if (SUCCEEDED(hr)) { + if (szNext && *szNext) { + /* try to analyse the next element */ + hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); + } else { + /* it's the last element */ + if (pdwAttributes && *pdwAttributes) { + hr = SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); + } + } + } + } + + if (SUCCEEDED(hr)) + *ppidl = pidlTemp; + else + *ppidl = NULL; + + TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl ? *ppidl : 0, hr); + + return hr; +} + +/************************************************************************** +* IShellFolder_fnEnumObjects +* PARAMETERS +* HWND hwndOwner, //[in ] Parent Window +* DWORD grfFlags, //[in ] SHCONTF enumeration mask +* LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface +*/ +static HRESULT WINAPI +IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); + + *ppEnumIDList = IEnumIDList_Constructor(); + if (*ppEnumIDList) + CreateFolderEnumList(*ppEnumIDList, This->sPathTarget, dwFlags); + + TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); + + return *ppEnumIDList ? S_OK : E_OUTOFMEMORY; +} + +/************************************************************************** +* IShellFolder_fnBindToObject +* PARAMETERS +* LPCITEMIDLIST pidl, //[in ] relative pidl to open +* LPBC pbc, //[in ] optional FileSystemBindData context +* REFIID riid, //[in ] Initial Interface +* LPVOID* ppvObject //[out] Interface* +*/ +static HRESULT WINAPI +IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, LPVOID * ppvOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbc, shdebugstr_guid (riid), ppvOut); + + return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut); +} + +/************************************************************************** +* IShellFolder_fnBindToStorage +* PARAMETERS +* LPCITEMIDLIST pidl, //[in ] complex pidl to store +* LPBC pbc, //[in ] reserved +* REFIID riid, //[in ] Initial storage interface +* LPVOID* ppvObject //[out] Interface* returned +*/ +static HRESULT WINAPI +IShellFolder_fnBindToStorage (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); + + *ppvOut = NULL; + return E_NOTIMPL; +} + +/************************************************************************** +* IShellFolder_fnCompareIDs +*/ + +static HRESULT WINAPI +IShellFolder_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + int nReturn; + + TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); + nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); + TRACE ("-- %i\n", nReturn); + return nReturn; +} + +/************************************************************************** +* IShellFolder_fnCreateViewObject +*/ +static HRESULT WINAPI +IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + LPSHELLVIEW pShellView; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IDropTarget)) { + hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, ppvOut); + } else if (IsEqualIID (riid, &IID_IContextMenu)) { + FIXME ("IContextMenu not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID (riid, &IID_IShellView)) { + pShellView = IShellView_Constructor ((IShellFolder *) iface); + if (pShellView) { + hr = IShellView_QueryInterface (pShellView, riid, ppvOut); + IShellView_Release (pShellView); + } + } + } + TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); + return hr; +} + +/************************************************************************** +* IShellFolder_fnGetAttributesOf +* +* PARAMETERS +* UINT cidl, //[in ] num elements in pidl array +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* ULONG* rgfInOut) //[out] result array +* +*/ +static HRESULT WINAPI +IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + HRESULT hr = S_OK; + + TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + + if ((!cidl) || (!apidl) || (!rgfInOut)) + return E_INVALIDARG; + + if (*rgfInOut == 0) + *rgfInOut = ~0; + + while (cidl > 0 && *apidl) { + pdump (*apidl); + SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); + apidl++; + cidl--; + } + + TRACE ("-- result=0x%08lx\n", *rgfInOut); + + return hr; +} + +/************************************************************************** +* IShellFolder_fnGetUIObjectOf +* +* PARAMETERS +* HWND hwndOwner, //[in ] Parent window for any output +* UINT cidl, //[in ] array size +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* REFIID riid, //[in ] Requested Interface +* UINT* prgfInOut, //[ ] reserved +* LPVOID* ppvObject) //[out] Resulting Interface +* +* NOTES +* This function gets asked to return "view objects" for one or more (multiple select) +* items: +* The viewobject typically is an COM object with one of the following interfaces: +* IExtractIcon,IDataObject,IContextMenu +* In order to support icon positions in the default Listview your DataObject +* must implement the SetData method (in addition to GetData :) - the shell passes +* a barely documented "Icon positions" structure to SetData when the drag starts, +* and GetData's it if the drop is in another explorer window that needs the positions. +*/ +static HRESULT WINAPI +IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface, + HWND hwndOwner, + UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + LPITEMIDLIST pidl; + IUnknown *pObj = NULL; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", + This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { + pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { + pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { + hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); + } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) + && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); + SHFree (pidl); + } else { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr) && !pObj) + hr = E_OUTOFMEMORY; + + *ppvOut = pObj; + } + TRACE ("(%p)->hr=0x%08lx\n", This, hr); + return hr; +} + +void SHELL_FS_ProcessDisplayFilename(LPSTR szPath, DWORD dwFlags) +{ + /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */ + if (!(dwFlags & SHGDN_FORPARSING) && + ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) { + HKEY hKey; + DWORD dwData; + DWORD dwDataSize = sizeof (DWORD); + BOOL doHide = FALSE; /* The default value is FALSE (win98 at least) */ + + if (!RegCreateKeyExA (HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", + 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) { + if (!RegQueryValueExA (hKey, "HideFileExt", 0, 0, (LPBYTE) & dwData, &dwDataSize)) + doHide = dwData; + + RegCloseKey (hKey); + } + + if (!doHide) { + LPSTR ext = PathFindExtensionA(szPath); + + if (ext) { + HKEY hkey; + char classname[MAX_PATH]; + LONG classlen = MAX_PATH; + + if (!RegQueryValueA(HKEY_CLASSES_ROOT, ext, classname, &classlen)) + if (!RegOpenKeyA(HKEY_CLASSES_ROOT, classname, &hkey)) { + if (!RegQueryValueExA(hkey, "NeverShowExt", 0, NULL, NULL, NULL)) + doHide = TRUE; + + RegCloseKey(hkey); + } + } + } + + if (doHide && szPath[0] != '.') + PathRemoveExtensionA (szPath); + } +} + +/************************************************************************** +* IShellFolder_fnGetDisplayNameOf +* Retrieves the display name for the specified file object or subfolder +* +* PARAMETERS +* LPCITEMIDLIST pidl, //[in ] complex pidl to item +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPSTRRET lpName) //[out] Returned display name +* +* FIXME +* if the name is in the pidl the ret value should be a STRRET_OFFSET +*/ + +static HRESULT WINAPI +IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + CHAR szPath[MAX_PATH]; + int len = 0; + BOOL bSimplePidl; + + *szPath = '\0'; + + TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); + pdump (pidl); + + if (!pidl || !strRet) + return E_INVALIDARG; + + bSimplePidl = _ILIsPidlSimple (pidl); + + /* take names of special folders only if its only this folder */ + if (_ILIsSpecialFolder (pidl)) { + if (bSimplePidl) { + _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ + } else { + FIXME ("special pidl\n"); + } + } else { + if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathTarget) { + lstrcpyA (szPath, This->sPathTarget); /* get path to root */ + PathAddBackslashA (szPath); + len = lstrlenA (szPath); + } + _ILSimpleGetText (pidl, szPath + len, MAX_PATH - len); /* append my own path */ + + if (!_ILIsFolder(pidl)) + SHELL_FS_ProcessDisplayFilename(szPath, dwFlags); + } + + if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */ + PathAddBackslashA (szPath); + len = lstrlenA (szPath); + + if (!SUCCEEDED + (SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len))) + return E_OUTOFMEMORY; + } + strRet->uType = STRRET_CSTR; + lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); + + TRACE ("-- (%p)->(%s)\n", This, szPath); + return S_OK; +} + +/************************************************************************** +* IShellFolder_fnSetNameOf +* Changes the name of a file object or subfolder, possibly changing its item +* identifier in the process. +* +* PARAMETERS +* HWND hwndOwner, //[in ] Owner window for output +* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change +* LPCOLESTR lpszName, //[in ] the items new display name +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned +*/ +static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ + LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + char szSrc[MAX_PATH], + szDest[MAX_PATH]; + int len; + BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); + + TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); + + /* build source path */ + if (dwFlags & SHGDN_INFOLDER) { + strcpy (szSrc, This->sPathTarget); + PathAddBackslashA (szSrc); + len = strlen (szSrc); + _ILSimpleGetText (pidl, szSrc + len, MAX_PATH - len); + } else { + /* FIXME: Can this work with a simple PIDL? */ + SHGetPathFromIDListA (pidl, szSrc); + } + + /* build destination path */ + strcpy (szDest, This->sPathTarget); + PathAddBackslashA (szDest); + len = strlen (szDest); + WideCharToMultiByte (CP_ACP, 0, lpName, -1, szDest + len, MAX_PATH - len, NULL, NULL); + szDest[MAX_PATH - 1] = 0; + TRACE ("src=%s dest=%s\n", szSrc, szDest); + if (MoveFileA (szSrc, szDest)) { + HRESULT hr = S_OK; + + if (pPidlOut) + hr = _ILCreateFromPathA(szDest, pPidlOut); + + SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest); + + return hr; + } + + return E_FAIL; +} + +static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI IShellFolder_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI +IShellFolder_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)\n", This); + + if (pSort) + *pSort = 0; + if (pDisplay) + *pDisplay = 0; + + return S_OK; +} +static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + + TRACE ("(%p)\n", This); + + if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + *pcsFlags = GenericSFHeader[iColumn].pcsFlags; + + return S_OK; +} +static HRESULT WINAPI +IShellFolder_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + FIXME ("(%p)\n", This); + + return E_NOTIMPL; +} +static HRESULT WINAPI +IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + HRESULT hr = E_FAIL; + + TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); + + if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + if (!pidl) { + /* the header titles */ + psd->fmt = GenericSFHeader[iColumn].fmt; + psd->cxChar = GenericSFHeader[iColumn].cxChar; + psd->str.uType = STRRET_CSTR; + LoadStringA (shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); + return S_OK; + } else { + /* the data from the pidl */ + switch (iColumn) { + case 0: /* name */ + hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); + break; + case 1: /* size */ + _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 2: /* type */ + _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 3: /* date */ + _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 4: /* attributes */ + _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH); + break; + } + hr = S_OK; + psd->str.uType = STRRET_CSTR; + } + + return hr; +} +static HRESULT WINAPI IShellFolder_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) +{ + _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface) + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} + +static IShellFolder2Vtbl sfvt = +{ + IShellFolder_fnQueryInterface, + IShellFolder_fnAddRef, + IShellFolder_fnRelease, + IShellFolder_fnParseDisplayName, + IShellFolder_fnEnumObjects, + IShellFolder_fnBindToObject, + IShellFolder_fnBindToStorage, + IShellFolder_fnCompareIDs, + IShellFolder_fnCreateViewObject, + IShellFolder_fnGetAttributesOf, + IShellFolder_fnGetUIObjectOf, + IShellFolder_fnGetDisplayNameOf, + IShellFolder_fnSetNameOf, + /* ShellFolder2 */ + IShellFolder_fnGetDefaultSearchGUID, + IShellFolder_fnEnumSearches, + IShellFolder_fnGetDefaultColumn, + IShellFolder_fnGetDefaultColumnState, + IShellFolder_fnGetDetailsEx, + IShellFolder_fnGetDetailsOf, + IShellFolder_fnMapColumnToSCID +}; + +/**************************************************************************** + * ISFHelper for IShellFolder implementation + */ + +static HRESULT WINAPI ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); +} + +static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef (This->pUnkOuter); +} + +static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_Release (This->pUnkOuter); +} + +/**************************************************************************** + * ISFHelper_fnAddFolder + * + * creates a unique folder name + */ + +static HRESULT WINAPI ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) + IEnumIDList *penum; + HRESULT hr; + char szText[MAX_PATH]; + char *szNewFolder = "New Folder"; + + TRACE ("(%p)(%s %u)\n", This, lpName, uLen); + + if (uLen < strlen (szNewFolder) + 4) + return E_POINTER; + + strcpy (lpName, szNewFolder); + + hr = IShellFolder_fnEnumObjects (_IShellFolder2_ (This), 0, + SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); + if (penum) { + LPITEMIDLIST pidl; + DWORD dwFetched; + int i = 1; + + next:IEnumIDList_Reset (penum); + while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && dwFetched) { + _ILSimpleGetText (pidl, szText, MAX_PATH); + if (0 == strcasecmp (szText, lpName)) { + sprintf (lpName, "%s %d", szNewFolder, i++); + if (i > 99) { + hr = E_FAIL; + break; + } + goto next; + } + } + + IEnumIDList_Release (penum); + } + return hr; +} + +/**************************************************************************** + * ISFHelper_fnAddFolder + * + * adds a new folder. + */ + +static HRESULT WINAPI ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) + char lpstrNewDir[MAX_PATH]; + DWORD bRes; + HRESULT hres = E_FAIL; + + TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut); + + strcpy (lpstrNewDir, This->sPathTarget); + PathAppendA(lpstrNewDir, lpName); + + bRes = CreateDirectoryA (lpstrNewDir, NULL); + if (bRes) { + SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHA, lpstrNewDir, NULL); + + hres = S_OK; + + if (ppidlOut) + hres = _ILCreateFromPathA(lpstrNewDir, ppidlOut); + } else { + char lpstrText[128 + MAX_PATH]; + char lpstrTempText[128]; + char lpstrCaption[256]; + + /* Cannot Create folder because of permissions */ + LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof (lpstrTempText)); + LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof (lpstrCaption)); + sprintf (lpstrText, lpstrTempText, lpstrNewDir); + MessageBoxA (hwnd, lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION); + } + + return hres; +} + +/**************************************************************************** + * ISFHelper_fnDeleteItems + * + * deletes items in folder + */ +static HRESULT WINAPI ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) +{ + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface) + UINT i; + char szPath[MAX_PATH]; + BOOL bConfirm = TRUE; + + TRACE ("(%p)(%u %p)\n", This, cidl, apidl); + + /* deleting multiple items so give a slightly different warning */ + if (cidl != 1) { + char tmp[8]; + + snprintf (tmp, sizeof (tmp), "%d", cidl); + if (!SHELL_ConfirmDialog(ASK_DELETE_MULTIPLE_ITEM, tmp)) + return E_FAIL; + bConfirm = FALSE; + } + + for (i = 0; i < cidl; i++) { + strcpy (szPath, This->sPathTarget); + PathAddBackslashA (szPath); + _ILSimpleGetText (apidl[i], szPath + strlen (szPath), MAX_PATH); + + if (_ILIsFolder (apidl[i])) { + LPITEMIDLIST pidl; + + TRACE ("delete %s\n", szPath); + if (!SHELL_DeleteDirectoryA (szPath, bConfirm)) { + TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm); + return E_FAIL; + } + pidl = ILCombine (This->pidlRoot, apidl[i]); + SHChangeNotify (SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL); + SHFree (pidl); + } else if (_ILIsValue (apidl[i])) { + LPITEMIDLIST pidl; + + TRACE ("delete %s\n", szPath); + if (!SHELL_DeleteFileA (szPath, bConfirm)) { + TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm); + return E_FAIL; + } + pidl = ILCombine (This->pidlRoot, apidl[i]); + SHChangeNotify (SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL); + SHFree (pidl); + } + + } + return S_OK; +} + +/**************************************************************************** + * ISFHelper_fnCopyItems + * + * copies items to this folder + */ +static HRESULT WINAPI +ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) +{ + UINT i; + IPersistFolder2 *ppf2 = NULL; + char szSrcPath[MAX_PATH], + szDstPath[MAX_PATH]; + + _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface); + + TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl); + + IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2); + if (ppf2) { + LPITEMIDLIST pidl; + + if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) { + for (i = 0; i < cidl; i++) { + SHGetPathFromIDListA (pidl, szSrcPath); + PathAddBackslashA (szSrcPath); + _ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath), MAX_PATH); + + strcpy (szDstPath, This->sPathTarget); + PathAddBackslashA (szDstPath); + _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH); + MESSAGE ("would copy %s to %s\n", szSrcPath, szDstPath); + } + SHFree (pidl); + } + IPersistFolder2_Release (ppf2); + } + return S_OK; +} + +static ISFHelperVtbl shvt = +{ + ISFHelper_fnQueryInterface, + ISFHelper_fnAddRef, + ISFHelper_fnRelease, + ISFHelper_fnGetUniqueName, + ISFHelper_fnAddFolder, + ISFHelper_fnDeleteItems, + ISFHelper_fnCopyItems +}; + +/************************************************************************ + * IFSFldr_PersistFolder3_QueryInterface + * + */ +static HRESULT WINAPI IFSFldr_PersistFolder3_QueryInterface (IPersistFolder3 * iface, REFIID iid, LPVOID * ppvObj) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_QueryInterface (This->pUnkOuter, iid, ppvObj); +} + +/************************************************************************ + * IFSFldr_PersistFolder3_AddRef + * + */ +static ULONG WINAPI IFSFldr_PersistFolder3_AddRef (IPersistFolder3 * iface) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef (This->pUnkOuter); +} + +/************************************************************************ + * IFSFldr_PersistFolder3_Release + * + */ +static ULONG WINAPI IFSFldr_PersistFolder3_Release (IPersistFolder3 * iface) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_Release (This->pUnkOuter); +} + +/************************************************************************ + * IFSFldr_PersistFolder3_GetClassID + */ +static HRESULT WINAPI IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + if (!lpClassId) + return E_POINTER; + *lpClassId = *This->pclsid; + + return S_OK; +} + +/************************************************************************ + * IFSFldr_PersistFolder3_Initialize + * + * NOTES + * sPathTarget is not set. Don't know how to handle in a non rooted environment. + */ +static HRESULT WINAPI IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl) +{ + char sTemp[MAX_PATH]; + + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)->(%p)\n", This, pidl); + + if (This->pidlRoot) + SHFree (This->pidlRoot); /* free the old pidl */ + This->pidlRoot = ILClone (pidl); /* set my pidl */ + + if (This->sPathTarget) + SHFree (This->sPathTarget); + + /* set my path */ + if (SHGetPathFromIDListA (pidl, sTemp)) { + This->sPathTarget = SHAlloc (strlen (sTemp) + 1); + strcpy (This->sPathTarget, sTemp); + } + + TRACE ("--(%p)->(%s)\n", This, This->sPathTarget); + return S_OK; +} + +/************************************************************************** + * IFSFldr_PersistFolder3_GetCurFolder + */ +static HRESULT WINAPI IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3 * iface, LPITEMIDLIST * pidl) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)->(%p)\n", This, pidl); + + if (!pidl) return E_POINTER; + *pidl = ILClone (This->pidlRoot); + return S_OK; +} + +/************************************************************************** + * IFSFldr_PersistFolder3_InitializeEx + * + * FIXME: errorhandling + */ +static HRESULT WINAPI +IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface, + IBindCtx * pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO * ppfti) +{ + char sTemp[MAX_PATH]; + + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + + TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti); + if (ppfti) + TRACE ("--%p %s %s 0x%08lx 0x%08x\n", + ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName), + debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl); + + pdump (pidlRoot); + if (ppfti && ppfti->pidlTargetFolder) + pdump (ppfti->pidlTargetFolder); + + if (This->pidlRoot) + __SHFreeAndNil (&This->pidlRoot); /* free the old */ + if (This->sPathTarget) + __SHFreeAndNil (&This->sPathTarget); + + /* + * Root path and pidl + */ + This->pidlRoot = ILClone (pidlRoot); + + /* + * the target folder is spezified in csidl OR pidlTargetFolder OR szTargetParsingName + */ + if (ppfti) { + if (ppfti->csidl != -1) { + if (SHGetSpecialFolderPathA (0, sTemp, ppfti->csidl, ppfti->csidl & CSIDL_FLAG_CREATE)) { + __SHCloneStrA (&This->sPathTarget, sTemp); + } + } else if (ppfti->szTargetParsingName[0]) { + __SHCloneStrWtoA (&This->sPathTarget, ppfti->szTargetParsingName); + } else if (ppfti->pidlTargetFolder) { + if (SHGetPathFromIDListA (ppfti->pidlTargetFolder, sTemp)) { + __SHCloneStrA (&This->sPathTarget, sTemp); + } + } + } + + TRACE ("--(%p)->(target=%s)\n", This, debugstr_a (This->sPathTarget)); + pdump (This->pidlRoot); + return (This->sPathTarget) ? S_OK : E_FAIL; +} + +static HRESULT WINAPI +IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3 * iface, PERSIST_FOLDER_TARGET_INFO * ppfti) +{ + _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface); + FIXME ("(%p)->(%p)\n", This, ppfti); + ZeroMemory (ppfti, sizeof (ppfti)); + return E_NOTIMPL; +} + +static IPersistFolder3Vtbl vt_FSFldr_PersistFolder3 = +{ + IFSFldr_PersistFolder3_QueryInterface, + IFSFldr_PersistFolder3_AddRef, + IFSFldr_PersistFolder3_Release, + IFSFldr_PersistFolder3_GetClassID, + IFSFldr_PersistFolder3_Initialize, + IFSFldr_PersistFolder3_fnGetCurFolder, + IFSFldr_PersistFolder3_InitializeEx, + IFSFldr_PersistFolder3_GetFolderTargetInfo +}; + +/**************************************************************************** + * ISFDropTarget implementation + */ +static BOOL ISFDropTarget_QueryDrop (IDropTarget * iface, DWORD dwKeyState, LPDWORD pdwEffect) +{ + DWORD dwEffect = *pdwEffect; + + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + *pdwEffect = DROPEFFECT_NONE; + + if (This->fAcceptFmt) { /* Does our interpretation of the keystate ... */ + *pdwEffect = KeyStateToDropEffect (dwKeyState); + + /* ... matches the desired effect ? */ + if (dwEffect & *pdwEffect) { + return TRUE; + } + } + return FALSE; +} + +static HRESULT WINAPI ISFDropTarget_QueryInterface (IDropTarget * iface, REFIID riid, LPVOID * ppvObj) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj); +} + +static ULONG WINAPI ISFDropTarget_AddRef (IDropTarget * iface) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_AddRef (This->pUnkOuter); +} + +static ULONG WINAPI ISFDropTarget_Release (IDropTarget * iface) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_Release (This->pUnkOuter); +} + +static HRESULT WINAPI +ISFDropTarget_DragEnter (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) +{ + FORMATETC fmt; + + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)->(DataObject=%p)\n", This, pDataObject); + + InitFormatEtc (fmt, This->cfShellIDList, TYMED_HGLOBAL); + + This->fAcceptFmt = (S_OK == IDataObject_QueryGetData (pDataObject, &fmt)) ? TRUE : FALSE; + + ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect); + + return S_OK; +} + +static HRESULT WINAPI ISFDropTarget_DragOver (IDropTarget * iface, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + if (!pdwEffect) + return E_INVALIDARG; + + ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect); + + return S_OK; +} + +static HRESULT WINAPI ISFDropTarget_DragLeave (IDropTarget * iface) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + This->fAcceptFmt = FALSE; + + return S_OK; +} + +static HRESULT WINAPI +ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect) +{ + _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface); + + FIXME ("(%p) object dropped\n", This); + + return E_NOTIMPL; +} + +static struct IDropTargetVtbl dtvt = { + ISFDropTarget_QueryInterface, + ISFDropTarget_AddRef, + ISFDropTarget_Release, + ISFDropTarget_DragEnter, + ISFDropTarget_DragOver, + ISFDropTarget_DragLeave, + ISFDropTarget_Drop +}; diff --git a/reactos/lib/shell32/shfldr_mycomp.c b/reactos/lib/shell32/shfldr_mycomp.c index 994514c55e9..5de8574efcd 100644 --- a/reactos/lib/shell32/shfldr_mycomp.c +++ b/reactos/lib/shell32/shfldr_mycomp.c @@ -1,833 +1,832 @@ - -/* - * Virtual Workplace folder - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" - -#include "wingdi.h" -#include "pidl.h" -#include "shlguid.h" -#include "enumidlist.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "shellfolder.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL (shell); - -/*********************************************************************** -* IShellFolder implementation -*/ - -typedef struct { - IShellFolder2Vtbl *lpVtbl; - DWORD ref; - IPersistFolder2Vtbl *lpVtblPersistFolder2; - - /* both paths are parsible from the desktop */ - LPITEMIDLIST pidlRoot; /* absolute pidl */ - int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ -} IGenericSFImpl; - -static struct IShellFolder2Vtbl vt_ShellFolder2; -static struct IPersistFolder2Vtbl vt_PersistFolder2; - -#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2))) -#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); - -/* - converts This to a interface pointer -*/ -#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) -#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl) - -#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2) -#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2) -#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2) - -/*********************************************************************** -* IShellFolder [MyComputer] implementation -*/ - -static shvheader MyComputerSFHeader[] = { - {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, - {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, - {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, -}; - -#define MYCOMPUTERSHELLVIEWCOLUMNS 4 - -/************************************************************************** -* ISF_MyComputer_Constructor -*/ -HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) -{ - IGenericSFImpl *sf; - - TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); - - if (!ppv) - return E_POINTER; - if (pUnkOuter) - return CLASS_E_NOAGGREGATION; - - sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); - if (!sf) - return E_OUTOFMEMORY; - - sf->ref = 0; - sf->lpVtbl = &vt_ShellFolder2; - sf->lpVtblPersistFolder2 = &vt_PersistFolder2; - sf->pidlRoot = _ILCreateMyComputer (); /* my qualified pidl */ - - if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { - IUnknown_Release (_IUnknown_ (sf)); - return E_NOINTERFACE; - } - - TRACE ("--(%p)\n", sf); - return S_OK; -} - -/************************************************************************** - * ISF_MyComputer_fnQueryInterface - * - * NOTES supports not IPersist/IPersistFolder - */ -static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - *ppvObj = NULL; - - if (IsEqualIID (riid, &IID_IUnknown) || - IsEqualIID (riid, &IID_IShellFolder) || IsEqualIID (riid, &IID_IShellFolder2)) { - *ppvObj = This; - } else if (IsEqualIID (riid, &IID_IPersist) || - IsEqualIID (riid, &IID_IPersistFolder) || IsEqualIID (riid, &IID_IPersistFolder2)) { - *ppvObj = _IPersistFolder2_ (This); - } - - if (*ppvObj) { - IUnknown_AddRef ((IUnknown *) (*ppvObj)); - TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); - return S_OK; - } - TRACE ("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return ++(This->ref); -} - -static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - if (!--(This->ref)) { - TRACE ("-- destroying IShellFolder(%p)\n", This); - if (This->pidlRoot) - SHFree (This->pidlRoot); - LocalFree ((HLOCAL) This); - return 0; - } - return This->ref; -} - -/************************************************************************** -* ISF_MyComputer_fnParseDisplayName -*/ -static HRESULT WINAPI -ISF_MyComputer_fnParseDisplayName (IShellFolder2 * iface, - HWND hwndOwner, - LPBC pbc, - LPOLESTR lpszDisplayName, - DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - HRESULT hr = E_INVALIDARG; - LPCWSTR szNext = NULL; - WCHAR szElement[MAX_PATH]; - LPITEMIDLIST pidlTemp = NULL; - CLSID clsid; - - TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", - This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); - - *ppidl = 0; - if (pchEaten) - *pchEaten = 0; /* strange but like the original */ - - /* handle CLSID paths */ - if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') { - szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - TRACE ("-- element: %s\n", debugstr_w (szElement)); - SHCLSIDFromStringW (szElement + 2, &clsid); - pidlTemp = _ILCreateGuid (PT_GUID, &clsid); - } - /* do we have an absolute path name ? */ - else if (PathGetDriveNumberW (lpszDisplayName) >= 0 && lpszDisplayName[2] == (WCHAR) '\\') { - szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - szElement[0] = toupper(szElement[0]); /* make drive letter uppercase to enable PIDL comparison */ - pidlTemp = _ILCreateDrive (szElement); - } - - if (szNext && *szNext) { - hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); - } else { - if (pdwAttributes && *pdwAttributes) { - SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); - } - hr = S_OK; - } - - *ppidl = pidlTemp; - - TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr); - - return hr; -} - -/************************************************************************** - * CreateMyCompEnumList() - */ -static BOOL CreateMyCompEnumList(IEnumIDList *list, DWORD dwFlags) -{ - BOOL ret = TRUE; - - TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags); - - /*enumerate the folders*/ - if(dwFlags & SHCONTF_FOLDERS) - { - WCHAR wszDriveName[] = {'A', ':', '\\', '\0'}; - DWORD dwDrivemap = GetLogicalDrives(); - HKEY hkey; - - while (ret && wszDriveName[0]<='Z') - { - if(dwDrivemap & 0x00000001L) - ret = AddToEnumList(list, _ILCreateDrive(wszDriveName)); - wszDriveName[0]++; - dwDrivemap = dwDrivemap >> 1; - } - - TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",list); - if (ret && !RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\mycomputer\\NameSpace", - 0, KEY_READ, &hkey)) - { - char iid[50]; - int i=0; - - while (ret) - { - DWORD size = sizeof (iid); - LONG apiRet = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL, - NULL); - - if (ERROR_SUCCESS == apiRet) - { - /* FIXME: shell extensions, shouldn't the type be - * PT_SHELLEXT? */ - ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid)); - i++; - } - else if (ERROR_NO_MORE_ITEMS == apiRet) - break; - else - ret = FALSE; - } - RegCloseKey(hkey); - } - } - return ret; -} - -/************************************************************************** -* ISF_MyComputer_fnEnumObjects -*/ -static HRESULT WINAPI -ISF_MyComputer_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); - - *ppEnumIDList = IEnumIDList_Constructor(); - if (*ppEnumIDList) - CreateMyCompEnumList(*ppEnumIDList, dwFlags); - - TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); - - return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY; -} - -/************************************************************************** -* ISF_MyComputer_fnBindToObject -*/ -static HRESULT WINAPI -ISF_MyComputer_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, - LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); - - return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut); -} - -/************************************************************************** -* ISF_MyComputer_fnBindToStorage -*/ -static HRESULT WINAPI -ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface, - LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); - - *ppvOut = NULL; - return E_NOTIMPL; -} - -/************************************************************************** -* ISF_MyComputer_fnCompareIDs -*/ - -static HRESULT WINAPI -ISF_MyComputer_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - int nReturn; - - TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); - nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); - TRACE ("-- %i\n", nReturn); - return nReturn; -} - -/************************************************************************** -* ISF_MyComputer_fnCreateViewObject -*/ -static HRESULT WINAPI -ISF_MyComputer_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - LPSHELLVIEW pShellView; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IDropTarget)) { - WARN ("IDropTarget not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID (riid, &IID_IContextMenu)) { - WARN ("IContextMenu not implemented\n"); - hr = E_NOTIMPL; - } else if (IsEqualIID (riid, &IID_IShellView)) { - pShellView = IShellView_Constructor ((IShellFolder *) iface); - if (pShellView) { - hr = IShellView_QueryInterface (pShellView, riid, ppvOut); - IShellView_Release (pShellView); - } - } - } - TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); - return hr; -} - -/************************************************************************** -* ISF_MyComputer_fnGetAttributesOf -*/ -static HRESULT WINAPI -ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - HRESULT hr = S_OK; - - TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); - - if ((!cidl) || (!apidl) || (!rgfInOut)) - return E_INVALIDARG; - - if (*rgfInOut == 0) - *rgfInOut = ~0; - - while (cidl > 0 && *apidl) { - pdump (*apidl); - SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); - apidl++; - cidl--; - } - - TRACE ("-- result=0x%08lx\n", *rgfInOut); - return hr; -} - -/************************************************************************** -* ISF_MyComputer_fnGetUIObjectOf -* -* PARAMETERS -* HWND hwndOwner, //[in ] Parent window for any output -* UINT cidl, //[in ] array size -* LPCITEMIDLIST* apidl, //[in ] simple pidl array -* REFIID riid, //[in ] Requested Interface -* UINT* prgfInOut, //[ ] reserved -* LPVOID* ppvObject) //[out] Resulting Interface -* -*/ -static HRESULT WINAPI -ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface, - HWND hwndOwner, - UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - LPITEMIDLIST pidl; - IUnknown *pObj = NULL; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", - This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); - - if (ppvOut) { - *ppvOut = NULL; - - if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { - pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { - pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); - SHFree (pidl); - hr = S_OK; - } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { - hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); - } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) - && (cidl == 1)) { - pidl = ILCombine (This->pidlRoot, apidl[0]); - hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); - SHFree (pidl); - } else { - hr = E_NOINTERFACE; - } - - if (SUCCEEDED(hr) && !pObj) - hr = E_OUTOFMEMORY; - - *ppvOut = pObj; - } - TRACE ("(%p)->hr=0x%08lx\n", This, hr); - return hr; -} - -/************************************************************************** -* ISF_MyComputer_fnGetDisplayNameOf -*/ -static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - char szPath[MAX_PATH], - szDrive[18]; - int len = 0; - BOOL bSimplePidl; - HRESULT hr = S_OK; - - TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); - pdump (pidl); - - if (!strRet) - return E_INVALIDARG; - - szPath[0] = 0x00; - szDrive[0] = 0x00; - - bSimplePidl = _ILIsPidlSimple (pidl); - - if (!pidl->mkid.cb) { - /* parsing name like ::{...} */ - lstrcpyA (szPath, "::"); - SHELL32_GUIDToStringA(&CLSID_MyComputer, &szPath[2]); - } else if (_ILIsSpecialFolder (pidl)) { - /* take names of special folders only if its only this folder */ - if (bSimplePidl) { - GUID const *clsid; - - if ((clsid = _ILGetGUIDPointer (pidl))) { - if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) { - int bWantsForParsing; - - /* - * we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in - * CLSID\\{...}\\shellfolder exists - * exception: the MyComputer folder has this keys not but like any filesystem backed - * folder it needs these behaviour - */ - /* get the "WantsFORPARSING" flag from the registry */ - char szRegPath[100]; - - lstrcpyA (szRegPath, "CLSID\\"); - SHELL32_GUIDToStringA (clsid, &szRegPath[6]); - lstrcatA (szRegPath, "\\shellfolder"); - bWantsForParsing = - (ERROR_SUCCESS == - SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL)); - - if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) { - /* we need the filesystem path to the destination folder. Only the folder itself can know it */ - hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); - } else { - LPSTR p; - - /* parsing name like ::{...} */ - p = lstrcpyA(szPath, "::") + 2; - p += SHELL32_GUIDToStringA(&CLSID_MyComputer, p); - - lstrcatA(p, "\\::"); - p += 3; - SHELL32_GUIDToStringA(clsid, p); - } - } else { - /* user friendly name */ - HCR_GetClassNameA (clsid, szPath, MAX_PATH); - } - } else - _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ - } else { - FIXME ("special folder\n"); - } - } else { - if (!_ILIsDrive (pidl)) { - ERR ("Wrong pidl type\n"); - return E_INVALIDARG; - } - - _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ - - /* long view "lw_name (C:)" */ - if (bSimplePidl && !(dwFlags & SHGDN_FORPARSING)) { - DWORD dwVolumeSerialNumber, - dwMaximumComponetLength, - dwFileSystemFlags; - - GetVolumeInformationA (szPath, szDrive, sizeof (szDrive) - 6, &dwVolumeSerialNumber, - &dwMaximumComponetLength, &dwFileSystemFlags, NULL, 0); - strcat (szDrive, " ("); - strncat (szDrive, szPath, 2); - strcat (szDrive, ")"); - strcpy (szPath, szDrive); - } - } - - if (!bSimplePidl) { /* go deeper if needed */ - PathAddBackslashA (szPath); - len = strlen (szPath); - - hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len); - } - - if (SUCCEEDED (hr)) { - strRet->uType = STRRET_CSTR; - lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); - } - - TRACE ("-- (%p)->(%s)\n", This, szPath); - return hr; -} - -/************************************************************************** -* ISF_MyComputer_fnSetNameOf -* Changes the name of a file object or subfolder, possibly changing its item -* identifier in the process. -* -* PARAMETERS -* HWND hwndOwner, //[in ] Owner window for output -* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change -* LPCOLESTR lpszName, //[in ] the items new display name -* DWORD dwFlags, //[in ] SHGNO formatting flags -* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned -*/ -static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ - LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); - return E_FAIL; -} - -static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} -static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)\n", This); - - if (pSort) *pSort = 0; - if (pDisplay) *pDisplay = 0; - return S_OK; -} -static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - - TRACE ("(%p)\n", This); - - if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) return E_INVALIDARG; - *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags; - return S_OK; -} -static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} - -/* FIXME: drive size >4GB is rolling over */ -static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - HRESULT hr; - - TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); - - if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) - return E_INVALIDARG; - - if (!pidl) { - psd->fmt = MyComputerSFHeader[iColumn].fmt; - psd->cxChar = MyComputerSFHeader[iColumn].cxChar; - psd->str.uType = STRRET_CSTR; - LoadStringA (shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); - return S_OK; - } else { - char szPath[MAX_PATH]; - ULARGE_INTEGER ulBytes; - - psd->str.u.cStr[0] = 0x00; - psd->str.uType = STRRET_CSTR; - switch (iColumn) { - case 0: /* name */ - hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); - break; - case 1: /* type */ - _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); - break; - case 2: /* total size */ - if (_ILIsDrive (pidl)) { - _ILSimpleGetText (pidl, szPath, MAX_PATH); - GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL); - StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH); - } - break; - case 3: /* free size */ - if (_ILIsDrive (pidl)) { - _ILSimpleGetText (pidl, szPath, MAX_PATH); - GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL); - StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH); - } - break; - } - hr = S_OK; - } - - return hr; -} -static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) -{ - IGenericSFImpl *This = (IGenericSFImpl *)iface; - FIXME ("(%p)\n", This); - return E_NOTIMPL; -} - -static IShellFolder2Vtbl vt_ShellFolder2 = -{ - ISF_MyComputer_fnQueryInterface, - ISF_MyComputer_fnAddRef, - ISF_MyComputer_fnRelease, - ISF_MyComputer_fnParseDisplayName, - ISF_MyComputer_fnEnumObjects, - ISF_MyComputer_fnBindToObject, - ISF_MyComputer_fnBindToStorage, - ISF_MyComputer_fnCompareIDs, - ISF_MyComputer_fnCreateViewObject, - ISF_MyComputer_fnGetAttributesOf, - ISF_MyComputer_fnGetUIObjectOf, - ISF_MyComputer_fnGetDisplayNameOf, - ISF_MyComputer_fnSetNameOf, - /* ShellFolder2 */ - ISF_MyComputer_fnGetDefaultSearchGUID, - ISF_MyComputer_fnEnumSearches, - ISF_MyComputer_fnGetDefaultColumn, - ISF_MyComputer_fnGetDefaultColumnState, - ISF_MyComputer_fnGetDetailsEx, - ISF_MyComputer_fnGetDetailsOf, - ISF_MyComputer_fnMapColumnToSCID -}; - -/************************************************************************ - * IMCFldr_PersistFolder2_QueryInterface - */ -static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj); -} - -/************************************************************************ - * IMCFldr_PersistFolder2_AddRef - */ -static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_AddRef (_IUnknown_ (This)); -} - -/************************************************************************ - * ISFPersistFolder_Release - */ -static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - - TRACE ("(%p)->(count=%lu)\n", This, This->ref); - - return IUnknown_Release (_IUnknown_ (This)); -} - -/************************************************************************ - * IMCFldr_PersistFolder2_GetClassID - */ -static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (IPersistFolder2 * iface, CLSID * lpClassId) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - - TRACE ("(%p)\n", This); - - if (!lpClassId) - return E_POINTER; - *lpClassId = CLSID_MyComputer; - - return S_OK; -} - -/************************************************************************ - * IMCFldr_PersistFolder2_Initialize - * - * NOTES: it makes no sense to change the pidl - */ -static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (IPersistFolder2 * iface, LPCITEMIDLIST pidl) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - TRACE ("(%p)->(%p)\n", This, pidl); - return E_NOTIMPL; -} - -/************************************************************************** - * IPersistFolder2_fnGetCurFolder - */ -static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (IPersistFolder2 * iface, LPITEMIDLIST * pidl) -{ - _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - - TRACE ("(%p)->(%p)\n", This, pidl); - - if (!pidl) - return E_POINTER; - *pidl = ILClone (This->pidlRoot); - return S_OK; -} - -static IPersistFolder2Vtbl vt_PersistFolder2 = -{ - IMCFldr_PersistFolder2_QueryInterface, - IMCFldr_PersistFolder2_AddRef, - IMCFldr_PersistFolder2_Release, - IMCFldr_PersistFolder2_GetClassID, - IMCFldr_PersistFolder2_Initialize, - IMCFldr_PersistFolder2_GetCurFolder -}; + +/* + * Virtual Workplace folder + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" + +#include "wingdi.h" +#include "pidl.h" +#include "shlguid.h" +#include "enumidlist.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shresdef.h" +#include "shlwapi.h" +#include "wine/debug.h" +#include "debughlp.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +/*********************************************************************** +* IShellFolder implementation +*/ + +typedef struct { + IShellFolder2Vtbl *lpVtbl; + DWORD ref; + IPersistFolder2Vtbl *lpVtblPersistFolder2; + + /* both paths are parsible from the desktop */ + LPITEMIDLIST pidlRoot; /* absolute pidl */ + int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */ +} IGenericSFImpl; + +static struct IShellFolder2Vtbl vt_ShellFolder2; +static struct IPersistFolder2Vtbl vt_PersistFolder2; + +#define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2))) +#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset); + +/* + converts This to a interface pointer +*/ +#define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) +#define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) +#define _IShellFolder2_(This) (IShellFolder2*)&(This->lpVtbl) + +#define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2) +#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2) + +/*********************************************************************** +* IShellFolder [MyComputer] implementation +*/ + +static shvheader MyComputerSFHeader[] = { + {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}, + {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, + {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}, +}; + +#define MYCOMPUTERSHELLVIEWCOLUMNS 4 + +/************************************************************************** +* ISF_MyComputer_Constructor +*/ +HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) +{ + IGenericSFImpl *sf; + + TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); + + if (!ppv) + return E_POINTER; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl)); + if (!sf) + return E_OUTOFMEMORY; + + sf->ref = 0; + sf->lpVtbl = &vt_ShellFolder2; + sf->lpVtblPersistFolder2 = &vt_PersistFolder2; + sf->pidlRoot = _ILCreateMyComputer (); /* my qualified pidl */ + + if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) { + IUnknown_Release (_IUnknown_ (sf)); + return E_NOINTERFACE; + } + + TRACE ("--(%p)\n", sf); + return S_OK; +} + +/************************************************************************** + * ISF_MyComputer_fnQueryInterface + * + * NOTES supports not IPersist/IPersistFolder + */ +static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); + + *ppvObj = NULL; + + if (IsEqualIID (riid, &IID_IUnknown) || + IsEqualIID (riid, &IID_IShellFolder) || IsEqualIID (riid, &IID_IShellFolder2)) { + *ppvObj = This; + } else if (IsEqualIID (riid, &IID_IPersist) || + IsEqualIID (riid, &IID_IPersistFolder) || IsEqualIID (riid, &IID_IPersistFolder2)) { + *ppvObj = _IPersistFolder2_ (This); + } + + if (*ppvObj) { + IUnknown_AddRef ((IUnknown *) (*ppvObj)); + TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); + return S_OK; + } + TRACE ("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + TRACE ("-- destroying IShellFolder(%p)\n", This); + if (This->pidlRoot) + SHFree (This->pidlRoot); + LocalFree ((HLOCAL) This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* ISF_MyComputer_fnParseDisplayName +*/ +static HRESULT WINAPI +ISF_MyComputer_fnParseDisplayName (IShellFolder2 * iface, + HWND hwndOwner, + LPBC pbc, + LPOLESTR lpszDisplayName, + DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + HRESULT hr = E_INVALIDARG; + LPCWSTR szNext = NULL; + WCHAR szElement[MAX_PATH]; + LPITEMIDLIST pidlTemp = NULL; + CLSID clsid; + + TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", + This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes); + + *ppidl = 0; + if (pchEaten) + *pchEaten = 0; /* strange but like the original */ + + /* handle CLSID paths */ + if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') { + szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); + TRACE ("-- element: %s\n", debugstr_w (szElement)); + SHCLSIDFromStringW (szElement + 2, &clsid); + pidlTemp = _ILCreateGuid (PT_GUID, &clsid); + } + /* do we have an absolute path name ? */ + else if (PathGetDriveNumberW (lpszDisplayName) >= 0 && lpszDisplayName[2] == (WCHAR) '\\') { + szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); + szElement[0] = toupper(szElement[0]); /* make drive letter uppercase to enable PIDL comparison */ + pidlTemp = _ILCreateDrive (szElement); + } + + if (szNext && *szNext) { + hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes); + } else { + if (pdwAttributes && *pdwAttributes) { + SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes); + } + hr = S_OK; + } + + *ppidl = pidlTemp; + + TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr); + + return hr; +} + +/************************************************************************** + * CreateMyCompEnumList() + */ +static BOOL CreateMyCompEnumList(IEnumIDList *list, DWORD dwFlags) +{ + BOOL ret = TRUE; + + TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags); + + /*enumerate the folders*/ + if(dwFlags & SHCONTF_FOLDERS) + { + WCHAR wszDriveName[] = {'A', ':', '\\', '\0'}; + DWORD dwDrivemap = GetLogicalDrives(); + HKEY hkey; + + while (ret && wszDriveName[0]<='Z') + { + if(dwDrivemap & 0x00000001L) + ret = AddToEnumList(list, _ILCreateDrive(wszDriveName)); + wszDriveName[0]++; + dwDrivemap = dwDrivemap >> 1; + } + + TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",list); + if (ret && !RegOpenKeyExA(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\mycomputer\\NameSpace", + 0, KEY_READ, &hkey)) + { + char iid[50]; + int i=0; + + while (ret) + { + DWORD size = sizeof (iid); + LONG apiRet = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL, + NULL); + + if (ERROR_SUCCESS == apiRet) + { + /* FIXME: shell extensions, shouldn't the type be + * PT_SHELLEXT? */ + ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid)); + i++; + } + else if (ERROR_NO_MORE_ITEMS == apiRet) + break; + else + ret = FALSE; + } + RegCloseKey(hkey); + } + } + return ret; +} + +/************************************************************************** +* ISF_MyComputer_fnEnumObjects +*/ +static HRESULT WINAPI +ISF_MyComputer_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList); + + *ppEnumIDList = IEnumIDList_Constructor(); + if (*ppEnumIDList) + CreateMyCompEnumList(*ppEnumIDList, dwFlags); + + TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList); + + return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY; +} + +/************************************************************************** +* ISF_MyComputer_fnBindToObject +*/ +static HRESULT WINAPI +ISF_MyComputer_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, + LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); + + return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut); +} + +/************************************************************************** +* ISF_MyComputer_fnBindToStorage +*/ +static HRESULT WINAPI +ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface, + LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut); + + *ppvOut = NULL; + return E_NOTIMPL; +} + +/************************************************************************** +* ISF_MyComputer_fnCompareIDs +*/ + +static HRESULT WINAPI +ISF_MyComputer_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + int nReturn; + + TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2); + nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2); + TRACE ("-- %i\n", nReturn); + return nReturn; +} + +/************************************************************************** +* ISF_MyComputer_fnCreateViewObject +*/ +static HRESULT WINAPI +ISF_MyComputer_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + LPSHELLVIEW pShellView; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IDropTarget)) { + WARN ("IDropTarget not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID (riid, &IID_IContextMenu)) { + WARN ("IContextMenu not implemented\n"); + hr = E_NOTIMPL; + } else if (IsEqualIID (riid, &IID_IShellView)) { + pShellView = IShellView_Constructor ((IShellFolder *) iface); + if (pShellView) { + hr = IShellView_QueryInterface (pShellView, riid, ppvOut); + IShellView_Release (pShellView); + } + } + } + TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut); + return hr; +} + +/************************************************************************** +* ISF_MyComputer_fnGetAttributesOf +*/ +static HRESULT WINAPI +ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + HRESULT hr = S_OK; + + TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut); + + if ((!cidl) || (!apidl) || (!rgfInOut)) + return E_INVALIDARG; + + if (*rgfInOut == 0) + *rgfInOut = ~0; + + while (cidl > 0 && *apidl) { + pdump (*apidl); + SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut); + apidl++; + cidl--; + } + + TRACE ("-- result=0x%08lx\n", *rgfInOut); + return hr; +} + +/************************************************************************** +* ISF_MyComputer_fnGetUIObjectOf +* +* PARAMETERS +* HWND hwndOwner, //[in ] Parent window for any output +* UINT cidl, //[in ] array size +* LPCITEMIDLIST* apidl, //[in ] simple pidl array +* REFIID riid, //[in ] Requested Interface +* UINT* prgfInOut, //[ ] reserved +* LPVOID* ppvObject) //[out] Resulting Interface +* +*/ +static HRESULT WINAPI +ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface, + HWND hwndOwner, + UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + LPITEMIDLIST pidl; + IUnknown *pObj = NULL; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", + This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut); + + if (ppvOut) { + *ppvOut = NULL; + + if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { + pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { + pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl); + SHFree (pidl); + hr = S_OK; + } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) { + hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj); + } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA)) + && (cidl == 1)) { + pidl = ILCombine (This->pidlRoot, apidl[0]); + hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj); + SHFree (pidl); + } else { + hr = E_NOINTERFACE; + } + + if (SUCCEEDED(hr) && !pObj) + hr = E_OUTOFMEMORY; + + *ppvOut = pObj; + } + TRACE ("(%p)->hr=0x%08lx\n", This, hr); + return hr; +} + +/************************************************************************** +* ISF_MyComputer_fnGetDisplayNameOf +*/ +static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + char szPath[MAX_PATH], + szDrive[18]; + int len = 0; + BOOL bSimplePidl; + HRESULT hr = S_OK; + + TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet); + pdump (pidl); + + if (!strRet) + return E_INVALIDARG; + + szPath[0] = 0x00; + szDrive[0] = 0x00; + + bSimplePidl = _ILIsPidlSimple (pidl); + + if (!pidl->mkid.cb) { + /* parsing name like ::{...} */ + lstrcpyA (szPath, "::"); + SHELL32_GUIDToStringA(&CLSID_MyComputer, &szPath[2]); + } else if (_ILIsSpecialFolder (pidl)) { + /* take names of special folders only if its only this folder */ + if (bSimplePidl) { + GUID const *clsid; + + if ((clsid = _ILGetGUIDPointer (pidl))) { + if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) { + int bWantsForParsing; + + /* + * we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in + * CLSID\\{...}\\shellfolder exists + * exception: the MyComputer folder has this keys not but like any filesystem backed + * folder it needs these behaviour + */ + /* get the "WantsFORPARSING" flag from the registry */ + char szRegPath[100]; + + lstrcpyA (szRegPath, "CLSID\\"); + SHELL32_GUIDToStringA (clsid, &szRegPath[6]); + lstrcatA (szRegPath, "\\shellfolder"); + bWantsForParsing = + (ERROR_SUCCESS == + SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL)); + + if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) { + /* we need the filesystem path to the destination folder. Only the folder itself can know it */ + hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH); + } else { + LPSTR p; + + /* parsing name like ::{...} */ + p = lstrcpyA(szPath, "::") + 2; + p += SHELL32_GUIDToStringA(&CLSID_MyComputer, p); + + lstrcatA(p, "\\::"); + p += 3; + SHELL32_GUIDToStringA(clsid, p); + } + } else { + /* user friendly name */ + HCR_GetClassNameA (clsid, szPath, MAX_PATH); + } + } else + _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ + } else { + FIXME ("special folder\n"); + } + } else { + if (!_ILIsDrive (pidl)) { + ERR ("Wrong pidl type\n"); + return E_INVALIDARG; + } + + _ILSimpleGetText (pidl, szPath, MAX_PATH); /* append my own path */ + + /* long view "lw_name (C:)" */ + if (bSimplePidl && !(dwFlags & SHGDN_FORPARSING)) { + DWORD dwVolumeSerialNumber, + dwMaximumComponetLength, + dwFileSystemFlags; + + GetVolumeInformationA (szPath, szDrive, sizeof (szDrive) - 6, &dwVolumeSerialNumber, + &dwMaximumComponetLength, &dwFileSystemFlags, NULL, 0); + strcat (szDrive, " ("); + strncat (szDrive, szPath, 2); + strcat (szDrive, ")"); + strcpy (szPath, szDrive); + } + } + + if (!bSimplePidl) { /* go deeper if needed */ + PathAddBackslashA (szPath); + len = strlen (szPath); + + hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len); + } + + if (SUCCEEDED (hr)) { + strRet->uType = STRRET_CSTR; + lstrcpynA (strRet->u.cStr, szPath, MAX_PATH); + } + + TRACE ("-- (%p)->(%s)\n", This, szPath); + return hr; +} + +/************************************************************************** +* ISF_MyComputer_fnSetNameOf +* Changes the name of a file object or subfolder, possibly changing its item +* identifier in the process. +* +* PARAMETERS +* HWND hwndOwner, //[in ] Owner window for output +* LPCITEMIDLIST pidl, //[in ] simple pidl of item to change +* LPCOLESTR lpszName, //[in ] the items new display name +* DWORD dwFlags, //[in ] SHGNO formatting flags +* LPITEMIDLIST* ppidlOut) //[out] simple pidl returned +*/ +static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */ + LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); + return E_FAIL; +} + +static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} +static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)\n", This); + + if (pSort) *pSort = 0; + if (pDisplay) *pDisplay = 0; + return S_OK; +} +static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + + TRACE ("(%p)\n", This); + + if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) return E_INVALIDARG; + *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags; + return S_OK; +} +static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} + +/* FIXME: drive size >4GB is rolling over */ +static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + HRESULT hr; + + TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); + + if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) + return E_INVALIDARG; + + if (!pidl) { + psd->fmt = MyComputerSFHeader[iColumn].fmt; + psd->cxChar = MyComputerSFHeader[iColumn].cxChar; + psd->str.uType = STRRET_CSTR; + LoadStringA (shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH); + return S_OK; + } else { + char szPath[MAX_PATH]; + ULARGE_INTEGER ulBytes; + + psd->str.u.cStr[0] = 0x00; + psd->str.uType = STRRET_CSTR; + switch (iColumn) { + case 0: /* name */ + hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); + break; + case 1: /* type */ + _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH); + break; + case 2: /* total size */ + if (_ILIsDrive (pidl)) { + _ILSimpleGetText (pidl, szPath, MAX_PATH); + GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL); + StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH); + } + break; + case 3: /* free size */ + if (_ILIsDrive (pidl)) { + _ILSimpleGetText (pidl, szPath, MAX_PATH); + GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL); + StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH); + } + break; + } + hr = S_OK; + } + + return hr; +} +static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid) +{ + IGenericSFImpl *This = (IGenericSFImpl *)iface; + FIXME ("(%p)\n", This); + return E_NOTIMPL; +} + +static IShellFolder2Vtbl vt_ShellFolder2 = +{ + ISF_MyComputer_fnQueryInterface, + ISF_MyComputer_fnAddRef, + ISF_MyComputer_fnRelease, + ISF_MyComputer_fnParseDisplayName, + ISF_MyComputer_fnEnumObjects, + ISF_MyComputer_fnBindToObject, + ISF_MyComputer_fnBindToStorage, + ISF_MyComputer_fnCompareIDs, + ISF_MyComputer_fnCreateViewObject, + ISF_MyComputer_fnGetAttributesOf, + ISF_MyComputer_fnGetUIObjectOf, + ISF_MyComputer_fnGetDisplayNameOf, + ISF_MyComputer_fnSetNameOf, + /* ShellFolder2 */ + ISF_MyComputer_fnGetDefaultSearchGUID, + ISF_MyComputer_fnEnumSearches, + ISF_MyComputer_fnGetDefaultColumn, + ISF_MyComputer_fnGetDefaultColumnState, + ISF_MyComputer_fnGetDetailsEx, + ISF_MyComputer_fnGetDetailsOf, + ISF_MyComputer_fnMapColumnToSCID +}; + +/************************************************************************ + * IMCFldr_PersistFolder2_QueryInterface + */ +static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj); +} + +/************************************************************************ + * IMCFldr_PersistFolder2_AddRef + */ +static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_AddRef (_IUnknown_ (This)); +} + +/************************************************************************ + * ISFPersistFolder_Release + */ +static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return IUnknown_Release (_IUnknown_ (This)); +} + +/************************************************************************ + * IMCFldr_PersistFolder2_GetClassID + */ +static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (IPersistFolder2 * iface, CLSID * lpClassId) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + + TRACE ("(%p)\n", This); + + if (!lpClassId) + return E_POINTER; + *lpClassId = CLSID_MyComputer; + + return S_OK; +} + +/************************************************************************ + * IMCFldr_PersistFolder2_Initialize + * + * NOTES: it makes no sense to change the pidl + */ +static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (IPersistFolder2 * iface, LPCITEMIDLIST pidl) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + TRACE ("(%p)->(%p)\n", This, pidl); + return E_NOTIMPL; +} + +/************************************************************************** + * IPersistFolder2_fnGetCurFolder + */ +static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (IPersistFolder2 * iface, LPITEMIDLIST * pidl) +{ + _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); + + TRACE ("(%p)->(%p)\n", This, pidl); + + if (!pidl) + return E_POINTER; + *pidl = ILClone (This->pidlRoot); + return S_OK; +} + +static IPersistFolder2Vtbl vt_PersistFolder2 = +{ + IMCFldr_PersistFolder2_QueryInterface, + IMCFldr_PersistFolder2_AddRef, + IMCFldr_PersistFolder2_Release, + IMCFldr_PersistFolder2_GetClassID, + IMCFldr_PersistFolder2_Initialize, + IMCFldr_PersistFolder2_GetCurFolder +}; diff --git a/reactos/lib/shell32/shlexec.c b/reactos/lib/shell32/shlexec.c index 9ea332195e3..14bab166d5f 100644 --- a/reactos/lib/shell32/shlexec.c +++ b/reactos/lib/shell32/shlexec.c @@ -1,1464 +1,1448 @@ -/* - * Shell Library Functions - * - * Copyright 1998 Marcus Meissner - * Copyright 2002 Eric Pouech - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "wownt32.h" -#include "shellapi.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "shlwapi.h" -#include "ddeml.h" - -#include "wine/winbase16.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "pidl.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(exec); - -static const WCHAR wszOpen[] = {'o','p','e','n',0}; -static const WCHAR wszExe[] = {'.','e','x','e',0}; -static const WCHAR wszILPtr[] = {':','%','p',0}; -static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0}; -static const WCHAR wszFolder[] = {'F','o','l','d','e','r',0}; -static const WCHAR wszEmpty[] = {0}; - - -/*********************************************************************** - * SHELL_ArgifyW [Internal] - * - * this function is supposed to expand the escape sequences found in the registry - * some diving reported that the following were used: - * + %1, %2... seem to report to parameter of index N in ShellExecute pmts - * %1 file - * %2 printer - * %3 driver - * %4 port - * %I address of a global item ID (explorer switch /idlist) - * %L seems to be %1 as long filename followed by the 8+3 variation - * %S ??? - * %* all following parameters (see batfile) - * - * FIXME: use 'len' - * FIXME: Careful of going over string boundaries. No checking is done to 'res'... - */ -static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args) -{ - WCHAR xlpFile[1024]; - BOOL done = FALSE; - PWSTR res = out; - PCWSTR cmd; - LPVOID pv; - - TRACE("%p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt), - debugstr_w(lpFile), pidl, args); - - while (*fmt) - { - if (*fmt == '%') - { - switch (*++fmt) - { - case '\0': - case '%': - *res++ = '%'; - break; - - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '0': - case '*': - if (args) - { - if (*fmt == '*') - { - *res++ = '"'; - while(*args) - *res++ = *args++; - *res++ = '"'; - } - else - { - while(*args && !isspace(*args)) - *res++ = *args++; - - while(isspace(*args)) - ++args; - } - break; - } - /* else fall through */ - case '1': - if (!done || (*fmt == '1')) - { - /*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */ - if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL)) - cmd = xlpFile; - else - cmd = lpFile; - - /* Add double quotation marks unless we already have them - (e.g.: "file://%1" %* for exefile) or unless the arg is already - enclosed in double quotation marks */ - if ((res == out || *(fmt + 1) != '"') && *cmd != '"') - { - *res++ = '"'; - strcpyW(res, cmd); - res += strlenW(cmd); - *res++ = '"'; - } - else - { - strcpyW(res, cmd); - res += strlenW(cmd); - } - } - break; - - /* - * IE uses this a lot for activating things such as windows media - * player. This is not verified to be fully correct but it appears - * to work just fine. - */ - case 'l': - case 'L': - if (lpFile) { - strcpyW(res, lpFile); - res += strlenW(lpFile); - } - break; - - case 'i': - case 'I': - if (pidl) { - HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0); - pv = SHLockShared(hmem, 0); - res += sprintfW(res, wszILPtr, pv); - SHUnlockShared(pv); - } - break; - - default: - /* - * Check if this is a env-variable here... - */ - - /* Make sure that we have at least one more %.*/ - if (strchrW(fmt, '%')) - { - WCHAR tmpBuffer[1024]; - PWSTR tmpB = tmpBuffer; - WCHAR tmpEnvBuff[MAX_PATH]; - DWORD envRet; - - while (*fmt != '%') - *tmpB++ = *fmt++; - *tmpB++ = 0; - - TRACE("Checking %s to be a env-var\n", debugstr_w(tmpBuffer)); - - envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH); - if (envRet == 0 || envRet > MAX_PATH) - strcpyW( res, tmpBuffer ); - else - strcpyW( res, tmpEnvBuff ); - res += strlenW(res); - } - done = TRUE; - break; - } - /* Don't skip past terminator (catch a single '%' at the end) */ - if (*fmt != '\0') - { - fmt++; - } - } - else - *res++ = *fmt++; - } - - *res = '\0'; - - return done; -} - -HRESULT SHELL_GetPathFromIDListForExecuteA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize) -{ - STRRET strret; - IShellFolder* desktop; - - HRESULT hr = SHGetDesktopFolder(&desktop); - - if (SUCCEEDED(hr)) { - hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret); - - if (SUCCEEDED(hr)) - StrRetToStrNA(pszPath, uOutSize, &strret, pidl); - - IShellFolder_Release(desktop); - } - - return hr; -} - -HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize) -{ - STRRET strret; - IShellFolder* desktop; - - HRESULT hr = SHGetDesktopFolder(&desktop); - - if (SUCCEEDED(hr)) { - hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret); - - if (SUCCEEDED(hr)) - StrRetToStrNW(pszPath, uOutSize, &strret, pidl); - - IShellFolder_Release(desktop); - } - - return hr; -} - -/************************************************************************* - * SHELL_ResolveShortCutW [Internal] - * read shortcut file at 'wcmd' - */ -static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl) -{ - IShellFolder* psf; - - HRESULT hr = SHGetDesktopFolder(&psf); - - *ppidl = NULL; - - if (SUCCEEDED(hr)) { - LPITEMIDLIST pidl; - ULONG l; - - hr = IShellFolder_ParseDisplayName(psf, 0, 0, wcmd, &l, &pidl, 0); - - if (SUCCEEDED(hr)) { - IShellLinkW* psl; - - hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, (LPCITEMIDLIST*)&pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl); - - if (SUCCEEDED(hr)) { - hr = IShellLinkW_Resolve(psl, hwnd, 0); - - if (SUCCEEDED(hr)) { - hr = IShellLinkW_GetPath(psl, wcmd, MAX_PATH, NULL, SLGP_UNCPRIORITY); - - if (SUCCEEDED(hr)) { - if (!*wcmd) { - /* We could not translate the PIDL in the shell link into a valid file system path - so return the PIDL instead. */ - hr = IShellLinkW_GetIDList(psl, ppidl); - - if (SUCCEEDED(hr) && *ppidl) { - /* We got a PIDL instead of a file system path - try to translate it. */ - if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) { - SHFree(*ppidl); - *ppidl = NULL; - } - } - } - - if (SUCCEEDED(hr)) { - /* get command line arguments, working directory and display mode if available */ - IShellLinkW_GetWorkingDirectory(psl, wdir, MAX_PATH); - IShellLinkW_GetArguments(psl, wargs, MAX_PATH); - IShellLinkW_GetShowCmd(psl, pshowcmd); - } - } - } - - IShellLinkW_Release(psl); - } - - SHFree(pidl); - } - - IShellFolder_Release(psf); - } - - return hr; -} - -/************************************************************************* - * SHELL_ExecuteW [Internal] - * - */ -static UINT SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, - LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) -{ - STARTUPINFOW startup; - PROCESS_INFORMATION info; - UINT retval = 31; - UINT gcdret = 0; - WCHAR curdir[MAX_PATH]; - - TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory)); - /* ShellExecute specifies the command from psei->lpDirectory - * if present. Not from the current dir as CreateProcess does */ - if( psei->lpDirectory && psei->lpDirectory[0] ) - if( ( gcdret = GetCurrentDirectoryW( MAX_PATH, curdir))) - if( !SetCurrentDirectoryW( psei->lpDirectory)) - ERR("cannot set directory %s\n", debugstr_w(psei->lpDirectory)); - ZeroMemory(&startup,sizeof(STARTUPINFOW)); - startup.cb = sizeof(STARTUPINFOW); - startup.dwFlags = STARTF_USESHOWWINDOW; - startup.wShowWindow = psei->nShow; - if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, - env, *psei->lpDirectory? psei->lpDirectory: NULL, &startup, &info)) - { - /* Give 30 seconds to the app to come up, if desired. Probably only needed - when starting app immediately before making a DDE connection. */ - if (shWait) - if (WaitForInputIdle( info.hProcess, 30000 ) == WAIT_FAILED) - WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() ); - retval = 33; - if (psei->fMask & SEE_MASK_NOCLOSEPROCESS) - psei_out->hProcess = info.hProcess; - else - CloseHandle( info.hProcess ); - CloseHandle( info.hThread ); - } - else if ((retval = GetLastError()) >= 32) - { - FIXME("Strange error set by CreateProcess: %d\n", retval); - retval = ERROR_BAD_FORMAT; - } - - TRACE("returning %u\n", retval); - - psei_out->hInstApp = (HINSTANCE)retval; - if( gcdret ) - if( !SetCurrentDirectoryW( curdir)) - ERR("cannot return to directory %s\n", debugstr_w(curdir)); - - return retval; -} - - -/*********************************************************************** - * SHELL_BuildEnvW [Internal] - * - * Build the environment for the new process, adding the specified - * path to the PATH variable. Returned pointer must be freed by caller. - */ -static void *SHELL_BuildEnvW( const WCHAR *path ) -{ - static const WCHAR wPath[] = {'P','A','T','H','=',0}; - WCHAR *strings, *new_env; - WCHAR *p, *p2; - int total = strlenW(path) + 1; - BOOL got_path = FALSE; - - if (!(strings = GetEnvironmentStringsW())) return NULL; - p = strings; - while (*p) - { - int len = strlenW(p) + 1; - if (!strncmpiW( p, wPath, 5 )) got_path = TRUE; - total += len; - p += len; - } - if (!got_path) total += 5; /* we need to create PATH */ - total++; /* terminating null */ - - if (!(new_env = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) ))) - { - FreeEnvironmentStringsW( strings ); - return NULL; - } - p = strings; - p2 = new_env; - while (*p) - { - int len = strlenW(p) + 1; - memcpy( p2, p, len * sizeof(WCHAR) ); - if (!strncmpiW( p, wPath, 5 )) - { - p2[len - 1] = ';'; - strcpyW( p2 + len, path ); - p2 += strlenW(path) + 1; - } - p += len; - p2 += len; - } - if (!got_path) - { - strcpyW( p2, wPath ); - strcatW( p2, path ); - p2 += strlenW(p2) + 1; - } - *p2 = 0; - FreeEnvironmentStringsW( strings ); - return new_env; -} - - -/*********************************************************************** - * SHELL_TryAppPathW [Internal] - * - * Helper function for SHELL_FindExecutable - * @param lpResult - pointer to a buffer of size MAX_PATH - * On entry: szName is a filename (probably without path separators). - * On exit: if szName found in "App Path", place full path in lpResult, and return true - */ -static BOOL SHELL_TryAppPathW( LPCWSTR szName, LPWSTR lpResult, WCHAR **env) -{ - static const WCHAR wszKeyAppPaths[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s', - '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p',' ','P','a','t','h','s','\\',0}; - static const WCHAR wPath[] = {'P','a','t','h',0}; - HKEY hkApp = 0; - WCHAR buffer[1024]; - LONG len; - LONG res; - BOOL found = FALSE; - - if (env) *env = NULL; - strcpyW(buffer, wszKeyAppPaths); - strcatW(buffer, szName); - res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buffer, 0, KEY_READ, &hkApp); - if (res) goto end; - - len = MAX_PATH*sizeof(WCHAR); - res = RegQueryValueW(hkApp, NULL, lpResult, &len); - if (res) goto end; - found = TRUE; - - if (env) - { - DWORD count = sizeof(buffer); - if (!RegQueryValueExW(hkApp, wPath, NULL, NULL, (LPBYTE)buffer, &count) && buffer[0]) - *env = SHELL_BuildEnvW( buffer ); - } - -end: - if (hkApp) RegCloseKey(hkApp); - return found; -} - -static UINT SHELL_FindExecutableByOperation(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen) -{ - static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0}; - - /* Looking for ...buffer\shell\\command */ - strcatW(filetype, wszShell); - strcatW(filetype, lpOperation); - strcatW(filetype, wCommand); - - if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command, - &commandlen) == ERROR_SUCCESS) - { - commandlen /= sizeof(WCHAR); - if (key) strcpyW(key, filetype); -#if 0 - LPWSTR tmp; - WCHAR param[256]; - LONG paramlen = sizeof(param); - static const WCHAR wSpace[] = {' ',0}; - - /* FIXME: it seems all Windows version don't behave the same here. - * the doc states that this ddeexec information can be found after - * the exec names. - * on Win98, it doesn't appear, but I think it does on Win2k - */ - /* Get the parameters needed by the application - from the associated ddeexec key */ - tmp = strstrW(filetype, wCommand); - tmp[0] = '\0'; - strcatW(filetype, wDdeexec); - if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param, - ¶mlen) == ERROR_SUCCESS) - { - paramlen /= sizeof(WCHAR); - strcatW(command, wSpace); - strcatW(command, param); - commandlen += paramlen; - } -#endif - - command[commandlen] = '\0'; - - return 33; /* FIXME see SHELL_FindExecutable() */ - } - - return 31; /* default - 'No association was found' */ -} - -/************************************************************************* - * SHELL_FindExecutable [Internal] - * - * Utility for code sharing between FindExecutable and ShellExecute - * in: - * lpFile the name of a file - * lpOperation the operation on it (open) - * out: - * lpResult a buffer, big enough :-(, to store the command to do the - * operation on the file - * key a buffer, big enough, to get the key name to do actually the - * command (it'll be used afterwards for more information - * on the operation) - */ -UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, - LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args) -{ - static const WCHAR wWindows[] = {'w','i','n','d','o','w','s',0}; - static const WCHAR wPrograms[] = {'p','r','o','g','r','a','m','s',0}; - static const WCHAR wExtensions[] = {'e','x','e',' ','p','i','f',' ','b','a','t',' ','c','m','d',' ','c','o','m',0}; - WCHAR *extension = NULL; /* pointer to file extension */ - WCHAR filetype[256]; /* registry name for this filetype */ - LONG filetypelen = sizeof(filetype); /* length of above */ - WCHAR command[1024]; /* command from registry */ - WCHAR wBuffer[256]; /* Used to GetProfileString */ - UINT retval = 31; /* default - 'No association was found' */ - WCHAR *tok; /* token pointer */ - WCHAR xlpFile[256]; /* result of SearchPath */ - DWORD attribs; /* file attributes */ - - TRACE("%s\n", (lpFile != NULL) ? debugstr_w(lpFile) : "-"); - - xlpFile[0] = '\0'; - lpResult[0] = '\0'; /* Start off with an empty return string */ - if (key) *key = '\0'; - - /* trap NULL parameters on entry */ - if ((lpFile == NULL) || (lpResult == NULL) || (lpOperation == NULL)) - { - WARN("(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n", - debugstr_w(lpFile), debugstr_w(lpOperation), debugstr_w(lpResult)); - return 2; /* File not found. Close enough, I guess. */ - } - - if (SHELL_TryAppPathW( lpFile, lpResult, env )) - { - TRACE("found %s via App Paths\n", debugstr_w(lpResult)); - return 33; - } - - if (SearchPathW(lpPath, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL)) - { - TRACE("SearchPathW returned non-zero\n"); - lpFile = xlpFile; - /* Hey, isn't this value ignored? Why make this call? Shouldn't we return here? --dank*/ - } - - attribs = GetFileAttributesW(lpFile); - if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY)) - { - strcpyW(filetype, wszFolder); - filetypelen = 6; /* strlen("Folder") */ - } - else - { - /* First thing we need is the file's extension */ - extension = strrchrW(xlpFile, '.'); /* Assume last "." is the one; */ - /* File->Run in progman uses */ - /* .\FILE.EXE :( */ - TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension)); - - if (extension == NULL || extension[1]==0) - { - WARN("Returning 31 - No association\n"); - return 31; /* no association */ - } - - /* Three places to check: */ - /* 1. win.ini, [windows], programs (NB no leading '.') */ - /* 2. Registry, HKEY_CLASS_ROOT\\shell\open\command */ - /* 3. win.ini, [extensions], extension (NB no leading '.' */ - /* All I know of the order is that registry is checked before */ - /* extensions; however, it'd make sense to check the programs */ - /* section first, so that's what happens here. */ - - /* See if it's a program - if GetProfileString fails, we skip this - * section. Actually, if GetProfileString fails, we've probably - * got a lot more to worry about than running a program... */ - if (GetProfileStringW(wWindows, wPrograms, wExtensions, wBuffer, sizeof(wBuffer)/sizeof(WCHAR)) > 0) - { - CharLowerW(wBuffer); - tok = wBuffer; - while (*tok) - { - WCHAR *p = tok; - while (*p && *p != ' ' && *p != '\t') p++; - if (*p) - { - *p++ = 0; - while (*p == ' ' || *p == '\t') p++; - } - - if (strcmpiW(tok, &extension[1]) == 0) /* have to skip the leading "." */ - { - strcpyW(lpResult, xlpFile); - /* Need to perhaps check that the file has a path - * attached */ - TRACE("found %s\n", debugstr_w(lpResult)); - return 33; - - /* Greater than 32 to indicate success FIXME According to the - * docs, I should be returning a handle for the - * executable. Does this mean I'm supposed to open the - * executable file or something? More RTFM, I guess... */ - } - tok = p; - } - } - - /* Check registry */ - if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, filetype, - &filetypelen) == ERROR_SUCCESS) - { - filetypelen /= sizeof(WCHAR); - filetype[filetypelen] = '\0'; - TRACE("File type: %s\n", debugstr_w(filetype)); - } - } - - if (*filetype) - { - if (lpOperation) - { - /* pass the operation string to SHELL_FindExecutableByOperation() */ - filetype[filetypelen] = '\0'; - retval = SHELL_FindExecutableByOperation(lpPath, lpFile, lpOperation, key, filetype, command, sizeof(command)); - } - else - { - WCHAR operation[MAX_PATH]; - HKEY hkey; - - /* Looking for ...buffer\shell\\command */ - strcatW(filetype, wszShell); - - /* enumerate the operation subkeys in the registry and search for one with an associated command */ - if (RegOpenKeyW(HKEY_CLASSES_ROOT, filetype, &hkey) == ERROR_SUCCESS) - { - int idx = 0; - for(;; ++idx) - { - if (RegEnumKeyW(hkey, idx, operation, MAX_PATH) != ERROR_SUCCESS) - break; - - filetype[filetypelen] = '\0'; - retval = SHELL_FindExecutableByOperation(lpPath, lpFile, operation, key, filetype, command, sizeof(command)); - - if (retval > 32) - break; - } - RegCloseKey(hkey); - } - } - - if (retval > 32) - { - SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args); - - /* Remove double quotation marks and command line arguments */ - if (*lpResult == '"') - { - WCHAR *p = lpResult; - while (*(p + 1) != '"') - { - *p = *(p + 1); - p++; - } - *p = '\0'; - } - } - } - else /* Check win.ini */ - { - static const WCHAR wExtensions[] = {'e','x','t','e','n','s','i','o','n','s',0}; - - /* Toss the leading dot */ - extension++; - if (GetProfileStringW(wExtensions, extension, wszEmpty, command, sizeof(command)/sizeof(WCHAR)) > 0) - { - if (strlenW(command) != 0) - { - strcpyW(lpResult, command); - tok = strchrW(lpResult, '^'); /* should be ^.extension? */ - if (tok != NULL) - { - tok[0] = '\0'; - strcatW(lpResult, xlpFile); /* what if no dir in xlpFile? */ - tok = strchrW(command, '^'); /* see above */ - if ((tok != NULL) && (strlenW(tok)>5)) - { - strcatW(lpResult, &tok[5]); - } - } - retval = 33; /* FIXME - see above */ - } - } - } - - TRACE("returning %s\n", debugstr_w(lpResult)); - return retval; -} - -/****************************************************************** - * dde_cb - * - * callback for the DDE connection. not really usefull - */ -static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv, - HSZ hsz1, HSZ hsz2, HDDEDATA hData, - ULONG_PTR dwData1, ULONG_PTR dwData2) -{ - TRACE("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n", - uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2); - return NULL; -} - -/****************************************************************** - * dde_connect - * - * ShellExecute helper. Used to do an operation with a DDE connection - * - * Handles both the direct connection (try #1), and if it fails, - * launching an application and trying (#2) to connect to it - * - */ -static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec, - const WCHAR* lpFile, WCHAR *env, - LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc, - LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) -{ - static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0}; - static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0}; - WCHAR * endkey = key + strlenW(key); - WCHAR app[256], topic[256], ifexec[256], res[256]; - LONG applen, topiclen, ifexeclen; - WCHAR * exec; - DWORD ddeInst = 0; - DWORD tid; - HSZ hszApp, hszTopic; - HCONV hConv; - HDDEDATA hDdeData; - unsigned ret = 31; - - strcpyW(endkey, wApplication); - applen = sizeof(app); - if (RegQueryValueW(HKEY_CLASSES_ROOT, key, app, &applen) != ERROR_SUCCESS) - { - FIXME("default app name NIY %s\n", debugstr_w(key)); - return 2; - } - - strcpyW(endkey, wTopic); - topiclen = sizeof(topic); - if (RegQueryValueW(HKEY_CLASSES_ROOT, key, topic, &topiclen) != ERROR_SUCCESS) - { - static const WCHAR wSystem[] = {'S','y','s','t','e','m',0}; - strcpyW(topic, wSystem); - } - - if (DdeInitializeW(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR) - { - return 2; - } - - hszApp = DdeCreateStringHandleW(ddeInst, app, CP_WINUNICODE); - hszTopic = DdeCreateStringHandleW(ddeInst, topic, CP_WINUNICODE); - - hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL); - exec = ddeexec; - if (!hConv) - { - static const WCHAR wIfexec[] = {'\\','i','f','e','x','e','c',0}; - TRACE("Launching '%s'\n", debugstr_w(start)); - ret = execfunc(start, env, TRUE, psei, psei_out); - if (ret < 32) - { - TRACE("Couldn't launch\n"); - goto error; - } - hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL); - if (!hConv) - { - TRACE("Couldn't connect. ret=%d\n", ret); - DdeUninitialize(ddeInst); - SetLastError(ERROR_DDE_FAIL); - return 30; /* whatever */ - } - strcpyW(endkey, wIfexec); - ifexeclen = sizeof(ifexec); - if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ifexec, &ifexeclen) == ERROR_SUCCESS) - { - exec = ifexec; - } - } - - SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile, pidl, szCommandline); - TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res)); - - /* It's documented in the KB 330337 that IE has a bug and returns - * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request. - */ - hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, - XTYP_EXECUTE, 10000, &tid); - if (hDdeData) - DdeFreeDataHandle(hDdeData); - else - WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst)); - ret = 33; - - DdeDisconnect(hConv); - - error: - DdeUninitialize(ddeInst); - - return ret; -} - -/************************************************************************* - * execute_from_key [Internal] - */ -static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline, - SHELL_ExecuteW32 execfunc, - LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) -{ - WCHAR cmd[1024]; - LONG cmdlen = sizeof(cmd); - UINT retval = 31; - - cmd[0] = '\0'; - - /* Get the application for the registry */ - if (RegQueryValueW(HKEY_CLASSES_ROOT, key, cmd, &cmdlen) == ERROR_SUCCESS) - { - static const WCHAR wCommand[] = {'c','o','m','m','a','n','d',0}; - static const WCHAR wDdeexec[] = {'d','d','e','e','x','e','c',0}; - LPWSTR tmp; - WCHAR param[256]; - LONG paramlen = sizeof(param); - - param[0] = '\0'; - - /* Get the parameters needed by the application - from the associated ddeexec key */ - tmp = strstrW(key, wCommand); - assert(tmp); - strcpyW(tmp, wDdeexec); - - if (RegQueryValueW(HKEY_CLASSES_ROOT, key, param, ¶mlen) == ERROR_SUCCESS) - { - TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(param)); - retval = dde_connect(key, cmd, param, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out); - } - else - { - /* Is there a replace() function anywhere? */ - cmdlen /= sizeof(WCHAR); - cmd[cmdlen] = '\0'; - SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline); - retval = execfunc(param, env, FALSE, psei, psei_out); - } - } - else TRACE("ooch\n"); - - return retval; -} - -/************************************************************************* - * FindExecutableA [SHELL32.@] - */ -HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult) -{ - HINSTANCE retval; - WCHAR *wFile = NULL, *wDirectory = NULL; - WCHAR wResult[MAX_PATH]; - - if (lpFile) __SHCloneStrAtoW(&wFile, lpFile); - if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory); - - retval = FindExecutableW(wFile, wDirectory, wResult); - WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL); - if (wFile) SHFree( wFile ); - if (wDirectory) SHFree( wDirectory ); - - TRACE("returning %s\n", lpResult); - return (HINSTANCE)retval; -} - -/************************************************************************* - * FindExecutableW [SHELL32.@] - */ -HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult) -{ - UINT retval = 31; /* default - 'No association was found' */ - WCHAR old_dir[1024]; - - TRACE("File %s, Dir %s\n", - (lpFile != NULL ? debugstr_w(lpFile) : "-"), (lpDirectory != NULL ? debugstr_w(lpDirectory) : "-")); - - lpResult[0] = '\0'; /* Start off with an empty return string */ - - /* trap NULL parameters on entry */ - if ((lpFile == NULL) || (lpResult == NULL)) - { - /* FIXME - should throw a warning, perhaps! */ - return (HINSTANCE)2; /* File not found. Close enough, I guess. */ - } - - if (lpDirectory) - { - GetCurrentDirectoryW(sizeof(old_dir)/sizeof(WCHAR), old_dir); - SetCurrentDirectoryW(lpDirectory); - } - - retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL); - - TRACE("returning %s\n", debugstr_w(lpResult)); - if (lpDirectory) - SetCurrentDirectoryW(old_dir); - return (HINSTANCE)retval; -} - -/************************************************************************* - * ShellExecuteExW32 [Internal] - */ -BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc) -{ - static const WCHAR wQuote[] = {'"',0}; - static const WCHAR wSpace[] = {' ',0}; - static const WCHAR wWww[] = {'w','w','w',0}; - static const WCHAR wFile[] = {'f','i','l','e',0}; - static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0}; - static const WCHAR wExtLnk[] = {'.','l','n','k',0}; - static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0}; - - WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH]; - SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */ - WCHAR wfileName[MAX_PATH]; - WCHAR *env; - WCHAR lpstrProtocol[256]; - LPCWSTR lpFile; - UINT retval = 31; - WCHAR wcmd[1024]; - WCHAR buffer[MAX_PATH]; - const WCHAR* ext; - BOOL done; - - /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */ - memcpy(&sei_tmp, sei, sizeof(sei_tmp)); - - TRACE("mask=0x%08lx hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n", - sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb), - debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters), - debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow, - (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei_tmp.lpClass) : "not used"); - - sei->hProcess = NULL; - - /* make copies of all path/command strings */ - if (sei_tmp.lpFile) - strcpyW(wszApplicationName, sei_tmp.lpFile); - else - *wszApplicationName = '\0'; - - if (sei_tmp.lpParameters) - strcpyW(wszParameters, sei_tmp.lpParameters); - else - *wszParameters = '\0'; - - if (sei_tmp.lpDirectory) - strcpyW(wszDir, sei_tmp.lpDirectory); - else - *wszDir = '\0'; - - /* adjust string pointers to point to the new buffers */ - sei_tmp.lpFile = wszApplicationName; - sei_tmp.lpParameters = wszParameters; - sei_tmp.lpDirectory = wszDir; - - if (sei_tmp.fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY | - SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | - SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE | - SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR )) - { - FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask); - } - - /* process the IDList */ - if (sei_tmp.fMask & SEE_MASK_IDLIST) - { - IShellExecuteHookW* pSEH; - - HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL); - - if (SUCCEEDED(hr)) - { - hr = IShellExecuteHookW_Execute(pSEH, sei); - - IShellExecuteHookW_Release(pSEH); - - if (hr == S_OK) - return TRUE; - } - - wszApplicationName[0] = '"'; - SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName+1); - strcatW(wszApplicationName, wQuote); - TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName)); - } - - if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)) - { - /* launch a document by fileclass like 'WordPad.Document.1' */ - /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */ - /* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */ - HCR_GetExecuteCommandW((sei_tmp.fMask & SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL, - (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL, - (sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen, - wszParameters, sizeof(wszParameters)/sizeof(WCHAR)); - - /* FIXME: get the extension of lpFile, check if it fits to the lpClass */ - TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", debugstr_w(wszParameters), debugstr_w(wszApplicationName)); - - wcmd[0] = '\0'; - done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszParameters, wszApplicationName, sei_tmp.lpIDList, NULL); - if (!done && wszApplicationName[0]) - { - strcatW(wcmd, wSpace); - strcatW(wcmd, wszApplicationName); - } - retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei); - if (retval > 32) - return TRUE; - else - return FALSE; - } - - - /* resolve shell shortcuts */ - ext = PathFindExtensionW(sei_tmp.lpFile); - - if (ext && !strncmpiW(ext, wExtLnk, sizeof(wExtLnk) / sizeof(WCHAR) - 1) && - (ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '\0' || - (sei_tmp.lpFile[0] == '"' && ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '"'))) /* or check for: shell_attribs & SFGAO_LINK */ - { - HRESULT hr; - BOOL Quoted; - - if (wszApplicationName[0] == '"') - { - if (wszApplicationName[strlenW(wszApplicationName) - 1] == '"') - { - wszApplicationName[strlenW(wszApplicationName) - 1] = '\0'; - Quoted = TRUE; - } - else - { - Quoted = FALSE; - } - } - else - { - Quoted = FALSE; - } - /* expand paths before reading shell link */ - if (ExpandEnvironmentStringsW(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile, buffer, MAX_PATH)) - lstrcpyW(Quoted ? wszApplicationName + 1 : wszApplicationName/*sei_tmp.lpFile*/, buffer); - - if (*sei_tmp.lpParameters) - if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH)) - lstrcpyW(wszParameters/*sei_tmp.lpParameters*/, buffer); - - hr = SHELL_ResolveShortCutW((LPWSTR)(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile), - (LPWSTR)sei_tmp.lpParameters, (LPWSTR)sei_tmp.lpDirectory, - sei_tmp.hwnd, sei_tmp.lpVerb?sei_tmp.lpVerb:wszEmpty, &sei_tmp.nShow, (LPITEMIDLIST*)&sei_tmp.lpIDList); - if (Quoted) - { - wszApplicationName[strlenW(wszApplicationName) + 1] = '\0'; - wszApplicationName[strlenW(wszApplicationName)] = '"'; - } - - if (sei->lpIDList) - sei->fMask |= SEE_MASK_IDLIST; - - if (SUCCEEDED(hr)) - { - /* repeat IDList processing if needed */ - if (sei_tmp.fMask & SEE_MASK_IDLIST) - { - IShellExecuteHookW* pSEH; - - HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL); - - if (SUCCEEDED(hr)) - { - hr = IShellExecuteHookW_Execute(pSEH, sei); - - IShellExecuteHookW_Release(pSEH); - - if (hr == S_OK) - return TRUE; - } - - TRACE("-- idlist=%p (%s)\n", debugstr_w(sei_tmp.lpIDList), debugstr_w(sei_tmp.lpFile)); - } - } - } - - - /* Has the IDList not yet been translated? */ - if (sei_tmp.fMask & SEE_MASK_IDLIST) - { - /* last chance to translate IDList: now also allow CLSID paths */ - if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, buffer, sizeof(buffer)))) { - if (buffer[0]==':' && buffer[1]==':') { - /* open shell folder for the specified class GUID */ - strcpyW(wszParameters, buffer); - strcpyW(wszApplicationName, wExplorer); - - sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; - } else if (HCR_GetExecuteCommandW(0, wszFolder, sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, buffer, sizeof(buffer))) { - SHELL_ArgifyW(wszApplicationName, sizeof(wszApplicationName)/sizeof(WCHAR), buffer, NULL, sei_tmp.lpIDList, NULL); - - sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; - } - } - } - - /* expand environment strings */ - if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH)) - lstrcpyW(wszApplicationName, buffer); - - if (*sei_tmp.lpParameters) - if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH)) - lstrcpyW(wszParameters, buffer); - - if (*sei_tmp.lpDirectory) - if (ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buffer, MAX_PATH)) - lstrcpyW(wszDir, buffer); - - /* Else, try to execute the filename */ - TRACE("execute:%s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir)); - - /* separate out command line arguments from executable file name */ - if (!*sei_tmp.lpParameters) { - /* If the executable path is quoted, handle the rest of the command line as parameters. */ - if (sei_tmp.lpFile[0] == '"') { - LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1; - LPWSTR dst = wfileName; - LPWSTR end; - - /* copy the unquoted executable path to 'wfileName' */ - while(*src && *src!='"') - *dst++ = *src++; - - *dst = '\0'; - - if (*src == '"') { - end = ++src; - - while(isspace(*src)) - ++src; - } else - end = src; - - /* copy the parameter string to 'wszParameters' */ - strcpyW(wszParameters, src); - - /* terminate previous command string after the quote character */ - *end = '\0'; - } - else - { - /* If the executable name is not quoted, we have to use this search loop here, - that in CreateProcess() is not sufficient because it does not handle shell links. */ - WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH]; - LPWSTR space, s; - - LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/; - for(s=beg; (space=strchrW(s, ' ')); s=space+1) { - int idx = space-sei_tmp.lpFile; - strncpyW(buffer, sei_tmp.lpFile, idx); - buffer[idx] = '\0'; - - /*FIXME This finds directory paths if the targeted file name contains spaces. */ - if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, buffer, wszExe, sizeof(xlpFile), xlpFile, NULL)) - { - /* separate out command from parameter string */ - LPCWSTR p = space + 1; - - while(isspaceW(*p)) - ++p; - - strcpyW(wszParameters, p); - *space = '\0'; - - break; - } - } - - strcpyW(wfileName, sei_tmp.lpFile); - } - } else - strcpyW(wfileName, sei_tmp.lpFile); - - lpFile = wfileName; - - if (sei_tmp.lpParameters[0]) { - strcatW(wszApplicationName, wSpace); - strcatW(wszApplicationName, wszParameters); - } - - /* We set the default to open, and that should generally work. - But that is not really the way the MS docs say to do it. */ - if (!sei_tmp.lpVerb) - sei_tmp.lpVerb = wszOpen; - - retval = execfunc(wszApplicationName, NULL, FALSE, &sei_tmp, sei); - if (retval > 32) - return TRUE; - - /* Else, try to find the executable */ - wcmd[0] = '\0'; - retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters); - if (retval > 32) /* Found */ - { - WCHAR wszQuotedCmd[MAX_PATH+2]; - /* Must quote to handle case where cmd contains spaces, - * else security hole if malicious user creates executable file "C:\\Program" - */ - strcpyW(wszQuotedCmd, wQuote); - strcatW(wszQuotedCmd, wcmd); - strcatW(wszQuotedCmd, wQuote); - if (wszParameters[0]) { - strcatW(wszQuotedCmd, wSpace); - strcatW(wszQuotedCmd, wszParameters); - } - TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol)); - if (*lpstrProtocol) - retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei); - else - retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei); - if (env) HeapFree( GetProcessHeap(), 0, env ); - } - else if (PathIsURLW((LPWSTR)lpFile)) /* File not found, check for URL */ - { - static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0}; - static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0}; - LPWSTR lpstrRes; - INT iSize; - - lpstrRes = strchrW(lpFile, ':'); - if (lpstrRes) - iSize = lpstrRes - lpFile; - else - iSize = strlenW(lpFile); - - TRACE("Got URL: %s\n", debugstr_w(lpFile)); - /* Looking for ...protocol\shell\lpOperation\command */ - strncpyW(lpstrProtocol, lpFile, iSize); - lpstrProtocol[iSize] = '\0'; - strcatW(lpstrProtocol, wShell); - strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen); - strcatW(lpstrProtocol, wCommand); - - /* Remove File Protocol from lpFile */ - /* In the case file://path/file */ - if (!strncmpiW(lpFile, wFile, iSize)) - { - lpFile += iSize; - while (*lpFile == ':') lpFile++; - } - retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei_tmp.lpParameters, execfunc, &sei_tmp, sei); - } - /* Check if file specified is in the form www.??????.*** */ - else if (!strncmpiW(lpFile, wWww, 3)) - { - /* if so, append lpFile http:// and call ShellExecute */ - WCHAR lpstrTmpFile[256]; - strcpyW(lpstrTmpFile, wHttp); - strcatW(lpstrTmpFile, lpFile); - retval = (UINT)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0); - } - - TRACE("retval %u\n", retval); - - if (retval <= 32) - { - sei->hInstApp = (HINSTANCE)retval; - return FALSE; - } - - sei->hInstApp = (HINSTANCE)33; - return TRUE; -} - -/************************************************************************* - * ShellExecuteA [SHELL32.290] - */ -HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile, - LPCSTR lpParameters,LPCSTR lpDirectory, INT iShowCmd) -{ - SHELLEXECUTEINFOA sei; - HANDLE hProcess = 0; - - TRACE("%p,%s,%s,%s,%s,%d\n", - hWnd, lpOperation, lpFile, lpParameters, lpDirectory, iShowCmd); - - sei.cbSize = sizeof(sei); - sei.fMask = 0; - sei.hwnd = hWnd; - sei.lpVerb = lpOperation; - sei.lpFile = lpFile; - sei.lpParameters = lpParameters; - sei.lpDirectory = lpDirectory; - sei.nShow = iShowCmd; - sei.lpIDList = 0; - sei.lpClass = 0; - sei.hkeyClass = 0; - sei.dwHotKey = 0; - sei.hProcess = hProcess; - - ShellExecuteExA (&sei); - return sei.hInstApp; -} - -/************************************************************************* - * ShellExecuteEx [SHELL32.291] - * - */ -BOOL WINAPI ShellExecuteExAW (LPVOID sei) -{ - if (SHELL_OsIsUnicode()) - return ShellExecuteExW32 (sei, SHELL_ExecuteW); - return ShellExecuteExA (sei); -} - -/************************************************************************* - * ShellExecuteExA [SHELL32.292] - * - */ -BOOL WINAPI ShellExecuteExA (LPSHELLEXECUTEINFOA sei) -{ - SHELLEXECUTEINFOW seiW; - BOOL ret; - WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL; - - TRACE("%p\n", sei); - - memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW)); - - if (sei->lpVerb) - seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb); - - if (sei->lpFile) - seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile); - - if (sei->lpParameters) - seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters); - - if (sei->lpDirectory) - seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory); - - if ((sei->fMask & SEE_MASK_CLASSNAME) && sei->lpClass) - seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass); - else - seiW.lpClass = NULL; - - ret = ShellExecuteExW32 (&seiW, SHELL_ExecuteW); - - sei->hInstApp = seiW.hInstApp; - - if (wVerb) SHFree(wVerb); - if (wFile) SHFree(wFile); - if (wParameters) SHFree(wParameters); - if (wDirectory) SHFree(wDirectory); - if (wClass) SHFree(wClass); - - return ret; -} - -/************************************************************************* - * ShellExecuteExW [SHELL32.293] - * - */ -BOOL WINAPI ShellExecuteExW (LPSHELLEXECUTEINFOW sei) -{ - return ShellExecuteExW32 (sei, SHELL_ExecuteW); -} - -/************************************************************************* - * ShellExecuteW [SHELL32.294] - * from shellapi.h - * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, - * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd); - */ -HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, - LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd) -{ - SHELLEXECUTEINFOW sei; - HANDLE hProcess = 0; - - TRACE("\n"); - sei.cbSize = sizeof(sei); - sei.fMask = 0; - sei.hwnd = hwnd; - sei.lpVerb = lpOperation; - sei.lpFile = lpFile; - sei.lpParameters = lpParameters; - sei.lpDirectory = lpDirectory; - sei.nShow = nShowCmd; - sei.lpIDList = 0; - sei.lpClass = 0; - sei.hkeyClass = 0; - sei.dwHotKey = 0; - sei.hProcess = hProcess; - - ShellExecuteExW32 (&sei, SHELL_ExecuteW); - return sei.hInstApp; -} +/* + * Shell Library Functions + * + * Copyright 1998 Marcus Meissner + * Copyright 2002 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "ddeml.h" + +#include "wine/winbase16.h" +#include "shell32_main.h" +#include "pidl.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(exec); + +static const WCHAR wszOpen[] = {'o','p','e','n',0}; +static const WCHAR wszExe[] = {'.','e','x','e',0}; +static const WCHAR wszILPtr[] = {':','%','p',0}; +static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0}; +static const WCHAR wszFolder[] = {'F','o','l','d','e','r',0}; +static const WCHAR wszEmpty[] = {0}; + + +/*********************************************************************** + * SHELL_ArgifyW [Internal] + * + * this function is supposed to expand the escape sequences found in the registry + * some diving reported that the following were used: + * + %1, %2... seem to report to parameter of index N in ShellExecute pmts + * %1 file + * %2 printer + * %3 driver + * %4 port + * %I address of a global item ID (explorer switch /idlist) + * %L seems to be %1 as long filename followed by the 8+3 variation + * %S ??? + * %* all following parameters (see batfile) + * + * FIXME: use 'len' + * FIXME: Careful of going over string boundaries. No checking is done to 'res'... + */ +static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args) +{ + WCHAR xlpFile[1024]; + BOOL done = FALSE; + PWSTR res = out; + PCWSTR cmd; + LPVOID pv; + + TRACE("%p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt), + debugstr_w(lpFile), pidl, args); + + while (*fmt) + { + if (*fmt == '%') + { + switch (*++fmt) + { + case '\0': + case '%': + *res++ = '%'; + break; + + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + case '*': + if (args) + { + if (*fmt == '*') + { + *res++ = '"'; + while(*args) + *res++ = *args++; + *res++ = '"'; + } + else + { + while(*args && !isspace(*args)) + *res++ = *args++; + + while(isspace(*args)) + ++args; + } + break; + } + /* else fall through */ + case '1': + if (!done || (*fmt == '1')) + { + /*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */ + if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL)) + cmd = xlpFile; + else + cmd = lpFile; + + /* Add double quotation marks unless we already have them + (e.g.: "file://%1" %* for exefile) or unless the arg is already + enclosed in double quotation marks */ + if ((res == out || *(fmt + 1) != '"') && *cmd != '"') + { + *res++ = '"'; + strcpyW(res, cmd); + res += strlenW(cmd); + *res++ = '"'; + } + else + { + strcpyW(res, cmd); + res += strlenW(cmd); + } + } + break; + + /* + * IE uses this a lot for activating things such as windows media + * player. This is not verified to be fully correct but it appears + * to work just fine. + */ + case 'l': + case 'L': + if (lpFile) { + strcpyW(res, lpFile); + res += strlenW(lpFile); + } + break; + + case 'i': + case 'I': + if (pidl) { + HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0); + pv = SHLockShared(hmem, 0); + res += sprintfW(res, wszILPtr, pv); + SHUnlockShared(pv); + } + break; + + default: + /* + * Check if this is a env-variable here... + */ + + /* Make sure that we have at least one more %.*/ + if (strchrW(fmt, '%')) + { + WCHAR tmpBuffer[1024]; + PWSTR tmpB = tmpBuffer; + WCHAR tmpEnvBuff[MAX_PATH]; + DWORD envRet; + + while (*fmt != '%') + *tmpB++ = *fmt++; + *tmpB++ = 0; + + TRACE("Checking %s to be a env-var\n", debugstr_w(tmpBuffer)); + + envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH); + if (envRet == 0 || envRet > MAX_PATH) + strcpyW( res, tmpBuffer ); + else + strcpyW( res, tmpEnvBuff ); + res += strlenW(res); + } + done = TRUE; + break; + } + /* Don't skip past terminator (catch a single '%' at the end) */ + if (*fmt != '\0') + { + fmt++; + } + } + else + *res++ = *fmt++; + } + + *res = '\0'; + + return done; +} + +HRESULT SHELL_GetPathFromIDListForExecuteA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize) +{ + STRRET strret; + IShellFolder* desktop; + + HRESULT hr = SHGetDesktopFolder(&desktop); + + if (SUCCEEDED(hr)) { + hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret); + + if (SUCCEEDED(hr)) + StrRetToStrNA(pszPath, uOutSize, &strret, pidl); + + IShellFolder_Release(desktop); + } + + return hr; +} + +HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize) +{ + STRRET strret; + IShellFolder* desktop; + + HRESULT hr = SHGetDesktopFolder(&desktop); + + if (SUCCEEDED(hr)) { + hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret); + + if (SUCCEEDED(hr)) + StrRetToStrNW(pszPath, uOutSize, &strret, pidl); + + IShellFolder_Release(desktop); + } + + return hr; +} + +/************************************************************************* + * SHELL_ResolveShortCutW [Internal] + * read shortcut file at 'wcmd' + */ +static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl) +{ + IShellFolder* psf; + + HRESULT hr = SHGetDesktopFolder(&psf); + + *ppidl = NULL; + + if (SUCCEEDED(hr)) { + LPITEMIDLIST pidl; + ULONG l; + + hr = IShellFolder_ParseDisplayName(psf, 0, 0, wcmd, &l, &pidl, 0); + + if (SUCCEEDED(hr)) { + IShellLinkW* psl; + + hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, (LPCITEMIDLIST*)&pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl); + + if (SUCCEEDED(hr)) { + hr = IShellLinkW_Resolve(psl, hwnd, 0); + + if (SUCCEEDED(hr)) { + hr = IShellLinkW_GetPath(psl, wcmd, MAX_PATH, NULL, SLGP_UNCPRIORITY); + + if (SUCCEEDED(hr)) { + if (!*wcmd) { + /* We could not translate the PIDL in the shell link into a valid file system path - so return the PIDL instead. */ + hr = IShellLinkW_GetIDList(psl, ppidl); + + if (SUCCEEDED(hr) && *ppidl) { + /* We got a PIDL instead of a file system path - try to translate it. */ + if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) { + SHFree(*ppidl); + *ppidl = NULL; + } + } + } + + if (SUCCEEDED(hr)) { + /* get command line arguments, working directory and display mode if available */ + IShellLinkW_GetWorkingDirectory(psl, wdir, MAX_PATH); + IShellLinkW_GetArguments(psl, wargs, MAX_PATH); + IShellLinkW_GetShowCmd(psl, pshowcmd); + } + } + } + + IShellLinkW_Release(psl); + } + + SHFree(pidl); + } + + IShellFolder_Release(psf); + } + + return hr; +} + +/************************************************************************* + * SHELL_ExecuteW [Internal] + * + */ +static UINT SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, + LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) +{ + STARTUPINFOW startup; + PROCESS_INFORMATION info; + UINT retval = 31; + UINT gcdret = 0; + WCHAR curdir[MAX_PATH]; + + TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory)); + /* ShellExecute specifies the command from psei->lpDirectory + * if present. Not from the current dir as CreateProcess does */ + if( psei->lpDirectory && psei->lpDirectory[0] ) + if( ( gcdret = GetCurrentDirectoryW( MAX_PATH, curdir))) + if( !SetCurrentDirectoryW( psei->lpDirectory)) + ERR("cannot set directory %s\n", debugstr_w(psei->lpDirectory)); + ZeroMemory(&startup,sizeof(STARTUPINFOW)); + startup.cb = sizeof(STARTUPINFOW); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = psei->nShow; + if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, + env, *psei->lpDirectory? psei->lpDirectory: NULL, &startup, &info)) + { + /* Give 30 seconds to the app to come up, if desired. Probably only needed + when starting app immediately before making a DDE connection. */ + if (shWait) + if (WaitForInputIdle( info.hProcess, 30000 ) == WAIT_FAILED) + WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() ); + retval = 33; + if (psei->fMask & SEE_MASK_NOCLOSEPROCESS) + psei_out->hProcess = info.hProcess; + else + CloseHandle( info.hProcess ); + CloseHandle( info.hThread ); + } + else if ((retval = GetLastError()) >= 32) + { + FIXME("Strange error set by CreateProcess: %d\n", retval); + retval = ERROR_BAD_FORMAT; + } + + TRACE("returning %u\n", retval); + + psei_out->hInstApp = (HINSTANCE)retval; + if( gcdret ) + if( !SetCurrentDirectoryW( curdir)) + ERR("cannot return to directory %s\n", debugstr_w(curdir)); + + return retval; +} + + +/*********************************************************************** + * SHELL_BuildEnvW [Internal] + * + * Build the environment for the new process, adding the specified + * path to the PATH variable. Returned pointer must be freed by caller. + */ +static void *SHELL_BuildEnvW( const WCHAR *path ) +{ + static const WCHAR wPath[] = {'P','A','T','H','=',0}; + WCHAR *strings, *new_env; + WCHAR *p, *p2; + int total = strlenW(path) + 1; + BOOL got_path = FALSE; + + if (!(strings = GetEnvironmentStringsW())) return NULL; + p = strings; + while (*p) + { + int len = strlenW(p) + 1; + if (!strncmpiW( p, wPath, 5 )) got_path = TRUE; + total += len; + p += len; + } + if (!got_path) total += 5; /* we need to create PATH */ + total++; /* terminating null */ + + if (!(new_env = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) ))) + { + FreeEnvironmentStringsW( strings ); + return NULL; + } + p = strings; + p2 = new_env; + while (*p) + { + int len = strlenW(p) + 1; + memcpy( p2, p, len * sizeof(WCHAR) ); + if (!strncmpiW( p, wPath, 5 )) + { + p2[len - 1] = ';'; + strcpyW( p2 + len, path ); + p2 += strlenW(path) + 1; + } + p += len; + p2 += len; + } + if (!got_path) + { + strcpyW( p2, wPath ); + strcatW( p2, path ); + p2 += strlenW(p2) + 1; + } + *p2 = 0; + FreeEnvironmentStringsW( strings ); + return new_env; +} + + +/*********************************************************************** + * SHELL_TryAppPathW [Internal] + * + * Helper function for SHELL_FindExecutable + * @param lpResult - pointer to a buffer of size MAX_PATH + * On entry: szName is a filename (probably without path separators). + * On exit: if szName found in "App Path", place full path in lpResult, and return true + */ +static BOOL SHELL_TryAppPathW( LPCWSTR szName, LPWSTR lpResult, WCHAR **env) +{ + static const WCHAR wszKeyAppPaths[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s', + '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p',' ','P','a','t','h','s','\\',0}; + static const WCHAR wPath[] = {'P','a','t','h',0}; + HKEY hkApp = 0; + WCHAR buffer[1024]; + LONG len; + LONG res; + BOOL found = FALSE; + + if (env) *env = NULL; + strcpyW(buffer, wszKeyAppPaths); + strcatW(buffer, szName); + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buffer, 0, KEY_READ, &hkApp); + if (res) goto end; + + len = MAX_PATH*sizeof(WCHAR); + res = RegQueryValueW(hkApp, NULL, lpResult, &len); + if (res) goto end; + found = TRUE; + + if (env) + { + DWORD count = sizeof(buffer); + if (!RegQueryValueExW(hkApp, wPath, NULL, NULL, (LPBYTE)buffer, &count) && buffer[0]) + *env = SHELL_BuildEnvW( buffer ); + } + +end: + if (hkApp) RegCloseKey(hkApp); + return found; +} + +static UINT SHELL_FindExecutableByOperation(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen) +{ + static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0}; + + /* Looking for ...buffer\shell\\command */ + strcatW(filetype, wszShell); + strcatW(filetype, lpOperation); + strcatW(filetype, wCommand); + + if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command, + &commandlen) == ERROR_SUCCESS) + { + commandlen /= sizeof(WCHAR); + if (key) strcpyW(key, filetype); +#if 0 + LPWSTR tmp; + WCHAR param[256]; + LONG paramlen = sizeof(param); + static const WCHAR wSpace[] = {' ',0}; + + /* FIXME: it seems all Windows version don't behave the same here. + * the doc states that this ddeexec information can be found after + * the exec names. + * on Win98, it doesn't appear, but I think it does on Win2k + */ + /* Get the parameters needed by the application + from the associated ddeexec key */ + tmp = strstrW(filetype, wCommand); + tmp[0] = '\0'; + strcatW(filetype, wDdeexec); + if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param, + ¶mlen) == ERROR_SUCCESS) + { + paramlen /= sizeof(WCHAR); + strcatW(command, wSpace); + strcatW(command, param); + commandlen += paramlen; + } +#endif + + command[commandlen] = '\0'; + + return 33; /* FIXME see SHELL_FindExecutable() */ + } + + return 31; /* default - 'No association was found' */ +} + +/************************************************************************* + * SHELL_FindExecutable [Internal] + * + * Utility for code sharing between FindExecutable and ShellExecute + * in: + * lpFile the name of a file + * lpOperation the operation on it (open) + * out: + * lpResult a buffer, big enough :-(, to store the command to do the + * operation on the file + * key a buffer, big enough, to get the key name to do actually the + * command (it'll be used afterwards for more information + * on the operation) + */ +UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, + LPWSTR lpResult, int resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args) +{ + static const WCHAR wWindows[] = {'w','i','n','d','o','w','s',0}; + static const WCHAR wPrograms[] = {'p','r','o','g','r','a','m','s',0}; + static const WCHAR wExtensions[] = {'e','x','e',' ','p','i','f',' ','b','a','t',' ','c','m','d',' ','c','o','m',0}; + WCHAR *extension = NULL; /* pointer to file extension */ + WCHAR filetype[256]; /* registry name for this filetype */ + LONG filetypelen = sizeof(filetype); /* length of above */ + WCHAR command[1024]; /* command from registry */ + WCHAR wBuffer[256]; /* Used to GetProfileString */ + UINT retval = 31; /* default - 'No association was found' */ + WCHAR *tok; /* token pointer */ + WCHAR xlpFile[256]; /* result of SearchPath */ + DWORD attribs; /* file attributes */ + + TRACE("%s\n", (lpFile != NULL) ? debugstr_w(lpFile) : "-"); + + xlpFile[0] = '\0'; + lpResult[0] = '\0'; /* Start off with an empty return string */ + if (key) *key = '\0'; + + /* trap NULL parameters on entry */ + if ((lpFile == NULL) || (lpResult == NULL) || (lpOperation == NULL)) + { + WARN("(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n", + debugstr_w(lpFile), debugstr_w(lpOperation), debugstr_w(lpResult)); + return 2; /* File not found. Close enough, I guess. */ + } + + if (SHELL_TryAppPathW( lpFile, lpResult, env )) + { + TRACE("found %s via App Paths\n", debugstr_w(lpResult)); + return 33; + } + + if (SearchPathW(lpPath, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL)) + { + TRACE("SearchPathW returned non-zero\n"); + lpFile = xlpFile; + /* Hey, isn't this value ignored? Why make this call? Shouldn't we return here? --dank*/ + } + + attribs = GetFileAttributesW(lpFile); + if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY)) + { + strcpyW(filetype, wszFolder); + filetypelen = 6; /* strlen("Folder") */ + } + else + { + /* First thing we need is the file's extension */ + extension = strrchrW(xlpFile, '.'); /* Assume last "." is the one; */ + /* File->Run in progman uses */ + /* .\FILE.EXE :( */ + TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension)); + + if (extension == NULL || extension[1]==0) + { + WARN("Returning 31 - No association\n"); + return 31; /* no association */ + } + + /* Three places to check: */ + /* 1. win.ini, [windows], programs (NB no leading '.') */ + /* 2. Registry, HKEY_CLASS_ROOT\\shell\open\command */ + /* 3. win.ini, [extensions], extension (NB no leading '.' */ + /* All I know of the order is that registry is checked before */ + /* extensions; however, it'd make sense to check the programs */ + /* section first, so that's what happens here. */ + + /* See if it's a program - if GetProfileString fails, we skip this + * section. Actually, if GetProfileString fails, we've probably + * got a lot more to worry about than running a program... */ + if (GetProfileStringW(wWindows, wPrograms, wExtensions, wBuffer, sizeof(wBuffer)/sizeof(WCHAR)) > 0) + { + CharLowerW(wBuffer); + tok = wBuffer; + while (*tok) + { + WCHAR *p = tok; + while (*p && *p != ' ' && *p != '\t') p++; + if (*p) + { + *p++ = 0; + while (*p == ' ' || *p == '\t') p++; + } + + if (strcmpiW(tok, &extension[1]) == 0) /* have to skip the leading "." */ + { + strcpyW(lpResult, xlpFile); + /* Need to perhaps check that the file has a path + * attached */ + TRACE("found %s\n", debugstr_w(lpResult)); + return 33; + + /* Greater than 32 to indicate success FIXME According to the + * docs, I should be returning a handle for the + * executable. Does this mean I'm supposed to open the + * executable file or something? More RTFM, I guess... */ + } + tok = p; + } + } + + /* Check registry */ + if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, filetype, + &filetypelen) == ERROR_SUCCESS) + { + filetypelen /= sizeof(WCHAR); + filetype[filetypelen] = '\0'; + TRACE("File type: %s\n", debugstr_w(filetype)); + } + } + + if (*filetype) + { + if (lpOperation) + { + /* pass the operation string to SHELL_FindExecutableByOperation() */ + filetype[filetypelen] = '\0'; + retval = SHELL_FindExecutableByOperation(lpPath, lpFile, lpOperation, key, filetype, command, sizeof(command)); + } + else + { + WCHAR operation[MAX_PATH]; + HKEY hkey; + + /* Looking for ...buffer\shell\\command */ + strcatW(filetype, wszShell); + + /* enumerate the operation subkeys in the registry and search for one with an associated command */ + if (RegOpenKeyW(HKEY_CLASSES_ROOT, filetype, &hkey) == ERROR_SUCCESS) + { + int idx = 0; + for(;; ++idx) + { + if (RegEnumKeyW(hkey, idx, operation, MAX_PATH) != ERROR_SUCCESS) + break; + + filetype[filetypelen] = '\0'; + retval = SHELL_FindExecutableByOperation(lpPath, lpFile, operation, key, filetype, command, sizeof(command)); + + if (retval > 32) + break; + } + RegCloseKey(hkey); + } + } + + if (retval > 32) + { + SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args); + + /* Remove double quotation marks and command line arguments */ + if (*lpResult == '"') + { + WCHAR *p = lpResult; + while (*(p + 1) != '"') + { + *p = *(p + 1); + p++; + } + *p = '\0'; + } + } + } + else /* Check win.ini */ + { + static const WCHAR wExtensions[] = {'e','x','t','e','n','s','i','o','n','s',0}; + + /* Toss the leading dot */ + extension++; + if (GetProfileStringW(wExtensions, extension, wszEmpty, command, sizeof(command)/sizeof(WCHAR)) > 0) + { + if (strlenW(command) != 0) + { + strcpyW(lpResult, command); + tok = strchrW(lpResult, '^'); /* should be ^.extension? */ + if (tok != NULL) + { + tok[0] = '\0'; + strcatW(lpResult, xlpFile); /* what if no dir in xlpFile? */ + tok = strchrW(command, '^'); /* see above */ + if ((tok != NULL) && (strlenW(tok)>5)) + { + strcatW(lpResult, &tok[5]); + } + } + retval = 33; /* FIXME - see above */ + } + } + } + + TRACE("returning %s\n", debugstr_w(lpResult)); + return retval; +} + +/****************************************************************** + * dde_cb + * + * callback for the DDE connection. not really usefull + */ +static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv, + HSZ hsz1, HSZ hsz2, HDDEDATA hData, + ULONG_PTR dwData1, ULONG_PTR dwData2) +{ + TRACE("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n", + uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2); + return NULL; +} + +/****************************************************************** + * dde_connect + * + * ShellExecute helper. Used to do an operation with a DDE connection + * + * Handles both the direct connection (try #1), and if it fails, + * launching an application and trying (#2) to connect to it + * + */ +static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec, + const WCHAR* lpFile, WCHAR *env, + LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc, + LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) +{ + static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0}; + static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0}; + WCHAR * endkey = key + strlenW(key); + WCHAR app[256], topic[256], ifexec[256], res[256]; + LONG applen, topiclen, ifexeclen; + WCHAR * exec; + DWORD ddeInst = 0; + DWORD tid; + HSZ hszApp, hszTopic; + HCONV hConv; + HDDEDATA hDdeData; + unsigned ret = 31; + + strcpyW(endkey, wApplication); + applen = sizeof(app); + if (RegQueryValueW(HKEY_CLASSES_ROOT, key, app, &applen) != ERROR_SUCCESS) + { + FIXME("default app name NIY %s\n", debugstr_w(key)); + return 2; + } + + strcpyW(endkey, wTopic); + topiclen = sizeof(topic); + if (RegQueryValueW(HKEY_CLASSES_ROOT, key, topic, &topiclen) != ERROR_SUCCESS) + { + static const WCHAR wSystem[] = {'S','y','s','t','e','m',0}; + strcpyW(topic, wSystem); + } + + if (DdeInitializeW(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR) + { + return 2; + } + + hszApp = DdeCreateStringHandleW(ddeInst, app, CP_WINUNICODE); + hszTopic = DdeCreateStringHandleW(ddeInst, topic, CP_WINUNICODE); + + hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL); + exec = ddeexec; + if (!hConv) + { + static const WCHAR wIfexec[] = {'\\','i','f','e','x','e','c',0}; + TRACE("Launching '%s'\n", debugstr_w(start)); + ret = execfunc(start, env, TRUE, psei, psei_out); + if (ret < 32) + { + TRACE("Couldn't launch\n"); + goto error; + } + hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL); + if (!hConv) + { + TRACE("Couldn't connect. ret=%d\n", ret); + DdeUninitialize(ddeInst); + SetLastError(ERROR_DDE_FAIL); + return 30; /* whatever */ + } + strcpyW(endkey, wIfexec); + ifexeclen = sizeof(ifexec); + if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ifexec, &ifexeclen) == ERROR_SUCCESS) + { + exec = ifexec; + } + } + + SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile, pidl, szCommandline); + TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res)); + + /* It's documented in the KB 330337 that IE has a bug and returns + * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request. + */ + hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, + XTYP_EXECUTE, 10000, &tid); + if (hDdeData) + DdeFreeDataHandle(hDdeData); + else + WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst)); + ret = 33; + + DdeDisconnect(hConv); + + error: + DdeUninitialize(ddeInst); + + return ret; +} + +/************************************************************************* + * execute_from_key [Internal] + */ +static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline, + SHELL_ExecuteW32 execfunc, + LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out) +{ + WCHAR cmd[1024]; + LONG cmdlen = sizeof(cmd); + UINT retval = 31; + + cmd[0] = '\0'; + + /* Get the application for the registry */ + if (RegQueryValueW(HKEY_CLASSES_ROOT, key, cmd, &cmdlen) == ERROR_SUCCESS) + { + static const WCHAR wCommand[] = {'c','o','m','m','a','n','d',0}; + static const WCHAR wDdeexec[] = {'d','d','e','e','x','e','c',0}; + LPWSTR tmp; + WCHAR param[256]; + LONG paramlen = sizeof(param); + + param[0] = '\0'; + + /* Get the parameters needed by the application + from the associated ddeexec key */ + tmp = strstrW(key, wCommand); + assert(tmp); + strcpyW(tmp, wDdeexec); + + if (RegQueryValueW(HKEY_CLASSES_ROOT, key, param, ¶mlen) == ERROR_SUCCESS) + { + TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(param)); + retval = dde_connect(key, cmd, param, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out); + } + else + { + /* Is there a replace() function anywhere? */ + cmdlen /= sizeof(WCHAR); + cmd[cmdlen] = '\0'; + SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline); + retval = execfunc(param, env, FALSE, psei, psei_out); + } + } + else TRACE("ooch\n"); + + return retval; +} + +/************************************************************************* + * FindExecutableA [SHELL32.@] + */ +HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult) +{ + HINSTANCE retval; + WCHAR *wFile = NULL, *wDirectory = NULL; + WCHAR wResult[MAX_PATH]; + + if (lpFile) __SHCloneStrAtoW(&wFile, lpFile); + if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory); + + retval = FindExecutableW(wFile, wDirectory, wResult); + WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL); + if (wFile) SHFree( wFile ); + if (wDirectory) SHFree( wDirectory ); + + TRACE("returning %s\n", lpResult); + return (HINSTANCE)retval; +} + +/************************************************************************* + * FindExecutableW [SHELL32.@] + */ +HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult) +{ + UINT retval = 31; /* default - 'No association was found' */ + WCHAR old_dir[1024]; + + TRACE("File %s, Dir %s\n", + (lpFile != NULL ? debugstr_w(lpFile) : "-"), (lpDirectory != NULL ? debugstr_w(lpDirectory) : "-")); + + lpResult[0] = '\0'; /* Start off with an empty return string */ + + /* trap NULL parameters on entry */ + if ((lpFile == NULL) || (lpResult == NULL)) + { + /* FIXME - should throw a warning, perhaps! */ + return (HINSTANCE)2; /* File not found. Close enough, I guess. */ + } + + if (lpDirectory) + { + GetCurrentDirectoryW(sizeof(old_dir)/sizeof(WCHAR), old_dir); + SetCurrentDirectoryW(lpDirectory); + } + + retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL); + + TRACE("returning %s\n", debugstr_w(lpResult)); + if (lpDirectory) + SetCurrentDirectoryW(old_dir); + return (HINSTANCE)retval; +} + +/************************************************************************* + * ShellExecuteExW32 [Internal] + */ +BOOL WINAPI ShellExecuteExW32 (LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc) +{ + static const WCHAR wQuote[] = {'"',0}; + static const WCHAR wSpace[] = {' ',0}; + static const WCHAR wWww[] = {'w','w','w',0}; + static const WCHAR wFile[] = {'f','i','l','e',0}; + static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0}; + static const WCHAR wExtLnk[] = {'.','l','n','k',0}; + static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0}; + + WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH]; + SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */ + WCHAR wfileName[MAX_PATH]; + WCHAR *env; + WCHAR lpstrProtocol[256]; + LPCWSTR lpFile; + UINT retval = 31; + WCHAR wcmd[1024]; + WCHAR buffer[MAX_PATH]; + const WCHAR* ext; + BOOL done; + + /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */ + memcpy(&sei_tmp, sei, sizeof(sei_tmp)); + + TRACE("mask=0x%08lx hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n", + sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb), + debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters), + debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow, + (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei_tmp.lpClass) : "not used"); + + sei->hProcess = NULL; + + /* make copies of all path/command strings */ + if (sei_tmp.lpFile) + strcpyW(wszApplicationName, sei_tmp.lpFile); + else + *wszApplicationName = '\0'; + + if (sei_tmp.lpParameters) + strcpyW(wszParameters, sei_tmp.lpParameters); + else + *wszParameters = '\0'; + + if (sei_tmp.lpDirectory) + strcpyW(wszDir, sei_tmp.lpDirectory); + else + *wszDir = '\0'; + + /* adjust string pointers to point to the new buffers */ + sei_tmp.lpFile = wszApplicationName; + sei_tmp.lpParameters = wszParameters; + sei_tmp.lpDirectory = wszDir; + + if (sei_tmp.fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY | + SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | + SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE | + SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR )) + { + FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask); + } + + /* process the IDList */ + if (sei_tmp.fMask & SEE_MASK_IDLIST) + { + IShellExecuteHookW* pSEH; + + HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL); + + if (SUCCEEDED(hr)) + { + hr = IShellExecuteHookW_Execute(pSEH, sei); + + IShellExecuteHookW_Release(pSEH); + + if (hr == S_OK) + return TRUE; + } + + wszApplicationName[0] = '"'; + SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName+1); + strcatW(wszApplicationName, wQuote); + TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName)); + } + + if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)) + { + /* launch a document by fileclass like 'WordPad.Document.1' */ + /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */ + /* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */ + HCR_GetExecuteCommandW((sei_tmp.fMask & SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL, + (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL, + (sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen, + wszParameters, sizeof(wszParameters)/sizeof(WCHAR)); + + /* FIXME: get the extension of lpFile, check if it fits to the lpClass */ + TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", debugstr_w(wszParameters), debugstr_w(wszApplicationName)); + + wcmd[0] = '\0'; + done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszParameters, wszApplicationName, sei_tmp.lpIDList, NULL); + if (!done && wszApplicationName[0]) + { + strcatW(wcmd, wSpace); + strcatW(wcmd, wszApplicationName); + } + retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei); + if (retval > 32) + return TRUE; + else + return FALSE; + } + + + /* resolve shell shortcuts */ + ext = PathFindExtensionW(sei_tmp.lpFile); + + if (ext && !strncmpiW(ext, wExtLnk, sizeof(wExtLnk) / sizeof(WCHAR) - 1) && + (ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '\0' || + (sei_tmp.lpFile[0] == '"' && ext[sizeof(wExtLnk) / sizeof(WCHAR) - 1] == '"'))) /* or check for: shell_attribs & SFGAO_LINK */ + { + HRESULT hr; + BOOL Quoted; + + if (wszApplicationName[0] == '"') + { + if (wszApplicationName[strlenW(wszApplicationName) - 1] == '"') + { + wszApplicationName[strlenW(wszApplicationName) - 1] = '\0'; + Quoted = TRUE; + } + else + { + Quoted = FALSE; + } + } + else + { + Quoted = FALSE; + } + /* expand paths before reading shell link */ + if (ExpandEnvironmentStringsW(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile, buffer, MAX_PATH)) + lstrcpyW(Quoted ? wszApplicationName + 1 : wszApplicationName/*sei_tmp.lpFile*/, buffer); + + if (*sei_tmp.lpParameters) + if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH)) + lstrcpyW(wszParameters/*sei_tmp.lpParameters*/, buffer); + + hr = SHELL_ResolveShortCutW((LPWSTR)(Quoted ? sei_tmp.lpFile + 1 : sei_tmp.lpFile), + (LPWSTR)sei_tmp.lpParameters, (LPWSTR)sei_tmp.lpDirectory, + sei_tmp.hwnd, sei_tmp.lpVerb?sei_tmp.lpVerb:wszEmpty, &sei_tmp.nShow, (LPITEMIDLIST*)&sei_tmp.lpIDList); + if (Quoted) + { + wszApplicationName[strlenW(wszApplicationName) + 1] = '\0'; + wszApplicationName[strlenW(wszApplicationName)] = '"'; + } + + if (sei->lpIDList) + sei->fMask |= SEE_MASK_IDLIST; + + if (SUCCEEDED(hr)) + { + /* repeat IDList processing if needed */ + if (sei_tmp.fMask & SEE_MASK_IDLIST) + { + IShellExecuteHookW* pSEH; + + HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL); + + if (SUCCEEDED(hr)) + { + hr = IShellExecuteHookW_Execute(pSEH, sei); + + IShellExecuteHookW_Release(pSEH); + + if (hr == S_OK) + return TRUE; + } + + TRACE("-- idlist=%p (%s)\n", debugstr_w(sei_tmp.lpIDList), debugstr_w(sei_tmp.lpFile)); + } + } + } + + + /* Has the IDList not yet been translated? */ + if (sei_tmp.fMask & SEE_MASK_IDLIST) + { + /* last chance to translate IDList: now also allow CLSID paths */ + if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, buffer, sizeof(buffer)))) { + if (buffer[0]==':' && buffer[1]==':') { + /* open shell folder for the specified class GUID */ + strcpyW(wszParameters, buffer); + strcpyW(wszApplicationName, wExplorer); + + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + } else if (HCR_GetExecuteCommandW(0, wszFolder, sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, buffer, sizeof(buffer))) { + SHELL_ArgifyW(wszApplicationName, sizeof(wszApplicationName)/sizeof(WCHAR), buffer, NULL, sei_tmp.lpIDList, NULL); + + sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST; + } + } + } + + /* expand environment strings */ + if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH)) + lstrcpyW(wszApplicationName, buffer); + + if (*sei_tmp.lpParameters) + if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH)) + lstrcpyW(wszParameters, buffer); + + if (*sei_tmp.lpDirectory) + if (ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buffer, MAX_PATH)) + lstrcpyW(wszDir, buffer); + + /* Else, try to execute the filename */ + TRACE("execute:%s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir)); + + /* separate out command line arguments from executable file name */ + if (!*sei_tmp.lpParameters) { + /* If the executable path is quoted, handle the rest of the command line as parameters. */ + if (sei_tmp.lpFile[0] == '"') { + LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1; + LPWSTR dst = wfileName; + LPWSTR end; + + /* copy the unquoted executable path to 'wfileName' */ + while(*src && *src!='"') + *dst++ = *src++; + + *dst = '\0'; + + if (*src == '"') { + end = ++src; + + while(isspace(*src)) + ++src; + } else + end = src; + + /* copy the parameter string to 'wszParameters' */ + strcpyW(wszParameters, src); + + /* terminate previous command string after the quote character */ + *end = '\0'; + } + else + { + /* If the executable name is not quoted, we have to use this search loop here, + that in CreateProcess() is not sufficient because it does not handle shell links. */ + WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH]; + LPWSTR space, s; + + LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/; + for(s=beg; (space=strchrW(s, ' ')); s=space+1) { + int idx = space-sei_tmp.lpFile; + strncpyW(buffer, sei_tmp.lpFile, idx); + buffer[idx] = '\0'; + + /*FIXME This finds directory paths if the targeted file name contains spaces. */ + if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, buffer, wszExe, sizeof(xlpFile), xlpFile, NULL)) + { + /* separate out command from parameter string */ + LPCWSTR p = space + 1; + + while(isspaceW(*p)) + ++p; + + strcpyW(wszParameters, p); + *space = '\0'; + + break; + } + } + + strcpyW(wfileName, sei_tmp.lpFile); + } + } else + strcpyW(wfileName, sei_tmp.lpFile); + + lpFile = wfileName; + + if (sei_tmp.lpParameters[0]) { + strcatW(wszApplicationName, wSpace); + strcatW(wszApplicationName, wszParameters); + } + + /* We set the default to open, and that should generally work. + But that is not really the way the MS docs say to do it. */ + if (!sei_tmp.lpVerb) + sei_tmp.lpVerb = wszOpen; + + retval = execfunc(wszApplicationName, NULL, FALSE, &sei_tmp, sei); + if (retval > 32) + return TRUE; + + /* Else, try to find the executable */ + wcmd[0] = '\0'; + retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters); + if (retval > 32) /* Found */ + { + WCHAR wszQuotedCmd[MAX_PATH+2]; + /* Must quote to handle case where cmd contains spaces, + * else security hole if malicious user creates executable file "C:\\Program" + */ + strcpyW(wszQuotedCmd, wQuote); + strcatW(wszQuotedCmd, wcmd); + strcatW(wszQuotedCmd, wQuote); + if (wszParameters[0]) { + strcatW(wszQuotedCmd, wSpace); + strcatW(wszQuotedCmd, wszParameters); + } + TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol)); + if (*lpstrProtocol) + retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei); + else + retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei); + HeapFree( GetProcessHeap(), 0, env ); + } + else if (PathIsURLW((LPWSTR)lpFile)) /* File not found, check for URL */ + { + static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0}; + static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0}; + LPWSTR lpstrRes; + INT iSize; + + lpstrRes = strchrW(lpFile, ':'); + if (lpstrRes) + iSize = lpstrRes - lpFile; + else + iSize = strlenW(lpFile); + + TRACE("Got URL: %s\n", debugstr_w(lpFile)); + /* Looking for ...protocol\shell\lpOperation\command */ + strncpyW(lpstrProtocol, lpFile, iSize); + lpstrProtocol[iSize] = '\0'; + strcatW(lpstrProtocol, wShell); + strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen); + strcatW(lpstrProtocol, wCommand); + + /* Remove File Protocol from lpFile */ + /* In the case file://path/file */ + if (!strncmpiW(lpFile, wFile, iSize)) + { + lpFile += iSize; + while (*lpFile == ':') lpFile++; + } + retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei_tmp.lpParameters, execfunc, &sei_tmp, sei); + } + /* Check if file specified is in the form www.??????.*** */ + else if (!strncmpiW(lpFile, wWww, 3)) + { + /* if so, append lpFile http:// and call ShellExecute */ + WCHAR lpstrTmpFile[256]; + strcpyW(lpstrTmpFile, wHttp); + strcatW(lpstrTmpFile, lpFile); + retval = (UINT)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0); + } + + TRACE("retval %u\n", retval); + + if (retval <= 32) + { + sei->hInstApp = (HINSTANCE)retval; + return FALSE; + } + + sei->hInstApp = (HINSTANCE)33; + return TRUE; +} + +/************************************************************************* + * ShellExecuteA [SHELL32.290] + */ +HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile, + LPCSTR lpParameters,LPCSTR lpDirectory, INT iShowCmd) +{ + SHELLEXECUTEINFOA sei; + HANDLE hProcess = 0; + + TRACE("%p,%s,%s,%s,%s,%d\n", + hWnd, lpOperation, lpFile, lpParameters, lpDirectory, iShowCmd); + + sei.cbSize = sizeof(sei); + sei.fMask = 0; + sei.hwnd = hWnd; + sei.lpVerb = lpOperation; + sei.lpFile = lpFile; + sei.lpParameters = lpParameters; + sei.lpDirectory = lpDirectory; + sei.nShow = iShowCmd; + sei.lpIDList = 0; + sei.lpClass = 0; + sei.hkeyClass = 0; + sei.dwHotKey = 0; + sei.hProcess = hProcess; + + ShellExecuteExA (&sei); + return sei.hInstApp; +} + +/************************************************************************* + * ShellExecuteExA [SHELL32.292] + * + */ +BOOL WINAPI ShellExecuteExA (LPSHELLEXECUTEINFOA sei) +{ + SHELLEXECUTEINFOW seiW; + BOOL ret; + WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL; + + TRACE("%p\n", sei); + + memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW)); + + if (sei->lpVerb) + seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb); + + if (sei->lpFile) + seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile); + + if (sei->lpParameters) + seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters); + + if (sei->lpDirectory) + seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory); + + if ((sei->fMask & SEE_MASK_CLASSNAME) && sei->lpClass) + seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass); + else + seiW.lpClass = NULL; + + ret = ShellExecuteExW32 (&seiW, SHELL_ExecuteW); + + sei->hInstApp = seiW.hInstApp; + + if (wVerb) SHFree(wVerb); + if (wFile) SHFree(wFile); + if (wParameters) SHFree(wParameters); + if (wDirectory) SHFree(wDirectory); + if (wClass) SHFree(wClass); + + return ret; +} + +/************************************************************************* + * ShellExecuteExW [SHELL32.293] + * + */ +BOOL WINAPI ShellExecuteExW (LPSHELLEXECUTEINFOW sei) +{ + return ShellExecuteExW32 (sei, SHELL_ExecuteW); +} + +/************************************************************************* + * ShellExecuteW [SHELL32.294] + * from shellapi.h + * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, + * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd); + */ +HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, + LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd) +{ + SHELLEXECUTEINFOW sei; + HANDLE hProcess = 0; + + TRACE("\n"); + sei.cbSize = sizeof(sei); + sei.fMask = 0; + sei.hwnd = hwnd; + sei.lpVerb = lpOperation; + sei.lpFile = lpFile; + sei.lpParameters = lpParameters; + sei.lpDirectory = lpDirectory; + sei.nShow = nShowCmd; + sei.lpIDList = 0; + sei.lpClass = 0; + sei.hkeyClass = 0; + sei.dwHotKey = 0; + sei.hProcess = hProcess; + + ShellExecuteExW32 (&sei, SHELL_ExecuteW); + return sei.hInstApp; +} diff --git a/reactos/lib/shell32/shlfileop.c b/reactos/lib/shell32/shlfileop.c index 814fce00f48..f229819b73b 100644 --- a/reactos/lib/shell32/shlfileop.c +++ b/reactos/lib/shell32/shlfileop.c @@ -1,1429 +1,1417 @@ -/* - * SHFileOperation - * - * Copyright 2000 Juergen Schmied - * Copyright 2002 Andriy Palamarchuk - * Copyright 2004 Dietrich Teickner (from Odin) - * Copyright 2004 Rolf Kalbermatter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "shellapi.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "shresdef.h" -#define NO_SHLWAPI_STREAM -#include "shlwapi.h" -#include "shell32_main.h" -#include "undocshell.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -#define IsAttrib(x, y) ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y))) -#define IsAttribFile(x) (!((x) & FILE_ATTRIBUTE_DIRECTORY)) -#define IsAttribDir(x) IsAttrib(x, FILE_ATTRIBUTE_DIRECTORY) -#define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0)))) - -#define FO_MASK 0xF - -static const WCHAR wWildcardFile[] = {'*',0}; -static const WCHAR wWildcardChars[] = {'*','?',0}; -static const WCHAR wBackslash[] = {'\\',0}; - -static BOOL SHELL_DeleteDirectoryW(LPCWSTR path, BOOL bShowUI); -static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec); -static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec); -static DWORD SHNotifyRemoveDirectoryA(LPCSTR path); -static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path); -static DWORD SHNotifyDeleteFileA(LPCSTR path); -static DWORD SHNotifyDeleteFileW(LPCWSTR path); -static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest); -static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists); -static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly); - -typedef struct -{ - UINT caption_resource_id, text_resource_id; -} SHELL_ConfirmIDstruc; - -static BOOL SHELL_ConfirmIDs(int nKindOfDialog, SHELL_ConfirmIDstruc *ids) -{ - switch (nKindOfDialog) { - case ASK_DELETE_FILE: - ids->caption_resource_id = IDS_DELETEITEM_CAPTION; - ids->text_resource_id = IDS_DELETEITEM_TEXT; - return TRUE; - case ASK_DELETE_FOLDER: - ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION; - ids->text_resource_id = IDS_DELETEITEM_TEXT; - return TRUE; - case ASK_DELETE_MULTIPLE_ITEM: - ids->caption_resource_id = IDS_DELETEITEM_CAPTION; - ids->text_resource_id = IDS_DELETEMULTIPLE_TEXT; - return TRUE; - case ASK_OVERWRITE_FILE: - ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION; - ids->text_resource_id = IDS_OVERWRITEFILE_TEXT; - return TRUE; - default: - FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog); - } - return FALSE; -} - -BOOL SHELL_ConfirmDialog(int nKindOfDialog, LPCSTR szDir) -{ - CHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256]; - SHELL_ConfirmIDstruc ids; - - if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) - return FALSE; - - LoadStringA(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)); - LoadStringA(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)); - - FormatMessageA(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, - szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir); - - return (IDOK == MessageBoxA(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION)); -} - -BOOL SHELL_ConfirmDialogW(int nKindOfDialog, LPCWSTR szDir) -{ - WCHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256]; - SHELL_ConfirmIDstruc ids; - - if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) - return FALSE; - - LoadStringW(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)); - LoadStringW(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)); - - FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, - szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir); - - return (IDOK == MessageBoxW(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION)); -} - -static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minChars) -{ - DWORD len = MultiByteToWideChar(CP_ACP, 0, aPath, -1, NULL, 0); - - if (len < minChars) - len = minChars; - - *wPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (*wPath) - { - MultiByteToWideChar(CP_ACP, 0, aPath, -1, *wPath, len); - return NO_ERROR; - } - return E_OUTOFMEMORY; -} - -static void SHELL32_FreeUnicodeBuf(LPWSTR wPath) -{ - HeapFree(GetProcessHeap(), 0, wPath); -} - -/************************************************************************** - * SHELL_DeleteDirectory() [internal] - * - * Asks for confirmation when bShowUI is true and deletes the directory and - * all its subdirectories and files if necessary. - */ -BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI) -{ - LPWSTR wPath; - BOOL ret = FALSE; - - if (!SHELL32_AnsiToUnicodeBuf(pszDir, &wPath, 0)) - { - ret = SHELL_DeleteDirectoryW(wPath, bShowUI); - SHELL32_FreeUnicodeBuf(wPath); - } - return ret; -} - -static BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI) -{ - BOOL ret = TRUE; - HANDLE hFind; - WIN32_FIND_DATAW wfd; - WCHAR szTemp[MAX_PATH]; - - /* Make sure the directory exists before eventually prompting the user */ - PathCombineW(szTemp, pszDir, wWildcardFile); - hFind = FindFirstFileW(szTemp, &wfd); - if (hFind == INVALID_HANDLE_VALUE) - return FALSE; - - if (!bShowUI || (ret = SHELL_ConfirmDialogW(ASK_DELETE_FOLDER, pszDir))) - { - do - { - LPWSTR lp = wfd.cAlternateFileName; - if (!lp[0]) - lp = wfd.cFileName; - if (IsDotDir(lp)) - continue; - PathCombineW(szTemp, pszDir, lp); - if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes) - ret = SHELL_DeleteDirectoryW(szTemp, FALSE); - else - ret = (SHNotifyDeleteFileW(szTemp) == ERROR_SUCCESS); - } while (ret && FindNextFileW(hFind, &wfd)); - } - FindClose(hFind); - if (ret) - ret = (SHNotifyRemoveDirectoryW(pszDir) == ERROR_SUCCESS); - return ret; -} - -/************************************************************************** - * SHELL_DeleteFileA() [internal] - */ -BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI) -{ - if (bShowUI && !SHELL_ConfirmDialog(ASK_DELETE_FILE, pszFile)) - return FALSE; - - return (SHNotifyDeleteFileA(pszFile) == ERROR_SUCCESS); -} - -BOOL SHELL_DeleteFileW(LPCWSTR pszFile, BOOL bShowUI) -{ - if (bShowUI && !SHELL_ConfirmDialogW(ASK_DELETE_FILE, pszFile)) - return FALSE; - - return (SHNotifyDeleteFileW(pszFile) == ERROR_SUCCESS); -} - -/************************************************************************** - * Win32CreateDirectory [SHELL32.93] - * - * Creates a directory. Also triggers a change notify if one exists. - * - * PARAMS - * path [I] path to directory to create - * - * RETURNS - * TRUE if successful, FALSE otherwise - * - * NOTES: - * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. - * This is Unicode on NT/2000 - */ -static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec) -{ - LPWSTR wPath; - DWORD retCode; - - TRACE("(%s, %p)\n", debugstr_a(path), sec); - - retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); - if (!retCode) - { - retCode = SHNotifyCreateDirectoryW(wPath, sec); - SHELL32_FreeUnicodeBuf(wPath); - } - return retCode; -} - -/**********************************************************************/ - -static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec) -{ - TRACE("(%s, %p)\n", debugstr_w(path), sec); - - if (CreateDirectoryW(path, sec)) - { - SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, path, NULL); - return ERROR_SUCCESS; - } - return GetLastError(); -} - -/**********************************************************************/ - -BOOL WINAPI Win32CreateDirectoryAW(LPCVOID path, LPSECURITY_ATTRIBUTES sec) -{ - if (SHELL_OsIsUnicode()) - return (SHNotifyCreateDirectoryW(path, sec) == ERROR_SUCCESS); - return (SHNotifyCreateDirectoryA(path, sec) == ERROR_SUCCESS); -} - -/************************************************************************ - * Win32RemoveDirectory [SHELL32.94] - * - * Deletes a directory. Also triggers a change notify if one exists. - * - * PARAMS - * path [I] path to directory to delete - * - * RETURNS - * TRUE if successful, FALSE otherwise - * - * NOTES: - * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. - * This is Unicode on NT/2000 - */ -static DWORD SHNotifyRemoveDirectoryA(LPCSTR path) -{ - LPWSTR wPath; - DWORD retCode; - - TRACE("(%s)\n", debugstr_a(path)); - - retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); - if (!retCode) - { - retCode = SHNotifyRemoveDirectoryW(wPath); - SHELL32_FreeUnicodeBuf(wPath); - } - return retCode; -} - -/***********************************************************************/ - -static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path) -{ - BOOL ret; - TRACE("(%s)\n", debugstr_w(path)); - - ret = RemoveDirectoryW(path); - if (!ret) - { - /* Directory may be write protected */ - DWORD dwAttr = GetFileAttributesW(path); - if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY)) - if (SetFileAttributesW(path, dwAttr & ~FILE_ATTRIBUTE_READONLY)) - ret = RemoveDirectoryW(path); - } - if (ret) - { - SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW, path, NULL); - return ERROR_SUCCESS; - } - return GetLastError(); -} - -/***********************************************************************/ - -BOOL WINAPI Win32RemoveDirectoryAW(LPCVOID path) -{ - if (SHELL_OsIsUnicode()) - return (SHNotifyRemoveDirectoryW(path) == ERROR_SUCCESS); - return (SHNotifyRemoveDirectoryA(path) == ERROR_SUCCESS); -} - -/************************************************************************ - * Win32DeleteFile [SHELL32.164] - * - * Deletes a file. Also triggers a change notify if one exists. - * - * PARAMS - * path [I] path to file to delete - * - * RETURNS - * TRUE if successful, FALSE otherwise - * - * NOTES: - * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. - * This is Unicode on NT/2000 - */ -static DWORD SHNotifyDeleteFileA(LPCSTR path) -{ - LPWSTR wPath; - DWORD retCode; - - TRACE("(%s)\n", debugstr_a(path)); - - retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); - if (!retCode) - { - retCode = SHNotifyDeleteFileW(wPath); - SHELL32_FreeUnicodeBuf(wPath); - } - return retCode; -} - -/***********************************************************************/ - -static DWORD SHNotifyDeleteFileW(LPCWSTR path) -{ - BOOL ret; - - TRACE("(%s)\n", debugstr_w(path)); - - ret = DeleteFileW(path); - if (!ret) - { - /* File may be write protected or a system file */ - DWORD dwAttr = GetFileAttributesW(path); - if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) - if (SetFileAttributesW(path, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) - ret = DeleteFileW(path); - } - if (ret) - { - SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, path, NULL); - return ERROR_SUCCESS; - } - return GetLastError(); -} - -/***********************************************************************/ - -DWORD WINAPI Win32DeleteFileAW(LPCVOID path) -{ - if (SHELL_OsIsUnicode()) - return (SHNotifyDeleteFileW(path) == ERROR_SUCCESS); - return (SHNotifyDeleteFileA(path) == ERROR_SUCCESS); -} - -/************************************************************************ - * SHNotifyMoveFile [internal] - * - * Moves a file. Also triggers a change notify if one exists. - * - * PARAMS - * src [I] path to source file to move - * dest [I] path to target file to move to - * - * RETURNS - * ERORR_SUCCESS if successful - */ -static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest) -{ - BOOL ret; - - TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest)); - - ret = MoveFileW(src, dest); - if (!ret) - { - DWORD dwAttr; - - dwAttr = SHFindAttrW(dest, FALSE); - if (INVALID_FILE_ATTRIBUTES == dwAttr) - { - /* Source file may be write protected or a system file */ - dwAttr = GetFileAttributesW(src); - if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) - if (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) - ret = MoveFileW(src, dest); - } - } - if (ret) - { - SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest); - return ERROR_SUCCESS; - } - return GetLastError(); -} - -/************************************************************************ - * SHNotifyCopyFile [internal] - * - * Copies a file. Also triggers a change notify if one exists. - * - * PARAMS - * src [I] path to source file to move - * dest [I] path to target file to move to - * bFailIfExists [I] if TRUE, the target file will not be overwritten if - * a file with this name already exists - * - * RETURNS - * ERROR_SUCCESS if successful - */ -static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists) -{ - BOOL ret; - - TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : ""); - - ret = CopyFileW(src, dest, bFailIfExists); - if (ret) - { - SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); - return ERROR_SUCCESS; - } - return GetLastError(); -} - -/************************************************************************* - * SHCreateDirectory [SHELL32.165] - * - * This function creates a file system folder whose fully qualified path is - * given by path. If one or more of the intermediate folders do not exist, - * they will be created as well. - * - * PARAMS - * hWnd [I] - * path [I] path of directory to create - * - * RETURNS - * ERRROR_SUCCESS or one of the following values: - * ERROR_BAD_PATHNAME if the path is relative - * ERROR_FILE_EXISTS when a file with that name exists - * ERROR_PATH_NOT_FOUND can't find the path, probably invalid - * ERROR_INVLID_NAME if the path contains invalid chars - * ERROR_ALREADY_EXISTS when the directory already exists - * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process - * - * NOTES - * exported by ordinal - * Win9x exports ANSI - * WinNT/2000 exports Unicode - */ -DWORD WINAPI SHCreateDirectory(HWND hWnd, LPCVOID path) -{ - if (SHELL_OsIsUnicode()) - return SHCreateDirectoryExW(hWnd, path, NULL); - return SHCreateDirectoryExA(hWnd, path, NULL); -} - -/************************************************************************* - * SHCreateDirectoryExA [SHELL32.@] - * - * This function creates a file system folder whose fully qualified path is - * given by path. If one or more of the intermediate folders do not exist, - * they will be created as well. - * - * PARAMS - * hWnd [I] - * path [I] path of directory to create - * sec [I] security attributes to use or NULL - * - * RETURNS - * ERRROR_SUCCESS or one of the following values: - * ERROR_BAD_PATHNAME or ERROR_PATH_NOT_FOUND if the path is relative - * ERROR_INVLID_NAME if the path contains invalid chars - * ERROR_FILE_EXISTS when a file with that name exists - * ERROR_ALREADY_EXISTS when the directory already exists - * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process - * - * FIXME: Not implemented yet; - * SHCreateDirectoryEx also verifies that the files in the directory will be visible - * if the path is a network path to deal with network drivers which might have a limited - * but unknown maximum path length. If not: - * - * If hWnd is set to a valid window handle, a message box is displayed warning - * the user that the files may not be accessible. If the user chooses not to - * proceed, the function returns ERROR_CANCELLED. - * - * If hWnd is set to NULL, no user interface is displayed and the function - * returns ERROR_CANCELLED. - */ -int WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec) -{ - LPWSTR wPath; - DWORD retCode; - - TRACE("(%s, %p)\n", debugstr_a(path), sec); - - retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); - if (!retCode) - { - retCode = SHCreateDirectoryExW(hWnd, wPath, sec); - SHELL32_FreeUnicodeBuf(wPath); - } - return retCode; -} - -/************************************************************************* - * SHCreateDirectoryExW [SHELL32.@] - */ -int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec) -{ - int ret = ERROR_BAD_PATHNAME; - TRACE("(%p, %s, %p)\n", hWnd, debugstr_w(path), sec); - - if (PathIsRelativeW(path)) - { - SetLastError(ret); - } - else - { - ret = SHNotifyCreateDirectoryW(path, sec); - /* Refuse to work on certain error codes before trying to create directories recursively */ - if (ret != ERROR_FILE_EXISTS && - ret != ERROR_ALREADY_EXISTS && - ret != ERROR_FILENAME_EXCED_RANGE) - { - WCHAR *pEnd, *pSlash, szTemp[MAX_PATH + 1]; /* extra for PathAddBackslash() */ - - lstrcpynW(szTemp, path, MAX_PATH); - pEnd = PathAddBackslashW(szTemp); - pSlash = szTemp + 3; - - while (*pSlash) - { - while (*pSlash && *pSlash != '\\') - pSlash = CharNextW(pSlash); - - if (*pSlash) - { - *pSlash = 0; /* terminate path at separator */ - - ret = SHNotifyCreateDirectoryW(szTemp, pSlash + 1 == pEnd ? sec : NULL); - } - *pSlash++ = '\\'; /* put the separator back */ - } - } - - if (ret && hWnd && (ERROR_CANCELLED != ret)) - { - /* We failed and should show a dialog box */ - FIXME("Show system error message, creating path %s, failed with error %d\n", debugstr_w(path), ret); - ret = ERROR_CANCELLED; /* Error has been already presented to user (not really yet!) */ - } - } - return ret; -} - - -/************************************************************************* - * SHFindAttrW [internal] - * - * Get the Attributes for a file or directory. The difference to GetAttributes() - * is that this function will also work for paths containing wildcard characters - * in its filename. - - * PARAMS - * path [I] path of directory or file to check - * fileOnly [I] TRUE if only files should be found - * - * RETURNS - * INVALID_FILE_ATTRIBUTES if the path does not exist, the actual attributes of - * the first file or directory found otherwise - */ -static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly) -{ - WIN32_FIND_DATAW wfd; - BOOL b_FileMask = fileOnly && (NULL != StrPBrkW(pName, wWildcardChars)); - DWORD dwAttr = INVALID_FILE_ATTRIBUTES; - HANDLE hFind = FindFirstFileW(pName, &wfd); - - TRACE("%s %d\n", debugstr_w(pName), fileOnly); - if (INVALID_HANDLE_VALUE != hFind) - { - do - { - if (b_FileMask && IsAttribDir(wfd.dwFileAttributes)) - continue; - dwAttr = wfd.dwFileAttributes; - break; - } - while (FindNextFileW(hFind, &wfd)); - FindClose(hFind); - } - return dwAttr; -} - -/************************************************************************* - * - * SHFileStrICmp HelperFunction for SHFileOperationW - * - */ -BOOL SHFileStrICmpW(LPWSTR p1, LPWSTR p2, LPWSTR p1End, LPWSTR p2End) -{ - WCHAR C1 = '\0'; - WCHAR C2 = '\0'; - int i_Temp = -1; - int i_len1 = lstrlenW(p1); - int i_len2 = lstrlenW(p2); - - if (p1End && (&p1[i_len1] >= p1End) && ('\\' == p1End[0])) - { - C1 = p1End[0]; - p1End[0] = '\0'; - i_len1 = lstrlenW(p1); - } - if (p2End) - { - if ((&p2[i_len2] >= p2End) && ('\\' == p2End[0])) - { - C2 = p2End[0]; - if (C2) - p2End[0] = '\0'; - } - } - else - { - if ((i_len1 <= i_len2) && ('\\' == p2[i_len1])) - { - C2 = p2[i_len1]; - if (C2) - p2[i_len1] = '\0'; - } - } - i_len2 = lstrlenW(p2); - if (i_len1 == i_len2) - i_Temp = lstrcmpiW(p1,p2); - if (C1) - p1[i_len1] = C1; - if (C2) - p2[i_len2] = C2; - return !(i_Temp); -} - -/************************************************************************* - * - * SHFileStrCpyCat HelperFunction for SHFileOperationW - * - */ -LPWSTR SHFileStrCpyCatW(LPWSTR pTo, LPCWSTR pFrom, LPCWSTR pCatStr) -{ - LPWSTR pToFile = NULL; - int i_len; - if (pTo) - { - if (pFrom) - lstrcpyW(pTo, pFrom); - if (pCatStr) - { - i_len = lstrlenW(pTo); - if ((i_len) && (pTo[--i_len] != '\\')) - i_len++; - pTo[i_len] = '\\'; - if (pCatStr[0] == '\\') - pCatStr++; \ - lstrcpyW(&pTo[i_len+1], pCatStr); - } - pToFile = StrRChrW(pTo,NULL,'\\'); - /* termination of the new string-group */ - pTo[(lstrlenW(pTo)) + 1] = '\0'; - } - return pToFile; -} - -/************************************************************************** - * SHELL_FileNamesMatch() - * - * Accepts two \0 delimited lists of the file names. Checks whether number of - * files in both lists is the same, and checks also if source-name exists. - */ -BOOL SHELL_FileNamesMatch(LPCWSTR pszFiles1, LPCWSTR pszFiles2, BOOL bOnlySrc) -{ - while ((pszFiles1[0] != '\0') && - (bOnlySrc || (pszFiles2[0] != '\0'))) - { - if (NULL == StrPBrkW(pszFiles1, wWildcardChars)) - { - if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(pszFiles1)) - return FALSE; - } - pszFiles1 += lstrlenW(pszFiles1) + 1; - if (!bOnlySrc) - pszFiles2 += lstrlenW(pszFiles2) + 1; - } - return ((pszFiles1[0] == '\0') && (bOnlySrc || (pszFiles2[0] == '\0'))); -} - -/************************************************************************* - * - * SHNameTranslate HelperFunction for SHFileOperationA - * - * Translates a list of 0 terminated ASCII strings into Unicode. If *wString - * is NULL, only the necessary size of the string is determined and returned, - * otherwise the ASCII strings are copied into it and the buffer is increased - * to point to the location after the final 0 termination char. - */ -DWORD SHNameTranslate(LPWSTR* wString, LPCWSTR* pWToFrom, BOOL more) -{ - DWORD size = 0, aSize = 0; - LPCSTR aString = (LPCSTR)*pWToFrom; - - if (aString) - { - do - { - size = lstrlenA(aString) + 1; - aSize += size; - aString += size; - } while ((size != 1) && more); - /* The two sizes might be different in the case of multibyte chars */ - size = MultiByteToWideChar(CP_ACP, 0, aString, aSize, *wString, 0); - if (*wString) /* only in the second loop */ - { - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*pWToFrom, aSize, *wString, size); - *pWToFrom = *wString; - *wString += size; - } - } - return size; -} -/************************************************************************* - * SHFileOperationA [SHELL32.@] - * - * Function to copy, move, delete and create one or more files with optional - * user prompts. - * - * PARAMS - * lpFileOp [I/O] pointer to a structure containing all the necessary information - * - * NOTES - * exported by name - */ -int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp) -{ - SHFILEOPSTRUCTW nFileOp = *((LPSHFILEOPSTRUCTW)lpFileOp); - int retCode = 0; - DWORD size; - LPWSTR ForFree = NULL, /* we change wString in SHNameTranslate and can't use it for freeing */ - wString = NULL; /* we change this in SHNameTranslate */ - - TRACE("\n"); - if (FO_DELETE == (nFileOp.wFunc & FO_MASK)) - nFileOp.pTo = NULL; /* we need a NULL or a valid pointer for translation */ - if (!(nFileOp.fFlags & FOF_SIMPLEPROGRESS)) - nFileOp.lpszProgressTitle = NULL; /* we need a NULL or a valid pointer for translation */ - while (1) /* every loop calculate size, second translate also, if we have storage for this */ - { - size = SHNameTranslate(&wString, &nFileOp.lpszProgressTitle, FALSE); /* no loop */ - size += SHNameTranslate(&wString, &nFileOp.pFrom, TRUE); /* internal loop */ - size += SHNameTranslate(&wString, &nFileOp.pTo, TRUE); /* internal loop */ - - if (ForFree) - { - retCode = SHFileOperationW(&nFileOp); - HeapFree(GetProcessHeap(), 0, ForFree); /* we can not use wString, it was changed */ - break; - } - else - { - wString = ForFree = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); - if (ForFree) continue; - retCode = ERROR_OUTOFMEMORY; - nFileOp.fAnyOperationsAborted = TRUE; - SetLastError(retCode); - return retCode; - } - } - - lpFileOp->hNameMappings = nFileOp.hNameMappings; - lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted; - return retCode; -} - -static const char * debug_shfileops_flags( DWORD fFlags ) -{ - return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s", - fFlags & FOF_MULTIDESTFILES ? "FOF_MULTIDESTFILES " : "", - fFlags & FOF_CONFIRMMOUSE ? "FOF_CONFIRMMOUSE " : "", - fFlags & FOF_SILENT ? "FOF_SILENT " : "", - fFlags & FOF_RENAMEONCOLLISION ? "FOF_RENAMEONCOLLISION " : "", - fFlags & FOF_NOCONFIRMATION ? "FOF_NOCONFIRMATION " : "", - fFlags & FOF_WANTMAPPINGHANDLE ? "FOF_WANTMAPPINGHANDLE " : "", - fFlags & FOF_ALLOWUNDO ? "FOF_ALLOWUNDO " : "", - fFlags & FOF_FILESONLY ? "FOF_FILESONLY " : "", - fFlags & FOF_SIMPLEPROGRESS ? "FOF_SIMPLEPROGRESS " : "", - fFlags & FOF_NOCONFIRMMKDIR ? "FOF_NOCONFIRMMKDIR " : "", - fFlags & FOF_NOERRORUI ? "FOF_NOERRORUI " : "", - fFlags & FOF_NOCOPYSECURITYATTRIBS ? "FOF_NOCOPYSECURITYATTRIBS" : "", - fFlags & 0xf000 ? "MORE-UNKNOWN-Flags" : ""); -} - -static const char * debug_shfileops_action( DWORD op ) -{ - LPCSTR cFO_Name [] = {"FO_????","FO_MOVE","FO_COPY","FO_DELETE","FO_RENAME"}; - return wine_dbg_sprintf("%s", cFO_Name[ op ]); -} - -#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026 -#define HIGH_ADR (LPWSTR)0xffffffff - -/************************************************************************* - * SHFileOperationW [SHELL32.@] - * - * See SHFileOperationA - */ -int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp) -{ - SHFILEOPSTRUCTW nFileOp = *(lpFileOp); - - LPCWSTR pNextFrom = nFileOp.pFrom; - LPCWSTR pNextTo = nFileOp.pTo; - LPCWSTR pFrom = pNextFrom; - LPCWSTR pTo = NULL; - HANDLE hFind = INVALID_HANDLE_VALUE; - WIN32_FIND_DATAW wfd; - LPWSTR pTempFrom = NULL; - LPWSTR pTempTo = NULL; - LPWSTR pFromFile; - LPWSTR pToFile = NULL; - LPWSTR lpFileName; - int retCode = 0; - DWORD ToAttr; - DWORD ToPathAttr; - DWORD FromPathAttr; - FILEOP_FLAGS OFl = ((FILEOP_FLAGS)lpFileOp->fFlags & 0xfff); - - BOOL b_Multi = (nFileOp.fFlags & FOF_MULTIDESTFILES); - - BOOL b_MultiTo = (FO_DELETE != (lpFileOp->wFunc & FO_MASK)); - BOOL b_MultiPaired = (!b_MultiTo); - BOOL b_MultiFrom = FALSE; - BOOL not_overwrite; - BOOL ask_overwrite; - BOOL b_SameRoot; - BOOL b_SameTailName; - BOOL b_ToInvalidTail = FALSE; - BOOL b_ToValid; /* for W98-Bug for FO_MOVE with source and target in same rootdrive */ - BOOL b_Mask; - BOOL b_ToTailSlash = FALSE; - - long FuncSwitch = (nFileOp.wFunc & FO_MASK); - long level= nFileOp.wFunc>>4; - - /* default no error */ - nFileOp.fAnyOperationsAborted = FALSE; - - if ((FuncSwitch < FO_MOVE) || (FuncSwitch > FO_RENAME)) - goto shfileop_end; /* no valid FunctionCode */ - - if (level == 0) - TRACE("%s: flags (0x%04x) : %s\n", - debug_shfileops_action(FuncSwitch), nFileOp.fFlags, - debug_shfileops_flags(nFileOp.fFlags) ); - - /* establish when pTo is interpreted as the name of the destination file - * or the directory where the Fromfile should be copied to. - * This depends on: - * (1) pTo points to the name of an existing directory; - * (2) the flag FOF_MULTIDESTFILES is present; - * (3) whether pFrom point to multiple filenames. - * - * Some experiments: - * - * destisdir 1 1 1 1 0 0 0 0 - * FOF_MULTIDESTFILES 1 1 0 0 1 1 0 0 - * multiple from filenames 1 0 1 0 1 0 1 0 - * --------------- - * copy files to dir 1 0 1 1 0 0 1 0 - * create dir 0 0 0 0 0 0 1 0 - */ - - /* - * Summary of flags: - * - * implemented flags: - * FOF_MULTIDESTFILES, FOF_NOCONFIRMATION, FOF_FILESONLY - * - * unimplememented and ignored flags: - * FOF_CONFIRMMOUSE, FOF_SILENT, FOF_NOCONFIRMMKDIR, - * FOF_SIMPLEPROGRESS, FOF_NOCOPYSECURITYATTRIBS - * - * partially implemented, breaks if file exists: - * FOF_RENAMEONCOLLISION - * - * unimplemented and break if any other flag set: - * FOF_ALLOWUNDO, FOF_WANTMAPPINGHANDLE - */ - - TRACE("%s level=%ld nFileOp.fFlags=0x%x\n", - debug_shfileops_action(FuncSwitch), level, lpFileOp->fFlags); - - /* OFl &= (-1 - (FOF_MULTIDESTFILES | FOF_FILESONLY)); */ - /* OFl ^= (FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR); */ - OFl &= (~(FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | FOF_FILESONLY)); /* implemented */ - OFl ^= (FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS); /* ignored, if one */ - OFl &= (~FOF_SIMPLEPROGRESS); /* ignored, only with FOF_SILENT */ - if (OFl) - { - if (OFl & (~(FOF_CONFIRMMOUSE | FOF_SILENT | FOF_RENAMEONCOLLISION | - FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS))) - { - TRACE("%s level=%ld lpFileOp->fFlags=0x%x not implemented, Aborted=TRUE, stub\n", - debug_shfileops_action(FuncSwitch), level, OFl); - retCode = 0x403; /* 1027, we need an extension to shlfileop */ - goto shfileop_end; - } - else - { - TRACE("%s level=%ld lpFileOp->fFlags=0x%x not fully implemented, stub\n", - debug_shfileops_action(FuncSwitch), level, OFl); - } - } - - if ((pNextFrom) && (!(b_MultiTo) || (pNextTo))) - { - nFileOp.pFrom = pTempFrom = HeapAlloc(GetProcessHeap(), 0, ((1 + 2 * (b_MultiTo)) * MAX_PATH + 6) * sizeof(WCHAR)); - if (!pTempFrom) - { - retCode = ERROR_OUTOFMEMORY; - SetLastError(retCode); - goto shfileop_end; - } - if (b_MultiTo) - pTempTo = &pTempFrom[MAX_PATH + 4]; - nFileOp.pTo = pTempTo; - ask_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) && !(nFileOp.fFlags & FOF_RENAMEONCOLLISION)); - not_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) || (nFileOp.fFlags & FOF_RENAMEONCOLLISION)); - } - else - { - retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; - goto shfileop_end; - } - /* need break at error before change sourcepointer */ - while(!nFileOp.fAnyOperationsAborted && (pNextFrom[0])) - { - nFileOp.wFunc = ((level + 1) << 4) + FuncSwitch; - nFileOp.fFlags = lpFileOp->fFlags; - - if (b_MultiTo) - { - pTo = pNextTo; - pNextTo = &pNextTo[lstrlenW(pTo)+1]; - b_MultiTo = (b_Multi && pNextTo[0]); - } - - pFrom = pNextFrom; - pNextFrom = &pNextFrom[lstrlenW(pNextFrom)+1]; - if (!b_MultiFrom && !b_MultiTo) - b_MultiFrom = (pNextFrom[0]); - - pFromFile = SHFileStrCpyCatW(pTempFrom, pFrom, NULL); - - if (pTo) - { - pToFile = SHFileStrCpyCatW(pTempTo, pTo, NULL); - } - if (!b_MultiPaired) - { - b_MultiPaired = - SHELL_FileNamesMatch(lpFileOp->pFrom, lpFileOp->pTo, (!b_Multi || b_MultiFrom)); - } - if (!(b_MultiPaired) || !(pFromFile) || !(pFromFile[1]) || ((pTo) && !(pToFile))) - { - retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; - goto shfileop_end; - } - if (pTo) - { - b_ToTailSlash = (!pToFile[1]); - if (b_ToTailSlash) - { - pToFile[0] = '\0'; - if (StrChrW(pTempTo,'\\')) - { - pToFile = SHFileStrCpyCatW(pTempTo, NULL, NULL); - } - } - b_ToInvalidTail = (NULL != StrPBrkW(&pToFile[1], wWildcardChars)); - } - - /* for all */ - b_Mask = (NULL != StrPBrkW(&pFromFile[1], wWildcardChars)); - if (FO_RENAME == FuncSwitch) - { - /* temporary only for FO_RENAME */ - if (b_MultiTo || b_MultiFrom || (b_Mask && !b_ToInvalidTail)) - { -#ifndef W98_FO_FUNCTION - retCode = ERROR_GEN_FAILURE; /* W2K ERROR_GEN_FAILURE, W98 returns no error */ -#endif - goto shfileop_end; - } - } - - hFind = FindFirstFileW(pFrom, &wfd); - if (INVALID_HANDLE_VALUE == hFind) - { - if ((FO_DELETE == FuncSwitch) && (b_Mask)) - { - pFromFile[0] = '\0'; - FromPathAttr = GetFileAttributesW(pTempFrom); - pFromFile[0] = '\\'; - if (IsAttribDir(FromPathAttr)) - { - /* FO_DELETE with mask and without found is valid */ - goto shfileop_end; - } - } - /* root (without mask) is also not allowed as source, tested in W98 */ - retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; - goto shfileop_end; - } - - /* for all */ - - /* ??? b_Mask = (!SHFileStrICmpA(&pFromFile[1], &wfd.cFileName[0], HIGH_ADR, HIGH_ADR)); */ - if (!pTo) /* FO_DELETE */ - { - do - { - lpFileName = wfd.cAlternateFileName; - if (!lpFileName[0]) - lpFileName = wfd.cFileName; - if (IsDotDir(lpFileName) || - ((b_Mask) && IsAttribDir(wfd.dwFileAttributes) && (nFileOp.fFlags & FOF_FILESONLY))) - continue; - SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL); - /* TODO: Check the SHELL_DeleteFileOrDirectoryW() function in shell32.dll */ - if (IsAttribFile(wfd.dwFileAttributes)) - { - if(SHNotifyDeleteFileW(pTempFrom) != ERROR_SUCCESS) - { - nFileOp.fAnyOperationsAborted = TRUE; - retCode = 0x78; /* value unknown */ - } - } - else - { - if(!SHELL_DeleteDirectoryW(pTempFrom, (!(nFileOp.fFlags & FOF_NOCONFIRMATION)))) - { - nFileOp.fAnyOperationsAborted = TRUE; - retCode = 0x79; /* value unknown */ - } - } - } while (!nFileOp.fAnyOperationsAborted && FindNextFileW(hFind, &wfd)); - FindClose(hFind); - hFind = INVALID_HANDLE_VALUE; - if (nFileOp.fAnyOperationsAborted) - goto shfileop_end; - continue; - } /* FO_DELETE ends, pTo must be always valid from here */ - - b_SameRoot = (toupperW(pTempFrom[0]) == toupperW(pTempTo[0])); - b_SameTailName = SHFileStrICmpW(pToFile, pFromFile, NULL, NULL); - - ToPathAttr = ToAttr = GetFileAttributesW(pTempTo); - if (!b_Mask && (ToAttr == INVALID_FILE_ATTRIBUTES) && (pToFile)) - { - pToFile[0] = '\0'; - ToPathAttr = GetFileAttributesW(pTempTo); - pToFile[0] = '\\'; - } - - if (FO_RENAME == FuncSwitch) - { - if (!b_SameRoot || b_Mask /* FO_RENAME works not with Mask */ - || !SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, NULL) - || (SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, HIGH_ADR) && !b_ToTailSlash)) - { - retCode = 0x73; - goto shfileop_end; - } - if (b_ToInvalidTail) - { - retCode=0x2; - goto shfileop_end; - } - if (INVALID_FILE_ATTRIBUTES == ToPathAttr) - { - retCode = 0x75; - goto shfileop_end; - } - if (IsAttribDir(wfd.dwFileAttributes) && IsAttribDir(ToAttr)) - { - retCode = (b_ToTailSlash) ? 0xb7 : 0x7b; - goto shfileop_end; - } - /* we use SHNotifyMoveFile() instead MoveFileW */ - if (SHNotifyMoveFileW(pTempFrom, pTempTo) != ERROR_SUCCESS) - { - /* we need still the value for the returncode, we use the mostly assumed */ - retCode = 0xb7; - goto shfileop_end; - } - goto shfileop_end; - } - - /* W98 Bug with FO_MOVE different from FO_COPY, better the same as FO_COPY */ - b_ToValid = ((b_SameTailName && b_SameRoot && (FO_COPY == FuncSwitch)) || - (b_SameTailName && !b_SameRoot) || (b_ToInvalidTail)); - - /* handle mask in source */ - if (b_Mask) - { - if (!IsAttribDir(ToAttr)) - { - retCode = (b_ToInvalidTail &&/* b_SameTailName &&*/ (FO_MOVE == FuncSwitch)) \ - ? 0x2 : 0x75; - goto shfileop_end; - } - pToFile = SHFileStrCpyCatW(pTempTo, NULL, wBackslash); - nFileOp.fFlags = (nFileOp.fFlags | FOF_MULTIDESTFILES); - do - { - lpFileName = wfd.cAlternateFileName; - if (!lpFileName[0]) - lpFileName = wfd.cFileName; - if (IsDotDir(lpFileName) || - (IsAttribDir(wfd.dwFileAttributes) && (nFileOp.fFlags & FOF_FILESONLY))) - continue; /* next name in pTempFrom(dir) */ - SHFileStrCpyCatW(&pToFile[1], lpFileName, NULL); - SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL); - retCode = SHFileOperationW (&nFileOp); - } while(!nFileOp.fAnyOperationsAborted && FindNextFileW(hFind, &wfd)); - } - FindClose(hFind); - hFind = INVALID_HANDLE_VALUE; - /* FO_COPY/FO_MOVE with mask, FO_DELETE and FO_RENAME are solved */ - if (b_Mask) - continue; - - /* only FO_COPY/FO_MOVE without mask, all others are (must be) solved */ - if (IsAttribDir(wfd.dwFileAttributes) && (ToAttr == INVALID_FILE_ATTRIBUTES)) - { - if (pToFile) - { - pToFile[0] = '\0'; - ToPathAttr = GetFileAttributesW(pTempTo); - if ((ToPathAttr == INVALID_FILE_ATTRIBUTES) && b_ToValid) - { - /* create dir must be here, sample target D:\y\ *.* create with RC=10003 */ - if (SHNotifyCreateDirectoryW(pTempTo, NULL)) - { - retCode = 0x73;/* value unknown */ - goto shfileop_end; - } - ToPathAttr = GetFileAttributesW(pTempTo); - } - pToFile[0] = '\\'; - if (b_ToInvalidTail) - { - retCode = 0x10003; - goto shfileop_end; - } - } - } - - /* trailing BackSlash is ever removed and pToFile points to BackSlash before */ - if (!b_MultiTo && (b_MultiFrom || (!(b_Multi) && IsAttribDir(ToAttr)))) - { - if ((FO_MOVE == FuncSwitch) && IsAttribDir(ToAttr) && IsAttribDir(wfd.dwFileAttributes)) - { - if (b_Multi) - { - retCode = 0x73; /* !b_Multi = 0x8 ?? */ - goto shfileop_end; - } - } - pToFile = SHFileStrCpyCatW(pTempTo, NULL, wfd.cFileName); - ToAttr = GetFileAttributesW(pTempTo); - } - - if (IsAttribDir(ToAttr)) - { - if (IsAttribFile(wfd.dwFileAttributes)) - { - retCode = (FO_COPY == FuncSwitch) ? 0x75 : 0xb7; - goto shfileop_end; - } - } - else - { - pToFile[0] = '\0'; - ToPathAttr = GetFileAttributesW(pTempTo); - pToFile[0] = '\\'; - if (IsAttribFile(ToPathAttr)) - { - /* error, is this tested ? */ - retCode = 0x777402; - goto shfileop_end; - } - } - - /* singlesource + no mask */ - if (INVALID_FILE_ATTRIBUTES == (ToAttr & ToPathAttr)) - { - /* Target-dir does not exist, and cannot be created */ - retCode=0x75; - goto shfileop_end; - } - - switch(FuncSwitch) - { - case FO_MOVE: - pToFile = NULL; - if ((ToAttr == INVALID_FILE_ATTRIBUTES) && SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, NULL)) - { - nFileOp.wFunc = ((level+1)<<4) + FO_RENAME; - } - else - { - if (b_SameRoot && IsAttribDir(ToAttr) && IsAttribDir(wfd.dwFileAttributes)) - { - /* we need pToFile for FO_DELETE after FO_MOVE contence */ - pToFile = SHFileStrCpyCatW(pTempFrom, NULL, wWildcardFile); - } - else - { - nFileOp.wFunc = ((level+1)<<4) + FO_COPY; - } - } - retCode = SHFileOperationW(&nFileOp); - if (pToFile) - ((DWORD*)pToFile)[0] = '\0'; - if (!nFileOp.fAnyOperationsAborted && (FO_RENAME != (nFileOp.wFunc & 0xf))) - { - nFileOp.wFunc = ((level+1)<<4) + FO_DELETE; - retCode = SHFileOperationW(&nFileOp); - } - continue; - case FO_COPY: - if (SHFileStrICmpW(pTempFrom, pTempTo, NULL, NULL)) - { /* target is the same as source ? */ - /* we still need the value for the returncode, we assume 0x71 */ - retCode = 0x71; - goto shfileop_end; - } - if (IsAttribDir((ToAttr & wfd.dwFileAttributes))) - { - if (IsAttribDir(ToAttr) || !SHNotifyCreateDirectoryW(pTempTo, NULL)) - { - /* ??? nFileOp.fFlags = (nFileOp.fFlags | FOF_MULTIDESTFILES); */ - SHFileStrCpyCatW(pTempFrom, NULL, wWildcardFile); - retCode = SHFileOperationW(&nFileOp); - } - else - { - retCode = 0x750;/* value unknown */ - goto shfileop_end; - } - } - else - { - if (!(ask_overwrite && SHELL_ConfirmDialogW(ASK_OVERWRITE_FILE, pTempTo)) - && (not_overwrite)) - { - /* we still need the value for the returncode, we use the mostly assumed */ - retCode = 0x73; - goto shfileop_end; - } - if (SHNotifyCopyFileW(pTempFrom, pTempTo, TRUE) != ERROR_SUCCESS) - { - retCode = 0x77; /* value unknown */ - goto shfileop_end; - } - } - } - } - -shfileop_end: - if (hFind != INVALID_HANDLE_VALUE) - FindClose(hFind); - hFind = INVALID_HANDLE_VALUE; - if (pTempFrom) - HeapFree(GetProcessHeap(), 0, pTempFrom); - if (retCode) - nFileOp.fAnyOperationsAborted = TRUE; - TRACE("%s level=%ld AnyOpsAborted=%s ret=0x%x, with %s %s%s\n", - debug_shfileops_action(FuncSwitch), level, - nFileOp.fAnyOperationsAborted ? "TRUE":"FALSE", - retCode, debugstr_w(pFrom), pTo ? "-> ":"", debugstr_w(pTo)); - - lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted; - return retCode; -} - -/************************************************************************* - * SHFileOperation [SHELL32.@] - * - */ -DWORD WINAPI SHFileOperationAW(LPVOID lpFileOp) -{ - if (SHELL_OsIsUnicode()) - return SHFileOperationW(lpFileOp); - return SHFileOperationA(lpFileOp); -} - -#define SHDSA_GetItemCount(hdsa) (*(int*)(hdsa)) - -/************************************************************************* - * SHFreeNameMappings [shell32.246] - * - * Free the mapping handle returned by SHFileoperation if FOF_WANTSMAPPINGHANDLE - * was specified. - * - * PARAMS - * hNameMapping [I] handle to the name mappings used during renaming of files - * - */ -void WINAPI SHFreeNameMappings(HANDLE hNameMapping) -{ - if (hNameMapping) - { - int i = SHDSA_GetItemCount((HDSA)hNameMapping) - 1; - - for (; i>= 0; i--) - { - LPSHNAMEMAPPINGW lp = DSA_GetItemPtr((HDSA)hNameMapping, i); - - SHFree(lp->pszOldPath); - SHFree(lp->pszNewPath); - } - DSA_Destroy((HDSA)hNameMapping); - } -} - -/************************************************************************* - * SheGetDirW [SHELL32.281] - * - */ -HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v) -{ FIXME("%p %p stub\n",u,v); - return 0; -} - -/************************************************************************* - * SheChangeDirW [SHELL32.274] - * - */ -HRESULT WINAPI SheChangeDirW(LPWSTR u) -{ FIXME("(%s),stub\n",debugstr_w(u)); - return 0; -} - -/************************************************************************* - * IsNetDrive [SHELL32.66] - */ -BOOL WINAPI IsNetDrive(DWORD drive) -{ - char root[4]; - strcpy(root, "A:\\"); - root[0] += (char)drive; - return (GetDriveTypeA(root) == DRIVE_REMOTE); -} - - -/************************************************************************* - * RealDriveType [SHELL32.524] - */ -INT WINAPI RealDriveType(INT drive, BOOL bQueryNet) -{ - char root[] = "A:\\"; - root[0] += (char)drive; - return GetDriveTypeA(root); -} +/* + * SHFileOperation + * + * Copyright 2000 Juergen Schmied + * Copyright 2002 Andriy Palamarchuk + * Copyright 2004 Dietrich Teickner (from Odin) + * Copyright 2004 Rolf Kalbermatter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "shellapi.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "shresdef.h" +#define NO_SHLWAPI_STREAM +#include "shlwapi.h" +#include "shell32_main.h" +#include "undocshell.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +#define IsAttrib(x, y) ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y))) +#define IsAttribFile(x) (!((x) & FILE_ATTRIBUTE_DIRECTORY)) +#define IsAttribDir(x) IsAttrib(x, FILE_ATTRIBUTE_DIRECTORY) +#define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0)))) + +#define FO_MASK 0xF + +static const WCHAR wWildcardFile[] = {'*',0}; +static const WCHAR wWildcardChars[] = {'*','?',0}; +static const WCHAR wBackslash[] = {'\\',0}; + +static BOOL SHELL_DeleteDirectoryW(LPCWSTR path, BOOL bShowUI); +static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec); +static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec); +static DWORD SHNotifyRemoveDirectoryA(LPCSTR path); +static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path); +static DWORD SHNotifyDeleteFileA(LPCSTR path); +static DWORD SHNotifyDeleteFileW(LPCWSTR path); +static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest); +static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists); +static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly); + +typedef struct +{ + UINT caption_resource_id, text_resource_id; +} SHELL_ConfirmIDstruc; + +static BOOL SHELL_ConfirmIDs(int nKindOfDialog, SHELL_ConfirmIDstruc *ids) +{ + switch (nKindOfDialog) { + case ASK_DELETE_FILE: + ids->caption_resource_id = IDS_DELETEITEM_CAPTION; + ids->text_resource_id = IDS_DELETEITEM_TEXT; + return TRUE; + case ASK_DELETE_FOLDER: + ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION; + ids->text_resource_id = IDS_DELETEITEM_TEXT; + return TRUE; + case ASK_DELETE_MULTIPLE_ITEM: + ids->caption_resource_id = IDS_DELETEITEM_CAPTION; + ids->text_resource_id = IDS_DELETEMULTIPLE_TEXT; + return TRUE; + case ASK_OVERWRITE_FILE: + ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION; + ids->text_resource_id = IDS_OVERWRITEFILE_TEXT; + return TRUE; + default: + FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog); + } + return FALSE; +} + +BOOL SHELL_ConfirmDialog(int nKindOfDialog, LPCSTR szDir) +{ + CHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256]; + SHELL_ConfirmIDstruc ids; + + if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) + return FALSE; + + LoadStringA(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)); + LoadStringA(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)); + + FormatMessageA(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, + szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir); + + return (IDOK == MessageBoxA(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION)); +} + +BOOL SHELL_ConfirmDialogW(int nKindOfDialog, LPCWSTR szDir) +{ + WCHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256]; + SHELL_ConfirmIDstruc ids; + + if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) + return FALSE; + + LoadStringW(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)); + LoadStringW(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)); + + FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, + szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir); + + return (IDOK == MessageBoxW(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION)); +} + +static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minChars) +{ + DWORD len = MultiByteToWideChar(CP_ACP, 0, aPath, -1, NULL, 0); + + if (len < minChars) + len = minChars; + + *wPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (*wPath) + { + MultiByteToWideChar(CP_ACP, 0, aPath, -1, *wPath, len); + return NO_ERROR; + } + return E_OUTOFMEMORY; +} + +static void SHELL32_FreeUnicodeBuf(LPWSTR wPath) +{ + HeapFree(GetProcessHeap(), 0, wPath); +} + +/************************************************************************** + * SHELL_DeleteDirectory() [internal] + * + * Asks for confirmation when bShowUI is true and deletes the directory and + * all its subdirectories and files if necessary. + */ +BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI) +{ + LPWSTR wPath; + BOOL ret = FALSE; + + if (!SHELL32_AnsiToUnicodeBuf(pszDir, &wPath, 0)) + { + ret = SHELL_DeleteDirectoryW(wPath, bShowUI); + SHELL32_FreeUnicodeBuf(wPath); + } + return ret; +} + +static BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI) +{ + BOOL ret = TRUE; + HANDLE hFind; + WIN32_FIND_DATAW wfd; + WCHAR szTemp[MAX_PATH]; + + /* Make sure the directory exists before eventually prompting the user */ + PathCombineW(szTemp, pszDir, wWildcardFile); + hFind = FindFirstFileW(szTemp, &wfd); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + + if (!bShowUI || (ret = SHELL_ConfirmDialogW(ASK_DELETE_FOLDER, pszDir))) + { + do + { + LPWSTR lp = wfd.cAlternateFileName; + if (!lp[0]) + lp = wfd.cFileName; + if (IsDotDir(lp)) + continue; + PathCombineW(szTemp, pszDir, lp); + if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes) + ret = SHELL_DeleteDirectoryW(szTemp, FALSE); + else + ret = (SHNotifyDeleteFileW(szTemp) == ERROR_SUCCESS); + } while (ret && FindNextFileW(hFind, &wfd)); + } + FindClose(hFind); + if (ret) + ret = (SHNotifyRemoveDirectoryW(pszDir) == ERROR_SUCCESS); + return ret; +} + +/************************************************************************** + * SHELL_DeleteFileA() [internal] + */ +BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI) +{ + if (bShowUI && !SHELL_ConfirmDialog(ASK_DELETE_FILE, pszFile)) + return FALSE; + + return (SHNotifyDeleteFileA(pszFile) == ERROR_SUCCESS); +} + +BOOL SHELL_DeleteFileW(LPCWSTR pszFile, BOOL bShowUI) +{ + if (bShowUI && !SHELL_ConfirmDialogW(ASK_DELETE_FILE, pszFile)) + return FALSE; + + return (SHNotifyDeleteFileW(pszFile) == ERROR_SUCCESS); +} + +/************************************************************************** + * Win32CreateDirectory [SHELL32.93] + * + * Creates a directory. Also triggers a change notify if one exists. + * + * PARAMS + * path [I] path to directory to create + * + * RETURNS + * TRUE if successful, FALSE otherwise + * + * NOTES: + * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. + * This is Unicode on NT/2000 + */ +static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec) +{ + LPWSTR wPath; + DWORD retCode; + + TRACE("(%s, %p)\n", debugstr_a(path), sec); + + retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); + if (!retCode) + { + retCode = SHNotifyCreateDirectoryW(wPath, sec); + SHELL32_FreeUnicodeBuf(wPath); + } + return retCode; +} + +/**********************************************************************/ + +static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec) +{ + TRACE("(%s, %p)\n", debugstr_w(path), sec); + + if (CreateDirectoryW(path, sec)) + { + SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, path, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/**********************************************************************/ + +BOOL WINAPI Win32CreateDirectoryAW(LPCVOID path, LPSECURITY_ATTRIBUTES sec) +{ + if (SHELL_OsIsUnicode()) + return (SHNotifyCreateDirectoryW(path, sec) == ERROR_SUCCESS); + return (SHNotifyCreateDirectoryA(path, sec) == ERROR_SUCCESS); +} + +/************************************************************************ + * Win32RemoveDirectory [SHELL32.94] + * + * Deletes a directory. Also triggers a change notify if one exists. + * + * PARAMS + * path [I] path to directory to delete + * + * RETURNS + * TRUE if successful, FALSE otherwise + * + * NOTES: + * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. + * This is Unicode on NT/2000 + */ +static DWORD SHNotifyRemoveDirectoryA(LPCSTR path) +{ + LPWSTR wPath; + DWORD retCode; + + TRACE("(%s)\n", debugstr_a(path)); + + retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); + if (!retCode) + { + retCode = SHNotifyRemoveDirectoryW(wPath); + SHELL32_FreeUnicodeBuf(wPath); + } + return retCode; +} + +/***********************************************************************/ + +static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path) +{ + BOOL ret; + TRACE("(%s)\n", debugstr_w(path)); + + ret = RemoveDirectoryW(path); + if (!ret) + { + /* Directory may be write protected */ + DWORD dwAttr = GetFileAttributesW(path); + if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY)) + if (SetFileAttributesW(path, dwAttr & ~FILE_ATTRIBUTE_READONLY)) + ret = RemoveDirectoryW(path); + } + if (ret) + { + SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW, path, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/***********************************************************************/ + +BOOL WINAPI Win32RemoveDirectoryAW(LPCVOID path) +{ + if (SHELL_OsIsUnicode()) + return (SHNotifyRemoveDirectoryW(path) == ERROR_SUCCESS); + return (SHNotifyRemoveDirectoryA(path) == ERROR_SUCCESS); +} + +/************************************************************************ + * Win32DeleteFile [SHELL32.164] + * + * Deletes a file. Also triggers a change notify if one exists. + * + * PARAMS + * path [I] path to file to delete + * + * RETURNS + * TRUE if successful, FALSE otherwise + * + * NOTES: + * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI. + * This is Unicode on NT/2000 + */ +static DWORD SHNotifyDeleteFileA(LPCSTR path) +{ + LPWSTR wPath; + DWORD retCode; + + TRACE("(%s)\n", debugstr_a(path)); + + retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); + if (!retCode) + { + retCode = SHNotifyDeleteFileW(wPath); + SHELL32_FreeUnicodeBuf(wPath); + } + return retCode; +} + +/***********************************************************************/ + +static DWORD SHNotifyDeleteFileW(LPCWSTR path) +{ + BOOL ret; + + TRACE("(%s)\n", debugstr_w(path)); + + ret = DeleteFileW(path); + if (!ret) + { + /* File may be write protected or a system file */ + DWORD dwAttr = GetFileAttributesW(path); + if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) + if (SetFileAttributesW(path, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) + ret = DeleteFileW(path); + } + if (ret) + { + SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, path, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/***********************************************************************/ + +DWORD WINAPI Win32DeleteFileAW(LPCVOID path) +{ + if (SHELL_OsIsUnicode()) + return (SHNotifyDeleteFileW(path) == ERROR_SUCCESS); + return (SHNotifyDeleteFileA(path) == ERROR_SUCCESS); +} + +/************************************************************************ + * SHNotifyMoveFile [internal] + * + * Moves a file. Also triggers a change notify if one exists. + * + * PARAMS + * src [I] path to source file to move + * dest [I] path to target file to move to + * + * RETURNS + * ERORR_SUCCESS if successful + */ +static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest) +{ + BOOL ret; + + TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest)); + + ret = MoveFileW(src, dest); + if (!ret) + { + DWORD dwAttr; + + dwAttr = SHFindAttrW(dest, FALSE); + if (INVALID_FILE_ATTRIBUTES == dwAttr) + { + /* Source file may be write protected or a system file */ + dwAttr = GetFileAttributesW(src); + if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) + if (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) + ret = MoveFileW(src, dest); + } + } + if (ret) + { + SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/************************************************************************ + * SHNotifyCopyFile [internal] + * + * Copies a file. Also triggers a change notify if one exists. + * + * PARAMS + * src [I] path to source file to move + * dest [I] path to target file to move to + * bFailIfExists [I] if TRUE, the target file will not be overwritten if + * a file with this name already exists + * + * RETURNS + * ERROR_SUCCESS if successful + */ +static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists) +{ + BOOL ret; + + TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : ""); + + ret = CopyFileW(src, dest, bFailIfExists); + if (ret) + { + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/************************************************************************* + * SHCreateDirectory [SHELL32.165] + * + * This function creates a file system folder whose fully qualified path is + * given by path. If one or more of the intermediate folders do not exist, + * they will be created as well. + * + * PARAMS + * hWnd [I] + * path [I] path of directory to create + * + * RETURNS + * ERRROR_SUCCESS or one of the following values: + * ERROR_BAD_PATHNAME if the path is relative + * ERROR_FILE_EXISTS when a file with that name exists + * ERROR_PATH_NOT_FOUND can't find the path, probably invalid + * ERROR_INVLID_NAME if the path contains invalid chars + * ERROR_ALREADY_EXISTS when the directory already exists + * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process + * + * NOTES + * exported by ordinal + * Win9x exports ANSI + * WinNT/2000 exports Unicode + */ +DWORD WINAPI SHCreateDirectory(HWND hWnd, LPCVOID path) +{ + if (SHELL_OsIsUnicode()) + return SHCreateDirectoryExW(hWnd, path, NULL); + return SHCreateDirectoryExA(hWnd, path, NULL); +} + +/************************************************************************* + * SHCreateDirectoryExA [SHELL32.@] + * + * This function creates a file system folder whose fully qualified path is + * given by path. If one or more of the intermediate folders do not exist, + * they will be created as well. + * + * PARAMS + * hWnd [I] + * path [I] path of directory to create + * sec [I] security attributes to use or NULL + * + * RETURNS + * ERRROR_SUCCESS or one of the following values: + * ERROR_BAD_PATHNAME or ERROR_PATH_NOT_FOUND if the path is relative + * ERROR_INVLID_NAME if the path contains invalid chars + * ERROR_FILE_EXISTS when a file with that name exists + * ERROR_ALREADY_EXISTS when the directory already exists + * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process + * + * FIXME: Not implemented yet; + * SHCreateDirectoryEx also verifies that the files in the directory will be visible + * if the path is a network path to deal with network drivers which might have a limited + * but unknown maximum path length. If not: + * + * If hWnd is set to a valid window handle, a message box is displayed warning + * the user that the files may not be accessible. If the user chooses not to + * proceed, the function returns ERROR_CANCELLED. + * + * If hWnd is set to NULL, no user interface is displayed and the function + * returns ERROR_CANCELLED. + */ +int WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec) +{ + LPWSTR wPath; + DWORD retCode; + + TRACE("(%s, %p)\n", debugstr_a(path), sec); + + retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0); + if (!retCode) + { + retCode = SHCreateDirectoryExW(hWnd, wPath, sec); + SHELL32_FreeUnicodeBuf(wPath); + } + return retCode; +} + +/************************************************************************* + * SHCreateDirectoryExW [SHELL32.@] + */ +int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec) +{ + int ret = ERROR_BAD_PATHNAME; + TRACE("(%p, %s, %p)\n", hWnd, debugstr_w(path), sec); + + if (PathIsRelativeW(path)) + { + SetLastError(ret); + } + else + { + ret = SHNotifyCreateDirectoryW(path, sec); + /* Refuse to work on certain error codes before trying to create directories recursively */ + if (ret != ERROR_FILE_EXISTS && + ret != ERROR_ALREADY_EXISTS && + ret != ERROR_FILENAME_EXCED_RANGE) + { + WCHAR *pEnd, *pSlash, szTemp[MAX_PATH + 1]; /* extra for PathAddBackslash() */ + + lstrcpynW(szTemp, path, MAX_PATH); + pEnd = PathAddBackslashW(szTemp); + pSlash = szTemp + 3; + + while (*pSlash) + { + while (*pSlash && *pSlash != '\\') + pSlash = CharNextW(pSlash); + + if (*pSlash) + { + *pSlash = 0; /* terminate path at separator */ + + ret = SHNotifyCreateDirectoryW(szTemp, pSlash + 1 == pEnd ? sec : NULL); + } + *pSlash++ = '\\'; /* put the separator back */ + } + } + + if (ret && hWnd && (ERROR_CANCELLED != ret)) + { + /* We failed and should show a dialog box */ + FIXME("Show system error message, creating path %s, failed with error %d\n", debugstr_w(path), ret); + ret = ERROR_CANCELLED; /* Error has been already presented to user (not really yet!) */ + } + } + return ret; +} + + +/************************************************************************* + * SHFindAttrW [internal] + * + * Get the Attributes for a file or directory. The difference to GetAttributes() + * is that this function will also work for paths containing wildcard characters + * in its filename. + + * PARAMS + * path [I] path of directory or file to check + * fileOnly [I] TRUE if only files should be found + * + * RETURNS + * INVALID_FILE_ATTRIBUTES if the path does not exist, the actual attributes of + * the first file or directory found otherwise + */ +static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly) +{ + WIN32_FIND_DATAW wfd; + BOOL b_FileMask = fileOnly && (NULL != StrPBrkW(pName, wWildcardChars)); + DWORD dwAttr = INVALID_FILE_ATTRIBUTES; + HANDLE hFind = FindFirstFileW(pName, &wfd); + + TRACE("%s %d\n", debugstr_w(pName), fileOnly); + if (INVALID_HANDLE_VALUE != hFind) + { + do + { + if (b_FileMask && IsAttribDir(wfd.dwFileAttributes)) + continue; + dwAttr = wfd.dwFileAttributes; + break; + } + while (FindNextFileW(hFind, &wfd)); + FindClose(hFind); + } + return dwAttr; +} + +/************************************************************************* + * + * SHFileStrICmp HelperFunction for SHFileOperationW + * + */ +BOOL SHFileStrICmpW(LPWSTR p1, LPWSTR p2, LPWSTR p1End, LPWSTR p2End) +{ + WCHAR C1 = '\0'; + WCHAR C2 = '\0'; + int i_Temp = -1; + int i_len1 = lstrlenW(p1); + int i_len2 = lstrlenW(p2); + + if (p1End && (&p1[i_len1] >= p1End) && ('\\' == p1End[0])) + { + C1 = p1End[0]; + p1End[0] = '\0'; + i_len1 = lstrlenW(p1); + } + if (p2End) + { + if ((&p2[i_len2] >= p2End) && ('\\' == p2End[0])) + { + C2 = p2End[0]; + if (C2) + p2End[0] = '\0'; + } + } + else + { + if ((i_len1 <= i_len2) && ('\\' == p2[i_len1])) + { + C2 = p2[i_len1]; + if (C2) + p2[i_len1] = '\0'; + } + } + i_len2 = lstrlenW(p2); + if (i_len1 == i_len2) + i_Temp = lstrcmpiW(p1,p2); + if (C1) + p1[i_len1] = C1; + if (C2) + p2[i_len2] = C2; + return !(i_Temp); +} + +/************************************************************************* + * + * SHFileStrCpyCat HelperFunction for SHFileOperationW + * + */ +LPWSTR SHFileStrCpyCatW(LPWSTR pTo, LPCWSTR pFrom, LPCWSTR pCatStr) +{ + LPWSTR pToFile = NULL; + int i_len; + if (pTo) + { + if (pFrom) + lstrcpyW(pTo, pFrom); + if (pCatStr) + { + i_len = lstrlenW(pTo); + if ((i_len) && (pTo[--i_len] != '\\')) + i_len++; + pTo[i_len] = '\\'; + if (pCatStr[0] == '\\') + pCatStr++; \ + lstrcpyW(&pTo[i_len+1], pCatStr); + } + pToFile = StrRChrW(pTo,NULL,'\\'); + /* termination of the new string-group */ + pTo[(lstrlenW(pTo)) + 1] = '\0'; + } + return pToFile; +} + +/************************************************************************** + * SHELL_FileNamesMatch() + * + * Accepts two \0 delimited lists of the file names. Checks whether number of + * files in both lists is the same, and checks also if source-name exists. + */ +BOOL SHELL_FileNamesMatch(LPCWSTR pszFiles1, LPCWSTR pszFiles2, BOOL bOnlySrc) +{ + while ((pszFiles1[0] != '\0') && + (bOnlySrc || (pszFiles2[0] != '\0'))) + { + if (NULL == StrPBrkW(pszFiles1, wWildcardChars)) + { + if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(pszFiles1)) + return FALSE; + } + pszFiles1 += lstrlenW(pszFiles1) + 1; + if (!bOnlySrc) + pszFiles2 += lstrlenW(pszFiles2) + 1; + } + return ((pszFiles1[0] == '\0') && (bOnlySrc || (pszFiles2[0] == '\0'))); +} + +/************************************************************************* + * + * SHNameTranslate HelperFunction for SHFileOperationA + * + * Translates a list of 0 terminated ASCII strings into Unicode. If *wString + * is NULL, only the necessary size of the string is determined and returned, + * otherwise the ASCII strings are copied into it and the buffer is increased + * to point to the location after the final 0 termination char. + */ +DWORD SHNameTranslate(LPWSTR* wString, LPCWSTR* pWToFrom, BOOL more) +{ + DWORD size = 0, aSize = 0; + LPCSTR aString = (LPCSTR)*pWToFrom; + + if (aString) + { + do + { + size = lstrlenA(aString) + 1; + aSize += size; + aString += size; + } while ((size != 1) && more); + /* The two sizes might be different in the case of multibyte chars */ + size = MultiByteToWideChar(CP_ACP, 0, aString, aSize, *wString, 0); + if (*wString) /* only in the second loop */ + { + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*pWToFrom, aSize, *wString, size); + *pWToFrom = *wString; + *wString += size; + } + } + return size; +} +/************************************************************************* + * SHFileOperationA [SHELL32.@] + * + * Function to copy, move, delete and create one or more files with optional + * user prompts. + * + * PARAMS + * lpFileOp [I/O] pointer to a structure containing all the necessary information + * + * NOTES + * exported by name + */ +int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp) +{ + SHFILEOPSTRUCTW nFileOp = *((LPSHFILEOPSTRUCTW)lpFileOp); + int retCode = 0; + DWORD size; + LPWSTR ForFree = NULL, /* we change wString in SHNameTranslate and can't use it for freeing */ + wString = NULL; /* we change this in SHNameTranslate */ + + TRACE("\n"); + if (FO_DELETE == (nFileOp.wFunc & FO_MASK)) + nFileOp.pTo = NULL; /* we need a NULL or a valid pointer for translation */ + if (!(nFileOp.fFlags & FOF_SIMPLEPROGRESS)) + nFileOp.lpszProgressTitle = NULL; /* we need a NULL or a valid pointer for translation */ + while (1) /* every loop calculate size, second translate also, if we have storage for this */ + { + size = SHNameTranslate(&wString, &nFileOp.lpszProgressTitle, FALSE); /* no loop */ + size += SHNameTranslate(&wString, &nFileOp.pFrom, TRUE); /* internal loop */ + size += SHNameTranslate(&wString, &nFileOp.pTo, TRUE); /* internal loop */ + + if (ForFree) + { + retCode = SHFileOperationW(&nFileOp); + HeapFree(GetProcessHeap(), 0, ForFree); /* we can not use wString, it was changed */ + break; + } + else + { + wString = ForFree = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); + if (ForFree) continue; + retCode = ERROR_OUTOFMEMORY; + nFileOp.fAnyOperationsAborted = TRUE; + SetLastError(retCode); + return retCode; + } + } + + lpFileOp->hNameMappings = nFileOp.hNameMappings; + lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted; + return retCode; +} + +static const char * debug_shfileops_flags( DWORD fFlags ) +{ + return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s", + fFlags & FOF_MULTIDESTFILES ? "FOF_MULTIDESTFILES " : "", + fFlags & FOF_CONFIRMMOUSE ? "FOF_CONFIRMMOUSE " : "", + fFlags & FOF_SILENT ? "FOF_SILENT " : "", + fFlags & FOF_RENAMEONCOLLISION ? "FOF_RENAMEONCOLLISION " : "", + fFlags & FOF_NOCONFIRMATION ? "FOF_NOCONFIRMATION " : "", + fFlags & FOF_WANTMAPPINGHANDLE ? "FOF_WANTMAPPINGHANDLE " : "", + fFlags & FOF_ALLOWUNDO ? "FOF_ALLOWUNDO " : "", + fFlags & FOF_FILESONLY ? "FOF_FILESONLY " : "", + fFlags & FOF_SIMPLEPROGRESS ? "FOF_SIMPLEPROGRESS " : "", + fFlags & FOF_NOCONFIRMMKDIR ? "FOF_NOCONFIRMMKDIR " : "", + fFlags & FOF_NOERRORUI ? "FOF_NOERRORUI " : "", + fFlags & FOF_NOCOPYSECURITYATTRIBS ? "FOF_NOCOPYSECURITYATTRIBS" : "", + fFlags & 0xf000 ? "MORE-UNKNOWN-Flags" : ""); +} + +static const char * debug_shfileops_action( DWORD op ) +{ + LPCSTR cFO_Name [] = {"FO_????","FO_MOVE","FO_COPY","FO_DELETE","FO_RENAME"}; + return wine_dbg_sprintf("%s", cFO_Name[ op ]); +} + +#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026 +#define HIGH_ADR (LPWSTR)0xffffffff + +/************************************************************************* + * SHFileOperationW [SHELL32.@] + * + * See SHFileOperationA + */ +int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp) +{ + SHFILEOPSTRUCTW nFileOp = *(lpFileOp); + + LPCWSTR pNextFrom = nFileOp.pFrom; + LPCWSTR pNextTo = nFileOp.pTo; + LPCWSTR pFrom = pNextFrom; + LPCWSTR pTo = NULL; + HANDLE hFind = INVALID_HANDLE_VALUE; + WIN32_FIND_DATAW wfd; + LPWSTR pTempFrom = NULL; + LPWSTR pTempTo = NULL; + LPWSTR pFromFile; + LPWSTR pToFile = NULL; + LPWSTR lpFileName; + int retCode = 0; + DWORD ToAttr; + DWORD ToPathAttr; + DWORD FromPathAttr; + FILEOP_FLAGS OFl = ((FILEOP_FLAGS)lpFileOp->fFlags & 0xfff); + + BOOL b_Multi = (nFileOp.fFlags & FOF_MULTIDESTFILES); + + BOOL b_MultiTo = (FO_DELETE != (lpFileOp->wFunc & FO_MASK)); + BOOL b_MultiPaired = (!b_MultiTo); + BOOL b_MultiFrom = FALSE; + BOOL not_overwrite; + BOOL ask_overwrite; + BOOL b_SameRoot; + BOOL b_SameTailName; + BOOL b_ToInvalidTail = FALSE; + BOOL b_ToValid; /* for W98-Bug for FO_MOVE with source and target in same rootdrive */ + BOOL b_Mask; + BOOL b_ToTailSlash = FALSE; + + long FuncSwitch = (nFileOp.wFunc & FO_MASK); + long level= nFileOp.wFunc>>4; + + /* default no error */ + nFileOp.fAnyOperationsAborted = FALSE; + + if ((FuncSwitch < FO_MOVE) || (FuncSwitch > FO_RENAME)) + goto shfileop_end; /* no valid FunctionCode */ + + if (level == 0) + TRACE("%s: flags (0x%04x) : %s\n", + debug_shfileops_action(FuncSwitch), nFileOp.fFlags, + debug_shfileops_flags(nFileOp.fFlags) ); + + /* establish when pTo is interpreted as the name of the destination file + * or the directory where the Fromfile should be copied to. + * This depends on: + * (1) pTo points to the name of an existing directory; + * (2) the flag FOF_MULTIDESTFILES is present; + * (3) whether pFrom point to multiple filenames. + * + * Some experiments: + * + * destisdir 1 1 1 1 0 0 0 0 + * FOF_MULTIDESTFILES 1 1 0 0 1 1 0 0 + * multiple from filenames 1 0 1 0 1 0 1 0 + * --------------- + * copy files to dir 1 0 1 1 0 0 1 0 + * create dir 0 0 0 0 0 0 1 0 + */ + + /* + * Summary of flags: + * + * implemented flags: + * FOF_MULTIDESTFILES, FOF_NOCONFIRMATION, FOF_FILESONLY + * + * unimplememented and ignored flags: + * FOF_CONFIRMMOUSE, FOF_SILENT, FOF_NOCONFIRMMKDIR, + * FOF_SIMPLEPROGRESS, FOF_NOCOPYSECURITYATTRIBS + * + * partially implemented, breaks if file exists: + * FOF_RENAMEONCOLLISION + * + * unimplemented and break if any other flag set: + * FOF_ALLOWUNDO, FOF_WANTMAPPINGHANDLE + */ + + TRACE("%s level=%ld nFileOp.fFlags=0x%x\n", + debug_shfileops_action(FuncSwitch), level, lpFileOp->fFlags); + + /* OFl &= (-1 - (FOF_MULTIDESTFILES | FOF_FILESONLY)); */ + /* OFl ^= (FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR); */ + OFl &= (~(FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | FOF_FILESONLY)); /* implemented */ + OFl ^= (FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS); /* ignored, if one */ + OFl &= (~FOF_SIMPLEPROGRESS); /* ignored, only with FOF_SILENT */ + if (OFl) + { + if (OFl & (~(FOF_CONFIRMMOUSE | FOF_SILENT | FOF_RENAMEONCOLLISION | + FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS))) + { + TRACE("%s level=%ld lpFileOp->fFlags=0x%x not implemented, Aborted=TRUE, stub\n", + debug_shfileops_action(FuncSwitch), level, OFl); + retCode = 0x403; /* 1027, we need an extension to shlfileop */ + goto shfileop_end; + } + else + { + TRACE("%s level=%ld lpFileOp->fFlags=0x%x not fully implemented, stub\n", + debug_shfileops_action(FuncSwitch), level, OFl); + } + } + + if ((pNextFrom) && (!(b_MultiTo) || (pNextTo))) + { + nFileOp.pFrom = pTempFrom = HeapAlloc(GetProcessHeap(), 0, ((1 + 2 * (b_MultiTo)) * MAX_PATH + 6) * sizeof(WCHAR)); + if (!pTempFrom) + { + retCode = ERROR_OUTOFMEMORY; + SetLastError(retCode); + goto shfileop_end; + } + if (b_MultiTo) + pTempTo = &pTempFrom[MAX_PATH + 4]; + nFileOp.pTo = pTempTo; + ask_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) && !(nFileOp.fFlags & FOF_RENAMEONCOLLISION)); + not_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) || (nFileOp.fFlags & FOF_RENAMEONCOLLISION)); + } + else + { + retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; + goto shfileop_end; + } + /* need break at error before change sourcepointer */ + while(!nFileOp.fAnyOperationsAborted && (pNextFrom[0])) + { + nFileOp.wFunc = ((level + 1) << 4) + FuncSwitch; + nFileOp.fFlags = lpFileOp->fFlags; + + if (b_MultiTo) + { + pTo = pNextTo; + pNextTo = &pNextTo[lstrlenW(pTo)+1]; + b_MultiTo = (b_Multi && pNextTo[0]); + } + + pFrom = pNextFrom; + pNextFrom = &pNextFrom[lstrlenW(pNextFrom)+1]; + if (!b_MultiFrom && !b_MultiTo) + b_MultiFrom = (pNextFrom[0]); + + pFromFile = SHFileStrCpyCatW(pTempFrom, pFrom, NULL); + + if (pTo) + { + pToFile = SHFileStrCpyCatW(pTempTo, pTo, NULL); + } + if (!b_MultiPaired) + { + b_MultiPaired = + SHELL_FileNamesMatch(lpFileOp->pFrom, lpFileOp->pTo, (!b_Multi || b_MultiFrom)); + } + if (!(b_MultiPaired) || !(pFromFile) || !(pFromFile[1]) || ((pTo) && !(pToFile))) + { + retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; + goto shfileop_end; + } + if (pTo) + { + b_ToTailSlash = (!pToFile[1]); + if (b_ToTailSlash) + { + pToFile[0] = '\0'; + if (StrChrW(pTempTo,'\\')) + { + pToFile = SHFileStrCpyCatW(pTempTo, NULL, NULL); + } + } + b_ToInvalidTail = (NULL != StrPBrkW(&pToFile[1], wWildcardChars)); + } + + /* for all */ + b_Mask = (NULL != StrPBrkW(&pFromFile[1], wWildcardChars)); + if (FO_RENAME == FuncSwitch) + { + /* temporary only for FO_RENAME */ + if (b_MultiTo || b_MultiFrom || (b_Mask && !b_ToInvalidTail)) + { +#ifndef W98_FO_FUNCTION + retCode = ERROR_GEN_FAILURE; /* W2K ERROR_GEN_FAILURE, W98 returns no error */ +#endif + goto shfileop_end; + } + } + + hFind = FindFirstFileW(pFrom, &wfd); + if (INVALID_HANDLE_VALUE == hFind) + { + if ((FO_DELETE == FuncSwitch) && (b_Mask)) + { + pFromFile[0] = '\0'; + FromPathAttr = GetFileAttributesW(pTempFrom); + pFromFile[0] = '\\'; + if (IsAttribDir(FromPathAttr)) + { + /* FO_DELETE with mask and without found is valid */ + goto shfileop_end; + } + } + /* root (without mask) is also not allowed as source, tested in W98 */ + retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND; + goto shfileop_end; + } + + /* for all */ + + /* ??? b_Mask = (!SHFileStrICmpA(&pFromFile[1], &wfd.cFileName[0], HIGH_ADR, HIGH_ADR)); */ + if (!pTo) /* FO_DELETE */ + { + do + { + lpFileName = wfd.cAlternateFileName; + if (!lpFileName[0]) + lpFileName = wfd.cFileName; + if (IsDotDir(lpFileName) || + ((b_Mask) && IsAttribDir(wfd.dwFileAttributes) && (nFileOp.fFlags & FOF_FILESONLY))) + continue; + SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL); + /* TODO: Check the SHELL_DeleteFileOrDirectoryW() function in shell32.dll */ + if (IsAttribFile(wfd.dwFileAttributes)) + { + if(SHNotifyDeleteFileW(pTempFrom) != ERROR_SUCCESS) + { + nFileOp.fAnyOperationsAborted = TRUE; + retCode = 0x78; /* value unknown */ + } + } + else + { + if(!SHELL_DeleteDirectoryW(pTempFrom, (!(nFileOp.fFlags & FOF_NOCONFIRMATION)))) + { + nFileOp.fAnyOperationsAborted = TRUE; + retCode = 0x79; /* value unknown */ + } + } + } while (!nFileOp.fAnyOperationsAborted && FindNextFileW(hFind, &wfd)); + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + if (nFileOp.fAnyOperationsAborted) + goto shfileop_end; + continue; + } /* FO_DELETE ends, pTo must be always valid from here */ + + b_SameRoot = (toupperW(pTempFrom[0]) == toupperW(pTempTo[0])); + b_SameTailName = SHFileStrICmpW(pToFile, pFromFile, NULL, NULL); + + ToPathAttr = ToAttr = GetFileAttributesW(pTempTo); + if (!b_Mask && (ToAttr == INVALID_FILE_ATTRIBUTES) && (pToFile)) + { + pToFile[0] = '\0'; + ToPathAttr = GetFileAttributesW(pTempTo); + pToFile[0] = '\\'; + } + + if (FO_RENAME == FuncSwitch) + { + if (!b_SameRoot || b_Mask /* FO_RENAME works not with Mask */ + || !SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, NULL) + || (SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, HIGH_ADR) && !b_ToTailSlash)) + { + retCode = 0x73; + goto shfileop_end; + } + if (b_ToInvalidTail) + { + retCode=0x2; + goto shfileop_end; + } + if (INVALID_FILE_ATTRIBUTES == ToPathAttr) + { + retCode = 0x75; + goto shfileop_end; + } + if (IsAttribDir(wfd.dwFileAttributes) && IsAttribDir(ToAttr)) + { + retCode = (b_ToTailSlash) ? 0xb7 : 0x7b; + goto shfileop_end; + } + /* we use SHNotifyMoveFile() instead MoveFileW */ + if (SHNotifyMoveFileW(pTempFrom, pTempTo) != ERROR_SUCCESS) + { + /* we need still the value for the returncode, we use the mostly assumed */ + retCode = 0xb7; + goto shfileop_end; + } + goto shfileop_end; + } + + /* W98 Bug with FO_MOVE different from FO_COPY, better the same as FO_COPY */ + b_ToValid = ((b_SameTailName && b_SameRoot && (FO_COPY == FuncSwitch)) || + (b_SameTailName && !b_SameRoot) || (b_ToInvalidTail)); + + /* handle mask in source */ + if (b_Mask) + { + if (!IsAttribDir(ToAttr)) + { + retCode = (b_ToInvalidTail &&/* b_SameTailName &&*/ (FO_MOVE == FuncSwitch)) \ + ? 0x2 : 0x75; + goto shfileop_end; + } + pToFile = SHFileStrCpyCatW(pTempTo, NULL, wBackslash); + nFileOp.fFlags = (nFileOp.fFlags | FOF_MULTIDESTFILES); + do + { + lpFileName = wfd.cAlternateFileName; + if (!lpFileName[0]) + lpFileName = wfd.cFileName; + if (IsDotDir(lpFileName) || + (IsAttribDir(wfd.dwFileAttributes) && (nFileOp.fFlags & FOF_FILESONLY))) + continue; /* next name in pTempFrom(dir) */ + SHFileStrCpyCatW(&pToFile[1], lpFileName, NULL); + SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL); + retCode = SHFileOperationW (&nFileOp); + } while(!nFileOp.fAnyOperationsAborted && FindNextFileW(hFind, &wfd)); + } + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + /* FO_COPY/FO_MOVE with mask, FO_DELETE and FO_RENAME are solved */ + if (b_Mask) + continue; + + /* only FO_COPY/FO_MOVE without mask, all others are (must be) solved */ + if (IsAttribDir(wfd.dwFileAttributes) && (ToAttr == INVALID_FILE_ATTRIBUTES)) + { + if (pToFile) + { + pToFile[0] = '\0'; + ToPathAttr = GetFileAttributesW(pTempTo); + if ((ToPathAttr == INVALID_FILE_ATTRIBUTES) && b_ToValid) + { + /* create dir must be here, sample target D:\y\ *.* create with RC=10003 */ + if (SHNotifyCreateDirectoryW(pTempTo, NULL)) + { + retCode = 0x73;/* value unknown */ + goto shfileop_end; + } + ToPathAttr = GetFileAttributesW(pTempTo); + } + pToFile[0] = '\\'; + if (b_ToInvalidTail) + { + retCode = 0x10003; + goto shfileop_end; + } + } + } + + /* trailing BackSlash is ever removed and pToFile points to BackSlash before */ + if (!b_MultiTo && (b_MultiFrom || (!(b_Multi) && IsAttribDir(ToAttr)))) + { + if ((FO_MOVE == FuncSwitch) && IsAttribDir(ToAttr) && IsAttribDir(wfd.dwFileAttributes)) + { + if (b_Multi) + { + retCode = 0x73; /* !b_Multi = 0x8 ?? */ + goto shfileop_end; + } + } + pToFile = SHFileStrCpyCatW(pTempTo, NULL, wfd.cFileName); + ToAttr = GetFileAttributesW(pTempTo); + } + + if (IsAttribDir(ToAttr)) + { + if (IsAttribFile(wfd.dwFileAttributes)) + { + retCode = (FO_COPY == FuncSwitch) ? 0x75 : 0xb7; + goto shfileop_end; + } + } + else + { + pToFile[0] = '\0'; + ToPathAttr = GetFileAttributesW(pTempTo); + pToFile[0] = '\\'; + if (IsAttribFile(ToPathAttr)) + { + /* error, is this tested ? */ + retCode = 0x777402; + goto shfileop_end; + } + } + + /* singlesource + no mask */ + if (INVALID_FILE_ATTRIBUTES == (ToAttr & ToPathAttr)) + { + /* Target-dir does not exist, and cannot be created */ + retCode=0x75; + goto shfileop_end; + } + + switch(FuncSwitch) + { + case FO_MOVE: + pToFile = NULL; + if ((ToAttr == INVALID_FILE_ATTRIBUTES) && SHFileStrICmpW(pTempFrom, pTempTo, pFromFile, NULL)) + { + nFileOp.wFunc = ((level+1)<<4) + FO_RENAME; + } + else + { + if (b_SameRoot && IsAttribDir(ToAttr) && IsAttribDir(wfd.dwFileAttributes)) + { + /* we need pToFile for FO_DELETE after FO_MOVE contence */ + pToFile = SHFileStrCpyCatW(pTempFrom, NULL, wWildcardFile); + } + else + { + nFileOp.wFunc = ((level+1)<<4) + FO_COPY; + } + } + retCode = SHFileOperationW(&nFileOp); + if (pToFile) + ((DWORD*)pToFile)[0] = '\0'; + if (!nFileOp.fAnyOperationsAborted && (FO_RENAME != (nFileOp.wFunc & 0xf))) + { + nFileOp.wFunc = ((level+1)<<4) + FO_DELETE; + retCode = SHFileOperationW(&nFileOp); + } + continue; + case FO_COPY: + if (SHFileStrICmpW(pTempFrom, pTempTo, NULL, NULL)) + { /* target is the same as source ? */ + /* we still need the value for the returncode, we assume 0x71 */ + retCode = 0x71; + goto shfileop_end; + } + if (IsAttribDir((ToAttr & wfd.dwFileAttributes))) + { + if (IsAttribDir(ToAttr) || !SHNotifyCreateDirectoryW(pTempTo, NULL)) + { + /* ??? nFileOp.fFlags = (nFileOp.fFlags | FOF_MULTIDESTFILES); */ + SHFileStrCpyCatW(pTempFrom, NULL, wWildcardFile); + retCode = SHFileOperationW(&nFileOp); + } + else + { + retCode = 0x750;/* value unknown */ + goto shfileop_end; + } + } + else + { + if (!(ask_overwrite && SHELL_ConfirmDialogW(ASK_OVERWRITE_FILE, pTempTo)) + && (not_overwrite)) + { + /* we still need the value for the returncode, we use the mostly assumed */ + retCode = 0x73; + goto shfileop_end; + } + if (SHNotifyCopyFileW(pTempFrom, pTempTo, TRUE) != ERROR_SUCCESS) + { + retCode = 0x77; /* value unknown */ + goto shfileop_end; + } + } + } + } + +shfileop_end: + if (hFind != INVALID_HANDLE_VALUE) + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + HeapFree(GetProcessHeap(), 0, pTempFrom); + if (retCode) + nFileOp.fAnyOperationsAborted = TRUE; + TRACE("%s level=%ld AnyOpsAborted=%s ret=0x%x, with %s %s%s\n", + debug_shfileops_action(FuncSwitch), level, + nFileOp.fAnyOperationsAborted ? "TRUE":"FALSE", + retCode, debugstr_w(pFrom), pTo ? "-> ":"", debugstr_w(pTo)); + + lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted; + return retCode; +} + +#define SHDSA_GetItemCount(hdsa) (*(int*)(hdsa)) + +/************************************************************************* + * SHFreeNameMappings [shell32.246] + * + * Free the mapping handle returned by SHFileoperation if FOF_WANTSMAPPINGHANDLE + * was specified. + * + * PARAMS + * hNameMapping [I] handle to the name mappings used during renaming of files + * + */ +void WINAPI SHFreeNameMappings(HANDLE hNameMapping) +{ + if (hNameMapping) + { + int i = SHDSA_GetItemCount((HDSA)hNameMapping) - 1; + + for (; i>= 0; i--) + { + LPSHNAMEMAPPINGW lp = DSA_GetItemPtr((HDSA)hNameMapping, i); + + SHFree(lp->pszOldPath); + SHFree(lp->pszNewPath); + } + DSA_Destroy((HDSA)hNameMapping); + } +} + +/************************************************************************* + * SheGetDirW [SHELL32.281] + * + */ +HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v) +{ FIXME("%p %p stub\n",u,v); + return 0; +} + +/************************************************************************* + * SheChangeDirW [SHELL32.274] + * + */ +HRESULT WINAPI SheChangeDirW(LPWSTR u) +{ FIXME("(%s),stub\n",debugstr_w(u)); + return 0; +} + +/************************************************************************* + * IsNetDrive [SHELL32.66] + */ +BOOL WINAPI IsNetDrive(DWORD drive) +{ + char root[4]; + strcpy(root, "A:\\"); + root[0] += (char)drive; + return (GetDriveTypeA(root) == DRIVE_REMOTE); +} + + +/************************************************************************* + * RealDriveType [SHELL32.524] + */ +INT WINAPI RealDriveType(INT drive, BOOL bQueryNet) +{ + char root[] = "A:\\"; + root[0] += (char)drive; + return GetDriveTypeA(root); +} diff --git a/reactos/lib/shell32/shlfolder.c b/reactos/lib/shell32/shlfolder.c index 3394155fdbb..1f5841906d6 100644 --- a/reactos/lib/shell32/shlfolder.c +++ b/reactos/lib/shell32/shlfolder.c @@ -1,516 +1,513 @@ - -/* - * Shell Folder stuff - * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied - * - * IShellFolder2 and related interfaces - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" - -#include "ole2.h" -#include "shlguid.h" - -#include "pidl.h" -#include "undocshell.h" -#include "shell32_main.h" -#include "shresdef.h" -#include "shlwapi.h" -#include "shellfolder.h" -#include "wine/debug.h" -#include "debughlp.h" -#include "shfldr.h" - -WINE_DEFAULT_DEBUG_CHANNEL (shell); - -/*************************************************************************** - * debughelper: print out the return address - * helps especially to track down unbalanced AddRef/Release - */ -#define MEM_DEBUG 0 - -#if MEM_DEBUG -#define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 )); -#else -#define _CALL_TRACE -#endif - -static const WCHAR wszDotShellClassInfo[] = {'.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0}; - -/*************************************************************************** - * SHELL32_GetCustomFolderAttribute (internal function) - * - * Gets a value from the folder's desktop.ini file, if one exists. - * - * PARAMETERS - * pidl [I] Folder containing the desktop.ini file. - * pwszHeading [I] Heading in .ini file. - * pwszAttribute [I] Attribute in .ini file. - * pwszValue [O] Buffer to store value into. - * cchValue [I] Size in characters including NULL of buffer pointed to - * by pwszValue. - * - * RETURNS - * TRUE if returned non-NULL value. - * FALSE otherwise. - */ -BOOL SHELL32_GetCustomFolderAttribute( - LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, - LPWSTR pwszValue, DWORD cchValue) -{ -#if 0 /* Hack around not having system attribute on non-Windows file systems */ - DWORD dwAttrib = _ILGetFileAttributes(pidl, NULL, 0); -#else - DWORD dwAttrib = FILE_ATTRIBUTE_SYSTEM; -#endif - if (dwAttrib & FILE_ATTRIBUTE_SYSTEM) - { - DWORD ret; - WCHAR wszDesktopIniPath[MAX_PATH]; - static const WCHAR wszDesktopIni[] = - {'d','e','s','k','t','o','p','.','i','n','i',0}; - static const WCHAR wszDefault[] = - {0}; - if (!SHGetPathFromIDListW(pidl, wszDesktopIniPath)) - return FALSE; - PathAppendW(wszDesktopIniPath, wszDesktopIni); - ret = GetPrivateProfileStringW(pwszHeading, pwszAttribute, - wszDefault, pwszValue, cchValue, wszDesktopIniPath); - if (!ret) return FALSE; - return TRUE; - } - return FALSE; -} - - -/*************************************************************************** - * GetNextElement (internal function) - * - * gets a part of a string till the first backslash - * - * PARAMETERS - * pszNext [IN] string to get the element from - * pszOut [IN] pointer to buffer whitch receives string - * dwOut [IN] length of pszOut - * - * RETURNS - * LPSTR pointer to first, not yet parsed char - */ - -LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut) -{ - LPCWSTR pszTail = pszNext; - DWORD dwCopy; - - TRACE ("(%s %p 0x%08lx)\n", debugstr_w (pszNext), pszOut, dwOut); - - *pszOut = 0x0000; - - if (!pszNext || !*pszNext) - return NULL; - - while (*pszTail && (*pszTail != (WCHAR) '\\')) - pszTail++; - - dwCopy = (const WCHAR *) pszTail - (const WCHAR *) pszNext + 1; - lstrcpynW (pszOut, pszNext, (dwOut < dwCopy) ? dwOut : dwCopy); - - if (*pszTail) - pszTail++; - else - pszTail = NULL; - - TRACE ("--(%s %s 0x%08lx %p)\n", debugstr_w (pszNext), debugstr_w (pszOut), dwOut, pszTail); - return pszTail; -} - -HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, - LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes) -{ - HRESULT hr = E_INVALIDARG; - LPITEMIDLIST pidlOut = NULL, - pidlTemp = NULL; - IShellFolder *psfChild; - - TRACE ("(%p, %p, %p, %s)\n", psf, pbc, pidlInOut ? *pidlInOut : NULL, debugstr_w (szNext)); - - /* get the shellfolder for the child pidl and let it analyse further */ - hr = IShellFolder_BindToObject (psf, *pidlInOut, pbc, &IID_IShellFolder, (LPVOID *) & psfChild); - - if (SUCCEEDED(hr)) { - hr = IShellFolder_ParseDisplayName (psfChild, hwndOwner, pbc, szNext, pEaten, &pidlOut, pdwAttributes); - IShellFolder_Release (psfChild); - - if (SUCCEEDED(hr)) { - pidlTemp = ILCombine (*pidlInOut, pidlOut); - - if (!pidlTemp) - hr = E_OUTOFMEMORY; - } - - if (pidlOut) - ILFree (pidlOut); - } - - ILFree (*pidlInOut); - *pidlInOut = pidlTemp; - - TRACE ("-- pidl=%p ret=0x%08lx\n", pidlInOut ? *pidlInOut : NULL, hr); - return hr; -} - -/*********************************************************************** - * SHELL32_CoCreateInitSF - * - * Creates a shell folder and initializes it with a pidl and a root folder - * via IPersistFolder3 or IPersistFolder. - * - * NOTES - * pathRoot can be NULL for Folders beeing a drive. - * In this case the absolute path is build from pidlChild (eg. C:) - */ -HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCSTR pathRoot, - LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID riid, LPVOID * ppvOut) -{ - HRESULT hr; - - TRACE ("%p %s %p\n", pidlRoot, pathRoot, pidlChild); - - if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, clsid, NULL, riid, ppvOut)))) { - LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); - IPersistFolder *pPF; - IPersistFolder3 *ppf; - - if (SUCCEEDED (IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder3, (LPVOID *) & ppf))) { - PERSIST_FOLDER_TARGET_INFO ppfti; - char szDestPath[MAX_PATH]; - - ZeroMemory (&ppfti, sizeof (ppfti)); - - /* build path */ - if (pathRoot) { - lstrcpyA (szDestPath, pathRoot); - PathAddBackslashA(szDestPath); /* FIXME: why have drives a backslash here ? */ - } else { - szDestPath[0] = '\0'; - } - - if (pidlChild) { - LPSTR pszChild = _ILGetTextPointer(pidlChild); - - if (pszChild) - lstrcatA (szDestPath, pszChild); - else - hr = E_INVALIDARG; - } - - /* fill the PERSIST_FOLDER_TARGET_INFO */ - ppfti.dwAttributes = -1; - ppfti.csidl = -1; - MultiByteToWideChar (CP_ACP, 0, szDestPath, -1, ppfti.szTargetParsingName, MAX_PATH); - - IPersistFolder3_InitializeEx (ppf, NULL, pidlAbsolute, &ppfti); - IPersistFolder3_Release (ppf); - } - else if (SUCCEEDED ((hr = IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder, (LPVOID *) & pPF)))) { - IPersistFolder_Initialize (pPF, pidlAbsolute); - IPersistFolder_Release (pPF); - } - ILFree (pidlAbsolute); - } - TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr); - return hr; -} - -/*********************************************************************** - * SHELL32_BindToChild - * - * Common code for IShellFolder_BindToObject. - * Creates a shell folder by binding to a root pidl. - */ -HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, - LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) -{ - GUID const *clsid; - IShellFolder *pSF; - HRESULT hr; - LPITEMIDLIST pidlChild; - - if (!pidlRoot || !ppvOut) - return E_INVALIDARG; - - *ppvOut = NULL; - - pidlChild = ILCloneFirst (pidlComplete); - - if ((clsid = _ILGetGUIDPointer (pidlChild))) { - /* virtual folder */ - hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, &IID_IShellFolder, (LPVOID *) & pSF); - } else { - /* file system folder */ - CLSID clsidFolder = CLSID_ShellFSFolder; - static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; - WCHAR wszCLSIDValue[CHARS_IN_GUID]; - LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); - /* see if folder CLSID should be overridden by desktop.ini file */ - if (SHELL32_GetCustomFolderAttribute (pidlAbsolute, - wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) - CLSIDFromString (wszCLSIDValue, &clsidFolder); - ILFree (pidlAbsolute); - hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, - &clsidFolder, &IID_IShellFolder, (LPVOID *)&pSF); - } - ILFree (pidlChild); - - if (SUCCEEDED (hr)) { - if (_ILIsPidlSimple (pidlComplete)) { - /* no sub folders */ - hr = IShellFolder_QueryInterface (pSF, riid, ppvOut); - } else { - /* go deeper */ - hr = IShellFolder_BindToObject (pSF, ILGetNext (pidlComplete), NULL, riid, ppvOut); - } - IShellFolder_Release (pSF); - } - - TRACE ("-- returning (%p) %08lx\n", *ppvOut, hr); - - return hr; -} - -/*********************************************************************** - * SHELL32_GetDisplayNameOfChild - * - * Retrives the display name of a child object of a shellfolder. - * - * For a pidl eg. [subpidl1][subpidl2][subpidl3]: - * - it binds to the child shellfolder [subpidl1] - * - asks it for the displayname of [subpidl2][subpidl3] - * - * Is possible the pidl is a simple pidl. In this case it asks the - * subfolder for the displayname of a empty pidl. The subfolder - * returns the own displayname eg. "::{guid}". This is used for - * virtual folders with the registry key WantsFORPARSING set. - */ -HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, - LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, DWORD dwOutLen) -{ - LPITEMIDLIST pidlFirst; - HRESULT hr = E_INVALIDARG; - - TRACE ("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n", psf, pidl, dwFlags, szOut, dwOutLen); - pdump (pidl); - - pidlFirst = ILCloneFirst (pidl); - if (pidlFirst) { - IShellFolder2 *psfChild; - - hr = IShellFolder_BindToObject (psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID *) & psfChild); - if (SUCCEEDED (hr)) { - STRRET strTemp; - LPITEMIDLIST pidlNext = ILGetNext (pidl); - - hr = IShellFolder_GetDisplayNameOf (psfChild, pidlNext, dwFlags, &strTemp); - if (SUCCEEDED (hr)) { - hr = StrRetToStrNA (szOut, dwOutLen, &strTemp, pidlNext); - } - IShellFolder_Release (psfChild); - } - ILFree (pidlFirst); - } else - hr = E_OUTOFMEMORY; - - TRACE ("-- ret=0x%08lx %s\n", hr, szOut); - - return hr; -} - -/*********************************************************************** - * SHELL32_GetItemAttributes - * - * NOTES - * observerd values: - * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER - * file: 0x40000177 FILESYSTEM - * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR - * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR - * (seems to be default for shell extensions if no registry entry exists) - * - * win2k: - * folder: 0xF0400177 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER - * file: 0x40400177 FILESYSTEM | CANMONIKER - * drive 0xF0400154 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER | CANRENAME (LABEL) - * - * This function does not set flags!! It only resets flags when necessary. - */ -HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) -{ - GUID const *clsid; - DWORD dwAttributes; - DWORD dwSupportedAttr=SFGAO_CANCOPY | /*0x00000001 */ - SFGAO_CANMOVE | /*0x00000002 */ - SFGAO_CANLINK | /*0x00000004 */ - SFGAO_CANRENAME | /*0x00000010 */ - SFGAO_CANDELETE | /*0x00000020 */ - SFGAO_HASPROPSHEET | /*0x00000040 */ - SFGAO_DROPTARGET | /*0x00000100 */ - SFGAO_LINK | /*0x00010000 */ - SFGAO_READONLY | /*0x00040000 */ - SFGAO_HIDDEN | /*0x00080000 */ - SFGAO_FILESYSANCESTOR | /*0x10000000 */ - SFGAO_FOLDER | /*0x20000000 */ - SFGAO_FILESYSTEM | /*0x40000000 */ - SFGAO_HASSUBFOLDER; /*0x80000000 */ - - TRACE ("0x%08lx\n", *pdwAttributes); - - if (*pdwAttributes & ~dwSupportedAttr) - { - WARN ("attributes 0x%08lx not implemented\n", (*pdwAttributes & ~dwSupportedAttr)); - *pdwAttributes &= dwSupportedAttr; - } - - if (_ILIsDrive (pidl)) { - *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK; - } else if ((clsid = _ILGetGUIDPointer (pidl))) { - if (HCR_GetFolderAttributes (clsid, &dwAttributes)) { - *pdwAttributes &= dwAttributes; - } else { - *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK; - } - } else if (_ILGetDataPointer (pidl)) { - dwAttributes = _ILGetFileAttributes (pidl, NULL, 0); - *pdwAttributes &= ~SFGAO_FILESYSANCESTOR; - - if ((SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) - *pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER); - - if ((SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN)) - *pdwAttributes &= ~SFGAO_HIDDEN; - - if ((SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY)) - *pdwAttributes &= ~SFGAO_READONLY; - - if (SFGAO_LINK & *pdwAttributes) { - char ext[MAX_PATH]; - - if (!_ILGetExtension(pidl, ext, MAX_PATH) || strcasecmp(ext, "lnk")) - *pdwAttributes &= ~SFGAO_LINK; - } - } else { - *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK; - } - TRACE ("-- 0x%08lx\n", *pdwAttributes); - return S_OK; -} - -/*********************************************************************** - * SHELL32_CompareIDs - */ -HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) -{ - int type1, - type2; - char szTemp1[MAX_PATH]; - char szTemp2[MAX_PATH]; - HRESULT nReturn; - LPITEMIDLIST firstpidl, - nextpidl1, - nextpidl2; - IShellFolder *psf; - - /* test for empty pidls */ - BOOL isEmpty1 = _ILIsDesktop (pidl1); - BOOL isEmpty2 = _ILIsDesktop (pidl2); - - if (isEmpty1 && isEmpty2) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 0 ); - if (isEmpty1) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); - if (isEmpty2) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); - - /* test for different types. Sort order is the PT_* constant */ - type1 = _ILGetDataPointer (pidl1)->type; - type2 = _ILGetDataPointer (pidl2)->type; - if (type1 < type2) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); - else if (type1 > type2) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); - - /* test for name of pidl */ - _ILSimpleGetText (pidl1, szTemp1, MAX_PATH); - _ILSimpleGetText (pidl2, szTemp2, MAX_PATH); - nReturn = strcasecmp (szTemp1, szTemp2); - if (nReturn < 0) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); - else if (nReturn > 0) - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); - - /* test of complex pidls */ - firstpidl = ILCloneFirst (pidl1); - nextpidl1 = ILGetNext (pidl1); - nextpidl2 = ILGetNext (pidl2); - - /* optimizing: test special cases and bind not deeper */ - /* the deeper shellfolder would do the same */ - isEmpty1 = _ILIsDesktop (nextpidl1); - isEmpty2 = _ILIsDesktop (nextpidl2); - - if (isEmpty1 && isEmpty2) { - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 0 ); - } else if (isEmpty1) { - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); - } else if (isEmpty2) { - return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); - /* optimizing end */ - } else if (SUCCEEDED (IShellFolder_BindToObject (iface, firstpidl, NULL, &IID_IShellFolder, (LPVOID *) & psf))) { - nReturn = IShellFolder_CompareIDs (psf, lParam, nextpidl1, nextpidl2); - IShellFolder_Release (psf); - } - ILFree (firstpidl); - return nReturn; -} - -/*********************************************************************** - * SHCreateLinks - * - * Undocumented. - */ -HRESULT WINAPI SHCreateLinks( HWND hWnd, LPCSTR lpszDir, LPDATAOBJECT lpDataObject, - UINT uFlags, LPITEMIDLIST *lppidlLinks) -{ - FIXME("%p %s %p %08x %p\n",hWnd,lpszDir,lpDataObject,uFlags,lppidlLinks); - return E_NOTIMPL; -} + +/* + * Shell Folder stuff + * + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied + * + * IShellFolder2 and related interfaces + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#define COBJMACROS + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" + +#include "ole2.h" +#include "shlguid.h" + +#include "pidl.h" +#include "undocshell.h" +#include "shell32_main.h" +#include "shlwapi.h" +#include "wine/debug.h" +#include "shfldr.h" + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +/*************************************************************************** + * debughelper: print out the return address + * helps especially to track down unbalanced AddRef/Release + */ +#define MEM_DEBUG 0 + +#if MEM_DEBUG +#define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 )); +#else +#define _CALL_TRACE +#endif + +static const WCHAR wszDotShellClassInfo[] = {'.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0}; + +/*************************************************************************** + * SHELL32_GetCustomFolderAttribute (internal function) + * + * Gets a value from the folder's desktop.ini file, if one exists. + * + * PARAMETERS + * pidl [I] Folder containing the desktop.ini file. + * pwszHeading [I] Heading in .ini file. + * pwszAttribute [I] Attribute in .ini file. + * pwszValue [O] Buffer to store value into. + * cchValue [I] Size in characters including NULL of buffer pointed to + * by pwszValue. + * + * RETURNS + * TRUE if returned non-NULL value. + * FALSE otherwise. + */ +BOOL SHELL32_GetCustomFolderAttribute( + LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, + LPWSTR pwszValue, DWORD cchValue) +{ +#if 0 /* Hack around not having system attribute on non-Windows file systems */ + DWORD dwAttrib = _ILGetFileAttributes(pidl, NULL, 0); +#else + DWORD dwAttrib = FILE_ATTRIBUTE_SYSTEM; +#endif + if (dwAttrib & FILE_ATTRIBUTE_SYSTEM) + { + DWORD ret; + WCHAR wszDesktopIniPath[MAX_PATH]; + static const WCHAR wszDesktopIni[] = + {'d','e','s','k','t','o','p','.','i','n','i',0}; + static const WCHAR wszDefault[] = + {0}; + if (!SHGetPathFromIDListW(pidl, wszDesktopIniPath)) + return FALSE; + PathAppendW(wszDesktopIniPath, wszDesktopIni); + ret = GetPrivateProfileStringW(pwszHeading, pwszAttribute, + wszDefault, pwszValue, cchValue, wszDesktopIniPath); + if (!ret) return FALSE; + return TRUE; + } + return FALSE; +} + + +/*************************************************************************** + * GetNextElement (internal function) + * + * gets a part of a string till the first backslash + * + * PARAMETERS + * pszNext [IN] string to get the element from + * pszOut [IN] pointer to buffer whitch receives string + * dwOut [IN] length of pszOut + * + * RETURNS + * LPSTR pointer to first, not yet parsed char + */ + +LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut) +{ + LPCWSTR pszTail = pszNext; + DWORD dwCopy; + + TRACE ("(%s %p 0x%08lx)\n", debugstr_w (pszNext), pszOut, dwOut); + + *pszOut = 0x0000; + + if (!pszNext || !*pszNext) + return NULL; + + while (*pszTail && (*pszTail != (WCHAR) '\\')) + pszTail++; + + dwCopy = (const WCHAR *) pszTail - (const WCHAR *) pszNext + 1; + lstrcpynW (pszOut, pszNext, (dwOut < dwCopy) ? dwOut : dwCopy); + + if (*pszTail) + pszTail++; + else + pszTail = NULL; + + TRACE ("--(%s %s 0x%08lx %p)\n", debugstr_w (pszNext), debugstr_w (pszOut), dwOut, pszTail); + return pszTail; +} + +HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, + LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes) +{ + HRESULT hr = E_INVALIDARG; + LPITEMIDLIST pidlOut = NULL, + pidlTemp = NULL; + IShellFolder *psfChild; + + TRACE ("(%p, %p, %p, %s)\n", psf, pbc, pidlInOut ? *pidlInOut : NULL, debugstr_w (szNext)); + + /* get the shellfolder for the child pidl and let it analyse further */ + hr = IShellFolder_BindToObject (psf, *pidlInOut, pbc, &IID_IShellFolder, (LPVOID *) & psfChild); + + if (SUCCEEDED(hr)) { + hr = IShellFolder_ParseDisplayName (psfChild, hwndOwner, pbc, szNext, pEaten, &pidlOut, pdwAttributes); + IShellFolder_Release (psfChild); + + if (SUCCEEDED(hr)) { + pidlTemp = ILCombine (*pidlInOut, pidlOut); + + if (!pidlTemp) + hr = E_OUTOFMEMORY; + } + + if (pidlOut) + ILFree (pidlOut); + } + + ILFree (*pidlInOut); + *pidlInOut = pidlTemp; + + TRACE ("-- pidl=%p ret=0x%08lx\n", pidlInOut ? *pidlInOut : NULL, hr); + return hr; +} + +/*********************************************************************** + * SHELL32_CoCreateInitSF + * + * Creates a shell folder and initializes it with a pidl and a root folder + * via IPersistFolder3 or IPersistFolder. + * + * NOTES + * pathRoot can be NULL for Folders beeing a drive. + * In this case the absolute path is build from pidlChild (eg. C:) + */ +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCSTR pathRoot, + LPCITEMIDLIST pidlChild, REFCLSID clsid, REFIID riid, LPVOID * ppvOut) +{ + HRESULT hr; + + TRACE ("%p %s %p\n", pidlRoot, pathRoot, pidlChild); + + if (SUCCEEDED ((hr = SHCoCreateInstance (NULL, clsid, NULL, riid, ppvOut)))) { + LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); + IPersistFolder *pPF; + IPersistFolder3 *ppf; + + if (SUCCEEDED (IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder3, (LPVOID *) & ppf))) { + PERSIST_FOLDER_TARGET_INFO ppfti; + char szDestPath[MAX_PATH]; + + ZeroMemory (&ppfti, sizeof (ppfti)); + + /* build path */ + if (pathRoot) { + lstrcpyA (szDestPath, pathRoot); + PathAddBackslashA(szDestPath); /* FIXME: why have drives a backslash here ? */ + } else { + szDestPath[0] = '\0'; + } + + if (pidlChild) { + LPSTR pszChild = _ILGetTextPointer(pidlChild); + + if (pszChild) + lstrcatA (szDestPath, pszChild); + else + hr = E_INVALIDARG; + } + + /* fill the PERSIST_FOLDER_TARGET_INFO */ + ppfti.dwAttributes = -1; + ppfti.csidl = -1; + MultiByteToWideChar (CP_ACP, 0, szDestPath, -1, ppfti.szTargetParsingName, MAX_PATH); + + IPersistFolder3_InitializeEx (ppf, NULL, pidlAbsolute, &ppfti); + IPersistFolder3_Release (ppf); + } + else if (SUCCEEDED ((hr = IUnknown_QueryInterface ((IUnknown *) * ppvOut, &IID_IPersistFolder, (LPVOID *) & pPF)))) { + IPersistFolder_Initialize (pPF, pidlAbsolute); + IPersistFolder_Release (pPF); + } + ILFree (pidlAbsolute); + } + TRACE ("-- (%p) ret=0x%08lx\n", *ppvOut, hr); + return hr; +} + +/*********************************************************************** + * SHELL32_BindToChild + * + * Common code for IShellFolder_BindToObject. + * Creates a shell folder by binding to a root pidl. + */ +HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, + LPCSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) +{ + GUID const *clsid; + IShellFolder *pSF; + HRESULT hr; + LPITEMIDLIST pidlChild; + + if (!pidlRoot || !ppvOut) + return E_INVALIDARG; + + *ppvOut = NULL; + + pidlChild = ILCloneFirst (pidlComplete); + + if ((clsid = _ILGetGUIDPointer (pidlChild))) { + /* virtual folder */ + hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsid, &IID_IShellFolder, (LPVOID *) & pSF); + } else { + /* file system folder */ + CLSID clsidFolder = CLSID_ShellFSFolder; + static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; + WCHAR wszCLSIDValue[CHARS_IN_GUID]; + LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); + /* see if folder CLSID should be overridden by desktop.ini file */ + if (SHELL32_GetCustomFolderAttribute (pidlAbsolute, + wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) + CLSIDFromString (wszCLSIDValue, &clsidFolder); + ILFree (pidlAbsolute); + hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, + &clsidFolder, &IID_IShellFolder, (LPVOID *)&pSF); + } + ILFree (pidlChild); + + if (SUCCEEDED (hr)) { + if (_ILIsPidlSimple (pidlComplete)) { + /* no sub folders */ + hr = IShellFolder_QueryInterface (pSF, riid, ppvOut); + } else { + /* go deeper */ + hr = IShellFolder_BindToObject (pSF, ILGetNext (pidlComplete), NULL, riid, ppvOut); + } + IShellFolder_Release (pSF); + } + + TRACE ("-- returning (%p) %08lx\n", *ppvOut, hr); + + return hr; +} + +/*********************************************************************** + * SHELL32_GetDisplayNameOfChild + * + * Retrives the display name of a child object of a shellfolder. + * + * For a pidl eg. [subpidl1][subpidl2][subpidl3]: + * - it binds to the child shellfolder [subpidl1] + * - asks it for the displayname of [subpidl2][subpidl3] + * + * Is possible the pidl is a simple pidl. In this case it asks the + * subfolder for the displayname of a empty pidl. The subfolder + * returns the own displayname eg. "::{guid}". This is used for + * virtual folders with the registry key WantsFORPARSING set. + */ +HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, + LPCITEMIDLIST pidl, DWORD dwFlags, LPSTR szOut, DWORD dwOutLen) +{ + LPITEMIDLIST pidlFirst; + HRESULT hr = E_INVALIDARG; + + TRACE ("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n", psf, pidl, dwFlags, szOut, dwOutLen); + pdump (pidl); + + pidlFirst = ILCloneFirst (pidl); + if (pidlFirst) { + IShellFolder2 *psfChild; + + hr = IShellFolder_BindToObject (psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID *) & psfChild); + if (SUCCEEDED (hr)) { + STRRET strTemp; + LPITEMIDLIST pidlNext = ILGetNext (pidl); + + hr = IShellFolder_GetDisplayNameOf (psfChild, pidlNext, dwFlags, &strTemp); + if (SUCCEEDED (hr)) { + hr = StrRetToStrNA (szOut, dwOutLen, &strTemp, pidlNext); + } + IShellFolder_Release (psfChild); + } + ILFree (pidlFirst); + } else + hr = E_OUTOFMEMORY; + + TRACE ("-- ret=0x%08lx %s\n", hr, szOut); + + return hr; +} + +/*********************************************************************** + * SHELL32_GetItemAttributes + * + * NOTES + * observerd values: + * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER + * file: 0x40000177 FILESYSTEM + * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR + * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR + * (seems to be default for shell extensions if no registry entry exists) + * + * win2k: + * folder: 0xF0400177 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER + * file: 0x40400177 FILESYSTEM | CANMONIKER + * drive 0xF0400154 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER | CANRENAME (LABEL) + * + * This function does not set flags!! It only resets flags when necessary. + */ +HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) +{ + GUID const *clsid; + DWORD dwAttributes; + DWORD dwSupportedAttr=SFGAO_CANCOPY | /*0x00000001 */ + SFGAO_CANMOVE | /*0x00000002 */ + SFGAO_CANLINK | /*0x00000004 */ + SFGAO_CANRENAME | /*0x00000010 */ + SFGAO_CANDELETE | /*0x00000020 */ + SFGAO_HASPROPSHEET | /*0x00000040 */ + SFGAO_DROPTARGET | /*0x00000100 */ + SFGAO_LINK | /*0x00010000 */ + SFGAO_READONLY | /*0x00040000 */ + SFGAO_HIDDEN | /*0x00080000 */ + SFGAO_FILESYSANCESTOR | /*0x10000000 */ + SFGAO_FOLDER | /*0x20000000 */ + SFGAO_FILESYSTEM | /*0x40000000 */ + SFGAO_HASSUBFOLDER; /*0x80000000 */ + + TRACE ("0x%08lx\n", *pdwAttributes); + + if (*pdwAttributes & ~dwSupportedAttr) + { + WARN ("attributes 0x%08lx not implemented\n", (*pdwAttributes & ~dwSupportedAttr)); + *pdwAttributes &= dwSupportedAttr; + } + + if (_ILIsDrive (pidl)) { + *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK; + } else if ((clsid = _ILGetGUIDPointer (pidl))) { + if (HCR_GetFolderAttributes (clsid, &dwAttributes)) { + *pdwAttributes &= dwAttributes; + } else { + *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK; + } + } else if (_ILGetDataPointer (pidl)) { + dwAttributes = _ILGetFileAttributes (pidl, NULL, 0); + *pdwAttributes &= ~SFGAO_FILESYSANCESTOR; + + if ((SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) + *pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER); + + if ((SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN)) + *pdwAttributes &= ~SFGAO_HIDDEN; + + if ((SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY)) + *pdwAttributes &= ~SFGAO_READONLY; + + if (SFGAO_LINK & *pdwAttributes) { + char ext[MAX_PATH]; + + if (!_ILGetExtension(pidl, ext, MAX_PATH) || strcasecmp(ext, "lnk")) + *pdwAttributes &= ~SFGAO_LINK; + } + } else { + *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK; + } + TRACE ("-- 0x%08lx\n", *pdwAttributes); + return S_OK; +} + +/*********************************************************************** + * SHELL32_CompareIDs + */ +HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) +{ + int type1, + type2; + char szTemp1[MAX_PATH]; + char szTemp2[MAX_PATH]; + HRESULT nReturn; + LPITEMIDLIST firstpidl, + nextpidl1, + nextpidl2; + IShellFolder *psf; + + /* test for empty pidls */ + BOOL isEmpty1 = _ILIsDesktop (pidl1); + BOOL isEmpty2 = _ILIsDesktop (pidl2); + + if (isEmpty1 && isEmpty2) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 0 ); + if (isEmpty1) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); + if (isEmpty2) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); + + /* test for different types. Sort order is the PT_* constant */ + type1 = _ILGetDataPointer (pidl1)->type; + type2 = _ILGetDataPointer (pidl2)->type; + if (type1 < type2) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); + else if (type1 > type2) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); + + /* test for name of pidl */ + _ILSimpleGetText (pidl1, szTemp1, MAX_PATH); + _ILSimpleGetText (pidl2, szTemp2, MAX_PATH); + nReturn = strcasecmp (szTemp1, szTemp2); + if (nReturn < 0) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); + else if (nReturn > 0) + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); + + /* test of complex pidls */ + firstpidl = ILCloneFirst (pidl1); + nextpidl1 = ILGetNext (pidl1); + nextpidl2 = ILGetNext (pidl2); + + /* optimizing: test special cases and bind not deeper */ + /* the deeper shellfolder would do the same */ + isEmpty1 = _ILIsDesktop (nextpidl1); + isEmpty2 = _ILIsDesktop (nextpidl2); + + if (isEmpty1 && isEmpty2) { + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 0 ); + } else if (isEmpty1) { + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, (WORD)-1 ); + } else if (isEmpty2) { + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); + /* optimizing end */ + } else if (SUCCEEDED (IShellFolder_BindToObject (iface, firstpidl, NULL, &IID_IShellFolder, (LPVOID *) & psf))) { + nReturn = IShellFolder_CompareIDs (psf, lParam, nextpidl1, nextpidl2); + IShellFolder_Release (psf); + } + ILFree (firstpidl); + return nReturn; +} + +/*********************************************************************** + * SHCreateLinks + * + * Undocumented. + */ +HRESULT WINAPI SHCreateLinks( HWND hWnd, LPCSTR lpszDir, LPDATAOBJECT lpDataObject, + UINT uFlags, LPITEMIDLIST *lppidlLinks) +{ + FIXME("%p %s %p %08x %p\n",hWnd,lpszDir,lpDataObject,uFlags,lppidlLinks); + return E_NOTIMPL; +} diff --git a/reactos/lib/shell32/shlfsbind.c b/reactos/lib/shell32/shlfsbind.c index cbf09d420fc..14e1f3a811d 100644 --- a/reactos/lib/shell32/shlfsbind.c +++ b/reactos/lib/shell32/shlfsbind.c @@ -1,223 +1,222 @@ -/* - * File System Bind Data object to use as parameter for the bind context to - * IShellFolder_ParseDisplayName - * - * Copyright 2003 Rolf Kalbermatter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include "config.h" -#include "wine/port.h" - -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winuser.h" -#include "shlobj.h" -#include "shell32_main.h" - -#include "debughlp.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(pidl); - -/*********************************************************************** - * IFileSystemBindData implementation - */ -typedef struct -{ - IFileSystemBindDataVtbl *lpVtbl; - DWORD ref; - WIN32_FIND_DATAW findFile; -} IFileSystemBindDataImpl; - -static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *iface, REFIID riid, LPVOID* ppvObj); -static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *iface); -static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *iface); -static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd); -static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd); - -static struct IFileSystemBindDataVtbl sbvt = -{ - IFileSystemBindData_fnQueryInterface, - IFileSystemBindData_fnAddRef, - IFileSystemBindData_fnRelease, - IFileSystemBindData_fnSetFindData, - IFileSystemBindData_fnGetFindData, -}; - -static const WCHAR wFileSystemBindData[] = {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d','D','a','t','a',0}; - -HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV) -{ - IFileSystemBindDataImpl *sb; - HRESULT ret = E_OUTOFMEMORY; - - TRACE("%p, %p\n", pfd, ppV); - - if (!ppV) - return E_INVALIDARG; - - *ppV = NULL; - - sb = (IFileSystemBindDataImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileSystemBindDataImpl)); - if (!sb) - return ret; - - sb->lpVtbl = &sbvt; - sb->ref = 1; - IFileSystemBindData_fnSetFindData((IFileSystemBindData*)sb, pfd); - - ret = CreateBindCtx(0, ppV); - if (SUCCEEDED(ret)) - { - BIND_OPTS bindOpts; - bindOpts.cbStruct = sizeof(BIND_OPTS); - bindOpts.grfFlags = 0; - bindOpts.grfMode = STGM_CREATE; - bindOpts.dwTickCountDeadline = 0; - IBindCtx_SetBindOptions(*ppV, &bindOpts); - IBindCtx_RegisterObjectParam(*ppV, (LPOLESTR)wFileSystemBindData, (LPUNKNOWN)sb); - - IFileSystemBindData_Release((IFileSystemBindData*)sb); - } - else - HeapFree(GetProcessHeap(), 0, sb); - return ret; -} - -HRESULT WINAPI FileSystemBindData_GetFindData(LPBC pbc, WIN32_FIND_DATAW *pfd) -{ - LPUNKNOWN pUnk; - IFileSystemBindData *pfsbd = NULL; - HRESULT ret; - - TRACE("%p, %p\n", pbc, pfd); - - if (!pfd) - return E_INVALIDARG; - - ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk); - if (SUCCEEDED(ret)) - { - ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd); - if (SUCCEEDED(ret)) - { - ret = IFileSystemBindData_GetFindData(pfsbd, pfd); - IFileSystemBindData_Release(pfsbd); - } - IUnknown_Release(pUnk); - } - return ret; -} - -HRESULT WINAPI FileSystemBindData_SetFindData(LPBC pbc, const WIN32_FIND_DATAW *pfd) -{ - LPUNKNOWN pUnk; - IFileSystemBindData *pfsbd = NULL; - HRESULT ret; - - TRACE("%p, %p\n", pbc, pfd); - - ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk); - if (SUCCEEDED(ret)) - { - ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd); - if (SUCCEEDED(ret)) - { - ret = IFileSystemBindData_SetFindData(pfsbd, pfd); - IFileSystemBindData_Release(pfsbd); - } - IUnknown_Release(pUnk); - } - return ret;} - - - -static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *iface, REFIID riid, LPVOID *ppV) -{ - IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; - TRACE("(%p)->(\n\tIID:\t%s, %p)\n", This, debugstr_guid(riid), ppV); - - *ppV = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - { - *ppV = This; - } - else if (IsEqualIID(riid, &IID_IFileSystemBindData)) - { - *ppV = (IFileSystemBindData*)This; - } - - if (*ppV) - { - IUnknown_AddRef((IUnknown*)(*ppV)); - TRACE("-- Interface: (%p)->(%p)\n", ppV, *ppV); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *iface) -{ - IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; - TRACE("(%p)\n", This); - return InterlockedIncrement(&This->ref); -} - -static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *iface) -{ - IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; - TRACE("(%p)\n", This); - - if (!InterlockedDecrement(&This->ref)) - { - TRACE(" destroying ISFBindPidl(%p)\n",This); - HeapFree(GetProcessHeap(), 0, This); - return 0; - } - return This->ref; -} - -static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd) -{ - IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; - TRACE("(%p), %p\n", This, pfd); - - if (!pfd) - return E_INVALIDARG; - - memcpy(pfd, &This->findFile, sizeof(WIN32_FIND_DATAW)); - return NOERROR; -} - -static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd) -{ - IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; - TRACE("(%p), %p\n", This, pfd); - - if (pfd) - memcpy(&This->findFile, pfd, sizeof(WIN32_FIND_DATAW)); - else - memset(&This->findFile, 0, sizeof(WIN32_FIND_DATAW)); - return NOERROR; -} +/* + * File System Bind Data object to use as parameter for the bind context to + * IShellFolder_ParseDisplayName + * + * Copyright 2003 Rolf Kalbermatter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "config.h" +#include "wine/port.h" + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlobj.h" +#include "shell32_main.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(pidl); + +/*********************************************************************** + * IFileSystemBindData implementation + */ +typedef struct +{ + IFileSystemBindDataVtbl *lpVtbl; + DWORD ref; + WIN32_FIND_DATAW findFile; +} IFileSystemBindDataImpl; + +static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *iface, REFIID riid, LPVOID* ppvObj); +static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *iface); +static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *iface); +static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd); +static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd); + +static struct IFileSystemBindDataVtbl sbvt = +{ + IFileSystemBindData_fnQueryInterface, + IFileSystemBindData_fnAddRef, + IFileSystemBindData_fnRelease, + IFileSystemBindData_fnSetFindData, + IFileSystemBindData_fnGetFindData, +}; + +static const WCHAR wFileSystemBindData[] = {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d','D','a','t','a',0}; + +HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV) +{ + IFileSystemBindDataImpl *sb; + HRESULT ret = E_OUTOFMEMORY; + + TRACE("%p, %p\n", pfd, ppV); + + if (!ppV) + return E_INVALIDARG; + + *ppV = NULL; + + sb = (IFileSystemBindDataImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileSystemBindDataImpl)); + if (!sb) + return ret; + + sb->lpVtbl = &sbvt; + sb->ref = 1; + IFileSystemBindData_fnSetFindData((IFileSystemBindData*)sb, pfd); + + ret = CreateBindCtx(0, ppV); + if (SUCCEEDED(ret)) + { + BIND_OPTS bindOpts; + bindOpts.cbStruct = sizeof(BIND_OPTS); + bindOpts.grfFlags = 0; + bindOpts.grfMode = STGM_CREATE; + bindOpts.dwTickCountDeadline = 0; + IBindCtx_SetBindOptions(*ppV, &bindOpts); + IBindCtx_RegisterObjectParam(*ppV, (LPOLESTR)wFileSystemBindData, (LPUNKNOWN)sb); + + IFileSystemBindData_Release((IFileSystemBindData*)sb); + } + else + HeapFree(GetProcessHeap(), 0, sb); + return ret; +} + +HRESULT WINAPI FileSystemBindData_GetFindData(LPBC pbc, WIN32_FIND_DATAW *pfd) +{ + LPUNKNOWN pUnk; + IFileSystemBindData *pfsbd = NULL; + HRESULT ret; + + TRACE("%p, %p\n", pbc, pfd); + + if (!pfd) + return E_INVALIDARG; + + ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk); + if (SUCCEEDED(ret)) + { + ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd); + if (SUCCEEDED(ret)) + { + ret = IFileSystemBindData_GetFindData(pfsbd, pfd); + IFileSystemBindData_Release(pfsbd); + } + IUnknown_Release(pUnk); + } + return ret; +} + +HRESULT WINAPI FileSystemBindData_SetFindData(LPBC pbc, const WIN32_FIND_DATAW *pfd) +{ + LPUNKNOWN pUnk; + IFileSystemBindData *pfsbd = NULL; + HRESULT ret; + + TRACE("%p, %p\n", pbc, pfd); + + ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk); + if (SUCCEEDED(ret)) + { + ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd); + if (SUCCEEDED(ret)) + { + ret = IFileSystemBindData_SetFindData(pfsbd, pfd); + IFileSystemBindData_Release(pfsbd); + } + IUnknown_Release(pUnk); + } + return ret;} + + + +static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *iface, REFIID riid, LPVOID *ppV) +{ + IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; + TRACE("(%p)->(\n\tIID:\t%s, %p)\n", This, debugstr_guid(riid), ppV); + + *ppV = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + { + *ppV = This; + } + else if (IsEqualIID(riid, &IID_IFileSystemBindData)) + { + *ppV = (IFileSystemBindData*)This; + } + + if (*ppV) + { + IUnknown_AddRef((IUnknown*)(*ppV)); + TRACE("-- Interface: (%p)->(%p)\n", ppV, *ppV); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *iface) +{ + IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; + TRACE("(%p)\n", This); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *iface) +{ + IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; + TRACE("(%p)\n", This); + + if (!InterlockedDecrement(&This->ref)) + { + TRACE(" destroying ISFBindPidl(%p)\n",This); + HeapFree(GetProcessHeap(), 0, This); + return 0; + } + return This->ref; +} + +static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd) +{ + IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; + TRACE("(%p), %p\n", This, pfd); + + if (!pfd) + return E_INVALIDARG; + + memcpy(pfd, &This->findFile, sizeof(WIN32_FIND_DATAW)); + return NOERROR; +} + +static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd) +{ + IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface; + TRACE("(%p), %p\n", This, pfd); + + if (pfd) + memcpy(&This->findFile, pfd, sizeof(WIN32_FIND_DATAW)); + else + memset(&This->findFile, 0, sizeof(WIN32_FIND_DATAW)); + return NOERROR; +} diff --git a/reactos/lib/shell32/shlmenu.c b/reactos/lib/shell32/shlmenu.c index d10acb430bd..6c2b149cf74 100644 --- a/reactos/lib/shell32/shlmenu.c +++ b/reactos/lib/shell32/shlmenu.c @@ -1,1002 +1,1002 @@ -/* - * see www.geocities.com/SiliconValley/4942/filemenu.html - * - * Copyright 1999, 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "undocshell.h" -#include "shlwapi.h" -#include "shell32_main.h" -#include "shlguid.h" - -#include "pidl.h" -#include "wine/debug.h" - -#ifdef FM_SEPARATOR -#undef FM_SEPARATOR -#endif -#define FM_SEPARATOR (LPCWSTR)1 - -static BOOL FileMenu_AppendItemW(HMENU hMenu, LPCWSTR lpText, UINT uID, int icon, - HMENU hMenuPopup, int nItemHeight); - -typedef struct -{ - BOOL bInitialized; - BOOL bFixedItems; - /* create */ - COLORREF crBorderColor; - int nBorderWidth; - HBITMAP hBorderBmp; - - /* insert using pidl */ - LPITEMIDLIST pidl; - UINT uID; - UINT uFlags; - UINT uEnumFlags; - LPFNFMCALLBACK lpfnCallback; -} FMINFO, *LPFMINFO; - -typedef struct -{ int cchItemText; - int iIconIndex; - HMENU hMenu; - WCHAR szItemText[1]; -} FMITEM, * LPFMITEM; - -static BOOL bAbortInit; - -#define CCH_MAXITEMTEXT 256 - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -LPFMINFO FM_GetMenuInfo(HMENU hmenu) -{ MENUINFO MenuInfo; - LPFMINFO menudata; - - MenuInfo.cbSize = sizeof(MENUINFO); - MenuInfo.fMask = MIM_MENUDATA; - - if (! GetMenuInfo(hmenu, &MenuInfo)) - return NULL; - - menudata = (LPFMINFO)MenuInfo.dwMenuData; - - if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) - { - ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); - return 0; - } - - return menudata; - -} -/************************************************************************* - * FM_SetMenuParameter [internal] - * - */ -static LPFMINFO FM_SetMenuParameter( - HMENU hmenu, - UINT uID, - LPCITEMIDLIST pidl, - UINT uFlags, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback) -{ - LPFMINFO menudata; - - TRACE("\n"); - - menudata = FM_GetMenuInfo(hmenu); - - if ( menudata->pidl) - { SHFree(menudata->pidl); - } - - menudata->uID = uID; - menudata->pidl = ILClone(pidl); - menudata->uFlags = uFlags; - menudata->uEnumFlags = uEnumFlags; - menudata->lpfnCallback = lpfnCallback; - - return menudata; -} - -/************************************************************************* - * FM_InitMenuPopup [internal] - * - */ -static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl) -{ IShellFolder *lpsf, *lpsf2; - ULONG ulItemAttr = SFGAO_FOLDER; - UINT uID, uFlags, uEnumFlags; - LPFNFMCALLBACK lpfnCallback; - LPCITEMIDLIST pidl; - WCHAR sTemp[MAX_PATH]; - int NumberOfItems = 0, iIcon; - MENUINFO MenuInfo; - LPFMINFO menudata; - - TRACE("%p %p\n", hmenu, pAlternatePidl); - - MenuInfo.cbSize = sizeof(MENUINFO); - MenuInfo.fMask = MIM_MENUDATA; - - if (! GetMenuInfo(hmenu, &MenuInfo)) - return FALSE; - - menudata = (LPFMINFO)MenuInfo.dwMenuData; - - if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) - { - ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); - return 0; - } - - if (menudata->bInitialized) - return 0; - - pidl = (pAlternatePidl? pAlternatePidl: menudata->pidl); - if (!pidl) - return 0; - - uID = menudata->uID; - uFlags = menudata->uFlags; - uEnumFlags = menudata->uEnumFlags; - lpfnCallback = menudata->lpfnCallback; - menudata->bInitialized = FALSE; - - SetMenuInfo(hmenu, &MenuInfo); - - if (SUCCEEDED (SHGetDesktopFolder(&lpsf))) - { - if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) - { - IEnumIDList *lpe = NULL; - - if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe ))) - { - - LPITEMIDLIST pidlTemp = NULL; - ULONG ulFetched; - - while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))) - { - if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulItemAttr))) - { - ILGetDisplayNameExW(NULL, pidlTemp, sTemp, ILGDN_FORPARSING); - if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon))) - iIcon = FM_BLANK_ICON; - if ( SFGAO_FOLDER & ulItemAttr) - { - LPFMINFO lpFmMi; - MENUINFO MenuInfo; - HMENU hMenuPopup = CreatePopupMenu(); - - lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO)); - - lpFmMi->pidl = ILCombine(pidl, pidlTemp); - lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS; - - MenuInfo.cbSize = sizeof(MENUINFO); - MenuInfo.fMask = MIM_MENUDATA; - MenuInfo.dwMenuData = (DWORD) lpFmMi; - SetMenuInfo (hMenuPopup, &MenuInfo); - - FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT); - } - else - { - LPWSTR pExt = PathFindExtensionW(sTemp); - if (pExt) - *pExt = 0; - FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT); - } - } - - if (lpfnCallback) - { - TRACE("enter callback\n"); - lpfnCallback ( pidl, pidlTemp); - TRACE("leave callback\n"); - } - - NumberOfItems++; - } - IEnumIDList_Release (lpe); - } - IShellFolder_Release(lpsf2); - } - IShellFolder_Release(lpsf); - } - - if ( GetMenuItemCount (hmenu) == 0 ) - { - static const WCHAR szEmpty[] = { '(','e','m','p','t','y',')',0 }; - FileMenu_AppendItemW (hmenu, szEmpty, uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT); - NumberOfItems++; - } - - menudata->bInitialized = TRUE; - SetMenuInfo(hmenu, &MenuInfo); - - return NumberOfItems; -} -/************************************************************************* - * FileMenu_Create [SHELL32.114] - * - * NOTES - * for non-root menus values are - * (ffffffff,00000000,00000000,00000000,00000000) - */ -HMENU WINAPI FileMenu_Create ( - COLORREF crBorderColor, - int nBorderWidth, - HBITMAP hBorderBmp, - int nSelHeight, - UINT uFlags) -{ - MENUINFO MenuInfo; - LPFMINFO menudata; - - HMENU hMenu = CreatePopupMenu(); - - TRACE("0x%08lx 0x%08x %p 0x%08x 0x%08x hMenu=%p\n", - crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu); - - menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO)); - menudata->crBorderColor = crBorderColor; - menudata->nBorderWidth = nBorderWidth; - menudata->hBorderBmp = hBorderBmp; - - MenuInfo.cbSize = sizeof(MENUINFO); - MenuInfo.fMask = MIM_MENUDATA; - MenuInfo.dwMenuData = (DWORD) menudata; - SetMenuInfo (hMenu, &MenuInfo); - - return hMenu; -} - -/************************************************************************* - * FileMenu_Destroy [SHELL32.118] - * - * NOTES - * exported by name - */ -void WINAPI FileMenu_Destroy (HMENU hmenu) -{ - LPFMINFO menudata; - - TRACE("%p\n", hmenu); - - FileMenu_DeleteAllItems (hmenu); - - menudata = FM_GetMenuInfo(hmenu); - - if ( menudata->pidl) - { SHFree( menudata->pidl); - } - HeapFree(GetProcessHeap(), 0, menudata); - - DestroyMenu (hmenu); -} - -/************************************************************************* - * FileMenu_AppendItem [SHELL32.115] - * - */ -static BOOL FileMenu_AppendItemW( - HMENU hMenu, - LPCWSTR lpText, - UINT uID, - int icon, - HMENU hMenuPopup, - int nItemHeight) -{ - MENUITEMINFOW mii; - LPFMITEM myItem; - LPFMINFO menudata; - MENUINFO MenuInfo; - - - TRACE("%p %s 0x%08x 0x%08x %p 0x%08x\n", - hMenu, (lpText!=FM_SEPARATOR) ? debugstr_w(lpText) : NULL, - uID, icon, hMenuPopup, nItemHeight); - - ZeroMemory (&mii, sizeof(MENUITEMINFOW)); - - mii.cbSize = sizeof(MENUITEMINFOW); - - if (lpText != FM_SEPARATOR) - { - int len = strlenW (lpText); - myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len*sizeof(WCHAR)); - strcpyW (myItem->szItemText, lpText); - myItem->cchItemText = len; - myItem->iIconIndex = icon; - myItem->hMenu = hMenu; - mii.fMask = MIIM_DATA; - mii.dwItemData = (DWORD) myItem; - } - - if ( hMenuPopup ) - { /* sub menu */ - mii.fMask |= MIIM_TYPE | MIIM_SUBMENU; - mii.fType = MFT_OWNERDRAW; - mii.hSubMenu = hMenuPopup; - } - else if (lpText == FM_SEPARATOR ) - { mii.fMask |= MIIM_ID | MIIM_TYPE; - mii.fType = MFT_SEPARATOR; - } - else - { /* normal item */ - mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE; - mii.fState = MFS_ENABLED | MFS_DEFAULT; - mii.fType = MFT_OWNERDRAW; - } - mii.wID = uID; - - InsertMenuItemW (hMenu, (UINT)-1, TRUE, &mii); - - /* set bFixedItems to true */ - MenuInfo.cbSize = sizeof(MENUINFO); - MenuInfo.fMask = MIM_MENUDATA; - - if (! GetMenuInfo(hMenu, &MenuInfo)) - return FALSE; - - menudata = (LPFMINFO)MenuInfo.dwMenuData; - if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) - { - ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); - return 0; - } - - menudata->bFixedItems = TRUE; - SetMenuInfo(hMenu, &MenuInfo); - - return TRUE; - -} - -/**********************************************************************/ - -BOOL WINAPI FileMenu_AppendItemAW( - HMENU hMenu, - LPCVOID lpText, - UINT uID, - int icon, - HMENU hMenuPopup, - int nItemHeight) -{ - BOOL ret; - - if ((SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR)) || (lpText == NULL)) - ret = FileMenu_AppendItemW(hMenu, lpText, uID, icon, hMenuPopup, nItemHeight); - else - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, lpText, -1, NULL, 0 ); - LPWSTR lpszText = HeapAlloc ( GetProcessHeap(), 0, len*sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, lpText, -1, lpszText, len ); - ret = FileMenu_AppendItemW(hMenu, lpszText, uID, icon, hMenuPopup, nItemHeight); - HeapFree( GetProcessHeap(), 0, lpszText ); - } - - return ret; -} -/************************************************************************* - * FileMenu_InsertUsingPidl [SHELL32.110] - * - * NOTES - * uEnumFlags any SHCONTF flag - */ -int WINAPI FileMenu_InsertUsingPidl ( - HMENU hmenu, - UINT uID, - LPCITEMIDLIST pidl, - UINT uFlags, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback) -{ - TRACE("%p 0x%08x %p 0x%08x 0x%08x %p\n", - hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); - - pdump (pidl); - - bAbortInit = FALSE; - - FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); - - return FM_InitMenuPopup(hmenu, NULL); -} - -/************************************************************************* - * FileMenu_ReplaceUsingPidl [SHELL32.113] - * - * FIXME: the static items are deleted but won't be refreshed - */ -int WINAPI FileMenu_ReplaceUsingPidl( - HMENU hmenu, - UINT uID, - LPCITEMIDLIST pidl, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback) -{ - TRACE("%p 0x%08x %p 0x%08x %p\n", - hmenu, uID, pidl, uEnumFlags, lpfnCallback); - - FileMenu_DeleteAllItems (hmenu); - - FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback); - - return FM_InitMenuPopup(hmenu, NULL); -} - -/************************************************************************* - * FileMenu_Invalidate [SHELL32.111] - */ -void WINAPI FileMenu_Invalidate (HMENU hMenu) -{ - FIXME("%p\n",hMenu); -} - -/************************************************************************* - * FileMenu_FindSubMenuByPidl [SHELL32.106] - */ -HMENU WINAPI FileMenu_FindSubMenuByPidl( - HMENU hMenu, - LPCITEMIDLIST pidl) -{ - FIXME("%p %p\n",hMenu, pidl); - return 0; -} - -/************************************************************************* - * FileMenu_AppendFilesForPidl [SHELL32.124] - */ -int WINAPI FileMenu_AppendFilesForPidl( - HMENU hmenu, - LPCITEMIDLIST pidl, - BOOL bAddSeperator) -{ - LPFMINFO menudata; - - menudata = FM_GetMenuInfo(hmenu); - - menudata->bInitialized = FALSE; - - FM_InitMenuPopup(hmenu, pidl); - - if (bAddSeperator) - FileMenu_AppendItemW (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT); - - TRACE("%p %p 0x%08x\n",hmenu, pidl,bAddSeperator); - - return 0; -} -/************************************************************************* - * FileMenu_AddFilesForPidl [SHELL32.125] - * - * NOTES - * uEnumFlags any SHCONTF flag - */ -int WINAPI FileMenu_AddFilesForPidl ( - HMENU hmenu, - UINT uReserved, - UINT uID, - LPCITEMIDLIST pidl, - UINT uFlags, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback) -{ - TRACE("%p 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n", - hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback); - - return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); - -} - - -/************************************************************************* - * FileMenu_TrackPopupMenuEx [SHELL32.116] - */ -BOOL WINAPI FileMenu_TrackPopupMenuEx ( - HMENU hMenu, - UINT uFlags, - int x, - int y, - HWND hWnd, - LPTPMPARAMS lptpm) -{ - TRACE("%p 0x%08x 0x%x 0x%x %p %p\n", - hMenu, uFlags, x, y, hWnd, lptpm); - return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm); -} - -/************************************************************************* - * FileMenu_GetLastSelectedItemPidls [SHELL32.107] - */ -BOOL WINAPI FileMenu_GetLastSelectedItemPidls( - UINT uReserved, - LPCITEMIDLIST *ppidlFolder, - LPCITEMIDLIST *ppidlItem) -{ - FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem); - return 0; -} - -#define FM_ICON_SIZE 16 -#define FM_Y_SPACE 4 -#define FM_SPACE1 4 -#define FM_SPACE2 2 -#define FM_LEFTBORDER 2 -#define FM_RIGHTBORDER 8 -/************************************************************************* - * FileMenu_MeasureItem [SHELL32.112] - */ -LRESULT WINAPI FileMenu_MeasureItem( - HWND hWnd, - LPMEASUREITEMSTRUCT lpmis) -{ - LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData); - HDC hdc = GetDC(hWnd); - SIZE size; - LPFMINFO menuinfo; - - TRACE("%p %p %s\n", hWnd, lpmis, debugstr_w(pMyItem->szItemText)); - - GetTextExtentPoint32W(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size); - - lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER; - lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE); - - /* add the menubitmap */ - menuinfo = FM_GetMenuInfo(pMyItem->hMenu); - if (menuinfo->nBorderWidth) - lpmis->itemWidth += menuinfo->nBorderWidth; - - TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight); - ReleaseDC (hWnd, hdc); - return 0; -} -/************************************************************************* - * FileMenu_DrawItem [SHELL32.105] - */ -LRESULT WINAPI FileMenu_DrawItem( - HWND hWnd, - LPDRAWITEMSTRUCT lpdis) -{ - LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData); - COLORREF clrPrevText, clrPrevBkgnd; - int xi,yi,xt,yt; - HIMAGELIST hImageList; - RECT TextRect, BorderRect; - LPFMINFO menuinfo; - - TRACE("%p %p %s\n", hWnd, lpdis, debugstr_w(pMyItem->szItemText)); - - if (lpdis->itemState & ODS_SELECTED) - { - clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); - clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); - } - else - { - clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT)); - clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU)); - } - - CopyRect(&TextRect, &(lpdis->rcItem)); - - /* add the menubitmap */ - menuinfo = FM_GetMenuInfo(pMyItem->hMenu); - if (menuinfo->nBorderWidth) - TextRect.left += menuinfo->nBorderWidth; - - BorderRect.right = menuinfo->nBorderWidth; -/* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor)); -*/ - TextRect.left += FM_LEFTBORDER; - xi = TextRect.left + FM_SPACE1; - yi = TextRect.top + FM_Y_SPACE/2; - TextRect.bottom -= FM_Y_SPACE/2; - - xt = xi + FM_ICON_SIZE + FM_SPACE2; - yt = yi; - - ExtTextOutW (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL); - - Shell_GetImageList(0, &hImageList); - ImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL); - - TRACE("-- 0x%04lx 0x%04lx 0x%04lx 0x%04lx\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom); - - SetTextColor(lpdis->hDC, clrPrevText); - SetBkColor(lpdis->hDC, clrPrevBkgnd); - - return TRUE; -} - -/************************************************************************* - * FileMenu_InitMenuPopup [SHELL32.109] - * - * NOTES - * The filemenu is a ownerdrawn menu. Call this function responding to - * WM_INITPOPUPMENU - * - */ -BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu) -{ - FM_InitMenuPopup(hmenu, NULL); - return TRUE; -} - -/************************************************************************* - * FileMenu_HandleMenuChar [SHELL32.108] - */ -LRESULT WINAPI FileMenu_HandleMenuChar( - HMENU hMenu, - WPARAM wParam) -{ - FIXME("%p 0x%08x\n",hMenu,wParam); - return 0; -} - -/************************************************************************* - * FileMenu_DeleteAllItems [SHELL32.104] - * - * NOTES - * exported by name - */ -BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu) -{ - MENUITEMINFOW mii; - LPFMINFO menudata; - - int i; - - TRACE("%p\n", hmenu); - - ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_SUBMENU|MIIM_DATA; - - for (i = 0; i < GetMenuItemCount( hmenu ); i++) - { GetMenuItemInfoW(hmenu, i, TRUE, &mii ); - - if (mii.dwItemData) - SHFree((LPFMINFO)mii.dwItemData); - - if (mii.hSubMenu) - FileMenu_Destroy(mii.hSubMenu); - } - - while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){}; - - menudata = FM_GetMenuInfo(hmenu); - - menudata->bInitialized = FALSE; - - return TRUE; -} - -/************************************************************************* - * FileMenu_DeleteItemByCmd [SHELL32.117] - * - */ -BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID) -{ - MENUITEMINFOW mii; - - TRACE("%p 0x%08x\n", hMenu, uID); - - ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_SUBMENU; - - GetMenuItemInfoW(hMenu, uID, FALSE, &mii ); - if ( mii.hSubMenu ) - { - /* FIXME: Do what? */ - } - - DeleteMenu(hMenu, MF_BYCOMMAND, uID); - return TRUE; -} - -/************************************************************************* - * FileMenu_DeleteItemByIndex [SHELL32.140] - */ -BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos) -{ - MENUITEMINFOW mii; - - TRACE("%p 0x%08x\n", hMenu, uPos); - - ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_SUBMENU; - - GetMenuItemInfoW(hMenu, uPos, TRUE, &mii ); - if ( mii.hSubMenu ) - { - /* FIXME: Do what? */ - } - - DeleteMenu(hMenu, MF_BYPOSITION, uPos); - return TRUE; -} - -/************************************************************************* - * FileMenu_DeleteItemByFirstID [SHELL32.141] - */ -BOOL WINAPI FileMenu_DeleteItemByFirstID( - HMENU hMenu, - UINT uID) -{ - TRACE("%p 0x%08x\n", hMenu, uID); - return 0; -} - -/************************************************************************* - * FileMenu_DeleteSeparator [SHELL32.142] - */ -BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu) -{ - TRACE("%p\n", hMenu); - return 0; -} - -/************************************************************************* - * FileMenu_EnableItemByCmd [SHELL32.143] - */ -BOOL WINAPI FileMenu_EnableItemByCmd( - HMENU hMenu, - UINT uID, - BOOL bEnable) -{ - TRACE("%p 0x%08x 0x%08x\n", hMenu, uID,bEnable); - return 0; -} - -/************************************************************************* - * FileMenu_GetItemExtent [SHELL32.144] - * - * NOTES - * if the menu is too big, entries are getting cut away!! - */ -DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos) -{ RECT rect; - - FIXME("%p 0x%08x\n", hMenu, uPos); - - if (GetMenuItemRect(0, hMenu, uPos, &rect)) - { FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx\n", - rect.right, rect.left, rect.top, rect.bottom); - return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom); - } - return 0x00100010; /*FIXME*/ -} - -/************************************************************************* - * FileMenu_AbortInitMenu [SHELL32.120] - * - */ -void WINAPI FileMenu_AbortInitMenu (void) -{ TRACE("\n"); - bAbortInit = TRUE; -} - -/************************************************************************* - * SHFind_InitMenuPopup [SHELL32.149] - * - * - * PARAMETERS - * hMenu [in] handle of menu previously created - * hWndParent [in] parent window - * w [in] no pointer (0x209 over here) perhaps menu IDs ??? - * x [in] no pointer (0x226 over here) - * - * RETURNS - * LPXXXXX pointer to struct containing a func addr at offset 8 - * or NULL at failure. - */ -LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x) -{ FIXME("hmenu=%p hwnd=%p 0x%08lx 0x%08lx stub\n", - hMenu,hWndParent,w,x); - return NULL; /* this is supposed to be a pointer */ -} - -/************************************************************************* - * Shell_MergeMenus [SHELL32.67] - * - */ -BOOL _SHIsMenuSeparator(HMENU hm, int i) -{ - MENUITEMINFOW mii; - - mii.cbSize = sizeof(MENUITEMINFOW); - mii.fMask = MIIM_TYPE; - mii.cch = 0; /* WARNING: We MUST initialize it to 0*/ - if (!GetMenuItemInfoW(hm, i, TRUE, &mii)) - { - return(FALSE); - } - - if (mii.fType & MFT_SEPARATOR) - { - return(TRUE); - } - - return(FALSE); -} - -/**********************************************************************/ - -HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags) -{ int nItem; - HMENU hmSubMenu; - BOOL bAlreadySeparated; - MENUITEMINFOW miiSrc; - WCHAR szName[256]; - UINT uTemp, uIDMax = uIDAdjust; - - TRACE("hmenu1=%p hmenu2=%p 0x%04x 0x%04x 0x%04x 0x%04lx\n", - hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags); - - if (!hmDst || !hmSrc) - { return uIDMax; - } - - nItem = GetMenuItemCount(hmDst); - - if (uInsert >= (UINT)nItem) /* insert position inside menu? */ - { - uInsert = (UINT)nItem; /* append on the end */ - bAlreadySeparated = TRUE; - } - else - { - bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert); - } - - if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) - { - /* Add a separator between the menus */ - InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - bAlreadySeparated = TRUE; - } - - - /* Go through the menu items and clone them*/ - for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--) - { - miiSrc.cbSize = sizeof(MENUITEMINFOW); - miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA; - - /* We need to reset this every time through the loop in case menus DON'T have IDs*/ - miiSrc.fType = MFT_STRING; - miiSrc.dwTypeData = szName; - miiSrc.dwItemData = 0; - miiSrc.cch = sizeof(szName)/sizeof(WCHAR); - - if (!GetMenuItemInfoW(hmSrc, nItem, TRUE, &miiSrc)) - { - continue; - } - -/* TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu); -*/ - if (miiSrc.fType & MFT_SEPARATOR) - { - /* This is a separator; don't put two of them in a row */ - if (bAlreadySeparated) - continue; - - bAlreadySeparated = TRUE; - } - else if (miiSrc.hSubMenu) - { - if (uFlags & MM_SUBMENUSHAVEIDS) - { - miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ - - if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ - continue; - - if (uIDMax <= miiSrc.wID) /* remember the highest ID */ - uIDMax = miiSrc.wID + 1; - } - else - { - miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */ - } - hmSubMenu = miiSrc.hSubMenu; - - miiSrc.hSubMenu = CreatePopupMenu(); - - if (!miiSrc.hSubMenu) return(uIDMax); - - uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS); - - if (uIDMax <= uTemp) - uIDMax = uTemp; - - bAlreadySeparated = FALSE; - } - else /* normal menu item */ - { - miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ - - if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ - continue; - - if (uIDMax <= miiSrc.wID) /* remember the highest ID */ - uIDMax = miiSrc.wID + 1; - - bAlreadySeparated = FALSE; - } - -/* TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu); -*/ - if (!InsertMenuItemW(hmDst, uInsert, TRUE, &miiSrc)) - { - return(uIDMax); - } - } - - /* Ensure the correct number of separators at the beginning of the - inserted menu items*/ - if (uInsert == 0) - { - if (bAlreadySeparated) - { - DeleteMenu(hmDst, uInsert, MF_BYPOSITION); - } - } - else - { - if (_SHIsMenuSeparator(hmDst, uInsert-1)) - { - if (bAlreadySeparated) - { - DeleteMenu(hmDst, uInsert, MF_BYPOSITION); - } - } - else - { - if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) - { - /* Add a separator between the menus*/ - InsertMenuW(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - } - } - } - return(uIDMax); -} +/* + * see www.geocities.com/SiliconValley/4942/filemenu.html + * + * Copyright 1999, 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "undocshell.h" +#include "shlwapi.h" +#include "shell32_main.h" +#include "shlguid.h" + +#include "pidl.h" +#include "wine/debug.h" + +#ifdef FM_SEPARATOR +#undef FM_SEPARATOR +#endif +#define FM_SEPARATOR (LPCWSTR)1 + +static BOOL FileMenu_AppendItemW(HMENU hMenu, LPCWSTR lpText, UINT uID, int icon, + HMENU hMenuPopup, int nItemHeight); + +typedef struct +{ + BOOL bInitialized; + BOOL bFixedItems; + /* create */ + COLORREF crBorderColor; + int nBorderWidth; + HBITMAP hBorderBmp; + + /* insert using pidl */ + LPITEMIDLIST pidl; + UINT uID; + UINT uFlags; + UINT uEnumFlags; + LPFNFMCALLBACK lpfnCallback; +} FMINFO, *LPFMINFO; + +typedef struct +{ int cchItemText; + int iIconIndex; + HMENU hMenu; + WCHAR szItemText[1]; +} FMITEM, * LPFMITEM; + +static BOOL bAbortInit; + +#define CCH_MAXITEMTEXT 256 + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +LPFMINFO FM_GetMenuInfo(HMENU hmenu) +{ MENUINFO MenuInfo; + LPFMINFO menudata; + + MenuInfo.cbSize = sizeof(MENUINFO); + MenuInfo.fMask = MIM_MENUDATA; + + if (! GetMenuInfo(hmenu, &MenuInfo)) + return NULL; + + menudata = (LPFMINFO)MenuInfo.dwMenuData; + + if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) + { + ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); + return 0; + } + + return menudata; + +} +/************************************************************************* + * FM_SetMenuParameter [internal] + * + */ +static LPFMINFO FM_SetMenuParameter( + HMENU hmenu, + UINT uID, + LPCITEMIDLIST pidl, + UINT uFlags, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback) +{ + LPFMINFO menudata; + + TRACE("\n"); + + menudata = FM_GetMenuInfo(hmenu); + + if ( menudata->pidl) + { SHFree(menudata->pidl); + } + + menudata->uID = uID; + menudata->pidl = ILClone(pidl); + menudata->uFlags = uFlags; + menudata->uEnumFlags = uEnumFlags; + menudata->lpfnCallback = lpfnCallback; + + return menudata; +} + +/************************************************************************* + * FM_InitMenuPopup [internal] + * + */ +static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl) +{ IShellFolder *lpsf, *lpsf2; + ULONG ulItemAttr = SFGAO_FOLDER; + UINT uID, uFlags, uEnumFlags; + LPFNFMCALLBACK lpfnCallback; + LPCITEMIDLIST pidl; + WCHAR sTemp[MAX_PATH]; + int NumberOfItems = 0, iIcon; + MENUINFO MenuInfo; + LPFMINFO menudata; + + TRACE("%p %p\n", hmenu, pAlternatePidl); + + MenuInfo.cbSize = sizeof(MENUINFO); + MenuInfo.fMask = MIM_MENUDATA; + + if (! GetMenuInfo(hmenu, &MenuInfo)) + return FALSE; + + menudata = (LPFMINFO)MenuInfo.dwMenuData; + + if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) + { + ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); + return 0; + } + + if (menudata->bInitialized) + return 0; + + pidl = (pAlternatePidl? pAlternatePidl: menudata->pidl); + if (!pidl) + return 0; + + uID = menudata->uID; + uFlags = menudata->uFlags; + uEnumFlags = menudata->uEnumFlags; + lpfnCallback = menudata->lpfnCallback; + menudata->bInitialized = FALSE; + + SetMenuInfo(hmenu, &MenuInfo); + + if (SUCCEEDED (SHGetDesktopFolder(&lpsf))) + { + if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) + { + IEnumIDList *lpe = NULL; + + if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe ))) + { + + LPITEMIDLIST pidlTemp = NULL; + ULONG ulFetched; + + while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))) + { + if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulItemAttr))) + { + ILGetDisplayNameExW(NULL, pidlTemp, sTemp, ILGDN_FORPARSING); + if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon))) + iIcon = FM_BLANK_ICON; + if ( SFGAO_FOLDER & ulItemAttr) + { + LPFMINFO lpFmMi; + MENUINFO MenuInfo; + HMENU hMenuPopup = CreatePopupMenu(); + + lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO)); + + lpFmMi->pidl = ILCombine(pidl, pidlTemp); + lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS; + + MenuInfo.cbSize = sizeof(MENUINFO); + MenuInfo.fMask = MIM_MENUDATA; + MenuInfo.dwMenuData = (DWORD) lpFmMi; + SetMenuInfo (hMenuPopup, &MenuInfo); + + FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT); + } + else + { + LPWSTR pExt = PathFindExtensionW(sTemp); + if (pExt) + *pExt = 0; + FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT); + } + } + + if (lpfnCallback) + { + TRACE("enter callback\n"); + lpfnCallback ( pidl, pidlTemp); + TRACE("leave callback\n"); + } + + NumberOfItems++; + } + IEnumIDList_Release (lpe); + } + IShellFolder_Release(lpsf2); + } + IShellFolder_Release(lpsf); + } + + if ( GetMenuItemCount (hmenu) == 0 ) + { + static const WCHAR szEmpty[] = { '(','e','m','p','t','y',')',0 }; + FileMenu_AppendItemW (hmenu, szEmpty, uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT); + NumberOfItems++; + } + + menudata->bInitialized = TRUE; + SetMenuInfo(hmenu, &MenuInfo); + + return NumberOfItems; +} +/************************************************************************* + * FileMenu_Create [SHELL32.114] + * + * NOTES + * for non-root menus values are + * (ffffffff,00000000,00000000,00000000,00000000) + */ +HMENU WINAPI FileMenu_Create ( + COLORREF crBorderColor, + int nBorderWidth, + HBITMAP hBorderBmp, + int nSelHeight, + UINT uFlags) +{ + MENUINFO MenuInfo; + LPFMINFO menudata; + + HMENU hMenu = CreatePopupMenu(); + + TRACE("0x%08lx 0x%08x %p 0x%08x 0x%08x hMenu=%p\n", + crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu); + + menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO)); + menudata->crBorderColor = crBorderColor; + menudata->nBorderWidth = nBorderWidth; + menudata->hBorderBmp = hBorderBmp; + + MenuInfo.cbSize = sizeof(MENUINFO); + MenuInfo.fMask = MIM_MENUDATA; + MenuInfo.dwMenuData = (DWORD) menudata; + SetMenuInfo (hMenu, &MenuInfo); + + return hMenu; +} + +/************************************************************************* + * FileMenu_Destroy [SHELL32.118] + * + * NOTES + * exported by name + */ +void WINAPI FileMenu_Destroy (HMENU hmenu) +{ + LPFMINFO menudata; + + TRACE("%p\n", hmenu); + + FileMenu_DeleteAllItems (hmenu); + + menudata = FM_GetMenuInfo(hmenu); + + if ( menudata->pidl) + { SHFree( menudata->pidl); + } + HeapFree(GetProcessHeap(), 0, menudata); + + DestroyMenu (hmenu); +} + +/************************************************************************* + * FileMenu_AppendItem [SHELL32.115] + * + */ +static BOOL FileMenu_AppendItemW( + HMENU hMenu, + LPCWSTR lpText, + UINT uID, + int icon, + HMENU hMenuPopup, + int nItemHeight) +{ + MENUITEMINFOW mii; + LPFMITEM myItem; + LPFMINFO menudata; + MENUINFO MenuInfo; + + + TRACE("%p %s 0x%08x 0x%08x %p 0x%08x\n", + hMenu, (lpText!=FM_SEPARATOR) ? debugstr_w(lpText) : NULL, + uID, icon, hMenuPopup, nItemHeight); + + ZeroMemory (&mii, sizeof(MENUITEMINFOW)); + + mii.cbSize = sizeof(MENUITEMINFOW); + + if (lpText != FM_SEPARATOR) + { + int len = strlenW (lpText); + myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len*sizeof(WCHAR)); + strcpyW (myItem->szItemText, lpText); + myItem->cchItemText = len; + myItem->iIconIndex = icon; + myItem->hMenu = hMenu; + mii.fMask = MIIM_DATA; + mii.dwItemData = (DWORD) myItem; + } + + if ( hMenuPopup ) + { /* sub menu */ + mii.fMask |= MIIM_TYPE | MIIM_SUBMENU; + mii.fType = MFT_OWNERDRAW; + mii.hSubMenu = hMenuPopup; + } + else if (lpText == FM_SEPARATOR ) + { mii.fMask |= MIIM_ID | MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + } + else + { /* normal item */ + mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.fState = MFS_ENABLED | MFS_DEFAULT; + mii.fType = MFT_OWNERDRAW; + } + mii.wID = uID; + + InsertMenuItemW (hMenu, (UINT)-1, TRUE, &mii); + + /* set bFixedItems to true */ + MenuInfo.cbSize = sizeof(MENUINFO); + MenuInfo.fMask = MIM_MENUDATA; + + if (! GetMenuInfo(hMenu, &MenuInfo)) + return FALSE; + + menudata = (LPFMINFO)MenuInfo.dwMenuData; + if ((menudata == 0) || (MenuInfo.cbSize != sizeof(MENUINFO))) + { + ERR("menudata corrupt: %p %lu\n", menudata, MenuInfo.cbSize); + return 0; + } + + menudata->bFixedItems = TRUE; + SetMenuInfo(hMenu, &MenuInfo); + + return TRUE; + +} + +/**********************************************************************/ + +BOOL WINAPI FileMenu_AppendItemAW( + HMENU hMenu, + LPCVOID lpText, + UINT uID, + int icon, + HMENU hMenuPopup, + int nItemHeight) +{ + BOOL ret; + + if ((SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR)) || (lpText == NULL)) + ret = FileMenu_AppendItemW(hMenu, lpText, uID, icon, hMenuPopup, nItemHeight); + else + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, lpText, -1, NULL, 0 ); + LPWSTR lpszText = HeapAlloc ( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, lpText, -1, lpszText, len ); + ret = FileMenu_AppendItemW(hMenu, lpszText, uID, icon, hMenuPopup, nItemHeight); + HeapFree( GetProcessHeap(), 0, lpszText ); + } + + return ret; +} +/************************************************************************* + * FileMenu_InsertUsingPidl [SHELL32.110] + * + * NOTES + * uEnumFlags any SHCONTF flag + */ +int WINAPI FileMenu_InsertUsingPidl ( + HMENU hmenu, + UINT uID, + LPCITEMIDLIST pidl, + UINT uFlags, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback) +{ + TRACE("%p 0x%08x %p 0x%08x 0x%08x %p\n", + hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); + + pdump (pidl); + + bAbortInit = FALSE; + + FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); + + return FM_InitMenuPopup(hmenu, NULL); +} + +/************************************************************************* + * FileMenu_ReplaceUsingPidl [SHELL32.113] + * + * FIXME: the static items are deleted but won't be refreshed + */ +int WINAPI FileMenu_ReplaceUsingPidl( + HMENU hmenu, + UINT uID, + LPCITEMIDLIST pidl, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback) +{ + TRACE("%p 0x%08x %p 0x%08x %p\n", + hmenu, uID, pidl, uEnumFlags, lpfnCallback); + + FileMenu_DeleteAllItems (hmenu); + + FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback); + + return FM_InitMenuPopup(hmenu, NULL); +} + +/************************************************************************* + * FileMenu_Invalidate [SHELL32.111] + */ +void WINAPI FileMenu_Invalidate (HMENU hMenu) +{ + FIXME("%p\n",hMenu); +} + +/************************************************************************* + * FileMenu_FindSubMenuByPidl [SHELL32.106] + */ +HMENU WINAPI FileMenu_FindSubMenuByPidl( + HMENU hMenu, + LPCITEMIDLIST pidl) +{ + FIXME("%p %p\n",hMenu, pidl); + return 0; +} + +/************************************************************************* + * FileMenu_AppendFilesForPidl [SHELL32.124] + */ +int WINAPI FileMenu_AppendFilesForPidl( + HMENU hmenu, + LPCITEMIDLIST pidl, + BOOL bAddSeperator) +{ + LPFMINFO menudata; + + menudata = FM_GetMenuInfo(hmenu); + + menudata->bInitialized = FALSE; + + FM_InitMenuPopup(hmenu, pidl); + + if (bAddSeperator) + FileMenu_AppendItemW (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT); + + TRACE("%p %p 0x%08x\n",hmenu, pidl,bAddSeperator); + + return 0; +} +/************************************************************************* + * FileMenu_AddFilesForPidl [SHELL32.125] + * + * NOTES + * uEnumFlags any SHCONTF flag + */ +int WINAPI FileMenu_AddFilesForPidl ( + HMENU hmenu, + UINT uReserved, + UINT uID, + LPCITEMIDLIST pidl, + UINT uFlags, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback) +{ + TRACE("%p 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n", + hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback); + + return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback); + +} + + +/************************************************************************* + * FileMenu_TrackPopupMenuEx [SHELL32.116] + */ +BOOL WINAPI FileMenu_TrackPopupMenuEx ( + HMENU hMenu, + UINT uFlags, + int x, + int y, + HWND hWnd, + LPTPMPARAMS lptpm) +{ + TRACE("%p 0x%08x 0x%x 0x%x %p %p\n", + hMenu, uFlags, x, y, hWnd, lptpm); + return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm); +} + +/************************************************************************* + * FileMenu_GetLastSelectedItemPidls [SHELL32.107] + */ +BOOL WINAPI FileMenu_GetLastSelectedItemPidls( + UINT uReserved, + LPCITEMIDLIST *ppidlFolder, + LPCITEMIDLIST *ppidlItem) +{ + FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem); + return 0; +} + +#define FM_ICON_SIZE 16 +#define FM_Y_SPACE 4 +#define FM_SPACE1 4 +#define FM_SPACE2 2 +#define FM_LEFTBORDER 2 +#define FM_RIGHTBORDER 8 +/************************************************************************* + * FileMenu_MeasureItem [SHELL32.112] + */ +LRESULT WINAPI FileMenu_MeasureItem( + HWND hWnd, + LPMEASUREITEMSTRUCT lpmis) +{ + LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData); + HDC hdc = GetDC(hWnd); + SIZE size; + LPFMINFO menuinfo; + + TRACE("%p %p %s\n", hWnd, lpmis, debugstr_w(pMyItem->szItemText)); + + GetTextExtentPoint32W(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size); + + lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER; + lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE); + + /* add the menubitmap */ + menuinfo = FM_GetMenuInfo(pMyItem->hMenu); + if (menuinfo->nBorderWidth) + lpmis->itemWidth += menuinfo->nBorderWidth; + + TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight); + ReleaseDC (hWnd, hdc); + return 0; +} +/************************************************************************* + * FileMenu_DrawItem [SHELL32.105] + */ +LRESULT WINAPI FileMenu_DrawItem( + HWND hWnd, + LPDRAWITEMSTRUCT lpdis) +{ + LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData); + COLORREF clrPrevText, clrPrevBkgnd; + int xi,yi,xt,yt; + HIMAGELIST hImageList; + RECT TextRect, BorderRect; + LPFMINFO menuinfo; + + TRACE("%p %p %s\n", hWnd, lpdis, debugstr_w(pMyItem->szItemText)); + + if (lpdis->itemState & ODS_SELECTED) + { + clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)); + clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT)); + } + else + { + clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT)); + clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU)); + } + + CopyRect(&TextRect, &(lpdis->rcItem)); + + /* add the menubitmap */ + menuinfo = FM_GetMenuInfo(pMyItem->hMenu); + if (menuinfo->nBorderWidth) + TextRect.left += menuinfo->nBorderWidth; + + BorderRect.right = menuinfo->nBorderWidth; +/* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor)); +*/ + TextRect.left += FM_LEFTBORDER; + xi = TextRect.left + FM_SPACE1; + yi = TextRect.top + FM_Y_SPACE/2; + TextRect.bottom -= FM_Y_SPACE/2; + + xt = xi + FM_ICON_SIZE + FM_SPACE2; + yt = yi; + + ExtTextOutW (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL); + + Shell_GetImageList(0, &hImageList); + ImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL); + + TRACE("-- 0x%04lx 0x%04lx 0x%04lx 0x%04lx\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom); + + SetTextColor(lpdis->hDC, clrPrevText); + SetBkColor(lpdis->hDC, clrPrevBkgnd); + + return TRUE; +} + +/************************************************************************* + * FileMenu_InitMenuPopup [SHELL32.109] + * + * NOTES + * The filemenu is a ownerdrawn menu. Call this function responding to + * WM_INITPOPUPMENU + * + */ +BOOL WINAPI FileMenu_InitMenuPopup (HMENU hmenu) +{ + FM_InitMenuPopup(hmenu, NULL); + return TRUE; +} + +/************************************************************************* + * FileMenu_HandleMenuChar [SHELL32.108] + */ +LRESULT WINAPI FileMenu_HandleMenuChar( + HMENU hMenu, + WPARAM wParam) +{ + FIXME("%p 0x%08x\n",hMenu,wParam); + return 0; +} + +/************************************************************************* + * FileMenu_DeleteAllItems [SHELL32.104] + * + * NOTES + * exported by name + */ +BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu) +{ + MENUITEMINFOW mii; + LPFMINFO menudata; + + int i; + + TRACE("%p\n", hmenu); + + ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_SUBMENU|MIIM_DATA; + + for (i = 0; i < GetMenuItemCount( hmenu ); i++) + { GetMenuItemInfoW(hmenu, i, TRUE, &mii ); + + if (mii.dwItemData) + SHFree((LPFMINFO)mii.dwItemData); + + if (mii.hSubMenu) + FileMenu_Destroy(mii.hSubMenu); + } + + while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){}; + + menudata = FM_GetMenuInfo(hmenu); + + menudata->bInitialized = FALSE; + + return TRUE; +} + +/************************************************************************* + * FileMenu_DeleteItemByCmd [SHELL32.117] + * + */ +BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID) +{ + MENUITEMINFOW mii; + + TRACE("%p 0x%08x\n", hMenu, uID); + + ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_SUBMENU; + + GetMenuItemInfoW(hMenu, uID, FALSE, &mii ); + if ( mii.hSubMenu ) + { + /* FIXME: Do what? */ + } + + DeleteMenu(hMenu, MF_BYCOMMAND, uID); + return TRUE; +} + +/************************************************************************* + * FileMenu_DeleteItemByIndex [SHELL32.140] + */ +BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos) +{ + MENUITEMINFOW mii; + + TRACE("%p 0x%08x\n", hMenu, uPos); + + ZeroMemory ( &mii, sizeof(MENUITEMINFOW)); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_SUBMENU; + + GetMenuItemInfoW(hMenu, uPos, TRUE, &mii ); + if ( mii.hSubMenu ) + { + /* FIXME: Do what? */ + } + + DeleteMenu(hMenu, MF_BYPOSITION, uPos); + return TRUE; +} + +/************************************************************************* + * FileMenu_DeleteItemByFirstID [SHELL32.141] + */ +BOOL WINAPI FileMenu_DeleteItemByFirstID( + HMENU hMenu, + UINT uID) +{ + TRACE("%p 0x%08x\n", hMenu, uID); + return 0; +} + +/************************************************************************* + * FileMenu_DeleteSeparator [SHELL32.142] + */ +BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu) +{ + TRACE("%p\n", hMenu); + return 0; +} + +/************************************************************************* + * FileMenu_EnableItemByCmd [SHELL32.143] + */ +BOOL WINAPI FileMenu_EnableItemByCmd( + HMENU hMenu, + UINT uID, + BOOL bEnable) +{ + TRACE("%p 0x%08x 0x%08x\n", hMenu, uID,bEnable); + return 0; +} + +/************************************************************************* + * FileMenu_GetItemExtent [SHELL32.144] + * + * NOTES + * if the menu is too big, entries are getting cut away!! + */ +DWORD WINAPI FileMenu_GetItemExtent (HMENU hMenu, UINT uPos) +{ RECT rect; + + FIXME("%p 0x%08x\n", hMenu, uPos); + + if (GetMenuItemRect(0, hMenu, uPos, &rect)) + { FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx\n", + rect.right, rect.left, rect.top, rect.bottom); + return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom); + } + return 0x00100010; /*FIXME*/ +} + +/************************************************************************* + * FileMenu_AbortInitMenu [SHELL32.120] + * + */ +void WINAPI FileMenu_AbortInitMenu (void) +{ TRACE("\n"); + bAbortInit = TRUE; +} + +/************************************************************************* + * SHFind_InitMenuPopup [SHELL32.149] + * + * + * PARAMETERS + * hMenu [in] handle of menu previously created + * hWndParent [in] parent window + * w [in] no pointer (0x209 over here) perhaps menu IDs ??? + * x [in] no pointer (0x226 over here) + * + * RETURNS + * LPXXXXX pointer to struct containing a func addr at offset 8 + * or NULL at failure. + */ +LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD x) +{ FIXME("hmenu=%p hwnd=%p 0x%08lx 0x%08lx stub\n", + hMenu,hWndParent,w,x); + return NULL; /* this is supposed to be a pointer */ +} + +/************************************************************************* + * Shell_MergeMenus [SHELL32.67] + * + */ +BOOL _SHIsMenuSeparator(HMENU hm, int i) +{ + MENUITEMINFOW mii; + + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_TYPE; + mii.cch = 0; /* WARNING: We MUST initialize it to 0*/ + if (!GetMenuItemInfoW(hm, i, TRUE, &mii)) + { + return(FALSE); + } + + if (mii.fType & MFT_SEPARATOR) + { + return(TRUE); + } + + return(FALSE); +} + +/**********************************************************************/ + +HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags) +{ int nItem; + HMENU hmSubMenu; + BOOL bAlreadySeparated; + MENUITEMINFOW miiSrc; + WCHAR szName[256]; + UINT uTemp, uIDMax = uIDAdjust; + + TRACE("hmenu1=%p hmenu2=%p 0x%04x 0x%04x 0x%04x 0x%04lx\n", + hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags); + + if (!hmDst || !hmSrc) + { return uIDMax; + } + + nItem = GetMenuItemCount(hmDst); + + if (uInsert >= (UINT)nItem) /* insert position inside menu? */ + { + uInsert = (UINT)nItem; /* append on the end */ + bAlreadySeparated = TRUE; + } + else + { + bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert); + } + + if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) + { + /* Add a separator between the menus */ + InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + bAlreadySeparated = TRUE; + } + + + /* Go through the menu items and clone them*/ + for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--) + { + miiSrc.cbSize = sizeof(MENUITEMINFOW); + miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA; + + /* We need to reset this every time through the loop in case menus DON'T have IDs*/ + miiSrc.fType = MFT_STRING; + miiSrc.dwTypeData = szName; + miiSrc.dwItemData = 0; + miiSrc.cch = sizeof(szName)/sizeof(WCHAR); + + if (!GetMenuItemInfoW(hmSrc, nItem, TRUE, &miiSrc)) + { + continue; + } + +/* TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu); +*/ + if (miiSrc.fType & MFT_SEPARATOR) + { + /* This is a separator; don't put two of them in a row */ + if (bAlreadySeparated) + continue; + + bAlreadySeparated = TRUE; + } + else if (miiSrc.hSubMenu) + { + if (uFlags & MM_SUBMENUSHAVEIDS) + { + miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ + + if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ + continue; + + if (uIDMax <= miiSrc.wID) /* remember the highest ID */ + uIDMax = miiSrc.wID + 1; + } + else + { + miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */ + } + hmSubMenu = miiSrc.hSubMenu; + + miiSrc.hSubMenu = CreatePopupMenu(); + + if (!miiSrc.hSubMenu) return(uIDMax); + + uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS); + + if (uIDMax <= uTemp) + uIDMax = uTemp; + + bAlreadySeparated = FALSE; + } + else /* normal menu item */ + { + miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ + + if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ + continue; + + if (uIDMax <= miiSrc.wID) /* remember the highest ID */ + uIDMax = miiSrc.wID + 1; + + bAlreadySeparated = FALSE; + } + +/* TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu); +*/ + if (!InsertMenuItemW(hmDst, uInsert, TRUE, &miiSrc)) + { + return(uIDMax); + } + } + + /* Ensure the correct number of separators at the beginning of the + inserted menu items*/ + if (uInsert == 0) + { + if (bAlreadySeparated) + { + DeleteMenu(hmDst, uInsert, MF_BYPOSITION); + } + } + else + { + if (_SHIsMenuSeparator(hmDst, uInsert-1)) + { + if (bAlreadySeparated) + { + DeleteMenu(hmDst, uInsert, MF_BYPOSITION); + } + } + else + { + if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated) + { + /* Add a separator between the menus*/ + InsertMenuW(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + } + } + } + return(uIDMax); +} diff --git a/reactos/lib/shell32/shlview.c b/reactos/lib/shell32/shlview.c index 6c650802be0..aa01c94a881 100644 --- a/reactos/lib/shell32/shlview.c +++ b/reactos/lib/shell32/shlview.c @@ -1,2406 +1,2407 @@ -/* - * ShellView - * - * Copyright 1998,1999 - * - * This is the view visualizing the data provied by the shellfolder. - * No direct access to data from pidls should be done from here. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * FIXME: The order by part of the background context menu should be - * buily according to the columns shown. - * - * FIXME: Load/Save the view state from/into the stream provied by - * the ShellBrowser - * - * FIXME: CheckToolbar: handle the "new folder" and "folder up" button - * - * FIXME: ShellView_FillList: consider sort orders - * - * FIXME: implement the drag and drop in the old (msg-based) way - * - * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a - * Release() ??? - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "winerror.h" -#include "winbase.h" -#include "winnls.h" -#include "objbase.h" -#include "servprov.h" -#include "shlguid.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "undocshell.h" -#include "shresdef.h" -#include "wine/debug.h" - -#include "docobj.h" -#include "pidl.h" -#include "shell32_main.h" -#include "shellfolder.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -typedef struct -{ BOOL bIsAscending; - INT nHeaderID; - INT nLastHeaderID; -}LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO; - -typedef struct -{ - IShellViewVtbl* lpVtbl; - DWORD ref; - IOleCommandTargetVtbl* lpvtblOleCommandTarget; - IDropTargetVtbl* lpvtblDropTarget; - IDropSourceVtbl* lpvtblDropSource; - IViewObjectVtbl* lpvtblViewObject; - IShellFolder* pSFParent; - IShellFolder2* pSF2Parent; - IShellBrowser* pShellBrowser; - ICommDlgBrowser* pCommDlgBrowser; - HWND hWnd; /* SHELLDLL_DefView */ - HWND hWndList; /* ListView control */ - HWND hWndParent; - FOLDERSETTINGS FolderSettings; - HMENU hMenu; - UINT uState; - UINT cidl; - LPITEMIDLIST *apidl; - LISTVIEW_SORT_INFO ListViewSortInfo; - ULONG hNotify; /* change notification handle */ - HANDLE hAccel; -} IShellViewImpl; - -static struct IShellViewVtbl svvt; - -static struct IOleCommandTargetVtbl ctvt; -#define _IOleCommandTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblOleCommandTarget))) -#define _ICOM_THIS_From_IOleCommandTarget(class, name) class* This = (class*)(((char*)name)-_IOleCommandTarget_Offset); - -static struct IDropTargetVtbl dtvt; -#define _IDropTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropTarget))) -#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); - -static struct IDropSourceVtbl dsvt; -#define _IDropSource_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropSource))) -#define _ICOM_THIS_From_IDropSource(class, name) class* This = (class*)(((char*)name)-_IDropSource_Offset); - -static struct IViewObjectVtbl vovt; -#define _IViewObject_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblViewObject))) -#define _ICOM_THIS_From_IViewObject(class, name) class* This = (class*)(((char*)name)-_IViewObject_Offset); - -/* ListView Header ID's */ -#define LISTVIEW_COLUMN_NAME 0 -#define LISTVIEW_COLUMN_SIZE 1 -#define LISTVIEW_COLUMN_TYPE 2 -#define LISTVIEW_COLUMN_TIME 3 -#define LISTVIEW_COLUMN_ATTRIB 4 - -/*menu items */ -#define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500) -#define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501) -#define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502) - -#define ID_LISTVIEW 2000 - -#define SHV_CHANGE_NOTIFY WM_USER + 0x1111 - -/*windowsx.h */ -#define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp) -#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp) -#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp) - -extern void WINAPI _InsertMenuItem (HMENU hmenu, UINT indexMenu, BOOL fByPosition, - UINT wID, UINT fType, LPSTR dwTypeData, UINT fState); - -/* - Items merged into the toolbar and and the filemenu -*/ -typedef struct -{ int idCommand; - int iImage; - int idButtonString; - int idMenuString; - BYTE bState; - BYTE bStyle; -} MYTOOLINFO, *LPMYTOOLINFO; - -MYTOOLINFO Tools[] = -{ -{ FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON }, -{ FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON }, -{ FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON }, -{ FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON }, -{ -1, 0, 0, 0, 0, 0} -}; - -typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask); - -/********************************************************** - * IShellView_Constructor - */ -IShellView * IShellView_Constructor( IShellFolder * pFolder) -{ IShellViewImpl * sv; - sv=(IShellViewImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl)); - sv->ref=1; - sv->lpVtbl=&svvt; - sv->lpvtblOleCommandTarget=&ctvt; - sv->lpvtblDropTarget=&dtvt; - sv->lpvtblDropSource=&dsvt; - sv->lpvtblViewObject=&vovt; - - sv->pSFParent = pFolder; - if(pFolder) IShellFolder_AddRef(pFolder); - IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent); - - TRACE("(%p)->(%p)\n",sv, pFolder); - return (IShellView *) sv; -} - -/********************************************************** - * - * ##### helperfunctions for communication with ICommDlgBrowser ##### - */ -static BOOL IsInCommDlg(IShellViewImpl * This) -{ return(This->pCommDlgBrowser != NULL); -} - -static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl) -{ - HRESULT ret = S_OK; - - if ( IsInCommDlg(This) ) - { - TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl); - ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl); - TRACE("--0x%08lx\n", ret); - } - return ret; -} - -static HRESULT OnDefaultCommand(IShellViewImpl * This) -{ - HRESULT ret = S_FALSE; - - if (IsInCommDlg(This)) - { - TRACE("ICommDlgBrowser::OnDefaultCommand\n"); - ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This); - TRACE("--\n"); - } - return ret; -} - -static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags) -{ - HRESULT ret = S_FALSE; - - if (IsInCommDlg(This)) - { - TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags); - ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags); - TRACE("--\n"); - } - return ret; -} -/********************************************************** - * set the toolbar of the filedialog buttons - * - * - activates the buttons from the shellbrowser according to - * the view state - */ -static void CheckToolbar(IShellViewImpl * This) -{ - LRESULT result; - - TRACE("\n"); - - if (IsInCommDlg(This)) - { - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON, - FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result); - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON, - FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result); - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON, - FCIDM_TB_SMALLICON, TRUE, &result); - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON, - FCIDM_TB_REPORTVIEW, TRUE, &result); - } -} - -/********************************************************** - * - * ##### helperfunctions for initializing the view ##### - */ -/********************************************************** - * change the style of the listview control - */ -static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove) -{ - DWORD tmpstyle; - - TRACE("(%p)\n", This); - - tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE); - SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove)); -} - -/********************************************************** -* ShellView_CreateList() -* -* - creates the list view window -*/ -static BOOL ShellView_CreateList (IShellViewImpl * This) -{ DWORD dwStyle, dwExStyle; - - TRACE("%p\n",This); - - dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | - LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE; - dwExStyle = WS_EX_CLIENTEDGE; - - switch (This->FolderSettings.ViewMode) - { - case FVM_ICON: dwStyle |= LVS_ICON; break; - case FVM_DETAILS: dwStyle |= LVS_REPORT; break; - case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break; - case FVM_LIST: dwStyle |= LVS_LIST; break; - default: dwStyle |= LVS_LIST; break; - } - - if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE; - if (This->FolderSettings.fFlags & FWF_DESKTOP) - This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL; - if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL; - if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE) - dwExStyle &= ~WS_EX_CLIENTEDGE; - - This->hWndList=CreateWindowExA( dwExStyle, - WC_LISTVIEWA, - NULL, - dwStyle, - 0,0,0,0, - This->hWnd, - (HMENU)ID_LISTVIEW, - shell32_hInstance, - NULL); - - if(!This->hWndList) - return FALSE; - - This->ListViewSortInfo.bIsAscending = TRUE; - This->ListViewSortInfo.nHeaderID = -1; - This->ListViewSortInfo.nLastHeaderID = -1; - - if (This->FolderSettings.fFlags & FWF_DESKTOP) { - if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */ - ListView_SetTextBkColor(This->hWndList, CLR_NONE); - else - ListView_SetTextBkColor(This->hWndList, GetSysColor(COLOR_DESKTOP)); - - ListView_SetTextColor(This->hWndList, RGB(255,255,255)); - } - - /* UpdateShellSettings(); */ - return TRUE; -} - -/********************************************************** -* ShellView_InitList() -* -* - adds all needed columns to the shellview -*/ -static BOOL ShellView_InitList(IShellViewImpl * This) -{ - LVCOLUMNA lvColumn; - SHELLDETAILS sd; - int i; - char szTemp[50]; - - TRACE("%p\n",This); - - ListView_DeleteAllItems(This->hWndList); - - lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; - lvColumn.pszText = szTemp; - - if (This->pSF2Parent) - { - for (i=0; 1; i++) - { - if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd))) - break; - lvColumn.fmt = sd.fmt; - lvColumn.cx = sd.cxChar*8; /* chars->pixel */ - StrRetToStrNA( szTemp, 50, &sd.str, NULL); - ListView_InsertColumnA(This->hWndList, i, &lvColumn); - } - } - else - { - FIXME("no SF2\n"); - } - - ListView_SetImageList(This->hWndList, ShellSmallIconList, LVSIL_SMALL); - ListView_SetImageList(This->hWndList, ShellBigIconList, LVSIL_NORMAL); - - return TRUE; -} -/********************************************************** -* ShellView_CompareItems() -* -* NOTES -* internal, CALLBACK for DSA_Sort -*/ -static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) -{ - int ret; - TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData); - - if(!lpData) return 0; - - ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2)); - TRACE("ret=%i\n",ret); - return ret; -} - -/************************************************************************* - * ShellView_ListViewCompareItems - * - * Compare Function for the Listview (FileOpen Dialog) - * - * PARAMS - * lParam1 [I] the first ItemIdList to compare with - * lParam2 [I] the second ItemIdList to compare with - * lpData [I] The column ID for the header Ctrl to process - * - * RETURNS - * A negative value if the first item should precede the second, - * a positive value if the first item should follow the second, - * or zero if the two items are equivalent - * - * NOTES - * FIXME: function does what ShellView_CompareItems is supposed to do. - * unify it and figure out how to use the undocumented first parameter - * of IShellFolder_CompareIDs to do the job this function does and - * move this code to IShellFolder. - * make LISTVIEW_SORT_INFO obsolete - * the way this function works is only usable if we had only - * filesystemfolders (25/10/99 jsch) - */ -static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) -{ - INT nDiff=0; - FILETIME fd1, fd2; - char strName1[MAX_PATH], strName2[MAX_PATH]; - BOOL bIsFolder1, bIsFolder2,bIsBothFolder; - LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1; - LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2; - LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData; - - - bIsFolder1 = _ILIsFolder(pItemIdList1); - bIsFolder2 = _ILIsFolder(pItemIdList2); - bIsBothFolder = bIsFolder1 && bIsFolder2; - - /* When sorting between a File and a Folder, the Folder gets sorted first */ - if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder) - { - nDiff = bIsFolder1 ? -1 : 1; - } - else - { - /* Sort by Time: Folders or Files can be sorted */ - - if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME) - { - _ILGetFileDateTime(pItemIdList1, &fd1); - _ILGetFileDateTime(pItemIdList2, &fd2); - nDiff = CompareFileTime(&fd2, &fd1); - } - /* Sort by Attribute: Folder or Files can be sorted */ - else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB) - { - _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH); - _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH); - nDiff = strcasecmp(strName1, strName2); - } - /* Sort by FileName: Folder or Files can be sorted */ - else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder) - { - /* Sort by Text */ - _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); - _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); - nDiff = strcasecmp(strName1, strName2); - } - /* Sort by File Size, Only valid for Files */ - else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE) - { - nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0)); - } - /* Sort by File Type, Only valid for Files */ - else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE) - { - /* Sort by Type */ - _ILGetFileType(pItemIdList1, strName1, MAX_PATH); - _ILGetFileType(pItemIdList2, strName2, MAX_PATH); - nDiff = strcasecmp(strName1, strName2); - } - } - /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */ - - if(nDiff == 0) - { - _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); - _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); - nDiff = strcasecmp(strName1, strName2); - } - - if(!pSortInfo->bIsAscending) - { - nDiff = -nDiff; - } - - return nDiff; - -} - -/********************************************************** -* LV_FindItemByPidl() -*/ -static int LV_FindItemByPidl( - IShellViewImpl * This, - LPCITEMIDLIST pidl) -{ - LVITEMA lvItem; - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.mask = LVIF_PARAM; - for(lvItem.iItem = 0; ListView_GetItemA(This->hWndList, &lvItem); lvItem.iItem++) - { - LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam; - HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl); - if(SUCCEEDED(hr) && !HRESULT_CODE(hr)) - { - return lvItem.iItem; - } - } - return -1; -} - -/********************************************************** -* LV_AddItem() -*/ -static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl) -{ - LVITEMA lvItem; - - TRACE("(%p)(pidl=%p)\n", This, pidl); - - ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/ - lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ - lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/ - lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/ - lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/ - lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ - return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE; -} - -/********************************************************** -* LV_DeleteItem() -*/ -static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl) -{ - int nIndex; - - TRACE("(%p)(pidl=%p)\n", This, pidl); - - nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl)); - return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE; -} - -/********************************************************** -* LV_RenameItem() -*/ -static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew ) -{ - int nItem; - LVITEMA lvItem; - - TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew); - - nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld)); - if ( -1 != nItem ) - { - ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/ - lvItem.mask = LVIF_PARAM; /* only the pidl */ - lvItem.iItem = nItem; - ListView_GetItemA(This->hWndList, &lvItem); - - SHFree((LPITEMIDLIST)lvItem.lParam); - lvItem.mask = LVIF_PARAM; - lvItem.iItem = nItem; - lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */ - ListView_SetItemA(This->hWndList, &lvItem); - ListView_Update(This->hWndList, nItem); - return TRUE; /* FIXME: better handling */ - } - return FALSE; -} -/********************************************************** -* ShellView_FillList() -* -* - gets the objectlist from the shellfolder -* - sorts the list -* - fills the list into the view -*/ - -static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg ) -{ - LPITEMIDLIST pidl = ptr; - IShellViewImpl *This = arg; - /* in a commdlg This works as a filemask*/ - if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl); - SHFree(pidl); - return TRUE; -} - -static HRESULT ShellView_FillList(IShellViewImpl * This) -{ - LPENUMIDLIST pEnumIDList; - LPITEMIDLIST pidl; - DWORD dwFetched; - HRESULT hRes; - HDPA hdpa; - - TRACE("%p\n",This); - - /* get the itemlist from the shfolder*/ - hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList); - if (hRes != S_OK) - { - if (hRes==S_FALSE) - return(NOERROR); - return(hRes); - } - - /* create a pointer array */ - hdpa = DPA_Create(16); - if (!hdpa) - { - return(E_OUTOFMEMORY); - } - - /* copy the items into the array*/ - while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched) - { - if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) - { - SHFree(pidl); - } - } - - /* sort the array */ - DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent); - - /*turn the listview's redrawing off*/ - SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0); - - DPA_DestroyCallback( hdpa, fill_list, This ); - - /*turn the listview's redrawing back on and force it to draw*/ - SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0); - - IEnumIDList_Release(pEnumIDList); /* destroy the list*/ - - return S_OK; -} - -/********************************************************** -* ShellView_OnCreate() -*/ -static LRESULT ShellView_OnCreate(IShellViewImpl * This) -{ - IDropTarget* pdt; - SHChangeNotifyEntry ntreg; - IPersistFolder2 * ppf2 = NULL; - - TRACE("%p\n",This); - - if(ShellView_CreateList(This)) - { - if(ShellView_InitList(This)) - { - ShellView_FillList(This); - } - } - - if (SUCCEEDED(IShellFolder_CreateViewObject(This->pSFParent, This->hWnd, &IID_IDropTarget, (LPVOID*)&pdt))) - { - RegisterDragDrop(This->hWnd, pdt); - IDropTarget_Release(pdt); - } - - /* register for receiving notifications */ - IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2); - if (ppf2) - { - IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl); - ntreg.fRecursive = TRUE; - This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg); - SHFree((LPITEMIDLIST)ntreg.pidl); - IPersistFolder2_Release(ppf2); - } - - This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel"); - - return S_OK; -} - -/********************************************************** - * #### Handling of the menus #### - */ - -/********************************************************** -* ShellView_BuildFileMenu() -*/ -static HMENU ShellView_BuildFileMenu(IShellViewImpl * This) -{ CHAR szText[MAX_PATH]; - MENUITEMINFOA mii; - int nTools,i; - HMENU hSubMenu; - - TRACE("(%p)\n",This); - - hSubMenu = CreatePopupMenu(); - if(hSubMenu) - { /*get the number of items in our global array*/ - for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){} - - /*add the menu items*/ - for(i = 0; i < nTools; i++) - { - LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); - - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; - - if(BTNS_SEP != Tools[i].bStyle) /* no separator*/ - { - mii.fType = MFT_STRING; - mii.fState = MFS_ENABLED; - mii.dwTypeData = szText; - mii.wID = Tools[i].idCommand; - } - else - { - mii.fType = MFT_SEPARATOR; - } - /* tack This item onto the end of the menu */ - InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii); - } - } - TRACE("-- return (menu=%p)\n",hSubMenu); - return hSubMenu; -} -/********************************************************** -* ShellView_MergeFileMenu() -*/ -static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu) -{ TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu); - - if(hSubMenu) - { /*insert This item at the beginning of the menu */ - _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED); - - } - TRACE("--\n"); -} - -/********************************************************** -* ShellView_MergeViewMenu() -*/ - -static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu) -{ MENUITEMINFOA mii; - - TRACE("(%p)->(submenu=%p)\n",This,hSubMenu); - - if(hSubMenu) - { /*add a separator at the correct position in the menu*/ - _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); - - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA; - mii.fType = MFT_STRING; - mii.dwTypeData = "View"; - mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001"); - InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); - } -} - -/********************************************************** -* ShellView_GetSelections() -* -* - fills the this->apidl list with the selected objects -* -* RETURNS -* number of selected items -*/ -static UINT ShellView_GetSelections(IShellViewImpl * This) -{ - LVITEMA lvItem; - UINT i = 0; - - if (This->apidl) - { - SHFree(This->apidl); - } - - This->cidl = ListView_GetSelectedCount(This->hWndList); - This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST)); - - TRACE("selected=%i\n", This->cidl); - - if(This->apidl) - { - TRACE("-- Items selected =%u\n", This->cidl); - - ZeroMemory(&lvItem, sizeof(lvItem)); - lvItem.mask = LVIF_STATE | LVIF_PARAM; - lvItem.stateMask = LVIS_SELECTED; - - while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl)) - { - if(lvItem.state & LVIS_SELECTED) - { - This->apidl[i] = (LPITEMIDLIST)lvItem.lParam; - i++; - TRACE("-- selected Item found\n"); - } - lvItem.iItem++; - } - } - return This->cidl; - -} - -/********************************************************** - * ShellView_OpenSelectedItems() - */ -static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This) -{ - static UINT CF_IDLIST = 0; - HRESULT hr; - IDataObject* selection; - FORMATETC fetc; - STGMEDIUM stgm; - LPIDA pIDList; - LPCITEMIDLIST parent_pidl; - int i; - - if (0 == ShellView_GetSelections(This)) - { - return S_OK; - } - hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, - (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, - 0, (LPVOID *)&selection); - if (FAILED(hr)) - return hr; - - if (0 == CF_IDLIST) - { - CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); - } - fetc.cfFormat = CF_IDLIST; - fetc.ptd = NULL; - fetc.dwAspect = DVASPECT_CONTENT; - fetc.lindex = -1; - fetc.tymed = TYMED_HGLOBAL; - - hr = IDataObject_QueryGetData(selection, &fetc); - if (FAILED(hr)) - return hr; - - hr = IDataObject_GetData(selection, &fetc, &stgm); - if (FAILED(hr)) - return hr; - - pIDList = GlobalLock(stgm.u.hGlobal); - - parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]); - for (i = pIDList->cidl; i > 0; --i) - { - LPCITEMIDLIST pidl; - SFGAOF attribs; - - pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]); - - attribs = SFGAO_FOLDER; - hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs); - - if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER)) - { - SHELLEXECUTEINFOA shexinfo; - - shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA); - shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */ - shexinfo.hwnd = NULL; - shexinfo.lpVerb = NULL; - shexinfo.lpFile = NULL; - shexinfo.lpParameters = NULL; - shexinfo.lpDirectory = NULL; - shexinfo.nShow = SW_NORMAL; - shexinfo.lpIDList = ILCombine(parent_pidl, pidl); - - ShellExecuteExA(&shexinfo); /* Discard error/success info */ - - ILFree((LPITEMIDLIST)shexinfo.lpIDList); - } - } - - GlobalUnlock(stgm.u.hGlobal); - ReleaseStgMedium(&stgm); - - IDataObject_Release(selection); - - return S_OK; -} - -/********************************************************** - * ShellView_DoContextMenu() - */ -static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault) -{ UINT uCommand; - DWORD wFlags; - HMENU hMenu; - BOOL fExplore = FALSE; - HWND hwndTree = 0; - LPCONTEXTMENU pContextMenu = NULL; - IContextMenu2 *pCM = NULL; - CMINVOKECOMMANDINFO cmi; - - TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault); - - /* look, what's selected and create a context menu object of it*/ - if( ShellView_GetSelections(This) ) - { - IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl, - (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu); - - if(pContextMenu) - { - TRACE("-- pContextMenu\n"); - hMenu = CreatePopupMenu(); - - if( hMenu ) - { - /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/ - if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree) - { - TRACE("-- explore mode\n"); - fExplore = TRUE; - } - - /* build the flags depending on what we can do with the selected item */ - wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0); - - /* let the ContextMenu merge its items in */ - if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags ))) - { - if (This->FolderSettings.fFlags & FWF_DESKTOP) - SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); - - if( bDefault ) - { - TRACE("-- get menu default command\n"); - uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS); - } - else - { - TRACE("-- track popup\n"); - uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); - } - - if(uCommand > 0) - { - TRACE("-- uCommand=%u\n", uCommand); - if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This)) - { - TRACE("-- dlg: OnDefaultCommand\n"); - if (FAILED(OnDefaultCommand(This))) - { - ShellView_OpenSelectedItems(This); - } - } - else - { - TRACE("-- explore -- invoke command\n"); - ZeroMemory(&cmi, sizeof(cmi)); - cmi.cbSize = sizeof(cmi); - cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */ - cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); - IContextMenu_InvokeCommand(pContextMenu, &cmi); - } - } - DestroyMenu(hMenu); - } - } - if (pContextMenu) - IContextMenu_Release(pContextMenu); - } - } - else /* background context menu */ - { - hMenu = CreatePopupMenu(); - - pCM = ISvBgCm_Constructor(This->pSFParent); - IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); - - uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); - DestroyMenu(hMenu); - - TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand); - - ZeroMemory(&cmi, sizeof(cmi)); - cmi.cbSize = sizeof(cmi); - cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); - cmi.hwnd = This->hWndParent; - IContextMenu2_InvokeCommand(pCM, &cmi); - - IContextMenu2_Release(pCM); - } -} - -/********************************************************** - * ##### message handling ##### - */ - -/********************************************************** -* ShellView_OnSize() -*/ -static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight) -{ - TRACE("%p width=%u height=%u\n",This, wWidth,wHeight); - - /*resize the ListView to fit our window*/ - if(This->hWndList) - { - MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE); - } - - return S_OK; -} -/********************************************************** -* ShellView_OnDeactivate() -* -* NOTES -* internal -*/ -static void ShellView_OnDeactivate(IShellViewImpl * This) -{ - TRACE("%p\n",This); - - if(This->uState != SVUIA_DEACTIVATE) - { - if(This->hMenu) - { - IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0); - IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu); - DestroyMenu(This->hMenu); - This->hMenu = 0; - } - - This->uState = SVUIA_DEACTIVATE; - } -} - -/********************************************************** -* ShellView_OnActivate() -*/ -static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState) -{ OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} }; - MENUITEMINFOA mii; - CHAR szText[MAX_PATH]; - - TRACE("%p uState=%x\n",This,uState); - - /*don't do anything if the state isn't really changing */ - if(This->uState == uState) - { - return S_OK; - } - - ShellView_OnDeactivate(This); - - /*only do This if we are active */ - if(uState != SVUIA_DEACTIVATE) - { - /*merge the menus */ - This->hMenu = CreateMenu(); - - if(This->hMenu) - { - IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw); - TRACE("-- after fnInsertMenusSB\n"); - - /*build the top level menu get the menu item's text*/ - strcpy(szText,"dummy 31"); - - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; - mii.fType = MFT_STRING; - mii.fState = MFS_ENABLED; - mii.dwTypeData = szText; - mii.hSubMenu = ShellView_BuildFileMenu(This); - - /*insert our menu into the menu bar*/ - if(mii.hSubMenu) - { - InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii); - } - - /*get the view menu so we can merge with it*/ - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU; - - if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii)) - { - ShellView_MergeViewMenu(This, mii.hSubMenu); - } - - /*add the items that should only be added if we have the focus*/ - if(SVUIA_ACTIVATE_FOCUS == uState) - { - /*get the file menu so we can merge with it */ - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU; - - if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii)) - { - ShellView_MergeFileMenu(This, mii.hSubMenu); - } - } - TRACE("-- before fnSetMenuSB\n"); - IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd); - } - } - This->uState = uState; - TRACE("--\n"); - return S_OK; -} - -/********************************************************** -* ShellView_OnSetFocus() -* -*/ -static LRESULT ShellView_OnSetFocus(IShellViewImpl * This) -{ - TRACE("%p\n",This); - - /* Tell the browser one of our windows has received the focus. This - should always be done before merging menus (OnActivate merges the - menus) if one of our windows has the focus.*/ - - IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This); - ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS); - - /* Set the focus to the listview */ - SetFocus(This->hWndList); - - /* Notify the ICommDlgBrowser interface */ - OnStateChange(This,CDBOSC_SETFOCUS); - - return 0; -} - -/********************************************************** -* ShellView_OnKillFocus() -*/ -static LRESULT ShellView_OnKillFocus(IShellViewImpl * This) -{ - TRACE("(%p) stub\n",This); - - ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS); - /* Notify the ICommDlgBrowser */ - OnStateChange(This,CDBOSC_KILLFOCUS); - - return 0; -} - -/********************************************************** -* ShellView_OnCommand() -* -* NOTES -* the CmdID's are the ones from the context menu -*/ -static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd) -{ - TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd); - - switch(dwCmdID) - { - case FCIDM_SHVIEW_SMALLICON: - This->FolderSettings.ViewMode = FVM_SMALLICON; - SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK); - CheckToolbar(This); - break; - - case FCIDM_SHVIEW_BIGICON: - This->FolderSettings.ViewMode = FVM_ICON; - SetStyle (This, LVS_ICON, LVS_TYPEMASK); - CheckToolbar(This); - break; - - case FCIDM_SHVIEW_LISTVIEW: - This->FolderSettings.ViewMode = FVM_LIST; - SetStyle (This, LVS_LIST, LVS_TYPEMASK); - CheckToolbar(This); - break; - - case FCIDM_SHVIEW_REPORTVIEW: - This->FolderSettings.ViewMode = FVM_DETAILS; - SetStyle (This, LVS_REPORT, LVS_TYPEMASK); - CheckToolbar(This); - break; - - /* the menu-ID's for sorting are 0x30... see shrec.rc */ - case 0x30: - case 0x31: - case 0x32: - case 0x33: - This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30); - This->ListViewSortInfo.bIsAscending = TRUE; - This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID; - ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo))); - break; - - default: - TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID); - } - return 0; -} - -/********************************************************** -* ShellView_OnNotify() -*/ - -static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh) -{ LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh; - NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh; - LPITEMIDLIST pidl; - - TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code); - - switch(lpnmh->code) - { - case NM_SETFOCUS: - TRACE("-- NM_SETFOCUS %p\n",This); - ShellView_OnSetFocus(This); - break; - - case NM_KILLFOCUS: - TRACE("-- NM_KILLFOCUS %p\n",This); - ShellView_OnDeactivate(This); - /* Notify the ICommDlgBrowser interface */ - OnStateChange(This,CDBOSC_KILLFOCUS); - break; - - case NM_CUSTOMDRAW: - TRACE("-- NM_CUSTOMDRAW %p\n",This); - return CDRF_DODEFAULT; - - case NM_RELEASEDCAPTURE: - TRACE("-- NM_RELEASEDCAPTURE %p\n",This); - break; - - case NM_CLICK: - TRACE("-- NM_CLICK %p\n",This); - break; - - case NM_RCLICK: - TRACE("-- NM_RCLICK %p\n",This); - break; - - case HDN_ENDTRACKA: - TRACE("-- HDN_ENDTRACKA %p\n",This); - /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0); - nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/ - break; - - case LVN_DELETEITEM: - TRACE("-- LVN_DELETEITEM %p\n",This); - SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/ - break; - - case LVN_DELETEALLITEMS: - TRACE("-- LVN_DELETEALLITEMS %p\n",This); - return FALSE; - - case LVN_INSERTITEM: - TRACE("-- LVN_INSERTITEM (STUB)%p\n",This); - break; - - case LVN_ITEMACTIVATE: - TRACE("-- LVN_ITEMACTIVATE %p\n",This); - OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ - ShellView_DoContextMenu(This, 0, 0, TRUE); - break; - - case LVN_COLUMNCLICK: - This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem; - if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID) - { - This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending; - } - else - { - This->ListViewSortInfo.bIsAscending = TRUE; - } - This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID; - - ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo))); - break; - - case LVN_GETDISPINFOA: - case LVN_GETDISPINFOW: - TRACE("-- LVN_GETDISPINFO %p\n",This); - pidl = (LPITEMIDLIST)lpdi->item.lParam; - - if(lpdi->item.mask & LVIF_TEXT) /* text requested */ - { - if (This->pSF2Parent) - { - SHELLDETAILS sd; - IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd); - if (lpnmh->code == LVN_GETDISPINFOA) - { - StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); - TRACE("-- text=%s\n",lpdi->item.pszText); - } - else /* LVN_GETDISPINFOW */ - { - StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); - TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText))); - } - } - else - { - FIXME("no SF2\n"); - } - } - if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ - { - lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0); - } - break; - - case LVN_ITEMCHANGED: - TRACE("-- LVN_ITEMCHANGED %p\n",This); - OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ - break; - - case LVN_BEGINDRAG: - case LVN_BEGINRDRAG: - TRACE("-- LVN_BEGINDRAG\n"); - - if (ShellView_GetSelections(This)) - { - IDataObject * pda; - DWORD dwAttributes = SFGAO_CANLINK; - DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE; - - if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda))) - { - IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */ - - if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes))) - { - if (dwAttributes & SFGAO_CANLINK) - { - dwEffect |= DROPEFFECT_LINK; - } - } - - if (pds) - { - DWORD dwEffect; - DoDragDrop(pda, pds, dwEffect, &dwEffect); - } - IDataObject_Release(pda); - } - } - break; - - case LVN_BEGINLABELEDITA: - { - DWORD dwAttr = SFGAO_CANRENAME; - pidl = (LPITEMIDLIST)lpdi->item.lParam; - - TRACE("-- LVN_BEGINLABELEDITA %p\n",This); - - IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr); - if (SFGAO_CANRENAME & dwAttr) - { - return FALSE; - } - return TRUE; - } - break; - - case LVN_ENDLABELEDITA: - { - TRACE("-- LVN_ENDLABELEDITA %p\n",This); - if (lpdi->item.pszText) - { - HRESULT hr; - WCHAR wszNewName[MAX_PATH]; - LVITEMA lvItem; - - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.iItem = lpdi->item.iItem; - lvItem.mask = LVIF_PARAM; - ListView_GetItemA(This->hWndList, &lvItem); - - pidl = (LPITEMIDLIST)lpdi->item.lParam; - if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH )) - wszNewName[MAX_PATH-1] = 0; - hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl); - - if(SUCCEEDED(hr) && pidl) - { - lvItem.mask = LVIF_PARAM; - lvItem.lParam = (LPARAM)pidl; - ListView_SetItemA(This->hWndList, &lvItem); - return TRUE; - } - } - return FALSE; - } - break; - - case LVN_KEYDOWN: - { - /* MSG msg; - msg.hwnd = This->hWnd; - msg.message = WM_KEYDOWN; - msg.wParam = plvKeyDown->wVKey; - msg.lParam = 0; - msg.time = 0; - msg.pt = 0;*/ - - LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh; - - /* initiate a rename of the selected file or directory */ - if(plvKeyDown->wVKey == VK_F2) - { - /* see how many files are selected */ - int i = ListView_GetSelectedCount(This->hWndList); - - /* get selected item */ - if(i == 1) - { - /* get selected item */ - i = ListView_GetNextItem(This->hWndList, -1, - LVNI_SELECTED); - - ListView_EnsureVisible(This->hWndList, i, 0); - ListView_EditLabelA(This->hWndList, i); - } - } -#if 0 - TranslateAccelerator(This->hWnd, This->hAccel, &msg) -#endif - else if(plvKeyDown->wVKey == VK_DELETE) - { - UINT i; - int item_index; - LVITEMA item; - LPITEMIDLIST* pItems; - ISFHelper *psfhlp; - - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, - (LPVOID*)&psfhlp); - - if(!(i = ListView_GetSelectedCount(This->hWndList))) - break; - - /* allocate memory for the pidl array */ - pItems = HeapAlloc(GetProcessHeap(), 0, - sizeof(LPITEMIDLIST) * i); - - /* retrieve all selected items */ - i = 0; - item_index = -1; - while(ListView_GetSelectedCount(This->hWndList) > i) - { - /* get selected item */ - item_index = ListView_GetNextItem(This->hWndList, - item_index, LVNI_SELECTED); - item.iItem = item_index; - item.mask |= LVIF_PARAM; - ListView_GetItemA(This->hWndList, &item); - - /* get item pidl */ - pItems[i] = (LPITEMIDLIST)item.lParam; - - i++; - } - - /* perform the item deletion */ - ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems); - - /* free pidl array memory */ - HeapFree(GetProcessHeap(), 0, pItems); - } - else - FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey); - } - break; - - default: - TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code); - break; - } - return 0; -} - -/********************************************************** -* ShellView_OnChange() -*/ - -static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId) -{ - - TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId); - switch(wEventId) - { - case SHCNE_MKDIR: - case SHCNE_CREATE: - LV_AddItem(This, Pidls[0]); - break; - case SHCNE_RMDIR: - case SHCNE_DELETE: - LV_DeleteItem(This, Pidls[0]); - break; - case SHCNE_RENAMEFOLDER: - case SHCNE_RENAMEITEM: - LV_RenameItem(This, Pidls[0], Pidls[1]); - break; - case SHCNE_UPDATEITEM: - break; - } - return TRUE; -} -/********************************************************** -* ShellView_WndProc -*/ - -static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) -{ - IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); - LPCREATESTRUCTA lpcs; - - TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam); - - switch (uMessage) - { - case WM_NCCREATE: - lpcs = (LPCREATESTRUCTA)lParam; - pThis = (IShellViewImpl*)(lpcs->lpCreateParams); - SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis); - pThis->hWnd = hWnd; /*set the window handle*/ - break; - - case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam)); - case WM_SETFOCUS: return ShellView_OnSetFocus(pThis); - case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis); - case WM_CREATE: return ShellView_OnCreate(pThis); - case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS); - case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam); - case WM_COMMAND: return ShellView_OnCommand(pThis, - GET_WM_COMMAND_ID(wParam, lParam), - GET_WM_COMMAND_CMD(wParam, lParam), - GET_WM_COMMAND_HWND(wParam, lParam)); - case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam); - - case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE); - return 0; - - case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList); - break; - - case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0); - - case WM_DESTROY: - RevokeDragDrop(pThis->hWnd); - SHChangeNotifyDeregister(pThis->hNotify); - break; - - case WM_ERASEBKGND: - if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) || - (pThis->FolderSettings.fFlags & FWF_TRANSPARENT)) - return 1; - break; - } - - return DefWindowProcA (hWnd, uMessage, wParam, lParam); -} -/********************************************************** -* -* -* The INTERFACE of the IShellView object -* -* -********************************************************** -* IShellView_QueryInterface -*/ -static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellView)) - { - *ppvObj = (IShellView*)This; - } - else if(IsEqualIID(riid, &IID_IOleCommandTarget)) - { - *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget); - } - else if(IsEqualIID(riid, &IID_IDropTarget)) - { - *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget); - } - else if(IsEqualIID(riid, &IID_IDropSource)) - { - *ppvObj = (IDropSource*)&(This->lpvtblDropSource); - } - else if(IsEqualIID(riid, &IID_IViewObject)) - { - *ppvObj = (IViewObject*)&(This->lpvtblViewObject); - } - - if(*ppvObj) - { - IUnknown_AddRef( (IUnknown*)*ppvObj ); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/********************************************************** -* IShellView_AddRef -*/ -static ULONG WINAPI IShellView_fnAddRef(IShellView * iface) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return ++(This->ref); -} -/********************************************************** -* IShellView_Release -*/ -static ULONG WINAPI IShellView_fnRelease(IShellView * iface) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IShellView(%p)\n",This); - - DestroyWindow(This->hWndList); - - if(This->pSFParent) - IShellFolder_Release(This->pSFParent); - - if(This->pSF2Parent) - IShellFolder2_Release(This->pSF2Parent); - - if (This->apidl) - SHFree(This->apidl); - - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -/********************************************************** -* ShellView_GetWindow -*/ -static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)\n",This); - - *phWnd = This->hWnd; - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - FIXME("(%p) stub\n",This); - - return E_NOTIMPL; -} - -/********************************************************** -* IShellView_TranslateAccelerator -* -* FIXME: -* use the accel functions -*/ -static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg) -{ -#if 0 - IShellViewImpl *This = (IShellViewImpl *)iface; - - FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam); -#endif - - if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST)) - { - TRACE("-- key=0x04%x\n",lpmsg->wParam) ; - } - return S_FALSE; /* not handled */ -} - -static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - FIXME("(%p) stub\n",This); - - return E_NOTIMPL; -} - -static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - -/* - CHAR szName[MAX_PATH]; -*/ - LRESULT lResult; - int nPartArray[1] = {-1}; - - TRACE("(%p)->(state=%x) stub\n",This, uState); - - /*don't do anything if the state isn't really changing*/ - if(This->uState == uState) - { - return S_OK; - } - - /*OnActivate handles the menu merging and internal state*/ - ShellView_OnActivate(This, uState); - - /*only do This if we are active*/ - if(uState != SVUIA_DEACTIVATE) - { - -/* - GetFolderPath is not a method of IShellFolder - IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) ); -*/ - /* set the number of parts */ - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1, - (LPARAM)nPartArray, &lResult); - - /* set the text for the parts */ -/* - IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA, - 0, (LPARAM)szName, &lResult); -*/ - } - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)\n",This); - - ListView_DeleteAllItems(This->hWndList); - ShellView_FillList(This); - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnCreateViewWindow( - IShellView * iface, - IShellView *lpPrevView, - LPCFOLDERSETTINGS lpfs, - IShellBrowser * psb, - RECT * prcView, - HWND *phWnd) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - WNDCLASSA wc; - *phWnd = 0; - - - TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd); - TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom); - - /*set up the member variables*/ - This->pShellBrowser = psb; - This->FolderSettings = *lpfs; - - /*get our parent window*/ - IShellBrowser_AddRef(This->pShellBrowser); - IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent)); - - /* try to get the ICommDlgBrowserInterface, adds a reference !!! */ - This->pCommDlgBrowser=NULL; - if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser, - (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser))) - { - TRACE("-- CommDlgBrowser\n"); - } - - /*if our window class has not been registered, then do so*/ - if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc)) - { - ZeroMemory(&wc, sizeof(wc)); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC) ShellView_WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = shell32_hInstance; - wc.hIcon = 0; - wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); - wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = SV_CLASS_NAME; - - if(!RegisterClassA(&wc)) - return E_FAIL; - } - - *phWnd = CreateWindowExA(0, - SV_CLASS_NAME, - NULL, - WS_CHILD | WS_VISIBLE | WS_TABSTOP, - prcView->left, - prcView->top, - prcView->right - prcView->left, - prcView->bottom - prcView->top, - This->hWndParent, - 0, - shell32_hInstance, - (LPVOID)This); - - CheckToolbar(This); - - if(!*phWnd) return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)\n",This); - - /*Make absolutely sure all our UI is cleaned up.*/ - IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE); - - if(This->hMenu) - { - DestroyMenu(This->hMenu); - } - - DestroyWindow(This->hWnd); - if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser); - if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser); - - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs, - This->FolderSettings.ViewMode, This->FolderSettings.fFlags); - - if (!lpfs) return E_INVALIDARG; - - *lpfs = This->FolderSettings; - return NOERROR; -} - -static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - FIXME("(%p) stub\n",This); - - return E_NOTIMPL; -} - -static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - FIXME("(%p) stub\n",This); - - return S_OK; -} - -static HRESULT WINAPI IShellView_fnSelectItem( - IShellView * iface, - LPCITEMIDLIST pidl, - UINT uFlags) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - int i; - - TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags); - - i = LV_FindItemByPidl(This, pidl); - - if (i != -1) - { - LVITEMA lvItem; - - if(uFlags & SVSI_ENSUREVISIBLE) - ListView_EnsureVisible(This->hWndList, i, 0); - - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.mask = LVIF_STATE; - lvItem.iItem = 0; - - while(ListView_GetItemA(This->hWndList, &lvItem)) - { - if (lvItem.iItem == i) - { - if (uFlags & SVSI_SELECT) - lvItem.state |= LVIS_SELECTED; - else - lvItem.state &= ~LVIS_SELECTED; - - if(uFlags & SVSI_FOCUSED) - lvItem.state &= ~LVIS_FOCUSED; - } - else - { - if (uFlags & SVSI_DESELECTOTHERS) - lvItem.state &= ~LVIS_SELECTED; - } - ListView_SetItemA(This->hWndList, &lvItem); - lvItem.iItem++; - } - - - if(uFlags & SVSI_EDIT) - ListView_EditLabelA(This->hWndList, i); - - } - return S_OK; -} - -static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut) -{ - IShellViewImpl *This = (IShellViewImpl *)iface; - - TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut); - - *ppvOut = NULL; - - switch(uItem) - { - case SVGIO_BACKGROUND: - *ppvOut = ISvBgCm_Constructor(This->pSFParent); - break; - - case SVGIO_SELECTION: - ShellView_GetSelections(This); - IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut); - break; - } - TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut); - - if(!*ppvOut) return E_OUTOFMEMORY; - - return S_OK; -} - -static struct IShellViewVtbl svvt = -{ - IShellView_fnQueryInterface, - IShellView_fnAddRef, - IShellView_fnRelease, - IShellView_fnGetWindow, - IShellView_fnContextSensitiveHelp, - IShellView_fnTranslateAccelerator, - IShellView_fnEnableModeless, - IShellView_fnUIActivate, - IShellView_fnRefresh, - IShellView_fnCreateViewWindow, - IShellView_fnDestroyViewWindow, - IShellView_fnGetCurrentInfo, - IShellView_fnAddPropertySheetPages, - IShellView_fnSaveViewState, - IShellView_fnSelectItem, - IShellView_fnGetItemObject -}; - - -/********************************************************** - * ISVOleCmdTarget_QueryInterface (IUnknown) - */ -static HRESULT WINAPI ISVOleCmdTarget_QueryInterface( - IOleCommandTarget * iface, - REFIID iid, - LPVOID* ppvObj) -{ - _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); - - return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj); -} - -/********************************************************** - * ISVOleCmdTarget_AddRef (IUnknown) - */ -static ULONG WINAPI ISVOleCmdTarget_AddRef( - IOleCommandTarget * iface) -{ - _ICOM_THIS_From_IOleCommandTarget(IShellFolder, iface); - - return IShellFolder_AddRef((IShellFolder*)This); -} - -/********************************************************** - * ISVOleCmdTarget_Release (IUnknown) - */ -static ULONG WINAPI ISVOleCmdTarget_Release( - IOleCommandTarget * iface) -{ - _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); - - return IShellFolder_Release((IShellFolder*)This); -} - -/********************************************************** - * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) - */ -static HRESULT WINAPI ISVOleCmdTarget_QueryStatus( - IOleCommandTarget *iface, - const GUID* pguidCmdGroup, - ULONG cCmds, - OLECMD * prgCmds, - OLECMDTEXT* pCmdText) -{ - UINT i; - _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); - - FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n", - This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); - - if (!prgCmds) - return E_POINTER; - for (i = 0; i < cCmds; i++) - { - FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID); - prgCmds[i].cmdf = 0; - } - return OLECMDERR_E_UNKNOWNGROUP; -} - -/********************************************************** - * ISVOleCmdTarget_Exec (IOleCommandTarget) - * - * nCmdID is the OLECMDID_* enumeration - */ -static HRESULT WINAPI ISVOleCmdTarget_Exec( - IOleCommandTarget *iface, - const GUID* pguidCmdGroup, - DWORD nCmdID, - DWORD nCmdexecopt, - VARIANT* pvaIn, - VARIANT* pvaOut) -{ - _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); - - FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n", - This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); - - if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) && - (nCmdID == 0x29) && - (nCmdexecopt == 4) && pvaOut) - return S_OK; - if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) && - (nCmdID == 9) && - (nCmdexecopt == 0)) - return 1; - - return OLECMDERR_E_UNKNOWNGROUP; -} - -static IOleCommandTargetVtbl ctvt = -{ - ISVOleCmdTarget_QueryInterface, - ISVOleCmdTarget_AddRef, - ISVOleCmdTarget_Release, - ISVOleCmdTarget_QueryStatus, - ISVOleCmdTarget_Exec -}; - -/********************************************************** - * ISVDropTarget implementation - */ - -static HRESULT WINAPI ISVDropTarget_QueryInterface( - IDropTarget *iface, - REFIID riid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); -} - -static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_AddRef((IShellFolder*)This); -} - -static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_Release((IShellFolder*)This); -} - -static HRESULT WINAPI ISVDropTarget_DragEnter( - IDropTarget *iface, - IDataObject *pDataObject, - DWORD grfKeyState, - POINTL pt, - DWORD *pdwEffect) -{ - - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject); - - return E_NOTIMPL; -} - -static HRESULT WINAPI ISVDropTarget_DragOver( - IDropTarget *iface, - DWORD grfKeyState, - POINTL pt, - DWORD *pdwEffect) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} - -static HRESULT WINAPI ISVDropTarget_DragLeave( - IDropTarget *iface) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} - -static HRESULT WINAPI ISVDropTarget_Drop( - IDropTarget *iface, - IDataObject* pDataObject, - DWORD grfKeyState, - POINTL pt, - DWORD *pdwEffect) -{ - _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} - -static struct IDropTargetVtbl dtvt = -{ - ISVDropTarget_QueryInterface, - ISVDropTarget_AddRef, - ISVDropTarget_Release, - ISVDropTarget_DragEnter, - ISVDropTarget_DragOver, - ISVDropTarget_DragLeave, - ISVDropTarget_Drop -}; - -/********************************************************** - * ISVDropSource implementation - */ - -static HRESULT WINAPI ISVDropSource_QueryInterface( - IDropSource *iface, - REFIID riid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); -} - -static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface) -{ - _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_AddRef((IShellFolder*)This); -} - -static ULONG WINAPI ISVDropSource_Release( IDropSource *iface) -{ - _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_Release((IShellFolder*)This); -} -static HRESULT WINAPI ISVDropSource_QueryContinueDrag( - IDropSource *iface, - BOOL fEscapePressed, - DWORD grfKeyState) -{ - _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); - TRACE("(%p)\n",This); - - if (fEscapePressed) - return DRAGDROP_S_CANCEL; - else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) - return DRAGDROP_S_DROP; - else - return NOERROR; -} - -static HRESULT WINAPI ISVDropSource_GiveFeedback( - IDropSource *iface, - DWORD dwEffect) -{ - _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); - TRACE("(%p)\n",This); - - return DRAGDROP_S_USEDEFAULTCURSORS; -} - -static struct IDropSourceVtbl dsvt = -{ - ISVDropSource_QueryInterface, - ISVDropSource_AddRef, - ISVDropSource_Release, - ISVDropSource_QueryContinueDrag, - ISVDropSource_GiveFeedback -}; -/********************************************************** - * ISVViewObject implementation - */ - -static HRESULT WINAPI ISVViewObject_QueryInterface( - IViewObject *iface, - REFIID riid, - LPVOID *ppvObj) -{ - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); -} - -static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface) -{ - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_AddRef((IShellFolder*)This); -} - -static ULONG WINAPI ISVViewObject_Release( IViewObject *iface) -{ - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - TRACE("(%p)->(count=%lu)\n",This,This->ref); - - return IShellFolder_Release((IShellFolder*)This); -} - -static HRESULT WINAPI ISVViewObject_Draw( - IViewObject *iface, - DWORD dwDrawAspect, - LONG lindex, - void* pvAspect, - DVTARGETDEVICE* ptd, - HDC hdcTargetDev, - HDC hdcDraw, - LPCRECTL lprcBounds, - LPCRECTL lprcWBounds, - BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), - ULONG_PTR dwContinue) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISVViewObject_GetColorSet( - IViewObject *iface, - DWORD dwDrawAspect, - LONG lindex, - void *pvAspect, - DVTARGETDEVICE* ptd, - HDC hicTargetDevice, - LOGPALETTE** ppColorSet) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISVViewObject_Freeze( - IViewObject *iface, - DWORD dwDrawAspect, - LONG lindex, - void* pvAspect, - DWORD* pdwFreeze) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISVViewObject_Unfreeze( - IViewObject *iface, - DWORD dwFreeze) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISVViewObject_SetAdvise( - IViewObject *iface, - DWORD aspects, - DWORD advf, - IAdviseSink* pAdvSink) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} -static HRESULT WINAPI ISVViewObject_GetAdvise( - IViewObject *iface, - DWORD* pAspects, - DWORD* pAdvf, - IAdviseSink** ppAdvSink) -{ - - _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); - - FIXME("Stub: This=%p\n",This); - - return E_NOTIMPL; -} - - -static struct IViewObjectVtbl vovt = -{ - ISVViewObject_QueryInterface, - ISVViewObject_AddRef, - ISVViewObject_Release, - ISVViewObject_Draw, - ISVViewObject_GetColorSet, - ISVViewObject_Freeze, - ISVViewObject_Unfreeze, - ISVViewObject_SetAdvise, - ISVViewObject_GetAdvise -}; +/* + * ShellView + * + * Copyright 1998,1999 + * + * This is the view visualizing the data provied by the shellfolder. + * No direct access to data from pidls should be done from here. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * FIXME: The order by part of the background context menu should be + * buily according to the columns shown. + * + * FIXME: Load/Save the view state from/into the stream provied by + * the ShellBrowser + * + * FIXME: CheckToolbar: handle the "new folder" and "folder up" button + * + * FIXME: ShellView_FillList: consider sort orders + * + * FIXME: implement the drag and drop in the old (msg-based) way + * + * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a + * Release() ??? + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winerror.h" +#include "winbase.h" +#include "winnls.h" +#include "objbase.h" +#include "servprov.h" +#include "shlguid.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "undocshell.h" +#include "shresdef.h" +#include "wine/debug.h" + +#include "docobj.h" +#include "pidl.h" +#include "shell32_main.h" +#include "shellfolder.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +typedef struct +{ BOOL bIsAscending; + INT nHeaderID; + INT nLastHeaderID; +}LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO; + +typedef struct +{ + IShellViewVtbl* lpVtbl; + DWORD ref; + IOleCommandTargetVtbl* lpvtblOleCommandTarget; + IDropTargetVtbl* lpvtblDropTarget; + IDropSourceVtbl* lpvtblDropSource; + IViewObjectVtbl* lpvtblViewObject; + IShellFolder* pSFParent; + IShellFolder2* pSF2Parent; + IShellBrowser* pShellBrowser; + ICommDlgBrowser* pCommDlgBrowser; + HWND hWnd; /* SHELLDLL_DefView */ + HWND hWndList; /* ListView control */ + HWND hWndParent; + FOLDERSETTINGS FolderSettings; + HMENU hMenu; + UINT uState; + UINT cidl; + LPITEMIDLIST *apidl; + LISTVIEW_SORT_INFO ListViewSortInfo; + ULONG hNotify; /* change notification handle */ + HANDLE hAccel; +} IShellViewImpl; + +static struct IShellViewVtbl svvt; + +static struct IOleCommandTargetVtbl ctvt; +#define _IOleCommandTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblOleCommandTarget))) +#define _ICOM_THIS_From_IOleCommandTarget(class, name) class* This = (class*)(((char*)name)-_IOleCommandTarget_Offset); + +static struct IDropTargetVtbl dtvt; +#define _IDropTarget_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropTarget))) +#define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); + +static struct IDropSourceVtbl dsvt; +#define _IDropSource_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblDropSource))) +#define _ICOM_THIS_From_IDropSource(class, name) class* This = (class*)(((char*)name)-_IDropSource_Offset); + +static struct IViewObjectVtbl vovt; +#define _IViewObject_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblViewObject))) +#define _ICOM_THIS_From_IViewObject(class, name) class* This = (class*)(((char*)name)-_IViewObject_Offset); + +/* ListView Header ID's */ +#define LISTVIEW_COLUMN_NAME 0 +#define LISTVIEW_COLUMN_SIZE 1 +#define LISTVIEW_COLUMN_TYPE 2 +#define LISTVIEW_COLUMN_TIME 3 +#define LISTVIEW_COLUMN_ATTRIB 4 + +/*menu items */ +#define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500) +#define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501) +#define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502) + +#define ID_LISTVIEW 2000 + +#define SHV_CHANGE_NOTIFY WM_USER + 0x1111 + +/*windowsx.h */ +#define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp) +#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp) +#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp) + +extern void WINAPI _InsertMenuItem (HMENU hmenu, UINT indexMenu, BOOL fByPosition, + UINT wID, UINT fType, LPSTR dwTypeData, UINT fState); + +/* + Items merged into the toolbar and and the filemenu +*/ +typedef struct +{ int idCommand; + int iImage; + int idButtonString; + int idMenuString; + BYTE bState; + BYTE bStyle; +} MYTOOLINFO, *LPMYTOOLINFO; + +MYTOOLINFO Tools[] = +{ +{ FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON }, +{ FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON }, +{ FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON }, +{ FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON }, +{ -1, 0, 0, 0, 0, 0} +}; + +typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask); + +/********************************************************** + * IShellView_Constructor + */ +IShellView * IShellView_Constructor( IShellFolder * pFolder) +{ IShellViewImpl * sv; + sv=(IShellViewImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl)); + sv->ref=1; + sv->lpVtbl=&svvt; + sv->lpvtblOleCommandTarget=&ctvt; + sv->lpvtblDropTarget=&dtvt; + sv->lpvtblDropSource=&dsvt; + sv->lpvtblViewObject=&vovt; + + sv->pSFParent = pFolder; + if(pFolder) IShellFolder_AddRef(pFolder); + IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent); + + TRACE("(%p)->(%p)\n",sv, pFolder); + return (IShellView *) sv; +} + +/********************************************************** + * + * ##### helperfunctions for communication with ICommDlgBrowser ##### + */ +static BOOL IsInCommDlg(IShellViewImpl * This) +{ return(This->pCommDlgBrowser != NULL); +} + +static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl) +{ + HRESULT ret = S_OK; + + if ( IsInCommDlg(This) ) + { + TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl); + ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl); + TRACE("--0x%08lx\n", ret); + } + return ret; +} + +static HRESULT OnDefaultCommand(IShellViewImpl * This) +{ + HRESULT ret = S_FALSE; + + if (IsInCommDlg(This)) + { + TRACE("ICommDlgBrowser::OnDefaultCommand\n"); + ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This); + TRACE("--\n"); + } + return ret; +} + +static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags) +{ + HRESULT ret = S_FALSE; + + if (IsInCommDlg(This)) + { + TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags); + ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags); + TRACE("--\n"); + } + return ret; +} +/********************************************************** + * set the toolbar of the filedialog buttons + * + * - activates the buttons from the shellbrowser according to + * the view state + */ +static void CheckToolbar(IShellViewImpl * This) +{ + LRESULT result; + + TRACE("\n"); + + if (IsInCommDlg(This)) + { + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON, + FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result); + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON, + FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result); + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON, + FCIDM_TB_SMALLICON, TRUE, &result); + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON, + FCIDM_TB_REPORTVIEW, TRUE, &result); + } +} + +/********************************************************** + * + * ##### helperfunctions for initializing the view ##### + */ +/********************************************************** + * change the style of the listview control + */ +static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove) +{ + DWORD tmpstyle; + + TRACE("(%p)\n", This); + + tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE); + SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove)); +} + +/********************************************************** +* ShellView_CreateList() +* +* - creates the list view window +*/ +static BOOL ShellView_CreateList (IShellViewImpl * This) +{ DWORD dwStyle, dwExStyle; + + TRACE("%p\n",This); + + dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | + LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE; + dwExStyle = WS_EX_CLIENTEDGE; + + switch (This->FolderSettings.ViewMode) + { + case FVM_ICON: dwStyle |= LVS_ICON; break; + case FVM_DETAILS: dwStyle |= LVS_REPORT; break; + case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break; + case FVM_LIST: dwStyle |= LVS_LIST; break; + default: dwStyle |= LVS_LIST; break; + } + + if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE; + if (This->FolderSettings.fFlags & FWF_DESKTOP) + This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL; + if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL; + if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE) + dwExStyle &= ~WS_EX_CLIENTEDGE; + + This->hWndList=CreateWindowExA( dwExStyle, + WC_LISTVIEWA, + NULL, + dwStyle, + 0,0,0,0, + This->hWnd, + (HMENU)ID_LISTVIEW, + shell32_hInstance, + NULL); + + if(!This->hWndList) + return FALSE; + + This->ListViewSortInfo.bIsAscending = TRUE; + This->ListViewSortInfo.nHeaderID = -1; + This->ListViewSortInfo.nLastHeaderID = -1; + + if (This->FolderSettings.fFlags & FWF_DESKTOP) { + if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */ + ListView_SetTextBkColor(This->hWndList, CLR_NONE); + else + ListView_SetTextBkColor(This->hWndList, GetSysColor(COLOR_DESKTOP)); + + ListView_SetTextColor(This->hWndList, RGB(255,255,255)); + } + + /* UpdateShellSettings(); */ + return TRUE; +} + +/********************************************************** +* ShellView_InitList() +* +* - adds all needed columns to the shellview +*/ +static BOOL ShellView_InitList(IShellViewImpl * This) +{ + LVCOLUMNA lvColumn; + SHELLDETAILS sd; + int i; + char szTemp[50]; + + TRACE("%p\n",This); + + ListView_DeleteAllItems(This->hWndList); + + lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + lvColumn.pszText = szTemp; + + if (This->pSF2Parent) + { + for (i=0; 1; i++) + { + if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd))) + break; + lvColumn.fmt = sd.fmt; + lvColumn.cx = sd.cxChar*8; /* chars->pixel */ + StrRetToStrNA( szTemp, 50, &sd.str, NULL); + ListView_InsertColumnA(This->hWndList, i, &lvColumn); + } + } + else + { + FIXME("no SF2\n"); + } + + ListView_SetImageList(This->hWndList, ShellSmallIconList, LVSIL_SMALL); + ListView_SetImageList(This->hWndList, ShellBigIconList, LVSIL_NORMAL); + + return TRUE; +} +/********************************************************** +* ShellView_CompareItems() +* +* NOTES +* internal, CALLBACK for DSA_Sort +*/ +static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) +{ + int ret; + TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData); + + if(!lpData) return 0; + + ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2)); + TRACE("ret=%i\n",ret); + return ret; +} + +/************************************************************************* + * ShellView_ListViewCompareItems + * + * Compare Function for the Listview (FileOpen Dialog) + * + * PARAMS + * lParam1 [I] the first ItemIdList to compare with + * lParam2 [I] the second ItemIdList to compare with + * lpData [I] The column ID for the header Ctrl to process + * + * RETURNS + * A negative value if the first item should precede the second, + * a positive value if the first item should follow the second, + * or zero if the two items are equivalent + * + * NOTES + * FIXME: function does what ShellView_CompareItems is supposed to do. + * unify it and figure out how to use the undocumented first parameter + * of IShellFolder_CompareIDs to do the job this function does and + * move this code to IShellFolder. + * make LISTVIEW_SORT_INFO obsolete + * the way this function works is only usable if we had only + * filesystemfolders (25/10/99 jsch) + */ +static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) +{ + INT nDiff=0; + FILETIME fd1, fd2; + char strName1[MAX_PATH], strName2[MAX_PATH]; + BOOL bIsFolder1, bIsFolder2,bIsBothFolder; + LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1; + LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2; + LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData; + + + bIsFolder1 = _ILIsFolder(pItemIdList1); + bIsFolder2 = _ILIsFolder(pItemIdList2); + bIsBothFolder = bIsFolder1 && bIsFolder2; + + /* When sorting between a File and a Folder, the Folder gets sorted first */ + if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder) + { + nDiff = bIsFolder1 ? -1 : 1; + } + else + { + /* Sort by Time: Folders or Files can be sorted */ + + if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME) + { + _ILGetFileDateTime(pItemIdList1, &fd1); + _ILGetFileDateTime(pItemIdList2, &fd2); + nDiff = CompareFileTime(&fd2, &fd1); + } + /* Sort by Attribute: Folder or Files can be sorted */ + else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB) + { + _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH); + _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH); + nDiff = strcasecmp(strName1, strName2); + } + /* Sort by FileName: Folder or Files can be sorted */ + else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder) + { + /* Sort by Text */ + _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); + _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); + nDiff = strcasecmp(strName1, strName2); + } + /* Sort by File Size, Only valid for Files */ + else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE) + { + nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0)); + } + /* Sort by File Type, Only valid for Files */ + else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE) + { + /* Sort by Type */ + _ILGetFileType(pItemIdList1, strName1, MAX_PATH); + _ILGetFileType(pItemIdList2, strName2, MAX_PATH); + nDiff = strcasecmp(strName1, strName2); + } + } + /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */ + + if(nDiff == 0) + { + _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); + _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); + nDiff = strcasecmp(strName1, strName2); + } + + if(!pSortInfo->bIsAscending) + { + nDiff = -nDiff; + } + + return nDiff; + +} + +/********************************************************** +* LV_FindItemByPidl() +*/ +static int LV_FindItemByPidl( + IShellViewImpl * This, + LPCITEMIDLIST pidl) +{ + LVITEMA lvItem; + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.mask = LVIF_PARAM; + for(lvItem.iItem = 0; ListView_GetItemA(This->hWndList, &lvItem); lvItem.iItem++) + { + LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam; + HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl); + if(SUCCEEDED(hr) && !HRESULT_CODE(hr)) + { + return lvItem.iItem; + } + } + return -1; +} + +/********************************************************** +* LV_AddItem() +*/ +static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl) +{ + LVITEMA lvItem; + + TRACE("(%p)(pidl=%p)\n", This, pidl); + + ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/ + lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ + lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/ + lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/ + lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/ + lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ + return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE; +} + +/********************************************************** +* LV_DeleteItem() +*/ +static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl) +{ + int nIndex; + + TRACE("(%p)(pidl=%p)\n", This, pidl); + + nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl)); + return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE; +} + +/********************************************************** +* LV_RenameItem() +*/ +static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew ) +{ + int nItem; + LVITEMA lvItem; + + TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew); + + nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld)); + if ( -1 != nItem ) + { + ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/ + lvItem.mask = LVIF_PARAM; /* only the pidl */ + lvItem.iItem = nItem; + ListView_GetItemA(This->hWndList, &lvItem); + + SHFree((LPITEMIDLIST)lvItem.lParam); + lvItem.mask = LVIF_PARAM; + lvItem.iItem = nItem; + lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */ + ListView_SetItemA(This->hWndList, &lvItem); + ListView_Update(This->hWndList, nItem); + return TRUE; /* FIXME: better handling */ + } + return FALSE; +} +/********************************************************** +* ShellView_FillList() +* +* - gets the objectlist from the shellfolder +* - sorts the list +* - fills the list into the view +*/ + +static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg ) +{ + LPITEMIDLIST pidl = ptr; + IShellViewImpl *This = arg; + /* in a commdlg This works as a filemask*/ + if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl); + SHFree(pidl); + return TRUE; +} + +static HRESULT ShellView_FillList(IShellViewImpl * This) +{ + LPENUMIDLIST pEnumIDList; + LPITEMIDLIST pidl; + DWORD dwFetched; + HRESULT hRes; + HDPA hdpa; + + TRACE("%p\n",This); + + /* get the itemlist from the shfolder*/ + hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList); + if (hRes != S_OK) + { + if (hRes==S_FALSE) + return(NOERROR); + return(hRes); + } + + /* create a pointer array */ + hdpa = DPA_Create(16); + if (!hdpa) + { + return(E_OUTOFMEMORY); + } + + /* copy the items into the array*/ + while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched) + { + if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) + { + SHFree(pidl); + } + } + + /* sort the array */ + DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent); + + /*turn the listview's redrawing off*/ + SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0); + + DPA_DestroyCallback( hdpa, fill_list, This ); + + /*turn the listview's redrawing back on and force it to draw*/ + SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0); + + IEnumIDList_Release(pEnumIDList); /* destroy the list*/ + + return S_OK; +} + +/********************************************************** +* ShellView_OnCreate() +*/ +static LRESULT ShellView_OnCreate(IShellViewImpl * This) +{ + IDropTarget* pdt; + SHChangeNotifyEntry ntreg; + IPersistFolder2 * ppf2 = NULL; + + TRACE("%p\n",This); + + if(ShellView_CreateList(This)) + { + if(ShellView_InitList(This)) + { + ShellView_FillList(This); + } + } + + if (SUCCEEDED(IShellFolder_CreateViewObject(This->pSFParent, This->hWnd, &IID_IDropTarget, (LPVOID*)&pdt))) + { + RegisterDragDrop(This->hWnd, pdt); + IDropTarget_Release(pdt); + } + + /* register for receiving notifications */ + IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2); + if (ppf2) + { + IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl); + ntreg.fRecursive = TRUE; + This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg); + SHFree((LPITEMIDLIST)ntreg.pidl); + IPersistFolder2_Release(ppf2); + } + + This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel"); + + return S_OK; +} + +/********************************************************** + * #### Handling of the menus #### + */ + +/********************************************************** +* ShellView_BuildFileMenu() +*/ +static HMENU ShellView_BuildFileMenu(IShellViewImpl * This) +{ CHAR szText[MAX_PATH]; + MENUITEMINFOA mii; + int nTools,i; + HMENU hSubMenu; + + TRACE("(%p)\n",This); + + hSubMenu = CreatePopupMenu(); + if(hSubMenu) + { /*get the number of items in our global array*/ + for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){} + + /*add the menu items*/ + for(i = 0; i < nTools; i++) + { + LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; + + if(BTNS_SEP != Tools[i].bStyle) /* no separator*/ + { + mii.fType = MFT_STRING; + mii.fState = MFS_ENABLED; + mii.dwTypeData = szText; + mii.wID = Tools[i].idCommand; + } + else + { + mii.fType = MFT_SEPARATOR; + } + /* tack This item onto the end of the menu */ + InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii); + } + } + TRACE("-- return (menu=%p)\n",hSubMenu); + return hSubMenu; +} +/********************************************************** +* ShellView_MergeFileMenu() +*/ +static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu) +{ TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu); + + if(hSubMenu) + { /*insert This item at the beginning of the menu */ + _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED); + + } + TRACE("--\n"); +} + +/********************************************************** +* ShellView_MergeViewMenu() +*/ + +static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu) +{ MENUITEMINFOA mii; + + TRACE("(%p)->(submenu=%p)\n",This,hSubMenu); + + if(hSubMenu) + { /*add a separator at the correct position in the menu*/ + _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA; + mii.fType = MFT_STRING; + mii.dwTypeData = "View"; + mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001"); + InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); + } +} + +/********************************************************** +* ShellView_GetSelections() +* +* - fills the this->apidl list with the selected objects +* +* RETURNS +* number of selected items +*/ +static UINT ShellView_GetSelections(IShellViewImpl * This) +{ + LVITEMA lvItem; + UINT i = 0; + + if (This->apidl) + { + SHFree(This->apidl); + } + + This->cidl = ListView_GetSelectedCount(This->hWndList); + This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST)); + + TRACE("selected=%i\n", This->cidl); + + if(This->apidl) + { + TRACE("-- Items selected =%u\n", This->cidl); + + ZeroMemory(&lvItem, sizeof(lvItem)); + lvItem.mask = LVIF_STATE | LVIF_PARAM; + lvItem.stateMask = LVIS_SELECTED; + + while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl)) + { + if(lvItem.state & LVIS_SELECTED) + { + This->apidl[i] = (LPITEMIDLIST)lvItem.lParam; + i++; + TRACE("-- selected Item found\n"); + } + lvItem.iItem++; + } + } + return This->cidl; + +} + +/********************************************************** + * ShellView_OpenSelectedItems() + */ +static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This) +{ + static UINT CF_IDLIST = 0; + HRESULT hr; + IDataObject* selection; + FORMATETC fetc; + STGMEDIUM stgm; + LPIDA pIDList; + LPCITEMIDLIST parent_pidl; + int i; + + if (0 == ShellView_GetSelections(This)) + { + return S_OK; + } + hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, + (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, + 0, (LPVOID *)&selection); + if (FAILED(hr)) + return hr; + + if (0 == CF_IDLIST) + { + CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST); + } + fetc.cfFormat = CF_IDLIST; + fetc.ptd = NULL; + fetc.dwAspect = DVASPECT_CONTENT; + fetc.lindex = -1; + fetc.tymed = TYMED_HGLOBAL; + + hr = IDataObject_QueryGetData(selection, &fetc); + if (FAILED(hr)) + return hr; + + hr = IDataObject_GetData(selection, &fetc, &stgm); + if (FAILED(hr)) + return hr; + + pIDList = GlobalLock(stgm.u.hGlobal); + + parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]); + for (i = pIDList->cidl; i > 0; --i) + { + LPCITEMIDLIST pidl; + SFGAOF attribs; + + pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]); + + attribs = SFGAO_FOLDER; + hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs); + + if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER)) + { + SHELLEXECUTEINFOA shexinfo; + + shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA); + shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */ + shexinfo.hwnd = NULL; + shexinfo.lpVerb = NULL; + shexinfo.lpFile = NULL; + shexinfo.lpParameters = NULL; + shexinfo.lpDirectory = NULL; + shexinfo.nShow = SW_NORMAL; + shexinfo.lpIDList = ILCombine(parent_pidl, pidl); + + ShellExecuteExA(&shexinfo); /* Discard error/success info */ + + ILFree((LPITEMIDLIST)shexinfo.lpIDList); + } + } + + GlobalUnlock(stgm.u.hGlobal); + ReleaseStgMedium(&stgm); + + IDataObject_Release(selection); + + return S_OK; +} + +/********************************************************** + * ShellView_DoContextMenu() + */ +static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault) +{ UINT uCommand; + DWORD wFlags; + HMENU hMenu; + BOOL fExplore = FALSE; + HWND hwndTree = 0; + LPCONTEXTMENU pContextMenu = NULL; + IContextMenu2 *pCM = NULL; + CMINVOKECOMMANDINFO cmi; + + TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault); + + /* look, what's selected and create a context menu object of it*/ + if( ShellView_GetSelections(This) ) + { + IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl, + (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu); + + if(pContextMenu) + { + TRACE("-- pContextMenu\n"); + hMenu = CreatePopupMenu(); + + if( hMenu ) + { + /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/ + if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree) + { + TRACE("-- explore mode\n"); + fExplore = TRUE; + } + + /* build the flags depending on what we can do with the selected item */ + wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0); + + /* let the ContextMenu merge its items in */ + if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags ))) + { + if (This->FolderSettings.fFlags & FWF_DESKTOP) + SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); + + if( bDefault ) + { + TRACE("-- get menu default command\n"); + uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS); + } + else + { + TRACE("-- track popup\n"); + uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); + } + + if(uCommand > 0) + { + TRACE("-- uCommand=%u\n", uCommand); + if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This)) + { + TRACE("-- dlg: OnDefaultCommand\n"); + if (FAILED(OnDefaultCommand(This))) + { + ShellView_OpenSelectedItems(This); + } + } + else + { + TRACE("-- explore -- invoke command\n"); + ZeroMemory(&cmi, sizeof(cmi)); + cmi.cbSize = sizeof(cmi); + cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */ + cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); + IContextMenu_InvokeCommand(pContextMenu, &cmi); + } + } + DestroyMenu(hMenu); + } + } + if (pContextMenu) + IContextMenu_Release(pContextMenu); + } + } + else /* background context menu */ + { + hMenu = CreatePopupMenu(); + + pCM = ISvBgCm_Constructor(This->pSFParent); + IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); + + uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); + DestroyMenu(hMenu); + + TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand); + + ZeroMemory(&cmi, sizeof(cmi)); + cmi.cbSize = sizeof(cmi); + cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); + cmi.hwnd = This->hWndParent; + IContextMenu2_InvokeCommand(pCM, &cmi); + + IContextMenu2_Release(pCM); + } +} + +/********************************************************** + * ##### message handling ##### + */ + +/********************************************************** +* ShellView_OnSize() +*/ +static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight) +{ + TRACE("%p width=%u height=%u\n",This, wWidth,wHeight); + + /*resize the ListView to fit our window*/ + if(This->hWndList) + { + MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE); + } + + return S_OK; +} +/********************************************************** +* ShellView_OnDeactivate() +* +* NOTES +* internal +*/ +static void ShellView_OnDeactivate(IShellViewImpl * This) +{ + TRACE("%p\n",This); + + if(This->uState != SVUIA_DEACTIVATE) + { + if(This->hMenu) + { + IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0); + IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu); + DestroyMenu(This->hMenu); + This->hMenu = 0; + } + + This->uState = SVUIA_DEACTIVATE; + } +} + +/********************************************************** +* ShellView_OnActivate() +*/ +static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState) +{ OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} }; + MENUITEMINFOA mii; + CHAR szText[MAX_PATH]; + + TRACE("%p uState=%x\n",This,uState); + + /*don't do anything if the state isn't really changing */ + if(This->uState == uState) + { + return S_OK; + } + + ShellView_OnDeactivate(This); + + /*only do This if we are active */ + if(uState != SVUIA_DEACTIVATE) + { + /*merge the menus */ + This->hMenu = CreateMenu(); + + if(This->hMenu) + { + IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw); + TRACE("-- after fnInsertMenusSB\n"); + + /*build the top level menu get the menu item's text*/ + strcpy(szText,"dummy 31"); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; + mii.fType = MFT_STRING; + mii.fState = MFS_ENABLED; + mii.dwTypeData = szText; + mii.hSubMenu = ShellView_BuildFileMenu(This); + + /*insert our menu into the menu bar*/ + if(mii.hSubMenu) + { + InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii); + } + + /*get the view menu so we can merge with it*/ + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + + if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii)) + { + ShellView_MergeViewMenu(This, mii.hSubMenu); + } + + /*add the items that should only be added if we have the focus*/ + if(SVUIA_ACTIVATE_FOCUS == uState) + { + /*get the file menu so we can merge with it */ + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + + if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii)) + { + ShellView_MergeFileMenu(This, mii.hSubMenu); + } + } + TRACE("-- before fnSetMenuSB\n"); + IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd); + } + } + This->uState = uState; + TRACE("--\n"); + return S_OK; +} + +/********************************************************** +* ShellView_OnSetFocus() +* +*/ +static LRESULT ShellView_OnSetFocus(IShellViewImpl * This) +{ + TRACE("%p\n",This); + + /* Tell the browser one of our windows has received the focus. This + should always be done before merging menus (OnActivate merges the + menus) if one of our windows has the focus.*/ + + IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This); + ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS); + + /* Set the focus to the listview */ + SetFocus(This->hWndList); + + /* Notify the ICommDlgBrowser interface */ + OnStateChange(This,CDBOSC_SETFOCUS); + + return 0; +} + +/********************************************************** +* ShellView_OnKillFocus() +*/ +static LRESULT ShellView_OnKillFocus(IShellViewImpl * This) +{ + TRACE("(%p) stub\n",This); + + ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS); + /* Notify the ICommDlgBrowser */ + OnStateChange(This,CDBOSC_KILLFOCUS); + + return 0; +} + +/********************************************************** +* ShellView_OnCommand() +* +* NOTES +* the CmdID's are the ones from the context menu +*/ +static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd) +{ + TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd); + + switch(dwCmdID) + { + case FCIDM_SHVIEW_SMALLICON: + This->FolderSettings.ViewMode = FVM_SMALLICON; + SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK); + CheckToolbar(This); + break; + + case FCIDM_SHVIEW_BIGICON: + This->FolderSettings.ViewMode = FVM_ICON; + SetStyle (This, LVS_ICON, LVS_TYPEMASK); + CheckToolbar(This); + break; + + case FCIDM_SHVIEW_LISTVIEW: + This->FolderSettings.ViewMode = FVM_LIST; + SetStyle (This, LVS_LIST, LVS_TYPEMASK); + CheckToolbar(This); + break; + + case FCIDM_SHVIEW_REPORTVIEW: + This->FolderSettings.ViewMode = FVM_DETAILS; + SetStyle (This, LVS_REPORT, LVS_TYPEMASK); + CheckToolbar(This); + break; + + /* the menu-ID's for sorting are 0x30... see shrec.rc */ + case 0x30: + case 0x31: + case 0x32: + case 0x33: + This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30); + This->ListViewSortInfo.bIsAscending = TRUE; + This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID; + ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo))); + break; + + default: + TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID); + } + return 0; +} + +/********************************************************** +* ShellView_OnNotify() +*/ + +static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh) +{ LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh; + NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh; + LPITEMIDLIST pidl; + + TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code); + + switch(lpnmh->code) + { + case NM_SETFOCUS: + TRACE("-- NM_SETFOCUS %p\n",This); + ShellView_OnSetFocus(This); + break; + + case NM_KILLFOCUS: + TRACE("-- NM_KILLFOCUS %p\n",This); + ShellView_OnDeactivate(This); + /* Notify the ICommDlgBrowser interface */ + OnStateChange(This,CDBOSC_KILLFOCUS); + break; + + case NM_CUSTOMDRAW: + TRACE("-- NM_CUSTOMDRAW %p\n",This); + return CDRF_DODEFAULT; + + case NM_RELEASEDCAPTURE: + TRACE("-- NM_RELEASEDCAPTURE %p\n",This); + break; + + case NM_CLICK: + TRACE("-- NM_CLICK %p\n",This); + break; + + case NM_RCLICK: + TRACE("-- NM_RCLICK %p\n",This); + break; + + case HDN_ENDTRACKA: + TRACE("-- HDN_ENDTRACKA %p\n",This); + /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0); + nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/ + break; + + case LVN_DELETEITEM: + TRACE("-- LVN_DELETEITEM %p\n",This); + SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/ + break; + + case LVN_DELETEALLITEMS: + TRACE("-- LVN_DELETEALLITEMS %p\n",This); + return FALSE; + + case LVN_INSERTITEM: + TRACE("-- LVN_INSERTITEM (STUB)%p\n",This); + break; + + case LVN_ITEMACTIVATE: + TRACE("-- LVN_ITEMACTIVATE %p\n",This); + OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ + ShellView_DoContextMenu(This, 0, 0, TRUE); + break; + + case LVN_COLUMNCLICK: + This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem; + if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID) + { + This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending; + } + else + { + This->ListViewSortInfo.bIsAscending = TRUE; + } + This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID; + + ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo))); + break; + + case LVN_GETDISPINFOA: + case LVN_GETDISPINFOW: + TRACE("-- LVN_GETDISPINFO %p\n",This); + pidl = (LPITEMIDLIST)lpdi->item.lParam; + + if(lpdi->item.mask & LVIF_TEXT) /* text requested */ + { + if (This->pSF2Parent) + { + SHELLDETAILS sd; + IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd); + if (lpnmh->code == LVN_GETDISPINFOA) + { + StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); + TRACE("-- text=%s\n",lpdi->item.pszText); + } + else /* LVN_GETDISPINFOW */ + { + StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); + TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText))); + } + } + else + { + FIXME("no SF2\n"); + } + } + if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ + { + lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0); + } + break; + + case LVN_ITEMCHANGED: + TRACE("-- LVN_ITEMCHANGED %p\n",This); + OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ + break; + + case LVN_BEGINDRAG: + case LVN_BEGINRDRAG: + TRACE("-- LVN_BEGINDRAG\n"); + + if (ShellView_GetSelections(This)) + { + IDataObject * pda; + DWORD dwAttributes = SFGAO_CANLINK; + DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE; + + if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda))) + { + IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */ + + if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes))) + { + if (dwAttributes & SFGAO_CANLINK) + { + dwEffect |= DROPEFFECT_LINK; + } + } + + if (pds) + { + DWORD dwEffect; + DoDragDrop(pda, pds, dwEffect, &dwEffect); + } + IDataObject_Release(pda); + } + } + break; + + case LVN_BEGINLABELEDITA: + { + DWORD dwAttr = SFGAO_CANRENAME; + pidl = (LPITEMIDLIST)lpdi->item.lParam; + + TRACE("-- LVN_BEGINLABELEDITA %p\n",This); + + IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr); + if (SFGAO_CANRENAME & dwAttr) + { + return FALSE; + } + return TRUE; + } + + case LVN_ENDLABELEDITA: + { + TRACE("-- LVN_ENDLABELEDITA %p\n",This); + if (lpdi->item.pszText) + { + HRESULT hr; + WCHAR wszNewName[MAX_PATH]; + LVITEMA lvItem; + + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.iItem = lpdi->item.iItem; + lvItem.mask = LVIF_PARAM; + ListView_GetItemA(This->hWndList, &lvItem); + + pidl = (LPITEMIDLIST)lpdi->item.lParam; + if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH )) + wszNewName[MAX_PATH-1] = 0; + hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl); + + if(SUCCEEDED(hr) && pidl) + { + lvItem.mask = LVIF_PARAM; + lvItem.lParam = (LPARAM)pidl; + ListView_SetItemA(This->hWndList, &lvItem); + return TRUE; + } + } + return FALSE; + } + + case LVN_KEYDOWN: + { + /* MSG msg; + msg.hwnd = This->hWnd; + msg.message = WM_KEYDOWN; + msg.wParam = plvKeyDown->wVKey; + msg.lParam = 0; + msg.time = 0; + msg.pt = 0;*/ + + LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh; + + /* initiate a rename of the selected file or directory */ + if(plvKeyDown->wVKey == VK_F2) + { + /* see how many files are selected */ + int i = ListView_GetSelectedCount(This->hWndList); + + /* get selected item */ + if(i == 1) + { + /* get selected item */ + i = ListView_GetNextItem(This->hWndList, -1, + LVNI_SELECTED); + + ListView_EnsureVisible(This->hWndList, i, 0); + ListView_EditLabelA(This->hWndList, i); + } + } +#if 0 + TranslateAccelerator(This->hWnd, This->hAccel, &msg) +#endif + else if(plvKeyDown->wVKey == VK_DELETE) + { + UINT i; + int item_index; + LVITEMA item; + LPITEMIDLIST* pItems; + ISFHelper *psfhlp; + + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, + (LPVOID*)&psfhlp); + + if (psfhlp == NULL) + break; + + if(!(i = ListView_GetSelectedCount(This->hWndList))) + break; + + /* allocate memory for the pidl array */ + pItems = HeapAlloc(GetProcessHeap(), 0, + sizeof(LPITEMIDLIST) * i); + + /* retrieve all selected items */ + i = 0; + item_index = -1; + while(ListView_GetSelectedCount(This->hWndList) > i) + { + /* get selected item */ + item_index = ListView_GetNextItem(This->hWndList, + item_index, LVNI_SELECTED); + item.iItem = item_index; + item.mask |= LVIF_PARAM; + ListView_GetItemA(This->hWndList, &item); + + /* get item pidl */ + pItems[i] = (LPITEMIDLIST)item.lParam; + + i++; + } + + /* perform the item deletion */ + ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems); + + /* free pidl array memory */ + HeapFree(GetProcessHeap(), 0, pItems); + } + else + FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey); + } + break; + + default: + TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code); + break; + } + return 0; +} + +/********************************************************** +* ShellView_OnChange() +*/ + +static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId) +{ + + TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId); + switch(wEventId) + { + case SHCNE_MKDIR: + case SHCNE_CREATE: + LV_AddItem(This, Pidls[0]); + break; + case SHCNE_RMDIR: + case SHCNE_DELETE: + LV_DeleteItem(This, Pidls[0]); + break; + case SHCNE_RENAMEFOLDER: + case SHCNE_RENAMEITEM: + LV_RenameItem(This, Pidls[0], Pidls[1]); + break; + case SHCNE_UPDATEITEM: + break; + } + return TRUE; +} +/********************************************************** +* ShellView_WndProc +*/ + +static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) +{ + IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); + LPCREATESTRUCTA lpcs; + + TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam); + + switch (uMessage) + { + case WM_NCCREATE: + lpcs = (LPCREATESTRUCTA)lParam; + pThis = (IShellViewImpl*)(lpcs->lpCreateParams); + SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis); + pThis->hWnd = hWnd; /*set the window handle*/ + break; + + case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam)); + case WM_SETFOCUS: return ShellView_OnSetFocus(pThis); + case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis); + case WM_CREATE: return ShellView_OnCreate(pThis); + case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS); + case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam); + case WM_COMMAND: return ShellView_OnCommand(pThis, + GET_WM_COMMAND_ID(wParam, lParam), + GET_WM_COMMAND_CMD(wParam, lParam), + GET_WM_COMMAND_HWND(wParam, lParam)); + case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam); + + case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE); + return 0; + + case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList); + break; + + case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0); + + case WM_DESTROY: + RevokeDragDrop(pThis->hWnd); + SHChangeNotifyDeregister(pThis->hNotify); + break; + + case WM_ERASEBKGND: + if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) || + (pThis->FolderSettings.fFlags & FWF_TRANSPARENT)) + return 1; + break; + } + + return DefWindowProcA (hWnd, uMessage, wParam, lParam); +} +/********************************************************** +* +* +* The INTERFACE of the IShellView object +* +* +********************************************************** +* IShellView_QueryInterface +*/ +static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IShellView)) + { + *ppvObj = (IShellView*)This; + } + else if(IsEqualIID(riid, &IID_IOleCommandTarget)) + { + *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget); + } + else if(IsEqualIID(riid, &IID_IDropTarget)) + { + *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget); + } + else if(IsEqualIID(riid, &IID_IDropSource)) + { + *ppvObj = (IDropSource*)&(This->lpvtblDropSource); + } + else if(IsEqualIID(riid, &IID_IViewObject)) + { + *ppvObj = (IViewObject*)&(This->lpvtblViewObject); + } + + if(*ppvObj) + { + IUnknown_AddRef( (IUnknown*)*ppvObj ); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/********************************************************** +* IShellView_AddRef +*/ +static ULONG WINAPI IShellView_fnAddRef(IShellView * iface) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return ++(This->ref); +} +/********************************************************** +* IShellView_Release +*/ +static ULONG WINAPI IShellView_fnRelease(IShellView * iface) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IShellView(%p)\n",This); + + DestroyWindow(This->hWndList); + + if(This->pSFParent) + IShellFolder_Release(This->pSFParent); + + if(This->pSF2Parent) + IShellFolder2_Release(This->pSF2Parent); + + if (This->apidl) + SHFree(This->apidl); + + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +/********************************************************** +* ShellView_GetWindow +*/ +static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)\n",This); + + *phWnd = This->hWnd; + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + FIXME("(%p) stub\n",This); + + return E_NOTIMPL; +} + +/********************************************************** +* IShellView_TranslateAccelerator +* +* FIXME: +* use the accel functions +*/ +static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg) +{ +#if 0 + IShellViewImpl *This = (IShellViewImpl *)iface; + + FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam); +#endif + + if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST)) + { + TRACE("-- key=0x04%x\n",lpmsg->wParam) ; + } + return S_FALSE; /* not handled */ +} + +static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + FIXME("(%p) stub\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + +/* + CHAR szName[MAX_PATH]; +*/ + LRESULT lResult; + int nPartArray[1] = {-1}; + + TRACE("(%p)->(state=%x) stub\n",This, uState); + + /*don't do anything if the state isn't really changing*/ + if(This->uState == uState) + { + return S_OK; + } + + /*OnActivate handles the menu merging and internal state*/ + ShellView_OnActivate(This, uState); + + /*only do This if we are active*/ + if(uState != SVUIA_DEACTIVATE) + { + +/* + GetFolderPath is not a method of IShellFolder + IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) ); +*/ + /* set the number of parts */ + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1, + (LPARAM)nPartArray, &lResult); + + /* set the text for the parts */ +/* + IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA, + 0, (LPARAM)szName, &lResult); +*/ + } + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)\n",This); + + ListView_DeleteAllItems(This->hWndList); + ShellView_FillList(This); + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnCreateViewWindow( + IShellView * iface, + IShellView *lpPrevView, + LPCFOLDERSETTINGS lpfs, + IShellBrowser * psb, + RECT * prcView, + HWND *phWnd) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + WNDCLASSA wc; + *phWnd = 0; + + + TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd); + TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom); + + /*set up the member variables*/ + This->pShellBrowser = psb; + This->FolderSettings = *lpfs; + + /*get our parent window*/ + IShellBrowser_AddRef(This->pShellBrowser); + IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent)); + + /* try to get the ICommDlgBrowserInterface, adds a reference !!! */ + This->pCommDlgBrowser=NULL; + if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser, + (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser))) + { + TRACE("-- CommDlgBrowser\n"); + } + + /*if our window class has not been registered, then do so*/ + if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc)) + { + ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ShellView_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = shell32_hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = SV_CLASS_NAME; + + if(!RegisterClassA(&wc)) + return E_FAIL; + } + + *phWnd = CreateWindowExA(0, + SV_CLASS_NAME, + NULL, + WS_CHILD | WS_VISIBLE | WS_TABSTOP, + prcView->left, + prcView->top, + prcView->right - prcView->left, + prcView->bottom - prcView->top, + This->hWndParent, + 0, + shell32_hInstance, + (LPVOID)This); + + CheckToolbar(This); + + if(!*phWnd) return E_FAIL; + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)\n",This); + + /*Make absolutely sure all our UI is cleaned up.*/ + IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE); + + if(This->hMenu) + { + DestroyMenu(This->hMenu); + } + + DestroyWindow(This->hWnd); + if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser); + if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser); + + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs, + This->FolderSettings.ViewMode, This->FolderSettings.fFlags); + + if (!lpfs) return E_INVALIDARG; + + *lpfs = This->FolderSettings; + return NOERROR; +} + +static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + FIXME("(%p) stub\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + FIXME("(%p) stub\n",This); + + return S_OK; +} + +static HRESULT WINAPI IShellView_fnSelectItem( + IShellView * iface, + LPCITEMIDLIST pidl, + UINT uFlags) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + int i; + + TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags); + + i = LV_FindItemByPidl(This, pidl); + + if (i != -1) + { + LVITEMA lvItem; + + if(uFlags & SVSI_ENSUREVISIBLE) + ListView_EnsureVisible(This->hWndList, i, 0); + + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.mask = LVIF_STATE; + lvItem.iItem = 0; + + while(ListView_GetItemA(This->hWndList, &lvItem)) + { + if (lvItem.iItem == i) + { + if (uFlags & SVSI_SELECT) + lvItem.state |= LVIS_SELECTED; + else + lvItem.state &= ~LVIS_SELECTED; + + if(uFlags & SVSI_FOCUSED) + lvItem.state &= ~LVIS_FOCUSED; + } + else + { + if (uFlags & SVSI_DESELECTOTHERS) + lvItem.state &= ~LVIS_SELECTED; + } + ListView_SetItemA(This->hWndList, &lvItem); + lvItem.iItem++; + } + + + if(uFlags & SVSI_EDIT) + ListView_EditLabelA(This->hWndList, i); + + } + return S_OK; +} + +static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut) +{ + IShellViewImpl *This = (IShellViewImpl *)iface; + + TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut); + + *ppvOut = NULL; + + switch(uItem) + { + case SVGIO_BACKGROUND: + *ppvOut = ISvBgCm_Constructor(This->pSFParent); + break; + + case SVGIO_SELECTION: + ShellView_GetSelections(This); + IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut); + break; + } + TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut); + + if(!*ppvOut) return E_OUTOFMEMORY; + + return S_OK; +} + +static struct IShellViewVtbl svvt = +{ + IShellView_fnQueryInterface, + IShellView_fnAddRef, + IShellView_fnRelease, + IShellView_fnGetWindow, + IShellView_fnContextSensitiveHelp, + IShellView_fnTranslateAccelerator, + IShellView_fnEnableModeless, + IShellView_fnUIActivate, + IShellView_fnRefresh, + IShellView_fnCreateViewWindow, + IShellView_fnDestroyViewWindow, + IShellView_fnGetCurrentInfo, + IShellView_fnAddPropertySheetPages, + IShellView_fnSaveViewState, + IShellView_fnSelectItem, + IShellView_fnGetItemObject +}; + + +/********************************************************** + * ISVOleCmdTarget_QueryInterface (IUnknown) + */ +static HRESULT WINAPI ISVOleCmdTarget_QueryInterface( + IOleCommandTarget * iface, + REFIID iid, + LPVOID* ppvObj) +{ + _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); + + return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj); +} + +/********************************************************** + * ISVOleCmdTarget_AddRef (IUnknown) + */ +static ULONG WINAPI ISVOleCmdTarget_AddRef( + IOleCommandTarget * iface) +{ + _ICOM_THIS_From_IOleCommandTarget(IShellFolder, iface); + + return IShellFolder_AddRef((IShellFolder*)This); +} + +/********************************************************** + * ISVOleCmdTarget_Release (IUnknown) + */ +static ULONG WINAPI ISVOleCmdTarget_Release( + IOleCommandTarget * iface) +{ + _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); + + return IShellFolder_Release((IShellFolder*)This); +} + +/********************************************************** + * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) + */ +static HRESULT WINAPI ISVOleCmdTarget_QueryStatus( + IOleCommandTarget *iface, + const GUID* pguidCmdGroup, + ULONG cCmds, + OLECMD * prgCmds, + OLECMDTEXT* pCmdText) +{ + UINT i; + _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); + + FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n", + This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); + + if (!prgCmds) + return E_POINTER; + for (i = 0; i < cCmds; i++) + { + FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID); + prgCmds[i].cmdf = 0; + } + return OLECMDERR_E_UNKNOWNGROUP; +} + +/********************************************************** + * ISVOleCmdTarget_Exec (IOleCommandTarget) + * + * nCmdID is the OLECMDID_* enumeration + */ +static HRESULT WINAPI ISVOleCmdTarget_Exec( + IOleCommandTarget *iface, + const GUID* pguidCmdGroup, + DWORD nCmdID, + DWORD nCmdexecopt, + VARIANT* pvaIn, + VARIANT* pvaOut) +{ + _ICOM_THIS_From_IOleCommandTarget(IShellViewImpl, iface); + + FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n", + This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); + + if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) && + (nCmdID == 0x29) && + (nCmdexecopt == 4) && pvaOut) + return S_OK; + if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) && + (nCmdID == 9) && + (nCmdexecopt == 0)) + return 1; + + return OLECMDERR_E_UNKNOWNGROUP; +} + +static IOleCommandTargetVtbl ctvt = +{ + ISVOleCmdTarget_QueryInterface, + ISVOleCmdTarget_AddRef, + ISVOleCmdTarget_Release, + ISVOleCmdTarget_QueryStatus, + ISVOleCmdTarget_Exec +}; + +/********************************************************** + * ISVDropTarget implementation + */ + +static HRESULT WINAPI ISVDropTarget_QueryInterface( + IDropTarget *iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); +} + +static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_AddRef((IShellFolder*)This); +} + +static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_Release((IShellFolder*)This); +} + +static HRESULT WINAPI ISVDropTarget_DragEnter( + IDropTarget *iface, + IDataObject *pDataObject, + DWORD grfKeyState, + POINTL pt, + DWORD *pdwEffect) +{ + + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ISVDropTarget_DragOver( + IDropTarget *iface, + DWORD grfKeyState, + POINTL pt, + DWORD *pdwEffect) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ISVDropTarget_DragLeave( + IDropTarget *iface) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ISVDropTarget_Drop( + IDropTarget *iface, + IDataObject* pDataObject, + DWORD grfKeyState, + POINTL pt, + DWORD *pdwEffect) +{ + _ICOM_THIS_From_IDropTarget(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} + +static struct IDropTargetVtbl dtvt = +{ + ISVDropTarget_QueryInterface, + ISVDropTarget_AddRef, + ISVDropTarget_Release, + ISVDropTarget_DragEnter, + ISVDropTarget_DragOver, + ISVDropTarget_DragLeave, + ISVDropTarget_Drop +}; + +/********************************************************** + * ISVDropSource implementation + */ + +static HRESULT WINAPI ISVDropSource_QueryInterface( + IDropSource *iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); +} + +static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface) +{ + _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_AddRef((IShellFolder*)This); +} + +static ULONG WINAPI ISVDropSource_Release( IDropSource *iface) +{ + _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_Release((IShellFolder*)This); +} +static HRESULT WINAPI ISVDropSource_QueryContinueDrag( + IDropSource *iface, + BOOL fEscapePressed, + DWORD grfKeyState) +{ + _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); + TRACE("(%p)\n",This); + + if (fEscapePressed) + return DRAGDROP_S_CANCEL; + else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) + return DRAGDROP_S_DROP; + else + return NOERROR; +} + +static HRESULT WINAPI ISVDropSource_GiveFeedback( + IDropSource *iface, + DWORD dwEffect) +{ + _ICOM_THIS_From_IDropSource(IShellViewImpl, iface); + TRACE("(%p)\n",This); + + return DRAGDROP_S_USEDEFAULTCURSORS; +} + +static struct IDropSourceVtbl dsvt = +{ + ISVDropSource_QueryInterface, + ISVDropSource_AddRef, + ISVDropSource_Release, + ISVDropSource_QueryContinueDrag, + ISVDropSource_GiveFeedback +}; +/********************************************************** + * ISVViewObject implementation + */ + +static HRESULT WINAPI ISVViewObject_QueryInterface( + IViewObject *iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj); +} + +static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface) +{ + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_AddRef((IShellFolder*)This); +} + +static ULONG WINAPI ISVViewObject_Release( IViewObject *iface) +{ + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + TRACE("(%p)->(count=%lu)\n",This,This->ref); + + return IShellFolder_Release((IShellFolder*)This); +} + +static HRESULT WINAPI ISVViewObject_Draw( + IViewObject *iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcTargetDev, + HDC hdcDraw, + LPCRECTL lprcBounds, + LPCRECTL lprcWBounds, + BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), + ULONG_PTR dwContinue) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISVViewObject_GetColorSet( + IViewObject *iface, + DWORD dwDrawAspect, + LONG lindex, + void *pvAspect, + DVTARGETDEVICE* ptd, + HDC hicTargetDevice, + LOGPALETTE** ppColorSet) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISVViewObject_Freeze( + IViewObject *iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DWORD* pdwFreeze) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISVViewObject_Unfreeze( + IViewObject *iface, + DWORD dwFreeze) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISVViewObject_SetAdvise( + IViewObject *iface, + DWORD aspects, + DWORD advf, + IAdviseSink* pAdvSink) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} +static HRESULT WINAPI ISVViewObject_GetAdvise( + IViewObject *iface, + DWORD* pAspects, + DWORD* pAdvf, + IAdviseSink** ppAdvSink) +{ + + _ICOM_THIS_From_IViewObject(IShellViewImpl, iface); + + FIXME("Stub: This=%p\n",This); + + return E_NOTIMPL; +} + + +static struct IViewObjectVtbl vovt = +{ + ISVViewObject_QueryInterface, + ISVViewObject_AddRef, + ISVViewObject_Release, + ISVViewObject_Draw, + ISVViewObject_GetColorSet, + ISVViewObject_Freeze, + ISVViewObject_Unfreeze, + ISVViewObject_SetAdvise, + ISVViewObject_GetAdvise +}; diff --git a/reactos/lib/shell32/shpolicy.c b/reactos/lib/shell32/shpolicy.c index d0d24ec9b8f..8e435425780 100644 --- a/reactos/lib/shell32/shpolicy.c +++ b/reactos/lib/shell32/shpolicy.c @@ -1,915 +1,915 @@ -/* - * shpolicy.c - Data for shell/system policies. - * - * Copyright 1999 Ian Schmidt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES: - * - * Some of these policies can be tweaked via the System Policy - * Editor which came with the Win95 Migration Guide, although - * there doesn't appear to be an updated Win98 version that - * would handle the many new policies introduced since then. - * You could easily write one with the information in - * this file... - * - * Up to date as of SHELL32 v5.00 (W2K) - */ - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" - -#include "shell32_main.h" -#include "shlobj.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -#define SHELL_NO_POLICY 0xffffffff - -typedef struct tagPOLICYDAT -{ - DWORD policy; /* policy value passed to SHRestricted */ - LPCSTR appstr; /* application str such as "Explorer" */ - LPCSTR keystr; /* name of the actual registry key / policy */ - DWORD cache; /* cached value or 0xffffffff for invalid */ -} POLICYDATA, *LPPOLICYDATA; - -/* registry strings */ -static const CHAR strRegistryPolicyA[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies"; -static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o', - 's','o','f','t','\\','W','i','n','d','o','w','s','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n', - '\\','P','o','l','i','c','i','e','s',0}; -static const CHAR strPolicyA[] = "Policy"; -static const WCHAR strPolicyW[] = {'P','o','l','i','c','y',0}; - -/* application strings */ - -static const char strExplorer[] = {"Explorer"}; -static const char strActiveDesk[] = {"ActiveDesktop"}; -static const char strWinOldApp[] = {"WinOldApp"}; -static const char strAddRemoveProgs[] = {"AddRemoveProgs"}; - -/* key strings */ - -static const char strNoFileURL[] = {"NoFileUrl"}; -static const char strNoFolderOptions[] = {"NoFolderOptions"}; -static const char strNoChangeStartMenu[] = {"NoChangeStartMenu"}; -static const char strNoWindowsUpdate[] = {"NoWindowsUpdate"}; -static const char strNoSetActiveDesktop[] = {"NoSetActiveDesktop"}; -static const char strNoForgetSoftwareUpdate[] = {"NoForgetSoftwareUpdate"}; -static const char strNoMSAppLogo[] = {"NoMSAppLogo5ChannelNotify"}; -static const char strForceCopyACLW[] = {"ForceCopyACLWithFile"}; -static const char strNoResolveTrk[] = {"NoResolveTrack"}; -static const char strNoResolveSearch[] = {"NoResolveSearch"}; -static const char strNoEditComponent[] = {"NoEditingComponents"}; -static const char strNoMovingBand[] = {"NoMovingBands"}; -static const char strNoCloseDragDrop[] = {"NoCloseDragDropBands"}; -static const char strNoCloseComponent[] = {"NoClosingComponents"}; -static const char strNoDelComponent[] = {"NoDeletingComponents"}; -static const char strNoAddComponent[] = {"NoAddingComponents"}; -static const char strNoComponent[] = {"NoComponents"}; -static const char strNoChangeWallpaper[] = {"NoChangingWallpaper"}; -static const char strNoHTMLWallpaper[] = {"NoHTMLWallpaper"}; -static const char strNoCustomWebView[] = {"NoCustomizeWebView"}; -static const char strClassicShell[] = {"ClassicShell"}; -static const char strClearRecentDocs[] = {"ClearRecentDocsOnExit"}; -static const char strNoFavoritesMenu[] = {"NoFavoritesMenu"}; -static const char strNoActiveDesktopChanges[] = {"NoActiveDesktopChanges"}; -static const char strNoActiveDesktop[] = {"NoActiveDesktop"}; -static const char strNoRecentDocMenu[] = {"NoRecentDocsMenu"}; -static const char strNoRecentDocHistory[] = {"NoRecentDocsHistory"}; -static const char strNoInetIcon[] = {"NoInternetIcon"}; -static const char strNoSettingsWizard[] = {"NoSettingsWizards"}; -static const char strNoLogoff[] = {"NoLogoff"}; -static const char strNoNetConDis[] = {"NoNetConnectDisconnect"}; -static const char strNoViewContextMenu[] = {"NoViewContextMenu"}; -static const char strNoTrayContextMenu[] = {"NoTrayContextMenu"}; -static const char strNoWebMenu[] = {"NoWebMenu"}; -static const char strLnkResolveIgnoreLnkInfo[] = {"LinkResolveIgnoreLinkInfo"}; -static const char strNoCommonGroups[] = {"NoCommonGroups"}; -static const char strEnforceShlExtSecurity[] = {"EnforceShellExtensionSecurity"}; -static const char strNoRealMode[] = {"NoRealMode"}; -static const char strMyDocsOnNet[] = {"MyDocsOnNet"}; -static const char strNoStartMenuSubfolder[] = {"NoStartMenuSubFolders"}; -static const char strNoAddPrinters[] = {"NoAddPrinter"}; -static const char strNoDeletePrinters[] = {"NoDeletePrinter"}; -static const char strNoPrintTab[] = {"NoPrinterTabs"}; -static const char strRestrictRun[] = {"RestrictRun"}; -static const char strNoStartBanner[] = {"NoStartBanner"}; -static const char strNoNetworkNeighborhood[] = {"NoNetHood"}; -static const char strNoDriveTypeAtRun[] = {"NoDriveTypeAutoRun"}; -static const char strNoDrivesAutoRun[] = {"NoDriveAutoRun"}; -static const char strSeparateProcess[] = {"SeparateProcess"}; -static const char strNoDrives[] = {"NoDrives"}; -static const char strNoFind[] = {"NoFind"}; -static const char strNoDesktop[] = {"NoDesktop"}; -static const char strNoSetTaskBar[] = {"NoSetTaskbar"}; -static const char strNoSetFld[] = {"NoSetFolders"}; -static const char strNoFileMenu[] = {"NoFileMenu"}; -static const char strNoSaveSetting[] = {"NoSaveSettings"}; -static const char strNoClose[] = {"NoClose"}; -static const char strNoRun[] = {"NoRun"}; - -/* policy data array */ -POLICYDATA sh32_policy_table[] = -{ - { - REST_NORUN, - strExplorer, - strNoRun, - SHELL_NO_POLICY - }, - { - REST_NOCLOSE, - strExplorer, - strNoClose, - SHELL_NO_POLICY - }, - { - REST_NOSAVESET, - strExplorer, - strNoSaveSetting, - SHELL_NO_POLICY - }, - { - REST_NOFILEMENU, - strExplorer, - strNoFileMenu, - SHELL_NO_POLICY - }, - { - REST_NOSETFOLDERS, - strExplorer, - strNoSetFld, - SHELL_NO_POLICY - }, - { - REST_NOSETTASKBAR, - strExplorer, - strNoSetTaskBar, - SHELL_NO_POLICY - }, - { - REST_NODESKTOP, - strExplorer, - strNoDesktop, - SHELL_NO_POLICY - }, - { - REST_NOFIND, - strExplorer, - strNoFind, - SHELL_NO_POLICY - }, - { - REST_NODRIVES, - strExplorer, - strNoDrives, - SHELL_NO_POLICY - }, - { - REST_NODRIVEAUTORUN, - strExplorer, - strNoDrivesAutoRun, - SHELL_NO_POLICY - }, - { - REST_NODRIVETYPEAUTORUN, - strExplorer, - strNoDriveTypeAtRun, - SHELL_NO_POLICY - }, - { - REST_NONETHOOD, - strExplorer, - strNoNetworkNeighborhood, - SHELL_NO_POLICY - }, - { - REST_STARTBANNER, - strExplorer, - strNoStartBanner, - SHELL_NO_POLICY - }, - { - REST_RESTRICTRUN, - strExplorer, - strRestrictRun, - SHELL_NO_POLICY - }, - { - REST_NOPRINTERTABS, - strExplorer, - strNoPrintTab, - SHELL_NO_POLICY - }, - { - REST_NOPRINTERDELETE, - strExplorer, - strNoDeletePrinters, - SHELL_NO_POLICY - }, - { - REST_NOPRINTERADD, - strExplorer, - strNoAddPrinters, - SHELL_NO_POLICY - }, - { - REST_NOSTARTMENUSUBFOLDERS, - strExplorer, - strNoStartMenuSubfolder, - SHELL_NO_POLICY - }, - { - REST_MYDOCSONNET, - strExplorer, - strMyDocsOnNet, - SHELL_NO_POLICY - }, - { - REST_NOEXITTODOS, - strWinOldApp, - strNoRealMode, - SHELL_NO_POLICY - }, - { - REST_ENFORCESHELLEXTSECURITY, - strExplorer, - strEnforceShlExtSecurity, - SHELL_NO_POLICY - }, - { - REST_LINKRESOLVEIGNORELINKINFO, - strExplorer, - strLnkResolveIgnoreLnkInfo, - SHELL_NO_POLICY - }, - { - REST_NOCOMMONGROUPS, - strExplorer, - strNoCommonGroups, - SHELL_NO_POLICY - }, - { - REST_SEPARATEDESKTOPPROCESS, - strExplorer, - strSeparateProcess, - SHELL_NO_POLICY - }, - { - REST_NOWEB, - strExplorer, - strNoWebMenu, - SHELL_NO_POLICY - }, - { - REST_NOTRAYCONTEXTMENU, - strExplorer, - strNoTrayContextMenu, - SHELL_NO_POLICY - }, - { - REST_NOVIEWCONTEXTMENU, - strExplorer, - strNoViewContextMenu, - SHELL_NO_POLICY - }, - { - REST_NONETCONNECTDISCONNECT, - strExplorer, - strNoNetConDis, - SHELL_NO_POLICY - }, - { - REST_STARTMENULOGOFF, - strExplorer, - strNoLogoff, - SHELL_NO_POLICY - }, - { - REST_NOSETTINGSASSIST, - strExplorer, - strNoSettingsWizard, - SHELL_NO_POLICY - }, - { - REST_NOINTERNETICON, - strExplorer, - strNoInetIcon, - SHELL_NO_POLICY - }, - { - REST_NORECENTDOCSHISTORY, - strExplorer, - strNoRecentDocHistory, - SHELL_NO_POLICY - }, - { - REST_NORECENTDOCSMENU, - strExplorer, - strNoRecentDocMenu, - SHELL_NO_POLICY - }, - { - REST_NOACTIVEDESKTOP, - strExplorer, - strNoActiveDesktop, - SHELL_NO_POLICY - }, - { - REST_NOACTIVEDESKTOPCHANGES, - strExplorer, - strNoActiveDesktopChanges, - SHELL_NO_POLICY - }, - { - REST_NOFAVORITESMENU, - strExplorer, - strNoFavoritesMenu, - SHELL_NO_POLICY - }, - { - REST_CLEARRECENTDOCSONEXIT, - strExplorer, - strClearRecentDocs, - SHELL_NO_POLICY - }, - { - REST_CLASSICSHELL, - strExplorer, - strClassicShell, - SHELL_NO_POLICY - }, - { - REST_NOCUSTOMIZEWEBVIEW, - strExplorer, - strNoCustomWebView, - SHELL_NO_POLICY - }, - { - REST_NOHTMLWALLPAPER, - strActiveDesk, - strNoHTMLWallpaper, - SHELL_NO_POLICY - }, - { - REST_NOCHANGINGWALLPAPER, - strActiveDesk, - strNoChangeWallpaper, - SHELL_NO_POLICY - }, - { - REST_NODESKCOMP, - strActiveDesk, - strNoComponent, - SHELL_NO_POLICY - }, - { - REST_NOADDDESKCOMP, - strActiveDesk, - strNoAddComponent, - SHELL_NO_POLICY - }, - { - REST_NODELDESKCOMP, - strActiveDesk, - strNoDelComponent, - SHELL_NO_POLICY - }, - { - REST_NOCLOSEDESKCOMP, - strActiveDesk, - strNoCloseComponent, - SHELL_NO_POLICY - }, - { - REST_NOCLOSE_DRAGDROPBAND, - strActiveDesk, - strNoCloseDragDrop, - SHELL_NO_POLICY - }, - { - REST_NOMOVINGBAND, - strActiveDesk, - strNoMovingBand, - SHELL_NO_POLICY - }, - { - REST_NOEDITDESKCOMP, - strActiveDesk, - strNoEditComponent, - SHELL_NO_POLICY - }, - { - REST_NORESOLVESEARCH, - strExplorer, - strNoResolveSearch, - SHELL_NO_POLICY - }, - { - REST_NORESOLVETRACK, - strExplorer, - strNoResolveTrk, - SHELL_NO_POLICY - }, - { - REST_FORCECOPYACLWITHFILE, - strExplorer, - strForceCopyACLW, - SHELL_NO_POLICY - }, - { - REST_NOLOGO3CHANNELNOTIFY, - strExplorer, - strNoMSAppLogo, - SHELL_NO_POLICY - }, - { - REST_NOFORGETSOFTWAREUPDATE, - strExplorer, - strNoForgetSoftwareUpdate, - SHELL_NO_POLICY - }, - { - REST_NOSETACTIVEDESKTOP, - strExplorer, - strNoSetActiveDesktop, - SHELL_NO_POLICY - }, - { - REST_NOUPDATEWINDOWS, - strExplorer, - strNoWindowsUpdate, - SHELL_NO_POLICY - }, - { - REST_NOCHANGESTARMENU, - strExplorer, - strNoChangeStartMenu, - SHELL_NO_POLICY - }, - { - REST_NOFOLDEROPTIONS, - strExplorer, - strNoFolderOptions, - SHELL_NO_POLICY - }, - { - REST_HASFINDCOMPUTERS, - strExplorer, - "FindComputers", - SHELL_NO_POLICY - }, - { - REST_INTELLIMENUS, - strExplorer, - "IntelliMenus", - SHELL_NO_POLICY - }, - { - REST_RUNDLGMEMCHECKBOX, - strExplorer, - "MemCheckBoxInRunDlg", - SHELL_NO_POLICY - }, - { - REST_ARP_ShowPostSetup, - strAddRemoveProgs, - "ShowPostSetup", - SHELL_NO_POLICY - }, - { - REST_NOCSC, - strExplorer, - "NoSyncAll", - SHELL_NO_POLICY - }, - { - REST_NOCONTROLPANEL, - strExplorer, - "NoControlPanel", - SHELL_NO_POLICY - }, - { - REST_ENUMWORKGROUP, - strExplorer, - "EnumWorkgroup", - SHELL_NO_POLICY - }, - { - REST_ARP_NOARP, - strAddRemoveProgs, - "NoAddRemovePrograms", - SHELL_NO_POLICY - }, - { - REST_ARP_NOREMOVEPAGE, - strAddRemoveProgs, - "NoRemovePage", - SHELL_NO_POLICY - }, - { - REST_ARP_NOADDPAGE, - strAddRemoveProgs, - "NoAddPage", - SHELL_NO_POLICY - }, - { - REST_ARP_NOWINSETUPPAGE, - strAddRemoveProgs, - "NoWindowsSetupPage", - SHELL_NO_POLICY - }, - { - REST_GREYMSIADS, - strExplorer, - "", - SHELL_NO_POLICY - }, - { - REST_NOCHANGEMAPPEDDRIVELABEL, - strExplorer, - "NoChangeMappedDriveLabel", - SHELL_NO_POLICY - }, - { - REST_NOCHANGEMAPPEDDRIVECOMMENT, - strExplorer, - "NoChangeMappedDriveComment", - SHELL_NO_POLICY - }, - { - REST_MaxRecentDocs, - strExplorer, - "MaxRecentDocs", - SHELL_NO_POLICY - }, - { - REST_NONETWORKCONNECTIONS, - strExplorer, - "NoNetworkConnections", - SHELL_NO_POLICY - }, - { - REST_FORCESTARTMENULOGOFF, - strExplorer, - "ForceStartMenuLogoff", - SHELL_NO_POLICY - }, - { - REST_NOWEBVIEW, - strExplorer, - "NoWebView", - SHELL_NO_POLICY - }, - { - REST_NOCUSTOMIZETHISFOLDER, - strExplorer, - "NoCustomizeThisFolder", - SHELL_NO_POLICY - }, - { - REST_NOENCRYPTION, - strExplorer, - "NoEncryption", - SHELL_NO_POLICY - }, - { - REST_ALLOWFRENCHENCRYPTION, - strExplorer, - "AllowFrenchEncryption", - SHELL_NO_POLICY - }, - { - REST_DONTSHOWSUPERHIDDEN, - strExplorer, - "DontShowSuperHidden", - SHELL_NO_POLICY - }, - { - REST_NOSHELLSEARCHBUTTON, - strExplorer, - "NoShellSearchButton", - SHELL_NO_POLICY - }, - { - REST_NOHARDWARETAB, - strExplorer, - "NoHardwareTab", - SHELL_NO_POLICY - }, - { - REST_NORUNASINSTALLPROMPT, - strExplorer, - "NoRunasInstallPrompt", - SHELL_NO_POLICY - }, - { - REST_PROMPTRUNASINSTALLNETPATH, - strExplorer, - "PromptRunasInstallNetPath", - SHELL_NO_POLICY - }, - { - REST_NOMANAGEMYCOMPUTERVERB, - strExplorer, - "NoManageMyComputerVerb", - SHELL_NO_POLICY - }, - { - REST_NORECENTDOCSNETHOOD, - strExplorer, - "NoRecentDocsNetHood", - SHELL_NO_POLICY - }, - { - REST_DISALLOWRUN, - strExplorer, - "DisallowRun", - SHELL_NO_POLICY - }, - { - REST_NOWELCOMESCREEN, - strExplorer, - "NoWelcomeScreen", - SHELL_NO_POLICY - }, - { - REST_RESTRICTCPL, - strExplorer, - "RestrictCpl", - SHELL_NO_POLICY - }, - { - REST_DISALLOWCPL, - strExplorer, - "DisallowCpl", - SHELL_NO_POLICY - }, - { - REST_NOSMBALLOONTIP, - strExplorer, - "NoSMBalloonTip", - SHELL_NO_POLICY - }, - { - REST_NOSMHELP, - strExplorer, - "NoSMHelp", - SHELL_NO_POLICY - }, - { - REST_NOWINKEYS, - strExplorer, - "NoWinKeys", - SHELL_NO_POLICY - }, - { - REST_NOENCRYPTONMOVE, - strExplorer, - "NoEncryptOnMove", - SHELL_NO_POLICY - }, - { - REST_NOLOCALMACHINERUN, - strExplorer, - "DisableLocalMachineRun", - SHELL_NO_POLICY - }, - { - REST_NOCURRENTUSERRUN, - strExplorer, - "DisableCurrentUserRun", - SHELL_NO_POLICY - }, - { - REST_NOLOCALMACHINERUNONCE, - strExplorer, - "DisableLocalMachineRunOnce", - SHELL_NO_POLICY - }, - { - REST_NOCURRENTUSERRUNONCE, - strExplorer, - "DisableCurrentUserRunOnce", - SHELL_NO_POLICY - }, - { - REST_FORCEACTIVEDESKTOPON, - strExplorer, - "ForceActiveDesktopOn", - SHELL_NO_POLICY - }, - { - REST_NOCOMPUTERSNEARME, - strExplorer, - "NoComputersNearMe", - SHELL_NO_POLICY - }, - { - REST_NOVIEWONDRIVE, - strExplorer, - "NoViewOnDrive", - SHELL_NO_POLICY - }, - { - REST_NONETCRAWL, - strExplorer, - "NoNetCrawl", - SHELL_NO_POLICY - }, - { - REST_NOSHAREDDOCUMENTS, - strExplorer, - "NoSharedDocs", - SHELL_NO_POLICY - }, - { - REST_NOSMMYDOCS, - strExplorer, - "NoSMMyDocs", - SHELL_NO_POLICY - }, -/* 0x4000050 - 0x4000060 */ - { - REST_NONLEGACYSHELLMODE, - strExplorer, - "NoneLegacyShellMode", - SHELL_NO_POLICY - }, - { - REST_STARTRUNNOHOMEPATH, - strExplorer, - "StartRunNoHOMEPATH", - SHELL_NO_POLICY - }, -/* 0x4000061 - 0x4000086 */ - { - REST_NODISCONNECT, - strExplorer, - "NoDisconnect", - SHELL_NO_POLICY - }, - { - REST_NOSECURITY, - strExplorer, - "NoNTSecurity", - SHELL_NO_POLICY - }, - { - REST_NOFILEASSOCIATE, - strExplorer, - "NoFileAssociate", - SHELL_NO_POLICY - }, - { - 0x50000024, - strExplorer, - strNoFileURL, - SHELL_NO_POLICY - }, - { - 0, - 0, - 0, - SHELL_NO_POLICY - } -}; - -/************************************************************************* - * SHRestricted [SHELL32.100] - * - * Get the value associated with a policy Id. - * - * PARAMS - * pol [I] Policy Id - * - * RETURNS - * The queried value for the policy. - * - * NOTES - * Exported by ordinal. - * This function caches the retrieved values to prevent unnecessary registry access, - * if SHInitRestricted() was previously called. - * - * REFERENCES - * a: MS System Policy Editor. - * b: 98Lite 2.0 (which uses many of these policy keys) http://www.98lite.net/ - * c: 'The Windows 95 Registry', by John Woram, 1996 MIS: Press - */ -DWORD WINAPI SHRestricted (RESTRICTIONS policy) -{ - char regstr[256]; - HKEY xhkey; - DWORD retval, datsize = 4; - LPPOLICYDATA p; - - TRACE("(%08x)\n", policy); - - /* scan to see if we know this policy ID */ - for (p = sh32_policy_table; p->policy; p++) - { - if (policy == p->policy) - { - break; - } - } - - if (p->policy == 0) - { - /* we don't know this policy, return 0 */ - TRACE("unknown policy: (%08x)\n", policy); - return 0; - } - - /* we have a known policy */ - - /* first check if this policy has been cached, return it if so */ - if (p->cache != SHELL_NO_POLICY) - { - return p->cache; - } - - lstrcpyA(regstr, strRegistryPolicyA); - lstrcatA(regstr, p->appstr); - - /* return 0 and don't set the cache if any registry errors occur */ - retval = 0; - if (RegOpenKeyA(HKEY_CURRENT_USER, regstr, &xhkey) == ERROR_SUCCESS) - { - if (RegQueryValueExA(xhkey, p->keystr, NULL, NULL, (LPBYTE)&retval, &datsize) == ERROR_SUCCESS) - { - p->cache = retval; - } - RegCloseKey(xhkey); - } - return retval; -} - -/************************************************************************* - * SHInitRestricted [SHELL32.244] - * - * Initialise the policy cache to speed up calls to SHRestricted(). - * - * PARAMS - * unused [I] Reserved. - * inpRegKey [I] Registry key to scan. - * - * RETURNS - * Success: -1. The policy cache is initialised. - * Failure: 0, if inpRegKey is any value other than NULL, "Policy", or - * "Software\Microsoft\Windows\CurrentVersion\Policies". - * - * NOTES - * Exported by ordinal. Introduced in Win98. - */ -BOOL WINAPI SHInitRestricted(LPCVOID unused, LPCVOID inpRegKey) -{ - TRACE("(%p, %p)\n", unused, inpRegKey); - - /* first check - if input is non-NULL and points to the secret - key string, then pass. Otherwise return 0. - */ - if (inpRegKey != NULL) - { - if (SHELL_OsIsUnicode()) - { - if (lstrcmpiW((LPCWSTR)inpRegKey, strRegistryPolicyW) && - lstrcmpiW((LPCWSTR)inpRegKey, strPolicyW)) - /* doesn't match, fail */ - return 0; - } - else - { - if (lstrcmpiA((LPCSTR)inpRegKey, strRegistryPolicyA) && - lstrcmpiA((LPCSTR)inpRegKey, strPolicyA)) - /* doesn't match, fail */ - return 0; - } - } - - return TRUE; -} +/* + * shpolicy.c - Data for shell/system policies. + * + * Copyright 1999 Ian Schmidt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES: + * + * Some of these policies can be tweaked via the System Policy + * Editor which came with the Win95 Migration Guide, although + * there doesn't appear to be an updated Win98 version that + * would handle the many new policies introduced since then. + * You could easily write one with the information in + * this file... + * + * Up to date as of SHELL32 v5.00 (W2K) + */ + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" + +#include "shell32_main.h" +#include "shlobj.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +#define SHELL_NO_POLICY 0xffffffff + +typedef struct tagPOLICYDAT +{ + DWORD policy; /* policy value passed to SHRestricted */ + LPCSTR appstr; /* application str such as "Explorer" */ + LPCSTR keystr; /* name of the actual registry key / policy */ + DWORD cache; /* cached value or 0xffffffff for invalid */ +} POLICYDATA, *LPPOLICYDATA; + +/* registry strings */ +static const CHAR strRegistryPolicyA[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies"; +static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o', + 's','o','f','t','\\','W','i','n','d','o','w','s','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n', + '\\','P','o','l','i','c','i','e','s',0}; +static const CHAR strPolicyA[] = "Policy"; +static const WCHAR strPolicyW[] = {'P','o','l','i','c','y',0}; + +/* application strings */ + +static const char strExplorer[] = {"Explorer"}; +static const char strActiveDesk[] = {"ActiveDesktop"}; +static const char strWinOldApp[] = {"WinOldApp"}; +static const char strAddRemoveProgs[] = {"AddRemoveProgs"}; + +/* key strings */ + +static const char strNoFileURL[] = {"NoFileUrl"}; +static const char strNoFolderOptions[] = {"NoFolderOptions"}; +static const char strNoChangeStartMenu[] = {"NoChangeStartMenu"}; +static const char strNoWindowsUpdate[] = {"NoWindowsUpdate"}; +static const char strNoSetActiveDesktop[] = {"NoSetActiveDesktop"}; +static const char strNoForgetSoftwareUpdate[] = {"NoForgetSoftwareUpdate"}; +static const char strNoMSAppLogo[] = {"NoMSAppLogo5ChannelNotify"}; +static const char strForceCopyACLW[] = {"ForceCopyACLWithFile"}; +static const char strNoResolveTrk[] = {"NoResolveTrack"}; +static const char strNoResolveSearch[] = {"NoResolveSearch"}; +static const char strNoEditComponent[] = {"NoEditingComponents"}; +static const char strNoMovingBand[] = {"NoMovingBands"}; +static const char strNoCloseDragDrop[] = {"NoCloseDragDropBands"}; +static const char strNoCloseComponent[] = {"NoClosingComponents"}; +static const char strNoDelComponent[] = {"NoDeletingComponents"}; +static const char strNoAddComponent[] = {"NoAddingComponents"}; +static const char strNoComponent[] = {"NoComponents"}; +static const char strNoChangeWallpaper[] = {"NoChangingWallpaper"}; +static const char strNoHTMLWallpaper[] = {"NoHTMLWallpaper"}; +static const char strNoCustomWebView[] = {"NoCustomizeWebView"}; +static const char strClassicShell[] = {"ClassicShell"}; +static const char strClearRecentDocs[] = {"ClearRecentDocsOnExit"}; +static const char strNoFavoritesMenu[] = {"NoFavoritesMenu"}; +static const char strNoActiveDesktopChanges[] = {"NoActiveDesktopChanges"}; +static const char strNoActiveDesktop[] = {"NoActiveDesktop"}; +static const char strNoRecentDocMenu[] = {"NoRecentDocsMenu"}; +static const char strNoRecentDocHistory[] = {"NoRecentDocsHistory"}; +static const char strNoInetIcon[] = {"NoInternetIcon"}; +static const char strNoSettingsWizard[] = {"NoSettingsWizards"}; +static const char strNoLogoff[] = {"NoLogoff"}; +static const char strNoNetConDis[] = {"NoNetConnectDisconnect"}; +static const char strNoViewContextMenu[] = {"NoViewContextMenu"}; +static const char strNoTrayContextMenu[] = {"NoTrayContextMenu"}; +static const char strNoWebMenu[] = {"NoWebMenu"}; +static const char strLnkResolveIgnoreLnkInfo[] = {"LinkResolveIgnoreLinkInfo"}; +static const char strNoCommonGroups[] = {"NoCommonGroups"}; +static const char strEnforceShlExtSecurity[] = {"EnforceShellExtensionSecurity"}; +static const char strNoRealMode[] = {"NoRealMode"}; +static const char strMyDocsOnNet[] = {"MyDocsOnNet"}; +static const char strNoStartMenuSubfolder[] = {"NoStartMenuSubFolders"}; +static const char strNoAddPrinters[] = {"NoAddPrinter"}; +static const char strNoDeletePrinters[] = {"NoDeletePrinter"}; +static const char strNoPrintTab[] = {"NoPrinterTabs"}; +static const char strRestrictRun[] = {"RestrictRun"}; +static const char strNoStartBanner[] = {"NoStartBanner"}; +static const char strNoNetworkNeighborhood[] = {"NoNetHood"}; +static const char strNoDriveTypeAtRun[] = {"NoDriveTypeAutoRun"}; +static const char strNoDrivesAutoRun[] = {"NoDriveAutoRun"}; +static const char strSeparateProcess[] = {"SeparateProcess"}; +static const char strNoDrives[] = {"NoDrives"}; +static const char strNoFind[] = {"NoFind"}; +static const char strNoDesktop[] = {"NoDesktop"}; +static const char strNoSetTaskBar[] = {"NoSetTaskbar"}; +static const char strNoSetFld[] = {"NoSetFolders"}; +static const char strNoFileMenu[] = {"NoFileMenu"}; +static const char strNoSaveSetting[] = {"NoSaveSettings"}; +static const char strNoClose[] = {"NoClose"}; +static const char strNoRun[] = {"NoRun"}; + +/* policy data array */ +POLICYDATA sh32_policy_table[] = +{ + { + REST_NORUN, + strExplorer, + strNoRun, + SHELL_NO_POLICY + }, + { + REST_NOCLOSE, + strExplorer, + strNoClose, + SHELL_NO_POLICY + }, + { + REST_NOSAVESET, + strExplorer, + strNoSaveSetting, + SHELL_NO_POLICY + }, + { + REST_NOFILEMENU, + strExplorer, + strNoFileMenu, + SHELL_NO_POLICY + }, + { + REST_NOSETFOLDERS, + strExplorer, + strNoSetFld, + SHELL_NO_POLICY + }, + { + REST_NOSETTASKBAR, + strExplorer, + strNoSetTaskBar, + SHELL_NO_POLICY + }, + { + REST_NODESKTOP, + strExplorer, + strNoDesktop, + SHELL_NO_POLICY + }, + { + REST_NOFIND, + strExplorer, + strNoFind, + SHELL_NO_POLICY + }, + { + REST_NODRIVES, + strExplorer, + strNoDrives, + SHELL_NO_POLICY + }, + { + REST_NODRIVEAUTORUN, + strExplorer, + strNoDrivesAutoRun, + SHELL_NO_POLICY + }, + { + REST_NODRIVETYPEAUTORUN, + strExplorer, + strNoDriveTypeAtRun, + SHELL_NO_POLICY + }, + { + REST_NONETHOOD, + strExplorer, + strNoNetworkNeighborhood, + SHELL_NO_POLICY + }, + { + REST_STARTBANNER, + strExplorer, + strNoStartBanner, + SHELL_NO_POLICY + }, + { + REST_RESTRICTRUN, + strExplorer, + strRestrictRun, + SHELL_NO_POLICY + }, + { + REST_NOPRINTERTABS, + strExplorer, + strNoPrintTab, + SHELL_NO_POLICY + }, + { + REST_NOPRINTERDELETE, + strExplorer, + strNoDeletePrinters, + SHELL_NO_POLICY + }, + { + REST_NOPRINTERADD, + strExplorer, + strNoAddPrinters, + SHELL_NO_POLICY + }, + { + REST_NOSTARTMENUSUBFOLDERS, + strExplorer, + strNoStartMenuSubfolder, + SHELL_NO_POLICY + }, + { + REST_MYDOCSONNET, + strExplorer, + strMyDocsOnNet, + SHELL_NO_POLICY + }, + { + REST_NOEXITTODOS, + strWinOldApp, + strNoRealMode, + SHELL_NO_POLICY + }, + { + REST_ENFORCESHELLEXTSECURITY, + strExplorer, + strEnforceShlExtSecurity, + SHELL_NO_POLICY + }, + { + REST_LINKRESOLVEIGNORELINKINFO, + strExplorer, + strLnkResolveIgnoreLnkInfo, + SHELL_NO_POLICY + }, + { + REST_NOCOMMONGROUPS, + strExplorer, + strNoCommonGroups, + SHELL_NO_POLICY + }, + { + REST_SEPARATEDESKTOPPROCESS, + strExplorer, + strSeparateProcess, + SHELL_NO_POLICY + }, + { + REST_NOWEB, + strExplorer, + strNoWebMenu, + SHELL_NO_POLICY + }, + { + REST_NOTRAYCONTEXTMENU, + strExplorer, + strNoTrayContextMenu, + SHELL_NO_POLICY + }, + { + REST_NOVIEWCONTEXTMENU, + strExplorer, + strNoViewContextMenu, + SHELL_NO_POLICY + }, + { + REST_NONETCONNECTDISCONNECT, + strExplorer, + strNoNetConDis, + SHELL_NO_POLICY + }, + { + REST_STARTMENULOGOFF, + strExplorer, + strNoLogoff, + SHELL_NO_POLICY + }, + { + REST_NOSETTINGSASSIST, + strExplorer, + strNoSettingsWizard, + SHELL_NO_POLICY + }, + { + REST_NOINTERNETICON, + strExplorer, + strNoInetIcon, + SHELL_NO_POLICY + }, + { + REST_NORECENTDOCSHISTORY, + strExplorer, + strNoRecentDocHistory, + SHELL_NO_POLICY + }, + { + REST_NORECENTDOCSMENU, + strExplorer, + strNoRecentDocMenu, + SHELL_NO_POLICY + }, + { + REST_NOACTIVEDESKTOP, + strExplorer, + strNoActiveDesktop, + SHELL_NO_POLICY + }, + { + REST_NOACTIVEDESKTOPCHANGES, + strExplorer, + strNoActiveDesktopChanges, + SHELL_NO_POLICY + }, + { + REST_NOFAVORITESMENU, + strExplorer, + strNoFavoritesMenu, + SHELL_NO_POLICY + }, + { + REST_CLEARRECENTDOCSONEXIT, + strExplorer, + strClearRecentDocs, + SHELL_NO_POLICY + }, + { + REST_CLASSICSHELL, + strExplorer, + strClassicShell, + SHELL_NO_POLICY + }, + { + REST_NOCUSTOMIZEWEBVIEW, + strExplorer, + strNoCustomWebView, + SHELL_NO_POLICY + }, + { + REST_NOHTMLWALLPAPER, + strActiveDesk, + strNoHTMLWallpaper, + SHELL_NO_POLICY + }, + { + REST_NOCHANGINGWALLPAPER, + strActiveDesk, + strNoChangeWallpaper, + SHELL_NO_POLICY + }, + { + REST_NODESKCOMP, + strActiveDesk, + strNoComponent, + SHELL_NO_POLICY + }, + { + REST_NOADDDESKCOMP, + strActiveDesk, + strNoAddComponent, + SHELL_NO_POLICY + }, + { + REST_NODELDESKCOMP, + strActiveDesk, + strNoDelComponent, + SHELL_NO_POLICY + }, + { + REST_NOCLOSEDESKCOMP, + strActiveDesk, + strNoCloseComponent, + SHELL_NO_POLICY + }, + { + REST_NOCLOSE_DRAGDROPBAND, + strActiveDesk, + strNoCloseDragDrop, + SHELL_NO_POLICY + }, + { + REST_NOMOVINGBAND, + strActiveDesk, + strNoMovingBand, + SHELL_NO_POLICY + }, + { + REST_NOEDITDESKCOMP, + strActiveDesk, + strNoEditComponent, + SHELL_NO_POLICY + }, + { + REST_NORESOLVESEARCH, + strExplorer, + strNoResolveSearch, + SHELL_NO_POLICY + }, + { + REST_NORESOLVETRACK, + strExplorer, + strNoResolveTrk, + SHELL_NO_POLICY + }, + { + REST_FORCECOPYACLWITHFILE, + strExplorer, + strForceCopyACLW, + SHELL_NO_POLICY + }, + { + REST_NOLOGO3CHANNELNOTIFY, + strExplorer, + strNoMSAppLogo, + SHELL_NO_POLICY + }, + { + REST_NOFORGETSOFTWAREUPDATE, + strExplorer, + strNoForgetSoftwareUpdate, + SHELL_NO_POLICY + }, + { + REST_NOSETACTIVEDESKTOP, + strExplorer, + strNoSetActiveDesktop, + SHELL_NO_POLICY + }, + { + REST_NOUPDATEWINDOWS, + strExplorer, + strNoWindowsUpdate, + SHELL_NO_POLICY + }, + { + REST_NOCHANGESTARMENU, + strExplorer, + strNoChangeStartMenu, + SHELL_NO_POLICY + }, + { + REST_NOFOLDEROPTIONS, + strExplorer, + strNoFolderOptions, + SHELL_NO_POLICY + }, + { + REST_HASFINDCOMPUTERS, + strExplorer, + "FindComputers", + SHELL_NO_POLICY + }, + { + REST_INTELLIMENUS, + strExplorer, + "IntelliMenus", + SHELL_NO_POLICY + }, + { + REST_RUNDLGMEMCHECKBOX, + strExplorer, + "MemCheckBoxInRunDlg", + SHELL_NO_POLICY + }, + { + REST_ARP_ShowPostSetup, + strAddRemoveProgs, + "ShowPostSetup", + SHELL_NO_POLICY + }, + { + REST_NOCSC, + strExplorer, + "NoSyncAll", + SHELL_NO_POLICY + }, + { + REST_NOCONTROLPANEL, + strExplorer, + "NoControlPanel", + SHELL_NO_POLICY + }, + { + REST_ENUMWORKGROUP, + strExplorer, + "EnumWorkgroup", + SHELL_NO_POLICY + }, + { + REST_ARP_NOARP, + strAddRemoveProgs, + "NoAddRemovePrograms", + SHELL_NO_POLICY + }, + { + REST_ARP_NOREMOVEPAGE, + strAddRemoveProgs, + "NoRemovePage", + SHELL_NO_POLICY + }, + { + REST_ARP_NOADDPAGE, + strAddRemoveProgs, + "NoAddPage", + SHELL_NO_POLICY + }, + { + REST_ARP_NOWINSETUPPAGE, + strAddRemoveProgs, + "NoWindowsSetupPage", + SHELL_NO_POLICY + }, + { + REST_GREYMSIADS, + strExplorer, + "", + SHELL_NO_POLICY + }, + { + REST_NOCHANGEMAPPEDDRIVELABEL, + strExplorer, + "NoChangeMappedDriveLabel", + SHELL_NO_POLICY + }, + { + REST_NOCHANGEMAPPEDDRIVECOMMENT, + strExplorer, + "NoChangeMappedDriveComment", + SHELL_NO_POLICY + }, + { + REST_MaxRecentDocs, + strExplorer, + "MaxRecentDocs", + SHELL_NO_POLICY + }, + { + REST_NONETWORKCONNECTIONS, + strExplorer, + "NoNetworkConnections", + SHELL_NO_POLICY + }, + { + REST_FORCESTARTMENULOGOFF, + strExplorer, + "ForceStartMenuLogoff", + SHELL_NO_POLICY + }, + { + REST_NOWEBVIEW, + strExplorer, + "NoWebView", + SHELL_NO_POLICY + }, + { + REST_NOCUSTOMIZETHISFOLDER, + strExplorer, + "NoCustomizeThisFolder", + SHELL_NO_POLICY + }, + { + REST_NOENCRYPTION, + strExplorer, + "NoEncryption", + SHELL_NO_POLICY + }, + { + REST_ALLOWFRENCHENCRYPTION, + strExplorer, + "AllowFrenchEncryption", + SHELL_NO_POLICY + }, + { + REST_DONTSHOWSUPERHIDDEN, + strExplorer, + "DontShowSuperHidden", + SHELL_NO_POLICY + }, + { + REST_NOSHELLSEARCHBUTTON, + strExplorer, + "NoShellSearchButton", + SHELL_NO_POLICY + }, + { + REST_NOHARDWARETAB, + strExplorer, + "NoHardwareTab", + SHELL_NO_POLICY + }, + { + REST_NORUNASINSTALLPROMPT, + strExplorer, + "NoRunasInstallPrompt", + SHELL_NO_POLICY + }, + { + REST_PROMPTRUNASINSTALLNETPATH, + strExplorer, + "PromptRunasInstallNetPath", + SHELL_NO_POLICY + }, + { + REST_NOMANAGEMYCOMPUTERVERB, + strExplorer, + "NoManageMyComputerVerb", + SHELL_NO_POLICY + }, + { + REST_NORECENTDOCSNETHOOD, + strExplorer, + "NoRecentDocsNetHood", + SHELL_NO_POLICY + }, + { + REST_DISALLOWRUN, + strExplorer, + "DisallowRun", + SHELL_NO_POLICY + }, + { + REST_NOWELCOMESCREEN, + strExplorer, + "NoWelcomeScreen", + SHELL_NO_POLICY + }, + { + REST_RESTRICTCPL, + strExplorer, + "RestrictCpl", + SHELL_NO_POLICY + }, + { + REST_DISALLOWCPL, + strExplorer, + "DisallowCpl", + SHELL_NO_POLICY + }, + { + REST_NOSMBALLOONTIP, + strExplorer, + "NoSMBalloonTip", + SHELL_NO_POLICY + }, + { + REST_NOSMHELP, + strExplorer, + "NoSMHelp", + SHELL_NO_POLICY + }, + { + REST_NOWINKEYS, + strExplorer, + "NoWinKeys", + SHELL_NO_POLICY + }, + { + REST_NOENCRYPTONMOVE, + strExplorer, + "NoEncryptOnMove", + SHELL_NO_POLICY + }, + { + REST_NOLOCALMACHINERUN, + strExplorer, + "DisableLocalMachineRun", + SHELL_NO_POLICY + }, + { + REST_NOCURRENTUSERRUN, + strExplorer, + "DisableCurrentUserRun", + SHELL_NO_POLICY + }, + { + REST_NOLOCALMACHINERUNONCE, + strExplorer, + "DisableLocalMachineRunOnce", + SHELL_NO_POLICY + }, + { + REST_NOCURRENTUSERRUNONCE, + strExplorer, + "DisableCurrentUserRunOnce", + SHELL_NO_POLICY + }, + { + REST_FORCEACTIVEDESKTOPON, + strExplorer, + "ForceActiveDesktopOn", + SHELL_NO_POLICY + }, + { + REST_NOCOMPUTERSNEARME, + strExplorer, + "NoComputersNearMe", + SHELL_NO_POLICY + }, + { + REST_NOVIEWONDRIVE, + strExplorer, + "NoViewOnDrive", + SHELL_NO_POLICY + }, + { + REST_NONETCRAWL, + strExplorer, + "NoNetCrawl", + SHELL_NO_POLICY + }, + { + REST_NOSHAREDDOCUMENTS, + strExplorer, + "NoSharedDocs", + SHELL_NO_POLICY + }, + { + REST_NOSMMYDOCS, + strExplorer, + "NoSMMyDocs", + SHELL_NO_POLICY + }, +/* 0x4000050 - 0x4000060 */ + { + REST_NONLEGACYSHELLMODE, + strExplorer, + "NoneLegacyShellMode", + SHELL_NO_POLICY + }, + { + REST_STARTRUNNOHOMEPATH, + strExplorer, + "StartRunNoHOMEPATH", + SHELL_NO_POLICY + }, +/* 0x4000061 - 0x4000086 */ + { + REST_NODISCONNECT, + strExplorer, + "NoDisconnect", + SHELL_NO_POLICY + }, + { + REST_NOSECURITY, + strExplorer, + "NoNTSecurity", + SHELL_NO_POLICY + }, + { + REST_NOFILEASSOCIATE, + strExplorer, + "NoFileAssociate", + SHELL_NO_POLICY + }, + { + 0x50000024, + strExplorer, + strNoFileURL, + SHELL_NO_POLICY + }, + { + 0, + 0, + 0, + SHELL_NO_POLICY + } +}; + +/************************************************************************* + * SHRestricted [SHELL32.100] + * + * Get the value associated with a policy Id. + * + * PARAMS + * pol [I] Policy Id + * + * RETURNS + * The queried value for the policy. + * + * NOTES + * Exported by ordinal. + * This function caches the retrieved values to prevent unnecessary registry access, + * if SHInitRestricted() was previously called. + * + * REFERENCES + * a: MS System Policy Editor. + * b: 98Lite 2.0 (which uses many of these policy keys) http://www.98lite.net/ + * c: 'The Windows 95 Registry', by John Woram, 1996 MIS: Press + */ +DWORD WINAPI SHRestricted (RESTRICTIONS policy) +{ + char regstr[256]; + HKEY xhkey; + DWORD retval, datsize = 4; + LPPOLICYDATA p; + + TRACE("(%08x)\n", policy); + + /* scan to see if we know this policy ID */ + for (p = sh32_policy_table; p->policy; p++) + { + if (policy == p->policy) + { + break; + } + } + + if (p->policy == 0) + { + /* we don't know this policy, return 0 */ + TRACE("unknown policy: (%08x)\n", policy); + return 0; + } + + /* we have a known policy */ + + /* first check if this policy has been cached, return it if so */ + if (p->cache != SHELL_NO_POLICY) + { + return p->cache; + } + + lstrcpyA(regstr, strRegistryPolicyA); + lstrcatA(regstr, p->appstr); + + /* return 0 and don't set the cache if any registry errors occur */ + retval = 0; + if (RegOpenKeyA(HKEY_CURRENT_USER, regstr, &xhkey) == ERROR_SUCCESS) + { + if (RegQueryValueExA(xhkey, p->keystr, NULL, NULL, (LPBYTE)&retval, &datsize) == ERROR_SUCCESS) + { + p->cache = retval; + } + RegCloseKey(xhkey); + } + return retval; +} + +/************************************************************************* + * SHInitRestricted [SHELL32.244] + * + * Initialise the policy cache to speed up calls to SHRestricted(). + * + * PARAMS + * unused [I] Reserved. + * inpRegKey [I] Registry key to scan. + * + * RETURNS + * Success: -1. The policy cache is initialised. + * Failure: 0, if inpRegKey is any value other than NULL, "Policy", or + * "Software\Microsoft\Windows\CurrentVersion\Policies". + * + * NOTES + * Exported by ordinal. Introduced in Win98. + */ +BOOL WINAPI SHInitRestricted(LPCVOID unused, LPCVOID inpRegKey) +{ + TRACE("(%p, %p)\n", unused, inpRegKey); + + /* first check - if input is non-NULL and points to the secret + key string, then pass. Otherwise return 0. + */ + if (inpRegKey != NULL) + { + if (SHELL_OsIsUnicode()) + { + if (lstrcmpiW((LPCWSTR)inpRegKey, strRegistryPolicyW) && + lstrcmpiW((LPCWSTR)inpRegKey, strPolicyW)) + /* doesn't match, fail */ + return 0; + } + else + { + if (lstrcmpiA((LPCSTR)inpRegKey, strRegistryPolicyA) && + lstrcmpiA((LPCSTR)inpRegKey, strPolicyA)) + /* doesn't match, fail */ + return 0; + } + } + + return TRUE; +} diff --git a/reactos/lib/shell32/shres.rc b/reactos/lib/shell32/shres.rc index 21ab4ced7d5..66a6f3b81fb 100644 --- a/reactos/lib/shell32/shres.rc +++ b/reactos/lib/shell32/shres.rc @@ -1,16642 +1,16642 @@ -/* - * Top level resource file for shell stuff - * - * Copyright 1998 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winnls.h" -#include "wingdi.h" -#include "shlobj.h" -#include "shresdef.h" - -#include "version.rc" - -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL - -shv_accel ACCELERATORS -BEGIN - VK_F5, FCIDM_SHVIEW_REFRESH, VIRTKEY -END - -/* BINRES document.ico */ -1 ICON document.ico -/* { - '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 11 11 00 22 22 22 00 33 33 33 00 55 55' - '55 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 88 88' - '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC CC' - 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' - '00 00 33 00 32 00 5C 00 64 00 6F 00 63 00 75 00' - '6D 00 65 00 6E 00 74 00 2E 00 69 00 63 00 6F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 5A 00 5C 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5A 00' - '00 00 00 00 00 00 03 00 00 00 62 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 64 6F 63 75 6D 65 6E 74 2E' - '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 00 00 00 00 00 00 00 00 00 00 00 00' - '10 01 08 09 09 09 09 09 09 08 09 09 08 09 09 08' - '06 03 10 10 10 00 00 00 00 00 00 00 00 00 00 00' - '10 02 0C 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F' - '0B 08 03 10 10 10 00 00 00 00 00 00 00 00 00 00' - '10 01 0C 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0A 0C 0A 02 10 10 10 00 00 00 00 00 00 00 00 00' - '10 02 0B 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0E' - '0A 0D 0D 0A 02 10 10 10 00 00 00 00 00 00 00 00' - '10 01 0C 0E 0D 0D 0D 0D 0D 0D 0E 0D 0D 0E 0D 0D' - '0B 0D 0E 0E 0A 03 10 10 10 00 00 00 00 00 00 00' - '10 02 0C 0E 0D 0D 0D 0E 0D 0D 0D 0D 0E 0D 0E 0D' - '0A 0D 0F 0E 0E 09 02 10 10 00 00 00 00 00 00 00' - '10 01 0C 0E 0D 0E 0D 0D 0D 0E 0D 0E 0D 0D 0E 0D' - '0B 0D 0E 0F 0E 0F 0A 02 10 10 00 00 00 00 00 00' - '10 02 0C 0E 0D 0D 0E 0D 0E 0D 0D 0E 0E 0D 0D 0E' - '0A 0E 0F 0E 0F 0F 0F 0A 02 10 10 10 00 00 00 00' - '10 01 0C 0E 0D 0E 0E 0D 0D 0E 0E 0D 0D 0E 0E 0E' - '0A 0D 0E 0E 0E 0E 0E 0E 09 03 10 10 00 00 00 00' - '10 02 0C 0E 0E 0D 0D 0E 0E 0D 0E 0E 0E 0D 0E 0E' - '0C 0A 0B 0B 0B 0A 0B 0B 0B 06 10 10 00 00 00 00' - '10 01 0C 0F 0D 0E 0E 0D 0E 0E 0D 0E 0D 0E 0D 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0F 09 10 10 00 00 00 00' - '10 02 0C 0E 0E 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0E 08 10 10 00 00 00 00' - '10 01 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0F 0E 0E 0E 0E 0E 0F 0E 09 10 10 00 00 00 00' - '10 01 0C 0F 0E 0E 0E 0E 0F 0E 0F 0E 0E 0E 0F 0E' - '0E 0E 0E 0E 0F 0E 0F 0E 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0E 0F 0E 0F 0E 0F 0E 0F 0F 0F 0E 0F' - '0F 0E 0F 0E 0E 0E 0E 0F 0F 08 10 10 00 00 00 00' - '10 02 0C 0F 0E 0E 0F 0E 0F 0E 0F 0F 0F 0E 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0E 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0F 0E 0E 0F 0E 0F 0E 0F 0E 0F 0F 0E' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0E 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0F 0E 0F 0F 0E 0F 0F 0E 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0F 0F 0E 0F 0F 0E 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0D 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 01 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0A 10 10 00 00 00 00' - '10 02 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' - '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0A 10 10 00 00 00 00' - '10 01 06 08 06 06 06 06 06 06 06 06 06 06 06 06' - '06 06 05 06 05 06 05 05 06 04 10 10 00 00 00 00' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 00 00 E0 00' - '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' - '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' - '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 11 11 11 00 33 33' - '33 00 44 44 44 00 77 77 77 00 7F 7F 7F 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 CC CC CC 00 DD DD' - 'DD 00 EE EE EE 00 FF FF FF 00 00 00 00 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 33 00 32 00 5C 00' - '64 00 6F 00 63 00 75 00 6D 00 65 00 6E 00 74 00' - '2E 00 69 00 63 00 6F 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' - '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' - '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 5A 00' - '5C 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 5A 00 00 00 00 00 00 00 03 00' - '00 00 62 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' - '6F 63 75 6D 65 6E 74 2E 69 63 6F 00 4B 00 14 1A' - '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' - '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' - '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' - '95 00 00 00 00 00 00 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0D 00 00 00 00 00 00 01 07 08 08 07 08 07 08 04' - '0D 0D 00 00 00 00 00 01 09 0B 0A 0B 0B 0B 0A 09' - '06 0D 0D 00 00 00 00 01 0A 0A 0A 0A 0A 0B 0A 09' - '0C 06 0D 0D 00 00 00 01 09 0A 0B 0A 0B 0A 0A 09' - '0C 0C 06 01 0D 00 00 01 0A 0B 0A 0B 0A 0B 0A 09' - '0A 09 0A 04 0D 00 00 01 09 0B 0B 0A 0B 0B 0B 0B' - '0A 0B 0B 08 0D 00 00 01 0A 0C 0B 0B 0B 0B 0B 0B' - '0B 0B 0C 08 0D 00 00 01 0A 0B 0B 0C 0B 0C 0B 0B' - '0C 0B 0C 09 0D 00 00 01 0B 0C 0B 0C 0B 0C 0C 0C' - '0C 0C 0C 08 0D 00 00 01 09 0C 0C 0B 0C 0C 0C 0C' - '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' - '0C 0C 0C 08 0D 00 00 01 0A 0C 0C 0C 0C 0C 0C 0C' - '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' - '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' - '0C 0C 0C 09 0D 00 00 0D 03 03 03 03 03 03 03 02' - '03 02 03 02 0D 00 80 1F 00 00 80 0F 00 00 80 07' - '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08' - '88 87 88 78 88 78 88 88 00 00 00 00 00 00 00 00' - '7F F7 FF 7F FF 7F F7 78 80 00 00 00 00 00 00 04' - '7F 7F 77 F7 F7 F7 FF 8F 88 00 00 00 00 00 00 00' - '7F F7 FF 7F 7F 7F 7F 77 F8 80 00 00 00 00 00 08' - '7F 77 F7 F7 F7 F7 F7 77 FF 88 00 00 00 00 00 00' - '7F F7 7F 7F 7F 7F 7F 7F 7F F8 80 00 00 00 00 08' - '7F 7F F7 F7 F7 F7 F7 77 FF FF 88 00 00 00 00 00' - '7F F7 FF 7F 7F F7 FF 8F FF FF F8 80 00 00 00 08' - '7F 7F 77 F7 FF 7F F7 77 F7 F7 FF 84 00 00 00 00' - '7F F7 FF 7F 7F F7 FF 77 77 77 87 78 00 00 00 08' - '7F 7F F7 FF F7 FF 7F FF 7F F7 FF F7 00 00 00 00' - '7F F7 FF 7F 7F 7F F7 FF F7 FF F7 F8 00 00 00 08' - '7F FF F7 F7 FF F7 FF 7F 7F FF 7F F8 00 00 00 00' - '7F 7F FF FF 7F FF 7F FF F7 FF FF F8 00 00 00 04' - '7F FF 7F F7 FF 7F FF F7 FF FF F7 F7 00 00 00 00' - 'FF FF FF FF FF F7 FF FF 7F F7 FF F8 00 00 00 08' - '7F 7F F7 FF FF FF FF FF FF FF FF F8 00 00 00 00' - '7F FF FF F7 FF FF FF FF FF FF FF F8 00 00 00 08' - '7F FF FF FF FF 7F FF FF FF FF FF F7 00 00 00 00' - 'FF F7 FF FF FF FF FF FF FF FF FF F8 00 00 00 08' - '7F FF FF 7F FF FF FF FF FF FF FF F7 00 00 00 00' - '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 08' - '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' - 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 08' - '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' - 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 04' - '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 08' - '7F FF FF FF FF FF FF F7 FF FF FF F7 00 00 00 00' - '88 88 88 88 88 88 88 88 88 88 88 88 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 00' - '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' - '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' - '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 77' - '77 77 78 00 00 00 00 7F F7 FF 7F 80 00 00 04 7F' - '7F 7F 77 F8 00 00 00 77 F7 F7 F7 FF 70 00 00 FF' - '7F 7F 7F 7F 78 00 08 77 FF 7F F7 F7 F7 00 00 FF' - '7F FF 7F 7F F7 00 00 7F FF F7 FF FF F7 00 04 7F' - 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 00 7F' - 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 04 7F' - 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 00 88' - '88 88 88 88 88 00 80 1F 00 00 80 0F 00 00 80 07' - '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 11 11 00 22 22 22 00 33 33 33 00 44 44' - '44 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 88 88' - '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC CC' - 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' - '00 00 33 00 32 00 5C 00 64 00 6F 00 63 00 75 00' - '6D 00 65 00 6E 00 74 00 2E 00 69 00 63 00 6F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 5A 00 5C 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5A 00' - '00 00 00 00 00 00 03 00 00 00 62 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 64 6F 63 75 6D 65 6E 74 2E' - '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 10 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 08 08 06 08 08 06 08 06 06 08 06 08' - '06 06 06 06 06 06 06 05 06 05 05 01 10 10 10 10' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0D' - '0E 0E 0E 0E 0E 0E 0E 0E 0E 0C 08 05 01 10 10 10' - '10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0E 0D' - '0D 0D 0D 0E 0D 0D 0D 0E 0E 0B 09 0A 05 01 10 10' - '10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0B 0F 0C 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0D 0D 0D 0D 0D 0D 0D 0D 0D 0B 0A 0D 0A 05 02 10' - '10 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0E 0D 0D 0D 0D 0E 0D 0D 0E 0A 0A 0E 0D 09 06 01' - '10 10 10 10 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0D 0D 0D 0D 0D 0D 0D 0E 0D 0B 0A 0E 0D 0E 0A 06' - '01 10 10 10 10 00 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' - '0D 0D 0D 0E 0D 0D 0D 0D 0E 0B 0A 0E 0E 0E 0E 0A' - '05 01 10 10 10 10 00 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0E 0D' - '0D 0E 0D 0D 0D 0D 0E 0D 0E 0B 0A 0E 0E 0E 0E 0F' - '0A 06 01 10 10 10 10 00 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0E 0D 0D 0D 0E 0D 0D 0D 0D' - '0E 0D 0E 0D 0E 0D 0D 0E 0D 0B 0A 0E 0F 0E 0E 0E' - '0F 0A 05 01 10 10 10 10 00 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0D 0E 0D 0D 0D 0E 0D 0E' - '0D 0D 0D 0E 0D 0D 0E 0D 0E 0B 0A 0F 0E 0E 0F 0E' - '0F 0E 0B 05 02 10 10 10 10 00 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0D 0E 0D 0D 0E 0D 0D 0E 0D' - '0E 0D 0E 0D 0E 0E 0D 0E 0E 0B 0B 0E 0F 0E 0E 0F' - '0E 0F 0F 0B 05 01 10 10 10 10 00 00 00 00 00 00' - '00 10 10 03 0C 0F 0E 0D 0D 0D 0E 0D 0E 0D 0D 0E' - '0D 0E 0D 0E 0D 0D 0E 0D 0E 0B 0A 0F 0E 0F 0F 0F' - '0F 0F 0F 0F 0B 06 01 10 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0E 0D 0E 0D 0D 0E 0E 0D 0E' - '0D 0D 0E 0D 0E 0E 0D 0E 0E 0B 0B 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0B 05 02 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0E 0D 0E 0D 0E 0E 0D 0D 0E 0D' - '0E 0E 0D 0E 0E 0D 0E 0E 0E 0B 09 0B 0B 0B 0A 0B' - '0B 0A 0B 0A 0B 0B 09 05 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0E 0D 0D 0E 0D 0D 0E 0E 0D 0E' - '0D 0E 0E 0D 0E 0E 0E 0D 0E 0D 0C 0C 0C 0C 0C 0C' - '0C 0C 0C 0C 0B 0C 0C 06 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0E 0E 0D 0E 0E 0E 0D 0E 0E' - '0E 0E 0D 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0F 0E 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0E 0D 0E 0E 0D 0E 0E 0E 0D 0E' - '0E 0D 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0F 0D 06 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0D 0E 0E 0E 0E 0D 0E 0D 0E 0E' - '0D 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0F 0E 0E 0E 0E 0E 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0F 0D 06 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F 0E' - '0E 0E 0E 0F 0E 0E 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' - '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E' - '0E 0F 0E 0E 0E 0F 0E 06 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0F 0E 0E 0E 0F 0E 0F 0E 0F 0E' - '0F 0E 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E 0E 0E 0E 0F' - '0E 0E 0F 0E 0F 0E 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0E 0E 0E 0F 0E 0E 0E 0F 0E 0F' - '0E 0F 0E 0F 0F 0E 0F 0E 0F 0E 0F 0E 0F 0E 0E 0E' - '0F 0E 0E 0E 0E 0F 0E 06 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0E 0E 0F 0E 0E 0E 0F 0E 0F 0E' - '0F 0E 0F 0F 0E 0F 0F 0F 0E 0F 0F 0F 0E 0F 0E 0F' - '0E 0F 0E 0F 0F 0E 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0E 0E 0E 0F 0E 0F 0E 0E 0F 0F' - '0E 0F 0F 0E 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F 0F 0E' - '0F 0E 0E 0E 0F 0F 0E 06 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0E 0F 0E 0F 0E 0F 0F 0F 0E' - '0F 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0E 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0E 0F 0E 0F 0E 0F 0E 0F 0E 0F' - '0F 0E 0F 0E 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 06 01 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0E 0E 0F 0F 0E 0F 0E 0F 0E' - '0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0E 0F 0F 0E 0E 0F 0F 0F 0F 0F' - '0E 0F 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 06 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0F 0E 0F 0F 0F 0E 0F 0F 0E' - '0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0E 0F 0F 0E 0F 0F 0F 0E 0F 0F' - '0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0C 0F 0F 0E 0F 0F 0F 0E 0F 0F 0F 0F' - '0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0F 0F 0E 0F 0F 0F 0F 0F 0E 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 03 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' - '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0E 0F 0F' - '0E 0F 0E 0F 0E 0F 0F 0E 0F 0E 0F 0F 0F 0F 0E 0F' - '0F 0F 0E 0F 0E 0F 0E 09 10 10 10 00 00 00 00 00' - '00 10 10 02 0A 09 09 09 09 09 09 09 09 09 09 09' - '09 09 09 08 09 09 08 09 08 09 08 08 08 08 08 08' - '08 08 08 08 08 08 08 05 10 10 10 00 00 00 00 00' - '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 00 00 00 00 00' - '00 00 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' - '10 10 10 10 10 10 10 10 10 10 00 00 00 00 F0 00' - '00 01 FF FF 00 00 E0 00 00 00 FF FF 00 00 E0 00' - '00 00 7F FF 00 00 E0 00 00 00 3F FF 00 00 E0 00' - '00 00 1F FF 00 00 E0 00 00 00 0F FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 03 FF 00 00 E0 00' - '00 00 01 FF 00 00 E0 00 00 00 00 FF 00 00 E0 00' - '00 00 00 7F 00 00 E0 00 00 00 00 3F 00 00 E0 00' - '00 00 00 1F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 04 00 00 00 29 00 00' - '00 38 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 38 00 00 00 34 00 00 00 19 00 00' - '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 01 00 00 00 76 00 00 00 F1 00 00' - '00 F9 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F8 00 00 00 F2 00 00 00 B2 00 00' - '00 49 00 00 00 05 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 5A 00 00 00 FF 01 01 01 FF 06 06' - '06 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' - '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' - '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' - '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 03 03 03 FF 02 02' - '02 FF 03 03 03 FF 02 02 02 FF 00 00 00 FF 00 00' - '00 D9 00 00 00 39 00 00 00 06 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 2E 2E 2E FF 88 88' - '88 FF 87 87 87 FF 86 86 86 FF 86 86 86 FF 85 85' - '85 FF 84 84 84 FF 84 84 84 FF 83 83 83 FF 82 82' - '82 FF 82 82 82 FF 81 81 81 FF 80 80 80 FF 7F 7F' - '7F FF 7F 7F 7F FF 7E 7E 7E FF 7D 7D 7D FF 7C 7C' - '7C FF 7C 7C 7C FF 7B 7B 7B FF 74 74 74 FF 72 72' - '72 FF 73 73 73 FF 67 67 67 FF 18 18 18 FF 00 00' - '00 FF 00 00 00 D9 00 00 00 58 00 00 00 03 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF C1 C1' - 'C1 FF F2 F2 F2 FF EA EA EA FF EA EA EA FF EA EA' - 'EA FF EA EA EA FF E9 E9 E9 FF E9 E9 E9 FF E9 E9' - 'E9 FF E9 E9 E9 FF E9 E9 E9 FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF E9 E9 E9 FF EB EB EB FF EA EA' - 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF F1 F1' - 'F1 FF C4 C4 C4 FF 8C 8C 8C FF 67 67 67 FF 15 15' - '15 FF 00 00 00 FF 00 00 00 DC 00 00 00 4C 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C8 C8' - 'C8 FF FA FA FA FF DD DD DD FF DE DE DE FF DE DE' - 'DE FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' - 'E2 FF E2 E2 E2 FF E2 E2 E2 FF E3 E3 E3 FF E8 E8' - 'E8 FF BA BA BA FF A3 A3 A3 FF A6 A6 A6 FF 6B 6B' - '6B FF 0B 0B 0B FF 00 00 00 FF 00 00 00 EB 00 00' - '00 4B 00 00 00 03 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C7 C7' - 'C7 FF F9 F9 F9 FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DB DB DB FF DB DB DB FF DB DB' - 'DB FF DC DC DC FF DC DC DC FF DC DC DC FF DC DC' - 'DC FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF E3 E3' - 'E3 FF B7 B7 B7 FF A8 A8 A8 FF DE DE DE FF A8 A8' - 'A8 FF 6C 6C 6C FF 25 25 25 FF 00 00 00 FF 00 00' - '00 DE 00 00 00 57 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C7 C7' - 'C7 FF F9 F9 F9 FF DC DC DC FF DB DB DB FF DB DB' - 'DB FF DC DC DC FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DE DE' - 'DE FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E5 E5' - 'E5 FF B8 B8 B8 FF A7 A7 A7 FF EB EB EB FF DE DE' - 'DE FF A4 A4 A4 FF 72 72 72 FF 17 17 17 FF 00 00' - '00 FF 00 00 00 DC 00 00 00 4C 00 00 00 06 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 36 36 36 FF C8 C8' - 'C8 FF FA FA FA FF DC DC DC FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E6 E6' - 'E6 FF B9 B9 B9 FF A9 A9 A9 FF EA EA EA FF EA EA' - 'EA FF E9 E9 E9 FF B1 B1 B1 FF 72 72 72 FF 14 14' - '14 FF 00 00 00 FF 00 00 00 EB 00 00 00 4B 00 00' - '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' - 'C9 FF FA FA FA FF DD DD DD FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1' - 'E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E7 E7' - 'E7 FF BA BA BA FF AA AA AA FF EC EC EC FF EA EA' - 'EA FF ED ED ED FF EA EA EA FF B2 B2 B2 FF 6A 6A' - '6A FF 1C 1C 1C FF 00 00 00 FF 00 00 00 DE 00 00' - '00 57 00 00 00 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' - 'C9 FF FA FA FA FF DF DF DF FF DE DE DE FF DF DF' - 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' - 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' - 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E8 E8' - 'E8 FF BA BA BA FF AC AC AC FF EF EF EF FF ED ED' - 'ED FF ED ED ED FF F1 F1 F1 FF F1 F1 F1 FF B1 B1' - 'B1 FF 6B 6B 6B FF 13 13 13 FF 00 00 00 FF 00 00' - '00 DC 00 00 00 46 00 00 00 05 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' - 'C9 FF FA FA FA FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' - 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' - 'E2 FF E2 E2 E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E9 E9' - 'E9 FF BB BB BB FF AD AD AD FF F3 F3 F3 FF F1 F1' - 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F4 F4 F4 FF F5 F5' - 'F5 FF B5 B5 B5 FF 70 70 70 FF 14 14 14 FF 00 00' - '00 FF 00 00 00 E0 00 00 00 3F 00 00 00 02 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF CA CA' - 'CA FF FB FB FB FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' - 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' - 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF EA EA' - 'EA FF BC BC BC FF AF AF AF FF F5 F5 F5 FF F3 F3' - 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4 F4 FF F8 F8' - 'F8 FF F4 F4 F4 FF B6 B6 B6 FF 6C 6C 6C FF 22 22' - '22 FF 00 00 00 FF 00 00 00 D4 00 00 00 49 00 00' - '00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CA CA' - 'CA FF FB FB FB FF E2 E2 E2 FF E1 E1 E1 FF E2 E2' - 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF EB EB' - 'EB FF BC BC BC FF B1 B1 B1 FF F8 F8 F8 FF F6 F6' - 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' - 'F8 FF FC FC FC FF FC FC FC FF B5 B5 B5 FF 70 70' - '70 FF 18 18 18 FF 00 00 00 FF 00 00 00 D4 00 00' - '00 3F 00 00 00 05 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CB CB' - 'CB FF FC FC FC FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF EC EC' - 'EC FF BD BD BD FF B3 B3 B3 FF FC FC FC FF F9 F9' - 'F9 FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FF FF FF FF FF FF FF FF BA BA' - 'BA FF 75 75 75 FF 18 18 18 FF 00 00 00 FF 00 00' - '00 E0 00 00 00 3E 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CB CB' - 'CB FF FC FC FC FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF ED ED' - 'ED FF BE BE BE FF B5 B5 B5 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FB FB' - 'FB FF BE BE BE FF 6E 6E 6E FF 1C 1C 1C FF 00 00' - '00 FF 00 00 00 BB 00 00 00 1F 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CC CC' - 'CC FF FC FC FC FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E5 E5 E5 FF E5 E5' - 'E5 FF E6 E6 E6 FF E7 E7 E7 FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF EE EE' - 'EE FF C3 C3 C3 FF 9A 9A 9A FF B9 B9 B9 FF B8 B8' - 'B8 FF B7 B7 B7 FF B7 B7 B7 FF B7 B7 B7 FF B7 B7' - 'B7 FF B6 B6 B6 FF B5 B5 B5 FF B5 B5 B5 FF B8 B8' - 'B8 FF B5 B5 B5 FF 91 91 91 FF 67 67 67 FF 01 01' - '01 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 39 39 39 FF CC CC' - 'CC FF FC FC FC FF E6 E6 E6 FF E7 E7 E7 FF E6 E6' - 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' - 'E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EB EB' - 'EB FF E2 E2 E2 FF CD CD CD FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF C9 C9 C9 FF C9 C9' - 'C9 FF C9 C9 C9 FF C9 C9 C9 FF C9 C9 C9 FF C9 C9' - 'C9 FF CD CD CD FF CC CC CC FF 7A 7A 7A FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 39 39 39 FF CC CC' - 'CC FF FC FC FC FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' - 'E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EA EA' - 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF EB EB' - 'EB FF ED ED ED FF EF EF EF FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' - 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' - 'F2 FF F6 F6 F6 FF EC EC EC FF 7A 7A 7A FF 04 04' - '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CE CE' - 'CE FF FD FD FD FF E9 E9 E9 FF E9 E9 E9 FF EA EA' - 'EA FF E9 E9 E9 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9' - 'E9 FF E9 E9 E9 FF EA EA EA FF EA EA EA FF EA EA' - 'EA FF EA EA EA FF EB EB EB FF EB EB EB FF EA EA' - 'EA FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' - 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' - 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF ED ED' - 'ED FF ED ED ED FF EE EE EE FF EF EF EF FF EF EF' - 'EF FF F2 F2 F2 FF E9 E9 E9 FF 7B 7B 7B FF 04 04' - '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CD CD' - 'CD FF FD FD FD FF EA EA EA FF EB EB EB FF EC EC' - 'EC FF ED ED ED FF EC EC EC FF E9 E9 E9 FF EA EA' - 'EA FF EA EA EA FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EC EC' - 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' - 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' - 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' - 'F0 FF F4 F4 F4 FF E9 E9 E9 FF 7B 7B 7B FF 04 04' - '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CE CE' - 'CE FF FE FE FE FF EC EC EC FF EC EC EC FF ED ED' - 'ED FF EE EE EE FF EF EF EF FF EE EE EE FF EB EB' - 'EB FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' - 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' - 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' - 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' - 'F1 FF F4 F4 F4 FF EA EA EA FF 7C 7C 7C FF 04 04' - '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CE CE' - 'CE FF FE FE FE FF ED ED ED FF ED ED ED FF EE EE' - 'EE FF EF EF EF FF F0 F0 F0 FF F1 F1 F1 FF F0 F0' - 'F0 FF EE EE EE FF EC EC EC FF EC EC EC FF ED ED' - 'ED FF ED ED ED FF EE EE EE FF EE EE EE FF EE EE' - 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' - 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' - 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F1 F1' - 'F1 FF F5 F5 F5 FF EA EA EA FF 7D 7D 7D FF 04 04' - '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CF CF' - 'CF FF FE FE FE FF EE EE EE FF EF EF EF FF F0 F0' - 'F0 FF F0 F0 F0 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' - 'F2 FF F3 F3 F3 FF F1 F1 F1 FF EE EE EE FF EE EE' - 'EE FF EE EE EE FF EE EE EE FF EE EE EE FF EF EF' - 'EF FF EF EF EF FF EF EF EF FF EF EF EF FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' - 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' - 'F3 FF F6 F6 F6 FF EB EB EB FF 7D 7D 7D FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CF CF' - 'CF FF FF FF FF FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F1 F1 F1 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' - 'F3 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4' - 'F4 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' - 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4 F4 FF F4 F4' - 'F4 FF F7 F7 F7 FF EB EB EB FF 7E 7E 7E FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3C 3C 3C FF D0 D0' - 'D0 FF FF FF FF FF F1 F1 F1 FF F1 F1 F1 FF F2 F2' - 'F2 FF F2 F2 F2 FF F3 F3 F3 FF F4 F4 F4 FF F4 F4' - 'F4 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6 F6 FF F7 F7' - 'F7 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' - 'F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F8 F8' - 'F8 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F3 F3' - 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4' - 'F4 FF F4 F4 F4 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' - 'F5 FF F8 F8 F8 FF EB EB EB FF 7E 7E 7E FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3D 3D 3D FF D1 D1' - 'D1 FF FF FF FF FF F2 F2 F2 FF F2 F2 F2 FF F3 F3' - 'F3 FF F3 F3 F3 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' - 'F5 FF F6 F6 F6 FF F7 F7 F7 FF F7 F7 F7 FF F8 F8' - 'F8 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF FA FA FA FF FB FB FB FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FA FA FA FF F7 F7 F7 FF F5 F5 F5 FF F5 F5' - 'F5 FF F5 F5 F5 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' - 'F6 FF F9 F9 F9 FF EC EC EC FF 7F 7F 7F FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3D 3D 3D FF D1 D1' - 'D1 FF FF FF FF FF F3 F3 F3 FF F3 F3 F3 FF F4 F4' - 'F4 FF F4 F4 F4 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' - 'F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' - 'F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF FA FA' - 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FE FE FE FF FD FD FD FF FA FA' - 'FA FF F7 F7 F7 FF F5 F5 F5 FF F6 F6 F6 FF F7 F7' - 'F7 FF FA FA FA FF EC EC EC FF 80 80 80 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D2 D2' - 'D2 FF FF FF FF FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' - 'F5 FF F5 F5 F5 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' - 'F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' - 'FB FF FB FB FB FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FE FE FE FF FB FB FB FF F8 F8 F8 FF F7 F7' - 'F7 FF FB FB FB FF ED ED ED FF 81 81 81 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D2 D2' - 'D2 FF FF FF FF FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' - 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' - 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F9 F9 F9 FF FA FA' - 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' - 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FA FA' - 'FA FF FC FC FC FF ED ED ED FF 80 80 80 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D3 D3' - 'D3 FF FF FF FF FF F6 F6 F6 FF F7 F7 F7 FF F7 F7' - 'F7 FF F7 F7 F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FA FA' - 'FA FF FB FB FB FF FB FB FB FF FC FC FC FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF EE EE EE FF 82 82 82 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D3 D3' - 'D3 FF FF FF FF FF F7 F7 F7 FF F7 F7 F7 FF F8 F8' - 'F8 FF F9 F9 F9 FF F8 F8 F8 FF F8 F8 F8 FF FA FA' - 'FA FF FA FA FA FF FB FB FB FF FB FB FB FF FB FB' - 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 82 82 82 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D4 D4' - 'D4 FF FF FF FF FF F8 F8 F8 FF F8 F8 F8 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FA FA' - 'FA FF FA FA FA FF FB FB FB FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FC FC FC FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF EF EF EF FF 82 82 82 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D5 D5' - 'D5 FF FF FF FF FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF FA FA FA FF FB FB FB FF FB FB FB FF FB FB' - 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 83 83 83 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D5 D5' - 'D5 FF FF FF FF FF FA FA FA FF FA FA FA FF FB FB' - 'FB FF FB FB FB FF FB FB FB FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FC FC FC FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 84 84 84 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 40 40 40 FF D5 D5' - 'D5 FF FF FF FF FF FB FB FB FF FB FB FB FF FB FB' - 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 85 85 85 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 40 40 40 FF D6 D6' - 'D6 FF FF FF FF FF FB FB FB FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 85 85 85 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D6 D6' - 'D6 FF FF FF FF FF FB FB FB FF FC FC FC FF FD FD' - 'FD FF FD FD FD FF FC FC FC FF FD FD FD FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F0 F0 F0 FF 86 86 86 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D6 D6' - 'D6 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F1 F1 F1 FF 87 87 87 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' - 'D7 FF FF FF FF FF FD FD FD FF FD FD FD FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F1 F1 F1 FF 87 87 87 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' - 'D7 FF FF FF FF FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F1 F1 F1 FF 88 88 88 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' - 'D7 FF FF FF FF FF FE FE FE FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F1 F1 F1 FF 88 88 88 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 42 42 42 FF D8 D8' - 'D8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F1 F1 F1 FF 89 89 89 FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 42 42 42 FF D9 D9' - 'D9 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F2 F2 F2 FF 8A 8A 8A FF 05 05' - '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 84 00 00 00 FF 47 47 47 FF D9 D9' - 'D9 FF FB FB FB FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' - 'F8 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' - 'F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' - 'F7 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' - 'F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5 F5 FF F5 F5' - 'F5 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' - 'F4 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4' - 'F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3' - 'F3 FF F6 F6 F6 FF E8 E8 E8 FF 8F 8F 8F FF 06 06' - '06 FF 00 00 00 F7 00 00 00 38 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 83 00 00 00 FF 2D 2D 2D FF 98 98' - '98 FF 98 98 98 FF 97 97 97 FF 97 97 97 FF 97 97' - '97 FF 96 96 96 FF 95 95 95 FF 95 95 95 FF 95 95' - '95 FF 93 93 93 FF 93 93 93 FF 93 93 93 FF 92 92' - '92 FF 91 91 91 FF 90 90 90 FF 90 90 90 FF 90 90' - '90 FF 8F 8F 8F FF 8F 8F 8F FF 8E 8E 8E FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8B 8B 8B FF 89 89' - '89 FF 89 89 89 FF 88 88 88 FF 88 88 88 FF 86 86' - '86 FF 86 86 86 FF 86 86 86 FF 86 86 86 FF 84 84' - '84 FF 84 84 84 FF 87 87 87 FF 6C 6C 6C FF 04 04' - '04 FF 00 00 00 F7 00 00 00 33 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 47 00 00 00 F5 00 00 00 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' - '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' - '04 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' - '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' - '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' - '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 00 00' - '00 FF 00 00 00 C1 00 00 00 14 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 52 00 00 00 EA 00 00' - '00 F3 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F4 00 00' - '00 C7 00 00 00 29 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 F0 00 00 01 FF FF 00 00 E0 00' - '00 00 FF FF 00 00 E0 00 00 00 7F FF 00 00 E0 00' - '00 00 3F FF 00 00 E0 00 00 00 1F FF 00 00 E0 00' - '00 00 0F FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 03 FF 00 00 E0 00 00 00 01 FF 00 00 E0 00' - '00 00 00 FF 00 00 E0 00 00 00 00 7F 00 00 E0 00' - '00 00 00 3F 00 00 E0 00 00 00 00 1F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 F0 00' - '00 00 00 0F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 00 00' - '00 64 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 62 00 00 00 41 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4D 01 01 01 FB 05 05' - '05 FF 03 03 03 FF 03 03 03 FF 02 02 02 FF 02 02' - '02 FF 02 02 02 FF 02 02 02 FF 02 02 02 FF 02 02' - '02 FF 02 02 02 FF 02 02 02 FF 02 02 02 FF 01 01' - '01 FF 00 00 00 FF 03 03 03 FF 01 01 01 FD 00 00' - '00 7F 00 00 00 02 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1A 1A 1A FF 8C 8C' - '8C FF 9F 9F 9F FF 9C 9C 9C FF 9A 9A 9A FF 9A 9A' - '9A FF 99 99 99 FF 99 99 99 FF 97 97 97 FF 97 97' - '97 FF 96 96 96 FF 96 96 96 FF 95 95 95 FF 93 93' - '93 FF 8E 8E 8E FF 7D 7D 7D FF 33 33 33 FF 00 00' - '00 FD 00 00 00 79 00 00 00 02 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' - 'C6 FF F7 F7 F7 FF EA EA EA FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EC EC' - 'EC FF ED ED ED FF EE EE EE FF EE EE EE FF EF EF' - 'EF FF F3 F3 F3 FF B7 B7 B7 FF 94 94 94 FF 34 34' - '34 FF 00 00 00 FD 00 00 00 7A 00 00 00 02 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1C 1C 1C FF C4 C4' - 'C4 FF EB EB EB FF D8 D8 D8 FF DA DA DA FF DB DB' - 'DB FF DB DB DB FF DC DC DC FF DC DC DC FF DC DC' - 'DC FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' - 'DE FF E0 E0 E0 FF AE AE AE FF D1 D1 D1 FF A4 A4' - 'A4 FF 32 32 32 FF 00 00 00 FD 00 00 00 7A 00 00' - '00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1C 1C 1C FF C4 C4' - 'C4 FF ED ED ED FF DB DB DB FF DD DD DD FF DD DD' - 'DD FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' - 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E2 E2 E2 FF AE AE AE FF D9 D9 D9 FF E9 E9' - 'E9 FF A3 A3 A3 FF 2E 2E 2E FF 00 00 00 FD 00 00' - '00 7A 00 00 00 02 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' - 'C6 FF EF EF EF FF DD DD DD FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2' - 'E2 FF E4 E4 E4 FF B0 B0 B0 FF DA DA DA FF F1 F1' - 'F1 FF EC EC EC FF A3 A3 A3 FF 2B 2B 2B FF 00 00' - '00 FD 00 00 00 79 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' - 'C6 FF EF EF EF FF DE DE DE FF E0 E0 E0 FF E0 E0' - 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2' - 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E5 E5 E5 FF B1 B1 B1 FF DE DE DE FF F2 F2' - 'F2 FF F4 F4 F4 FF F1 F1 F1 FF A4 A4 A4 FF 2B 2B' - '2B FF 00 00 00 FC 00 00 00 72 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C7 C7' - 'C7 FF F1 F1 F1 FF E0 E0 E0 FF E2 E2 E2 FF E2 E2' - 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E7 E7 E7 FF B3 B3 B3 FF E1 E1 E1 FF F6 F6' - 'F6 FF F4 F4 F4 FF F9 F9 F9 FF F6 F6 F6 FF A6 A6' - 'A6 FF 2D 2D 2D FF 00 00 00 F9 00 00 00 6F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C7 C7' - 'C7 FF F1 F1 F1 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5' - 'E5 FF E5 E5 E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6' - 'E6 FF E8 E8 E8 FF B5 B5 B5 FF E8 E8 E8 FF FE FE' - 'FE FF FC FC FC FF FD FD FD FF FF FF FF FF FC FC' - 'FC FF AD AD AD FF 31 31 31 FF 00 00 00 F9 00 00' - '00 6F 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C8 C8' - 'C8 FF F3 F3 F3 FF E3 E3 E3 FF E5 E5 E5 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' - 'E8 FF EA EA EA FF B2 B2 B2 FF D8 D8 D8 FF EC EC' - 'EC FF EA EA EA FF EB EB EB FF EB EB EB FF EF EF' - 'EF FF EA EA EA FF 98 98 98 FF 2C 2C 2C FF 00 00' - '00 F5 00 00 00 42 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C8 C8' - 'C8 FF F3 F3 F3 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' - 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' - 'E9 FF EC EC EC FF C9 C9 C9 FF B3 B3 B3 FF B6 B6' - 'B6 FF B5 B5 B5 FF B5 B5 B5 FF B5 B5 B5 FF B4 B4' - 'B4 FF B6 B6 B6 FF BA BA BA FF 80 80 80 FF 03 03' - '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF C9 C9' - 'C9 FF F5 F5 F5 FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9 E9 FF E9 E9' - 'E9 FF EA EA EA FF EA EA EA FF EA EA EA FF EB EB' - 'EB FF EB EB EB FF EE EE EE FF EE EE EE FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' - 'EF FF F0 F0 F0 FF F7 F7 F7 FF 93 93 93 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF CA CA' - 'CA FF F7 F7 F7 FF EA EA EA FF EC EC EC FF EA EA' - 'EA FF E9 E9 E9 FF EA EA EA FF EA EA EA FF EB EB' - 'EB FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' - 'EF FF F1 F1 F1 FF F6 F6 F6 FF 93 93 93 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF CA CA' - 'CA FF F8 F8 F8 FF EC EC EC FF EE EE EE FF EF EF' - 'EF FF EE EE EE FF EB EB EB FF EB EB EB FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF ED ED ED FF EE EE' - 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' - 'EF FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1' - 'F1 FF F2 F2 F2 FF F7 F7 F7 FF 93 93 93 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CB CB' - 'CB FF F9 F9 F9 FF EE EE EE FF F0 F0 F0 FF F1 F1' - 'F1 FF F2 F2 F2 FF F1 F1 F1 FF EE EE EE FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF EE EE EE FF EF EF' - 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F1 F1' - 'F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F3 F3 F3 FF F8 F8 F8 FF 94 94 94 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CC CC' - 'CC FF FB FB FB FF F0 F0 F0 FF F2 F2 F2 FF F2 F2' - 'F2 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4' - 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3' - 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F4 F4' - 'F4 FF F5 F5 F5 FF F9 F9 F9 FF 94 94 94 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CD CD' - 'CD FF FB FB FB FF F2 F2 F2 FF F3 F3 F3 FF F4 F4' - 'F4 FF F5 F5 F5 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8' - 'F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF FB FB' - 'FB FF FB FB FB FF FB FB FB FF FA FA FA FF F8 F8' - 'F8 FF F6 F6 F6 FF F5 F5 F5 FF F4 F4 F4 FF F5 F5' - 'F5 FF F6 F6 F6 FF FA FA FA FF 95 95 95 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CE CE' - 'CE FF FD FD FD FF F4 F4 F4 FF F4 F4 F4 FF F6 F6' - 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' - 'F8 FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' - 'FB FF FC FC FC FF FD FD FD FF FD FD FD FF FE FE' - 'FE FF FE FE FE FF FC FC FC FF F9 F9 F9 FF F6 F6' - 'F6 FF F7 F7 F7 FF FB FB FB FF 96 96 96 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CE CE' - 'CE FF FE FE FE FF F5 F5 F5 FF F6 F6 F6 FF F7 F7' - 'F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' - 'FA FF FB FB FB FF FB FB FB FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FD FD' - 'FD FF FB FB FB FF FC FC FC FF 97 97 97 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CF CF' - 'CF FF FF FF FF FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' - 'F8 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FB FB' - 'FB FF FB FB FB FF FC FC FC FF FC FC FC FF FD FD' - 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 98 98 98 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 22 22 22 FF CF CF' - 'CF FF FF FF FF FF F8 F8 F8 FF F9 F9 F9 FF FA FA' - 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 99 99 99 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 22 22 22 FF D0 D0' - 'D0 FF FF FF FF FF F9 F9 F9 FF FA FA FA FF FB FB' - 'FB FF FB FB FB FF FB FB FB FF FC FC FC FF FD FD' - 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 99 99 99 FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D1 D1' - 'D1 FF FF FF FF FF FA FA FA FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9A 9A 9A FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D1 D1' - 'D1 FF FF FF FF FF FC FC FC FF FC FC FC FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9B 9B 9B FF 02 02' - '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D2 D2' - 'D2 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9C 9C 9C FF 03 03' - '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D3 D3' - 'D3 FF FF FF FF FF FE FE FE FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9D 9D 9D FF 03 03' - '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D3 D3' - 'D3 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9D 9D 9D FF 03 03' - '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 24 24 24 FF D4 D4' - 'D4 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 9E 9E 9E FF 03 03' - '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 84 27 27 27 FF D8 D8' - 'D8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FE FE' - 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FC FC FC FF FC FC FC FF FC FC' - 'FC FF FD FD FD FF FF FF FF FF A3 A3 A3 FF 04 04' - '04 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 7F 18 18 18 FF 77 77' - '77 FF 7D 7D 7D FF 7B 7B 7B FF 7A 7A 7A FF 79 79' - '79 FF 79 79 79 FF 78 78 78 FF 78 78 78 FF 77 77' - '77 FF 76 76 76 FF 75 75 75 FF 75 75 75 FF 74 74' - '74 FF 73 73 73 FF 72 72 72 FF 71 71 71 FF 70 70' - '70 FF 70 70 70 FF 6F 6F 6F FF 6E 6E 6E FF 6E 6E' - '6E FF 6D 6D 6D FF 6E 6E 6E FF 59 59 59 FF 03 03' - '03 FF 00 00 00 59 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2A 00 00 00 D3 00 00' - '00 F5 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F6 00 00' - '00 B6 00 00 00 14 00 00 00 00 00 00 00 00 E0 00' - '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' - '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' - '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 01 01 63 05 05' - '05 AF 04 04 04 A8 04 04 04 A8 04 04 04 A8 04 04' - '04 A8 03 03 03 A8 03 03 03 AA 02 02 02 A0 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 13 13 13 CB A8 A8' - 'A8 FF BC BC BC FF B7 B7 B7 FF B7 B7 B7 FF B6 B6' - 'B6 FF B7 B7 B7 FF B6 B6 B6 FF 7A 7A 7A FF 0F 0F' - '0F D5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 17 17 17 CC D1 D1' - 'D1 FF EA EA EA FF E5 E5 E5 FF E6 E6 E6 FF E7 E7' - 'E7 FF E9 E9 E9 FF E3 E3 E3 FF D0 D0 D0 FF 95 95' - '95 FF 0B 0B 0B D5 00 00 00 28 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 17 17 17 CC CD CD' - 'CD FF E4 E4 E4 FF DF DF DF FF E0 E0 E0 FF E1 E1' - 'E1 FF E2 E2 E2 FF DA DA DA FF CE CE CE FF F9 F9' - 'F9 FF 95 95 95 FF 0A 0A 0A D4 00 00 00 25 00 00' - '00 00 00 00 00 00 00 00 00 00 17 17 17 CC D0 D0' - 'D0 FF E7 E7 E7 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' - 'E4 FF E6 E6 E6 FF DD DD DD FF D2 D2 D2 FF FF FF' - 'FF FF FF FF FF FF 9E 9E 9E FF 0D 0D 0D D1 00 00' - '00 24 00 00 00 00 00 00 00 00 17 17 17 CC D1 D1' - 'D1 FF EB EB EB FF E5 E5 E5 FF E7 E7 E7 FF E7 E7' - 'E7 FF E9 E9 E9 FF E4 E4 E4 FF CB CB CB FF D7 D7' - 'D7 FF D9 D9 D9 FF DF DF DF FF 7C 7C 7C FF 00 00' - '00 9D 00 00 00 00 00 00 00 00 17 17 17 CC D4 D4' - 'D4 FF F0 F0 F0 FF E9 E9 E9 FF E9 E9 E9 FF EA EA' - 'EA FF EB EB EB FF EC EC EC FF E8 E8 E8 FF E4 E4' - 'E4 FF E5 E5 E5 FF EF EF EF FF BC BC BC FF 03 03' - '03 A8 00 00 00 00 00 00 00 00 17 17 17 CC D6 D6' - 'D6 FF F4 F4 F4 FF EF EF EF FF EE EE EE FF ED ED' - 'ED FF ED ED ED FF EE EE EE FF F0 F0 F0 FF F1 F1' - 'F1 FF F1 F1 F1 FF FC FC FC FF BD BD BD FF 02 02' - '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC D8 D8' - 'D8 FF F8 F8 F8 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' - 'F5 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5' - 'F5 FF F4 F4 F4 FF FE FE FE FF BE BE BE FF 03 03' - '03 A8 00 00 00 00 00 00 00 00 18 18 18 CC DB DB' - 'DB FF FB FB FB FF F6 F6 F6 FF F8 F8 F8 FF FA FA' - 'FA FF FB FB FB FF FC FC FC FF FD FD FD FF FE FE' - 'FE FF FD FD FD FF FF FF FF FF C0 C0 C0 FF 02 02' - '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC DC DC' - 'DC FF FE FE FE FF F9 F9 F9 FF FB FB FB FF FC FC' - 'FC FF FC FC FC FF FD FD FD FF FE FE FE FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF C3 C3 C3 FF 02 02' - '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC DE DE' - 'DE FF FF FF FF FF FC FC FC FF FC FC FC FF FD FD' - 'FD FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF C4 C4 C4 FF 03 03' - '03 A8 00 00 00 00 00 00 00 00 18 18 18 CC DF DF' - 'DF FF FF FF FF FF FD FD FD FF FE FE FE FF FE FE' - 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF C5 C5 C5 FF 03 03' - '03 A8 00 00 00 00 00 00 00 00 19 19 19 CC E2 E2' - 'E2 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF C7 C7 C7 FF 03 03' - '03 A8 00 00 00 00 00 00 00 00 19 19 19 CC E2 E2' - 'E2 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' - 'FD FF FD FD FD FF FD FD FD FF FC FC FC FF FC FC' - 'FC FF FB FB FB FF FF FF FF FF C6 C6 C6 FF 04 04' - '04 A8 00 00 00 00 00 00 00 00 09 09 09 A0 41 41' - '41 F9 46 46 46 F0 44 44 44 F0 44 44 44 F0 43 43' - '43 F0 42 42 42 F0 42 42 42 F0 41 41 41 F0 3F 3F' - '3F F0 3F 3F 3F F0 40 40 40 F0 36 36 36 FB 02 02' - '02 82 00 00 00 00 80 1F 00 00 80 0F 00 00 80 07' - '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00' -} */ - - -/* BINRES folder.ico */ -3 ICON folder.ico -/* { - '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 00 00 00 00 11 00 00 00 00 11 00 22 00' - '00 00 33 00 00 00 33 33 00 00 33 33 33 00 44 00' - '00 00 66 33 00 00 66 33 33 00 66 66 33 00 7F 7F' - '7F 00 99 33 00 00 99 33 33 00 99 66 33 00 99 66' - '66 00 CC 66 66 00 FF 99 33 00 FF CC 33 00 99 99' - '66 00 CC 99 66 00 FF 99 66 00 CC CC 66 00 FF CC' - '66 00 BB BB BB 00 CC 99 99 00 FF 99 99 00 CC CC' - '99 00 FF CC 99 00 FF FF 99 00 CC 99 CC 00 CC CC' - 'CC 00 DD DD DD 00 FF CC CC 00 FF FF CC 00 FF CC' - 'FF 00 EE EE EE 00 FF FF FF 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 56 00 58 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' - '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 66 6F 6C 64 65 72 2E 69 63' - '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 27 27 27 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 27 02 03 27 27' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 27 03 04 0D 06 27' - '27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 27 27 27 09 11 22 1A 06' - '27 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 27 27 27 0F 1B 22 26 26 1A' - '05 27 27 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 27 02 08 15 1B 1C 26 26 26 26' - '1A 04 27 27 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 27 27 27 08 1A 1D 1A 26 26 26 26 26' - '25 15 04 27 27 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 27 27 27 0A 1D 1D 1A 1D 1D 26 26 26 26' - '26 25 10 04 27 27 00 00 00 00 00 00 00 00 00 00' - '00 00 27 01 01 10 23 1D 15 23 16 12 18 26 26 26' - '26 26 25 10 01 27 27 00 00 00 00 00 00 00 00 00' - '27 27 02 06 1B 23 1D 1A 22 12 12 16 12 1D 26 26' - '26 25 25 25 10 01 27 27 00 00 00 00 00 00 00 27' - '27 27 0E 22 23 1D 1A 22 18 12 16 12 16 12 18 25' - '26 24 25 23 25 10 01 27 27 00 00 00 00 00 27 01' - '04 15 23 22 22 1C 1D 1B 12 16 12 12 18 16 16 1D' - '23 25 25 21 25 22 10 01 27 27 00 00 00 00 03 06' - '1D 25 25 23 1C 1B 1D 13 16 12 18 16 12 16 18 16' - '1D 25 25 25 22 21 21 0F 01 27 27 00 00 00 27 09' - '22 23 22 22 17 1D 16 12 16 16 12 16 16 18 16 18' - '1B 1D 25 21 21 21 20 22 09 02 27 27 00 00 27 27' - '06 22 23 15 1D 16 12 16 16 13 16 18 12 16 18 1B' - '18 1D 1D 21 21 20 22 20 22 0A 27 27 27 00 00 27' - '27 09 16 1D 16 13 16 16 12 16 12 16 16 18 16 18' - '1D 1D 1E 22 20 22 19 20 19 22 0F 27 27 27 00 00' - '27 27 09 16 12 16 16 12 18 16 16 12 18 16 18 1D' - '1D 1D 22 22 23 20 22 19 22 19 1C 0E 27 27 00 00' - '00 27 27 09 16 16 16 18 16 12 18 16 16 1D 1D 1D' - '22 1E 22 23 22 23 20 19 19 22 1F 14 01 27 00 00' - '00 00 27 27 09 12 18 16 12 16 16 1D 1D 1D 1D 23' - '1D 22 23 22 23 23 25 22 19 19 14 02 27 27 00 00' - '00 00 00 27 27 09 16 18 16 18 1D 1D 1D 1D 22 1D' - '23 22 23 23 23 24 23 25 20 1A 04 27 27 00 00 00' - '00 00 00 00 27 27 09 16 18 1D 22 1D 1D 22 1D 23' - '22 23 22 23 24 23 26 26 1D 07 27 27 00 00 00 00' - '00 00 00 00 00 27 27 09 1D 22 1D 22 1D 22 23 22' - '23 22 26 23 25 23 25 22 0A 27 27 00 00 00 00 00' - '00 00 00 00 00 00 27 27 10 1D 22 1E 22 23 22 23' - '22 23 23 24 23 26 25 0B 27 27 00 00 00 00 00 00' - '00 00 00 00 00 00 27 27 15 23 22 22 23 22 23 24' - '23 25 25 23 26 26 0F 27 27 00 00 00 00 00 00 00' - '00 00 00 00 00 00 27 27 05 1C 23 22 22 23 24 23' - '25 25 23 26 26 10 27 27 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 27 27 04 17 22 23 23 25 25' - '23 25 26 26 15 27 27 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 27 27 04 1D 26 26 25 23' - '26 26 25 22 04 27 27 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 27 27 06 22 25 26 26' - '25 26 22 06 27 27 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 27 27 04 1C 26 26' - '26 23 07 27 27 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 27 27 01 1A 26' - '23 0A 27 27 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 27 27 27 06' - '04 27 27 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 27' - '27 27 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' - '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' - '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' - '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' - '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' - '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' - '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' - '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' - '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 11 00 00 00 00 11' - '00 00 00 00 11 00 11 11 11 00 22 00 00 00 33 00' - '00 00 33 33 00 00 33 00 33 00 22 22 22 00 33 33' - '33 00 66 33 00 00 66 33 33 00 66 66 33 00 44 44' - '44 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 99 66' - '66 00 FF 99 33 00 99 99 66 00 CC 99 66 00 FF 99' - '66 00 FF CC 66 00 CC 99 99 00 CC CC 99 00 FF CC' - '99 00 FF FF 99 00 CC 99 CC 00 CC CC CC 00 DD DD' - 'DD 00 FF CC CC 00 FF FF CC 00 EE EE EE 00 FF FF' - 'FF 00 00 00 00 00 FF CC FF 00 EE EE EE 00 FF FF' - 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' - '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' - '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 56 00' - '58 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 56 00 00 00 00 00 00 00 03 00' - '00 00 5E 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 66' - '6F 6C 64 65 72 2E 69 63 6F 00 1A 93 4B 00 14 1A' - '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' - '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' - '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 01 23 23 00' - '00 00 00 00 00 00 00 00 00 00 00 02 03 12 0C 23' - '00 00 00 00 00 00 00 00 00 00 02 08 15 22 20 0A' - '03 00 00 00 00 00 00 00 23 23 0C 1A 1F 22 22 1F' - '07 03 00 00 00 00 00 01 01 10 1A 1A 13 1A 22 22' - '1D 07 23 00 00 00 23 09 1A 1F 1A 13 16 13 1A 21' - '22 1C 06 02 00 00 05 1F 20 1A 16 16 13 17 16 1A' - '1E 21 19 05 23 00 23 0D 1A 16 13 17 16 16 17 1A' - '1A 1E 1D 18 04 01 00 23 0B 17 16 16 13 16 1A 1A' - '20 1F 1D 1F 14 23 00 00 23 0B 17 16 1A 1A 1F 20' - '1F 21 20 1C 0A 23 00 00 00 23 0C 17 1F 1B 1F 1F' - '20 20 21 0D 23 00 00 00 00 00 23 18 20 1F 20 1F' - '22 22 0F 23 00 00 00 00 00 00 23 0E 1A 21 20 22' - '22 14 23 00 00 00 00 00 00 00 00 23 0C 20 22 22' - '18 02 23 00 00 00 00 00 00 00 00 00 23 0E 1F 1D' - '02 23 00 00 00 00 00 00 00 00 00 00 00 23 02 01' - '23 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' - '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' - '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' - '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' - '00 00 FE 1F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 08 10 00 00 00 00 00 00 00 00 00' - '00 00 00 00 08 BF 81 00 00 00 00 00 00 00 00 00' - '00 00 00 04 1B 7F F8 00 00 00 00 00 00 00 00 00' - '00 00 00 9B 77 FF FF 89 00 00 00 00 00 00 00 00' - '00 00 00 78 7F FF FF F8 20 00 00 00 00 00 00 00' - '00 00 1F B7 78 FF FF F7 10 00 00 00 00 00 00 00' - '00 81 77 8F B7 BF FF FF F8 20 00 00 00 00 00 00' - '08 BF FB FB 8B 8B FF FF F7 18 00 00 00 00 00 00' - '17 7F B7 88 B1 B7 BF FF 7F F8 00 00 00 00 00 0B' - 'FF F8 77 BB 7B 7B 78 FF F7 F7 B0 00 00 00 09 7F' - '7F B7 7B 88 B7 B8 BF BF 7F 77 7B 00 00 00 08 7F' - '7F 87 B8 B7 B8 B8 7B FB F7 F7 F7 90 00 00 00 97' - 'FB 7B 7B 7B 7B 8F B7 BF BF 7F 77 78 00 00 00 08' - 'B7 B8 B7 B8 B8 BB 7B 7B F7 77 77 7F 90 00 00 00' - '1B 7B 8B 7B 87 B7 BF BF 7F F7 77 FB F1 00 00 00' - '08 B8 B7 B7 BB 7B 77 F7 FB FF 77 77 78 00 00 00' - '00 8B 7B 7B B7 77 7F BF BF FF 77 77 80 00 00 00' - '00 08 B8 B7 7B FB F7 F7 F7 FF FF B7 00 00 00 00' - '00 00 1B FB 77 7F BF 7F BF FF FF 78 00 00 00 00' - '00 00 08 BF 7F BF 7F F7 FF BF FF 80 00 00 00 00' - '00 00 00 87 FB F7 FF BF FF FF F8 00 00 00 00 00' - '00 00 00 BF 77 FF BF FF 7F FF 80 00 00 00 00 00' - '00 00 00 07 F7 F7 FF F7 FF F8 00 00 00 00 00 00' - '00 00 00 00 BF 7F 7F FF FF B0 00 00 00 00 00 00' - '00 00 00 00 8B FF FF FF F7 00 00 00 00 00 00 00' - '00 00 00 00 08 7F FF FF 78 00 00 00 00 00 00 00' - '00 00 00 00 00 07 FF F7 80 00 00 00 00 00 00 00' - '00 00 00 00 00 00 8F F8 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' - '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' - '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' - '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' - '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' - '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' - '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' - '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' - '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 01 80 00 00 00 00 00 01 8F 78 00 00 00 00 00' - '1B FF F7 10 00 00 00 4B 8F B7 FF 70 00 00 08 BF' - '7B 8B FF F7 90 00 07 F7 7B 87 B7 F7 70 00 08 7B' - 'B7 BB 7B 7F 77 00 00 8B 7B B7 BF F7 77 B0 00 08' - 'B7 B7 FB FF F7 00 00 00 17 7F BF 7F F8 00 00 00' - '0B F7 FF FF 80 00 00 00 08 7F 7F F8 00 00 00 00' - '00 8F FF 70 00 00 00 00 00 08 F7 00 00 00 00 00' - '00 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' - '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' - '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' - '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' - '00 00 FE 1F 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 00 00 00 00 11 00 00 00 00 11 00 22 00' - '00 00 33 00 00 00 00 22 00 00 33 33 00 00 22 22' - '22 00 44 00 00 00 55 00 00 00 66 00 00 00 66 33' - '00 00 66 33 33 00 66 66 33 00 7F 7F 7F 00 99 33' - '00 00 99 33 33 00 99 66 00 00 99 66 33 00 CC 66' - '00 00 CC 66 33 00 99 66 66 00 CC 66 66 00 CC 99' - '33 00 FF 99 33 00 FF CC 33 00 99 99 66 00 CC 99' - '66 00 FF 99 66 00 CC CC 66 00 FF CC 66 00 BB BB' - 'BB 00 CC 99 99 00 FF 99 99 00 CC CC 99 00 FF CC' - '99 00 FF FF 99 00 CC 99 CC 00 CC CC CC 00 DD DD' - 'DD 00 FF CC CC 00 CC FF CC 00 FF FF CC 00 FF CC' - 'FF 00 EE EE EE 00 FF FF FF 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 56 00 58 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' - '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 66 6F 6C 64 65 72 2E 69 63' - '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 2F 2F 2F 2F 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 2F 2F 2F 2F 2F 2F 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 2F 2F 2F 01 2F 2F 2F 2F 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '2F 2F 2F 2F 09 10 0C 02 2F 2F 2F 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' - '2F 2F 04 11 15 1C 17 09 02 2F 2F 2F 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F 2F' - '2F 05 13 1C 23 2E 2D 1C 0B 2F 2F 2F 2F 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 2F' - '0B 23 22 21 2E 2E 2E 28 1C 0A 2F 2F 2F 2F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 01 0C' - '23 22 18 2E 2E 2E 2E 2E 28 1C 05 2F 2F 2F 2F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2F 2F 2F 2F 04 13 29' - '24 17 2D 2E 2E 2E 2E 2E 2E 28 17 05 02 2F 2F 2F' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 2F 2F 2F 01 05 1C 2D 24' - '15 2D 2E 2E 2E 2E 2E 2E 2E 2E 27 1C 04 01 2F 2F' - '2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 2F 2F 2F 01 0C 24 29 1F 17' - '2D 24 24 2E 2E 2E 2E 2E 2E 2E 2E 28 17 06 2F 2F' - '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2F 2F 2F 2F 05 16 29 29 24 17 29' - '29 19 1D 24 2E 2E 2E 2E 2E 2E 2E 2D 28 17 09 2F' - '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 2F 2F 2F 2F 0C 21 2B 24 24 1D 27 2B' - '19 19 19 1D 29 2E 2E 2E 2E 2E 2D 2E 2E 28 1B 05' - '2F 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 2F 2F 2F 03 10 29 2B 24 29 1D 20 2B 19' - '19 1D 19 19 19 29 2E 2E 2E 2E 2E 2D 2D 2D 29 17' - '04 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' - '00 2F 2F 2F 2F 05 13 29 2B 24 29 1C 1C 2E 1D 19' - '19 19 1D 19 1D 19 2D 2E 2E 2E 2D 2E 2D 2D 2D 27' - '13 04 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00' - '2F 2F 2F 2F 0A 21 2B 2B 24 29 24 21 2E 1D 19 1D' - '19 1D 19 1D 19 1F 19 29 2E 2D 2E 2D 29 2D 28 2D' - '28 15 2F 2F 2F 2F 00 00 00 00 00 00 00 00 00 2F' - '2F 2F 04 13 24 28 29 2B 29 24 1C 2B 24 19 1D 19' - '1D 19 1D 1A 1D 1D 1F 1D 2B 2C 2E 2D 2D 2D 2D 28' - '29 27 15 04 2F 2F 2F 00 00 00 00 00 00 00 2F 2F' - '2F 05 13 29 2E 2B 2B 29 24 1C 2D 24 19 1D 1A 1D' - '19 1D 19 1D 19 1D 1D 1F 1D 25 28 2D 2D 2D 29 28' - '28 28 29 13 01 2F 2F 2F 00 00 00 00 00 00 2F 2F' - '0C 22 2E 2B 29 29 2D 2B 1C 29 1F 1D 1D 19 1D 19' - '1D 1A 1D 19 1D 1F 1D 1D 1F 22 2B 2D 2D 28 28 28' - '28 27 28 27 15 2F 2F 2F 2F 00 00 00 00 00 2F 2F' - '0C 2B 29 2B 29 2B 2B 17 24 24 1D 1D 19 1D 1D 1A' - '1D 1D 19 1D 1F 1D 1D 1F 22 1F 1F 29 28 2D 29 28' - '28 28 27 29 20 15 04 2F 2F 2F 2F 00 00 00 2F 2F' - '2F 10 2B 2D 2B 2D 1D 23 24 1D 19 1D 1F 19 1D 1D' - '1A 1D 1D 19 1D 1F 1F 1D 1F 24 22 1F 29 28 2D 28' - '29 28 29 27 29 20 10 2F 2F 2F 2F 00 00 00 2F 2F' - '2F 2F 10 24 2E 1D 1C 24 19 1D 1F 19 1D 1F 19 1D' - '1D 1D 19 1D 1F 1D 1D 1F 22 1F 1F 24 24 29 2A 29' - '28 27 27 27 27 20 29 13 2F 2F 2F 2F 00 00 00 00' - '2F 2F 2F 11 24 1C 24 1D 1D 19 1D 1D 19 1D 1D 1A' - '1D 19 1F 1D 19 1F 1D 24 1F 22 24 24 24 24 29 28' - '27 29 27 29 20 27 28 24 11 02 2F 2F 2F 2F 00 00' - '00 2F 2F 01 12 1D 1F 1D 1A 1D 19 1D 1F 19 1F 1D' - '19 1D 1D 1A 1D 1D 1D 1F 1D 24 24 24 25 29 2B 29' - '28 27 27 27 27 27 21 27 28 10 2F 2F 2F 2F 00 00' - '00 00 2F 2F 04 14 1D 1D 1D 1D 1F 1D 19 1D 19 1D' - '1F 1D 19 1D 1F 1D 1F 24 24 24 25 29 29 25 29 2B' - '29 28 29 20 29 23 27 26 23 29 13 01 2F 2F 00 00' - '00 00 2F 2F 2F 08 10 19 1D 1F 19 1F 1D 1D 1D 1F' - '1D 19 1D 1D 1D 24 24 24 24 24 29 2B 24 29 2B 2B' - '29 2B 20 20 27 27 26 23 26 27 1C 02 2F 2F 00 00' - '00 00 00 2F 2F 2F 01 14 1D 1D 1D 19 1D 1F 1D 19' - '1D 1F 1D 1F 24 24 24 24 2B 24 24 29 2B 29 29 2B' - '2B 29 2E 27 23 26 23 20 20 21 05 2F 2F 2F 00 00' - '00 00 00 00 2F 2F 2F 03 12 19 1D 1D 1F 19 1F 1D' - '1F 1D 24 24 24 24 29 24 24 29 29 2B 29 2B 2B 29' - '2B 2E 2B 29 27 23 26 27 21 07 2F 2F 2F 00 00 00' - '00 00 00 00 00 00 2F 2F 2F 12 1D 1F 1D 1D 1D 1D' - '24 24 24 24 24 24 24 2B 29 24 2B 29 2B 29 2B 2B' - '2C 2B 2D 2E 28 26 23 21 0D 2F 2F 2F 00 00 00 00' - '00 00 00 00 00 00 2F 2F 2F 03 10 18 1D 1D 1F 24' - '24 29 24 24 2B 24 29 29 24 2B 29 2B 29 2B 2B 2C' - '2B 2D 2D 2E 2B 2B 27 0D 2F 2F 2F 00 00 00 00 00' - '00 00 00 00 00 00 00 00 2F 2F 2F 10 1D 1F 24 29' - '24 24 29 24 24 29 25 29 2B 29 2B 29 2E 29 2B 2D' - '2B 2E 2B 29 2E 2B 13 2F 2F 2F 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2F 2F 2F 0C 24 29 24' - '25 29 24 2B 29 25 29 29 2B 29 2B 2B 29 2B 2D 2B' - '2E 29 2B 2E 2E 13 2F 2F 2F 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 2F 2F 2F 0D 1F 29' - '29 24 29 24 29 29 2B 29 29 2B 29 2D 2B 2D 2D 2B' - '2D 2B 2E 2E 13 01 2F 2F 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 2F 2F 0C 1E 24' - '29 2B 29 2B 29 2B 29 2B 2B 2C 2B 2B 2D 2D 2B 2C' - '2B 2E 2E 1C 01 2F 2F 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 2F 2F 15 2D 29' - '1E 29 2B 29 2B 29 2B 29 2D 2B 2C 2B 2D 2B 2C 2B' - '2E 2D 22 02 01 2F 2F 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 2F 2F 07 22 2B' - '29 24 29 2B 29 2B 2C 2B 2B 2D 2B 2C 2B 2D 2B 2E' - '2E 29 07 2F 2F 2F 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 07 1C' - '2E 23 24 2C 2B 2D 2B 2C 2B 2D 2D 2B 2D 2D 2E 2E' - '24 07 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 04' - '1B 1D 29 2B 2D 2B 2C 2B 2E 2D 2B 2E 2D 2E 2E 29' - '0C 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F' - '01 18 2B 2D 2B 2C 2B 2E 2C 2B 2E 2D 2E 2E 29 0E' - '2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' - '2F 04 1C 2E 2E 2B 2E 2D 2B 2E 2D 2E 2E 2B 13 2F' - '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' - '2F 2F 04 1C 2D 2E 2D 2E 2E 2E 2E 2E 2E 1B 01 2F' - '2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '2F 2F 2F 2F 1C 2D 2E 2E 2E 2E 2E 2E 1C 01 2F 2F' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 2F 2F 2F 2F 13 2B 2E 2E 2E 2E 1E 01 2F 2F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 2F 2F 2F 0E 29 2E 2D 23 05 2F 2F 2F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 2F 2F 2F 07 13 07 04 2F 2F 2F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2F 2F 2F 2F 2F 2F 2F 2F 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 2F 2F 2F 2F 2F 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FC 3F FF FF 00 00 FF FF' - 'F8 1F FF FF 00 00 FF FF F0 0F FF FF 00 00 FF FF' - 'C0 07 FF FF 00 00 FF FF 80 03 FF FF 00 00 FF FF' - '00 01 FF FF 00 00 FF FC 00 00 FF FF 00 00 FF F8' - '00 00 7F FF 00 00 FF E0 00 00 3F FF 00 00 FF C0' - '00 00 1F FF 00 00 FF 80 00 00 0F FF 00 00 FE 00' - '00 00 0F FF 00 00 FC 00 00 00 03 FF 00 00 F8 00' - '00 00 03 FF 00 00 E0 00 00 00 01 FF 00 00 C0 00' - '00 00 00 FF 00 00 80 00 00 00 00 7F 00 00 00 00' - '00 00 00 3F 00 00 00 00 00 00 00 1F 00 00 00 00' - '00 00 00 07 00 00 00 00 00 00 00 07 00 00 00 00' - '00 00 00 03 00 00 C0 00 00 00 00 00 00 00 E0 00' - '00 00 00 00 00 00 F0 00 00 00 00 00 00 00 F0 00' - '00 00 00 00 00 00 F8 00 00 00 00 00 00 00 FC 00' - '00 00 00 01 00 00 FF 00 00 00 00 03 00 00 FF 00' - '00 00 00 07 00 00 FF C0 00 00 00 0F 00 00 FF E0' - '00 00 00 1F 00 00 FF F0 00 00 00 3F 00 00 FF F8' - '00 00 00 7F 00 00 FF F8 00 00 00 7F 00 00 FF F8' - '00 00 00 FF 00 00 FF F8 00 00 01 FF 00 00 FF FC' - '00 00 03 FF 00 00 FF FE 00 00 07 FF 00 00 FF FF' - '80 00 0F FF 00 00 FF FF 80 00 1F FF 00 00 FF FF' - 'C0 00 3F FF 00 00 FF FF E0 00 7F FF 00 00 FF FF' - 'F8 00 7F FF 00 00 FF FF FC 00 FF FF 00 00 FF FF' - 'FE 01 FF FF 00 00 FF FF FF 07 FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0E 00 00 00 32 00 00 00 2D 00 00 00 0B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 31 00 00' - '00 B1 00 00 00 F6 00 00 00 DF 00 00 00 65 00 00' - '00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 58 00 00 00 F2 00 00' - '00 FF 12 04 00 FF 02 00 00 FF 00 00 00 F6 00 00' - '00 71 00 00 00 08 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 12 00 00 00 9D 00 00 00 F6 00 00 00 FF 59 17' - '00 FF 97 2E 01 FF 6E 20 00 FF 06 00 00 FF 00 00' - '00 F0 00 00 00 65 00 00 00 08 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3A 00 00' - '00 C2 00 00 00 FF 17 03 00 FF 7A 37 1A FF BE 59' - '2D FF CF 9C 89 FF BF 81 6D FF 5A 1E 08 FF 06 00' - '00 FF 00 00 00 EE 00 00 00 5C 00 00 00 08 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 70 00 00 00 F3 00 00' - '00 FF 32 07 00 FF B1 63 41 FF D5 8F 70 FF E3 BF' - 'AF FF FF FF FF FF EA E7 EA FF C0 82 6C FF 64 1B' - '01 FF 00 00 00 FF 00 00 00 EE 00 00 00 5E 00 00' - '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 20 00 00 00 AC 00 00 00 FD 06 00 00 FF 61 1B' - '00 FF D5 9F 86 FF E2 A3 84 FF DB AE 9A FF FD FB' - 'FA FF FF FF FF FF FF FF FF FF E9 E3 E4 FF BD 87' - '77 FF 5A 1A 01 FF 02 00 00 FF 00 00 00 E6 00 00' - '00 52 00 00 00 08 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2A 00 00' - '00 C4 00 00 00 FF 08 00 00 FF 73 29 0F FF EE BD' - 'A5 FF EB AE 8B FF CA 7F 5C FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF E6 DF' - 'E1 FF BE 7A 63 FF 3D 0E 00 FF 00 00 00 FF 00 00' - '00 E2 00 00 00 3D 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 01 00 00 00 6C 00 00 00 E3 00 00' - '00 FF 2F 01 00 FF A7 66 50 FF F5 D0 B8 FF F3 B6' - '8D FF CF 89 67 FF F5 EB E8 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FD FD' - 'FE FF E4 DA DC FF B6 78 61 FF 44 11 00 FF 00 00' - '00 FF 00 00 00 CB 00 00 00 3C 00 00 00 01 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1C 00 00 00 8D 00 00 00 FF 07 00 00 FF 4D 1A' - '07 FF C9 81 63 FF FF E3 CD FF F7 BC 91 FF C7 71' - '47 FF F1 E5 E0 FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF E5 D8 DA FF B3 77 61 FF 33 0E' - '00 FF 00 00 00 FF 00 00 00 C8 00 00 00 33 00 00' - '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 30 00 00' - '00 D3 00 00 00 FF 0B 00 00 FF 85 36 19 FF E9 B7' - '9F FF FF E6 CB FF F9 B8 88 FF CE 7B 50 FF F2 EE' - 'EF FF FF C8 98 FF FF D7 B6 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FD FE FF FF E5 DA DB FF BE 7D' - '65 FF 30 0B 00 FF 00 00 00 FF 00 00 00 D2 00 00' - '00 33 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 04 00 00 00 72 00 00 00 EA 00 00' - '00 FF 37 0B 00 FF B1 71 56 FF F7 D4 BE FF FF DF' - 'C0 FF FD C3 95 FF D0 80 56 FF E9 D4 CC FF FF D4' - 'AD FF FF 92 39 FF FF 98 44 FF FF D6 B4 FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FE FE FE FF FC FC FB FF F8 F6 F7 FF E4 D9' - 'DA FF B5 80 6B FF 3A 12 02 FF 00 00 00 FF 00 00' - '00 C8 00 00 00 39 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1F 00 00 00 9F 00 00 00 FF 08 00 00 FF 5F 28' - '11 FF D3 93 74 FF FF EF DE FF FF D9 B5 FF FC C5' - '9B FF D5 83 56 FF E6 CE C4 FF FF EB D2 FF FF 93' - '3A FF FF 94 3D FF FF 93 3B FF FF 95 3E FF FF DD' - 'BF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FD FB FB FF FA F8 F8 FF F8 F6 F6 FF F5 F3' - 'F4 FF E7 DA DA FF B6 82 6C FF 2A 0D 00 FF 00 00' - '00 FF 00 00 00 BF 00 00 00 29 00 00 00 02 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3D 00 00' - '00 E1 00 00 00 FF 12 00 00 FF 94 3F 15 FF F3 CF' - 'BC FF FF EC D7 FF FF D1 AC FF FF D8 B4 FF DC 91' - '64 FF E0 C0 B3 FF FF E9 D3 FF FF 99 44 FF FF 96' - '40 FF FF 98 44 FF FF 98 43 FF FF 97 42 FF FF 9B' - '46 FF FF D3 AE FF FF FF FF FF FF FF FF FF FE FD' - 'FD FF FC FA FA FF F9 F6 F6 FF F6 F3 F3 FF F4 F0' - 'F0 FF F1 ED EF FF E3 D6 D6 FF BD 77 57 FF 27 08' - '00 FF 00 00 00 FF 00 00 00 C4 00 00 00 28 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 02 00 00 00 60 00 00 00 DD 00 00' - '00 FF 2F 0C 00 FF A1 5E 3C FF F7 D5 C0 FF FF EA' - 'D2 FF FF D4 B0 FF FF DB B8 FF E3 A2 76 FF D6 9E' - '83 FF FF F8 F1 FF FF AB 64 FF FF 95 3D FF FF 9A' - '46 FF FF 99 46 FF FF 99 45 FF FF 9A 47 FF FF 9C' - '49 FF FF A8 5D FF FF E3 CA FF FF FF FF FF FD FC' - 'FD FF FA F8 F8 FF F7 F5 F5 FF F4 F1 F1 FF F2 EE' - 'EE FF F1 EC EC FF EB E6 E8 FF E1 CF CC FF A2 62' - '43 FF 24 0A 00 FF 00 00 00 FF 00 00 00 A1 00 00' - '00 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 12 00 00 00 9E 00 00 00 FF 00 00 00 FF 59 1E' - '00 FF D5 99 7A FF FF F5 E8 FF FF E4 C7 FF FF D9' - 'B8 FF FF E0 C1 FF ED B6 8E FF D7 A1 86 FF FD FA' - 'F6 FF FF AC 66 FF FF 98 41 FF FF 9C 49 FF FF 9C' - '49 FF FF 9C 49 FF FF 9C 48 FF FF 9C 49 FF FF A0' - '51 FF FF A3 54 FF FF A7 59 FF FE DF C3 FF FB FF' - 'FF FF F9 F7 F8 FF F6 F3 F3 FF F4 F0 F0 FF F1 EC' - 'EC FF EF E9 E8 FF EC E6 E6 FF E9 E3 E5 FF E4 D0' - 'CA FF AE 6B 48 FF 16 02 00 FF 00 00 00 FF 00 00' - '00 B0 00 00 00 1C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 48 00 00' - '00 C8 00 00 00 FF 21 04 00 FF 8E 4B 25 FF EF C7' - 'B0 FF FF F0 DE FF FF E3 C9 FF FF DE C0 FF FF E8' - 'CC FF EF BF 99 FF D2 93 71 FF F9 F0 E9 FF FF BF' - '86 FF FF 98 43 FF FF 9D 4C FF FF 9E 4C FF FF 9D' - '4B FF FF 9D 4B FF FF 9D 4B FF FF 9E 4B FF FF A2' - '53 FF FF A7 59 FF FF AA 5E FF FF B0 6A FF FD D7' - 'B5 FF F7 F8 FC FF F5 F3 F3 FF F2 ED ED FF F0 EA' - 'EA FF ED E7 E7 FF EA E3 E3 FF E9 E1 E1 FF E5 DE' - 'E1 FF E0 CA C3 FF B0 6B 44 FF 23 09 00 FF 00 00' - '00 FE 00 00 00 B1 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4C 00 00 00 EB 00 00' - '00 FF 37 11 00 FF B5 72 4C FF FC DD C8 FF FF F8' - 'E8 FF FF E4 C8 FF FF E3 C8 FF FF E9 CF FF F2 CA' - 'A9 FF D4 92 69 FF F8 EC E3 FF FF C4 8E FF FF 98' - '42 FF FF 9F 4F FF FF A0 4F FF FF A0 4E FF FF 9F' - '4E FF FF 9F 4E FF FF 9F 4D FF FF 9F 4E FF FF A3' - '54 FF FF A8 5C FF FF AD 64 FF FF B0 67 FF FF B4' - '6F FF FA D9 BC FF F4 F0 F1 FF F1 ED EE FF EF E9' - 'E9 FF EC E5 E5 FF E9 E2 E2 FF E7 DE DE FF E5 DC' - 'DC FF E2 DA DD FF E3 CC C3 FF A4 5F 37 FF 25 0B' - '00 FF 00 00 00 FF 00 00 00 A1 00 00 00 25 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 EB 02 00 00 FF 6A 2F' - '0C FF E4 AC 8B FF FF FA EF FF FF F1 DC FF FF E7' - 'CE FF FF E8 D0 FF FF EC D5 FF FC E3 C8 FF D2 8B' - '5F FF F0 D2 BD FF FF C9 96 FF FF 9E 4A FF FF A1' - '51 FF FF A2 52 FF FF A1 51 FF FF A1 51 FF FF A1' - '51 FF FF A1 51 FF FF A1 50 FF FF A1 50 FF FF A5' - '57 FF FF AA 5E FF FF AE 66 FF FF B3 6D FF FF B7' - '72 FF FF B9 74 FF F8 D6 B7 FF EF EC EF FF ED E8' - 'E9 FF EB E4 E4 FF E8 E0 E0 FF E6 DD DD FF E3 DA' - 'D9 FF E0 D6 D6 FF DE D5 D8 FF E2 C7 BD FF AF 63' - '36 FF 16 03 00 FF 00 00 00 FF 00 00 00 B0 00 00' - '00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 ED 06 01 00 FF 7A 3C' - '16 FF F7 CA AA FF FF F4 E0 FF FF E9 D2 FF FF E9' - 'D2 FF FF ED D7 FF FA E1 C7 FF D1 87 58 FF EF C6' - 'A8 FF FF CD 9E FF FF A0 4D FF FF A2 53 FF FF A3' - '54 FF FF A3 54 FF FF A3 54 FF FF A3 53 FF FF A3' - '53 FF FF A3 53 FF FF A3 53 FF FF A3 53 FF FF A7' - '59 FF FF AC 60 FF FF B0 68 FF FF B4 6F FF FF B9' - '76 FF FF BD 7C FF FF C1 81 FF F9 D4 B1 FF EC E6' - 'E8 FF E9 E3 E3 FF E7 DE DE FF E4 DB DB FF E2 D7' - 'D7 FF DF D4 D4 FF DD D1 D0 FF DB D2 D5 FF DF C3' - 'B8 FF A9 5E 30 FF 1D 08 00 FF 00 00 00 FE 00 00' - '00 B1 00 00 00 26 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 7D 00 00 00 FF 08 01' - '00 FF 96 46 13 FF FB CF AC FF FF F4 E1 FF FF EB' - 'D6 FF FF F1 DE FF DF A6 7E FF E2 A8 7F FF FF CF' - 'A1 FF FF A2 52 FF FF A2 52 FF FF A3 54 FF FF A3' - '54 FF FF A3 54 FF FF A3 54 FF FF A3 54 FF FF A3' - '54 FF FF A3 54 FF FF A3 54 FF FF A3 54 FF FF A7' - '5A FF FF AC 62 FF FF B1 69 FF FF B5 71 FF FF BA' - '78 FF FF BF 7F FF FF C3 85 FF FF C6 89 FF F5 D7' - 'B9 FF E8 E1 E3 FF E5 DD DE FF E4 DA DA FF E1 D6' - 'D6 FF DD D3 D3 FF DB CF CF FF D8 CB CB FF D9 CF' - 'D3 FF E6 C9 BA FF 95 50 23 FF 0C 00 00 FF 00 00' - '00 FF 00 00 00 91 00 00 00 17 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 01 00 00 00 7C 00 00' - '00 FF 0B 03 00 FF 89 49 1D FF F7 C4 9A FF FF FC' - 'EC FF DF A8 7F FF DE 98 67 FF FF CC 9D FF FF A8' - '5C FF FF A2 52 FF FF A4 56 FF FF A4 55 FF FF A4' - '55 FF FF A4 55 FF FF A4 55 FF FF A4 55 FF FF A3' - '55 FF FF A3 55 FF FF A3 54 FF FF A3 54 FF FF A7' - '5B FF FF AC 62 FF FF B0 69 FF FF B5 71 FF FF BA' - '78 FF FF BF 80 FF FF C4 87 FF FF C8 8C FF FF CC' - '91 FF F4 D7 B9 FF E4 DB DB FF E1 D8 D9 FF DF D5' - 'D5 FF DD D1 D1 FF DB CE CE FF D8 CA CA FF D4 C6' - 'C6 FF D5 CA CE FF E5 C3 B1 FF 9D 5D 34 FF 0A 00' - '00 FF 00 00 00 FA 00 00 00 99 00 00 00 13 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 76 00 00 00 FC 09 00 00 FF 87 4B 20 FF E7 AE' - '83 FF DF 95 60 FF FD C1 8C FF FF A9 5F FF FF A2' - '53 FF FF A4 57 FF FF A4 57 FF FF A4 57 FF FF A4' - '56 FF FF A4 56 FF FF A4 56 FF FF A4 56 FF FF A4' - '56 FF FF A4 56 FF FF A4 55 FF FF A3 55 FF FF A7' - '5B FF FF AC 62 FF FF B1 6A FF FF B5 71 FF FF BA' - '78 FF FF BE 7E FF FF C4 86 FF FF CA 92 FF FF D2' - '9E FF FF D9 A9 FF F4 DE C6 FF E0 D6 D7 FF DD D2' - 'D3 FF DB CF CF FF D9 CC CC FF D6 C8 C8 FF D3 C4' - 'C4 FF D0 BF BF FF D6 CC D0 FF E6 C5 B3 FF 96 54' - '29 FF 11 05 00 FF 00 00 00 F9 00 00 00 82 00 00' - '00 16 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 5F 00 00 00 FB 0D 03 00 FF B1 50' - '0F FF FD AB 6A FF FF B3 6D FF FF A3 55 FF FF A5' - '58 FF FF A5 58 FF FF A5 58 FF FF A4 58 FF FF A4' - '58 FF FF A4 58 FF FF A4 58 FF FF A4 57 FF FF A4' - '57 FF FF A4 57 FF FF A4 57 FF FF A4 57 FF FF A8' - '5C FF FF AC 63 FF FF B0 69 FF FF B5 70 FF FF BA' - '7A FF FF C3 88 FF FF CF 9D FF FF D7 AB FF FF DB' - 'B4 FF FF E0 BA FF FF E3 BE FF F4 E0 CA FF DD D1' - 'D1 FF D9 CD CE FF D8 CA CA FF D5 C6 C6 FF D2 C3' - 'C3 FF D0 C0 C0 FF CC BA BA FF D0 C3 C6 FF EA CC' - 'BD FF 97 55 26 FF 0D 02 00 FF 00 00 00 FF 00 00' - '00 7D 00 00 00 0E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9E 00 00 00 FF 26 12' - '04 FF B2 5F 23 FF FB 98 48 FF FF AA 5F FF FF A6' - '5A FF FF A6 59 FF FF A6 59 FF FF A6 59 FF FF A6' - '59 FF FF A5 59 FF FF A5 59 FF FF A5 59 FF FF A5' - '58 FF FF A5 58 FF FF A5 58 FF FF A5 58 FF FF A7' - '5B FF FF AC 62 FF FF B5 72 FF FF C2 89 FF FF CB' - '99 FF FF D2 A6 FF FF D7 AD FF FF DA B2 FF FF DD' - 'B8 FF FF E1 BD FF FF E4 C3 FF FF E9 C8 FF F4 E3' - 'CE FF DB CD CC FF D5 C7 C8 FF D4 C5 C5 FF D1 C2' - 'C2 FF CF BE BE FF CC BA BA FF C9 B5 B6 FF CC BD' - 'C0 FF E2 BE AD FF A2 65 3A FF 0E 05 00 FF 00 00' - '00 EC 00 00 00 30 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 14 00 00 00 AC 00 00' - '00 FF 27 12 03 FF A7 53 15 FF F9 93 40 FF FF A7' - '5B FF FF A7 5C FF FF A6 5B FF FF A6 5B FF FF A6' - '5B FF FF A6 5B FF FF A6 5B FF FF A6 5A FF FF A6' - '5A FF FF A6 5A FF FF A5 58 FF FF A5 58 FF FF AE' - '69 FF FF BB 7F FF FF C9 97 FF FF CF A2 FF FF D2' - 'A7 FF FF D5 AC FF FF D9 B1 FF FF DC B8 FF FF E0' - 'BD FF FF E3 C2 FF FF E7 C8 FF FF EA CD FF FF EF' - 'D2 FF F4 E5 D3 FF D7 C9 C8 FF D1 C2 C2 FF D0 C0' - 'C0 FF CE BD BD FF CB B9 B9 FF C8 B5 B5 FF C3 B0' - 'B0 FF D6 C7 CA FF BF 94 78 FF 18 09 00 FF 00 00' - '00 F4 00 00 00 2C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00' - '00 A6 00 00 00 FF 11 08 02 FF A1 4F 12 FF FA 93' - '3F FF FF AC 61 FF FF A7 5D FF FF A7 5C FF FF A6' - '5C FF FF A6 5C FF FF A6 5C FF FF A7 5B FF FF A6' - '5B FF FF A4 57 FF FF A9 60 FF FF BA 7F FF FF C5' - '94 FF FF CB 9C FF FF CE A1 FF FF D1 A6 FF FF D4' - 'AC FF FF D8 B1 FF FF DC B7 FF FF DF BD FF FF E3' - 'C2 FF FF E5 C7 FF FF E8 CC FF FF EC D1 FF FF EE' - 'D6 FF FF F3 DB FF F6 EB D9 FF D3 C3 C3 FF CD BC' - 'BC FF CD BB BB FF CA B7 B7 FF C6 B3 B4 FF CB B9' - 'BC FF BD 92 7B FF 31 19 0B FF 00 00 00 FF 00 00' - '00 8D 00 00 00 03 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 05 00 00 00 A6 00 00 00 FF 16 0B 03 FF A6 54' - '16 FF FA 94 41 FF FF AB 61 FF FF A9 5F FF FF A8' - '5D FF FF A8 5E FF FF A8 5D FF FF A6 5B FF FF A7' - '5D FF FF B2 71 FF FF C2 8E FF FF C8 9A FF FF C9' - '9B FF FF CD A0 FF FF D0 A6 FF FF D4 AC FF FF D7' - 'B1 FF FF DB B7 FF FF DE BC FF FF E1 C1 FF FF E4' - 'C6 FF FF E7 CB FF FF EA D0 FF FF ED D4 FF FF EF' - 'D9 FF FF F2 DD FF FF F8 E3 FF EE E5 D9 FF D1 C1' - 'C0 FF CA B7 B8 FF C8 B5 B5 FF CA B7 B8 FF CB A8' - '9A FF 46 2D 1D FF 00 00 00 FF 00 00 00 C8 00 00' - '00 1F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 87 00 00 00 FF 0D 06' - '02 FF 92 4B 14 FF FD 96 41 FF FF AB 63 FF FF A9' - '60 FF FF A8 5F FF FF A6 5B FF FF AB 64 FF FF C1' - '8C FF FF CB A0 FF FF CC A0 FF FF CB 9F FF FF CD' - 'A2 FF FF D1 A8 FF FF D4 AD FF FF D7 B2 FF FF DA' - 'B8 FF FF DE BD FF FF E1 C2 FF FF E4 C7 FF FF E7' - 'CB FF FF E9 D0 FF FF EC D4 FF FF EF D8 FF FF F1' - 'DD FF FF F4 E1 FF FF F7 E5 FF FF FD EC FF F2 EA' - 'E0 FF CA B8 B6 FF C8 B6 B9 FF CD AD A1 FF 57 35' - '1B FF 00 00 00 FF 00 00 00 D6 00 00 00 18 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 75 00 00' - '00 FD 0C 06 02 FF 7E 42 11 FF F3 91 3F FF FF AC' - '63 FF FF A7 5D FF FF B5 77 FF FF C8 9A FF FF CF' - 'A7 FF FF CE A5 FF FF CF A6 FF FF CF A7 FF FF D1' - 'AA FF FF D4 AF FF FF D8 B4 FF FF DA B9 FF FF DD' - 'BE FF FF E0 C2 FF FF E3 C7 FF FF E6 CC FF FF E9' - 'D0 FF FF EB D4 FF FF EE D8 FF FF F0 DC FF FF F2' - 'E0 FF FF F5 E4 FF FF F8 E9 FF FF F9 EB FF FD F3' - 'E0 FF F3 EC E4 FF DB BD B0 FF 68 46 30 FF 00 00' - '00 FF 00 00 00 D1 00 00 00 32 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 78 00 00 00 F1 00 00 00 FF 7F 43 12 FF EF 90' - '40 FF FF BC 80 FF FF D0 A8 FF FF D3 AD FF FF D2' - 'AC FF FF D2 AD FF FF D3 AD FF FF D3 AE FF FF D5' - 'B1 FF FF D8 B5 FF FF DB BA FF FF DD BF FF FF E0' - 'C4 FF FF E3 C8 FF FF E6 CC FF FF E8 D1 FF FF EB' - 'D5 FF FF ED D8 FF FF EF DC FF FF F2 E0 FF FF F4' - 'E3 FF FF F7 E8 FF FE F5 E6 FF FC EF DC FF FD F7' - 'EA FF FF F0 DA FF 83 5C 3B FF 00 00 00 FF 00 00' - '00 EB 00 00 00 3F 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 54 00 00 00 FD 00 00 00 FF 66 3A' - '14 FF F4 B8 85 FF FF D9 B8 FF FF D6 B3 FF FF D5' - 'B3 FF FF D6 B4 FF FF D6 B5 FF FF D7 B5 FF FF D9' - 'B8 FF FF DC BC FF FF DF C1 FF FF E1 C5 FF FF E4' - 'C9 FF FF E7 CE FF FF E8 D1 FF FF EB D5 FF FF EE' - 'D9 FF FF F0 DD FF FF F1 E0 FF FF F4 E4 FF FF F6' - 'E8 FF FE F2 E1 FF FB EB D7 FF FF FD F6 FF FF F6' - 'E4 FF 9C 66 38 FF 03 00 00 FF 00 00 00 F5 00 00' - '00 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 45 00 00 00 E0 01 00' - '00 FF 78 47 1B FF F2 B5 7F FF FF DC BE FF FF DA' - 'BB FF FF DA BB FF FF DB BC FF FF DB BD FF FF DC' - 'BF FF FF DF C3 FF FF E2 C7 FF FF E4 CB FF FF E6' - 'CF FF FF E9 D4 FF FF EB D6 FF FF ED DA FF FF F0' - 'DE FF FF F2 E1 FF FF F3 E5 FF FF F4 E6 FF FC EE' - 'DB FF FD F1 E0 FF FF FC F5 FF FF F5 E3 FF A7 7A' - '51 FF 07 00 00 FF 00 00 00 F3 00 00 00 60 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 8B 00 00' - '00 FF 69 42 1C FF ED AC 6F FF EE BC 90 FF FF E2' - 'C7 FF FF DE C2 FF FF DE C2 FF FF DF C4 FF FF E0' - 'C5 FF FF E2 C9 FF FF E5 CD FF FF E7 D1 FF FF E9' - 'D4 FF FF EC D8 FF FF EE DB FF FF F0 DF FF FF F1' - 'E2 FF FF F4 E6 FF FE F3 E5 FF FC EB D9 FF FD F2' - 'E2 FF FF FC F4 FF FF FF FE FF CB 9A 6C FF 1A 09' - '00 FF 00 00 00 FF 00 00 00 7D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 02 00' - '00 FF AA 6B 2D FF FF FA EA FF F1 D6 BF FF EC B8' - '88 FF FF E1 C9 FF FF E3 CB FF FF E2 CA FF FF E3' - 'CB FF FF E5 CF FF FF E8 D3 FF FF EA D6 FF FF EC' - 'D9 FF FF ED DD FF FF EF E0 FF FF F2 E3 FF FF F4' - 'E6 FF FD F0 E0 FF FD EF DE FF FE F4 E8 FF FF FB' - 'F4 FF FF FF F7 FF DC B0 84 FF 29 17 09 FF 00 00' - '00 FF 00 00 00 94 00 00 00 0B 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 94 01 00' - '00 FF 51 30 0F FF DF B0 7F FF FF FB F0 FF EF D0' - 'B3 FF F0 C5 9D FF FD E4 CD FF FF E6 D1 FF FF E7' - 'D2 FF FF E8 D5 FF FF EB D9 FF FF ED DC FF FF EF' - 'DF FF FF F0 E2 FF FF F2 E5 FF FF F3 E6 FF FE F0' - 'E1 FF FE F0 E1 FF FE F6 ED FF FF FA F3 FF FF FF' - 'FC FF E5 C3 A0 FF 3B 20 06 FF 00 00 00 FF 00 00' - '00 B0 00 00 00 07 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 1F 00 00' - '00 CC 00 00 00 FF 35 1B 00 FF D4 99 5A FF FF FF' - 'FE FF EC C3 9B FF F4 CE AA FF FF ED DC FF FF EA' - 'D8 FF FF EC DB FF FF EE DF FF FF F0 E1 FF FF F1' - 'E4 FF FF F3 E7 FF FE F2 E6 FF FE EF E0 FF FE F3' - 'E7 FF FF F8 F0 FF FF FA F3 FF FF FF FF FF F3 CD' - 'A6 FF 52 2F 0D FF 00 00 00 FF 00 00 00 B8 00 00' - '00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1A 00 00 00 AE 00 00 00 FF 23 13 01 FF BF 8D' - '56 FF F3 B6 77 FF F6 D4 B6 FF FF F0 E3 FF FF ED' - 'DF FF FF EF E1 FF FF F1 E4 FF FF F3 E7 FF FF F3' - 'E9 FF FE F2 E5 FF FE F2 E6 FF FF F6 ED FF FF F9' - 'F2 FF FF F9 F4 FF FF FF FF FF FB DE BE FF 55 37' - '1A FF 00 00 00 FF 00 00 00 CB 00 00 00 1E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 04 00 00 00 A1 00 00 00 FF 11 07' - '00 FF B5 72 2D FF FF EB CF FF FF F4 EA FF FF F1' - 'E5 FF FF F2 E7 FF FF F4 EA FF FF F4 EB FF FE F3' - 'E9 FF FE F4 EA FF FF F8 F2 FF FF FA F5 FF FF FB' - 'F6 FF FF FF FF FF F7 E5 D0 FF 76 4D 25 FF 00 00' - '00 FF 00 00 00 DB 00 00 00 25 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00' - '00 FF 23 14 04 FF C7 99 68 FF FF FF F2 FF FF F8' - 'F1 FF FF F5 ED FF FE F6 ED FF FE F4 EC FF FE F8' - 'F1 FF FF FA F6 FF FF FB F6 FF FF FC F8 FF FF FF' - 'FF FF FF F4 DE FF 8C 61 34 FF 00 00 00 FF 00 00' - '00 EA 00 00 00 3B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00' - '00 BB 00 00 00 FF 28 17 05 FF C1 9C 74 FF FF F6' - 'E7 FF FF FB F8 FF FE F8 F1 FF FF FA F6 FF FF FC' - 'F8 FF FF FC FA FF FF FD FB FF FF FF FF FF FF FD' - 'F5 FF AA 82 56 FF 0E 05 00 FF 00 00 00 F9 00 00' - '00 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 04 00 00 00 A8 00 00 00 FF 06 00 00 FF AB 84' - '58 FF FF FA EB FF FF FF FF FF FF FE FD FF FF FF' - 'FD FF FF FF FF FF FF FF FF FF FF FF FC FF C9 9B' - '66 FF 0F 05 00 FF 00 00 00 FF 00 00 00 68 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0A 00 00 00 74 00 00 00 FF 0E 05' - '00 FF 79 5C 3A FF FF ED D6 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FE FF C9 A5 7A FF 19 0D' - '00 FF 00 00 00 FF 00 00 00 82 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 67 00 00' - '00 EE 00 00 00 FF 6E 4E 29 FF F0 DD C5 FF FF FF' - 'F4 FF FF F1 DC FF D1 AC 80 FF 36 1D 02 FF 00 00' - '00 FF 00 00 00 8F 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 3F 00 00 00 E0 00 00 00 FF 48 2F 12 FF 87 5D' - '2D FF 53 38 19 FF 12 0A 00 FF 00 00 00 FF 00 00' - '00 AD 00 00 00 08 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 26 00 00 00 BF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 EC 00 00 00 83 00 00' - '00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0A 00 00 00 75 00 00' - '00 84 00 00 00 60 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FC 3F FF FF 00 00 FF FF F8 1F FF FF 00 00 FF FF' - 'F0 0F FF FF 00 00 FF FF C0 07 FF FF 00 00 FF FF' - '80 03 FF FF 00 00 FF FF 00 01 FF FF 00 00 FF FC' - '00 00 FF FF 00 00 FF F8 00 00 7F FF 00 00 FF E0' - '00 00 3F FF 00 00 FF C0 00 00 1F FF 00 00 FF 80' - '00 00 0F FF 00 00 FE 00 00 00 0F FF 00 00 FC 00' - '00 00 03 FF 00 00 F8 00 00 00 03 FF 00 00 E0 00' - '00 00 01 FF 00 00 C0 00 00 00 00 FF 00 00 80 00' - '00 00 00 7F 00 00 00 00 00 00 00 3F 00 00 00 00' - '00 00 00 1F 00 00 00 00 00 00 00 07 00 00 00 00' - '00 00 00 07 00 00 00 00 00 00 00 03 00 00 C0 00' - '00 00 00 00 00 00 E0 00 00 00 00 00 00 00 F0 00' - '00 00 00 00 00 00 F0 00 00 00 00 00 00 00 F8 00' - '00 00 00 00 00 00 FC 00 00 00 00 01 00 00 FF 00' - '00 00 00 03 00 00 FF 00 00 00 00 07 00 00 FF C0' - '00 00 00 0F 00 00 FF E0 00 00 00 1F 00 00 FF F0' - '00 00 00 3F 00 00 FF F8 00 00 00 7F 00 00 FF F8' - '00 00 00 7F 00 00 FF F8 00 00 00 FF 00 00 FF F8' - '00 00 01 FF 00 00 FF FC 00 00 03 FF 00 00 FF FE' - '00 00 07 FF 00 00 FF FF 80 00 0F FF 00 00 FF FF' - '80 00 1F FF 00 00 FF FF C0 00 3F FF 00 00 FF FF' - 'E0 00 7F FF 00 00 FF FF F8 00 7F FF 00 00 FF FF' - 'FC 00 FF FF 00 00 FF FF FE 01 FF FF 00 00 FF FF' - 'FF 07 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0E 00 00 00 58 00 00' - '00 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 30 00 00 00 C1 09 00 00 FF 00 00' - '00 ED 00 00 00 59 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 61 00 00 00 E9 33 0D 00 FF 97 3E 19 FF 4D 1D' - '0A FF 00 00 00 F0 00 00 00 52 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 14 00 00 00 9A 02 00' - '00 FF 63 32 1D FF C6 78 55 FF F2 DA D2 FF CC A1' - '95 FF 44 17 07 FF 00 00 00 EB 00 00 00 4C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3B 00 00 00 CD 18 03 00 FF 9A 62' - '4A FF E0 9D 7D FF F1 DB D2 FF FF FF FF FF FD FD' - 'FE FF CA 9D 8F FF 3D 15 08 FF 00 00 00 E5 00 00' - '00 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 6F 00 00 00 F1 3B 15 09 FF CB 95 7B FF EE AA' - '83 FF E9 C8 B8 FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FD FC FE FF C8 9B 8D FF 39 14 07 FF 00 00' - '00 E2 00 00 00 3C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 03 00 00 00 80 00 00' - '00 FF 45 1B 0D FF E1 AC 91 FF FC BD 95 FF DB A5' - '8B FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FA F7 F9 FF B5 80 6E FF 1A 05' - '00 FF 00 00 00 CA 00 00 00 1E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1F 00 00 00 AC 07 00 00 FF 74 43' - '2F FF EF C3 A7 FF FC C4 9B FF DB A2 86 FF FA D0' - 'AF FF FF BE 87 FF FF FC FA FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF F4 EB EB FF A8 78' - '67 FF 16 05 00 FF 00 00 00 BB 00 00 00 1B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4A 00 00 00 DA 24 0A 00 FF AB 76 5E FF FF DE' - 'C1 FF FE CB A2 FF DC A0 80 FF F7 D7 BD FF FF 9D' - '49 FF FF 8E 31 FF FF BB 82 FF FF FB F8 FF FF FF' - 'FF FF FF FF FF FF FD FB FB FF FA FA FB FF F3 EA' - 'E9 FF A6 7B 6A FF 16 05 00 FF 00 00 00 B5 00 00' - '00 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 07 00 00 00 82 00 00' - '00 F9 50 28 15 FF D8 A9 8F FF FF E9 CE FF FE D1' - 'AA FF DE A2 81 FF F4 D5 C0 FF FF A6 58 FF FF 96' - '3E FF FF 98 44 FF FF 96 3E FF FF BD 85 FF FF FA' - 'F6 FF FE FF FF FF FA F8 F8 FF F6 F3 F3 FF F4 F2' - 'F3 FF F0 E4 E3 FF A5 74 5E FF 16 05 00 FF 00 00' - '00 B1 00 00 00 16 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 28 00 00 00 B8 0E 00 00 FF 86 55' - '3D FF F6 D3 BA FF FF EB D1 FF FE D9 B7 FF E2 A9' - '88 FF F1 D4 C1 FF FF B0 69 FF FF 98 40 FF FF 9C' - '49 FF FF 9C 48 FF FF 9D 4C FF FF A0 4E FF FF C1' - '89 FF FD F6 F1 FF F8 F9 FB FF F5 F0 F0 FF F1 EB' - 'EB FF EE EA EB FF ED E0 DD FF A6 74 5B FF 16 05' - '00 FF 00 00 00 B1 00 00 00 16 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4F 00 00 00 E2 30 13 04 FF BB 8B 70 FF FF ED' - 'D8 FF FF EB D1 FF FF E3 C7 FF E5 B0 8C FF ED CB' - 'B6 FF FF B9 7A FF FF 99 44 FF FF 9F 4D FF FF 9E' - '4D FF FF 9E 4C FF FF A0 4F FF FF A6 5A FF FF AA' - '5D FF FE C3 8D FF F7 EE E8 FF F2 F0 F2 FF EE E8' - 'E8 FF EB E3 E3 FF E8 E2 E3 FF EA DA D7 FF A7 72' - '56 FF 18 06 00 FF 00 00 00 B1 00 00 00 17 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 EA 53 27 0F FF E8 BF A3 FF FF F9 E7 FF FF EB' - 'D2 FF FF EF D8 FF EA BC 9B FF E7 BB 9E FF FF C0' - '86 FF FF 9C 47 FF FF A2 51 FF FF A1 51 FF FF A1' - '51 FF FF A1 50 FF FF A2 53 FF FF A9 5D FF FF B0' - '68 FF FF B3 6B FF FD C8 94 FF F1 EA E7 FF EC E8' - 'EA FF E9 E1 E1 FF E5 DC DB FF E2 DA DB FF E7 D4' - 'D0 FF A2 65 42 FF 08 00 00 FF 00 00 00 A8 00 00' - '00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 EB 5F 32 18 FF F9 D2 B3 FF FF F4 DE FF FF EF' - 'DA FF F4 D4 B9 FF E1 A8 82 FF FD C5 93 FF FF A1' - '50 FF FF A2 53 FF FF A3 54 FF FF A3 54 FF FF A3' - '53 FF FF A3 53 FF FF A3 55 FF FF AB 60 FF FF B2' - '6B FF FF B9 76 FF FF BE 7A FF FA D1 A8 FF EC E4' - 'E2 FF E7 DF E2 FF E4 DA DA FF DF D4 D4 FF DD D4' - 'D6 FF E2 C5 B9 FF 7D 4A 2C FF 01 00 00 FF 00 00' - '00 86 00 00 00 05 00 00 00 00 00 00 00 00 00 00' - '00 51 00 00 00 F3 5A 2F 15 FF F1 C8 A5 FF FC E5' - 'CD FF E1 A2 77 FF FB BB 85 FF FF A5 56 FF FF A3' - '53 FF FF A4 55 FF FF A4 55 FF FF A4 55 FF FF A3' - '55 FF FF A3 55 FF FF A4 57 FF FF AB 61 FF FF B3' - '6C FF FF BA 77 FF FF C0 81 FF FF C6 87 FF F9 D4' - 'AC FF E7 DC DA FF E1 D7 D9 FF DE D2 D2 FF DA CD' - 'CD FF D8 CD D0 FF E1 C4 B8 FF 7F 4F 31 FF 01 00' - '00 FF 00 00 00 83 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 48 00 00 00 EB 56 2F 16 FF E3 94' - '5B FF FB B5 79 FF FF A8 5C FF FF A3 55 FF FF A4' - '58 FF FF A4 56 FF FF A4 56 FF FF A4 56 FF FF A4' - '56 FF FF A4 56 FF FF A5 58 FF FF AB 62 FF FF B2' - '6B FF FF B9 76 FF FF C2 85 FF FF CD 97 FF FF D7' - 'A7 FF F8 DF C1 FF E2 D6 D4 FF DB CF D0 FF D9 CB' - 'CB FF D4 C5 C4 FF D3 C6 C8 FF E2 C5 B8 FF 80 51' - '31 FF 02 00 00 FE 00 00 00 79 00 00 00 06 00 00' - '00 00 00 00 00 00 00 00 00 4E 00 00 00 FF 7A 40' - '16 FF FB 9E 51 FF FF AA 5C FF FF A6 5A FF FF A5' - '59 FF FF A5 59 FF FF A5 58 FF FF A5 59 FF FF A5' - '59 FF FF A4 57 FF FF A4 57 FF FF AB 62 FF FF B8' - '76 FF FF C6 8F FF FF D2 A3 FF FF DA B1 FF FF E0' - 'BA FF FF E5 C1 FF F8 E5 CB FF DE D0 CD FF D4 C6' - 'C7 FF D3 C3 C3 FF CE BC BC FF CD BE C0 FF DE C0' - 'B3 FF 85 56 37 FF 06 01 00 FE 00 00 00 4C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 6B 00 00' - '00 FB 6D 37 0D FF F5 92 41 FF FF AC 5F FF FF A7' - '5C FF FF A6 5B FF FF A6 5B FF FF A6 5B FF FF A5' - '59 FF FF A5 58 FF FF AE 68 FF FF C0 87 FF FF CC' - '9D FF FF D3 A9 FF FF D8 B0 FF FF DD B8 FF FF E2' - 'C0 FF FF E7 C8 FF FF EE D0 FF F8 EA D5 FF DA CB' - 'C8 FF CF BE BF FF CD BB BB FF C8 B5 B5 FF D3 C0' - 'C1 FF 9B 77 61 FF 09 03 00 FF 00 00 00 4B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 5B 00 00 00 F7 5D 2F 0C FF F1 90 41 FF FF AD' - '62 FF FF A8 5E FF FF A7 5D FF FF A6 5A FF FF AB' - '64 FF FF BC 83 FF FF C8 98 FF FF CE A1 FF FF D2' - 'A8 FF FF D7 B0 FF FF DC B8 FF FF E1 C0 FF FF E5' - 'C8 FF FF EA CF FF FF EE D6 FF FF F4 DE FF F8 EF' - 'DE FF D6 C6 C4 FF C8 B6 B7 FF D0 BC BD FF A0 80' - '70 FF 10 09 04 FF 00 00 00 8E 00 00 00 04 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 6B 00 00 00 FF 70 3A 0F FF FB 9C' - '4B FF FF AE 64 FF FF A6 5B FF FF AE 6A FF FF C6' - '95 FF FF CD A3 FF FF CD A1 FF FF D1 A8 FF FF D6' - 'B0 FF FF DB B8 FF FF DF C0 FF FF E4 C6 FF FF E8' - 'CD FF FF EC D4 FF FF F0 DB FF FF F3 E1 FF FF FC' - 'EA FF F5 EC E0 FF D3 C2 C3 FF BF A0 95 FF 29 19' - '0C FF 00 00 00 C7 00 00 00 0B 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 69 00 00 00 FB 6F 3C' - '12 FF F7 9B 4C FF FF BC 7F FF FF CD A3 FF FF D1' - 'AB FF FF D0 AA FF FF D2 AC FF FF D6 B1 FF FF DB' - 'B9 FF FF DF C0 FF FF E3 C7 FF FF E7 CD FF FF EB' - 'D4 FF FF EF DA FF FF F3 E0 FF FF F6 E6 FF FE F5' - 'E5 FF FF FF EF FF E9 D0 BA FF 43 2D 20 FF 00 00' - '00 D9 00 00 00 25 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' - '00 F2 60 36 14 FF ED BA 8B FF FF DB B9 FF FF D7' - 'B4 FF FF D6 B5 FF FF D8 B7 FF FF DC BC FF FF E0' - 'C2 FF FF E4 C9 FF FF E8 CF FF FF EB D5 FF FF EF' - 'DB FF FF F2 E1 FF FF F4 E5 FF FE F2 E1 FF FF FA' - 'EE FF F9 EA D3 FF 5B 41 2A FF 00 00 00 E4 00 00' - '00 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4F 00 00 00 F9 A5 74 48 FF FB CF A6 FF FF DE' - 'C1 FF FF DD C0 FF FF DD C1 FF FF E1 C6 FF FF E5' - 'CD FF FF E8 D2 FF FF EC D7 FF FF EE DD FF FF F2' - 'E2 FF FF F3 E4 FF FE F0 DF FF FF F9 EF FF FF F3' - 'E2 FF 70 52 37 FF 00 00 00 F0 00 00 00 42 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 23 03 00 00 FD BF 97 6F FF FF EA D3 FF F4 CC' - 'A9 FF FF E3 CB FF FF E3 CC FF FF E6 CF FF FF EA' - 'D5 FF FF EC DA FF FF EF DF FF FF F2 E4 FF FE F2' - 'E3 FF FE F0 E1 FF FF FA F3 FF FF FA ED FF 83 65' - '48 FF 00 00 00 F6 00 00 00 52 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 12 00 00 00 CD 37 23 0E FF D6 B6 91 FF FD E7' - 'D0 FF F6 D3 B4 FF FF EB D9 FF FF EB D9 FF FF EE' - 'DE FF FF F0 E2 FF FF F2 E6 FF FF F1 E4 FF FE F3' - 'E6 FF FF FA F4 FF FF FE F4 FF 98 79 5A FF 01 00' - '00 FC 00 00 00 65 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1C 00 00 00 D4 24 13 01 FF D7 A8' - '74 FF FE D8 B5 FF FF F1 E5 FF FF EF E1 FF FF F2' - 'E6 FF FF F4 E9 FF FE F2 E5 FF FF F6 EC FF FF FA' - 'F4 FF FF FF FF FF BB 9C 7B FF 06 01 00 FF 00 00' - '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2A 00 00 00 D3 36 1F' - '07 FF EB C5 9C FF FF FF F6 FF FF F4 EA FF FF F5' - 'EB FF FF F4 EB FF FF F7 F0 FF FF FB F7 FF FF FF' - 'FF FF E0 C8 AD FF 29 1A 0B FF 00 00 00 B7 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00' - '00 DA 3E 2D 1A FF DE C5 A8 FF FF FF FD FF FF FA' - 'F5 FF FF FB F7 FF FF FD FB FF FF FF FF FF EC D9' - 'C2 FF 3A 27 14 FF 00 00 00 C7 00 00 00 16 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 22 00 00 00 C4 25 18 0A FF C6 B0 95 FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF F4 E5 D3 FF 4B 36' - '20 FF 00 00 00 D6 00 00 00 22 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 10 00 00 00 A6 12 09 01 FF AA 94' - '7A FF FF F6 EA FF F0 DE C8 FF 5E 46 2B FF 00 00' - '00 E3 00 00 00 2E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 84 05 01' - '00 FF 44 31 1A FF 26 19 0A FF 00 00 00 E1 00 00' - '00 3D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 54 00 00 00 84 00 00 00 67 00 00 00 1F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' - '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' - '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' - '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' - '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' - '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' - '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' - '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' - '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 10 00 00 00 8A 00 00 00 67 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 36 1E 0B' - '04 C9 9D 6B 56 FF 5D 3E 32 FE 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 69 4C 2F 21 EF CE 9D' - '87 FF FF FF FE FF F0 E3 DF FF 50 36 2D F9 00 00' - '00 5D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0A 00 00 00 90 71 4F 3D FF EE B2 90 FF FD D2' - 'B5 FF FF FF FD FF FF FF FF FF E8 D7 D1 FF 3C 27' - '1F F3 00 00 00 47 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 1A 0D' - '07 BF A6 83 6D FF FB CC AC FF F7 BA 8F FF FF 9A' - '44 FF FF C3 91 FF FF FD FC FF FF FF FF FF DC C7' - 'C1 FF 38 26 1D E9 00 00 00 40 00 00 00 00 00 00' - '00 00 00 00 00 00 02 01 00 5C 47 33 27 E8 D6 B9' - 'A1 FF FF E0 C2 FF F3 BF 98 FF FF A3 55 FF FF 9A' - '44 FF FF 9D 4A FF FF CB 9D FF F5 F2 F2 FF F6 F2' - 'F5 FF D5 BD B4 FF 39 24 19 E9 00 00 00 3E 00 00' - '00 00 00 00 00 00 29 16 0B F2 F3 D0 B4 FF FF F3' - 'DC FF EF BC 94 FF FE A9 60 FF FF 9F 4D FF FF A1' - '51 FF FF A5 57 FF FF B1 67 FF F9 D1 AA FF E9 E2' - 'E3 FF EA E2 E5 FF CA AB 9D FF 28 17 0D E2 00 00' - '00 2D 00 00 00 00 06 03 02 67 6D 53 3F FB F7 B8' - '88 FF FF AD 65 FF FF A3 52 FF FF A4 56 FF FF A3' - '54 FF FF A7 5A FF FF B5 6F FF FF C5 88 FF F5 D9' - 'BD FF DE D4 D4 FF DE D1 D3 FF BD 9F 92 FF 2D 1E' - '13 D8 00 00 00 2D 00 00 00 00 00 00 00 6E 76 43' - '1B FF FD A4 53 FF FF AA 5D FF FF A5 57 FF FF A4' - '56 FF FF B0 6C FF FF C6 91 FF FF D7 AE FF FF E4' - 'C0 FF F3 E2 D0 FF D3 C5 C5 FF D9 C7 C9 FF A5 85' - '75 FF 06 03 01 9C 00 00 00 00 00 00 00 00 00 00' - '00 6D 6E 3E 18 FF FF A6 58 FF FF AE 65 FF FF BD' - '85 FF FF CC A0 FF FF D7 B2 FF FF E0 C0 FF FF E9' - 'CE FF FF F3 DC FF F3 EA DF FF CB B4 AF FF 3C 30' - '2A EB 01 01 00 32 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 6F 71 43 1E F6 F7 C2 90 FF FF D8' - 'B5 FF FF D7 B4 FF FF DF C1 FF FF E7 CE FF FF EE' - 'DA FF FF F8 E8 FF FF F7 E4 FF 61 51 44 F8 00 00' - '00 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9F D0 AA 86 FF FF E6' - 'CA FF FF E1 C9 FF FF E8 D3 FF FF EE DD FF FF F4' - 'E7 FF FF FC ED FF 7C 6B 5A FD 00 00 00 64 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 43 53 43 32 F4 F3 D2' - 'B0 FF FF F1 E0 FF FF F0 E3 FF FF F4 E8 FF FF FF' - 'FB FF 98 86 75 FF 00 00 00 7D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 4E 59 47' - '34 F4 F5 EA D9 FF FF FF FC FF FF FF FF FF BA AC' - '9C FF 0C 07 03 A2 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 45 47 3C 31 E3 E3 DC D4 FF C9 BE B0 FF 16 10' - '09 B4 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2B 19 12 0A BB 0D 09 03 A0 00 00' - '00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' - '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' - '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' - '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' - '00 00 FE 1F 00 00' -} */ - -/* BINRES folder_open.ico */ -4 ICON folder_open.ico -/* { - '00 00 01 00 06 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 66 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 0E 09 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 76 0E 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 1E 34 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 C6 44 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 2E 49 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 B7 35 09 00 C4 3D 06 00 B5 44 16 00 B5 48' - '23 00 BE 50 2B 00 CE 48 0F 00 CC 4A 15 00 CB 53' - '1B 00 D4 58 1A 00 DC 66 1F 00 C5 53 26 00 D0 5A' - '22 00 D0 59 31 00 DE 69 20 00 DA 72 2B 00 CE 63' - '3C 00 D5 67 31 00 DF 6F 37 00 DC 72 30 00 E4 6C' - '24 00 EA 78 27 00 EB 6D 31 00 E8 75 36 00 F1 76' - '30 00 BB 6C 4F 00 C4 6D 55 00 C4 76 5D 00 CE 7D' - '5F 00 D2 74 50 00 D4 7A 5B 00 E6 72 41 00 C5 7F' - '6B 00 C8 7B 68 00 DB 7E 65 00 F8 8A 29 00 EF 88' - '35 00 F2 8A 34 00 FD 99 35 00 FC 9B 3B 00 FF A3' - '3A 00 BC 89 79 00 E9 88 46 00 E5 85 4B 00 F5 9A' - '44 00 FD 9D 45 00 F0 95 49 00 FA 9C 4D 00 EA 81' - '5B 00 FF A6 40 00 FF A9 45 00 F4 A0 49 00 FF AD' - '4E 00 FA A0 53 00 FE A9 53 00 FD A6 58 00 FA AA' - '5B 00 FF B2 55 00 FF B3 5C 00 C5 80 6C 00 CB 82' - '6C 00 D5 84 69 00 C3 85 77 00 CA 8B 77 00 D4 89' - '78 00 CD 90 7C 00 DA 9B 7E 00 EF 9D 65 00 ED 97' - '6F 00 F4 9E 63 00 F5 9C 6F 00 E3 8C 78 00 E0 9D' - '7E 00 E8 9A 7D 00 F0 9B 79 00 FA AF 65 00 F6 AB' - '6C 00 FD B2 62 00 FF BA 65 00 FE B6 6E 00 FF BF' - '6D 00 EC A1 76 00 EB A2 7A 00 F2 A6 75 00 F7 AC' - '70 00 F0 A3 7D 00 F5 AC 7F 00 FE B7 71 00 FC BC' - '72 00 F9 BA 7F 00 FE C4 78 00 92 8F 8D 00 91 90' - '8E 00 9F 93 8F 00 93 91 91 00 9B 96 94 00 9C 9B' - '9B 00 BC 8F 82 00 A1 93 8D 00 BC 92 85 00 B1 96' - '8A 00 A3 95 91 00 A5 98 94 00 A0 9E 9F 00 BC 9A' - '93 00 BE 9E 98 00 A8 A0 9C 00 B6 A1 9D 00 B9 A3' - '9F 00 A4 A2 A2 00 A9 A6 A6 00 AD AA A6 00 A9 A5' - 'A8 00 AE AB AC 00 B7 A7 A1 00 B9 A3 A0 00 B6 A8' - 'A3 00 BA AA A5 00 B3 AB AB 00 B5 B1 AD 00 B4 AE' - 'B0 00 BB B3 B7 00 C1 93 84 00 C2 93 89 00 CE 97' - '8B 00 C2 9A 8D 00 CF 99 8A 00 D6 98 87 00 C3 9F' - '92 00 CB 9D 92 00 DF 9D 90 00 E4 9A 88 00 C2 A1' - '97 00 CB A0 92 00 C3 A6 9C 00 C8 A4 99 00 DC A4' - '91 00 DB A9 91 00 D0 A3 99 00 E8 A7 80 00 EC AD' - '83 00 F0 AA 82 00 F3 AB 89 00 F0 B7 80 00 FF BF' - '85 00 F3 B2 8C 00 F8 B1 88 00 F5 BB 8C 00 F8 BE' - '8E 00 F1 AE 9A 00 EE B2 95 00 F7 B8 96 00 C1 AC' - 'A5 00 D7 AA A4 00 C4 B1 AD 00 D7 B0 A1 00 DA B5' - 'A6 00 DA B4 AA 00 D9 BB AF 00 C2 BC BD 00 D0 B3' - 'B2 00 DA BD B4 00 D0 BB BB 00 E0 B2 A5 00 EE BD' - 'A2 00 E3 B4 AA 00 E4 BB AF 00 F1 B6 A7 00 F6 BE' - 'A2 00 F0 BA AB 00 E5 BE B3 00 EC BC B0 00 E2 BF' - 'BB 00 FD C9 86 00 F4 C4 97 00 FF CB 95 00 FB C4' - '9C 00 FE CC 9D 00 FD D1 93 00 FE D5 9C 00 FE DB' - '9E 00 EC C5 AF 00 F4 C2 A5 00 FD CD A1 00 F5 C8' - 'AA 00 F9 CB AB 00 FD D4 A3 00 FF DE A4 00 FD D3' - 'AC 00 FD DB A9 00 E9 C2 B7 00 F1 C2 B5 00 F3 CA' - 'B3 00 FA D2 B3 00 FD DC B5 00 FB D6 BB 00 FB DC' - 'BC 00 FF E0 A5 00 FF E2 AE 00 FF E3 B2 00 FE E6' - 'BE 00 FF E8 BF 00 C3 BF C0 00 D0 C1 C1 00 DB C5' - 'C0 00 DD C6 CC 00 DF CA CB 00 DF CF D0 00 EB C5' - 'C0 00 EB CF CA 00 F9 CD C6 00 FC D3 C5 00 FC DC' - 'C5 00 F0 D3 CA 00 FF D7 CB 00 FA DD CA 00 E0 CF' - 'D0 00 E5 D7 DA 00 FA D8 D1 00 F0 DC D9 00 FE E4' - 'C1 00 FF E9 C3 00 FF EE CE 00 F0 E0 D4 00 FC E2' - 'D3 00 FF EE D0 00 F0 E1 DF 00 FD E5 DA 00 FE EB' - 'DC 00 FF F0 D5 00 FE F2 DD 00 ED DE E0 00 F0 DF' - 'E2 00 F1 E3 E3 00 FD E9 E5 00 F0 E7 EF 00 F1 EB' - 'EC 00 FE F5 E3 00 FF F3 EB 00 FF FA EE 00 F3 EE' - 'F0 00 FE F3 F2 00 FF FA F1 00 FF F7 FF 00 FF F9' - 'FC 00 7F 7F 7F 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 40 B4' - '0C 01 66 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 5F 5F 5F 5C 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 A5 99 98 76 70 60 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 7F 83 88 7E 68 74 71 67 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 65 47 A7 E3 A9 83 7E 68 75 71 6D 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 9D 8E 95 F4 F4 EA BF 82 7C 68 73 71 6D' - '5C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 9B B1 95 F4 F4 F3 F1 E9 D0 83 7F 7A 6B' - '76 6E 5E 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 89 BA 91 F1 F4 F3 F1 F1 EC E8 AB 83 41' - '63 69 76 70 5E 00 00 00 00 00 00 00 00 00 00 00' - '00 00 62 89 C5 93 E0 E3 F1 F1 F0 F0 EB E9 E2 AA' - '83 40 3E 68 6B 71 6D 00 00 00 00 00 00 00 00 00' - '00 00 BE B6 B4 93 B0 90 B7 C3 DF EC EB E9 E2 E7' - 'E7 AC 83 40 3E 7B 6C 71 70 5C 00 00 00 00 00 00' - '00 00 AB C1 C5 94 97 4F 36 37 8F C0 D5 DB E7 E7' - 'E7 D9 D8 AC 82 3D 20 63 6B 77 6D 00 00 00 00 00' - '00 00 95 C2 C7 B0 91 5A 4D 36 2C 2E 43 96 BE D1' - 'D9 D9 D8 CF CF A1 7E 3C 1B 69 CA 00 00 00 00 00' - '00 66 95 C2 C7 B7 8D AD 4E 3A 36 2C 24 18 2B 48' - 'A5 AC D8 CF CF CD CB A0 3D 3E 9F 60 00 00 00 00' - '00 9E C0 C4 C7 BD 55 B2 5A 4E 3A 36 2C 24 15 14' - '12 3D 88 9D CE CD CB A2 8A 20 9F 6D 00 00 00 00' - '00 9E D4 C8 C9 BD 4A BA AD 5A 4E 3A 34 2C 24 15' - '0E 0C 0C 1D 7F 99 A0 A2 A0 21 79 70 00 00 00 00' - '00 9C E1 DD C9 C2 8E BC AD AD 5A 4E 39 36 2C 25' - '15 0E 0C 08 07 10 3C 7B 8A 21 73 6E 00 00 00 00' - '5D A6 E5 DE DD C4 95 B9 B3 B2 AD 5A 4E 3A 36 2D' - '25 15 14 09 08 06 02 04 19 1A 63 6F 00 00 00 00' - 'D0 D3 E5 E1 DE DC B8 A8 B0 B0 AF AD 5A 4E 3A 39' - '32 26 25 15 0A 09 06 01 03 05 20 76 00 00 00 00' - 'D0 E0 E6 E5 E1 DE DD BC 97 97 B0 94 94 90 50 3A' - '34 32 31 26 23 14 09 01 08 0B 1A 76 00 00 00 00' - 'AB E4 E6 E6 E5 E1 DE DD C9 C2 B7 91 8E 97 AF 50' - '39 34 32 31 28 23 14 08 0C 0B 10 75 60 00 00 66' - 'BF ED ED ED E6 E5 E1 DE DD C9 C9 C7 BA 92 97 AD' - '50 39 34 32 31 26 18 17 0F 0C 0D 69 67 00 00 A1' - 'D6 EE F2 ED E6 E6 E5 E1 DE DD C9 C8 C7 B7 52 91' - '59 57 4D 39 32 27 16 2F 33 13 0D 61 6D 00 00 CC' - 'EA F2 F2 EF ED ED E6 E5 DE DE DD C9 C9 C7 B1 8D' - '8E 92 56 4C 38 35 1F 4B 4E 2E 11 3B 70 00 00 A1' - 'F1 F4 F2 F2 F2 ED E6 E6 E5 E1 DE DD C9 C8 C7 C6' - 'BA 94 52 51 53 46 30 54 58 4B 2A 1C 78 00 00 A1' - 'EA EA F1 EE F2 EF ED E6 D7 C3 C4 DC DC C9 C9 C7' - 'C7 C6 C5 B3 93 44 22 49 8E 53 45 1E 77 00 00 74' - '98 9D D2 DA E0 E3 E4 D4 A9 87 86 B5 C1 B9 C1 C2' - 'C7 C7 C7 C5 B4 8C 81 98 84 61 29 3F 00 00 00 00' - '00 5B 98 98 86 A5 A6 A3 98 00 00 72 86 80 86 A4' - 'B9 B7 BA BD BB 8B 9A 00 00 00 00 6A 00 00 00 00' - '00 00 00 00 00 66 5D 66 00 00 00 00 00 00 00 6B' - '7D 85 B6 B0 AE 42 76 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 9A 84 63 64 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FC 3F FF FF FC 0F FF FF FC 03 FF FF F8 00' - 'FF FF F8 00 1F FF F8 00 07 FF F8 00 01 FF F0 00' - '00 7F F0 00 00 0F F0 00 00 07 F0 00 00 07 E0 00' - '00 03 E0 00 00 03 E0 00 00 03 E0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 01 80 00' - '00 01 80 00 00 01 80 00 00 01 80 00 00 01 80 00' - '00 01 80 00 00 03 E0 18 00 7B FE 3F 80 7F FF FF' - 'F0 FF FF FF FF FF FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 B8 47 1D 00 C9 45' - '0E 00 CB 55 1F 00 D7 5F 1F 00 DE 65 1E 00 D0 59' - '28 00 CE 68 3F 00 E2 69 24 00 E7 77 27 00 EB 7B' - '2F 00 F0 7F 39 00 C7 6B 4E 00 DE 7A 45 00 C9 7B' - '60 00 F3 8B 32 00 FD 9C 35 00 BE 80 70 00 BF 91' - '7F 00 F0 96 46 00 F6 99 44 00 F7 99 44 00 E8 8D' - '51 00 ED 8A 5E 00 FD A4 44 00 FF AA 46 00 FF AA' - '49 00 F7 A2 52 00 FF B2 59 00 FF B5 59 00 FF B2' - '5D 00 FF B3 5E 00 C4 84 72 00 EF A1 6B 00 FF B4' - '62 00 FF B5 68 00 F2 A7 73 00 F8 B3 71 00 F8 B5' - '7E 00 FF C3 73 00 FF C5 7A 00 FF C7 7A 00 96 8A' - '85 00 96 90 8E 00 99 91 8E 00 92 91 90 00 96 95' - '94 00 9F 97 94 00 9A 98 97 00 9C 99 98 00 9E 9C' - '9C 00 A6 96 91 00 AD 9C 95 00 B6 9D 93 00 A6 A0' - '9F 00 BB A0 94 00 B7 A0 9B 00 B1 A2 9F 00 BB A0' - '9A 00 A6 A2 A3 00 AE A7 A5 00 AC A7 A8 00 B3 A3' - 'A3 00 BF AB A6 00 BF AE AB 00 B7 AF B0 00 C9 8E' - '82 00 C4 95 8B 00 C9 94 88 00 CD 9A 8E 00 D9 9C' - '85 00 C3 9C 95 00 C2 9E 95 00 CE 9D 91 00 D1 9F' - '94 00 CD A0 90 00 C6 AA 9F 00 DA A3 98 00 DF AA' - '98 00 DF A9 9A 00 DC AB 9F 00 EC B5 8D 00 F1 B2' - '83 00 F3 B3 8B 00 F5 B6 8A 00 F7 B5 8E 00 F7 B8' - '8A 00 EE AC 93 00 F6 BB 99 00 CF B3 A9 00 D9 B0' - 'A0 00 D1 B7 B1 00 D9 BD B2 00 E9 BC A3 00 E5 BE' - 'AF 00 EA BC A8 00 FD C3 8C 00 FF D1 8F 00 FE C7' - '92 00 F8 C3 98 00 F9 C2 9B 00 FC C1 99 00 FF C8' - '9B 00 FA CF 9C 00 FB D0 97 00 FD CD A3 00 F8 CE' - 'AE 00 FC D0 A1 00 F7 D0 AE 00 FF DD AC 00 F4 CB' - 'B0 00 F2 CA B5 00 FF DF B2 00 FF E2 AD 00 FE E0' - 'B3 00 FF E1 B3 00 FF E4 B6 00 FE E0 BA 00 D3 C0' - 'C2 00 DE C1 C1 00 DF C4 C3 00 EF CA C3 00 EA D0' - 'CF 00 F6 D7 CE 00 F6 DA CF 00 F3 DD CD 00 E0 D0' - 'D1 00 EE D6 D4 00 E3 D4 D8 00 FA DF DB 00 FB E2' - 'C7 00 FF E8 C0 00 FF E8 C1 00 FF ED CB 00 FF EC' - 'CC 00 FF ED CC 00 EF E0 DF 00 FB E2 D3 00 FF EB' - 'D2 00 FF F0 D5 00 FF F1 D6 00 FC E5 E0 00 FC E7' - 'E4 00 F0 E6 EA 00 F7 ED ED 00 FB EB EA 00 FF F4' - 'E0 00 FF F9 ED 00 FF FA F6 00 FF F6 FB 00 7F 7F' - '7F 00 F7 B8 96 00 C1 AC A5 00 D7 AA A4 00 C4 B1' - 'AD 00 D7 B0 A1 00 DA B5 A6 00 DA B4 AA 00 D9 BB' - 'AF 00 C2 BC BD 00 D0 B3 B2 00 DA BD B4 00 D0 BB' - 'BB 00 E0 B2 A5 00 EE BD A2 00 E3 B4 AA 00 E4 BB' - 'AF 00 F1 B6 A7 00 F6 BE A2 00 F0 BA AB 00 E5 BE' - 'B3 00 EC BC B0 00 E2 BF BB 00 FD C9 86 00 F4 C4' - '97 00 FF CB 95 00 FB C4 9C 00 FE CC 9D 00 FD D1' - '93 00 FE D5 9C 00 FE DB 9E 00 EC C5 AF 00 F4 C2' - 'A5 00 FD CD A1 00 F5 C8 AA 00 F9 CB AB 00 FD D4' - 'A3 00 FF DE A4 00 FD D3 AC 00 FD DB A9 00 E9 C2' - 'B7 00 F1 C2 B5 00 F3 CA B3 00 FA D2 B3 00 FD DC' - 'B5 00 FB D6 BB 00 FB DC BC 00 FF E0 A5 00 FF E2' - 'AE 00 FF E3 B2 00 FE E6 BE 00 FF E8 BF 00 C3 BF' - 'C0 00 D0 C1 C1 00 DB C5 C0 00 DD C6 CC 00 DF CA' - 'CB 00 DF CF D0 00 EB C5 C0 00 EB CF CA 00 F9 CD' - 'C6 00 FC D3 C5 00 FC DC C5 00 F0 D3 CA 00 FF D7' - 'CB 00 FA DD CA 00 E0 CF D0 00 E5 D7 DA 00 FA D8' - 'D1 00 F0 DC D9 00 FE E4 C1 00 FF E9 C3 00 FF EE' - 'CE 00 F0 E0 D4 00 FC E2 D3 00 FF EE D0 00 F0 E1' - 'DF 00 FD E5 DA 00 FE EB DC 00 FF F0 D5 00 FE F2' - 'DD 00 ED DE E0 00 F0 DF E2 00 F1 E3 E3 00 FD E9' - 'E5 00 F0 E7 EF 00 F1 EB EC 00 FE F5 E3 00 FF F3' - 'EB 00 FF FA EE 00 F3 EE F0 00 FE F3 F2 00 FF FA' - 'F1 00 FF F7 FF 00 FF F9 FC 00 7F 7F 7F 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 40 B4 0C 01 66 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 2F 31 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 45 4F 48 3D 2D 00 00' - '00 00 00 00 00 00 00 00 00 57 8E 81 50 47 3C 2E' - '00 00 00 00 00 00 00 00 00 63 8D 95 90 7F 4E 43' - '3E 30 00 00 00 00 00 00 59 67 65 66 7D 8F 88 7A' - '4D 42 38 3B 00 00 00 00 5A 6D 56 22 1B 21 5F 80' - '7E 78 4A 20 41 00 00 00 6F 74 54 29 1E 14 0A 0D' - '46 77 76 49 40 00 00 00 82 83 58 61 27 1C 15 09' - '04 06 0E 44 3A 00 00 5B 8A 87 6A 64 62 28 1F 18' - '0F 05 02 01 11 00 00 5C 92 8C 86 75 69 55 60 1D' - '19 10 08 03 0C 32 2B 7B 93 92 8C 87 84 70 53 26' - '23 1A 0B 13 07 36 2C 91 94 93 92 8B 85 84 72 6B' - '52 24 17 25 16 39 00 3F 79 7C 89 5E 4C 6E 6C 73' - '71 68 4B 35 12 2A 00 00 00 00 33 00 00 00 00 37' - '5D 51 34 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E7 FF 00 00 E0 FF 00 00 E0 3F' - '00 00 E0 0F 00 00 C0 03 00 00 C0 01 00 00 C0 01' - '00 00 C0 01 00 00 80 01 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 F7 87 00 00 FF FF' - '00 00 FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D5 C9' - 'BE 1C DC C8 BE 54 D4 C6 BE 54 CF C4 BF 54 CB C4' - 'BF 54 CF C7 C2 41 D2 CA C6 2E D6 CE C9 1B DA D3' - 'CD 0C D8 D2 C9 03 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DC C8' - 'BE 54 F0 C5 BC FF DA BF BE FF CA BA BF FF BF B8' - 'BF FF C9 C2 C9 C3 D4 CC D4 8A DF D8 DF 54 EA E7' - 'EA 26 E6 E2 DF 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D8 BE' - 'B4 54 E5 A7 9E FF DE 9C 90 FF D5 96 89 FF CA 95' - '89 FF C6 A1 9B EB C2 AE AD D8 BF BD BF C6 CA C9' - 'CA 96 D3 D0 D1 6B DA D2 D4 43 E1 DA DB 24 DE D7' - 'D4 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 B7' - 'AB 54 E0 91 84 FF E3 95 84 FF E3 9B 88 FF DF A2' - '8F FF D4 9B 8C FF C9 99 8E FF BF 9D 95 FF BF A9' - 'A3 DF C4 B8 B6 BD CF C9 CF 98 DA D4 DA 6C DA D5' - 'D6 47 D1 CC C4 27 D8 D1 CB 17 D8 D0 C9 0A 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 B2' - 'A4 54 E0 84 6F FF EA AB 9A FF F5 C9 BA FF FF DF' - 'D0 FF F4 AF 9A FF E9 8C 75 FF DF 78 5F FF C9 88' - '74 FF BA 9A 8F FF B0 AF B0 FF BA B9 BA DB C5 C4' - 'C5 AE D0 D0 D0 78 E4 DF E4 46 E5 DD DF 1E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 DF C7 BD 71 E7 B4' - 'A6 C6 EA 90 79 FF ED A1 8F FF F4 C1 B6 FF FF F2' - 'EF FF FB E2 DD FF F7 D2 CA FF F4 C1 B4 FF E6 AA' - '98 FF D6 98 84 FF C5 89 7A FF C1 94 8B F3 BD A4' - 'A1 E4 BA BA BA D1 C8 C3 C8 B1 CF C9 CD 89 D0 CD' - 'CA 5B D7 D4 D1 39 D8 D3 CD 1A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 C4 BA A9 F1 B9' - 'A8 FF F4 A9 8A FF F0 A0 8A FF F4 BC B0 FF FF FC' - 'FF FF FF FC FF FF FF F6 F8 FF FF EC EA FF F8 CE' - 'C3 FF EC B3 A2 FF DA 99 89 FF D2 96 89 FF C9 97' - '8D FF BF 9C 95 FF BF A3 9F EF C1 AF AD D5 C5 C1' - 'C0 B0 CF CC CD 8A D3 CF CF 60 D1 C9 C4 33 D4 CE' - 'C8 22 D5 CE C6 10 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 C2 B5 A9 F4 C3' - 'AA FF FF CD A0 FF F4 A9 8A FF F4 B8 AA FF FF FC' - 'FF FF FF FC FF FF FF FA FF FF FF F7 FF FF FF F3' - 'F5 FF FA EB EA FF F0 DF DF FF EF BD B4 FF E9 9B' - '89 FF DF 77 5F FF CA 7F 6A FF BA 8F 7F FF B0 A7' - 'A0 FF B9 B1 B4 F3 C4 BC C4 D2 CF C8 CF 9C DA D7' - 'DA 66 DB D8 D5 32 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 B8 A6 A9 F4 BA' - '9C FF FF D1 A0 FF F4 A7 83 FF F4 B5 A2 FF FF FC' - 'FF FF FF FC FF FF FF FA FF FF FF F7 FF FF FF F3' - 'F5 FF FD EE EE FF FA E9 EA FF F3 DE DC FF ED CF' - 'CA FF EA BC B4 FF E3 A9 9B FF DA 97 83 FF CF 87' - '6A FF C4 8B 78 FB BD 97 8F F0 BA AC AF DD C4 BC' - 'C0 CB CC C5 C9 A8 D0 C8 C9 73 D7 CF D0 50 D7 D0' - 'CD 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 AF 9C A9 F4 B4' - '93 FF FF D9 A5 FF F4 AB 81 FF F4 B5 9D FF FF F8' - 'FA FF FF F9 FD FF FF F9 FF FF FF F7 FF FF FF F3' - 'F5 FF FD F0 F0 FF FA EF F0 FF F3 EF F0 FF F0 EA' - 'EC FF F0 E1 E5 FF EF CA C4 FF EB B2 A3 FF E4 9A' - '7F FF D3 8F 78 FF C7 8C 7C FF BF 91 89 FF C2 9A' - '94 FE C4 A6 A4 EC C4 B4 B9 C9 CB C3 C8 A5 CE C9' - 'CA 77 CC C6 BF 3F D2 CB C6 2E D8 D0 CB 1C DB D3' - 'CF 0C D5 CD C4 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 AA 95 A9 F4 B2' - '90 FF FF E4 B0 FF F5 B6 85 FF F5 BA 9A FF FF F1' - 'F0 FF FF F5 FA FF FF F7 FF FF FF F7 FF FF FF F3' - 'F5 FF FA F0 F0 FF F0 EF F0 FF F0 EF F0 FF F0 EC' - 'EF FF F0 E7 EF FF F0 E3 E5 FF F0 E2 E0 FF F0 E2' - 'E0 FF E5 C0 B5 FF DF 9C 8A FF DF 77 5F FF D4 71' - '55 FF C4 79 64 FF B0 90 8F FF B0 A5 A4 FF B5 B5' - 'B5 EA C0 C0 C0 C0 D4 CF D4 8A E4 DC E4 56 EF E8' - 'EF 26 DB D4 CF 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 D8 C8 BE 38 E6 C6 BD A9 EC B6 A2 E2 F4 BE' - '9A FF FF E0 A5 FF F5 BA 88 FF F5 B6 90 FF FF D3' - 'BA FF FF D2 AF FF FF D9 BB FF FF E7 DF FF FF ED' - 'EA FF FA F0 F0 FF F0 EF F0 FF F0 EF F0 FF F0 EC' - 'EF FF F0 E7 EF FF F0 E3 E5 FF F0 E2 E0 FF F0 E2' - 'E0 FF EC D5 D1 FF E9 C8 C3 FF E9 BC B4 FF DF A8' - '9C FF D6 94 85 FF CF 80 6F FF C8 7F 6F FF C2 88' - '7B F8 BF 9A 94 E9 BF B0 B1 D8 C5 C1 C5 BC CF CC' - 'CF 98 D0 CD CC 6C D7 D3 D1 45 E5 DD DE 23 D8 D0' - 'C9 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DC C8 BE 54 F0 C5 BD FF F3 C0 AD FF F8 C9' - 'A3 FF FF DE A0 FF F5 BD 8A FF F5 B4 8A FF FF C3' - '9F FF FF BD 83 FF FF C0 84 FF FF CB A4 FF FF D2' - 'B3 FF FA D9 C3 FF F0 E1 D5 FF F0 EA E7 FF F0 EC' - 'EF FF F0 E7 EF FF F0 E3 E5 FF EF E1 E0 FF EF E1' - 'E0 FF EF DF E0 FF EF DF E0 FF EF DF E0 FF E5 CB' - 'CA FF DF B2 AC FF DF 95 84 FF D8 89 79 FF D0 84' - '76 FF C9 86 79 FF BF 8F 84 FF BC 9B 93 F5 BF A9' - 'A5 E0 C3 BA B7 BD CD C9 CA 97 DF D7 DF 6F D5 CF' - 'CD 45 D4 CF C8 25 DB D6 CF 0E D5 CE C4 04 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DC C9 BF 54 F0 C7 BF FF FA CA B5 FF FF D2' - 'AA FF FF DE A0 FF F5 BF 8A FF F5 B5 8A FF FF BF' - '9F FF FF B5 74 FF FF AD 59 FF FF A5 4F FF FF A1' - '4F FF FA AC 6A FF F0 C7 A0 FF F0 E1 D5 FF F0 EC' - 'EF FF F0 E7 EF FF F0 E3 E5 FF EF E1 E0 FF EF DF' - 'E0 FF EF DF E0 FF EF DF E0 FF EF DF E0 FF E5 D9' - 'DF FF E0 D4 DA FF E0 D0 D0 FF DF C4 C4 FF DF AB' - 'A4 FF E0 84 6F FF D5 6A 4F FF CA 68 4F FF BF 7F' - '70 FF B5 99 8F FF B5 AC AA F6 BF B8 BF E4 CA C7' - 'CA AE DA DA DA 70 F0 EF F0 2C DC D6 CF 0E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DB C3 B7 54 EF B5 A9 FF F9 D0 B4 FF FF DE' - 'B4 FF FF E2 AA FF FB C7 95 FF F8 BA 8E FF F5 B9' - '95 FF FB BD 7F FF FF B9 6B FF FF AD 59 FF FF A6' - '52 FF FA A4 54 FF F0 A7 60 FF F0 AC 71 FF F0 B5' - '88 FF F0 BF A5 FF F0 D0 C4 FF EF DA D8 FF EF DF' - 'E0 FF EF DF E0 FF EB DD DF FF E5 D9 DF FF E1 D7' - 'DF FF E0 D4 DA FF E0 D0 D0 FF DF CB CC FF DF C3' - 'C1 FF DF B5 AF FF DB A2 96 FF D4 92 81 FF CA 85' - '70 FF C7 7A 64 FF C3 7D 6A FC BF 8C 7F F6 C2 AA' - 'A6 E4 CF C6 C8 C0 E4 DF E4 8A D8 D1 CB 2E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DB BF B2 54 EF AB 9A FF F9 D2 B2 FF FF E5' - 'BA FF FF E4 B0 FF FF CE 9E FF FA BD 91 FF F0 B1' - '8A FF FA C1 83 FF FF C1 74 FF FF B3 5F FF FF AC' - '57 FF FB A4 4F FF F5 9B 44 FF F1 95 41 FF EF 96' - '4B FF EF 9D 65 FF EF AB 84 FF ED B8 9F FF EA C4' - 'B5 FF EA CD C6 FF E6 D3 D4 FF E0 D7 DF FF E0 D5' - 'DB FF E0 D3 D6 FF E0 CF D0 FF DF CF D0 FF DF CF' - 'D0 FF DF CF D0 FF DF C2 C1 FF DA B1 AA FF D0 9A' - '8A FF D0 85 74 FF CC 78 64 FF C4 74 5A FF C0 90' - '84 FF C7 B0 AF EB D9 D2 D9 C5 DB D5 D2 4C D8 D2' - 'C9 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DC BE AF 54 F0 A8 90 FF FA D2 AF FF FF E6' - 'BA FF FF E4 B0 FF FF D4 A4 FF FA BF 94 FF F0 A7' - '80 FF FA BF 80 FF FF C5 75 FF FF B8 60 FF FF B3' - '5F FF FF AD 59 FF FF A5 4F FF F5 9B 45 FF EF 8F' - '3A FF EF 80 30 FF EF 75 25 FF EA 7A 35 FF E0 90' - '60 FF E0 AA 94 FF E0 C2 BE FF E0 D7 DF FF E0 D2' - 'D5 FF E0 CF D0 FF E0 CF D0 FF DF CF D0 FF DF CF' - 'D0 FF DF CF D0 FF DF C9 CF FF DA C4 CA FF D0 C0' - 'C0 FF D0 BA BF FF D0 9F 9A FF D0 6F 50 FF C4 79' - '65 FF C4 97 8F F3 CF C8 CF DD E4 E2 E4 69 E6 E3' - 'DF 1F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E1 C7' - 'BD 71 EB C1 B4 C6 F0 B8 A4 FF FA D7 B6 FF FF E5' - 'BA FF FF E4 B0 FF FF DE AC FF FA CA 9C FF F0 A7' - '80 FF FA C7 8E FF FF CF 86 FF FF BD 69 FF FF B8' - '63 FF FF B2 5D FF FF AD 59 FF FB A4 4F FF F6 9A' - '44 FF EF 8F 3A FF EF 81 30 FF ED 7A 2E FF EA 7A' - '35 FF E2 7F 46 FF DF 87 5B FF DF 92 74 FF DF A6' - '94 FF DF BA B3 FF E0 CF D0 FF DF CF D0 FF DF CF' - 'D0 FF DF CF D0 FF DF C9 CF FF DA C4 CA FF D0 C0' - 'C0 FF D0 BD BF FF D0 AD A8 FF D0 8E 7A FF C5 7D' - '65 FF C1 8E 7E F9 C5 C2 C5 EF E1 E0 E1 79 E6 E2' - 'DF 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E7 C8' - 'BD A9 F3 C7 BA FF F5 C7 B4 FF FB DC BB FF FF E6' - 'BB FF FF E4 B5 FF FF E4 B1 FF F9 CD 9E FF EF 9F' - '7A FF F9 CA 97 FF FF D6 95 FF FF C4 74 FF FF BD' - '6A FF FF B8 63 FF FF B3 5F FF FF AC 57 FF FB A4' - '4F FF F5 9B 44 FF F1 8E 3A FF EF 81 30 FF EF 75' - '25 FF E4 6D 21 FF DF 6B 26 FF DF 6D 34 FF DB 7F' - '57 FF DA 92 78 FF DA A7 95 FF DA B1 A6 FF DB BC' - 'B8 FF DF C9 CA FF DF C7 CD FF DA C4 CA FF D0 C0' - 'C0 FF D0 BF C0 FF D0 B6 B3 FF D0 A4 9A FF C8 7C' - '65 FF C3 84 71 FD BF BD BF FB DF DC DF 88 E5 E1' - 'DF 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 CC' - 'BF A9 F5 D0 BF FF FF D7 BF FF FF E2 BF FF FF E7' - 'BF FF FF E6 BF FF FF E4 B5 FF F9 C7 9A FF EF 8F' - '70 FF F9 C7 9A FF FF DC A0 FF FF CC 80 FF FF C4' - '74 FF FF BD 6A FF FF B8 60 FF FF B3 5F FF FF AD' - '59 FF FF A5 4F FF F5 9B 45 FF EF 8F 3A FF EF 80' - '30 FF E5 75 25 FF DF 6D 1F FF DF 67 1F FF D5 5D' - '1F FF D0 57 1F FF D0 57 1F FF D0 74 54 FF D5 97' - '89 FF DF BF BF FF DF C4 C9 FF DA C4 CA FF D0 C0' - 'C0 FF D0 BF C0 FF D0 BA BA FF D0 B0 B0 FF D0 78' - '64 FF CA 7A 69 FF BF B7 BF FF DE D7 DE 95 E5 DE' - 'DF 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E5 C0' - 'B1 A9 F4 CA B5 FF FF E6 CA FF FF E7 C3 FF FF E7' - 'BF FF FF E7 BF FF FF E6 BB FF F9 CD A4 FF EF 9E' - '7A FF F9 CE A5 FF FF DD A7 FF FF CC 80 FF FF C9' - '7C FF FF C4 74 FF FF BD 69 FF FF B8 63 FF FF B2' - '5A FF FF AC 4F FF FB A4 4B FF F6 9A 44 FF EF 8F' - '3A FF EB 81 2F FF E6 76 26 FF DF 6D 1F FF DB 65' - '1F FF D6 5E 1F FF D0 57 1F FF CF 5D 2A FF D1 65' - '38 FF D4 6D 4A FF D4 82 69 FF D2 97 89 FF D0 AF' - 'AA FF D0 B9 B8 FF D0 BC BE FF D0 B8 BA FF D0 7B' - '68 FF C7 79 66 FF B5 B2 B5 FF D4 D2 D4 A1 DE DA' - 'D8 4C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E5 BB' - 'AA A9 F4 C7 B1 FF FF EF D5 FF FF EC CA FF FF E9' - 'C3 FF FF E8 C0 FF FF E7 BF FF FA D1 AB FF F0 A7' - '85 FF FA CE AC FF FF DB AC FF FF CE 85 FF FF CC' - '81 FF FF C9 7C FF FF C4 74 FF FF BD 6A FF FF B8' - '5F FF FF B2 55 FF FF AC 54 FF FB A4 4F FF F5 9B' - '44 FF F4 8E 39 FF EF 81 2F FF E5 75 24 FF E1 6D' - '21 FF DB 65 1F FF D5 5C 1F FF D1 55 18 FF CF 4E' - '13 FF CF 48 10 FF CF 58 2B FF CD 6C 4A FF CA 82' - '6A FF C7 91 83 FF C7 9E 96 FF CA A9 A4 FF CE 7C' - '68 FF C7 7B 68 FF B5 A7 A5 FF CE C9 C8 AD D7 D4' - 'D1 58 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 BB' - 'AA A9 F5 C9 B5 FF FF F3 DF FF FF F0 D4 FF FF EC' - 'CA FF FF E8 C0 FF FF E8 C0 FF FA D2 AF FF F0 A7' - '8F FF FA C6 AE FF FF D6 AF FF FF D4 90 FF FF CE' - '85 FF FF CC 80 FF FF CC 80 FF FF C4 74 FF FF BD' - '6A FF FF B8 60 FF FF B3 5F FF FF AD 59 FF FF A5' - '4F FF FF 9B 44 FF F9 8F 39 FF EF 80 2F FF E5 75' - '25 FF DF 6D 1F FF DF 67 1F FF D5 5D 1F FF CF 55' - '1A FF CF 4F 10 FF CF 48 10 FF CA 40 0A FF C0 38' - '00 FF B5 47 1F FF B5 60 45 FF C0 84 70 FF CA 7B' - '64 FF CA 81 6E FF BF 97 8F FF CA BC BA BA D0 CE' - 'CA 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 D9 C9 BE 38 E8 C7 BD A9 F4 C3' - 'B7 E2 FB D1 BF FF FF F1 D5 FF FF EF D1 FF FF ED' - 'CD FF FF EC C9 FF FF E9 C3 FF FA D6 B3 FF F0 B2' - '99 FF F3 BB A4 FF F8 C7 A8 FF FF D6 A5 FF FF D7' - 'A1 FF FF D5 98 FF FF CE 89 FF FF C7 7F FF FF C2' - '74 FF FF BD 69 FF FF B8 63 FF FF B2 5D FF FF AC' - '59 FF FF A8 4F FF FD A2 44 FF F9 99 3A FF F6 8D' - '2F FF F0 82 2A FF E9 77 29 FF DF 69 22 FF D6 5D' - '1D FF CF 54 19 FF CF 4E 13 FF CD 47 0E FF C9 40' - '0A FF B8 38 0E FF B1 3F 1A FF B5 56 30 FF C0 56' - '32 FF C3 68 4B FF BF 8A 7A FF CA B5 B2 C6 D6 D2' - 'D4 73 E5 E3 DF 07 D8 D2 C9 02 00 00 00 00 00 00' - '00 00 00 00 00 00 DC C9 C0 54 F2 C9 C2 FF FA CD' - 'C3 FF FF DA C9 FF FF F1 D5 FF FF EF D1 FF FF EE' - 'CF FF FF EE CF FF FF EB C8 FF FB DE BC FF F5 C7' - 'A9 FF F5 BE A3 FF F6 BE A0 FF FA C7 A0 FF F9 C7' - '9F FF FB C8 9B FF FF C9 94 FF FF CA 8D FF FF C9' - '84 FF FF C6 79 FF FF BE 6B FF FF B8 63 FF FF B3' - '5F FF FF B0 58 FF FF AD 4F FF FF A9 44 FF FF 9F' - '3A FF FB 95 35 FF F4 8C 34 FF ED 7D 2A FF E4 6F' - '22 FF DA 62 1F FF D6 59 18 FF D2 50 13 FF CF 48' - '10 FF B9 32 05 FF B1 30 06 FF B5 44 14 FF BC 46' - '1B FF C0 58 38 FF C0 7D 6A FF C6 AD AA D2 D6 D3' - 'D6 83 F0 EF F0 12 DC D6 CF 06 00 00 00 00 00 00' - '00 00 00 00 00 00 DC CB C4 54 F0 CF CF FF FA D9' - 'CF FF FF E5 D4 FF FF F3 DF FF FF F1 D5 FF FF EF' - 'D0 FF FF EE D0 FF FF EE CF FF FF EC CA FF FF E7' - 'C0 FF FF D0 AA FF FA BB 95 FF F0 A7 80 FF EF 9E' - '80 FF F4 A6 8A FF FF BF A0 FF FF CC A0 FF FF D4' - '9A FF FF D4 90 FF FF C6 7A FF FF BD 6A FF FF B8' - '60 FF FF B3 5F FF FF B0 59 FF FF AF 4F FF FF A9' - '45 FF FF A6 40 FF FF A6 40 FF FF 9A 35 FF FA 8A' - '2A FF F0 78 20 FF E4 67 1F FF D9 59 1A FF CF 4F' - '10 FF B9 34 05 FF B4 34 0A FF C0 4F 1F FF C0 49' - '1F FF C0 54 34 FF C0 6F 5F FF C0 A4 9F DF CF CF' - 'CF 95 F0 EF F0 23 DC D6 CF 0B 00 00 00 00 00 00' - '00 00 00 00 00 00 DC C8 BD 54 F0 C4 BA FF FA E0' - 'CF FF FF EF DB FF FF F3 DF FF FF F2 DB FF FF F1' - 'D6 FF FF EF D0 FF FF EE CF FF FF ED CD FF FF EC' - 'C9 FF FF E1 BC FF FD D8 B1 FF F9 D2 AA FF F9 C8' - 'A3 FF FB C2 9C FF FF BF 95 FF F7 AE 86 FF F4 A8' - '81 FF F4 AD 85 FF FB BC 8C FF FF C4 8A FF FF C7' - '7F FF FF BB 6A FF FF B3 5A FF FF AF 4F FF FF AD' - '4B FF FF AA 46 FF FF A6 40 FF FF A1 3C FF FD 9B' - '35 FF F9 91 2A FF F6 85 29 FF EB 72 24 FF D9 59' - '19 FF BD 3F 0F FF B8 3D 11 FF C9 54 1F FF C3 4F' - '1F FF C3 54 2D FF C9 65 4A FF C2 9D 98 EB CF CA' - 'CF A7 EF EA EF 32 DB D4 CF 11 00 00 00 00 00 00' - '00 00 00 00 00 00 DC C5 B9 54 F0 BD AF FF FA E3' - 'D3 FF FF F6 E3 FF FF F4 DF FF FF F3 DF FF FF F2' - 'DB FF FF F1 D5 FF FF EF D1 FF FF EE CF FF FF EE' - 'CF FF FF EB C8 FF FF E9 C3 FF FF E8 C0 FF FF E0' - 'B8 FF FF D7 AE FF FF CC 9F FF F7 B6 8D FF F4 AB' - '86 FF F4 AA 8A FF F7 B0 8E FF FB BC 93 FF FF CE' - '99 FF FF C3 7A FF FF BA 63 FF FF B2 55 FF FF B0' - '51 FF FF AD 4B FF FF A9 44 FF FF A7 41 FF FF A4' - '3C FF FF A1 35 FF FF 98 31 FF F6 85 2B FF E4 67' - '24 FF CC 50 1D FF C4 4B 1B FF CF 59 1F FF C8 54' - '1F FF C8 55 28 FF CF 5C 3A FF C1 97 8F F6 C9 C4' - 'C9 B7 EA E5 EA 42 DA D3 CD 16 00 00 00 00 00 00' - '00 00 00 00 00 00 DC C4 B9 54 F0 BA AF FF FA E4' - 'DA FF FF F8 EA FF FF F6 E0 FF FF F4 DF FF FF F3' - 'DF FF FF F3 DF FF FF F1 D5 FF FF EF D0 FF FF EE' - 'D0 FF FF EE CF FF FF EC CA FF FF E8 C0 FF FF E8' - 'C0 FF FF E7 BF FF FF E6 BF FF FF E4 B5 FF FF DC' - 'AA FF FF CD A0 FF F4 A3 7F FF F4 A3 84 FF FF CC' - 'B0 FF FF CC 90 FF FF C5 75 FF FF B8 60 FF FF B2' - '55 FF FF AF 4F FF FF AF 4F FF FF A9 45 FF FF A6' - '40 FF FF A6 40 FF FF A1 35 FF FA 92 2F FF F0 78' - '2F FF E4 68 2F FF D9 60 2A FF CF 60 20 FF CF 5A' - '1F FF CF 56 24 FF D0 54 2F FF BA 91 84 FF BF BF' - 'BF C5 E0 DF E0 52 D6 D1 CA 1B 00 00 00 00 00 00' - '00 00 E1 C8 BD 71 EE C7 BC C6 F9 C8 BA FF FD E9' - 'DE FF FF F9 EE FF FF F8 EA FF FF F6 E3 FF FF F4' - 'DF FF FF F3 DF FF FF F2 DB FF FF F1 D6 FF FF EF' - 'D0 FF FF EE CF FF FF ED CD FF FF EC C9 FF FF E9' - 'C3 FF FF E7 BF FF FF E7 BF FF FF E6 BB FF FF E2' - 'B4 FF FF DC AA FF FB C4 98 FF F4 B1 8C FF EA A3' - '85 FF F8 C3 97 FF FF CF 91 FF FF C5 75 FF FF BA' - '63 FF FF B3 56 FF FF AF 4F FF FF AD 4B FF FF AA' - '46 FF FF A6 40 FF FF A4 3C FF FA 93 36 FF F0 72' - '2F FF F2 81 3D FF EF 88 3F FF E4 84 35 FF D6 6A' - '26 FF CF 5A 24 FF D0 54 2F FF C1 86 76 FF C3 B1' - 'AD CB D5 D5 D5 64 D3 CD C6 21 00 00 00 00 00 00' - '00 00 E7 CA C1 AA F6 CE C5 FF FF D6 CA FF FF EE' - 'E3 FF FF FA F0 FF FF FA F0 FF FF F8 E8 FF FF F6' - 'E3 FF FF F4 DF FF FF F3 DF FF FF F2 DB FF FF F1' - 'D5 FF FF EF D1 FF FF EE CF FF FF EF CF FF FF EB' - 'C8 FF FF E9 C3 FF FF E8 C0 FF FF E7 BF FF FF E6' - 'BB FF FF E4 B5 FF FF DA AA FF F8 C2 97 FF EA 9F' - '7A FF F1 B1 8C FF F6 BB 8E FF F9 BB 80 FF FD B8' - '75 FF FF B6 6C FF FF B5 64 FF FF B4 5D FF FF B0' - '53 FF FF A9 45 FF FF A7 41 FF F8 92 3A FF EA 6A' - '2F FF F8 92 48 FF FB A5 51 FF F5 A1 4A FF E2 7E' - '35 FF D6 65 2B FF D0 57 2F FF C4 7D 68 FF C4 A4' - '9D D1 CF CD CF 77 D7 D3 CF 2C DB D6 CF 07 00 00' - '00 00 E6 D0 C9 AA F5 D9 D4 FF FF E4 DF FF FF F2' - 'EA FF FF FA F0 FF FF FA F0 FF FF FA F0 FF FF F8' - 'EA FF FF F6 E0 FF FF F4 DF FF FF F3 DF FF FF F3' - 'DF FF FF F1 D5 FF FF EF CF FF FF EF CF FF FF EF' - 'CF FF FF EC CA FF FF E8 C0 FF FF E8 C0 FF FF E7' - 'BF FF FF E6 BF FF FF E4 B5 FF FF D8 A5 FF FF C0' - '90 FF EA 96 70 FF E5 89 6A FF EF 9A 80 FF F9 AD' - '89 FF FF BA 8F FF FF C0 8F FF FF C0 7A FF FF BA' - '65 FF FF B0 50 FF FF A9 45 FF F4 8E 3A FF E0 60' - '2F FF F4 9A 4F FF FF B8 60 FF FF B8 60 FF F4 97' - '4A FF E4 79 39 FF D0 5F 2F FF C5 77 5A FF C5 9A' - '8F D8 CF C7 CF 8A E4 E2 E4 3C F0 F0 F0 16 00 00' - '00 00 E6 CA C2 AA F5 D6 D1 FF FF EC EA FF FF F6' - 'F4 FF FF FA F6 FF FF FA F0 FF FF FA F0 FF FF F9' - 'EE FF FF F8 EA FF FF F6 E3 FF FF F4 DF FF FF F3' - 'DF FF FF F2 DB FF FF F1 D6 FF FF EF CF FF FF EF' - 'CF FF FF EE CD FF FF EC C9 FF FF E9 C3 FF FF E7' - 'BF FF FF E7 BF FF FF E6 BB FF FF E0 B3 FF FF D7' - 'A5 FF F8 CA 9A FF F6 C0 95 FF F9 BB 94 FF F6 B3' - '89 FF F1 A7 7D FF EA 96 6F FF EA 96 68 FF ED 9B' - '65 FF F5 A4 65 FF FB A9 68 FF F8 9C 61 FF E9 7A' - '4F FF F7 AC 68 FF FF C2 71 FF FF BD 69 FF FB AB' - '5B FF EF 90 48 FF D9 6A 2F FF CF 72 4C FF C8 8F' - '7E DE C5 C1 C5 9B D4 CF CB 38 DC D6 CF 07 00 00' - '00 00 E6 C6 BB AA F5 D4 CD FF FF F4 F5 FF FF F9' - 'FB FF FF FB FB FF FF FA F5 FF FF FA F1 FF FF FA' - 'F0 FF FF FA F0 FF FF F8 E8 FF FF F6 E3 FF FF F4' - 'DF FF FF F3 DF FF FF F2 DB FF FF F1 D5 FF FF EF' - 'D1 FF FF EF CF FF FF EF CF FF FF EB C8 FF FF E9' - 'C3 FF FF E8 C0 FF FF E7 BF FF FF E6 BB FF FF E4' - 'B5 FF FF E4 B1 FF FF DE AC FF FF D3 A4 FF F8 C5' - '96 FF F1 B4 86 FF EA A0 75 FF EA 9E 75 FF EC 9F' - '75 FF F0 A4 74 FF F6 A3 74 FF F4 97 6B FF E9 7F' - '5A FF F4 A3 6C FF F9 B6 75 FF FA B9 74 FF FD B7' - '6D FF F7 A6 5D FF E9 87 44 FF D8 73 48 FF CB 87' - '73 EB C5 C1 C5 C2 CD C7 C1 41 00 00 00 00 00 00' - '00 00 E6 C3 B5 AA F5 D4 CA FF FF FC FF FF FF FC' - 'FF FF FF FC FF FF FF FC FF FF FF FA F5 FF FF FA' - 'F0 FF FF FA F0 FF FF FA F0 FF FF F8 EA FF FF F6' - 'E0 FF FF F4 DF FF FF F3 DF FF FF F3 DF FF FF F1' - 'D5 FF FF EF CF FF FF EF CF FF FF EF CF FF FF EC' - 'CA FF FF E8 C0 FF FF E8 BF FF FF E7 BF FF FF E6' - 'BF FF FF E4 B5 FF FF E4 B0 FF FF E4 B0 FF FF E4' - 'B0 FF FF E2 AA FF FF DE A0 FF FF D7 A0 FF FA C8' - '95 FF F0 B0 7F FF EF 95 6A FF E9 7F 5A FF DF 6F' - '4F FF E9 7F 5A FF EF 93 6A FF F0 AC 80 FF F9 B9' - '80 FF FF BD 7A FF FF B7 6F FF DF 7D 4F FF CF 82' - '6F FF CF C7 CF FF D0 C8 C4 55 00 00 00 00 00 00' - '00 00 EA CB C3 AA F6 D0 CA FF F5 D8 D4 FF F5 D5' - 'CD FF F8 D8 D1 FF FF E1 DF FF FF E8 E2 FF FF F0' - 'E8 FF FF FA F0 FF FF FA F0 FF FF F9 EE FF FF F8' - 'EA FF FF F4 E2 FF FB E3 D0 FF F5 C5 B4 FF F4 BD' - 'A9 FF F4 BD A8 FF F5 C4 AF FF FB D1 B6 FF FF DB' - 'BC FF FF E2 BF FF FF E6 BF FF FF E7 BF FF FF E7' - 'BF FF FF E6 BB FF FF E4 B6 FF FF E4 B0 FF FF E4' - 'B0 FF FF E3 AE FF FF E2 AA FF FF DD A3 FF FD D6' - '9C FF F9 CE 94 FF F3 AF 7F FF E6 98 76 FF D4 89' - '79 FF DF A4 93 FF E8 B0 9C FF EF AC 94 FF EC 99' - '78 FF EA 8D 65 FF EA 87 59 FF DF 69 41 FF D7 7F' - '64 C6 D0 C8 C4 55 D1 C9 C0 1C 00 00 00 00 00 00' - '00 00 E3 CE C6 71 EA CD C6 AA E6 C8 BF AA EC C0' - 'B4 BB F3 C2 B7 D7 FA CE C7 FF FA D4 CE FF FA DB' - 'D3 FF FA E2 D5 FF FA E4 D8 FF FB E7 DC FF FF EC' - 'E0 FF FB E2 D1 FF F6 D1 BF FF F0 B8 A9 FF E8 B1' - 'A2 C6 E5 B0 A2 AA E6 B7 A9 AA F3 C5 B1 E2 F9 CD' - 'B5 FF F9 D0 B4 FF F9 CE AE FF F9 D0 AE FF FA D6' - 'B4 FF FD D9 B4 FF FF DE B4 FF FF E4 B5 FF FF E4' - 'B1 FF FF E4 B0 FF FF E4 B0 FF FF E1 A8 FF FF DF' - 'A3 FF FF DE A0 FF F5 B9 86 FF E3 A3 82 FF CA 9C' - '94 FF D5 B9 B1 C6 DE C2 B8 AA E5 B6 A9 AA DE 9F' - '8D AA DB 91 7B AA DB 8D 74 AA E1 83 66 E2 DE 97' - '7F AA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 BF' - 'B4 33 F0 BC B2 88 F2 C2 B8 FF F0 C1 B8 FF F0 BC' - 'B0 FF F0 B4 A0 FF F0 B8 AA FF F5 C1 B4 FF FF D0' - 'C0 FF F5 BD AA FF F0 BC AA FF F0 CD C0 FF DC CB' - 'BF 55 00 00 00 00 00 00 00 00 E6 CC BF A9 EF C4' - 'B5 FF EF B4 A0 FF EF A2 8A FF EF A2 8A FF F0 B4' - 'A0 FF F9 BF A0 FF FF CF AA FF FF E6 BF FF FF E4' - 'B5 FF FF E4 B0 FF FF E4 B0 FF FF E4 B0 FF FF E2' - 'AA FF FF DE A0 FF F5 B4 80 FF E0 A1 7F FF C0 A7' - 'A0 FF CB BE B4 55 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 E5 CC BF A9 E6 CC' - 'BF AA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D8 C6' - 'BB 11 DC C5 BA 2D DC C7 BC 55 DC C7 BC 55 DC C5' - 'B9 55 DC C2 B4 55 E9 BC B0 A6 F1 BC B0 C1 F5 C1' - 'B4 A5 F1 BA AD C2 E8 BD B0 A7 DC CB BF 55 D5 CA' - 'BF 1C 00 00 00 00 00 00 00 00 D8 CA BF 38 DB C8' - 'BB 55 DB C2 B4 55 DB BC AD 55 DB BC AD 55 DC C2' - 'B4 55 EC BF AD C6 F4 BA A3 FF F4 B3 95 FF F4 B2' - '91 FF F4 B9 93 FF F5 C6 9A FF FB CF A1 FF FF D9' - 'A7 FF FF E2 AA FF ED A8 7C FF DC 9D 83 FF CA C1' - 'BF FF CF C7 BF 55 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 D8 CA BF 38 D8 CA' - 'BF 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 DF C2 B7 51 E6 BF B4 6C E6 BF' - 'B4 50 E5 BE B3 6D DE C2 B7 52 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 DF C2 B7 71 E5 B8 A9 AA E5 A9 94 AA E5 A9' - '94 AA EA B1 9A C6 F5 C0 A4 FF F8 C0 9E FF F8 C2' - '9A FF F4 C7 9A FF E6 9C 77 FF DA 9D 86 E2 D0 CD' - 'CA AA D1 CB C2 38 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 E0 CD C4 54 FF D4 CF FF F4 B6 A5 FF EA 9F' - '85 FF E0 8F 70 FF E0 8F 70 FF DB A2 8A AA 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 D7 CB C0 1C E1 CD C4 55 DD C3 B6 55 DA BB' - 'AB 55 D6 B6 A4 55 D6 B6 A4 55 D5 BC AD 38 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF 00' - '3F FF FF FF 00 00 FF 00 3F FF FF FF 00 00 FF 00' - '07 FF FF FF 00 00 FF 00 00 FF FF FF 00 00 FF 00' - '00 FF FF FF 00 00 FE 00 00 1F FF FF 00 00 FE 00' - '00 03 FF FF 00 00 FE 00 00 03 FF FF 00 00 FE 00' - '00 00 7F FF 00 00 FE 00 00 00 03 FF 00 00 FE 00' - '00 00 03 FF 00 00 F8 00 00 00 00 7F 00 00 F8 00' - '00 00 00 0F 00 00 F8 00 00 00 00 0F 00 00 F8 00' - '00 00 00 0F 00 00 F8 00 00 00 00 07 00 00 F8 00' - '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' - '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' - '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' - '00 00 00 07 00 00 C0 00 00 00 00 01 00 00 C0 00' - '00 00 00 01 00 00 C0 00 00 00 00 01 00 00 C0 00' - '00 00 00 01 00 00 C0 00 00 00 00 01 00 00 C0 00' - '00 00 00 01 00 00 80 00 00 00 00 01 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 01 00 00 80 00' - '00 00 00 01 00 00 80 00 00 00 00 01 00 00 80 00' - '00 00 00 07 00 00 F0 00 60 00 03 E7 00 00 F0 00' - '60 00 03 E7 00 00 FF C1 FF 80 03 FF 00 00 FF FF' - 'FF F8 0F FF 00 00 FF FF FF F8 0F FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' - '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 C5' - 'BC FF D0 BC BF FF BF B8 BF FF CF C7 CF A5 DF D8' - 'DF 54 F0 EF F0 0F 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 98' - '8F FF E0 84 6F FF D0 84 6F FF BF 98 90 FF B0 B0' - 'B0 FF C0 C0 C0 B7 DF D7 DF 66 EF E8 EF 1E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 84' - '6F FF F0 BF B0 FF FF DF D0 FF EF 97 80 FF DF 78' - '5F FF BF 90 80 FF B0 AF B0 FF C0 BF C0 C9 D0 D0' - 'D0 78 EF E7 EF 2D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F0 C4 BC FF EF 97' - '7F FF EF 9F 8F FF FF FC FF FF FF FC FF FF FF E7' - 'E0 FF F0 A7 8F FF D0 77 5F FF BF 88 7F FF B0 AF' - 'B0 FF BF B8 BF DB D0 CF D0 8A E0 E0 E0 3C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 EF BF B0 FF FF CD' - 'A0 FF EF 97 80 FF FF FC FF FF FF FC FF FF FF F7' - 'FF FF FF F1 F0 FF F0 DF DF FF EF AD 9F FF DF 77' - '5F FF C0 84 70 FF B0 A7 A0 FF BF B7 BF ED CF C8' - 'CF 9C E0 E0 E0 4B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 EF A7 90 FF FF D4' - 'A0 FF EF 8F 6F FF FF FC FF FF FF FC FF FF FF F7' - 'FF FF FF F1 F0 FF FF EF F0 FF F0 EF F0 FF F0 DF' - 'E0 FF EF AD 9F FF DF 77 50 FF C0 78 60 FF B0 9F' - '9F FF BF B7 BF FE CF C7 CF AE DF D8 DF 5D 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 EF 9A 80 FF FF E4' - 'B0 FF F0 9F 70 FF FF F1 F0 FF FF F7 FF FF FF F7' - 'FF FF FF F1 F0 FF F0 EF F0 FF F0 EF F0 FF F0 E7' - 'EF FF F0 E2 E0 FF F0 E2 E0 FF E0 AF A0 FF DF 77' - '5F FF CF 6F 50 FF B0 90 8F FF B0 B0 B0 FF C0 C0' - 'C0 C0 DF D7 DF 6F EF E8 EF 26 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 F0 C4 BC FF F0 B8 A0 FF FF DE' - 'A0 FF F0 AC 80 FF FF C5 A0 FF FF C0 80 FF FF DF' - 'CF FF FF F1 F0 FF F0 EF F0 FF F0 EF F0 FF F0 E7' - 'EF FF F0 E2 E0 FF F0 E2 E0 FF EF DF E0 FF EF DF' - 'E0 FF E0 B7 B0 FF DF 78 5F FF CF 67 4F FF BF 87' - '7F FF B0 AF B0 FF C0 BF C0 D2 D0 D0 D0 81 EF E7' - 'EF 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 F0 C7 BF FF FF CC B0 FF FF DE' - 'A0 FF F0 B0 80 FF FF BF 9F FF FF B1 5F FF FF A5' - '4F FF FF 9F 50 FF F0 C7 A0 FF F0 EF F0 FF F0 E7' - 'EF FF F0 E2 E0 FF EF DF E0 FF EF DF E0 FF EF DF' - 'E0 FF E0 D7 DF FF E0 D0 D0 FF DF BF BF FF E0 84' - '6F FF D0 5D 3F FF BF 7F 70 FF B0 A7 A0 FF BF B8' - 'BF E4 D0 D0 D0 93 F0 EF F0 2C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 EF AD 9F FF FF E6 BF FF FF E4' - 'B0 FF FF C0 90 FF F0 B7 90 FF FF C7 7F FF FF B1' - '5F FF FF A5 4F FF F0 97 40 FF F0 90 3F FF F0 AC' - '80 FF F0 D4 CF FF EF DF E0 FF EF DF E0 FF E0 D7' - 'DF FF E0 D7 DF FF E0 D0 D0 FF DF CF D0 FF DF CF' - 'D0 FF DF B7 B0 FF D0 88 70 FF D0 5D 3F FF BF 77' - '60 FF BF AF AF FF DF D8 DF BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 F0 A8 90 FF FF E8 C0 FF FF E4' - 'B0 FF FF CC 9F FF F0 A7 80 FF FF CC 80 FF FF B8' - '60 FF FF B1 5F FF FF A5 4F FF F0 97 40 FF EF 80' - '30 FF EF 70 20 FF E0 90 60 FF E0 B8 AF FF E0 D7' - 'DF FF E0 D0 D0 FF E0 CF D0 FF DF CF D0 FF DF CF' - 'D0 FF DF C7 CF FF D0 C0 C0 FF D0 B7 BF FF D0 6F' - '50 FF BF 7F 70 FF CF C8 CF DD F0 F0 F0 2F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F4 C5 BC FF F0 C0 AF FF FF E6 BF FF FF E4' - 'B0 FF FF E4 B0 FF F0 A7 80 FF FF DE A0 FF FF C0' - '6F FF FF B8 60 FF FF B1 5F FF FF A5 4F FF F0 97' - '40 FF EF 80 30 FF EF 70 20 FF DF 67 1F FF DF 70' - '3F FF DF A0 8F FF E0 CF D0 FF DF CF D0 FF DF CF' - 'D0 FF DF C7 CF FF D0 C0 C0 FF D0 BF C0 FF D0 9F' - '90 FF C0 6F 50 FF C0 C0 C0 F9 F0 EF F0 46 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F0 CD C0 FF FF D7 BF FF FF E8 C0 FF FF E6' - 'BF FF FF E4 B0 FF EF 8F 70 FF FF E4 B0 FF FF CC' - '80 FF FF C0 6F FF FF B8 60 FF FF B1 5F FF FF A5' - '4F FF F0 97 40 FF EF 80 30 FF E0 70 20 FF DF 67' - '1F FF D0 58 1F FF D0 57 1F FF D0 84 6F FF DF BF' - 'BF FF DF C7 CF FF D0 C0 C0 FF D0 BF C0 FF D0 B0' - 'B0 FF D0 5D 3F FF BF B7 BF FF EF E8 EF 60 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 EF B4 A0 FF FF EE D0 FF FF E8 C0 FF FF E8' - 'C0 FF FF E6 BF FF F0 A7 80 FF FF E8 C0 FF FF CC' - '80 FF FF CC 80 FF FF C0 6F FF FF B8 60 FF FF B0' - '50 FF FF A5 4F FF F0 97 40 FF EF 80 2F FF E0 70' - '20 FF DF 67 1F FF D0 58 1F FF CF 4F 10 FF CF 45' - '10 FF CF 6F 4F FF D0 A7 9F FF D0 BF C0 FF D0 BC' - 'BF FF D0 5D 3F FF B0 B0 B0 FF E0 DF E0 7C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F0 B4 A0 FF FF F3 DF FF FF EF CF FF FF E8' - 'C0 FF FF E8 C0 FF F0 A7 8F FF FF D7 BF FF FF D4' - '90 FF FF CC 80 FF FF CC 80 FF FF C0 6F FF FF B8' - '60 FF FF B1 5F FF FF A5 4F FF FF 97 3F FF EF 80' - '2F FF E0 70 20 FF DF 67 1F FF D0 58 1F FF CF 4F' - '10 FF CF 45 10 FF C0 38 00 FF B0 4F 30 FF C0 84' - '70 FF D0 77 5F FF BF 97 8F FF D0 D0 D0 98 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 F4 C6' - 'BC FF FF C8 BF FF FF F0 D0 FF FF EE D0 FF FF EF' - 'CF FF FF E8 C0 FF F0 B8 9F FF F0 B4 A0 FF FF D7' - 'B0 FF FF DF AF FF FF CF 8F FF FF C7 7F FF FF C0' - '6F FF FF B8 60 FF FF B1 5F FF FF AF 4F FF FF A6' - '40 FF FF 94 30 FF EF 80 2F FF DF 67 1F FF D0 58' - '1F FF CF 4F 10 FF CF 45 10 FF AF 27 00 FF B0 3F' - '10 FF C0 47 1F FF C0 84 70 FF CF C8 CF B3 F0 F0' - 'F0 0B 00 00 00 00 00 00 00 00 00 00 00 00 F0 CF' - 'CF FF FF DF CF FF FF F3 DF FF FF F0 D0 FF FF EE' - 'D0 FF FF EF CF FF FF E7 C0 FF FF C5 A0 FF F0 A7' - '80 FF EF 9A 80 FF FF BF A0 FF FF D4 A0 FF FF D4' - '90 FF FF C0 6F FF FF B8 60 FF FF B1 5F FF FF AF' - '4F FF FF A6 40 FF FF A6 40 FF FF 94 30 FF F0 78' - '20 FF DF 5F 1F FF CF 4F 10 FF AF 27 00 FF C0 4F' - '1F FF C0 47 1F FF C0 6F 5F FF C0 C0 C0 CF F0 EF' - 'F0 23 00 00 00 00 00 00 00 00 00 00 00 00 F0 BF' - 'B0 FF FF F6 E0 FF FF F3 DF FF FF F3 DF FF FF F0' - 'D0 FF FF EE D0 FF FF EF CF FF FF E8 C0 FF FF E8' - 'C0 FF FF D8 B0 FF FF C0 90 FF EF 8F 6F FF EF 9A' - '80 FF FF C5 A0 FF FF CF 8F FF FF B8 60 FF FF B0' - '50 FF FF AF 4F FF FF A6 40 FF FF A6 40 FF FF 9F' - '30 FF FF 8F 2F FF DF 5F 1F FF B0 37 10 FF CF 57' - '1F FF C0 4F 1F FF CF 60 40 FF BF B7 BF EB EF E8' - 'EF 3B 00 00 00 00 00 00 00 00 00 00 00 00 F0 BA' - 'AF FF FF FA F0 FF FF F6 E0 FF FF F3 DF FF FF F3' - 'DF FF FF F0 D0 FF FF EE D0 FF FF EF CF FF FF E8' - 'C0 FF FF E8 C0 FF FF E6 BF FF FF E4 B0 FF FF CD' - 'A0 FF EF 8F 6F FF FF CC B0 FF FF CC 80 FF FF B8' - '60 FF FF B0 50 FF FF AF 4F FF FF A6 40 FF FF A6' - '40 FF FF 9F 30 FF F0 78 2F FF DF 60 2F FF CF 60' - '20 FF CF 57 1F FF D0 54 2F FF B0 B0 B0 FF E0 DF' - 'E0 52 00 00 00 00 00 00 00 00 F4 C6 BC FF FF D0' - 'C0 FF FF FA F0 FF FF FA F0 FF FF F6 E0 FF FF F3' - 'DF FF FF F3 DF FF FF F0 D0 FF FF EE D0 FF FF EF' - 'CF FF FF E8 C0 FF FF E8 C0 FF FF E6 BF FF FF E4' - 'B0 FF FF CD A0 FF E0 8F 70 FF FF D8 B0 FF FF CC' - '80 FF FF B8 60 FF FF B0 50 FF FF AF 4F FF FF A6' - '40 FF FF A6 40 FF F0 6F 2F FF FF 9F 4F FF F0 97' - '40 FF CF 60 20 FF D0 54 2F FF BF 97 8F FF D0 D0' - 'D0 6E 00 00 00 00 00 00 00 00 F0 D4 CF FF FF E4' - 'DF FF FF FA F0 FF FF FA F0 FF FF FA F0 FF FF F6' - 'E0 FF FF F3 DF FF FF F3 DF FF FF F0 D0 FF FF EF' - 'CF FF FF EF CF FF FF E8 C0 FF FF E8 C0 FF FF E6' - 'BF FF FF E4 B0 FF FF C0 90 FF E0 82 60 FF EF 9A' - '80 FF FF B7 8F FF FF C0 8F FF FF C0 70 FF FF B0' - '50 FF FF A6 40 FF E0 60 2F FF FF B8 60 FF FF B8' - '60 FF EF 87 3F FF D0 5F 2F FF C0 84 70 FF CF C7' - 'CF 8A F0 F0 F0 16 00 00 00 00 F0 C7 BF FF FF F1' - 'F0 FF FF FC FF FF FF FA F0 FF FF FA F0 FF FF FA' - 'F0 FF FF F6 E0 FF FF F3 DF FF FF F3 DF FF FF F0' - 'D0 FF FF EF CF FF FF EF CF FF FF E8 C0 FF FF E8' - 'C0 FF FF E6 BF FF FF E4 B0 FF FF E4 B0 FF FF CC' - '9F FF F0 AC 7F FF E0 82 60 FF E0 82 60 FF F0 9F' - '70 FF FF B0 7F FF EF 88 60 FF FF CC 80 FF FF C0' - '6F FF FF B1 5F FF DF 70 30 FF CF 6F 50 FF C0 BF' - 'C0 A5 00 00 00 00 00 00 00 00 F0 C0 B0 FF FF FC' - 'FF FF FF FC FF FF FF FC FF FF FF FA F0 FF FF FA' - 'F0 FF FF FA F0 FF FF F6 E0 FF FF F3 DF FF FF F3' - 'DF FF FF F0 D0 FF FF EF CF FF FF EF CF FF FF E8' - 'C0 FF FF E8 BF FF FF E6 BF FF FF E4 B0 FF FF E4' - 'B0 FF FF E4 B0 FF FF DE A0 FF FF D4 A0 FF F0 B0' - '7F FF EF 88 60 FF DF 6F 4F FF EF 88 60 FF F0 AC' - '80 FF FF C0 80 FF FF B7 6F FF D0 60 40 FF CF C7' - 'CF FF 00 00 00 00 00 00 00 00 FA D3 D0 FF F0 C7' - 'BF FF F0 BF B0 FF FF D4 CF FF FF E4 DF FF FF FA' - 'F0 FF FF FA F0 FF FF FA F0 FF FF F3 DF FF F0 AF' - '9F FF EF 9F 8F FF F0 AF 9F FF FF CC B0 FF FF DF' - 'BF FF FF E8 C0 FF FF E8 BF FF FF E6 BF FF FF E4' - 'B0 FF FF E4 B0 FF FF E4 B0 FF FF DE A0 FF FF DE' - 'A0 FF F0 AC 7F FF CF 97 8F FF E0 C7 C0 FF EF AD' - '9F FF E0 78 60 FF E0 70 4F FF DF 58 30 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F0 BA AF 4D F2 C2 B8 FF F0 C1 B8 FF F0 B4' - 'A0 FF F0 BA AF FF FF D0 C0 FF F0 B4 A0 FF F0 CD' - 'C0 FF 00 00 00 00 00 00 00 00 F0 CD C0 FF EF B4' - 'A0 FF EF 9A 80 FF F0 B4 A0 FF FF C5 A0 FF FF E6' - 'BF FF FF E4 B0 FF FF E4 B0 FF FF E4 B0 FF FF DE' - 'A0 FF F0 9F 70 FF C0 A7 A0 FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F0 CD C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F0 BA AF B7 F0 BA AF 79 EF B9 AE B9 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F0 BA AF FF EF 9A' - '80 FF EF 9A 80 FF F0 B7 90 FF FF CD A0 FF FF E4' - 'B0 FF E0 82 60 FF D0 CF D0 FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF D4 CF FF EF A7 90 FF E0 8F' - '70 FF E0 8F 70 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FC 0F' - 'FF FF FC 03 FF FF FC 00 FF FF F8 00 3F FF F8 00' - '0F FF F8 00 03 FF F8 00 00 7F F0 00 00 1F F0 00' - '00 07 F0 00 00 07 F0 00 00 03 E0 00 00 03 E0 00' - '00 03 E0 00 00 03 E0 00 00 03 C0 00 00 01 C0 00' - '00 01 C0 00 00 01 C0 00 00 01 80 00 00 01 80 00' - '00 00 80 00 00 01 80 00 00 01 80 00 00 03 E0 18' - '00 7B FE 3F 80 7F FF FF F0 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 D7 C8 BE 01 DD C6 BD 57 CA C1' - 'BF 65 D8 D1 D0 27 DD D7 D1 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 D7 B8 AC 03 DF A0 92 D1 E0 AA' - '9B FD CA A2 98 E7 CC C3 C4 98 D6 D1 CF 38 DC D4' - 'D0 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E4 C3 B7 2A F2 AE 94 F8 FC E7' - 'E4 FF FA DF DB FF DD AC A0 FE C9 9F 97 ED C6 BB' - 'B8 AC D2 CC CA 49 D7 D1 CB 08 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E6 B1 9D 31 F9 C4 99 FD FC E5' - 'E0 FF FF F6 FB FF F7 ED ED FF EE D6 D4 FF DF AA' - '98 FF C8 96 8C F4 C5 B0 B0 BF CD C7 C5 59 DD D5' - 'D3 15 DE D7 D5 01 00 00 00 00 00 00 00 00 00 00' - '00 00 DB C8 BE 02 EA C5 B8 BF FA CF 9C FF FC C1' - '99 FF FF C8 9B FF F3 DD CD FF F0 E6 EA FF EF E0' - 'DF FF EA D0 CF FF DA A3 98 FF CC 8F 83 F8 C4 A8' - 'A2 D0 D3 CB CC 78 DC D8 D2 19 00 00 00 00 00 00' - '00 00 DB C0 B3 03 ED BC A8 D1 FF DD AC FF F7 B8' - '8A FF FF B4 62 FF F7 A2 52 FF EF A1 6B FF EA BC' - 'A8 FF E3 D4 D8 FF E0 D0 D1 FF DF C4 C3 FF D1 9F' - '94 FF C6 85 72 FB D6 CA CB A6 DC D6 D0 05 00 00' - '00 00 E6 C8 BD 2A F6 CD B7 F8 FF E4 B6 FF F5 B6' - '8A FF FF C7 7A FF FF B2 5D FF F6 99 44 FF EB 7B' - '2F FF DE 7A 45 FF D9 9C 85 FF DE C1 C1 FF D3 C0' - 'C2 FF CE 9D 91 FF CA B6 B3 DA E5 E0 DF 10 00 00' - '00 00 E6 BE AD 31 FC E3 C8 FD FF E8 C0 FF F6 BB' - '99 FF FF D1 8F FF FF C3 73 FF FF B2 59 FF F7 99' - '44 FF E7 77 27 FF D7 5F 1F FF D0 59 28 FF C9 7B' - '60 FF C9 94 88 FF C2 A4 9D E7 D7 D3 D1 19 DB C9' - 'C0 03 ED CB C2 BF FF EB D2 FF FF ED CC FF F8 CE' - 'AE FF F9 C2 9B FF FE C7 92 FF FF C5 7A FF FF B3' - '5E FF FD A4 44 FF F3 8B 32 FF DE 65 1E FF C9 45' - '0E FF B8 47 1D FF C2 81 70 F1 E1 DE DC 30 DC C6' - 'BA 04 EE CB BE D1 FF F4 E0 FF FF F1 D6 FF FF EC' - 'CC FF FE E0 BA FF FD CD A3 FF F7 B5 8E FF FD C3' - '8C FF FF B5 59 FF FF AA 46 FF FD 9C 35 FF E2 69' - '24 FF CB 55 1F FF C9 6B 4E FB DC D6 D7 56 E6 CB' - 'C2 3A FA DA D1 F8 FF F9 ED FF FF F4 E0 FF FF F1' - 'D6 FF FF ED CC FF FF E8 C1 FF FF DF B2 FF F3 B3' - '8B FF F8 B5 7E FF FF B5 68 FF FF AA 49 FF F0 7F' - '39 FF F0 96 46 FF CF 68 3F FE D0 C4 C2 7B E7 C8' - 'BD 40 FC EC EB FD FF FA F6 FF FF F9 ED FF FF F4' - 'E0 FF FF F0 D5 FF FF ED CB FF FF E8 C1 FF FE E0' - 'B3 FF FC D0 A1 FF F1 B2 83 FF F2 A7 73 FF ED 8A' - '5E FF F8 B3 71 FF E8 8D 51 FF CB B4 B0 AB E6 CD' - 'C5 25 EB C9 C1 98 F7 D0 C8 EE F8 DC D0 FC FC E3' - 'D4 FD F0 C5 B4 E8 EC C2 B1 A7 F7 CD B1 FA F9 D1' - 'AF FC FF E1 B3 FF FF E2 AD FF FB D0 97 FF D4 A3' - '92 EB DE B3 A3 94 E2 9B 80 A5 DD AC 9A 3F 00 00' - '00 00 D9 C5 BA 02 DE C6 BB 17 E0 C1 B6 2A EA BF' - 'B3 5D DF C4 B8 25 D9 CA BF 05 DD C1 B2 1A E1 C0' - 'B3 30 E8 B9 A5 93 F4 C3 A7 E8 EF B7 8E FA D4 B5' - 'A8 8B D0 C9 C1 01 D9 CA BF 05 D9 CA BF 05 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 DF CA BF 15 D8 B5 A2 1A D6 BA' - 'A9 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 FF' - '00 00 C0 7F 00 00 C0 1F 00 00 C0 03 00 00 80 01' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 FF C7 00 00 FF FF 00 00 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 7F 7F 7F 00 00 99' - '99 00 66 CC CC 00 99 CC FF 00 99 FF FF 00 F8 F8' - 'F8 00 00 00 00 00 E2 69 24 00 E7 77 27 00 EB 7B' - '2F 00 F0 7F 39 00 C7 6B 4E 00 DE 7A 45 00 C9 7B' - '60 00 F3 8B 32 00 FD 9C 35 00 BE 80 70 00 BF 91' - '7F 00 F0 96 46 00 F6 99 44 00 F7 99 44 00 E8 8D' - '51 00 ED 8A 5E 00 FD A4 44 00 FF AA 46 00 FF AA' - '49 00 F7 A2 52 00 FF B2 59 00 FF B5 59 00 FF B2' - '5D 00 FF B3 5E 00 C4 84 72 00 EF A1 6B 00 FF B4' - '62 00 FF B5 68 00 F2 A7 73 00 F8 B3 71 00 F8 B5' - '7E 00 FF C3 73 00 FF C5 7A 00 FF C7 7A 00 96 8A' - '85 00 96 90 8E 00 99 91 8E 00 92 91 90 00 96 95' - '94 00 9F 97 94 00 9A 98 97 00 3C 17 95 00 00 00' - '38 00 A8 44 F9 77 21 00 00 00 B8 0C 38 00 00 00' - '38 00 30 7E 0D 01 14 17 95 00 B1 A2 9F 00 5C 19' - '95 00 00 40 0D 01 68 19 95 00 77 82 F5 77 98 7F' - 'F5 77 3A 8A F5 77 00 04 00 00 C4 A2 AF 00 10 00' - '00 00 10 00 00 00 C9 94 88 00 CD 9A 8E 00 D9 9C' - '85 00 C3 9C 95 00 C2 9E 95 00 CE 9D 91 00 D1 9F' - '94 00 CD A0 90 00 C6 AA 9F 00 DA A3 98 00 DF AA' - '98 00 DF A9 9A 00 DC AB 9F 00 EC B5 8D 00 F1 B2' - '83 00 F3 B3 8B 00 F5 B6 8A 00 F7 B5 8E 00 F7 B8' - '8A 00 EE AC 93 00 F6 BB 99 00 CF B3 A9 00 D9 B0' - 'A0 00 D1 B7 B1 00 D9 BD B2 00 E9 BC A3 00 E5 BE' - 'AF 00 EA BC A8 00 FD C3 8C 00 FF D1 8F 00 FE C7' - '92 00 F8 C3 98 00 F9 C2 9B 00 FC C1 99 00 FF C8' - '9B 00 FA CF 9C 00 FB D0 97 00 FD CD A3 00 F8 CE' - 'AE 00 FC D0 A1 00 F7 D0 AE 00 FF DD AC 00 F4 CB' - 'B0 00 F2 CA B5 00 FF DF B2 00 FF E2 AD 00 FE E0' - 'B3 00 FF E1 B3 00 FF E4 B6 00 FE E0 BA 00 D3 C0' - 'C2 00 A8 01 38 00 10 44 0D 01 40 00 00 00 00 00' - '00 00 A8 01 38 00 38 44 0D 01 38 44 0D 01 E0 D0' - 'D1 00 EE D6 D4 00 E3 D4 D8 00 FA DF DB 00 FB E2' - 'C7 00 FF E8 C0 00 FF E8 C1 00 FF ED CB 00 FF EC' - 'CC 00 08 44 0D 01 08 44 0D 01 FB E2 D3 00 FF EB' - 'D2 00 FF F0 D5 00 FF F1 D6 00 FC E5 E0 00 FC E7' - 'E4 00 F0 E6 EA 00 00 40 0D 01 A4 18 95 00 E5 3A' - 'F8 77 06 00 00 00 08 44 0D 01 00 00 38 00 00 40' - '0D 01 00 00 00 00 78 19 95 00 CA 8C F5 77 78 01' - '38 00 BE 8E F5 77 08 06 38 00 37 90 F5 77 08 40' - '0D 01 08 40 0D 01 40 00 00 00 40 00 00 00 D0 BB' - 'BB 00 E0 B2 A5 00 EE BD A2 00 E3 B4 AA 00 E4 BB' - 'AF 00 F1 B6 A7 00 F6 BE A2 00 F0 BA AB 00 E5 BE' - 'B3 00 EC BC B0 00 00 40 0D 01 00 40 0D 01 F4 C4' - '97 00 78 01 38 00 08 40 0D 01 E0 07 0D 01 E8 07' - '0D 01 78 01 38 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 F5 C8 AA 00 00 40 0D 01 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 C2' - 'B7 00 08 04 00 00 87 00 00 00 08 04 00 00 08 01' - '00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00' - '38 00 BC 18 95 00 C0 18 95 00 B0 19 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 81 E9' - '49 00 00 00 38 00 00 00 00 00 08 40 0D 01 08 40' - '0D 01 A4 1A 95 00 40 00 00 00 40 00 00 00 B8 10' - 'E9 77 FF FF FF FF C9 F1 E7 77 16 EA 4B 00 F8 00' - '00 00 B4 1A 95 00 DC E3 49 00 E0 A3 4E 00 FF FF' - 'FF FF 10 00 00 00 10 DA 4B 00 08 40 0D 01 71 CC' - '43 00 08 40 0D 01 30 7E 0D 01 A4 1A 95 00 C4 A2' - 'AF 00 C4 F5 AF 00 02 00 00 00 30 7E 0D 01 0F 02' - '00 00 48 40 0D 01 10 00 00 00 00 00 00 00 20 00' - '00 00 08 40 0D 01 40 00 00 00 10 00 00 00 00 01' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 10 00 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 00 00 02 02 02 02 02 02 02 02' - '02 02 02 02 07 07 00 00 02 06 04 05 04 05 04 04' - '04 04 03 02 07 07 00 02 06 05 05 04 05 04 05 04' - '04 04 03 07 02 07 00 02 06 05 05 05 05 05 04 05' - '04 04 02 07 02 07 02 06 05 05 05 05 04 05 05 04' - '05 03 07 03 03 07 02 06 05 05 05 05 05 05 04 05' - '04 03 07 03 03 07 02 02 02 02 02 02 02 02 02 02' - '02 02 03 05 03 07 00 02 06 05 05 05 05 05 05 05' - '05 05 05 05 03 07 00 02 06 05 05 05 05 05 05 05' - '06 06 06 06 03 07 00 02 06 05 05 05 05 05 06 02' - '02 02 02 02 02 00 00 00 02 06 06 06 06 06 02 00' - '00 00 00 00 00 00 00 00 00 02 02 02 02 02 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 FF FF 00 00 E0 00' - '00 00 C0 00 00 00 C0 00 00 00 80 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 00 00 00 80 01 00 00 C0 7F 00 00 E0 FF' - '00 00 FF FF 00 00' -} */ - -/* BINRES floppy.ico */ -5 ICON floppy.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 A6 0E 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 CE 0F 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 01 01 00 02 02 02 00 04 04 04 00 05 05' - '05 00 07 07 07 00 09 09 09 00 0A 0A 0A 00 0C 0C' - '0C 00 0D 0D 0D 00 10 10 10 00 12 12 12 00 13 13' - '13 00 15 15 15 00 16 16 16 00 17 17 17 00 18 18' - '18 00 19 19 19 00 1B 1B 1B 00 1C 1C 1C 00 1E 1E' - '1E 00 1F 1F 1F 00 20 20 20 00 21 21 21 00 23 23' - '23 00 24 24 24 00 25 25 25 00 26 26 26 00 27 27' - '27 00 28 28 24 00 2A 2A 25 00 28 28 28 00 2A 2A' - '2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E 2E 00 32 32' - '32 00 33 33 33 00 34 34 34 00 35 35 35 00 37 37' - '37 00 3B 3B 3B 00 3C 3C 3C 00 3D 3D 3D 00 3F 3F' - '3F 00 40 40 40 00 44 44 44 00 45 45 45 00 46 46' - '46 00 47 47 47 00 48 48 48 00 49 49 49 00 4B 4B' - '4B 00 4C 4C 4C 00 4E 4E 4E 00 50 50 50 00 52 52' - '52 00 57 57 57 00 59 59 59 00 5E 5E 5E 00 61 61' - '61 00 64 64 64 00 65 65 65 00 6A 6A 6A 00 7F 60' - '60 00 71 71 71 00 77 77 77 00 79 79 79 00 7F 7F' - '7F 00 D5 40 40 00 00 C0 00 00 00 FF 00 00 87 80' - '7D 00 8B 86 84 00 8A 8A 8A 00 8C 8C 8C 00 8D 8D' - '8D 00 8E 8E 8E 00 97 97 97 00 99 99 99 00 9A 9A' - '9A 00 9E 9E 9E 00 A3 A3 9E 00 A4 A4 A4 00 A7 A7' - 'A7 00 AA AA AA 00 AB AB AB 00 AD A8 AB 00 AE AE' - 'AE 00 AF AF AF 00 B0 B0 B0 00 B2 B2 B2 00 B5 B5' - 'B5 00 B6 B6 B6 00 B7 B7 B7 00 BB BB BB 00 BC BC' - 'BC 00 BD BD BD 00 BF BF BF 00 EA 80 80 00 CA A8' - '94 00 CC AF 9D 00 E9 B6 99 00 E9 B8 9C 00 CE B6' - 'A6 00 D0 B3 A3 00 EB BE A5 00 D2 C3 B9 00 EC C0' - 'A7 00 EF CC B8 00 C2 C2 C2 00 C4 C4 C4 00 C5 C5' - 'C5 00 C6 C6 C6 00 C8 C9 C9 00 C9 C9 C9 00 CA CA' - 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CF CF' - 'CF 00 D5 CB C4 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' - 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' - 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' - 'D8 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' - 'DE 00 DF DF DF 00 F1 D2 C2 00 F2 D6 C7 00 F4 DD' - 'D0 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3' - 'E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7' - 'E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' - 'EB 00 EC EC EC 00 ED ED ED 00 F0 F0 F0 00 F2 F2' - 'F2 00 F3 F3 F3 00 F9 F9 F9 00 FA FA FA 00 FF FF' - 'FF 00 00 00 00 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' - '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 66 6C 6F 70 70 79 2E 69 63' - '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 2A 2A 2A 2A 40 40 40 40 40 40 40 40 40 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4B 4B 4B 4B A1 A1 A1 A1 A1 A1 A1 A1 A1 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1D 00 4B 08 45 45 45 45 45 45 45 45 45 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1E A1 A1 08 63 63 63 63 63 63 63 63 63 00 A1' - 'A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' - 'A1 03 08 0A 10 9A 94 94 94 94 94 94 94 94 00 A1' - 'A1 17 22 22 21 21 21 21 21 21 21 20 20 20 20 20' - '20 08 08 10 0F 99 94 4F 4F 4F 4F 4F 4F 4F A1 01' - '4A 98 95 95 7E 46 94 95 90 82 7C 77 77 77 72 55' - '23 A1 A1 15 10 97 93 95 95 97 97 98 98 99 A1 11' - '57 98 95 95 47 47 46 89 7F 7C 75 77 77 77 77 2D' - '23 A1 A1 0D 0C 96 94 4F 4F 4F 4F 4F 4F 4F A1 1F' - '7B 98 98 95 95 47 5C 5D 29 29 29 29 29 29 29 5D' - '5D A1 A1 07 09 95 94 90 90 91 91 93 93 94 A1 1F' - '7B 95 98 95 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' - 'A1 19 15 05 07 92 94 4F 4F 4F 4F 4F 4F 4F A1 1C' - '7C 97 98 98 54 56 58 59 59 59 59 56 56 56 56 56' - '56 24 08 A1 A1 92 92 94 94 96 96 97 97 98 A1 1B' - '7D 98 9A 96 95 91 8F 86 82 7C 7C 7A 7A 7A 7A 7A' - '7A 28 02 03 03 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 19' - '80 96 8E 8F 8D 89 89 89 8D 8D 8D 8D 8D 8D 8D 8D' - '8D 2C 09 0B 0E 17 1B 2A 2E 30 30 22 22 22 A1 19' - '88 83 6F 62 82 83 83 83 83 83 83 83 83 83 83 83' - '83 2E 18 12 16 21 27 2E 31 30 30 22 22 22 A1 04' - '6E 60 5B 56 5F 7F 7F 7E 7D 7F 81 82 81 7D 7D 7E' - '7F 34 35 23 25 2F 2E 34 34 2A 24 1A 13 0E 00 A1' - '53 78 70 62 73 7C 7A 7A 7A 7F 7F 7F 7F 7F 7A 7E' - '7A 38 39 27 2C 4B 4B 4B 4B 4B 4B 4B 4B 4B 00 A1' - '3A 7A 77 77 74 7D 7D 7E 7F 80 80 80 80 80 7F 85' - '91 3B 3B 3F 2E 4D A0 49 48 69 6C 66 66 66 00 A1' - '2D 7C 74 74 7E 7D 7D 7C 7C 7C 7C 7D 7C 7D 7C 7B' - '7A 3B 3B 3F 2E 4D A0 49 48 69 6C 66 66 66 00 A1' - '05 87 76 7D 7D 7A 7A 7A 7A 7D 7D 7D 7D 7D 7D 7D' - '7D 3E 3F 41 43 51 A0 38 36 8B 6D 67 66 66 00 A1' - 'A1 87 78 7D 7D 7A 7A 7A 7A 7A 78 7D 7D 7D 7D 7D' - '7D 2A 3F 41 43 55 A0 37 35 8C 8A 6A 66 66 00 A1' - 'A1 82 7E 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D' - '7D A1 A1 A1 A1 52 84 84 84 79 6B 68 65 64 00 A1' - 'A1 76 80 7D 7D 80 80 80 80 80 80 80 7D 7D 7D 76' - '73 6F 6E 61 7A 06 A1 00 00 00 00 00 00 00 00 A1' - 'A1 4E 86 86 88 88 87 87 87 87 87 87 87 87 87 87' - '87 94 94 86 71 A1 A1 00 00 00 00 00 00 00 00 00' - 'A1 42 7D 8E 88 88 88 8D 8D 8D 8D 8D 8D 8D 8D 8E' - '8E 94 94 83 5F A1 A1 00 00 00 00 00 00 00 00 00' - 'A1 27 61 93 93 94 98 98 98 98 98 98 98 98 98 94' - '94 94 93 7E 50 A1 A1 00 00 00 00 00 00 00 00 00' - 'A1 14 56 9A 94 99 98 9A 98 98 98 98 98 98 98 98' - '99 92 98 80 4A A1 A1 00 00 00 00 00 00 00 00 00' - '00 A1 4C 6F 5B 5B 98 9B 9B 9B 9B 9B 9B 9B 9B 9D' - '7F 5D 5E 77 3C A1 A1 00 00 00 00 00 00 00 00 00' - '00 A1 3D 87 86 91 9E 9E 9E 9E 9E 9E 9E 9E 9E 9F' - '9C 82 86 5A 26 A1 00 00 00 00 00 00 00 00 00 00' - '00 A1 A1 2B 33 32 32 32 32 32 32 32 32 32 32 32' - '32 33 33 02 A1 00 00 00 00 00 00 00 00 00 00 00' - '00 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' - 'A1 A1 A1 A1 A1 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF E0 00 FF FF E0 00 FF FF E8 00 FF FF' - 'E0 00 80 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 7F 80 00 00 7F C0 00' - '00 7F C0 00 00 7F C0 00 00 7F E0 00 00 7F E0 00' - '00 FF E0 00 01 FF E0 00 01 FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 01 00 00 01 01' - '01 00 03 06 04 00 05 05 05 00 09 09 09 00 0A 0C' - '0C 00 08 0D 0F 00 13 13 13 00 15 15 15 00 16 16' - '15 00 17 17 17 00 18 18 18 00 19 19 19 00 1D 1D' - '1D 00 1E 1E 1E 00 31 0A 0B 00 1A 1E 20 00 35 19' - '35 00 21 21 21 00 29 23 23 00 30 2A 30 00 31 31' - '31 00 32 33 33 00 34 34 34 00 35 35 35 00 36 36' - '36 00 39 39 39 00 3A 3A 3B 00 3B 3B 3B 00 7A 00' - '00 00 4E 3E 3E 00 3F 41 42 00 44 44 44 00 46 46' - '46 00 4B 4B 4B 00 50 52 52 00 57 57 57 00 59 59' - '59 00 5C 5C 5C 00 5E 5E 5E 00 65 6A 68 00 69 69' - '69 00 6E 6E 6E 00 6F 6E 6E 00 77 6E 69 00 7E 69' - '69 00 72 72 72 00 75 75 75 00 79 73 79 00 79 79' - '79 00 7B 7B 7B 00 7F 7F 7F 00 83 00 00 00 88 70' - '70 00 00 FF 00 00 75 99 75 00 97 97 97 00 9B 9B' - '9B 00 A5 A5 A5 00 A6 A6 A6 00 A8 A2 A8 00 A8 A8' - 'A8 00 A9 A9 A9 00 AF AF AF 00 B8 AC B8 00 B2 B2' - 'B2 00 ED B7 97 00 C0 AE A4 00 DB B7 A2 00 DC B7' - 'A2 00 B7 E6 B7 00 FB C6 A8 00 F9 C7 AB 00 C0 C0' - 'C0 00 C1 C2 C2 00 C2 C2 C2 00 C3 C3 C3 00 C6 CD' - 'CD 00 C7 CE CE 00 C9 C9 C9 00 CA CA CA 00 C8 CF' - 'CF 00 CC CC CC 00 CE CE CE 00 D0 D0 D0 00 D1 D1' - 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' - 'D5 00 D6 D6 D6 00 D7 D7 D7 00 DE D8 D3 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DE DE DE 00 FF C9' - 'C9 00 FF D7 D7 00 FF E3 D0 00 DF E6 E6 00 E0 E0' - 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E4 E4 E4 00 E5 E5' - 'E5 00 E6 E6 E6 00 E8 E3 E1 00 E8 E8 E8 00 E9 E9' - 'E9 00 EA EA EA 00 EB EB EB 00 ED ED ED 00 F3 F3' - 'F3 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6 F6 00 FF F2' - 'FF 00 F9 F9 F9 00 FA FA FA 00 FB FB FB 00 FB FC' - 'FC 00 FC FC FC 00 FF FD FE 00 FE FE FE 00 FF FF' - 'FF 00 00 00 00 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA D8 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 F1 D2' - 'C2 00 F2 D6 C7 00 F4 DD D0 00 E0 E0 E0 00 E1 E1' - 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' - 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' - 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' - 'ED 00 F0 F0 F0 00 F2 F2 F2 00 F3 F3 F3 00 F9 F9' - 'F9 00 FA FA FA 00 FF FF FF 00 00 00 00 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 56 00 00 00 00 00 00 00 03 00' - '00 00 5E 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 66' - '6C 6F 70 70 79 2E 69 63 6F 00 1A 93 4B 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '06 14 36 2E 2E 2E 00 00 00 00 00 00 00 00 00 0A' - '29 10 35 1E 1E 1E 00 7F 7F 7F 7F 7F 7F 7F 7F 01' - '03 1F 63 62 62 62 7F 2C 3D 38 41 40 3E 3C 3F 0D' - '05 24 65 4E 4F 52 7F 7C 76 37 47 31 33 32 42 08' - '7F 23 6B 51 53 53 7F 7D 7D 12 15 19 19 18 19 13' - '7F 23 7D 66 68 69 7F 7E 72 7D 77 75 72 72 7E 28' - '7F 02 7F 0B 0C 04 7F 7B 3B 58 5B 5A 5C 5B 69 25' - '0F 16 1C 20 11 07 7F 5C 54 54 57 59 5A 5A 67 27' - '25 17 6C 44 46 45 7F 3A 57 58 55 55 56 57 66 26' - '2F 22 4B 2D 48 43 00 2A 61 55 55 55 56 57 67 1D' - '0E 21 7A 5D 64 49 00 1B 71 60 5E 5F 5F 5E 5E 6A' - '71 30 7F 00 00 00 00 04 72 6F 6D 6B 6A 6A 69 70' - '75 1A 00 00 00 00 00 7F 6E 50 77 75 73 74 78 54' - '79 09 00 00 00 00 00 7F 2B 4A 4D 4C 4C 4C 4C 4A' - '39 7F 00 00 00 00 00 00 7F 7F 7F 7F 7F 7F 7F 7F' - '7F 00 00 00 00 00 FF C0 00 00 FF 80 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 80 0F' - '00 00 C0 1F 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00' - '00 00 00 09 99 99 00 00 00 00 00 0F FF FF 0F FA' - '77 77 00 0F 88 88 0F F0 00 00 00 0F FF FF 0F F7' - '77 77 70 00 00 00 07 77 77 77 70 00 00 00 07 77' - '77 77 70 08 88 88 07 77 77 77 70 08 87 77 07 77' - '77 77 70 07 8F 77 07 77 77 77 77 70 00 00 08 77' - '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 77' - '77 77 77 70 00 00 00 00 00 00 00 00 00 00 FF 80' - '00 00 FF 80 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 07 00 00 80 07' - '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 04 00 00 00' - '00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 08 88 88 88 88 00 00 00 00 00 00 00 00 00 08' - '88 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '08 09 99 99 99 99 00 00 00 00 00 00 00 00 00 00' - '00 07 77 77 77 77 00 00 00 00 00 00 00 00 00 00' - '00 0F FF FF FF FF 00 00 00 00 00 00 00 00 00 00' - '00 0F F8 88 88 88 00 8F FF 7A FF F7 77 77 77 00' - '00 0F FF FF FF FF 00 7F FF AA A7 77 77 77 70 00' - '00 0F F8 88 88 88 00 7F FF FA 77 00 00 00 07 70' - '00 0F FF FF FF FF 00 7F FF 00 00 00 00 00 00 00' - '00 0F F8 88 88 88 00 7F FF 77 77 77 77 77 77 70' - '00 0F FF FF FF FF 00 7F FF 77 77 77 77 77 77 70' - '00 00 00 00 00 00 00 7F FF FF FF FF FF FF FF F0' - '00 00 00 88 80 00 00 77 77 77 77 77 77 77 77 78' - '00 00 08 88 80 00 00 77 77 77 77 77 77 77 77 78' - '80 08 88 80 00 00 00 77 77 77 77 77 77 77 77 78' - '80 08 88 88 88 88 00 87 77 77 77 77 77 77 77 78' - '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 78' - '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 78' - '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 70' - '88 87 F8 8F 77 77 00 07 77 77 77 77 77 77 77 70' - '00 07 77 77 77 77 00 07 77 77 77 77 77 77 77 77' - '77 70 00 00 00 00 00 08 77 77 77 77 77 77 77 77' - '77 70 00 00 00 00 00 08 77 77 77 77 77 77 77 77' - '77 70 00 00 00 00 00 00 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 87 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 87 77 77 77 77 77 77 77' - '77 00 00 00 00 00 00 00 00 88 88 88 88 88 88 88' - '80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF E0 00 FF FF E0 00 FF FF' - 'E0 00 FF FF E8 00 E0 00 00 00 80 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 3F 80 00 00 7F C0 00 00 7F C0 00 00 7F C0 00' - '00 7F E0 00 00 7F E0 00 00 FF E0 00 00 FF E0 00' - '01 FF FF FF FF FF 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 01 01 00 02 02 02 00 03 03 03 00 04 04' - '04 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' - '08 00 09 09 09 00 0A 0A 0A 00 0B 0B 0B 00 0C 0C' - '0C 00 0D 0D 0D 00 0E 0E 0E 00 10 10 10 00 11 11' - '11 00 12 12 10 00 12 12 12 00 13 13 13 00 14 14' - '14 00 15 15 15 00 16 16 14 00 16 16 16 00 17 17' - '17 00 18 18 18 00 19 19 19 00 1B 1B 1B 00 1C 1C' - '1C 00 1E 1E 1E 00 1F 1F 1F 00 22 22 1F 00 20 20' - '20 00 21 21 21 00 22 22 22 00 23 23 23 00 24 24' - '24 00 25 25 25 00 26 26 26 00 27 27 27 00 28 28' - '24 00 2A 2A 25 00 2B 2B 26 00 28 28 28 00 29 29' - '29 00 2A 2A 2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E' - '2E 00 2F 2F 2F 00 30 30 2C 00 30 30 30 00 32 32' - '32 00 33 33 33 00 36 36 30 00 34 34 34 00 35 35' - '35 00 36 36 36 00 37 37 37 00 39 39 39 00 3B 3B' - '3B 00 3C 3C 3C 00 3D 3D 3D 00 3F 3F 3F 00 40 40' - '40 00 41 41 41 00 42 42 42 00 43 43 43 00 44 44' - '44 00 45 45 45 00 46 46 46 00 47 47 47 00 48 48' - '48 00 49 49 49 00 4A 4A 4A 00 4B 4B 4B 00 4C 4C' - '4C 00 4E 4E 4E 00 4F 4F 4F 00 50 50 50 00 52 52' - '52 00 53 53 53 00 54 54 54 00 57 57 57 00 5B 58' - '57 00 59 59 59 00 5D 5D 5D 00 5E 5E 5E 00 5F 5F' - '5F 00 61 61 61 00 64 64 64 00 65 65 65 00 66 66' - '66 00 6D 6A 67 00 6A 6A 6A 00 7F 60 60 00 71 71' - '71 00 75 75 75 00 77 77 77 00 7B 77 75 00 79 79' - '79 00 7A 7A 7A 00 7E 7E 7E 00 7F 7F 7F 00 C0 00' - '00 00 83 7A 75 00 D5 40 40 00 00 C0 00 00 00 FF' - '00 00 87 80 7D 00 80 80 80 00 83 83 83 00 84 84' - '84 00 8B 86 84 00 8A 8A 8A 00 8C 8C 8C 00 8D 8D' - '8D 00 8E 8E 8E 00 90 90 90 00 93 93 93 00 97 97' - '97 00 99 99 99 00 9A 9A 9A 00 9E 9E 9E 00 9F 9F' - '9F 00 A3 A3 9E 00 A4 A4 A4 00 A6 A6 A6 00 A7 A7' - 'A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA AA 00 AB AB' - 'AB 00 AD A8 AB 00 AB AC AC 00 AD AD AD 00 AE AE' - 'AE 00 AF AF AF 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' - 'B2 00 B3 B3 B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7' - 'B7 00 B8 B4 B6 00 B8 B6 B6 00 B8 B8 B8 00 BA BA' - 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' - 'BE 00 BF BF BF 00 EA 80 80 00 CA A8 94 00 CC AF' - '9D 00 E9 B6 99 00 E9 B8 9C 00 CE B6 A6 00 D0 B3' - 'A3 00 D0 BC B0 00 EA BB A0 00 EA BC A1 00 EB BE' - 'A5 00 D2 C3 B9 00 EC C0 A7 00 EC C2 AA 00 ED C5' - 'AE 00 ED C6 AF 00 EE C8 B3 00 EF CC B8 00 F0 CF' - 'BC 00 F0 D0 BE 00 C0 C0 C0 00 C1 C1 C1 00 C2 C2' - 'C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5 C5 00 C6 C6' - 'C6 00 C8 C8 C8 00 C8 C9 C9 00 C9 C9 C9 00 CA CA' - 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' - 'CE 00 CF CF CF 00 D5 CB C4 00 D0 CB C8 00 D7 D2' - 'CE 00 D9 D1 CC 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' - 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' - 'D6 00 D7 D7 D7 00 DC D9 D7 00 D8 D8 D8 00 D9 D9' - 'D9 00 DA DA D8 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 FF C0' - 'C0 00 F1 D2 C2 00 F2 D6 C7 00 F3 D9 CB 00 F4 DD' - 'D0 00 F6 E4 D9 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' - 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' - 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' - 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' - 'EE 00 EF EF EF 00 F9 EE E8 00 F0 F0 F0 00 F1 F1' - 'F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5' - 'F5 00 F6 F6 F6 00 F7 F7 F7 00 FD F9 F7 00 F8 F8' - 'F8 00 F9 F9 F9 00 FA FA FA 00 FF FF FF 00 00 00' - '00 00 C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 F8 F8 F8 F8 F8' - 'F8 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 3D 3D 3D 3D 3D' - 'F8 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 73 73 73 73 73' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 16 36 36 1F 04' - 'F8 68 68 68 68 68 68 68 68 68 68 68 68 68 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 28 00 00 73 0C' - 'F8 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 F8 29 F8 F8 F8 0C' - 'F8 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 00 00' - '00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 11 2A 32 1F 0F' - 'F8 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 00 00' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 04 0C 0C 0F 19' - 'F8 E7 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 00 F8' - 'F8 F8 F8 21 2F 2E 2F 2E 2E 2E 2E 2E 2E 2E 2E 2E' - '2E 2E 2D 2D 2D 2D 2D 2D 2D 2D F8 0C 0C 0F 19 18' - 'F8 E6 E1 79 79 79 79 79 79 79 79 79 79 79 00 F8' - 'F8 26 76 91 87 86 85 BB BA B9 B7 B2 B1 B0 B0 B1' - 'AE AF 99 99 96 97 94 97 97 97 F8 0C 0F 19 19 1D' - 'F8 E5 CF DA DA DA DB DB DB DC DD DD DD DE F8 F8' - '01 72 85 E5 E2 E2 E2 C6 6B 6B E1 E2 E2 DD D1 CB' - 'C4 BB BB BB BB BB B6 BB 83 30 F8 F8 F8 19 1E 19' - 'F8 E4 E0 E1 E2 E2 E3 E4 E4 E4 E5 E5 E5 E6 F8 F8' - '1A 85 E5 E5 E2 E2 E2 6C 6C 6C 6B DB D3 C7 BA C4' - 'B9 BB BB BB BB BB BB BB 40 30 F8 F8 F8 1E 15 13' - 'F8 E3 E1 79 79 79 79 79 79 79 79 79 79 79 F8 F8' - '2C 85 E4 E5 E5 E2 E2 6C 6C 6C 6C B9 B5 5C 5C 5C' - '5C 5C 5C 5C 5C 5C 5C BB 77 40 F8 F8 F8 F8 0E 0F' - 'F8 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 F8 F8' - '2B C3 E6 E5 E5 E2 E2 E2 6C 6C 8E 8E 8F 3C 3C 3C' - '3C 3C 3C 3C 3C 3C 3C 8F 8F 8F F8 F8 F8 F8 0A 0D' - 'F8 E2 E1 DD DD DD DD DE DE DF E0 E0 E0 E1 F8 F8' - '2B C3 E8 E2 E5 E2 E2 F8 F8 F8 F8 F8 F8 F8 F8 F8' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 24 1E 05 07 0A' - 'F8 DF E1 79 79 79 79 79 79 79 79 79 79 79 F8 F8' - '27 C3 E9 E5 E5 E5 E5 6E 3C 3C 3C 3C 3C 3C 3C 3C' - '3C 3C 3C 3C 3C 3C 3C 3C 3C 3C F8 2E 10 02 03 03' - 'F8 D0 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 F8 F8' - '27 C4 ED E4 E5 E5 E5 80 80 84 88 8A 89 89 89 89' - '89 89 84 84 84 84 84 84 84 84 F8 34 0C F8 F8 F8' - 'F8 DF DF E0 E1 E1 E2 E3 E3 E3 E4 E4 E4 E5 F8 F8' - '26 C5 EE E5 E7 E5 E3 E2 E0 DE DC CF D0 CB CC C4' - 'C4 BD C2 C2 C2 C2 C2 C2 C2 C2 F8 3A 02 03 04 04' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - '26 C5 F2 F4 F1 F1 F1 F0 F0 EF EF EE EE EE ED ED' - 'EC EC EC EB EB EB E9 E9 E8 E8 F8 3A 07 09 0B 0D' - '0F 13 1A 1D 27 37 42 46 46 46 46 2F 2F 2F F8 F8' - '24 C8 F7 E3 DB DC DC DA D3 D3 D3 D3 D3 DA DA DA' - 'DA DA DA DA DA DA DA DA DA DA F8 3F 0D 10 12 17' - '1B 21 26 33 3D 44 47 46 46 46 2F 2F 2F 2F F8 F8' - '24 D2 F4 CC B2 95 99 CB CE CC CC CC CC CC CC CC' - 'CC CC CC CC CC CC CC CC CC CC F8 44 23 18 1B 20' - '27 2E 38 40 44 47 4A 46 46 2F 2F 2F 2F 2F F8 F8' - '1E CE EE B4 82 90 8A B1 CE CB CB CB CB CB C9 C9' - 'C9 C9 C9 C9 C9 C9 CB CB CB CB F8 4B 30 1E 25 2E' - '31 3B 43 44 47 4B 49 42 39 2F 23 1C 1C 14 F8 F8' - '05 B0 F1 96 8C B1 84 95 CB C7 C7 C7 C6 C5 C5 C7' - 'C9 CB CB C9 C7 C5 C5 C5 C6 C7 F8 4B 4C 27 30 35' - '3D 45 44 47 4B 4B 45 3D 34 2D 25 1C 1C 17 00 F8' - 'F8 7E EF BD B3 C4 99 B7 C5 C4 C2 C5 C2 C2 C7 C7' - 'C7 C7 C7 C7 C7 C7 C2 C2 C6 C2 F8 50 53 3D 38 3F' - 'F8 73 73 73 73 73 73 73 73 73 73 73 73 73 00 F8' - 'F8 66 E9 C3 BD B9 BD C3 BC BD C7 C7 C7 C7 C7 C7' - 'C7 C7 C7 C7 C7 C7 C7 C7 C7 DB F8 53 57 56 49 45' - 'F8 70 F3 EA D9 D7 AC A8 A2 9D 9D 9D 9D 9D 00 F8' - 'F8 55 E3 C2 BB BB BB B8 C5 C5 C5 C5 C6 C7 C8 C8' - 'C8 C8 C8 C8 C8 C8 C7 C7 CF DE F8 57 57 5B 5E 44' - 'F8 75 F7 BF 71 6D 69 A0 A6 9D 9D 9D 9D 9D 00 F8' - 'F8 40 C9 C4 B8 B9 B8 C6 C5 C5 C5 C3 C4 C4 C4 C4' - 'C4 C4 C5 C4 C5 C5 C4 C4 C3 C2 F8 57 57 5B 5E 44' - 'F8 75 F7 BF 71 6D 69 A0 A6 9D 9D 9D 9D 9D 00 F8' - 'F8 22 90 CF B8 B9 BC C5 C5 BD C3 C2 C2 C2 C2 BD' - 'C5 C5 BC C5 C5 C5 C5 C5 C5 BC F8 57 5B 5E 5E 60' - 'F8 78 F7 92 52 4E 54 AD A9 A3 9D 9D 9D 9D 00 F8' - 'F8 07 7C D1 BA BB C5 C5 C5 C2 C2 C2 C2 C2 C2 C5' - 'C5 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5B 5B 5E 60 64' - 'F8 7B F7 89 50 4D 5D D6 AB A7 9E 9D 9D 9D 00 00' - 'F8 F8 6F D1 BD C3 C5 C5 C2 C2 C2 C2 C2 C2 C2 C2' - 'BD C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5B 5B 5E 64 64' - '3D 83 F7 7F 4F 4C 63 D8 D5 AA A4 9D 9D 9D 00 00' - 'F8 F8 58 D0 C3 C4 C5 C5 C3 C3 C3 C3 C3 C3 C3 C3' - 'C3 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5E 60 64 66 66' - 'F8 8B F7 DA D3 CA C1 D9 D7 AC A8 A2 A2 9D 00 00' - 'F8 F8 41 CB C6 C4 C5 C5 C5 C5 C5 C5 C5 C5 C5 C5' - 'C5 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 F8 F8 F8 F8 F8' - 'F8 7D CD CD CD CD C0 BE A5 A1 9F 9C 9C 9B 00 00' - 'F8 F8 2F BA C8 C7 C5 C5 C8 C8 C8 C8 C8 C8 C8 C8' - 'C8 C8 C8 C5 C5 C5 C5 C5 BA B7 B4 B2 B0 8D 97 C2' - '79 09 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00' - 'F8 F8 19 8A CF CF D2 D2 D2 CC CE CE CE CE CE CE' - 'CE CE CE CE D1 D1 D1 D1 D1 CE D1 D1 E1 CC BA B8' - '65 02 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00' - 'F8 F8 08 78 D0 D3 D0 D2 D2 D2 D1 D1 D1 D1 D1 D1' - 'D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 E1 E1 E1 D1 D0 B4' - '51 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 F8 F8 62 C5 DC DB D2 D2 D2 D2 D2 DA DA DA DA' - 'DA DA DA DA DA DA DA DA DB DB E1 E1 E1 DD CC 95' - '3B F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 F8 F8 4B B7 DF DD DE E5 E5 E5 E5 E5 E5 DE DE' - 'DE DE DE DE DE DE DF DF E1 E1 E1 E1 DE E0 C8 81' - '20 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 F8 F8 38 97 E0 E0 E0 E1 E1 E5 E5 E5 E5 E5 E5' - 'E5 E5 E5 E5 E5 E5 E5 E1 E1 E1 E1 E1 E0 E2 C6 7A' - '0B F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 F8 F8 1D 84 DE E7 E1 E0 E6 E5 E4 E7 E5 E5 E5' - 'E5 E5 E5 E5 E5 E5 E5 E5 E5 E6 E4 DF E5 E5 C8 72' - 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 F8 F8 08 79 DE D3 97 AF C8 E6 E7 E7 E8 E8 E7' - 'E6 E5 E5 E6 E7 E8 E8 E7 E8 DE B0 98 C3 E6 C6 61' - 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F8 F8 74 DA B2 8C 93 8C E5 EC EB EB EB EB' - 'EB EB EB EB EB EB EB EB EE C7 8A 8F 90 E5 BB 59' - 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F8 F8 5A BC D1 D0 C7 DE F5 F5 F5 F5 F5 F5' - 'F5 F5 F5 F5 F5 F5 F5 F5 F6 ED D3 CB D0 C9 8A 37' - 'F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F8 F8 1A 6E 98 C5 C9 CF CB CB CB CB CB CB' - 'CB CB CB CB CB CB CB CB CB CC CC C9 BB 8A 56 06' - 'F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 F8 F8 F8 0C 3E 49 48 48 48 48 48 48 48 48' - '48 48 48 48 48 48 48 48 48 48 48 49 49 31 02 F8' - 'F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' - 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F3 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 C0 00 00 00 03 FF 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' - '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' - '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07' - '77 77 77 77 77 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 08 88 88 88 88 88 88 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 08 88 88 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 09 99 99 99 99 99 99 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 09' - '99 99 99 99 99 99 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 07 77 77 77 77 77 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07' - '77 77 77 77 77 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 0F FF FF FF FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F' - 'F8 88 88 88 88 88 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 00 00 00 0F 7F FF FF FF FF FF 00 08' - '7F FF F7 AA FF FF 77 77 77 77 77 70 00 00 00 0F' - 'FF FF FF FF FF FF 00 07 FF FF FA AA AF 77 77 77' - '77 77 77 00 00 00 00 0F F8 88 88 88 88 88 00 07' - 'FF FF FA AA A7 78 88 88 88 88 87 80 00 00 00 0F' - 'FF FF FF FF FF FF 00 07 FF FF FF AA 77 70 00 00' - '00 00 07 77 00 00 00 0F FF FF FF FF FF FF 00 07' - 'FF FF F0 00 00 00 00 00 00 00 00 00 00 00 00 0F' - 'F8 88 88 88 88 88 00 07 FF FF F8 00 00 00 00 00' - '00 00 00 00 00 00 00 07 FF FF FF FF FF FF 00 07' - 'FF FF F7 77 77 77 77 77 77 77 77 77 00 00 00 0F' - 'FF FF FF FF FF FF 00 07 FF FF FF FF F7 77 77 77' - '77 77 77 77 00 00 00 00 00 00 00 00 00 00 00 07' - 'FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00' - '00 00 88 88 80 00 00 07 F7 7F FF 77 77 7F FF FF' - 'FF FF FF FF 00 00 00 00 00 08 88 88 00 00 00 07' - '77 77 77 77 77 77 77 77 77 7F 77 F7 08 00 00 00' - '00 88 88 80 00 00 00 07 F7 77 77 77 77 77 77 77' - '77 77 77 77 08 00 00 00 88 88 88 00 00 00 00 07' - '77 77 77 77 77 77 77 77 77 77 77 77 08 80 00 08' - '88 88 80 00 00 00 00 07 77 77 77 77 77 77 77 77' - '77 77 77 77 08 80 00 08 88 88 88 88 88 88 00 08' - '77 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' - 'FF F7 77 77 77 77 00 08 77 77 77 77 77 77 77 77' - '77 77 77 77 08 88 88 08 F7 88 87 77 77 77 00 00' - '77 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' - 'F7 88 87 77 77 77 00 00 77 77 77 77 77 77 77 77' - '77 77 77 77 08 88 88 08 F7 88 87 77 77 77 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' - 'F7 88 87 77 77 77 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 08 88 88 07 F7 88 8F 77 77 77 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 08 88 88 07' - 'FF 77 7F 77 77 77 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 00 00 00 07 77 77 77 77 77 77 00 00' - '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '00 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' - '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' - '00 00 00 00 00 00 00 00 00 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' - '00 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' - '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' - '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' - '00 87 77 77 77 77 77 77 77 77 77 77 77 77 78 00' - '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' - '77 77 77 77 77 77 70 00 00 00 00 00 00 00 00 00' - '00 08 77 77 77 77 77 77 77 77 77 77 77 77 80 00' - '00 00 00 00 00 00 00 00 00 00 08 88 88 88 88 88' - '88 88 88 88 88 80 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F3 00 00 00 00 FF FF FF F0 00 00 00 00 F0 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 03 FF 00 00 C0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' - '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' - '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 24 00 00 00 6C 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C' - '3C FF 3C 3C 3C FF 00 00 00 FF 7F 60 60 FF 7F 60' - '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' - '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' - '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 16 16 14 FF 36 36 30 FF 36 36 30 FF 22 22' - '1F FF 04 04 04 FF 00 00 00 FF C0 00 00 FF C0 00' - '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF C0 00' - '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF C0 00' - '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 28 28 24 FF 00 00 00 B4 00 00 00 9C 8C 8C' - '8C FF 0C 0C 0C FF 00 00 00 FF D5 40 40 FF D5 40' - '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' - '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' - '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 FF 2A 2A 25 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 0C 0C 0C FF 00 00 00 FF EA 80 80 FF EA 80' - '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' - '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' - '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 FF 12 12 10 FF 2B 2B 26 FF 30 30 2C FF 22 22' - '1F FF 10 10 10 FF 00 00 00 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' - '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 FF 04 04 04 FF 0C 0C 0C FF 0C 0C 0C FF 10 10' - '10 FF 18 18 18 FF 00 00 00 FF ED ED ED FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' - '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' - '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' - '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 00 00' - '00 FF 0C 0C 0C FF 0C 0C 0C FF 10 10 10 FF 18 18' - '18 FF 17 17 17 FF 00 00 00 FF EC EC EC FF E7 E7' - 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' - '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' - '90 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' - 'AB FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' - 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2' - 'C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF' - 'BF FF BF BF BF FF BC BC BC FF BD BD BD FF BA BA' - 'BA FF BD BD BD FF BD BD BD FF BD BD BD FF 00 00' - '00 FF 0C 0C 0C FF 10 10 10 FF 18 18 18 FF 18 18' - '18 FF 1E 1E 1E FF 00 00 00 FF EB EB EB FF DB DB' - 'DB FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' - 'E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E3 E3' - 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF 00 00' - '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF AD A8' - 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF D4 D4 D4 FF 00 C0 00 FF 00 C0 00 FF E7 E7' - 'E7 FF E8 E8 E8 FF E8 E8 E8 FF E3 E3 E3 FF DD DD' - 'DD FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' - 'C9 FF CD CD CD FF AA AA AA FF 2E 2E 2E FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 18 18 18 FF 1F 1F' - '1F FF 18 18 18 FF 00 00 00 FF EA EA EA FF E6 E6' - 'E6 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9' - 'E9 FF EA EA EA FF EA EA EA FF EA EA EA FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF 00 00' - '00 15 00 00 00 F0 19 19 19 FF AD A8 AB FF EB EB' - 'EB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 C0' - '00 FF E1 E1 E1 FF DF DF DF FF D5 D5 D5 FF CC CC' - 'CC FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF 40 40 40 FF 2E 2E 2E FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 1F 1F 1F FF 15 15' - '15 FF 13 13 13 FF 00 00 00 FF E9 E9 E9 FF E7 E7' - 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' - '00 30 00 00 00 FA 29 29 29 FF AD A8 AB FF EA EA' - 'EA FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF' - '00 FF CB CB CB FF C8 C8 C8 FF 66 66 66 FF 66 66' - '66 FF 66 66 66 FF 66 66 66 FF 66 66 66 FF 66 66' - '66 FF 66 66 66 FF 66 66 66 FF 66 66 66 FF 66 66' - '66 FF CD CD CD FF 93 93 93 FF 40 40 40 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 0E 0E' - '0E FF 10 10 10 FF 00 00 00 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' - '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' - 'EC FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF B5 B5' - 'B5 FF B5 B5 B5 FF B6 B6 B6 FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 0A 0A' - '0A FF 0D 0D 0D FF 00 00 00 FF E8 E8 E8 FF E7 E7' - 'E7 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF E6 E6' - 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF 00 00' - '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' - 'EE FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 24 24 24 FF 1F 1F 1F FF 05 05 05 FF 07 07' - '07 FF 0A 0A 0A FF 00 00 00 FF E5 E5 E5 FF E7 E7' - 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' - '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' - 'EF FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF 80 80 80 FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 00 00' - '00 FF 2B 2B 2B FF 11 11 11 FF 02 02 02 FF 03 03' - '03 FF 03 03 03 FF 00 00 00 FF DC DC DC FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' - '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' - 'F2 FF EA EA EA FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' - 'AE FF B0 B0 B0 FF AF AF AF FF AF AF AF FF AF AF' - 'AF FF AF AF AF FF AF AF AF FF AF AF AF FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF 00 00' - '00 FF 32 32 32 FF 0C 0C 0C FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF E5 E5 E5 FF E5 E5' - 'E5 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' - 'E8 FF E9 E9 E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA' - 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' - 'F3 FF EB EB EB FF ED ED ED FF EB EB EB FF E9 E9' - 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' - 'E2 FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' - 'D9 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF 00 00' - '00 FF 37 37 37 FF 02 02 02 FF 03 03 03 FF 04 04' - '04 FF 04 04 04 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' - 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' - 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' - 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' - 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF 00 00' - '00 FF 37 37 37 FF 07 07 07 FF 09 09 09 FF 0B 0B' - '0B FF 0D 0D 0D FF 10 10 10 FF 13 13 13 FF 19 19' - '19 FF 1E 1E 1E FF 27 27 27 FF 34 34 34 FF 42 42' - '42 FF 46 46 46 FF 46 46 46 FF 46 46 46 FF 46 46' - '46 FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' - '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' - 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' - 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF 00 00' - '00 FF 3F 3F 3F FF 0D 0D 0D FF 11 11 11 FF 12 12' - '12 FF 16 16 16 FF 1B 1B 1B FF 21 21 21 FF 26 26' - '26 FF 30 30 30 FF 3C 3C 3C FF 44 44 44 FF 47 47' - '47 FF 46 46 46 FF 46 46 46 FF 46 46 46 FF 2C 2C' - '2C FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' - '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' - 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' - 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF 00 00' - '00 FF 44 44 44 FF 23 23 23 FF 17 17 17 FF 1B 1B' - '1B FF 20 20 20 FF 27 27 27 FF 2B 2B 2B FF 35 35' - '35 FF 40 40 40 FF 44 44 44 FF 47 47 47 FF 4A 4A' - '4A FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' - '2C FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' - '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' - 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' - 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF 00 00' - '00 FF 4B 4B 4B FF 2E 2E 2E FF 1F 1F 1F FF 25 25' - '25 FF 2B 2B 2B FF 2F 2F 2F FF 39 39 39 FF 43 43' - '43 FF 44 44 44 FF 47 47 47 FF 4B 4B 4B FF 49 49' - '49 FF 42 42 42 FF 36 36 36 FF 2C 2C 2C FF 23 23' - '23 FF 1C 1C 1C FF 1C 1C 1C FF 14 14 14 FF 00 00' - '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' - 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' - 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' - 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF 00 00' - '00 FF 4B 4B 4B FF 4C 4C 4C FF 27 27 27 FF 2E 2E' - '2E FF 33 33 33 FF 3C 3C 3C FF 45 45 45 FF 44 44' - '44 FF 47 47 47 FF 4B 4B 4B FF 4B 4B 4B FF 45 45' - '45 FF 3C 3C 3C FF 32 32 32 FF 2A 2A 2A FF 25 25' - '25 FF 1C 1C 1C FF 1C 1C 1C FF 16 16 16 FF 00 00' - '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' - 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' - 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' - 'D0 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0 D0 FF 00 00' - '00 FF 52 52 52 FF 57 57 57 FF 3C 3C 3C FF 35 35' - '35 FF 3F 3F 3F FF 00 00 00 FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 00 00' - '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' - 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' - 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF E1 E1 E1 FF 00 00' - '00 FF 57 57 57 FF 5E 5E 5E FF 5D 5D 5D FF 49 49' - '49 FF 45 45 45 FF 00 00 00 FF 84 84 84 FF FD F9' - 'F7 FF F9 EE E8 FF F6 E4 D9 FF F3 D9 CB FF F0 CF' - 'BC FF ED C5 AE FF EA BB A0 FF E9 B6 99 FF E9 B6' - '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' - 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CA CA CA FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF 00 00' - '00 FF 5E 5E 5E FF 5E 5E 5E FF 65 65 65 FF 6A 6A' - '6A FF 44 44 44 FF 00 00 00 FF 8E 8E 8E FF FF FF' - 'FF FF D0 CB C8 FF 8B 86 84 FF 87 80 7D FF 83 7A' - '75 FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' - '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' - 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' - 'CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3' - 'D3 FF D2 D2 D2 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2' - 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF 00 00' - '00 FF 5E 5E 5E FF 5E 5E 5E FF 65 65 65 FF 6A 6A' - '6A FF 44 44 44 FF 00 00 00 FF 8E 8E 8E FF FF FF' - 'FF FF D0 CB C8 FF 8B 86 84 FF 87 80 7D FF 83 7A' - '75 FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' - '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' - 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' - 'CE FF D3 D3 D3 FF D3 D3 D3 FF CF CF CF FF D1 D1' - 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF D3 D3 D3 FF D3 D3 D3 FF CE CE' - 'CE FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CE CE CE FF 00 00' - '00 FF 5E 5E 5E FF 65 65 65 FF 6A 6A 6A FF 6A 6A' - '6A FF 71 71 71 FF 00 00 00 FF 97 97 97 FF FF FF' - 'FF FF B8 B6 B6 FF 54 54 54 FF 4F 4F 4F FF 5B 58' - '57 FF F0 D0 BE FF ED C6 AF FF EA BC A1 FF E9 B6' - '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' - '9F FF DD DD DD FF CC CC CC FF CD CD CD FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' - '00 FF 65 65 65 FF 6A 6A 6A FF 6A 6A 6A FF 71 71' - '71 FF 79 79 79 FF 00 00 00 FF 9E 9E 9E FF FF FF' - 'FF FF AF AF AF FF 52 52 52 FF 4E 4E 4E FF 6D 6A' - '67 FF F2 D6 C7 FF EF CC B8 FF EC C2 AA FF E9 B8' - '9C FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' - '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF D3 D3' - 'D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' - '00 FF 65 65 65 FF 6A 6A 6A FF 71 71 71 FF 7E 7E' - '7E FF 79 79 79 FF 00 00 00 FF AA AA AA FF FF FF' - 'FF FF A6 A6 A6 FF 50 50 50 FF 4C 4C 4C FF 7B 77' - '75 FF F4 DD D0 FF F1 D2 C2 FF EE C8 B3 FF EB BE' - 'A5 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' - '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D3 D3' - 'D3 FF D3 D3 D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' - '00 FF 65 65 65 FF 71 71 71 FF 79 79 79 FF 7E 7E' - '7E FF 7E 7E 7E FF 00 00 00 FF B1 B1 B1 FF FF FF' - 'FF FF E0 E0 E0 FF DF DF DF FF DC D9 D7 FF D9 D1' - 'CC FF F6 E4 D9 FF F3 D9 CB FF F0 CF BC FF ED C5' - 'AE FF EA BB A0 FF EA BB A0 FF E9 B6 99 FF 00 00' - '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' - '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF A3 A3 9E FF DA DA' - 'D8 FF DA DA D8 FF DA DA D8 FF DA DA D8 FF D7 D2' - 'CE FF D5 CB C4 FF D2 C3 B9 FF D0 BC B0 FF CE B6' - 'A6 FF CC AF 9D FF CC AF 9D FF CA A8 94 FF 00 00' - '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' - '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' - 'D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF CC CC CC FF C9 C9 C9 FF C6 C6' - 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' - 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' - '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' - '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF D9 D9 D9 FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DA DA DA FF DD DD' - 'DD FF DD DD DD FF E7 E7 E7 FF D9 D9 D9 FF CC CC' - 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' - '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' - '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' - 'DC FF DE DE DE FF DE DE DE FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF DD DD DD FF DC DC' - 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' - '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' - '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' - 'E1 FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E3 E3 E3 FF D9 D9' - 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' - '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' - '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' - 'E3 FF E4 E4 E4 FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' - 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' - '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' - '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' - 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' - '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' - 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' - 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EA EA' - 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' - 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' - 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' - 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' - 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' - 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' - 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' - 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' - 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' - 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' - 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' - 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' - 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' - 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' - 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' - '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' - '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' - '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' - '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' - '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' - 'FF F0 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 C0 00 00 00 03 FF 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' - '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' - '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 24 00 00 00 6C 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 3C 3C 3C FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C' - '3C FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' - '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' - '60 FF 7F 60 60 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' - '00 04 00 00 00 14 00 00 00 26 00 00 00 2D 00 00' - '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' - '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' - '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' - '00 2D 28 28 24 FF 00 00 00 8F 8C 8C 8C FF 0C 0C' - '0C FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' - '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' - '40 FF D5 40 40 FF 00 00 00 00 00 00 00 07 00 00' - '00 23 00 00 00 55 00 00 00 7E 00 00 00 8C 00 00' - '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' - '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' - '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' - '00 8C 2A 2A 25 FF 00 00 00 FF 00 00 00 FF 0C 0C' - '0C FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' - '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' - '80 FF EA 80 80 FF 00 00 00 00 00 00 00 1F 00 00' - '00 C2 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 04 04 04 FF 0C 0C 0C FF 10 10 10 FF 18 18' - '18 FF ED ED ED FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF 00 00 00 00 00 00 00 C0 00 00' - '00 FF 21 21 21 FF 2C 2C 2C FF 2C 2C 2C FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 0C 0C 0C FF 0C 0C 0C FF 18 18 18 FF 17 17' - '17 FF EC EC EC FF E7 E7 E7 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 00 00 00 06 01 01 01 FF 8A 8A' - '8A FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF D4 D4' - 'D4 FF 00 C0 00 FF E7 E7 E7 FF E8 E8 E8 FF E3 E3' - 'E3 FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF C8 C9 C9 FF AA AA AA FF 2E 2E' - '2E FF 00 00 00 FF 00 00 00 FF 1F 1F 1F FF 18 18' - '18 FF EA EA EA FF E6 E6 E6 FF E8 E8 E8 FF E8 E8' - 'E8 FF EA EA EA FF EA EA EA FF EB EB EB FF EB EB' - 'EB FF EC EC EC FF 00 00 00 1B 19 19 19 FF AD A8' - 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF 00 FF' - '00 FF 00 FF 00 FF 00 C0 00 FF DF DF DF FF D5 D5' - 'D5 FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF 40 40 40 FF 2E 2E' - '2E FF 00 00 00 FF 00 00 00 FF 15 15 15 FF 13 13' - '13 FF E9 E9 E9 FF E7 E7 E7 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 00 00 00 3A 28 28 28 FF D1 D1' - 'D1 FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 FF 00 FF B5 B5 B5 FF B6 B6 B6 FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF B6 B6 B6 FF B6 B6' - 'B6 FF 00 00 00 FF 00 00 00 FF 0A 0A 0A FF 0D 0D' - '0D FF E8 E8 E8 FF E7 E7 E7 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF 00 00 00 39 28 28 28 FF D1 D1' - 'D1 FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 24 24 24 FF 1F 1F 1F FF 07 07 07 FF 0A 0A' - '0A FF E5 E5 E5 FF E7 E7 E7 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' - '99 FF 99 99 99 FF 00 00 00 39 27 27 27 FF D2 D2' - 'D2 FF EA EA EA FF EB EB EB FF EB EB EB FF A7 A7' - 'A7 FF AB AB AB FF AE AE AE FF AF AF AF FF AF AF' - 'AF FF AF AF AF FF AF AF AF FF AB AB AB FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' - 'AB FF 32 32 32 FF 0C 0C 0C FF 00 00 00 FF 00 00' - '00 FF E5 E5 E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7' - 'E7 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EA EA' - 'EA FF EB EB EB FF 00 00 00 39 26 26 26 FF D3 D3' - 'D3 FF EB EB EB FF ED ED ED FF E9 E9 E9 FF E8 E8' - 'E8 FF E4 E4 E4 FF E2 E2 E2 FF DC DC DC FF D8 D8' - 'D8 FF D2 D2 D2 FF D2 D2 D2 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF 37 37 37 FF 02 02 02 FF 04 04 04 FF 04 04' - '04 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 37 24 24 24 FF D6 D6' - 'D6 FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' - 'E0 FF DF DF DF FF DF DF DF FF DF DF DF FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF 3F 3F 3F FF 0D 0D 0D FF 12 12 12 FF 16 16' - '16 FF 21 21 21 FF 26 26 26 FF 3C 3C 3C FF 44 44' - '44 FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' - '2C FF 2C 2C 2C FF 00 00 00 34 24 24 24 FF DE DE' - 'DE FF D9 D9 D9 FF C4 C4 C4 FF BF BF BF FF D8 D8' - 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF 44 44 44 FF 23 23 23 FF 1B 1B 1B FF 20 20' - '20 FF 2B 2B 2B FF 35 35 35 FF 44 44 44 FF 47 47' - '47 FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' - '2C FF 2C 2C 2C FF 00 00 00 07 05 05 05 FF C2 C2' - 'C2 FF BC BC BC FF B2 B2 B2 FF AB AB AB FF BB BB' - 'BB FF D5 D5 D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3' - 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D7 D7' - 'D7 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5' - 'D5 FF 4B 4B 4B FF 4C 4C 4C FF 2E 2E 2E FF 33 33' - '33 FF 45 45 45 FF 44 44 44 FF 4B 4B 4B FF 4B 4B' - '4B FF 3C 3C 3C FF 32 32 32 FF 25 25 25 FF 1C 1C' - '1C FF 16 16 16 FF 00 00 00 00 00 00 00 FF A4 A4' - 'A4 FF CF CF CF FF C5 C5 C5 FF BF BF BF FF C9 C9' - 'C9 FF D2 D2 D2 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0' - 'D0 FF 52 52 52 FF 57 57 57 FF 35 35 35 FF 3F 3F' - '3F FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' - '8C FF 8C 8C 8C FF 00 00 00 00 00 00 00 FF 59 59' - '59 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CA CA' - 'CA FF D3 D3 D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5' - 'D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D5 D5 D5 FF DB DB DB FF E4 E4' - 'E4 FF 5E 5E 5E FF 5E 5E 5E FF 6A 6A 6A FF 44 44' - '44 FF 8E 8E 8E FF FF FF FF FF 8B 86 84 FF 87 80' - '7D FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' - '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 FF 40 40' - '40 FF D2 D2 D2 FF CA CA CA FF CA CA CA FF D4 D4' - 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3 D3 FF D2 D2' - 'D2 FF D3 D3 D3 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0' - 'D0 FF 5E 5E 5E FF 5E 5E 5E FF 6A 6A 6A FF 44 44' - '44 FF 8E 8E 8E FF FF FF FF FF 8B 86 84 FF 87 80' - '7D FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' - '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 F4 07 07' - '07 FF DD DD DD FF CC CC CC FF D3 D3 D3 FF D3 D3' - 'D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 65 65 65 FF 6A 6A 6A FF 71 71 71 FF 79 79' - '79 FF 9E 9E 9E FF FF FF FF FF 52 52 52 FF 4E 4E' - '4E FF F2 D6 C7 FF EF CC B8 FF E9 B8 9C FF E9 B6' - '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 BA 00 00' - '00 FF DD DD DD FF CF CF CF FF D3 D3 D3 FF D3 D3' - 'D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 3C 3C 3C FF 6A 6A 6A FF 71 71 71 FF 79 79' - '79 FF AA AA AA FF FF FF FF FF 50 50 50 FF 4C 4C' - '4C FF F4 DD D0 FF F1 D2 C2 FF EB BE A5 FF E9 B6' - '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 4D 00 00' - '00 FF D8 D8 D8 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF A3 A3 9E FF DA DA D8 FF DA DA D8 FF DA DA' - 'D8 FF D5 CB C4 FF D2 C3 B9 FF CE B6 A6 FF CC AF' - '9D FF CA A8 94 FF 00 00 00 00 00 00 00 1A 00 00' - '00 FF CC CC CC FF D6 D6 D6 FF D3 D3 D3 FF D3 D3' - 'D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CC CC CC FF C9 C9' - 'C9 FF C4 C4 C4 FF C2 C2 C2 FF BD BD BD FF D0 D0' - 'D0 FF 09 09 09 FF 00 00 00 FF 00 00 00 6C 00 00' - '00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00' - '00 D2 97 97 97 FF DC DC DC FF DC DC DC FF DE DE' - 'DE FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF E7 E7 E7 FF E7 E7 E7 FF DC DC DC FF C6 C6' - 'C6 FF 00 00 00 FF 00 00 00 FF 00 00 00 59 00 00' - '00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 AF 77 77 77 FF D3 D3 D3 FF E1 E1 E1 FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1' - 'E1 FF E7 E7 E7 FF E7 E7 E7 FF D9 D9 D9 FF BB BB' - 'BB FF 00 00 00 FF 00 00 00 FF 00 00 00 40 00 00' - '00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 66 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E6 E6 E6 FF D4 D4 D4 FF 9A 9A' - '9A FF 00 00 00 FF 00 00 00 A4 00 00 00 2B 00 00' - '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 2D 1E 1E 1E FF AB AB AB FF ED ED ED FF E7 E7' - 'E7 FF EC EC EC FF EB EB EB FF ED ED ED FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EC EC' - 'EC FF E5 E5 E5 FF EB EB EB FF D6 D6 D6 FF 8A 8A' - '8A FF 00 00 00 FF 00 00 00 7B 00 00 00 1B 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 8D 8D 8D FF C4 C4 C4 FF B2 B2' - 'B2 FF B2 B2 B2 FF EB EB EB FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5' - 'D5 FF B6 B6 B6 FF B7 B7 B7 FF CD CD CD FF 61 61' - '61 FF 00 00 00 FF 00 00 00 50 00 00 00 0F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 64 64 64 FF DD DD DD FF DC DC' - 'DC FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF F2 F2' - 'F2 FF D8 D8 D8 FF DC DC DC FF B0 B0 B0 FF 34 34' - '34 FF 00 00 00 E5 00 00 00 31 00 00 00 04 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9C 00 00 00 FF 3D 3D 3D FF 49 49' - '49 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 49 49 49 FF 49 49 49 FF 02 02 02 FF 00 00' - '00 FF 00 00 00 49 00 00 00 14 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 00 00 00 7F 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FA 00 00' - '00 7C 00 00 00 12 00 00 00 04 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF E0 00 FF FF E0 00 FF FF' - 'E0 00 C0 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 1F 80 00 00 1F C0 00 00 1F C0 00 00 1F C0 00' - '00 1F E0 00 00 3F E0 00 00 3F E0 00 00 7F E0 00' - '00 7F FF FF FF FF 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 00 00 00 FF 00 00 00 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 36 36 30 FF 00 00 00 FF C0 00' - '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF 00 00' - '00 00 00 00 00 16 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 FF 30 30 2C FF 00 00 00 FF FF C0' - 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' - '00 54 90 90 90 FF AB AC AC FF CC CC CC FF C4 C4' - 'C4 FF C2 C2 C2 FF C1 C1 C1 FF BC BC BC FF BD BD' - 'BD FF 00 00 00 FF 18 18 18 FF 00 00 00 FF E0 E0' - 'E0 FF E1 E1 E1 FF E2 E2 E2 FF E3 E3 E3 FF 00 00' - '00 FA EA EA EA FF E8 E8 E8 FF 00 FF 00 FF CB CB' - 'CB FF 66 66 66 FF 66 66 66 FF 66 66 66 FF CD CD' - 'CD FF 00 00 00 FF 00 00 00 FF 00 00 00 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' - '00 F9 EF EF EF FF EB EB EB FF 3B 3B 3B FF 3B 3B' - '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' - '3B FF 00 00 00 FF 02 02 02 FF 00 00 00 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' - '00 F9 F7 F7 F7 FF F6 F6 F6 FF F5 F5 F5 FF F3 F3' - 'F3 FF F2 F2 F2 FF F1 F1 F1 FF F0 F0 F0 FF EF EF' - 'EF FF 00 00 00 FF 09 09 09 FF 10 10 10 FF 1E 1E' - '1E FF 42 42 42 FF 46 46 46 FF 2C 2C 2C FF 00 00' - '00 F7 F3 F3 F3 FF B7 B7 B7 FF DA DA DA FF D8 D8' - 'D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' - 'D8 FF 00 00 00 FF 1F 1F 1F FF 2F 2F 2F FF 44 44' - '44 FF 49 49 49 FF 2C 2C 2C FF 1C 1C 1C FF 00 00' - '00 73 EF EF EF FF CB CB CB FF CE CE CE FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF 00 00 00 FF 5D 5D 5D FF 00 00 00 FF F9 EE' - 'E8 FF F0 CF BC FF E9 B6 99 FF E9 B6 99 FF 00 00' - '00 25 B7 B7 B7 FF CB CB CB FF D3 D3 D3 FF D0 D0' - 'D0 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 00 00 00 FF 6A 6A 6A FF 00 00 00 FF B8 B6' - 'B6 FF 5B 58 57 FF EA BC A1 FF E9 B6 99 FF 00 00' - '00 00 5F 5F 5F FF D2 D2 D2 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 00 00 00 FF 79 79 79 FF 00 00 00 FF E0 E0' - 'E0 FF D9 D1 CC FF F0 CF BC FF EA BB A0 FF 00 00' - '00 00 18 18 18 FF DB DB DB FF DE DE DE FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF D9 D9 D9 FF 7A 7A 7A FF 00 00' - '00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF E5 E5 E5 FF EB EB EB FF EB EB' - 'EB FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E7 E7 E7 FF E6 E6 E6 FF 20 20 20 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 DD E4 E4 E4 FF C1 C1 C1 FF ED ED' - 'ED FF EE EE EE FF EB EB EB FF ED ED ED FF ED ED' - 'ED FF C2 C2 C2 FF EC EC EC FF 00 00 00 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 44 80 80 80 FF D7 D7 D7 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D9 D9 D9 FF B0 B0 B0 FF 00 00 00 ED 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2C 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 70 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 80' - '00 00 FF 80 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 80 07 00 00 80 0F' - '00 00 80 0F 00 00 80 0F 00 00 C0 1F 00 00' -} */ - - -/* BINRES drive.ico */ -8 ICON drive.ico -/* { - '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 00 00 00 00 11 00 00 11 11 11 00 22 22' - '22 00 33 33 33 00 44 44 44 00 55 55 55 00 66 66' - '66 00 77 77 77 00 7F 7F 7F 00 00 CC 66 00 66 99' - '99 00 33 CC 99 00 66 CC 99 00 88 88 88 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 99 CC 99 00 CC CC' - 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 54 00 56 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' - '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 50 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 64 72 69 76 65 2E 69 63 6F' - '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 18 18 18 18 18 18 18 18 18 18 18 18 18 18' - '18 18 18 18 18 02 18 18 18 18 00 00 00 00 00 00' - '00 18 18 03 03 04 03 04 03 03 04 03 03 04 03 03' - '04 03 03 04 03 03 03 04 01 18 18 00 00 00 00 00' - '18 18 06 12 14 12 12 12 12 11 12 12 12 12 12 12' - '12 12 12 12 12 11 0F 10 0C 04 18 18 00 00 00 00' - '18 18 12 16 16 11 07 08 0F 10 11 12 12 11 12 12' - '12 12 12 12 12 12 0D 0B 10 0F 18 18 00 00 00 00' - '18 03 14 16 16 11 06 0F 0F 10 11 11 11 11 10 10' - '11 11 10 11 11 12 13 0E 12 0F 18 18 00 00 00 00' - '18 03 14 16 16 12 09 09 0F 10 10 11 12 0F 0F 10' - '0F 10 0F 10 11 14 12 12 14 10 18 18 00 00 00 00' - '18 03 15 16 16 12 08 0F 0F 10 11 11 12 10 09 0F' - '10 0F 0F 0F 11 14 14 12 14 0F 18 18 00 00 00 00' - '18 03 14 17 15 16 15 15 15 15 15 14 15 14 15 14' - '14 14 14 14 14 14 14 12 14 0F 18 18 00 00 00 00' - '18 03 14 17 17 16 17 17 16 17 16 17 16 17 16 17' - '16 17 16 17 16 16 16 17 15 10 18 18 00 00 00 00' - '18 03 15 16 15 15 15 15 15 15 15 15 15 15 15 15' - '15 15 15 15 15 15 15 15 17 10 18 18 00 00 00 00' - '18 03 15 15 11 11 14 15 15 14 15 15 14 15 14 15' - '14 15 14 15 14 12 11 12 16 10 18 18 00 00 00 00' - '18 18 11 15 12 12 12 14 14 15 15 15 15 16 15 16' - '15 15 15 14 15 11 12 12 16 09 18 18 00 00 00 00' - '18 18 0F 16 14 14 14 15 15 15 16 15 15 15 15 15' - '15 16 15 15 14 15 14 14 16 07 18 18 00 00 00 00' - '00 18 08 16 14 14 14 15 15 15 14 15 15 14 15 14' - '15 14 15 15 16 14 14 14 15 05 18 00 00 00 00 00' - '00 18 05 15 14 14 15 15 14 14 14 14 14 14 14 14' - '14 14 14 14 14 15 14 14 14 03 18 00 00 00 00 00' - '00 18 04 14 14 14 15 14 14 14 15 14 14 14 14 14' - '12 14 14 14 14 14 14 14 11 18 18 00 00 00 00 00' - '00 18 18 12 15 14 15 14 15 14 14 14 15 14 14 12' - '14 12 12 14 14 14 12 15 0F 18 18 00 00 00 00 00' - '00 18 18 10 15 14 14 15 14 15 14 15 14 14 15 15' - '14 12 14 12 12 12 12 14 08 18 18 00 00 00 00 00' - '00 18 18 09 15 15 14 15 14 15 15 15 15 15 14 15' - '15 15 15 15 15 12 14 14 06 18 18 00 00 00 00 00' - '00 00 18 06 15 15 15 14 16 15 15 15 15 15 15 15' - '15 15 15 15 14 15 15 14 05 18 00 00 00 00 00 00' - '00 00 18 05 14 16 15 15 14 15 15 16 15 16 16 15' - '16 15 15 15 15 15 15 11 03 18 00 00 00 00 00 00' - '00 00 18 04 11 15 16 16 16 15 15 15 15 15 15 15' - '15 15 15 15 16 16 15 10 18 18 00 00 00 00 00 00' - '00 00 18 18 11 16 14 14 15 16 16 15 16 15 15 16' - '15 16 16 15 12 15 15 09 18 18 00 00 00 00 00 00' - '00 00 18 18 0F 15 14 12 16 17 17 17 17 17 17 17' - '17 17 17 15 14 14 15 07 18 18 00 00 00 00 00 00' - '00 00 00 18 04 10 15 15 15 15 15 15 15 15 15 15' - '15 15 15 15 15 14 09 03 18 00 00 00 00 00 00 00' - '00 00 00 18 18 03 04 04 04 04 04 04 04 04 04 04' - '04 04 04 04 04 04 18 18 18 00 00 00 00 00 00 00' - '00 00 00 00 18 18 18 18 18 18 18 18 18 18 18 18' - '18 18 18 18 18 18 18 18 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' - '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' - '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 11 00 11 11' - '11 00 22 00 00 00 22 22 22 00 44 44 44 00 55 55' - '55 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 33 CC' - '99 00 88 88 88 00 99 99 99 00 AA AA AA 00 BB BB' - 'BB 00 99 CC 99 00 CC CC CC 00 DD DD DD 00 EE EE' - 'EE 00 00 00 00 00 CC CC CC 00 DD DD DD 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' - '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' - '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 54 00' - '56 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 54 00 00 00 00 00 00 00 03 00' - '00 00 5C 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 50 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' - '72 69 76 65 2E 69 63 6F 00 00 1A 93 4B 00 14 1A' - '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' - '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' - '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 13 13 02 02 02 02 02 02 02' - '02 02 03 01 13 00 00 13 0C 0E 0B 0C 0D 0E 0D 0E' - '0E 0D 0A 07 13 00 00 02 11 10 07 0B 0D 0D 0C 0C' - '0C 0E 0F 0C 13 00 00 02 11 11 0C 0D 0E 0E 0C 0D' - '0C 0E 10 0D 13 00 00 02 11 12 12 12 11 11 12 11' - '11 11 11 0E 13 00 00 13 10 0E 10 10 11 11 11 11' - '11 10 10 0E 13 00 00 13 0D 10 10 11 11 11 11 11' - '11 10 11 0B 13 00 00 13 0B 11 11 11 10 10 10 11' - '10 10 11 07 13 00 00 13 07 11 10 10 11 10 10 0E' - '10 10 10 06 13 00 00 13 05 10 11 11 10 11 11 10' - '11 10 10 04 13 00 00 13 04 11 11 11 11 11 11 11' - '11 11 0E 02 13 00 00 00 13 0E 11 12 12 12 12 12' - '11 12 0D 13 00 00 00 00 13 08 10 11 11 12 11 12' - '10 10 07 13 00 00 00 00 13 13 04 02 04 02 04 02' - '04 02 13 13 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 80 00 00 00 00 80 82 00 00 00 00 00' - '87 77 77 77 77 77 77 77 77 87 88 88 00 00 00 00' - '7F F7 88 87 87 77 77 77 77 77 2E 88 00 00 00 00' - '7F F8 88 88 78 78 77 88 77 77 77 78 00 00 00 00' - 'F7 F7 88 78 77 77 88 87 88 77 77 78 00 00 00 08' - '7F 77 88 88 87 78 88 78 88 77 77 77 00 00 00 00' - '7F FF 77 77 F7 77 77 77 77 77 77 78 00 00 00 00' - '7F FF FF FF FF FF FF FF FF 7F FF F8 00 00 00 04' - '7F 77 F7 FF 7F 7F 77 F7 F7 FF 77 F8 00 00 00 00' - 'F7 77 7F 77 7F 77 F7 F7 7F 77 77 77 00 00 00 00' - '77 77 77 77 F7 FF 7F 77 F7 77 77 F8 00 00 00 00' - '8F 77 77 FF 7F 77 F7 FF 7F 77 77 F8 00 00 00 00' - '8F 77 7F F7 F7 7F 7F 77 F7 7F 7F 78 00 00 00 00' - '8F 77 F7 77 7F 77 77 F7 7F 77 77 70 00 00 00 00' - '87 7F 77 7F 77 F7 7F 77 77 7F 77 70 00 00 00 00' - '07 77 F7 77 F7 77 77 77 77 77 7F 80 00 00 00 00' - '08 7F 77 F7 77 7F 77 77 77 77 77 80 00 00 00 00' - '08 F7 7F 7F 7F 77 F7 F7 F7 77 77 80 00 00 00 00' - '08 7F 77 F7 F7 FF 7F 7F 7F 77 F7 80 00 00 00 00' - '04 7F 7F 7F 7F 7F F7 F7 F7 F7 77 00 00 00 00 00' - '08 8F FF 77 F7 F7 7F 7F 7F 7F F8 00 00 00 00 00' - '00 77 77 FF 7F 7F F7 F7 FF 77 F8 00 00 00 00 00' - '00 8F 77 FF FF FF FF FF F7 7F 78 00 00 00 00 00' - '00 48 7F 77 F7 F7 7F 7F 77 F7 80 00 00 00 00 00' - '00 00 80 48 08 04 80 80 48 04 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' - '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' - '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '80 00 00 02 00 00 00 87 88 77 77 77 68 00 00 F7' - '88 87 87 87 78 00 08 77 87 77 87 87 77 00 00 FF' - 'F7 FF 7F 7F 77 00 00 77 77 F7 F7 F7 77 00 00 77' - '7F 77 F7 7F 78 00 00 87 F7 7F 77 F7 F8 00 00 8F' - '77 F7 77 77 78 00 00 87 7F 77 7F 77 78 00 00 47' - 'F7 F7 F7 F7 70 00 00 07 F7 FF 7F 7F 70 00 00 08' - '7F 7F F7 F7 80 00 00 00 04 08 00 40 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 11 00 11 11 11 00 22 22 22 00 33 33' - '33 00 44 44 44 00 55 55 55 00 66 66 66 00 77 77' - '77 00 7F 7F 7F 00 00 99 66 00 33 99 66 00 00 CC' - '66 00 33 CC 66 00 66 99 99 00 88 88 88 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 99 CC 99 00 99 FF' - '99 00 99 CC CC 00 CC CC CC 00 DD DD DD 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 54 00 56 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' - '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 50 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 64 72 69 76 65 2E 69 63 6F' - '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' - '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' - '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' - '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' - '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' - '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 1A 1A 02 03 03 04 03 03 04 03 03' - '04 03 03 04 03 03 03 04 03 03 03 03 04 03 03 04' - '03 03 03 04 01 1A 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 03 10 16 16 16 16 16 16 16 16 16' - '12 16 12 12 16 12 12 12 16 12 12 12 12 12 12 11' - '12 12 11 11 11 07 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 1A 1A 1A 0F 17 18 18 17 0F 0F 10 10 10 11' - '12 16 12 16 16 16 16 17 16 16 16 17 16 16 16 16' - '16 11 0B 0B 13 12 06 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 02 16 18 17 17 16 04 05 06 08 0F 0F' - '11 10 11 11 12 11 10 12 10 12 10 16 10 12 10 16' - '12 0D 0C 0A 0B 16 08 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 16 18 17 18 17 05 06 08 0F 10 10' - '10 11 11 12 12 10 10 12 0F 12 10 12 10 12 0F 12' - '16 10 15 14 0E 16 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 04 17 18 18 17 16 07 08 08 0F 0F 10' - '10 11 11 11 12 11 08 12 08 11 0F 12 0F 12 08 16' - '16 12 11 10 16 12 10 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 16 18 17 18 17 07 08 08 0F 0F 10' - '11 11 11 11 12 10 08 11 07 10 08 11 0F 11 07 12' - '12 16 12 16 12 16 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 17 18 18 17 17 07 07 08 0F 0F 0F' - '10 11 10 11 12 0F 07 11 06 10 07 12 07 11 06 16' - '16 12 16 12 12 16 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 16 18 18 18 17 11 11 11 11 11 12' - '11 12 12 12 12 12 11 12 11 12 12 12 11 12 11 12' - '16 12 16 12 16 12 10 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 17 18 18 18 18 17 18 18 18 17 17' - '18 17 17 17 17 17 17 17 17 17 16 17 16 16 16 16' - '16 16 12 16 12 16 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 16 18 19 19 18 19 19 18 18 18 19' - '18 19 18 19 18 18 18 18 18 18 18 18 18 18 18 18' - '18 18 18 18 17 17 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 17 19 17 17 18 17 17 18 17 17 17' - '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' - '18 17 18 17 19 18 0F 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 17 19 17 16 12 12 17 16 17 17 16' - '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' - '16 12 12 16 17 19 10 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 03 17 18 16 11 11 11 16 17 17 16 17' - '17 16 17 16 17 17 16 17 16 17 16 17 16 17 17 16' - '11 12 11 12 16 19 10 1A 1A 1A 00 00 00 00 00 00' - '00 00 1A 1A 1A 12 19 12 11 16 11 12 17 16 17 17' - '16 17 16 17 16 16 17 16 17 16 17 16 17 17 16 16' - '11 12 12 11 17 19 08 1A 1A 1A 00 00 00 00 00 00' - '00 00 00 1A 1A 11 18 16 16 16 16 16 16 17 16 16' - '17 17 17 18 18 18 18 18 17 18 17 17 16 16 17 16' - '16 16 12 16 16 18 06 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 08 18 17 16 16 16 16 16 16 17 18' - '18 17 17 17 17 17 17 17 17 17 17 18 18 18 16 16' - '16 16 16 16 17 17 04 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 06 18 16 16 16 16 16 17 18 18 17' - '16 17 17 17 16 17 17 16 17 17 16 17 17 17 18 17' - '16 16 16 16 17 12 03 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 05 17 16 16 16 16 16 18 17 16 16' - '16 17 16 16 16 17 16 16 17 16 16 17 16 16 17 18' - '16 16 16 16 17 11 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 03 12 17 16 16 16 18 16 16 17 16' - '17 16 17 16 16 16 16 16 16 16 16 16 16 16 16 16' - '18 16 16 16 17 0F 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 00 1A 1A 1A 10 17 16 16 17 16 17 16 16 16' - '16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16' - '16 17 12 16 17 06 1A 1A 1A 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 0F 17 17 16 17 16 16 17 16 17' - '16 17 16 16 16 16 16 16 12 16 12 16 16 16 12 16' - '16 16 16 16 17 05 1A 1A 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 06 17 16 16 16 17 16 16 16 16' - '16 16 16 16 17 16 16 12 16 12 16 12 16 12 16 12' - '16 12 16 16 17 03 1A 1A 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 05 17 16 17 16 16 17 16 17 16' - '17 16 17 16 16 17 16 16 16 12 16 12 12 12 16 12' - '12 16 12 16 11 03 1A 1A 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 03 16 17 16 16 17 16 17 16 17' - '16 17 16 16 17 16 16 17 16 17 16 16 16 16 12 16' - '16 11 12 16 11 1A 1A 1A 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 02 12 17 17 16 16 17 17 17 17' - '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 16' - '16 16 16 16 08 1A 1A 1A 00 00 00 00 00 00 00 00' - '00 00 00 00 1A 1A 1A 10 17 17 17 16 17 17 17 17' - '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' - '16 17 17 16 06 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 1A 08 17 17 18 17 16 17 17 17' - '17 17 18 17 17 18 17 17 17 17 17 17 18 17 17 16' - '17 17 17 12 04 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 1A 06 16 17 17 18 17 17 16 17' - '17 18 17 18 17 17 18 17 17 18 18 17 17 16 16 18' - '17 18 16 11 03 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 1A 04 12 18 17 17 18 17 17 16' - '17 17 17 17 18 17 17 18 17 17 17 17 16 17 18 17' - '18 17 17 10 1A 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 1A 02 11 18 18 18 18 18 18 18' - '17 17 17 17 17 17 17 17 17 17 17 17 18 18 17 18' - '17 18 17 0F 1A 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 1A 1A 11 17 17 12 12 17 18 18' - '18 18 18 18 18 17 18 18 18 18 18 18 18 17 16 12' - '17 18 16 08 1A 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 1A 1A 0F 17 16 11 12 11 18 18' - '18 18 18 18 18 18 18 18 18 18 18 18 18 17 11 12' - '11 18 16 07 1A 1A 1A 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 1A 1A 07 16 17 17 17 17 19 19' - '19 19 19 19 19 19 19 19 19 19 19 19 19 18 17 17' - '17 17 11 04 1A 1A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 1A 1A 02 0F 12 17 17 17 17 17' - '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' - '17 11 07 1A 1A 1A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 1A 1A 1A 1A 05 05 05 05 05 05' - '05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05' - '05 04 1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' - '1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF 00' - '00 00 00 7F 00 00 FC 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' - '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' - '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 16 00 00 00 34 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 35 00 00 00 18 00 00 00 04 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 05 00 00 00 69 00 00 00 C5 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F1 00 00 00 B1 00 00 00 5C 00 00 00 0D 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' - '00 9B 00 00 00 FF 00 00 00 FF 21 21 21 FF 2C 2C' - '2C FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2E 2C 2D FF 2E 2C 2D FF 13 13' - '13 FF 00 00 00 FF 00 00 00 F6 00 00 00 69 00 00' - '00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 54 00 00' - '00 FF 26 26 26 FF 90 90 90 FF CA CA CA FF CD CD' - 'CD FF CB CB CB FF CE CE CE FF CD CD CD FF CC CC' - 'CC FF CB CB CB FF C9 C9 C9 FF C7 C7 C7 FF C6 C6' - 'C6 FF C5 C5 C5 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2' - 'C2 FF C2 C2 C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1' - 'C1 FF BF BF BF FF BF BF BF FF BC BC BC FF BD BD' - 'BD FF BA BA BA FF BB BB BB FF B5 B5 B5 FF B3 B4' - 'B3 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' - 'AB FF 63 63 63 FF 09 09 09 FF 00 00 00 EF 00 00' - '00 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 03 00 00 00 AD 01 01' - '01 FF 8A 8A 8A FF EB EB EB FF E8 E8 E8 FF E7 E7' - 'E7 FF D5 D5 D5 FF 85 85 85 FF 88 88 88 FF 92 92' - '92 FF 98 98 98 FF A2 A2 A2 FF AD AD AD FF BA BA' - 'BA FF C0 C0 C0 FF C3 C3 C3 FF C6 C6 C6 FF CB CB' - 'CB FF CA CA CA FF CA CA CA FF D6 D6 D6 FF CA CA' - 'CA FF D3 D3 D3 FF CB CB CB FF D7 D7 D7 FF CC CC' - 'CC FF D4 D4 D4 FF C7 C7 C7 FF C8 C9 C9 FF C6 C2' - 'C4 FF 9D B3 A8 FF 20 A8 63 FF 1C A8 60 FF 90 AF' - 'A0 FF BF BB BD FF 4F 4F 4F FF 00 00 00 FF 00 00' - '00 81 00 00 00 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 15 00 00 00 F0 19 19' - '19 FF C7 C7 C7 FF EC EC EC FF E2 E2 E2 FF E6 E6' - 'E6 FF CB CB CB FF 3B 3B 3B FF 3F 3F 3F FF 56 56' - '56 FF 72 72 72 FF 87 87 87 FF 92 92 92 FF 9D 9D' - '9D FF A5 A5 A5 FF A8 A8 A8 FF AC AC AC FF B7 B7' - 'B7 FF A9 A9 A9 FF 9C 9C 9C FF BD BD BD FF 99 99' - '99 FF B7 B7 B7 FF A1 A1 A1 FF C3 C3 C3 FF A3 A3' - 'A3 FF BD BD BD FF 98 98 98 FF C5 C4 C4 FF C7 BF' - 'C3 FF 51 A7 7C FF 17 CE 71 FF 0A BF 61 FF 2F 99' - '64 FF C3 BD C0 FF 84 83 84 FF 01 01 01 FF 00 00' - '00 A3 00 00 00 0B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 30 00 00 00 FA 29 29' - '29 FF D1 D1 D1 FF EA EA EA FF E4 E4 E4 FF E7 E7' - 'E7 FF CD CD CD FF 47 47 47 FF 5F 5F 5F FF 79 79' - '79 FF 87 87 87 FF 8F 8F 8F FF 97 97 97 FF A0 A0' - 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF B9 B9' - 'B9 FF A4 A4 A4 FF 90 90 90 FF B8 B8 B8 FF 8A 8A' - '8A FF AF AF AF FF 94 94 94 FF BF BF BF FF 97 97' - '97 FF B7 B7 B7 FF 88 88 88 FF C4 C3 C3 FF C6 C3' - 'C5 FF 95 B2 A3 FF 91 D6 B4 FF 91 D8 B5 FF 83 AB' - '97 FF C4 C1 C3 FF 8E 8E 8E FF 01 01 01 FF 00 00' - '00 B7 00 00 00 13 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 34 00 00 00 F9 28 28' - '28 FF D1 D1 D1 FF EC EC EC FF E6 E6 E6 FF E7 E7' - 'E7 FF D1 D1 D1 FF 68 68 68 FF 74 74 74 FF 7E 7E' - '7E FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' - 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF BA BA' - 'BA FF 9F 9F 9F FF 83 83 83 FF B3 B3 B3 FF 7C 7C' - '7C FF A8 A8 A8 FF 87 87 87 FF BB BB BB FF 8A 8A' - '8A FF B2 B2 B2 FF 79 79 79 FF C2 C2 C2 FF C4 C4' - 'C4 FF C6 C3 C4 FF 99 AC A2 FF 96 AB A0 FF C2 BE' - 'C0 FF C4 C4 C4 FF 8D 8D 8D FF 01 01 01 FF 00 00' - '00 BA 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 28 28' - '28 FF D1 D1 D1 FF EE EE EE FF E7 E7 E7 FF E8 E8' - 'E8 FF D6 D6 D6 FF 70 70 70 FF 71 71 71 FF 7D 7D' - '7D FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' - 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF BB BB' - 'BB FF 98 98 98 FF 73 73 73 FF AD AD AD FF 6A 6A' - '6A FF A0 A0 A0 FF 78 78 78 FF B7 B7 B7 FF 7C 7C' - '7C FF AB AB AB FF 67 67 67 FF C2 C2 C2 FF C6 C6' - 'C6 FF C4 C3 C4 FF C7 C4 C5 FF C6 C2 C4 FF BF BF' - 'BF FF C5 C5 C5 FF 8D 8D 8D FF 01 01 01 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 27 27' - '27 FF D1 D1 D1 FF EF EF EF FF E9 E9 E9 FF EB EB' - 'EB FF D6 D6 D6 FF 6A 6A 6A FF 6C 6C 6C FF 78 78' - '78 FF 81 81 81 FF 8A 8A 8A FF 93 93 93 FF 9C 9C' - '9C FF A3 A3 A3 FF A6 A6 A6 FF AB AB AB FF B9 B9' - 'B9 FF 90 90 90 FF 66 66 66 FF A5 A5 A5 FF 5B 5B' - '5B FF 98 98 98 FF 6B 6B 6B FF B1 B1 B1 FF 70 70' - '70 FF A4 A4 A4 FF 58 58 58 FF C1 C1 C1 FF C8 C8' - 'C8 FF C5 C5 C5 FF C3 C3 C3 FF C2 C2 C2 FF C1 C1' - 'C1 FF C6 C6 C6 FF 8E 8E 8E FF 01 01 01 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 27 27' - '27 FF D2 D2 D2 FF F2 F2 F2 FF EB EB EB FF EA EA' - 'EA FF DF DF DF FF A7 A7 A7 FF A7 A7 A7 FF AB AB' - 'AB FF AE AE AE FF B0 B0 B0 FF B3 B3 B3 FF B6 B6' - 'B6 FF B9 B9 B9 FF B9 B9 B9 FF BA BA BA FF BD BD' - 'BD FF B7 B7 B7 FF B1 B1 B1 FF BE BE BE FF AF AF' - 'AF FF BA BA BA FF B1 B1 B1 FF BE BE BE FF B0 B0' - 'B0 FF BA BA BA FF AB AB AB FF C5 C5 C5 FF C8 C8' - 'C8 FF C6 C6 C6 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2' - 'C2 FF C9 C9 C9 FF 8E 8E 8E FF 00 00 00 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 26 26' - '26 FF D3 D3 D3 FF F3 F3 F3 FF EB EB EB FF EB EB' - 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF E9 E9' - 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' - 'E2 FF E1 E1 E1 FF DF DF DF FF DE DE DE FF DB DB' - 'DB FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' - 'D9 FF D6 D6 D6 FF D6 D6 D6 FF D2 D2 D2 FF D2 D2' - 'D2 FF CF CF CF FF D0 D0 D0 FF CB CB CB FF CA CA' - 'CA FF C9 C9 C9 FF C7 C7 C7 FF C4 C4 C4 FF C0 C0' - 'C0 FF CA CA CA FF 8E 8E 8E FF 00 00 00 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 26 26' - '26 FF D3 D3 D3 FF F7 F7 F7 FF F8 F8 F8 FF F6 F6' - 'F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5' - 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3' - 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F1 F1' - 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF EF EF EF FF EF EF EF FF EE EE' - 'EE FF EE EE EE FF ED ED ED FF ED ED ED FF ED ED' - 'ED FF EC EC EC FF EC EC EC FF EB EB EB FF E0 E0' - 'E0 FF D0 D0 D0 FF 8D 8D 8D FF 00 00 00 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 24 24' - '24 FF D6 D6 D6 FF FF FF FF FF E9 E9 E9 FF E1 E1' - 'E1 FF E2 E2 E2 FF E2 E2 E2 FF E0 E0 E0 FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E2 E2' - 'E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3 E3 FF F8 F8' - 'F8 FF EF EF EF FF 8C 8C 8C FF 00 00 00 FF 00 00' - '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 34 00 00 00 FA 24 24' - '24 FF DE DE DE FF F8 F8 F8 FF D9 D9 D9 FF C4 C4' - 'C4 FF BB BB BB FF BF BF BF FF D8 D8 D8 FF DA DA' - 'DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF DB DB DB FF CF CF' - 'CF FF BC BC BC FF BB BB BB FF D1 D1 D1 FF DE DE' - 'DE FF FF FF FF FF 9A 9A 9A FF 00 00 00 FF 00 00' - '00 BA 00 00 00 14 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 00 00 00 F7 1F 1F' - '1F FF DA DA DA FF F3 F3 F3 FF C6 C6 C6 FF A9 A9' - 'A9 FF B7 B7 B7 FF B0 B0 B0 FF C3 C3 C3 FF DA DA' - 'DA FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D9 D9 D9 FF D2 D2 D2 FF A8 A8' - 'A8 FF B6 B6 B6 FF B1 B1 B1 FF B5 B5 B5 FF D8 D8' - 'D8 FF FC FC FC FF 9C 9C 9C FF 00 00 00 FF 00 00' - '00 AE 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 07 00 00 00 D0 05 05' - '05 FF C2 C2 C2 FF F6 F6 F6 FF BC BC BC FF B2 B2' - 'B2 FF C3 C3 C3 FF AB AB AB FF BB BB BB FF D8 D8' - 'D8 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' - 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' - 'D7 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D5 D5' - 'D5 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4' - 'D4 FF D5 D5 D5 FF D7 D7 D7 FF C9 C9 C9 FF A6 A6' - 'A6 FF C3 C3 C3 FF B3 B3 B3 FF AD AD AD FF D6 D6' - 'D6 FF F5 F5 F5 FF 76 76 76 FF 00 00 00 FF 00 00' - '00 8C 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' - '00 FF A4 A4 A4 FF F4 F4 F4 FF CF CF CF FF C5 C5' - 'C5 FF D2 D2 D2 FF BF BF BF FF C9 C9 C9 FF D3 D3' - 'D3 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF DD DD' - 'DD FF E1 E1 E1 FF E3 E3 E3 FF E6 E6 E6 FF EA EA' - 'EA FF ED ED ED FF ED ED ED FF EB EB EB FF E7 E7' - 'E7 FF E4 E4 E4 FF E2 E2 E2 FF DE DE DE FF D4 D4' - 'D4 FF D0 D0 D0 FF D2 D2 D2 FF D3 D3 D3 FF C5 C5' - 'C5 FF D0 D0 D0 FF C2 C2 C2 FF BF BF BF FF D9 D9' - 'D9 FF E8 E8 E8 FF 56 56 56 FF 00 00 00 FF 00 00' - '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 73 00 00' - '00 FF 7E 7E 7E FF EF EF EF FF D1 D1 D1 FF CF CF' - 'CF FF CB CB CB FF CF CF CF FF D1 D1 D1 FF CE CE' - 'CE FF CF CF CF FF DF DF DF FF F0 F0 F0 FF EC EC' - 'EC FF E1 E1 E1 FF DE DE DE FF DD DD DD FF DC DC' - 'DC FF DB DB DB FF DB DB DB FF DC DC DC FF DD DD' - 'DD FF DE DE DE FF E1 E1 E1 FF EC EC EC FF F1 F1' - 'F1 FF E1 E1 E1 FF D1 D1 D1 FF CE CE CE FF D0 D0' - 'D0 FF CB CB CB FF CE CE CE FF D1 D1 D1 FF D9 D9' - 'D9 FF D4 D4 D4 FF 3F 3F 3F FF 00 00 00 FF 00 00' - '00 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' - '00 FF 59 59 59 FF E9 E9 E9 FF D0 D0 D0 FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CA CA CA FF D6 D6' - 'D6 FF ED ED ED FF E6 E6 E6 FF DC DC DC FF D4 D4' - 'D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D5 D5 D5 FF D5 D5 D5 FF DB DB' - 'DB FF E4 E4 E4 FF ED ED ED FF DA DA DA FF CA CA' - 'CA FF CD CD CD FF CD CD CD FF CB CB CB FF DF DF' - 'DF FF B8 B8 B8 FF 22 22 22 FF 00 00 00 FB 00 00' - '00 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' - '00 FE 40 40 40 FF D7 D7 D7 FF D2 D2 D2 FF CA CA' - 'CA FF CB CB CB FF CA CA CA FF D4 D4 D4 FF E9 E9' - 'E9 FF DC DC DC FF D0 D0 D0 FF D1 D1 D1 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' - 'D1 FF D0 D0 D0 FF D8 D8 D8 FF EA EA EA FF D8 D8' - 'D8 FF C9 C9 C9 FF CA CA CA FF C9 C9 C9 FF E0 E0' - 'E0 FF A0 A0 A0 FF 08 08 08 FF 00 00 00 EB 00 00' - '00 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 25 00 00' - '00 F8 22 22 22 FF B7 B7 B7 FF DB DB DB FF CA CA' - 'CA FF CB CB CB FF CE CE CE FF E4 E4 E4 FF D4 D4' - 'D4 FF CF CF CF FF D1 D1 D1 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CD CD' - 'CD FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CC CC CC FF D0 D0 D0 FF E2 E2' - 'E2 FF CF CF CF FF C7 C7 C7 FF C9 C9 C9 FF E2 E2' - 'E2 FF 80 80 80 FF 00 00 00 FF 00 00 00 C2 00 00' - '00 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 E1 07 07 07 FF 9F 9F 9F FF DD DD DD FF CC CC' - 'CC FF CD CD CD FF DB DB DB FF D6 D6 D6 FF CE CE' - 'CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CC CC' - 'CC FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF C8 C8 C8 FF CF CF' - 'CF FF DA DA DA FF C7 C7 C7 FF C9 C9 C9 FF E2 E2' - 'E2 FF 5A 5A 5A FF 00 00 00 FF 00 00 00 94 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 B2 00 00 00 FF 83 83 83 FF DD DD DD FF CF CF' - 'CF FF D1 D1 D1 FF DB DB DB FF D1 D1 D1 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' - 'CF FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C7 C7' - 'C7 FF D3 D3 D3 FF C8 C8 C8 FF C9 C9 C9 FF DE DE' - 'DE FF 42 42 42 FF 00 00 00 FF 00 00 00 6C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 5F 5F 5F FF DC DC DC FF D1 D1' - 'D1 FF D2 D2 D2 FF D4 D4 D4 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D0 D0 D0 FF C8 C8 C8 FF C3 C3 C3 FF C3 C3' - 'C3 FF C3 C3 C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF C7 C7 C7 FF C5 C5 C5 FF CB CB CB FF CC CC' - 'CC FF 2D 2D 2D FF 00 00 00 F8 00 00 00 40 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4B 00 00 00 FE 41 41 41 FF D8 D8 D8 FF D4 D4' - 'D4 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CD CD CD FF C7 C7' - 'C7 FF C4 C4 C4 FF C2 C2 C2 FF C1 C1 C1 FF C0 C0' - 'C0 FF C1 C1 C1 FF C1 C1 C1 FF C1 C1 C1 FF C2 C2' - 'C2 FF BF BF BF FF C0 C0 C0 FF CE CE CE FF B2 B2' - 'B2 FF 1A 1A 1A FF 00 00 00 E5 00 00 00 28 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1A 00 00 00 F2 2C 2C 2C FF CC CC CC FF D6 D6' - 'D6 FF D5 D5 D5 FF CC CC CC FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D6 D6' - 'D6 FF D5 D5 D5 FF D3 D3 D3 FF CF CF CF FF CC CC' - 'CC FF C9 C9 C9 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2' - 'C2 FF B3 B3 B3 FF BD BD BD FF D0 D0 D0 FF 99 99' - '99 FF 09 09 09 FF 00 00 00 CF 00 00 00 19 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 09 00 00 00 D8 18 18 18 FF B0 B0 B0 FF DB DB' - 'DB FF DB DB DB FF D0 D0 D0 FF D2 D2 D2 FF DB DB' - 'DB FF D9 D9 D9 FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DB DB DB FF DB DB' - 'DB FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF CF CF' - 'CF FF C5 C5 C5 FF CC CC CC FF CA CA CA FF 7A 7A' - '7A FF 02 02 02 FF 00 00 00 B8 00 00 00 0A 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 BF 08 08 08 FF 97 97 97 FF DC DC' - 'DC FF DF DF DF FF DC DC DC FF CE CE CE FF D6 D6' - 'D6 FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DE DE DE FF D8 D8 D8 FF CE CE' - 'CE FF DD DD DD FF DC DC DC FF C6 C6 C6 FF 53 53' - '53 FF 00 00 00 FF 00 00 00 A0 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 A4 00 00 00 FF 77 77 77 FF D3 D3' - 'D3 FF E2 E2 E2 FF E1 E1 E1 FF DE DE DE FF CE CE' - 'CE FF D7 D7 D7 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' - 'E1 FF E1 E1 E1 FF D9 D9 D9 FF CD CD CD FF DA DA' - 'DA FF E3 E3 E3 FF D9 D9 D9 FF BB BB BB FF 39 39' - '39 FF 00 00 00 FF 00 00 00 7E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 89 00 00 00 FF 4B 4B 4B FF C9 C9' - 'C9 FF E5 E5 E5 FF E3 E3 E3 FF E4 E4 E4 FF E1 E1' - 'E1 FF D7 D7 D7 FF D2 D2 D2 FF DA DA DA FF E4 E4' - 'E4 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF DC DC' - 'DC FF D2 D2 D2 FF D6 D6 D6 FF E0 E0 E0 FF E4 E4' - 'E4 FF E6 E6 E6 FF D6 D6 D6 FF A8 A8 A8 FF 20 20' - '20 FF 00 00 00 FD 00 00 00 4E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 62 00 00 00 FF 35 35 35 FF BD BD' - 'BD FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7' - 'E7 FF E7 E7 E7 FF DF DF DF FF D2 D2 D2 FF D3 D3' - 'D3 FF DE DE DE FF E3 E3 E3 FF E3 E3 E3 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3' - 'E3 FF E3 E3 E3 FF DE DE DE FF D4 D4 D4 FF D1 D1' - 'D1 FF DD DD DD FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' - 'E6 FF E8 E8 E8 FF D4 D4 D4 FF 9A 9A 9A FF 0B 0B' - '0B FF 00 00 00 ED 00 00 00 2C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2D 00 00 00 F9 1E 1E 1E FF AB AB' - 'AB FF E4 E4 E4 FF ED ED ED FF E7 E7 E7 FF E6 E6' - 'E6 FF EC EC EC FF EB EB EB FF EA EA EA FF E4 E4' - 'E4 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DD DD' - 'DD FF DC DC DC FF DC DC DC FF DD DD DD FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' - 'E9 FF EC EC EC FF EA EA EA FF E5 E5 E5 FF EB EB' - 'EB FF EB EB EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00' - '00 FF 00 00 00 C3 00 00 00 17 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 09 00 00 00 DD 08 08 08 FF 99 99' - '99 FF E4 E4 E4 FF DF DF DF FF BD BD BD FF C1 C1' - 'C1 FF D6 D6 D6 FF EC EC EC FF ED ED ED FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EC EC' - 'EC FF EB EB EB FF EB EB EB FF EC EC EC FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EE EE' - 'EE FF E4 E4 E4 FF C2 C2 C2 FF BE BE BE FF D1 D1' - 'D1 FF EC EC EC FF D4 D4 D4 FF 75 75 75 FF 00 00' - '00 FF 00 00 00 9C 00 00 00 06 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 AE 00 00 00 FF 8D 8D' - '8D FF E0 E0 E0 FF C4 C4 C4 FF B2 B2 B2 FF B8 B8' - 'B8 FF B2 B2 B2 FF EB EB EB FF F1 F1 F1 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' - 'F3 FF D5 D5 D5 FF B0 B0 B0 FF B6 B6 B6 FF B7 B7' - 'B7 FF EB EB EB FF CD CD CD FF 61 61 61 FF 00 00' - '00 FF 00 00 00 85 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 64 64' - '64 FF CE CE CE FF DD DD DD FF DC DC DC FF D5 D5' - 'D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' - 'FA FF F2 F2 F2 FF DF DF DF FF D8 D8 D8 FF DC DC' - 'DC FF D7 D7 D7 FF B0 B0 B0 FF 34 34 34 FF 00 00' - '00 FF 00 00 00 67 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 44 00 00 00 FF 19 19' - '19 FF 80 80 80 FF BE BE BE FF D3 D3 D3 FF D7 D7' - 'D7 FF DB DB DB FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D7 D7 D7 FF CD CD' - 'CD FF B0 B0 B0 FF 5D 5D 5D FF 06 06 06 FF 00 00' - '00 ED 00 00 00 2B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 9C 00 00' - '00 FF 0C 0C 0C FF 3D 3D 3D FF 49 49 49 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' - '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 FF 00 00' - '00 5C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' - '00 7F 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 5C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2C 00 00 00 7E 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 70 00 00 00 1A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF 00 00 00 00 7F 00 00 FC 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 15 00 00 00 54 00 00 00 63 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 63 00 00 00 50 00 00 00 14 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 33 00 00' - '00 D7 0D 0D 0D FF 1B 1B 1B FF 1C 1C 1C FF 1E 1E' - '1E FF 1D 1D 1D FF 1D 1D 1D FF 1C 1C 1C FF 1B 1B' - '1B FF 1B 1B 1B FF 1B 1B 1B FF 1A 1A 1A FF 1A 1A' - '1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A' - '1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A 1A FF 20 1C' - '1E FF 22 1B 1F FF 09 09 09 FF 00 00 00 C3 00 00' - '00 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 07 00 00 00 C9 40 40' - '40 FF BA BA BA FF CB CB CB FF BE BE BE FF B3 B3' - 'B3 FF B4 B4 B4 FF B4 B4 B4 FF B7 B7 B7 FF BB BB' - 'BB FF BB BB BB FF BB BB BB FF BC BC BC FF BE BE' - 'BE FF BD BD BD FF BC BC BC FF BB BB BB FF BA BA' - 'BA FF BA BA BA FF B4 B4 B4 FF B1 AE AF FF 8C A4' - '98 FF 80 A5 93 FF 90 91 91 FF 21 21 21 FF 00 00' - '00 AB 00 00 00 07 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 3D 08 08 08 FD B7 B7' - 'B7 FF F2 F2 F2 FF EE EE EE FF AF AF AF FF 51 51' - '51 FF 6E 6E 6E FF 89 89 89 FF 9A 9A 9A FF AB AB' - 'AB FF B3 B3 B3 FF BC BC BC FF B5 B5 B5 FF B5 B5' - 'B5 FF BC BC BC FF BD BD BD FF BE BE BE FF B7 B7' - 'B7 FF C0 C0 C0 FF C4 C1 C3 FF B7 BF BA FF 2A BF' - '75 FF 0E C0 67 FF 8C B8 A2 FF 80 79 7C FF 00 00' - '00 EC 00 00 00 25 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 58 19 19 19 FF CE CE' - 'CE FF EB EB EB FF EB EB EB FF AA AA AA FF 56 56' - '56 FF 7A 7A 7A FF 8C 8C 8C FF 96 96 96 FF A2 A2' - 'A2 FF A9 A9 A9 FF B4 B4 B4 FF A1 A1 A1 FF 97 97' - '97 FF A1 A1 A1 FF A5 A5 A5 FF A5 A5 A5 FF 9B 9B' - '9B FF A7 A7 A7 FF B3 B1 B2 FF BC C1 BE FF 87 C6' - 'A6 FF 85 CC A8 FF A6 BC B1 FF 94 90 92 FF 02 02' - '02 F9 00 00 00 36 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 5A 18 18 18 FF CC CC' - 'CC FF ED ED ED FF EC EC EC FF B9 B9 B9 FF 6D 6D' - '6D FF 7D 7D 7D FF 8B 8B 8B FF 96 96 96 FF A2 A2' - 'A2 FF A9 A9 A9 FF B6 B6 B6 FF 96 96 96 FF 82 82' - '82 FF 8E 8E 8E FF 93 93 93 FF 94 94 94 FF 86 86' - '86 FF 95 95 95 FF A6 A6 A6 FF C8 C8 C8 FF C2 C0' - 'C1 FF BF BD BE FF C9 C6 C7 FF 8E 8E 8E FF 01 01' - '01 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF CD CD' - 'CD FF F0 F0 F0 FF ED ED ED FF BF BF BF FF 77 77' - '77 FF 85 85 85 FF 91 91 91 FF 9A 9A 9A FF A4 A4' - 'A4 FF AA AA AA FF B5 B5 B5 FF 97 97 97 FF 83 83' - '83 FF 8D 8D 8D FF 92 92 92 FF 93 93 93 FF 86 86' - '86 FF 93 93 93 FF A7 A7 A7 FF CA CA CA FF C4 C3' - 'C4 FF C3 C2 C2 FF C8 C8 C8 FF 8E 8E 8E FF 00 00' - '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF CE CE' - 'CE FF F2 F2 F2 FF EC EC EC FF E6 E6 E6 FF DC DC' - 'DC FF DB DB DB FF DA DA DA FF DA DA DA FF D9 D9' - 'D9 FF D8 D8 D8 FF D7 D7 D7 FF D4 D4 D4 FF D4 D4' - 'D4 FF D2 D2 D2 FF D0 D0 D0 FF CF CF CF FF CC CC' - 'CC FF CB CB CB FF CB CB CB FF CC CC CC FF CA CA' - 'CA FF C7 C7 C7 FF C9 C9 C9 FF 8D 8D 8D FF 00 00' - '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF D0 D0' - 'D0 FF FF FF FF FF F8 F8 F8 FF F8 F8 F8 FF F9 F9' - 'F9 FF F8 F8 F8 FF F7 F7 F7 FF F7 F7 F7 FF F6 F6' - 'F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5 F5 FF F5 F5' - 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3' - 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1 F1 FF F2 F2' - 'F2 FF F3 F3 F3 FF E8 E8 E8 FF 8D 8D 8D FF 00 00' - '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 5B 17 17 17 FF D7 D7' - 'D7 FF F4 F4 F4 FF DB DB DB FF D8 D8 D8 FF DD DD' - 'DD FF DF DF DF FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' - 'DF FF DF DF DF FF E0 E0 E0 FF DD DD DD FF D8 D8' - 'D8 FF E0 E0 E0 FF FB FB FB FF 9C 9C 9C FF 00 00' - '00 FA 00 00 00 38 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 51 11 11 11 FF D3 D3' - 'D3 FF D9 D9 D9 FF AD AD AD FF B0 B0 B0 FF BE BE' - 'BE FF D9 D9 D9 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D7 D7' - 'D7 FF D9 D9 D9 FF D3 D3 D3 FF AF AF AF FF B1 B1' - 'B1 FF B8 B8 B8 FF ED ED ED FF A0 A0 A0 FF 00 00' - '00 F7 00 00 00 2E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2B 00 00 00 F8 B3 B3' - 'B3 FF DC DC DC FF B9 B9 B9 FF BA BA BA FF BC BC' - 'BC FF D5 D5 D5 FF D3 D3 D3 FF D4 D4 D4 FF D8 D8' - 'D8 FF DF DF DF FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' - 'E4 FF E3 E3 E3 FF DF DF DF FF D9 D9 D9 FF D4 D4' - 'D4 FF D3 D3 D3 FF CF CF CF FF BA BA BA FF B8 B8' - 'B8 FF B8 B8 B8 FF E9 E9 E9 FF 7C 7C 7C FF 00 00' - '00 DE 00 00 00 17 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0C 00 00 00 E2 89 89' - '89 FF E5 E5 E5 FF CE CE CE FF D0 D0 D0 FF D0 D0' - 'D0 FF D1 D1 D1 FF DE DE DE FF E5 E5 E5 FF E5 E5' - 'E5 FF E2 E2 E2 FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF E2 E2 E2 FF E6 E6 E6 FF E5 E5' - 'E5 FF DF DF DF FF D2 D2 D2 FF CF CF CF FF CF CF' - 'CF FF D0 D0 D0 FF E6 E6 E6 FF 54 54 54 FF 00 00' - '00 BC 00 00 00 07 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 BB 64 64' - '64 FF E2 E2 E2 FF CB CB CB FF CB CB CB FF CE CE' - 'CE FF E2 E2 E2 FF E0 E0 E0 FF D7 D7 D7 FF D3 D3' - 'D3 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4' - 'D4 FF D4 D4 D4 FF D4 D4 D4 FF D3 D3 D3 FF D7 D7' - 'D7 FF DF DF DF FF E4 E4 E4 FF D1 D1 D1 FF CB CB' - 'CB FF CF CF CF FF D7 D7 D7 FF 34 34 34 FF 00 00' - '00 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 93 3E 3E' - '3E FF DB DB DB FF CC CC CC FF CC CC CC FF DC DC' - 'DC FF D7 D7 D7 FF CF CF CF FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CC CC CC FF D3 D3 D3 FF DC DC DC FF C9 C9' - 'C9 FF CF CF CF FF C2 C2 C2 FF 1A 1A 1A FF 00 00' - '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 6B 21 21' - '21 FF C9 C9 C9 FF D2 D2 D2 FF D3 D3 D3 FF D7 D7' - 'D7 FF CF CF CF FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF CA CA CA FF C7 C7' - 'C7 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' - 'C8 FF C8 C8 C8 FF C7 C7 C7 FF CF CF CF FF CC CC' - 'CC FF D0 D0 D0 FF A9 A9 A9 FF 04 04 04 FF 00 00' - '00 4D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 44 0B 0B' - '0B FF B1 B1 B1 FF D8 D8 D8 FF D2 D2 D2 FF D2 D2' - 'D2 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D2 D2 D2 FF D1 D1 D1 FF C9 C9' - 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C5 C5 C5 FF C5 C5' - 'C5 FF D2 D2 D2 FF 86 86 86 FF 00 00 00 F3 00 00' - '00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00' - '00 F4 93 93 93 FF DF DF DF FF D2 D2 D2 FF D2 D2' - 'D2 FF D5 D5 D5 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4' - 'D4 FF D4 D4 D4 FF D4 D4 D4 FF D5 D5 D5 FF D5 D5' - 'D5 FF D2 D2 D2 FF CD CD CD FF C7 C7 C7 FF C3 C3' - 'C3 FF C2 C2 C2 FF C2 C2 C2 FF BE BE BE FF BC BC' - 'BC FF D0 D0 D0 FF 67 67 67 FF 00 00 00 D9 00 00' - '00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0B 00 00' - '00 DE 75 75 75 FF DE DE DE FF D7 D7 D7 FF D1 D1' - 'D1 FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF DA DA DA FF DA DA DA FF DA DA DA FF D8 D8' - 'D8 FF D6 D6 D6 FF D5 D5 D5 FF C7 C7 C7 FF C5 C5' - 'C5 FF CD CD CD FF 4B 4B 4B FF 00 00 00 BD 00 00' - '00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 B7 53 53 53 FF D9 D9 D9 FF E1 E1 E1 FF D5 D5' - 'D5 FF D5 D5 D5 FF DF DF DF FF DF DF DF FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' - 'DF FF E0 E0 E0 FF D7 D7 D7 FF D6 D6 D6 FF DE DE' - 'DE FF C3 C3 C3 FF 2C 2C 2C FF 00 00 00 9A 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 90 31 31 31 FF CB CB CB FF E5 E5 E5 FF E4 E4' - 'E4 FF DA DA DA FF D7 D7 D7 FF DD DD DD FF E2 E2' - 'E2 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E2 E2 E2 FF DE DE' - 'DE FF D7 D7 D7 FF D9 D9 D9 FF E4 E4 E4 FF DF DF' - 'DF FF AB AB AB FF 17 17 17 FF 00 00 00 73 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 67 1A 1A 1A FF B3 B3 B3 FF E8 E8 E8 FF EA EA' - 'EA FF EA EA EA FF E5 E5 E5 FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF DD DD DD FF DC DC DC FF DD DD' - 'DD FF E5 E5 E5 FF E9 E9 E9 FF EC EC EC FF DF DF' - 'DF FF 95 95 95 FF 04 04 04 FF 00 00 00 4D 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 41 07 07 07 FE 9F 9F 9F FF E8 E8 E8 FF CD CD' - 'CD FF CB CB CB FF E7 E7 E7 FF EF EF EF FF ED ED' - 'ED FF EA EA EA FF E9 E9 E9 FF E7 E7 E7 FF E7 E7' - 'E7 FF E8 E8 E8 FF EA EA EA FF EC EC EC FF F0 F0' - 'F0 FF DB DB DB FF C6 C6 C6 FF DC DC DC FF E1 E1' - 'E1 FF 78 78 78 FF 00 00 00 F4 00 00 00 29 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1E 00 00 00 F4 83 83 83 FF E0 E0 E0 FF C9 C9' - 'C9 FF C6 C6 C6 FF EA EA EA FF FA FA FA FF F8 F8' - 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' - 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8 F8 FF FB FB' - 'FB FF D9 D9 D9 FF C4 C4 C4 FF D1 D1 D1 FF D2 D2' - 'D2 FF 50 50 50 FF 00 00 00 DA 00 00 00 15 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 BB 24 24 24 FF 98 98 98 FF CF CF' - 'CF FF D2 D2 D2 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D2 D2 D2 FF C8 C8 C8 FF 7C 7C' - '7C FF 0D 0D 0D FF 00 00 00 9A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 31 00 00 00 DF 0F 0F 0F FF 29 29' - '29 FF 29 29 29 FF 28 28 28 FF 28 28 28 FF 28 28' - '28 FF 28 28 28 FF 28 28 28 FF 28 28 28 FF 28 28' - '28 FF 28 28 28 FF 28 28 28 FF 28 28 28 FF 28 28' - '28 FF 28 28 28 FF 2A 2A 2A FF 26 26 26 FF 08 08' - '08 FF 00 00 00 C8 00 00 00 1D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 14 00 00 00 62 00 00' - '00 87 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 86 00 00' - '00 55 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' - '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' - '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 11 04 04' - '04 8A 16 16 16 A8 1B 1B 1B A8 18 18 18 A8 16 16' - '16 A8 15 15 15 A8 16 16 16 A8 15 15 15 A8 15 15' - '15 A8 14 13 14 A8 19 12 16 A8 05 03 04 84 00 00' - '00 0F 00 00 00 00 00 00 00 00 05 05 05 83 9B 9B' - '9B FF C1 C1 C1 FF 83 83 83 FF 9A 9A 9A FF AD AD' - 'AD FF B2 B2 B2 FF B3 B3 B3 FF B5 B5 B5 FF B2 B1' - 'B2 FF AC B2 AF FF 59 B0 84 FF 5B 6C 64 FF 04 01' - '03 71 00 00 00 00 00 00 00 00 13 13 13 B3 DC DC' - 'DC FF CB CB CB FF 65 65 65 FF 8A 8A 8A FF A7 A7' - 'A7 FF AB AB AB FF 95 95 95 FF A2 A2 A2 FF 95 94' - '95 FF BA BF BC FF 8F CC AD FF 93 A1 9A FF 09 06' - '07 95 00 00 00 00 00 00 00 00 13 13 13 B2 D7 D7' - 'D7 FF DE DE DE FF A1 A1 A1 FF AC AC AC FF BA BA' - 'BA FF B7 B7 B7 FF A2 A2 A2 FF A9 A9 A9 FF 9D 9D' - '9D FF C2 C1 C1 FF CF C9 CC FF A2 A0 A1 FF 06 06' - '06 93 00 00 00 00 00 00 00 00 14 14 14 B3 D9 D9' - 'D9 FF ED ED ED FF EA EA EA FF E8 E8 E8 FF E5 E5' - 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E4 E4 E4 FF E4 E4' - 'E4 FF DF DF DF FF E3 E3 E3 FF B2 B2 B2 FF 04 05' - '05 94 00 00 00 00 00 00 00 00 11 11 11 A5 C6 C6' - 'C6 FF BC BC BC FF CA CA CA FF D9 D9 D9 FF DA DA' - 'DA FF DA DA DA FF DB DB DB FF DA DA DA FF DA DA' - 'DA FF C6 C6 C6 FF C5 C5 C5 FF B4 B4 B4 FF 04 04' - '04 8B 00 00 00 00 00 00 00 00 04 04 04 7B A8 A8' - 'A8 FF CE CE CE FF CF CF CF FF DC DC DC FF DD DD' - 'DD FF DE DE DE FF DE DE DE FF DE DE DE FF DC DC' - 'DC FF CF CF CF FF D4 D4 D4 FF 91 91 91 FF 00 00' - '00 69 00 00 00 00 00 00 00 00 00 00 00 53 85 85' - '85 FF DB DB DB FF D7 D7 D7 FF D3 D3 D3 FF D0 D0' - 'D0 FF CE CE CE FF CD CD CD FF CE CE CE FF D0 D0' - 'D0 FF D6 D6 D6 FF D9 D9 D9 FF 6E 6E 6E FE 00 00' - '00 43 00 00 00 00 00 00 00 00 00 00 00 2E 64 64' - '64 FA DD DD DD FF D3 D3 D3 FF D0 D0 D0 FF D1 D1' - 'D1 FF CF CF CF FF C8 C8 C8 FF C4 C4 C4 FF C4 C4' - 'C4 FF C5 C5 C5 FF CF CF CF FF 4D 4D 4D F3 00 00' - '00 20 00 00 00 00 00 00 00 00 00 00 00 0E 42 42' - '42 E8 D7 D7 D7 FF D6 D6 D6 FF D9 D9 D9 FF D8 D8' - 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D4 D4 D4 FF D3 D3' - 'D3 FF CD CD CD FF C5 C5 C5 FF 2C 2C 2C D8 00 00' - '00 0A 00 00 00 00 00 00 00 00 00 00 00 02 22 22' - '22 C5 D1 D1 D1 FF E3 E3 E3 FF DC DC DC FF DF DF' - 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF DE DE' - 'DE FF E5 E5 E5 FF C0 C0 C0 FF 11 11 11 B6 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 08 08' - '08 A1 BE BE BE FF E1 E1 E1 FF EA EA EA FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF E5 E5' - 'E5 FF E5 E5 E5 FF A3 A3 A3 FF 01 01 01 93 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 74 78 78 78 FF C7 C7 C7 FF D9 D9 D9 FF DE DE' - 'DE FF DD DD DD FF DD DD DD FF DF DF DF FF D4 D4' - 'D4 FF C7 C7 C7 FF 60 60 60 FF 00 00 00 65 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 11 04 04 04 94 1D 1D 1D CC 1C 1C 1C CC 1C 1C' - '1C CC 1C 1C 1C CC 1C 1C 1C CC 1C 1C 1C CC 1D 1D' - '1D CC 1B 1B 1B CB 02 02 02 88 00 00 00 0C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 FF FF 00 00' -} */ - -/* BINRES netdrive.ico */ -9 ICON netdrive.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 8E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 02 02 02 00 04 04 04 00 05 06 06 00 06 06' - '06 00 09 09 09 00 0A 0A 0A 00 0C 0C 0C 00 12 12' - '12 00 14 14 14 00 15 15 15 00 16 16 16 00 1D 1D' - '1D 00 1F 1F 1F 00 21 21 21 00 22 22 22 00 23 23' - '23 00 24 24 24 00 25 25 25 00 26 26 26 00 38 38' - '38 00 39 39 39 00 3B 3B 3B 00 00 67 67 00 43 43' - '43 00 46 46 46 00 4A 4A 4A 00 54 4C 50 00 53 53' - '53 00 55 55 55 00 56 56 56 00 58 58 58 00 59 59' - '59 00 5A 58 59 00 5A 5A 5A 00 5B 5B 5B 00 5C 5C' - '5C 00 5D 5D 5D 00 5E 5E 5E 00 65 58 5F 00 60 60' - '60 00 61 61 61 00 62 62 62 00 64 64 64 00 67 67' - '67 00 69 69 69 00 71 71 71 00 72 72 72 00 73 73' - '73 00 75 75 75 00 78 78 78 00 7A 7A 7A 00 7B 7B' - '7B 00 7C 7C 7C 00 7F 7F 7F 00 24 A7 64 00 3C AD' - '74 00 25 DC 7F 00 7D AA 94 00 18 FF FF 00 56 D8' - 'D8 00 81 81 81 00 83 83 83 00 89 89 89 00 8A 8A' - '8A 00 8B 8B 8B 00 8F 8F 8F 00 91 89 8C 00 90 90' - '90 00 91 91 91 00 94 94 94 00 95 95 95 00 97 97' - '97 00 99 99 99 00 9A 9A 9A 00 9C 9C 9C 00 9D 9D' - '9D 00 9E 9E 9E 00 9F 9F 9F 00 A0 91 91 00 94 B6' - 'A4 00 93 BD A9 00 A0 A0 A0 00 A1 A1 A1 00 A3 A3' - 'A3 00 A4 A4 A4 00 A5 A5 A5 00 A8 A8 A8 00 A9 A9' - 'A9 00 AA AA AA 00 AC AC AC 00 AD AD AD 00 AE AE' - 'AE 00 AF AF AF 00 B7 AF AF 00 AD B9 B3 00 B0 B0' - 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' - 'B4 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B9 B9' - 'B9 00 BC BC BC 00 BD BD BD 00 BE BE BE 00 BF BF' - 'BF 00 89 CF CF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C0' - 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C2 00 C5 C2' - 'C4 00 C4 C4 C4 00 C5 C5 C5 00 C6 C5 C6 00 C6 C6' - 'C6 00 C8 C3 C5 00 CC C4 C8 00 C8 C8 C8 00 C9 C9' - 'C9 00 CB C9 CA 00 CA CA CA 00 CB CB CB 00 CC CC' - 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D2 C1' - 'CA 00 D3 C8 CD 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' - 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' - 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' - 'DA 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' - 'DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' - 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' - 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' - 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' - 'EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2' - 'F2 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7' - 'F7 00 F8 F8 F8 00 F9 F9 F9 00 FC FC FC 00 FD FD' - 'FD 00 FF FF FF 00 00 00 00 00 62 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 6E 65 74 64 72 69 76 65 2E' - '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 B2 B2' - 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 17 17 B2' - 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 62 62' - '62 62 62 62 62 62 62 62 62 62 62 5E 6D 3B 3B 6D' - '5E 62 62 62 62 62 62 62 62 62 62 62 62 62 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 3C 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 4F 4F 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 0D 0D B2' - 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 00 00 00 00 00 00' - '00 B2 B2 09 26 26 2C 2B 2A 28 26 25 24 1E 1D 22' - '20 1F 1F 1F 1E 21 27 1B 05 B2 B2 00 00 00 00 00' - '00 B2 09 6E AA A0 58 64 68 6F 86 88 8C 8D 92 92' - '91 93 90 8E 82 79 38 51 43 03 B2 00 00 00 00 00' - '00 B2 1E AC 9C 9A 0C 1A 33 41 4C 54 5D 59 4E 4B' - '59 66 56 48 85 3A 39 37 84 13 B2 00 00 00 00 00' - '00 B2 25 A8 9D 99 1C 34 40 46 54 58 64 59 47 44' - '52 60 4A 3F 7D 70 50 5F 73 13 B2 00 00 00 00 00' - '00 B2 23 A9 9F 9E 24 2F 3E 42 4E 56 63 53 32 2E' - '41 52 3D 2C 7F 77 7A 74 6E 12 B2 00 00 00 00 00' - '00 B2 23 AB A2 9E 3D 44 4A 52 58 5B 64 5A 4B 49' - '54 5C 4C 45 7B 76 6F 6F 72 11 B2 00 00 00 00 00' - '00 B2 22 AD A6 A5 AF AE AA A8 A4 A2 9F 9D A0 9E' - '9A 96 96 96 8C 8A 88 7F 75 10 B2 00 00 00 00 00' - '00 B2 20 B1 A5 A3 A2 9D 9D 9C 9D 9D 9E 9D 9D 9D' - '9D 9D 9D 9C 9F A3 A2 AE 8B 0E B2 00 00 00 00 00' - '00 B2 25 B1 78 61 69 8E 8D 8D 8D 8D 8C 8C 8C 8C' - '8D 8D 8D 8E 87 65 65 8C AB 13 B2 00 00 00 00 00' - '00 B2 18 B1 5D 67 57 87 8D 8B 89 87 8A 8B 8B 8A' - '87 88 8A 90 68 62 58 7B 9E 0C B2 00 00 00 00 00' - '00 B2 10 9E 82 86 78 86 82 8F 9A 99 9C A0 A0 9D' - '9A 9B 91 83 83 83 75 8E 6B 06 B2 00 00 00 00 00' - '00 B2 08 87 87 80 81 81 9F 9C 90 8E 8D 8C 8C 8D' - '8E 91 9C 9F 86 7E 81 98 48 B2 B2 00 00 00 00 00' - '00 B2 01 55 8E 7C 81 9B 89 82 86 86 83 86 86 86' - '86 86 81 83 9C 83 78 9F 29 B2 B2 00 00 00 00 00' - '00 B2 B2 31 9A 7C 90 88 82 86 83 86 81 7E 7F 7F' - '7F 7F 7F 7E 80 90 72 A5 15 B2 B2 00 00 00 00 00' - '00 00 B2 19 A0 83 8E 82 86 86 86 86 86 80 71 72' - '75 76 76 76 72 81 76 A1 0A B2 00 00 00 00 00 00' - '00 00 B2 0F A4 87 87 88 87 87 87 87 87 88 81 75' - '6E 6C 6B 6E 6E 6E 78 8C 01 B2 00 00 00 00 00 00' - '00 00 B2 02 94 8F 80 8E 8C 8D 8D 8D 8D 8D 8D 8E' - '8D 8A 86 80 7C 67 7C 63 B2 B2 00 00 00 00 00 00' - '00 00 B2 B2 76 99 89 89 94 92 91 91 91 91 91 91' - '92 92 93 95 8C 89 93 3F B2 B2 00 00 00 00 00 00' - '00 00 00 B2 45 9C 99 8B 8C 96 99 97 97 97 97 97' - '97 99 95 8E 88 9D 8E 1F B2 00 00 00 00 00 00 00' - '00 00 00 B2 2C 9C 9D 9D 95 87 8F 98 99 9A 9A 99' - '98 8F 87 95 9E A1 82 14 B2 00 00 00 00 00 00 00' - '00 00 00 B2 16 93 A0 8F A2 A4 9C 98 97 94 94 97' - '98 9A A4 9A 91 A7 78 0C B2 00 00 00 00 00 00 00' - '00 00 00 B2 13 94 6F 5B 76 A8 A6 A6 A6 A5 A5 A6' - 'A6 A6 A3 65 5B 9D 6A 0B B2 00 00 00 00 00 00 00' - '00 00 00 B2 07 4D A2 9A AB B0 AF AF AF AF AF AF' - 'AF AF AF A7 9C 9B 30 B2 B2 00 00 00 00 00 00 00' - '00 00 00 B2 B2 0B 31 34 33 32 32 32 32 32 32 32' - '32 32 32 33 35 2D 04 B2 00 00 00 00 00 00 00 00' - '00 00 00 00 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2' - 'B2 B2 B2 B2 B2 B2 B2 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF 00 00 00 00 00 00 00 00 FF FE 7F FF FF FE' - '7F FF F0 00 00 0F E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 0C 0C 0C 00 15 15' - '15 00 1F 12 12 00 19 19 19 00 25 20 22 00 29 29' - '29 00 35 35 35 00 3E 3E 3E 00 40 40 40 00 57 57' - '57 00 6D 6D 6D 00 73 73 73 00 75 75 75 00 78 78' - '78 00 7B 7B 7B 00 7D 7D 7D 00 7F 7F 7F 00 89 7D' - '7D 00 66 8E 7A 00 86 7B 81 00 5E CA 93 00 4F D8' - 'D8 00 85 85 85 00 8C 8C 8C 00 8F 8F 8F 00 90 90' - '90 00 91 91 91 00 97 97 97 00 98 95 97 00 99 99' - '99 00 9B 9A 9B 00 9B 9B 9B 00 9F 9F 9F 00 A1 A1' - 'A1 00 A3 A3 A3 00 A5 A5 A5 00 A9 A9 A9 00 AC AC' - 'AC 00 AE AE AE 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' - 'B4 00 B6 B6 B6 00 B8 B8 B8 00 BA BA BA 00 BF BF' - 'BF 00 C1 C1 C1 00 C2 C2 C2 00 C0 C7 C4 00 C4 C4' - 'C4 00 C7 C7 C7 00 CB C9 CA 00 CA CA CA 00 CC CC' - 'CC 00 CD CD CD 00 CF CF CF 00 D4 C9 CF 00 D0 D0' - 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' - 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DF DF' - 'DF 00 E0 E0 E0 00 E1 E1 E1 00 E3 E3 E3 00 E4 E4' - 'E4 00 E6 E6 E6 00 E7 E7 E7 00 E9 E9 E9 00 EA EA' - 'EA 00 EC EC EC 00 ED ED ED 00 EF EF EF 00 F0 F0' - 'F0 00 F3 F3 F3 00 F4 F4 F4 00 F7 F7 F7 00 FC FC' - 'FC 00 00 00 00 00 A9 A9 A9 00 AA AA AA 00 AC AC' - 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B7 AF' - 'AF 00 AD B9 B3 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' - 'B2 00 B3 B3 B3 00 B4 B4 B4 00 B5 B5 B5 00 B6 B6' - 'B6 00 B7 B7 B7 00 B9 B9 B9 00 BC BC BC 00 BD BD' - 'BD 00 BE BE BE 00 BF BF BF 00 89 CF CF 00 C0 C0' - 'C0 00 C1 C1 C1 00 C2 C0 C1 00 C2 C2 C2 00 C3 C3' - 'C3 00 C4 C1 C2 00 C5 C2 C4 00 C4 C4 C4 00 C5 C5' - 'C5 00 C6 C5 C6 00 C6 C6 C6 00 C8 C3 C5 00 CC C4' - 'C8 00 C8 C8 C8 00 C9 C9 C9 00 CB C9 CA 00 CA CA' - 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' - 'CE 00 CF CF CF 00 D2 C1 CA 00 D3 C8 CD 00 D0 D0' - 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' - 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' - 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' - 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' - 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' - 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' - 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F4 F4 F4 00 F5 F5' - 'F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9' - 'F9 00 FC FC FC 00 FD FD FD 00 FF FF FF 00 00 00' - '00 00 62 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6E' - '65 74 64 72 69 76 65 2E 69 63 6F 00 4B 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 17 17 17 17 17 17 12 16 16 12' - '17 17 17 17 17 17 00 00 00 57 57 57 57 03 03 57' - '57 57 57 57 00 00 00 00 07 2B 1A 1C 21 20 21 23' - '22 1D 13 05 00 00 00 57 2B 56 08 18 25 2A 1E 29' - '1F 31 15 14 00 00 00 57 27 55 0B 19 24 26 10 20' - '0F 34 39 0D 00 00 00 57 28 56 56 54 52 4F 51 4E' - '4E 4A 51 0E 00 00 00 57 2A 2C 2E 40 3D 3F 3F 3E' - '42 2C 33 1B 00 00 00 00 11 43 35 47 47 48 48 47' - '48 37 46 0A 00 00 00 00 09 46 43 38 38 36 36 37' - '36 43 4B 04 00 00 00 00 01 50 3B 3A 3A 3A 32 2E' - '2E 30 48 57 00 00 00 00 57 4C 3C 45 43 43 44 44' - '41 36 30 57 00 00 00 00 57 2C 4F 42 46 49 49 47' - '43 52 1B 57 00 00 00 00 57 19 43 4F 53 51 51 53' - '49 4D 0C 57 00 00 00 00 00 06 2E 30 30 30 30 30' - '2F 2D 02 00 00 00 00 00 00 00 57 57 57 57 57 57' - '57 57 00 00 00 00 FF FF 00 00 00 00 00 00 E0 03' - '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' - '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' - '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 60 00 00 00 00 00 00 00 77 77' - '77 77 77 77 77 7E E7 77 77 77 77 77 77 77 00 00' - '00 00 00 00 00 0E E0 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 08 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 88 88 88 88 88 88 88 88 88 88 00 00 00 00 00' - '07 FF 77 77 77 77 77 77 77 77 67 80 00 00 00 00' - '8F FF 08 88 87 77 88 77 78 78 66 70 00 00 00 00' - '8F FF 88 88 77 77 88 77 88 77 77 70 00 00 00 00' - '8F FF 88 88 87 77 88 87 88 77 77 70 00 00 00 00' - '8F FF 88 87 77 77 88 77 88 77 77 70 00 00 00 00' - '8F FF FF FF FF FF FF FF FF 77 77 70 00 00 00 00' - '8F FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00' - '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' - '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' - '0F 77 77 77 FF FF FF FF 77 77 77 70 00 00 00 00' - '07 77 77 FF 77 77 77 77 FF 77 7F 80 00 00 00 00' - '07 77 7F 77 77 77 77 77 77 F7 7F 80 00 00 00 00' - '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' - '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' - '00 F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' - '00 77 77 77 77 77 77 77 77 77 77 00 00 00 00 00' - '00 7F 77 77 77 77 77 77 77 77 78 00 00 00 00 00' - '00 8F F7 7F FF FF FF FF 77 7F 78 00 00 00 00 00' - '00 8F FF 77 7F FF FF F7 77 FF 70 00 00 00 00 00' - '00 07 F7 FF FF F7 7F FF FF 7F 70 00 00 00 00 00' - '00 07 77 7F FF FF FF FF F7 7F 70 00 00 00 00 00' - '00 08 FF FF FF FF FF FF FF FF 80 00 00 00 00 00' - '00 00 88 88 88 88 88 88 88 88 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF 00 00 00 00 00 00 00 00 FF FE 7F FF FF FE' - '7F FF F0 00 00 0F E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 88 88' - '88 8E E8 88 88 88 00 00 00 00 00 00 00 00 00 07' - '88 88 87 78 80 00 00 7F 08 77 87 87 88 00 00 7F' - '88 77 88 87 78 00 00 7F FF FF FF FF F8 00 00 77' - '77 77 77 77 78 00 00 87 7F FF FF F7 78 00 00 07' - '77 77 77 77 F0 00 00 0F 77 77 77 77 F0 00 00 0F' - '77 77 77 77 70 00 00 07 F7 7F FF 7F 80 00 00 08' - '7F FF FF FF 80 00 00 00 77 77 77 77 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 E0 03' - '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' - '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' - '00 00 F0 0F 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 01 01 00 02 02 02 00 05 05 05 00 06 06' - '06 00 07 07 07 00 08 08 08 00 09 09 09 00 0B 0B' - '0B 00 0C 0C 0C 00 13 13 13 00 18 18 18 00 19 19' - '19 00 1A 1A 1A 00 1E 1E 1E 00 1F 1F 1F 00 20 20' - '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' - '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2A 2A' - '2A 00 2B 2B 2B 00 2C 2C 2C 00 2D 2D 2D 00 2E 2C' - '2D 00 2F 2F 2F 00 34 34 34 00 35 35 35 00 39 39' - '39 00 3B 3B 3B 00 3D 3D 3D 00 3F 3F 3F 00 40 40' - '40 00 41 41 41 00 42 42 42 00 47 47 47 00 48 48' - '48 00 49 49 49 00 4B 4B 4B 00 4F 4F 4F 00 53 53' - '53 00 56 56 56 00 58 58 58 00 59 59 59 00 5A 5A' - '5A 00 5B 5B 5B 00 5D 5D 5D 00 5F 5F 5F 00 61 61' - '61 00 63 63 63 00 64 64 64 00 66 66 66 00 67 67' - '67 00 68 68 68 00 6A 6A 6A 00 6B 6B 6B 00 6C 6C' - '6C 00 70 70 70 00 71 71 71 00 72 72 72 00 73 73' - '73 00 74 74 74 00 75 75 75 00 76 76 76 00 77 77' - '77 00 78 78 78 00 79 79 79 00 7A 7A 7A 00 7C 7C' - '7C 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F 7F 00 2F 99' - '64 00 1C A8 60 00 0A BF 61 00 20 A8 63 00 51 A7' - '7C 00 17 CE 71 00 00 DC DC 00 00 FF FF 00 6B FF' - 'FF 00 80 80 80 00 81 81 81 00 83 83 83 00 84 83' - '84 00 85 85 85 00 87 87 87 00 88 88 88 00 8A 8A' - '8A 00 8C 8C 8C 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' - '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 94 94' - '94 00 97 97 97 00 98 98 98 00 99 99 99 00 9A 9A' - '9A 00 9C 9C 9C 00 9D 9D 9D 00 9F 9F 9F 00 83 AB' - '97 00 96 AB A0 00 90 AF A0 00 99 AC A2 00 95 B2' - 'A3 00 9D B3 A8 00 A0 A0 A0 00 A1 A1 A1 00 A2 A2' - 'A2 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A6 A6' - 'A6 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' - 'AA 00 AB AB AB 00 AD A8 AB 00 AB AC AC 00 AC AC' - 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' - 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B3 B4' - 'B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B8 B4' - 'B6 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BB BB' - 'BB 00 BF BB BD 00 BC BC BC 00 BD BD BD 00 BE BE' - 'BE 00 BF BF BF 00 91 D6 B4 00 91 D8 B5 00 C3 BD' - 'C0 00 C2 BE C0 00 C7 BF C3 00 C0 C0 C0 00 C1 C1' - 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C3 00 C4 C3' - 'C3 00 C4 C3 C4 00 C6 C2 C4 00 C6 C3 C4 00 C6 C3' - 'C5 00 C4 C4 C4 00 C5 C4 C4 00 C5 C5 C5 00 C7 C4' - 'C5 00 C6 C6 C6 00 C7 C7 C7 00 C8 C8 C8 00 C8 C9' - 'C9 00 C9 C9 C9 00 CA CA CA 00 CB CB CB 00 CC CC' - 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' - 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' - 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' - 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' - 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' - 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' - 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' - 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4' - 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' - 'F8 00 F9 F9 F9 00 FA FA FA 00 FC FC FC 00 FF FF' - 'FF 00 00 00 00 00 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 52 52 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 55 55' - '55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55' - '55 55 55 55 52 53 53 52 55 55 55 55 55 55 55 55' - '55 55 55 55 55 55 55 55 55 55 55 55 55 55 9B 9B' - '9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B' - '9B 9B 9B 9B 54 54 54 54 9B 9B 9B 9B 9B 9B 9B 9B' - '9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 54 54 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9B 9B E1 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9B 9B E1 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 E1 E1 E1 E1 11 1A 19 1A 19 19 19 19 19' - '19 19 19 19 19 19 18 18 18 18 18 18 18 18 18 19' - '19 19 1C 1C 0A E1 E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 E1 E1 14 61 AE B1 AF B2 B1 B0 AF AD AA' - 'A9 A7 A5 9E 9D 9D 9E 9B 9C 95 95 92 93 8F 90 89' - '88 8C 81 7F 7E 35 07 E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 01 5C CF CC CB B9 59 5B 62 66 74 81' - '8F 9B 9E A9 AF AE AE BA AE B7 AF BB B0 B8 AA AC' - 'A2 71 4F 4D 6E 91 2B E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 0C AA D0 C6 CA AF 21 23 2D 3F 5A 62' - '6A 77 7A 80 8B 7B 69 93 67 8B 73 9E 75 93 66 A6' - '9A 50 51 4E 4C 98 58 01 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 17 B5 CE C8 CB B1 27 33 46 5A 60 65' - '72 79 7C 82 8E 76 61 8D 5C 83 64 95 65 8B 5B A0' - 'A4 70 96 97 6C 9F 5F 01 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 16 B5 D0 CA CB B5 39 41 4A 59 5F 65' - '72 79 7C 82 8F 6B 57 87 48 7A 5A 90 5C 86 46 9D' - 'A5 A3 6F 6D 99 A5 5E 01 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 16 B5 D2 CB CC BA 3D 3E 49 59 5F 65' - '72 79 7C 82 90 66 40 81 3A 72 45 8B 48 7D 38 9D' - 'A9 A1 A8 A2 95 A7 5E 01 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 15 B5 D3 CD CF BA 3A 3C 45 56 5C 63' - '69 75 78 7D 8E 61 37 77 31 66 3B 85 3D 76 2E 9C' - 'AB A7 9E 9D 9C A9 5F 01 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 15 B6 D6 CF CE C3 79 79 7D 82 84 87' - '8A 8E 8E 8F 93 8B 85 94 83 8F 85 94 84 8F 7D A7' - 'AB A9 A5 9E 9D AD 5F E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 14 B7 D7 CF CF CE D1 CF CD CC CA C8' - 'C6 C5 C3 C2 BF BF C0 BC BD BA BA B6 B6 B3 B4 AF' - 'AE AD AA A5 9B AE 5F E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 14 B7 DB DC DA DA DA D9 D9 D8 D8 D7' - 'D7 D7 D6 D6 D5 D5 D5 D4 D4 D4 D3 D3 D2 D2 D1 D1' - 'D1 D0 D0 CF C4 B4 5E E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 13 BA E0 CD C5 C6 C6 C4 C3 C3 C3 C3' - 'C3 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4' - 'C6 C7 C7 C7 DC D3 5D E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 13 C2 DC BD A5 90 95 BC BE BD BD BD' - 'BD BD BD BD BD BD BD BD BD BD BD BD BD BD BD BF' - 'B3 92 90 B5 C2 E0 68 E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 0F BE D7 A9 7B 8B 84 9E BE BC BC BC' - 'BC BC BB BB BB BB BB BB BB BB BC BC BC BC BD B6' - '7A 8A 85 89 BC DF 69 E1 E1 00 00 00 00 00 00 00' - '00 00 E1 E1 03 9D DA 92 86 9E 7D 90 BC B9 B9 B9' - 'B8 B7 B7 B9 BB BC BC BB B9 B7 B7 B7 B8 B9 BB AD' - '78 9E 87 81 BA D9 43 E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 76 D8 B3 A7 B6 95 AD B7 B6 B4 B7' - 'C1 C5 C7 CA CE D1 D1 CF CB C8 C6 C2 B8 B4 B6 B7' - 'A7 B4 9D 95 BD CC 2D E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 4A D3 B5 B3 AF B3 B5 B2 B3 C3 D4' - 'D0 C5 C2 C1 C0 BF BF C0 C1 C2 C5 D0 D5 C5 B5 B2' - 'B4 AF B2 B5 BD B8 23 E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 2F CD B4 B1 B1 B1 AE BA D1 CA C0' - 'B8 B9 BA BA BA BA BA BA BA BA B9 B9 BF C8 D1 BE' - 'AE B1 B1 AF C3 8D 12 E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 24 BB B6 AE AF AE B8 CD C0 B4 B5' - 'B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B5 B4 BC CE' - 'BC AD AE AD C4 72 06 E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 12 8B BF AE AF B2 C8 B8 B3 B5 B4' - 'B4 B4 B4 B3 B1 B2 B2 B2 B2 B2 B2 B2 B2 B2 B0 B4' - 'C6 B3 AA AD C6 55 E1 E1 E1 00 00 00 00 00 00 00' - '00 00 00 E1 E1 05 6B C1 B0 B1 BF BA B2 B4 B4 B4' - 'B4 B4 B4 B3 B0 AD AE AE AE AE AE AE AE AE AE AB' - 'B3 BE AA AD C6 30 E1 E1 E1 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 57 C1 B3 B5 BF B5 B4 B4 B4 B4' - 'B4 B4 B4 B4 B3 AD A7 A9 A9 A9 A9 A9 A9 A9 A9 A9' - 'AA B7 AB AD C2 26 E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 33 C0 B5 B6 B8 B5 B5 B5 B5 B5' - 'B5 B5 B5 B5 B5 B4 AB 9E 9E 9E A5 A5 A5 A5 A5 A5' - 'A5 AA A7 AF B0 1B E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 25 BC B8 B6 B4 B7 B7 B7 B7 B7' - 'B7 B7 B7 B7 B7 B7 B7 B1 AA A5 9D 9C 9B 9C 9C 9C' - '9D 95 9B B2 86 0D E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 1A B0 BA B9 B0 B9 BA BA BA BA' - 'BA BA BA BA BA BA BA BB BA B9 B7 B3 B0 AD A9 A5' - '9D 87 93 B4 67 07 E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 0B 84 BF BF B4 B6 BF BD BE BE' - 'BE BE BE BE BE BE BE BE BE BE BE BF BF BE BD BD' - 'B3 A7 B0 AE 47 02 E1 E1 00 00 00 00 00 00 00 00' - '00 00 00 00 E1 E1 06 65 C0 C3 C0 B2 BA C2 C1 C1' - 'C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C2 BC' - 'B2 C1 C0 A9 2C E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 E1 E1 44 B7 C6 C5 C2 B2 BB C5 C6' - 'C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C5 C5 BD B1' - 'BE C7 BD 90 20 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 E1 E1 2A AD C9 C7 C8 C5 BB B6 BE' - 'C8 C9 C8 C8 C8 C8 C8 C8 C8 C8 C9 C9 C0 B6 BA C4' - 'C8 CA BA 7A 10 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 E1 E1 1F 93 CA CA CA CB CB C3 B6' - 'B7 C2 C7 C7 C8 C8 C8 C8 C7 C7 C2 B8 B5 C1 CB CB' - 'CA CC B8 68 08 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 E1 E1 0E 7D C8 D1 CB CA D0 CF CE' - 'C8 C4 C3 C3 C1 C0 C0 C1 C3 C3 C3 C6 CD D0 CE C9' - 'CF CF BA 5C E1 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 E1 E1 06 67 C8 C3 93 9C BA D0 D1' - 'D1 D2 D2 D1 D0 CF CF D0 D1 D2 D2 D1 D2 C8 9D 94' - 'B5 D0 B8 42 E1 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E1 E1 5E C4 A5 86 8D 86 CF D5' - 'D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D7 B9 84 8A' - '8B CF B1 34 E1 E1 E1 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E1 E1 36 B2 C1 C0 B9 C8 DD DD' - 'DD DD DD DD DD DD DD DD DD DD DD DD DE D6 C3 BC' - 'C0 BB 84 1E E1 E1 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E1 E1 0C 55 94 B7 BB BF BC BC' - 'BC BC BC BC BC BC BC BC BC BC BC BC BC BD BD BB' - 'B1 84 32 04 E1 E1 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E1 E1 E1 09 22 29 28 28 28 28' - '28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 29' - '29 1D 02 E1 E1 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' - 'E1 E1 E1 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FE 3F FF FF 00 00 FF FF' - 'FE 3F FF FF 00 00 FF FF FE 3F FF FF 00 00 FC 00' - '00 00 00 7F 00 00 F8 00 00 00 00 3F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' - '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0E E0 00 00 00 00 00 00 00 00 00 00 00 88 88' - '88 88 88 88 88 88 88 88 88 EE EE 88 88 88 88 88' - '88 88 88 88 88 88 77 77 77 77 77 77 77 77 77 77' - '77 EE EE 77 77 77 77 77 77 77 77 77 77 77 00 00' - '00 00 00 00 00 00 00 00 00 0E E0 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 07 70 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 07 70 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' - '00 08 FF F7 88 88 77 77 77 77 77 77 77 77 77 77' - '66 87 80 00 00 00 00 00 00 07 FF F7 00 88 88 87' - '77 77 87 87 77 77 87 78 66 67 80 00 00 00 00 00' - '00 07 FF F7 88 88 88 77 77 77 87 87 87 87 87 77' - '77 87 80 00 00 00 00 00 00 07 FF F7 88 88 88 77' - '77 78 87 87 87 87 87 77 77 77 80 00 00 00 00 00' - '00 07 FF F7 88 88 88 77 77 78 87 87 87 87 87 77' - '77 77 80 00 00 00 00 00 00 07 FF F7 88 88 88 87' - '77 78 87 88 87 87 87 77 77 77 80 00 00 00 00 00' - '00 07 FF F7 77 77 77 77 77 77 77 77 77 77 77 77' - '77 77 80 00 00 00 00 00 00 07 FF FF FF FF FF FF' - '77 77 77 77 77 77 77 77 77 77 80 00 00 00 00 00' - '00 07 FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF F7 80 00 00 00 00 00 00 07 FF FF FF 77 77 7F' - 'FF FF FF FF FF FF FF FF FF FF 80 00 00 00 00 00' - '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 7F 80 00 00 00 00 00' - '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 7F' - 'FF FF FF FF F7 77 77 77 77 7F 80 00 00 00 00 00' - '00 08 F7 77 77 77 7F FF 77 77 77 77 FF FF 77 77' - '77 77 00 00 00 00 00 00 00 08 F7 77 77 7F F7 77' - '77 77 77 77 77 7F F7 77 77 77 00 00 00 00 00 00' - '00 00 77 77 77 F7 77 77 77 77 77 77 77 77 7F 77' - '77 F7 00 00 00 00 00 00 00 00 77 77 7F 77 77 77' - '77 77 77 77 77 77 77 F7 77 F8 00 00 00 00 00 00' - '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 F8 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' - '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 70 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' - '00 00 07 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 00 00 07 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' - '00 00 08 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 00 00 08 7F F7 77 77 77' - '77 77 77 77 77 77 77 7F 77 00 00 00 00 00 00 00' - '00 00 08 7F FF F7 77 77 77 77 77 77 77 77 7F FF' - '77 00 00 00 00 00 00 00 00 00 00 7F FF FF 77 77' - '77 77 77 77 77 77 FF FF 78 00 00 00 00 00 00 00' - '00 00 00 7F FF FF FF FF 77 77 77 77 7F FF FF FF' - '78 00 00 00 00 00 00 00 00 00 00 8F 77 77 FF FF' - 'FF FF FF FF FF FF 77 7F 78 00 00 00 00 00 00 00' - '00 00 00 8F 77 77 FF FF FF FF FF FF FF F7 77 7F' - '78 00 00 00 00 00 00 00 00 00 00 87 77 7F FF FF' - 'FF FF FF FF FF FF 77 77 70 00 00 00 00 00 00 00' - '00 00 00 08 77 77 77 77 77 77 77 77 77 77 77 77' - '80 00 00 00 00 00 00 00 00 00 00 00 08 88 88 88' - '88 88 88 88 88 88 88 80 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FE 3F FF FF 00 00 FF FF FE 3F FF FF 00 00 FF FF' - 'FE 3F FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' - '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' - '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' - '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 48 00 00' - '00 78 00 00 00 78 00 00 00 48 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 DC DC FF 00 DC' - 'DC FF 00 00 00 B4 00 00 00 9C 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 00 DC DC FF 00 FF FF FF 00 FF' - 'FF FF 00 DC DC FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF 6B FF FF FF 6B FF FF FF 6B FF' - 'FF FF 6B FF FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 6B FF FF FF 6B FF' - 'FF FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 C0 C0 C0 FF C0 C0' - 'C0 FF 00 00 00 92 00 00 00 37 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 C0 C0 C0 FF C0 C0' - 'C0 FF 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 35 00 00 00 18 00 00' - '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' - '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F1 00 00 00 B1 00 00' - '00 5C 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' - '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' - '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' - '2D FF 2E 2C 2D FF 13 13 13 FF 00 00 00 FF 00 00' - '00 F6 00 00 00 69 00 00 00 09 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' - '90 FF CA CA CA FF CD CD CD FF CB CB CB FF CE CE' - 'CE FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' - 'C9 FF C7 C7 C7 FF C6 C6 C6 FF C5 C5 C5 FF C4 C4' - 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2 C2 FF C3 C3' - 'C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF BF FF BF BF' - 'BF FF BC BC BC FF BD BD BD FF BA BA BA FF BB BB' - 'BB FF B5 B5 B5 FF B3 B4 B3 FF B8 B4 B6 FF AD AD' - 'AD FF AB AC AC FF AD A8 AB FF 63 63 63 FF 09 09' - '09 FF 00 00 00 EF 00 00 00 42 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF EB EB' - 'EB FF E8 E8 E8 FF E7 E7 E7 FF D5 D5 D5 FF 85 85' - '85 FF 88 88 88 FF 92 92 92 FF 98 98 98 FF A2 A2' - 'A2 FF AD AD AD FF BA BA BA FF C0 C0 C0 FF C3 C3' - 'C3 FF C6 C6 C6 FF CB CB CB FF CA CA CA FF CA CA' - 'CA FF D6 D6 D6 FF CA CA CA FF D3 D3 D3 FF CB CB' - 'CB FF D7 D7 D7 FF CC CC CC FF D4 D4 D4 FF C7 C7' - 'C7 FF C8 C9 C9 FF C6 C2 C4 FF 9D B3 A8 FF 20 A8' - '63 FF 1C A8 60 FF 90 AF A0 FF BF BB BD FF 4F 4F' - '4F FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 15 00 00 00 F0 19 19 19 FF C7 C7 C7 FF EC EC' - 'EC FF E2 E2 E2 FF E6 E6 E6 FF CB CB CB FF 3B 3B' - '3B FF 3F 3F 3F FF 56 56 56 FF 72 72 72 FF 87 87' - '87 FF 92 92 92 FF 9D 9D 9D FF A5 A5 A5 FF A8 A8' - 'A8 FF AC AC AC FF B7 B7 B7 FF A9 A9 A9 FF 9C 9C' - '9C FF BD BD BD FF 99 99 99 FF B7 B7 B7 FF A1 A1' - 'A1 FF C3 C3 C3 FF A3 A3 A3 FF BD BD BD FF 98 98' - '98 FF C5 C4 C4 FF C7 BF C3 FF 51 A7 7C FF 17 CE' - '71 FF 0A BF 61 FF 2F 99 64 FF C3 BD C0 FF 84 83' - '84 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 30 00 00 00 FA 29 29 29 FF D1 D1 D1 FF EA EA' - 'EA FF E4 E4 E4 FF E7 E7 E7 FF CD CD CD FF 47 47' - '47 FF 5F 5F 5F FF 79 79 79 FF 87 87 87 FF 8F 8F' - '8F FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF B9 B9 B9 FF A4 A4 A4 FF 90 90' - '90 FF B8 B8 B8 FF 8A 8A 8A FF AF AF AF FF 94 94' - '94 FF BF BF BF FF 97 97 97 FF B7 B7 B7 FF 88 88' - '88 FF C4 C3 C3 FF C6 C3 C5 FF 95 B2 A3 FF 91 D6' - 'B4 FF 91 D8 B5 FF 83 AB 97 FF C4 C1 C3 FF 8E 8E' - '8E FF 01 01 01 FF 00 00 00 B7 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' - 'EC FF E6 E6 E6 FF E7 E7 E7 FF D1 D1 D1 FF 68 68' - '68 FF 74 74 74 FF 7E 7E 7E FF 85 85 85 FF 8E 8E' - '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF BA BA BA FF 9F 9F 9F FF 83 83' - '83 FF B3 B3 B3 FF 7C 7C 7C FF A8 A8 A8 FF 87 87' - '87 FF BB BB BB FF 8A 8A 8A FF B2 B2 B2 FF 79 79' - '79 FF C2 C2 C2 FF C4 C4 C4 FF C6 C3 C4 FF 99 AC' - 'A2 FF 96 AB A0 FF C2 BE C0 FF C4 C4 C4 FF 8D 8D' - '8D FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' - 'EE FF E7 E7 E7 FF E8 E8 E8 FF D6 D6 D6 FF 70 70' - '70 FF 71 71 71 FF 7D 7D 7D FF 85 85 85 FF 8E 8E' - '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF BB BB BB FF 98 98 98 FF 73 73' - '73 FF AD AD AD FF 6A 6A 6A FF A0 A0 A0 FF 78 78' - '78 FF B7 B7 B7 FF 7C 7C 7C FF AB AB AB FF 67 67' - '67 FF C2 C2 C2 FF C6 C6 C6 FF C4 C3 C4 FF C7 C4' - 'C5 FF C6 C2 C4 FF BF BF BF FF C5 C5 C5 FF 8D 8D' - '8D FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' - 'EF FF E9 E9 E9 FF EB EB EB FF D6 D6 D6 FF 6A 6A' - '6A FF 6C 6C 6C FF 78 78 78 FF 81 81 81 FF 8A 8A' - '8A FF 93 93 93 FF 9C 9C 9C FF A3 A3 A3 FF A6 A6' - 'A6 FF AB AB AB FF B9 B9 B9 FF 90 90 90 FF 66 66' - '66 FF A5 A5 A5 FF 5B 5B 5B FF 98 98 98 FF 6B 6B' - '6B FF B1 B1 B1 FF 70 70 70 FF A4 A4 A4 FF 58 58' - '58 FF C1 C1 C1 FF C8 C8 C8 FF C5 C5 C5 FF C3 C3' - 'C3 FF C2 C2 C2 FF C1 C1 C1 FF C6 C6 C6 FF 8E 8E' - '8E FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' - 'F2 FF EB EB EB FF EA EA EA FF DF DF DF FF A7 A7' - 'A7 FF A7 A7 A7 FF AB AB AB FF AE AE AE FF B0 B0' - 'B0 FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF B9 B9' - 'B9 FF BA BA BA FF BD BD BD FF B7 B7 B7 FF B1 B1' - 'B1 FF BE BE BE FF AF AF AF FF BA BA BA FF B1 B1' - 'B1 FF BE BE BE FF B0 B0 B0 FF BA BA BA FF AB AB' - 'AB FF C5 C5 C5 FF C8 C8 C8 FF C6 C6 C6 FF C4 C4' - 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C9 C9 C9 FF 8E 8E' - '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' - 'F3 FF EB EB EB FF EB EB EB FF EA EA EA FF ED ED' - 'ED FF EB EB EB FF E9 E9 E9 FF E8 E8 E8 FF E6 E6' - 'E6 FF E4 E4 E4 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' - 'DF FF DE DE DE FF DB DB DB FF DB DB DB FF DC DC' - 'DC FF D8 D8 D8 FF D9 D9 D9 FF D6 D6 D6 FF D6 D6' - 'D6 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' - 'D0 FF CB CB CB FF CA CA CA FF C9 C9 C9 FF C7 C7' - 'C7 FF C4 C4 C4 FF C0 C0 C0 FF CA CA CA FF 8E 8E' - '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' - 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' - 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' - 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' - 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF ED ED' - 'ED FF ED ED ED FF ED ED ED FF EC EC EC FF EC EC' - 'EC FF EB EB EB FF E0 E0 E0 FF D0 D0 D0 FF 8D 8D' - '8D FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' - 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' - 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF EF FF 8C 8C' - '8C FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' - 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' - 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF DB DB DB FF CF CF CF FF BC BC BC FF BB BB' - 'BB FF D1 D1 D1 FF DE DE DE FF FF FF FF FF 9A 9A' - '9A FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' - 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' - 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9' - 'D9 FF D2 D2 D2 FF A8 A8 A8 FF B6 B6 B6 FF B1 B1' - 'B1 FF B5 B5 B5 FF D8 D8 D8 FF FC FC FC FF 9C 9C' - '9C FF 00 00 00 FF 00 00 00 AE 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' - 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' - 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' - 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D7 D7' - 'D7 FF C9 C9 C9 FF A6 A6 A6 FF C3 C3 C3 FF B3 B3' - 'B3 FF AD AD AD FF D6 D6 D6 FF F5 F5 F5 FF 76 76' - '76 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' - 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' - 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF DD DD DD FF E1 E1 E1 FF E3 E3' - 'E3 FF E6 E6 E6 FF EA EA EA FF ED ED ED FF ED ED' - 'ED FF EB EB EB FF E7 E7 E7 FF E4 E4 E4 FF E2 E2' - 'E2 FF DE DE DE FF D4 D4 D4 FF D0 D0 D0 FF D2 D2' - 'D2 FF D3 D3 D3 FF C5 C5 C5 FF D0 D0 D0 FF C2 C2' - 'C2 FF BF BF BF FF D9 D9 D9 FF E8 E8 E8 FF 56 56' - '56 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' - 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' - 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF DF DF' - 'DF FF F0 F0 F0 FF EC EC EC FF E1 E1 E1 FF DE DE' - 'DE FF DD DD DD FF DC DC DC FF DB DB DB FF DB DB' - 'DB FF DC DC DC FF DD DD DD FF DE DE DE FF E1 E1' - 'E1 FF EC EC EC FF F1 F1 F1 FF E1 E1 E1 FF D1 D1' - 'D1 FF CE CE CE FF D0 D0 D0 FF CB CB CB FF CE CE' - 'CE FF D1 D1 D1 FF D9 D9 D9 FF D4 D4 D4 FF 3F 3F' - '3F FF 00 00 00 FF 00 00 00 55 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' - 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CA CA CA FF D6 D6 D6 FF ED ED ED FF E6 E6' - 'E6 FF DC DC DC FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF ED ED' - 'ED FF DA DA DA FF CA CA CA FF CD CD CD FF CD CD' - 'CD FF CB CB CB FF DF DF DF FF B8 B8 B8 FF 22 22' - '22 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' - 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' - 'CA FF D4 D4 D4 FF E9 E9 E9 FF DC DC DC FF D0 D0' - 'D0 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D8 D8' - 'D8 FF EA EA EA FF D8 D8 D8 FF C9 C9 C9 FF CA CA' - 'CA FF C9 C9 C9 FF E0 E0 E0 FF A0 A0 A0 FF 08 08' - '08 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' - 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' - 'CE FF E4 E4 E4 FF D4 D4 D4 FF CF CF CF FF D1 D1' - 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF CD CD CD FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CC CC' - 'CC FF D0 D0 D0 FF E2 E2 E2 FF CF CF CF FF C7 C7' - 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 C2 00 00 00 0E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' - '9F FF DD DD DD FF CC CC CC FF CD CD CD FF DB DB' - 'DB FF D6 D6 D6 FF CE CE CE FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF C8 C8 C8 FF CF CF CF FF DA DA DA FF C7 C7' - 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 5A 5A 5A FF 00 00' - '00 FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' - '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF DB DB' - 'DB FF D1 D1 D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF C5 C5' - 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C7 C7 C7 FF D3 D3 D3 FF C8 C8' - 'C8 FF C9 C9 C9 FF DE DE DE FF 42 42 42 FF 00 00' - '00 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' - '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D4 D4' - 'D4 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D0 D0 D0 FF C8 C8' - 'C8 FF C3 C3 C3 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C7 C7 C7 FF C5 C5' - 'C5 FF CB CB CB FF CC CC CC FF 2D 2D 2D FF 00 00' - '00 F8 00 00 00 40 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' - '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF CD CD CD FF C7 C7 C7 FF C4 C4 C4 FF C2 C2' - 'C2 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' - 'C1 FF C1 C1 C1 FF C2 C2 C2 FF BF BF BF FF C0 C0' - 'C0 FF CE CE CE FF B2 B2 B2 FF 1A 1A 1A FF 00 00' - '00 E5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' - '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF CC CC' - 'CC FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D7 D7 D7 FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' - 'D3 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF C6 C6' - 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' - 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' - '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' - '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF D0 D0' - 'D0 FF D2 D2 D2 FF DB DB DB FF D9 D9 D9 FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DB DB DB FF DB DB DB FF DA DA DA FF D9 D9' - 'D9 FF D9 D9 D9 FF CF CF CF FF C5 C5 C5 FF CC CC' - 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' - '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' - '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' - 'DC FF CE CE CE FF D6 D6 D6 FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' - 'DE FF D8 D8 D8 FF CE CE CE FF DD DD DD FF DC DC' - 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' - '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' - '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' - 'E1 FF DE DE DE FF CE CE CE FF D7 D7 D7 FF E1 E1' - 'E1 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF D9 D9' - 'D9 FF CD CD CD FF DA DA DA FF E3 E3 E3 FF D9 D9' - 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' - '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' - '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' - 'E3 FF E4 E4 E4 FF E1 E1 E1 FF D7 D7 D7 FF D2 D2' - 'D2 FF DA DA DA FF E4 E4 E4 FF E5 E5 E5 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E5 E5 E5 FF DC DC DC FF D2 D2 D2 FF D6 D6' - 'D6 FF E0 E0 E0 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' - 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' - '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' - '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF DF DF' - 'DF FF D2 D2 D2 FF D3 D3 D3 FF DE DE DE FF E3 E3' - 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3 E3 FF DE DE' - 'DE FF D4 D4 D4 FF D1 D1 D1 FF DD DD DD FF E7 E7' - 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' - 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' - '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' - 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' - 'EB FF EA EA EA FF E4 E4 E4 FF E0 E0 E0 FF DF DF' - 'DF FF DF DF DF FF DD DD DD FF DC DC DC FF DC DC' - 'DC FF DD DD DD FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E2 E2 E2 FF E9 E9 E9 FF EC EC EC FF EA EA' - 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' - 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' - 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' - 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' - 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' - 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' - 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' - 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' - 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' - 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' - 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' - 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' - 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' - 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' - 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' - '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' - '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' - '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' - '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' - '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FE 1F FF FF 00 00 FF FF' - 'FE 1F FF FF 00 00 FF 00 00 00 00 7F 00 00 FC 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' - '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 DC DC FF 00 DC DC FF 00 00 00 9C 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 00 FF FF FF 00 FF FF FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 6B FF FF FF 6B FF FF FF 00 00 00 30 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 C0 C0 C0 FF C0 C0 C0 FF 00 00 00 37 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 C5 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F1 00 00' - '00 B1 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 21 21' - '21 FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2B 2B' - '2B FF 2B 2B 2B FF 2E 2C 2D FF 13 13 13 FF 00 00' - '00 FF 00 00 00 69 00 00 00 09 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 AD 01 01 01 FF EB EB EB FF E8 E8' - 'E8 FF D5 D5 D5 FF 85 85 85 FF 92 92 92 FF 98 98' - '98 FF AD AD AD FF BA BA BA FF C3 C3 C3 FF C6 C6' - 'C6 FF CA CA CA FF CA CA CA FF CA CA CA FF D3 D3' - 'D3 FF D7 D7 D7 FF CC CC CC FF C7 C7 C7 FF C8 C9' - 'C9 FF 9D B3 A8 FF 20 A8 63 FF 90 AF A0 FF BF BB' - 'BD FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F0 19 19 19 FF EC EC EC FF E2 E2' - 'E2 FF CB CB CB FF 3B 3B 3B FF 56 56 56 FF 72 72' - '72 FF 92 92 92 FF 9D 9D 9D FF A8 A8 A8 FF AC AC' - 'AC FF A9 A9 A9 FF 9C 9C 9C FF 99 99 99 FF B7 B7' - 'B7 FF C3 C3 C3 FF A3 A3 A3 FF 98 98 98 FF C5 C4' - 'C4 FF 51 A7 7C FF 17 CE 71 FF 2F 99 64 FF C3 BD' - 'C0 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 28 28 28 FF EC EC EC FF E6 E6' - 'E6 FF D1 D1 D1 FF 68 68 68 FF 7E 7E 7E FF 85 85' - '85 FF 97 97 97 FF A0 A0 A0 FF AA AA AA FF AE AE' - 'AE FF 9F 9F 9F FF 83 83 83 FF 7C 7C 7C FF A8 A8' - 'A8 FF BB BB BB FF 8A 8A 8A FF 79 79 79 FF C2 C2' - 'C2 FF C6 C3 C4 FF 99 AC A2 FF C2 BE C0 FF C4 C4' - 'C4 FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 28 28 28 FF EE EE EE FF E7 E7' - 'E7 FF D6 D6 D6 FF 70 70 70 FF 7D 7D 7D FF 85 85' - '85 FF 97 97 97 FF A0 A0 A0 FF AA AA AA FF AE AE' - 'AE FF 98 98 98 FF 73 73 73 FF 6A 6A 6A FF A0 A0' - 'A0 FF B7 B7 B7 FF 7C 7C 7C FF 67 67 67 FF C2 C2' - 'C2 FF C4 C3 C4 FF C7 C4 C5 FF BF BF BF FF C5 C5' - 'C5 FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 27 27 27 FF F2 F2 F2 FF EB EB' - 'EB FF DF DF DF FF A7 A7 A7 FF AB AB AB FF AE AE' - 'AE FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF BA BA' - 'BA FF B7 B7 B7 FF B1 B1 B1 FF AF AF AF FF BA BA' - 'BA FF BE BE BE FF B0 B0 B0 FF AB AB AB FF C5 C5' - 'C5 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2 C2 FF C9 C9' - 'C9 FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 26 26 26 FF F3 F3 F3 FF EB EB' - 'EB FF EA EA EA FF ED ED ED FF E9 E9 E9 FF E8 E8' - 'E8 FF E4 E4 E4 FF E2 E2 E2 FF DF DF DF FF DE DE' - 'DE FF DB DB DB FF DC DC DC FF D9 D9 D9 FF D6 D6' - 'D6 FF D2 D2 D2 FF D2 D2 D2 FF D0 D0 D0 FF CB CB' - 'CB FF C9 C9 C9 FF C7 C7 C7 FF C0 C0 C0 FF CA CA' - 'CA FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 24 24 24 FF FF FF FF FF E9 E9' - 'E9 FF E2 E2 E2 FF E2 E2 E2 FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E3 E3 E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF' - 'EF FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FA 24 24 24 FF F8 F8 F8 FF D9 D9' - 'D9 FF BB BB BB FF BF BF BF FF DA DA DA FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF DB DB' - 'DB FF BC BC BC FF BB BB BB FF DE DE DE FF FF FF' - 'FF FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 D0 05 05 05 FF F6 F6 F6 FF BC BC' - 'BC FF C3 C3 C3 FF AB AB AB FF D8 D8 D8 FF D5 D5' - 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D5 D5' - 'D5 FF D8 D8 D8 FF D8 D8 D8 FF D5 D5 D5 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D7 D7 D7 FF C9 C9' - 'C9 FF C3 C3 C3 FF B3 B3 B3 FF D6 D6 D6 FF F5 F5' - 'F5 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9C 00 00 00 FF F4 F4 F4 FF CF CF' - 'CF FF D2 D2 D2 FF BF BF BF FF D3 D3 D3 FF D2 D2' - 'D2 FF D3 D3 D3 FF DD DD DD FF E3 E3 E3 FF E6 E6' - 'E6 FF ED ED ED FF ED ED ED FF E7 E7 E7 FF E4 E4' - 'E4 FF DE DE DE FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' - 'D3 FF D0 D0 D0 FF C2 C2 C2 FF D9 D9 D9 FF E8 E8' - 'E8 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 59 00 00 00 FF E9 E9 E9 FF D0 D0' - 'D0 FF CD CD CD FF CD CD CD FF D6 D6 D6 FF ED ED' - 'ED FF DC DC DC FF D4 D4 D4 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D5 D5 D5 FF DB DB DB FF ED ED ED FF DA DA' - 'DA FF CD CD CD FF CD CD CD FF DF DF DF FF B8 B8' - 'B8 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3E 00 00 00 FE D7 D7 D7 FF D2 D2' - 'D2 FF CB CB CB FF CA CA CA FF E9 E9 E9 FF DC DC' - 'DC FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D8 D8 D8 FF EA EA' - 'EA FF C9 C9 C9 FF CA CA CA FF E0 E0 E0 FF A0 A0' - 'A0 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 E1 9F 9F 9F FF DD DD' - 'DD FF CD CD CD FF DB DB DB FF CE CE CE FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' - 'CF FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF C8 C8' - 'C8 FF DA DA DA FF C7 C7 C7 FF E2 E2 E2 FF 5A 5A' - '5A FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 B2 83 83 83 FF DD DD' - 'DD FF D1 D1 D1 FF DB DB DB FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF D3 D3 D3 FF C8 C8 C8 FF DE DE DE FF 42 42' - '42 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4B 41 41 41 FF D8 D8' - 'D8 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C7 C7 C7 FF C4 C4' - 'C4 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' - 'C1 FF BF BF BF FF C0 C0 C0 FF B2 B2 B2 FF 1A 1A' - '1A FF 00 00 00 28 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1A 2C 2C 2C FF CC CC' - 'CC FF D5 D5 D5 FF CC CC CC FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF CF CF CF FF CC CC CC FF C6 C6 C6 FF C4 C4' - 'C4 FF B3 B3 B3 FF BD BD BD FF 99 99 99 FF 09 09' - '09 FF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 08 08 08 FF 97 97' - '97 FF DF DF DF FF DC DC DC FF D6 D6 D6 FF DE DE' - 'DE FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF D8 D8' - 'D8 FF DD DD DD FF DC DC DC FF 53 53 53 FF 00 00' - '00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 77 77' - '77 FF E2 E2 E2 FF E1 E1 E1 FF CE CE CE FF D7 D7' - 'D7 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF D9 D9 D9 FF CD CD' - 'CD FF E3 E3 E3 FF D9 D9 D9 FF 39 39 39 FF 00 00' - '00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 35 35' - '35 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' - 'E7 FF D2 D2 D2 FF D3 D3 D3 FF E3 E3 E3 FF E3 E3' - 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3' - 'E3 FF D4 D4 D4 FF D1 D1 D1 FF E7 E7 E7 FF E7 E7' - 'E7 FF E8 E8 E8 FF D4 D4 D4 FF 0B 0B 0B FF 00 00' - '00 ED 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 1E 1E' - '1E FF E4 E4 E4 FF ED ED ED FF E6 E6 E6 FF EC EC' - 'EC FF EA EA EA FF E4 E4 E4 FF DF DF DF FF DF DF' - 'DF FF DC DC DC FF DC DC DC FF DF DF DF FF DF DF' - 'DF FF E2 E2 E2 FF E9 E9 E9 FF EA EA EA FF E5 E5' - 'E5 FF EB EB EB FF D6 D6 D6 FF 00 00 00 FF 00 00' - '00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 AE 00 00' - '00 FF E0 E0 E0 FF C4 C4 C4 FF B8 B8 B8 FF B2 B2' - 'B2 FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F3 F3 F3 FF B0 B0 B0 FF B6 B6' - 'B6 FF EB EB EB FF CD CD CD FF 00 00 00 FF 00 00' - '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00' - '00 FF CE CE CE FF DD DD DD FF D5 D5 D5 FF E4 E4' - 'E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF DF DF DF FF D8 D8' - 'D8 FF D7 D7 D7 FF B0 B0 B0 FF 00 00 00 FF 00 00' - '00 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00' - '00 9C 0C 0C 0C FF 3D 3D 3D FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 49 49' - '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 5C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 06 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF 00 00 00 00 00 00' - '00 00 FF FE 3F FF FF FE 3F FF F0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' - '00 0F F0 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 3F FC 00' - '00 7F FF FF FF FF 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 78 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF 6B FF FF FF 6B FF' - 'FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 26 26 26 FF CD CD CD FF CD CD' - 'CD FF C9 C9 C9 FF C5 C5 C5 FF C2 C2 C2 FF C0 C0' - 'C0 FF BF BF BF FF BA BA BA FF B3 B4 B3 FF AB AC' - 'AC FF 09 09 09 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 30 D1 D1 D1 FF E7 E7 E7 FF 5F 5F' - '5F FF 8F 8F 8F FF A7 A7 A7 FF B9 B9 B9 FF B8 B8' - 'B8 FF 94 94 94 FF B7 B7 B7 FF C6 C3 C5 FF 91 D8' - 'B5 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 33 D1 D1 D1 FF EB EB EB FF 6C 6C' - '6C FF 8A 8A 8A FF A3 A3 A3 FF B9 B9 B9 FF A5 A5' - 'A5 FF 6B 6B 6B FF A4 A4 A4 FF C8 C8 C8 FF C2 C2' - 'C2 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 33 D3 D3 D3 FF F6 F6 F6 FF F5 F5' - 'F5 FF F4 F4 F4 FF F3 F3 F3 FF F1 F1 F1 FF F0 F0' - 'F0 FF EF EF EF FF EE EE EE FF ED ED ED FF EB EB' - 'EB FF 8D 8D 8D FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 25 DA DA DA FF A9 A9 A9 FF C3 C3' - 'C3 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' - 'D7 FF D8 D8 D8 FF D8 D8 D8 FF A8 A8 A8 FF B5 B5' - 'B5 FF 9C 9C 9C FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 7E 7E 7E FF CF CF CF FF D1 D1' - 'D1 FF DF DF DF FF E1 E1 E1 FF DC DC DC FF DC DC' - 'DC FF E1 E1 E1 FF E1 E1 E1 FF D0 D0 D0 FF D1 D1' - 'D1 FF 3F 3F 3F FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 22 22 FF CA CA CA FF E4 E4' - 'E4 FF D1 D1 D1 FF D0 D0 D0 FF CD CD CD FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF E2 E2 E2 FF C9 C9' - 'C9 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF C3 C3' - 'C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF CB CB' - 'CB FF 00 00 00 F8 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 D8 DB DB DB FF D2 D2' - 'D2 FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF CF CF CF FF CA CA' - 'CA FF 00 00 00 B8 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 89 C9 C9 C9 FF E4 E4' - 'E4 FF D2 D2 D2 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4' - 'E4 FF E5 E5 E5 FF D2 D2 D2 FF E4 E4 E4 FF A8 A8' - 'A8 FF 00 00 00 4E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 99 99 99 FF BD BD' - 'BD FF EC EC EC FF EE EE EE FF EC EC EC FF EC EC' - 'EC FF EE EE EE FF E4 E4 E4 FF D1 D1 D1 FF 75 75' - '75 FF 00 00 00 06 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 19 19 19 FF D3 D3' - 'D3 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D9 D9 D9 FF CD CD CD FF 06 06' - '06 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E0 03 00 00 C0 03 00 00 80 03' - '00 00 80 03 00 00 80 03 00 00 80 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 E0 07 00 00 F0 0F 00 00' -} */ - -/* BINRES netdrive2.ico */ -10 ICON netdrive2.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 8E 11 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 5E 23 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 C6 29 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 6E 4F 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 02 02 02 00 04 04 04 00 05 06 06 00 06 06' - '06 00 00 00 0D 00 09 09 09 00 0A 0A 0A 00 0C 0C' - '0C 00 12 12 12 00 14 14 14 00 15 15 15 00 16 16' - '16 00 1F 1F 10 00 1D 1D 1D 00 00 00 20 00 00 00' - '2C 00 00 00 2D 00 21 21 21 00 22 22 22 00 23 23' - '23 00 24 24 24 00 25 25 25 00 26 26 26 00 38 38' - '38 00 39 39 39 00 3B 3B 3B 00 43 43 43 00 46 46' - '46 00 4A 4A 4A 00 54 4C 50 00 53 53 53 00 55 55' - '55 00 56 56 56 00 59 59 52 00 5A 5A 53 00 5C 5C' - '55 00 5D 5D 56 00 58 58 58 00 59 59 59 00 5A 58' - '59 00 5A 5A 5A 00 5B 5B 5B 00 5C 5C 5C 00 5D 5D' - '5D 00 5E 5E 5E 00 65 58 5F 00 60 60 60 00 61 61' - '61 00 62 62 62 00 64 64 64 00 67 67 67 00 69 69' - '69 00 71 71 71 00 72 72 72 00 73 73 73 00 75 75' - '75 00 78 78 78 00 7A 7A 7A 00 7B 7B 7B 00 7C 7C' - '7C 00 7F 7F 7F 00 24 A7 64 00 3C AD 74 00 25 DC' - '7F 00 7C 7C A3 00 00 00 C9 00 00 00 CD 00 00 00' - 'D3 00 00 00 D8 00 00 00 FF 00 2B 2B FF 00 7D AA' - '94 00 81 81 81 00 83 83 83 00 89 89 89 00 8A 8A' - '8A 00 8B 8B 8B 00 8F 8F 8F 00 91 89 8C 00 90 90' - '90 00 91 91 91 00 94 94 94 00 95 95 95 00 97 97' - '97 00 99 99 99 00 9A 9A 9A 00 9C 9C 9C 00 9D 9D' - '9D 00 9E 9E 9E 00 9F 9F 9F 00 94 B6 A4 00 93 BD' - 'A9 00 A0 A0 A0 00 A1 A1 A1 00 A3 A3 A3 00 A4 A4' - 'A4 00 A5 A5 A5 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' - 'AA 00 AC AC AC 00 AD AD AD 00 AE AE AE 00 AF AF' - 'AF 00 B8 B8 A7 00 AA AA BC 00 AD B9 B3 00 B0 B0' - 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' - 'B4 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B9 B9' - 'B9 00 BC BC BC 00 BD BD BD 00 BE BE BE 00 BF BF' - 'BF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C0 C1 00 C2 C2' - 'C2 00 C3 C3 C3 00 C4 C1 C2 00 C5 C2 C4 00 C4 C4' - 'C4 00 C5 C5 C5 00 C6 C5 C6 00 C6 C6 C6 00 C8 C3' - 'C5 00 CC C4 C8 00 C8 C8 C8 00 C9 C9 C9 00 CB C9' - 'CA 00 CA CA CA 00 CB CB CB 00 CC CC CC 00 CD CD' - 'CD 00 CE CE CE 00 CF CF CF 00 D2 C1 CA 00 D3 C8' - 'CD 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3' - 'D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7' - 'D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA DA 00 DB DB' - 'DB 00 DC DC DC 00 DD DD DD 00 DE DE DE 00 DF DF' - 'DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3' - 'E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7' - 'E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' - 'EB 00 EC EC EC 00 ED ED ED 00 EE EE EE 00 EF EF' - 'EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2 F2 00 F4 F4' - 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' - 'F8 00 F9 F9 F9 00 FC FC FC 00 FD FD FD 00 FF FF' - 'FF 00 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 6E 65 74 64 72 69 76 65 32' - '2E 69 63 6F 00 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 42 45 BD 00 45' - '42 BD 00 00 00 00 00 00 00 00 00 00 00 00 BD BD' - 'BD BD BD BD BD BD BD BD BD BD BD 05 46 43 43 46' - '05 BD BD BD BD BD BD BD BD BD BD BD BD BD 6E 6E' - '6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 69 41 46 46 41' - '69 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 47 46 46 47' - 'BD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 44 46 6A 6A 46' - '44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 BD BD BD BD BD BD BD BD BD 10 0F 0D 0D 0F' - '11 BD BD BD BD BD BD BD BD 00 00 00 00 00 00 00' - '00 BD BD 0A 2D 2D 33 32 31 2F 2D 25 24 21 20 23' - '22 26 26 26 21 28 2E 1E 06 BD 00 00 00 00 00 00' - '00 BD 0A 79 B5 AB 63 70 74 7A 91 93 97 98 9D 9D' - '9C 9E 9B 99 8D 84 3F 5C 4F 03 BD 00 00 00 00 00' - '00 BD 21 B7 A7 A5 0E 1D 3A 4D 58 5F 68 64 5A 57' - '64 72 61 54 90 48 40 3E 8F 17 BD 00 00 00 00 00' - '00 BD 2C B3 A8 A4 1F 3B 4C 52 5F 63 70 64 53 50' - '5D 6C 56 4B 88 7B 5B 6B 7E 17 BD 00 00 00 00 00' - '00 BD 2A B4 AA A9 2B 36 4A 4E 5A 61 6F 5E 39 35' - '4D 5D 49 33 8A 82 85 7F 79 16 BD 00 00 00 00 00' - '00 BD 2A B6 AD A9 49 50 56 5D 63 66 70 65 57 55' - '5F 67 58 51 86 81 7A 7A 7D 15 BD 00 00 00 00 00' - '00 BD 29 B8 B1 B0 BA B9 B5 B3 AF AD AA A8 AB A9' - 'A5 A1 A1 A1 97 95 93 8A 80 14 BD 00 00 00 00 00' - '00 BD 27 BC B0 AE AD A8 A8 A7 A8 A8 A9 A8 A8 A8' - 'A8 A8 A8 A7 AA AE AD B9 96 12 BD 00 00 00 00 00' - '00 BD 2C BC 83 6D 75 99 98 98 98 98 97 97 97 97' - '98 98 98 99 92 71 71 97 B6 17 BD 00 00 00 00 00' - '00 BD 1B BC 68 73 62 92 98 96 94 92 95 96 96 95' - '92 93 95 9B 74 6E 63 86 A9 0E BD 00 00 00 00 00' - '00 BD 14 A9 8D 91 83 91 8D 9A A5 A4 A7 AB AB A8' - 'A5 A6 9C 8E 8E 8E 80 99 77 07 BD 00 00 00 00 00' - '00 BD 09 92 92 8B 8C 8C AA A7 9B 99 98 97 97 98' - '99 9C A7 AA 91 89 8C A3 54 BD BD 00 00 00 00 00' - '00 BD 01 60 99 87 8C A6 94 8D 91 91 8E 91 91 91' - '91 91 8C 8E A7 8E 83 AA 30 BD BD 00 00 00 00 00' - '00 BD BD 38 A5 87 9B 93 8D 91 8E 91 8C 89 8A 8A' - '8A 8A 8A 89 8B 9B 7D B0 19 BD BD 00 00 00 00 00' - '00 00 BD 1C AB 8E 99 8D 91 91 91 91 91 8B 7C 7D' - '80 81 81 81 7D 8C 81 AC 0B BD 00 00 00 00 00 00' - '00 00 BD 13 AF 92 92 93 92 92 92 92 92 93 8C 80' - '79 78 77 79 79 79 83 97 01 BD 00 00 00 00 00 00' - '00 00 BD 02 9F 9A 8B 99 97 98 98 98 98 98 98 99' - '98 95 91 8B 87 73 87 6F BD BD 00 00 00 00 00 00' - '00 00 BD BD 81 A4 94 94 9F 9D 9C 9C 9C 9C 9C 9C' - '9D 9D 9E A0 97 94 9E 4B BD BD 00 00 00 00 00 00' - '00 00 00 BD 51 A7 A4 96 97 A1 A4 A2 A2 A2 A2 A2' - 'A2 A4 A0 99 93 A8 99 26 BD 00 00 00 00 00 00 00' - '00 00 00 BD 33 A7 A8 A8 A0 92 9A A3 A4 A5 A5 A4' - 'A3 9A 92 A0 A9 AC 8D 18 BD 00 00 00 00 00 00 00' - '00 00 00 BD 1A 9E AB 9A AD AF A7 A3 A2 9F 9F A2' - 'A3 A5 AF A5 9C B2 83 0E BD 00 00 00 00 00 00 00' - '00 00 00 BD 17 9F 7A 66 81 B3 B1 B1 B1 B0 B0 B1' - 'B1 B1 AE 71 66 A8 76 0C BD 00 00 00 00 00 00 00' - '00 00 00 BD 08 59 AD A5 B6 BB BA BA BA BA BA BA' - 'BA BA BA B2 A7 A6 37 BD BD 00 00 00 00 00 00 00' - '00 00 00 BD BD 0C 38 3B 3A 39 39 39 39 39 39 39' - '39 39 39 3A 3C 34 04 BD 00 00 00 00 00 00 00 00' - '00 00 00 00 BD BD BD BD BD BD BD BD BD BD BD BD' - 'BD BD BD BD BD BD BD 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' - '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF FF F8' - '1F FF F0 00 00 1F E0 00 00 0F E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 06 06 06 00 09 09' - '09 00 19 19 19 00 22 22 22 00 26 26 26 00 3F 3F' - '3F 00 5F 5F 5F 00 6B 6B 6B 00 6C 6C 6C 00 75 75' - '75 00 7E 7E 7E 00 7F 7F 7F 00 00 00 FF 00 8A 8A' - '8A 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F 8F 00 94 94' - '94 00 99 99 99 00 9C 9C 9C 00 A3 A3 A3 00 A4 A4' - 'A4 00 A5 A5 A5 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9' - 'A9 00 AB AC AC 00 B3 B4 B3 00 B5 B5 B5 00 B7 B7' - 'B7 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BD BD' - 'BD 00 BF BF BF 00 91 D8 B5 00 C0 C0 C0 00 C2 C2' - 'C2 00 C3 C3 C3 00 C6 C3 C5 00 C4 C4 C4 00 C5 C5' - 'C5 00 C8 C8 C8 00 C9 C9 C9 00 CA CA CA 00 CB CB' - 'CB 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' - 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D7 D7' - 'D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA DA 00 DB DB' - 'DB 00 DC DC DC 00 DF DF DF 00 E1 E1 E1 00 E2 E2' - 'E2 00 E4 E4 E4 00 E5 E5 E5 00 E7 E7 E7 00 EB EB' - 'EB 00 EC EC EC 00 ED ED ED 00 EE EE EE 00 EF EF' - 'EF 00 F0 F0 F0 00 F1 F1 F1 00 F3 F3 F3 00 F4 F4' - 'F4 00 F5 F5 F5 00 F6 F6 F6 00 00 00 00 00 8F 8F' - '8F 00 91 89 8C 00 90 90 90 00 91 91 91 00 94 94' - '94 00 95 95 95 00 97 97 97 00 99 99 99 00 9A 9A' - '9A 00 9C 9C 9C 00 9D 9D 9D 00 9E 9E 9E 00 9F 9F' - '9F 00 94 B6 A4 00 93 BD A9 00 A0 A0 A0 00 A1 A1' - 'A1 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A8 A8' - 'A8 00 A9 A9 A9 00 AA AA AA 00 AC AC AC 00 AD AD' - 'AD 00 AE AE AE 00 AF AF AF 00 B8 B8 A7 00 AA AA' - 'BC 00 AD B9 B3 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' - 'B2 00 B3 B3 B3 00 B4 B4 B4 00 B5 B5 B5 00 B6 B6' - 'B6 00 B7 B7 B7 00 B9 B9 B9 00 BC BC BC 00 BD BD' - 'BD 00 BE BE BE 00 BF BF BF 00 C0 C0 C0 00 C1 C1' - 'C1 00 C2 C0 C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1' - 'C2 00 C5 C2 C4 00 C4 C4 C4 00 C5 C5 C5 00 C6 C5' - 'C6 00 C6 C6 C6 00 C8 C3 C5 00 CC C4 C8 00 C8 C8' - 'C8 00 C9 C9 C9 00 CB C9 CA 00 CA CA CA 00 CB CB' - 'CB 00 CC CC CC 00 CD CD CD 00 CE CE CE 00 CF CF' - 'CF 00 D2 C1 CA 00 D3 C8 CD 00 D0 D0 D0 00 D1 D1' - 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' - 'D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9' - 'D9 00 DA DA DA 00 DB DB DB 00 DC DC DC 00 DD DD' - 'DD 00 DE DE DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1' - 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' - 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' - 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' - 'ED 00 EE EE EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1' - 'F1 00 F2 F2 F2 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' - 'F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9 F9 00 FC FC' - 'FC 00 FD FD FD 00 FF FF FF 00 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6E' - '65 74 64 72 69 76 65 32 2E 69 63 6F 00 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 4D 4D 4D 4D 4D 4D 4D 0D 0D 4D' - '4D 4D 4D 4D 4D 4D 25 25 25 25 25 25 25 0D 0D 25' - '25 25 25 25 25 25 00 00 00 4D 4D 4D 4D 4D 4D 4D' - '4D 4D 4D 4D 00 00 00 00 05 2F 2F 2C 2A 26 25 23' - '21 1C 1B 02 00 00 00 4D 33 41 07 11 18 20 1F 12' - '1E 28 24 10 00 00 00 4D 33 42 09 0E 15 20 17 08' - '16 2B 26 10 00 00 00 4D 35 4C 4B 4A 49 48 47 46' - '45 44 42 0F 00 00 00 4D 39 1A 27 37 37 36 36 37' - '37 19 1D 14 00 00 00 00 0B 31 33 3C 3D 3B 3B 3D' - '3D 32 33 06 00 00 00 00 04 2D 3F 33 32 2F 30 30' - '30 3E 2C 4D 00 00 00 00 4D 33 33 33 33 33 27 29' - '29 29 2E 4D 00 00 00 00 4D 3A 34 39 39 39 39 39' - '39 31 2D 4D 00 00 00 00 4D 2C 3F 34 40 3F 3F 40' - '34 3F 19 4D 00 00 00 00 4D 13 22 43 45 43 43 45' - '3F 33 0A 4D 00 00 00 00 00 03 35 37 37 37 37 37' - '38 2F 01 00 00 00 00 00 00 00 4D 4D 4D 4D 4D 4D' - '4D 4D 00 00 00 00 00 00 00 00 00 00 00 00 E0 03' - '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' - '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' - '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 0C C0 0C C0 00 00 00 00 00 00 00 00' - '00 00 00 00 00 CC CC 00 00 00 00 00 00 00 77 77' - '77 77 77 77 77 8C C8 77 77 77 77 77 77 77 00 00' - '00 00 00 00 00 CC CC 00 00 00 00 00 00 00 00 00' - '00 00 00 00 0C C7 7C C0 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 88 88 88 88 88 88 88 88 88 88 00 00 00 00 00' - '07 FF 77 77 77 77 77 77 77 77 67 80 00 00 00 00' - '8F FF 08 88 87 77 88 77 78 78 66 70 00 00 00 00' - '8F FF 88 88 77 77 88 77 88 77 77 70 00 00 00 00' - '8F FF 88 88 87 77 88 87 88 77 77 70 00 00 00 00' - '8F FF 88 87 77 77 88 77 88 77 77 70 00 00 00 00' - '8F FF FF FF FF FF FF FF FF 77 77 70 00 00 00 00' - '8F FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00' - '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' - '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' - '0F 77 77 77 FF FF FF FF 77 77 77 70 00 00 00 00' - '07 77 77 FF 77 77 77 77 FF 77 7F 80 00 00 00 00' - '07 77 7F 77 77 77 77 77 77 F7 7F 80 00 00 00 00' - '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' - '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' - '00 F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' - '00 77 77 77 77 77 77 77 77 77 77 00 00 00 00 00' - '00 7F 77 77 77 77 77 77 77 77 78 00 00 00 00 00' - '00 8F F7 7F FF FF FF FF 77 7F 78 00 00 00 00 00' - '00 8F FF 77 7F FF FF F7 77 FF 70 00 00 00 00 00' - '00 07 F7 FF FF F7 7F FF FF 7F 70 00 00 00 00 00' - '00 07 77 7F FF FF FF FF F7 7F 70 00 00 00 00 00' - '00 08 FF FF FF FF FF FF FF FF 80 00 00 00 00 00' - '00 00 88 88 88 88 88 88 88 88 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' - '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF FF F8' - '1F FF F0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 0C C0 00 00 00 77 77' - '77 7C C7 77 77 77 00 00 00 00 00 00 00 00 00 07' - '77 77 77 77 70 00 00 7F 88 77 78 77 78 00 00 7F' - '88 77 78 77 78 00 00 7F FF FF FF FF F8 00 00 77' - '77 77 77 77 78 00 00 87 77 F7 7F F7 70 00 00 07' - 'F7 77 77 7F 70 00 00 07 77 77 77 77 70 00 00 07' - '77 77 77 77 70 00 00 07 F7 FF FF 7F 70 00 00 08' - '7F FF FF F7 80 00 00 00 77 77 77 77 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 03' - '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' - '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' - '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' - '00 00 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF 00 00 00 9C 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 00 00 FF FF 00 00' - 'FF FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF 00 00 00 3C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 01 00 00 00 04 00 00 00 09 00 00' - '00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00' - '00 09 00 00 FF FF 00 00 FF FF C0 C0 C0 FF C0 C0' - 'C0 FF 00 00 FF FF 00 00 FF FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 05 00 00 00 C5 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F1 00 00 00 B1 00 00 00 0D 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' - '00 9B 00 00 00 FF 21 21 21 FF 2B 2B 2B FF 2C 2C' - '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' - '2D FF 13 13 13 FF 00 00 00 FF 00 00 00 69 00 00' - '00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 AD 01 01' - '01 FF EB EB EB FF E8 E8 E8 FF D5 D5 D5 FF 85 85' - '85 FF 92 92 92 FF 98 98 98 FF AD AD AD FF BA BA' - 'BA FF C3 C3 C3 FF C6 C6 C6 FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF D3 D3 D3 FF D7 D7 D7 FF CC CC' - 'CC FF C7 C7 C7 FF C8 C9 C9 FF 9D B3 A8 FF 20 A8' - '63 FF 90 AF A0 FF BF BB BD FF 00 00 00 FF 00 00' - '00 81 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F0 19 19' - '19 FF EC EC EC FF E2 E2 E2 FF CB CB CB FF 3B 3B' - '3B FF 56 56 56 FF 72 72 72 FF 92 92 92 FF 9D 9D' - '9D FF A8 A8 A8 FF AC AC AC FF A9 A9 A9 FF 9C 9C' - '9C FF 99 99 99 FF B7 B7 B7 FF C3 C3 C3 FF A3 A3' - 'A3 FF 98 98 98 FF C5 C4 C4 FF 51 A7 7C FF 17 CE' - '71 FF 2F 99 64 FF C3 BD C0 FF 01 01 01 FF 00 00' - '00 A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 28 28' - '28 FF EC EC EC FF E6 E6 E6 FF D1 D1 D1 FF 68 68' - '68 FF 7E 7E 7E FF 85 85 85 FF 97 97 97 FF A0 A0' - 'A0 FF AA AA AA FF AE AE AE FF 9F 9F 9F FF 83 83' - '83 FF 7C 7C 7C FF A8 A8 A8 FF BB BB BB FF 8A 8A' - '8A FF 79 79 79 FF C2 C2 C2 FF C6 C3 C4 FF 99 AC' - 'A2 FF C2 BE C0 FF C4 C4 C4 FF 01 01 01 FF 00 00' - '00 BA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 28 28' - '28 FF EE EE EE FF E7 E7 E7 FF D6 D6 D6 FF 70 70' - '70 FF 7D 7D 7D FF 85 85 85 FF 97 97 97 FF A0 A0' - 'A0 FF AA AA AA FF AE AE AE FF 98 98 98 FF 73 73' - '73 FF 6A 6A 6A FF A0 A0 A0 FF B7 B7 B7 FF 7C 7C' - '7C FF 67 67 67 FF C2 C2 C2 FF C4 C3 C4 FF C7 C4' - 'C5 FF BF BF BF FF C5 C5 C5 FF 01 01 01 FF 00 00' - '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 27 27' - '27 FF F2 F2 F2 FF EB EB EB FF DF DF DF FF A7 A7' - 'A7 FF AB AB AB FF AE AE AE FF B3 B3 B3 FF B6 B6' - 'B6 FF B9 B9 B9 FF BA BA BA FF B7 B7 B7 FF B1 B1' - 'B1 FF AF AF AF FF BA BA BA FF BE BE BE FF B0 B0' - 'B0 FF AB AB AB FF C5 C5 C5 FF C6 C6 C6 FF C4 C4' - 'C4 FF C2 C2 C2 FF C9 C9 C9 FF 00 00 00 FF 00 00' - '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 26 26' - '26 FF F3 F3 F3 FF EB EB EB FF EA EA EA FF ED ED' - 'ED FF E9 E9 E9 FF E8 E8 E8 FF E4 E4 E4 FF E2 E2' - 'E2 FF DF DF DF FF DE DE DE FF DB DB DB FF DC DC' - 'DC FF D9 D9 D9 FF D6 D6 D6 FF D2 D2 D2 FF D2 D2' - 'D2 FF D0 D0 D0 FF CB CB CB FF C9 C9 C9 FF C7 C7' - 'C7 FF C0 C0 C0 FF CA CA CA FF 00 00 00 FF 00 00' - '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 24 24' - '24 FF FF FF FF FF E9 E9 E9 FF E2 E2 E2 FF E2 E2' - 'E2 FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E3 E3 E3 FF E3 E3' - 'E3 FF F8 F8 F8 FF EF EF EF FF 00 00 00 FF 00 00' - '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FA 24 24' - '24 FF F8 F8 F8 FF D9 D9 D9 FF BB BB BB FF BF BF' - 'BF FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF DB DB DB FF BC BC BC FF BB BB' - 'BB FF DE DE DE FF FF FF FF FF 00 00 00 FF 00 00' - '00 BA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 D0 05 05' - '05 FF F6 F6 F6 FF BC BC BC FF C3 C3 C3 FF AB AB' - 'AB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' - 'D4 FF D3 D3 D3 FF D5 D5 D5 FF D8 D8 D8 FF D8 D8' - 'D8 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4' - 'D4 FF D7 D7 D7 FF C9 C9 C9 FF C3 C3 C3 FF B3 B3' - 'B3 FF D6 D6 D6 FF F5 F5 F5 FF 00 00 00 FF 00 00' - '00 8C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' - '00 FF F4 F4 F4 FF CF CF CF FF D2 D2 D2 FF BF BF' - 'BF FF D3 D3 D3 FF D2 D2 D2 FF D3 D3 D3 FF DD DD' - 'DD FF E3 E3 E3 FF E6 E6 E6 FF ED ED ED FF ED ED' - 'ED FF E7 E7 E7 FF E4 E4 E4 FF DE DE DE FF D4 D4' - 'D4 FF D2 D2 D2 FF D3 D3 D3 FF D0 D0 D0 FF C2 C2' - 'C2 FF D9 D9 D9 FF E8 E8 E8 FF 00 00 00 FF 00 00' - '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' - '00 FF E9 E9 E9 FF D0 D0 D0 FF CD CD CD FF CD CD' - 'CD FF D6 D6 D6 FF ED ED ED FF DC DC DC FF D4 D4' - 'D4 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5 D5 FF DB DB' - 'DB FF ED ED ED FF DA DA DA FF CD CD CD FF CD CD' - 'CD FF DF DF DF FF B8 B8 B8 FF 00 00 00 FB 00 00' - '00 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' - '00 FE D7 D7 D7 FF D2 D2 D2 FF CB CB CB FF CA CA' - 'CA FF E9 E9 E9 FF DC DC DC FF D1 D1 D1 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' - 'D1 FF D8 D8 D8 FF EA EA EA FF C9 C9 C9 FF CA CA' - 'CA FF E0 E0 E0 FF A0 A0 A0 FF 00 00 00 EB 00 00' - '00 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 E1 9F 9F 9F FF DD DD DD FF CD CD CD FF DB DB' - 'DB FF CE CE CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF C8 C8 C8 FF DA DA DA FF C7 C7' - 'C7 FF E2 E2 E2 FF 5A 5A 5A FF 00 00 00 94 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 B2 83 83 83 FF DD DD DD FF D1 D1 D1 FF DB DB' - 'DB FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF C9 C9 C9 FF C5 C5' - 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF D3 D3 D3 FF C8 C8' - 'C8 FF DE DE DE FF 42 42 42 FF 00 00 00 6C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4B 41 41 41 FF D8 D8 D8 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF C7 C7 C7 FF C4 C4 C4 FF C1 C1 C1 FF C0 C0' - 'C0 FF C1 C1 C1 FF C1 C1 C1 FF BF BF BF FF C0 C0' - 'C0 FF B2 B2 B2 FF 1A 1A 1A FF 00 00 00 28 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1A 2C 2C 2C FF CC CC CC FF D5 D5 D5 FF CC CC' - 'CC FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D5 D5 D5 FF CF CF CF FF CC CC' - 'CC FF C6 C6 C6 FF C4 C4 C4 FF B3 B3 B3 FF BD BD' - 'BD FF 99 99 99 FF 09 09 09 FF 00 00 00 19 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 08 08 08 FF 97 97 97 FF DF DF DF FF DC DC' - 'DC FF D6 D6 D6 FF DE DE DE FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DE DE DE FF D8 D8 D8 FF DD DD DD FF DC DC' - 'DC FF 53 53 53 FF 00 00 00 FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 77 77 77 FF E2 E2 E2 FF E1 E1' - 'E1 FF CE CE CE FF D7 D7 D7 FF E2 E2 E2 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' - 'E1 FF D9 D9 D9 FF CD CD CD FF E3 E3 E3 FF D9 D9' - 'D9 FF 39 39 39 FF 00 00 00 FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF 35 35 35 FF E6 E6 E6 FF E6 E6' - 'E6 FF E7 E7 E7 FF E7 E7 E7 FF D2 D2 D2 FF D3 D3' - 'D3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' - 'E4 FF E3 E3 E3 FF E3 E3 E3 FF D4 D4 D4 FF D1 D1' - 'D1 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF D4 D4' - 'D4 FF 0B 0B 0B FF 00 00 00 ED 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 F9 1E 1E 1E FF E4 E4 E4 FF ED ED' - 'ED FF E6 E6 E6 FF EC EC EC FF EA EA EA FF E4 E4' - 'E4 FF DF DF DF FF DF DF DF FF DC DC DC FF DC DC' - 'DC FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' - 'E9 FF EA EA EA FF E5 E5 E5 FF EB EB EB FF D6 D6' - 'D6 FF 00 00 00 FF 00 00 00 C3 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 AE 00 00 00 FF E0 E0 E0 FF C4 C4' - 'C4 FF B8 B8 B8 FF B2 B2 B2 FF F1 F1 F1 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' - 'F3 FF B0 B0 B0 FF B6 B6 B6 FF EB EB EB FF CD CD' - 'CD FF 00 00 00 FF 00 00 00 85 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 80 00 00 00 FF CE CE CE FF DD DD' - 'DD FF D5 D5 D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' - 'FA FF DF DF DF FF D8 D8 D8 FF D7 D7 D7 FF B0 B0' - 'B0 FF 00 00 00 FF 00 00 00 67 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 02 00 00 00 9C 0C 0C 0C FF 3D 3D' - '3D FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 49 49 49 FF 2F 2F 2F FF 02 02' - '02 FF 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 06 00 00 00 F1 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 D6 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' - '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF F8 00' - '1F FF F0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' - '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' - '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 1F F8 00' - '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' - '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' - '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - 'CC 00 00 CC 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 CC C0 0C CC 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '0C CC CC C0 00 00 00 00 00 00 00 00 00 00 88 88' - '88 88 88 88 88 88 88 88 88 CC CC 88 88 88 88 88' - '88 88 88 88 88 88 77 77 77 77 77 77 77 77 77 77' - '77 CC CC 77 77 77 77 77 77 77 77 77 77 77 00 00' - '00 00 00 00 00 00 00 00 0C CC CC C0 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - 'CC C7 7C CC 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 CC 07 70 CC 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' - '00 08 FF F7 88 88 77 77 77 77 77 77 77 77 77 77' - '66 87 80 00 00 00 00 00 00 07 FF F7 00 88 88 87' - '77 77 87 87 77 77 87 78 66 67 80 00 00 00 00 00' - '00 07 FF F7 88 88 88 77 77 77 87 87 87 87 87 77' - '77 87 80 00 00 00 00 00 00 07 FF F7 88 88 88 77' - '77 78 87 87 87 87 87 77 77 77 80 00 00 00 00 00' - '00 07 FF F7 88 88 88 77 77 78 87 87 87 87 87 77' - '77 77 80 00 00 00 00 00 00 07 FF F7 88 88 88 87' - '77 78 87 88 87 87 87 77 77 77 80 00 00 00 00 00' - '00 07 FF F7 77 77 77 77 77 77 77 77 77 77 77 77' - '77 77 80 00 00 00 00 00 00 07 FF FF FF FF FF FF' - '77 77 77 77 77 77 77 77 77 77 80 00 00 00 00 00' - '00 07 FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF F7 80 00 00 00 00 00 00 07 FF FF FF 77 77 7F' - 'FF FF FF FF FF FF FF FF FF FF 80 00 00 00 00 00' - '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 7F 80 00 00 00 00 00' - '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 7F' - 'FF FF FF FF F7 77 77 77 77 7F 80 00 00 00 00 00' - '00 08 F7 77 77 77 7F FF 77 77 77 77 FF FF 77 77' - '77 77 00 00 00 00 00 00 00 08 F7 77 77 7F F7 77' - '77 77 77 77 77 7F F7 77 77 77 00 00 00 00 00 00' - '00 00 77 77 77 F7 77 77 77 77 77 77 77 77 7F 77' - '77 F7 00 00 00 00 00 00 00 00 77 77 7F 77 77 77' - '77 77 77 77 77 77 77 F7 77 F8 00 00 00 00 00 00' - '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 F8 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' - '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 70 00 00 00 00 00 00 00 00 87 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' - '00 00 07 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 00 00 07 77 77 77 77 77' - '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' - '00 00 08 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 80 00 00 00 00 00 00 00 00 08 7F F7 77 FF FF' - 'FF FF FF FF FF FF 77 7F 77 00 00 00 00 00 00 00' - '00 00 08 7F FF F7 77 FF FF FF FF FF FF 77 7F FF' - '77 00 00 00 00 00 00 00 00 00 00 7F FF FF 77 77' - 'FF FF FF FF 77 77 FF FF 78 00 00 00 00 00 00 00' - '00 00 00 7F FF FF FF FF 77 77 77 77 7F FF FF FF' - '78 00 00 00 00 00 00 00 00 00 00 8F 77 77 FF FF' - 'FF FF FF FF FF FF 77 7F 78 00 00 00 00 00 00 00' - '00 00 00 8F 77 77 FF FF FF FF FF FF FF F7 77 7F' - '78 00 00 00 00 00 00 00 00 00 00 87 77 7F FF FF' - 'FF FF FF FF FF FF 77 77 70 00 00 00 00 00 00 00' - '00 00 00 08 77 77 77 77 77 77 77 77 77 77 77 77' - '80 00 00 00 00 00 00 00 00 00 00 00 08 88 88 88' - '88 88 88 88 88 88 88 80 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF F1 C7 FF FF 00 00 FF FF' - 'F0 07 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'F8 0F FF FF 00 00 FF FF F0 07 FF FF 00 00 FF FF' - 'F2 07 FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' - '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' - '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' - '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - 'FF FF 00 00 FF FF 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 FF FF 00 00 FF FF 00 00' - '00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 30 00 00 00 24 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' - '00 30 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' - '00 3C 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 9C 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' - 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 3C 00 00' - '00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - 'FF FF 00 00 FF FF 00 00 FF FF C0 C0 C0 FF C0 C0' - 'C0 FF 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' - '00 15 00 00 00 09 00 00 00 09 00 00 00 09 00 00' - '00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00' - '00 09 00 00 00 09 00 00 00 09 00 00 00 07 00 00' - '00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - 'FF FF 00 00 FF FF 00 00 00 37 C0 C0 C0 FF C0 C0' - 'C0 FF 00 00 00 37 00 00 FF FF 00 00 FF FF 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 35 00 00 00 18 00 00' - '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' - '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F1 00 00 00 B1 00 00' - '00 5C 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' - '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' - '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' - '2D FF 2E 2C 2D FF 13 13 13 FF 00 00 00 FF 00 00' - '00 F6 00 00 00 69 00 00 00 09 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' - '90 FF CA CA CA FF CD CD CD FF CB CB CB FF CE CE' - 'CE FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' - 'C9 FF C7 C7 C7 FF C6 C6 C6 FF C5 C5 C5 FF C4 C4' - 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2 C2 FF C3 C3' - 'C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF BF FF BF BF' - 'BF FF BC BC BC FF BD BD BD FF BA BA BA FF BB BB' - 'BB FF B5 B5 B5 FF B3 B4 B3 FF B8 B4 B6 FF AD AD' - 'AD FF AB AC AC FF AD A8 AB FF 63 63 63 FF 09 09' - '09 FF 00 00 00 EF 00 00 00 42 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF EB EB' - 'EB FF E8 E8 E8 FF E7 E7 E7 FF D5 D5 D5 FF 85 85' - '85 FF 88 88 88 FF 92 92 92 FF 98 98 98 FF A2 A2' - 'A2 FF AD AD AD FF BA BA BA FF C0 C0 C0 FF C3 C3' - 'C3 FF C6 C6 C6 FF CB CB CB FF CA CA CA FF CA CA' - 'CA FF D6 D6 D6 FF CA CA CA FF D3 D3 D3 FF CB CB' - 'CB FF D7 D7 D7 FF CC CC CC FF D4 D4 D4 FF C7 C7' - 'C7 FF C8 C9 C9 FF C6 C2 C4 FF 9D B3 A8 FF 20 A8' - '63 FF 1C A8 60 FF 90 AF A0 FF BF BB BD FF 4F 4F' - '4F FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 15 00 00 00 F0 19 19 19 FF C7 C7 C7 FF EC EC' - 'EC FF E2 E2 E2 FF E6 E6 E6 FF CB CB CB FF 3B 3B' - '3B FF 3F 3F 3F FF 56 56 56 FF 72 72 72 FF 87 87' - '87 FF 92 92 92 FF 9D 9D 9D FF A5 A5 A5 FF A8 A8' - 'A8 FF AC AC AC FF B7 B7 B7 FF A9 A9 A9 FF 9C 9C' - '9C FF BD BD BD FF 99 99 99 FF B7 B7 B7 FF A1 A1' - 'A1 FF C3 C3 C3 FF A3 A3 A3 FF BD BD BD FF 98 98' - '98 FF C5 C4 C4 FF C7 BF C3 FF 51 A7 7C FF 17 CE' - '71 FF 0A BF 61 FF 2F 99 64 FF C3 BD C0 FF 84 83' - '84 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 30 00 00 00 FA 29 29 29 FF D1 D1 D1 FF EA EA' - 'EA FF E4 E4 E4 FF E7 E7 E7 FF CD CD CD FF 47 47' - '47 FF 5F 5F 5F FF 79 79 79 FF 87 87 87 FF 8F 8F' - '8F FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF B9 B9 B9 FF A4 A4 A4 FF 90 90' - '90 FF B8 B8 B8 FF 8A 8A 8A FF AF AF AF FF 94 94' - '94 FF BF BF BF FF 97 97 97 FF B7 B7 B7 FF 88 88' - '88 FF C4 C3 C3 FF C6 C3 C5 FF 95 B2 A3 FF 91 D6' - 'B4 FF 91 D8 B5 FF 83 AB 97 FF C4 C1 C3 FF 8E 8E' - '8E FF 01 01 01 FF 00 00 00 B7 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' - 'EC FF E6 E6 E6 FF E7 E7 E7 FF D1 D1 D1 FF 68 68' - '68 FF 74 74 74 FF 7E 7E 7E FF 85 85 85 FF 8E 8E' - '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF BA BA BA FF 9F 9F 9F FF 83 83' - '83 FF B3 B3 B3 FF 7C 7C 7C FF A8 A8 A8 FF 87 87' - '87 FF BB BB BB FF 8A 8A 8A FF B2 B2 B2 FF 79 79' - '79 FF C2 C2 C2 FF C4 C4 C4 FF C6 C3 C4 FF 99 AC' - 'A2 FF 96 AB A0 FF C2 BE C0 FF C4 C4 C4 FF 8D 8D' - '8D FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' - 'EE FF E7 E7 E7 FF E8 E8 E8 FF D6 D6 D6 FF 70 70' - '70 FF 71 71 71 FF 7D 7D 7D FF 85 85 85 FF 8E 8E' - '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' - 'AA FF AE AE AE FF BB BB BB FF 98 98 98 FF 73 73' - '73 FF AD AD AD FF 6A 6A 6A FF A0 A0 A0 FF 78 78' - '78 FF B7 B7 B7 FF 7C 7C 7C FF AB AB AB FF 67 67' - '67 FF C2 C2 C2 FF C6 C6 C6 FF C4 C3 C4 FF C7 C4' - 'C5 FF C6 C2 C4 FF BF BF BF FF C5 C5 C5 FF 8D 8D' - '8D FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' - 'EF FF E9 E9 E9 FF EB EB EB FF D6 D6 D6 FF 6A 6A' - '6A FF 6C 6C 6C FF 78 78 78 FF 81 81 81 FF 8A 8A' - '8A FF 93 93 93 FF 9C 9C 9C FF A3 A3 A3 FF A6 A6' - 'A6 FF AB AB AB FF B9 B9 B9 FF 90 90 90 FF 66 66' - '66 FF A5 A5 A5 FF 5B 5B 5B FF 98 98 98 FF 6B 6B' - '6B FF B1 B1 B1 FF 70 70 70 FF A4 A4 A4 FF 58 58' - '58 FF C1 C1 C1 FF C8 C8 C8 FF C5 C5 C5 FF C3 C3' - 'C3 FF C2 C2 C2 FF C1 C1 C1 FF C6 C6 C6 FF 8E 8E' - '8E FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' - 'F2 FF EB EB EB FF EA EA EA FF DF DF DF FF A7 A7' - 'A7 FF A7 A7 A7 FF AB AB AB FF AE AE AE FF B0 B0' - 'B0 FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF B9 B9' - 'B9 FF BA BA BA FF BD BD BD FF B7 B7 B7 FF B1 B1' - 'B1 FF BE BE BE FF AF AF AF FF BA BA BA FF B1 B1' - 'B1 FF BE BE BE FF B0 B0 B0 FF BA BA BA FF AB AB' - 'AB FF C5 C5 C5 FF C8 C8 C8 FF C6 C6 C6 FF C4 C4' - 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C9 C9 C9 FF 8E 8E' - '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' - 'F3 FF EB EB EB FF EB EB EB FF EA EA EA FF ED ED' - 'ED FF EB EB EB FF E9 E9 E9 FF E8 E8 E8 FF E6 E6' - 'E6 FF E4 E4 E4 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' - 'DF FF DE DE DE FF DB DB DB FF DB DB DB FF DC DC' - 'DC FF D8 D8 D8 FF D9 D9 D9 FF D6 D6 D6 FF D6 D6' - 'D6 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' - 'D0 FF CB CB CB FF CA CA CA FF C9 C9 C9 FF C7 C7' - 'C7 FF C4 C4 C4 FF C0 C0 C0 FF CA CA CA FF 8E 8E' - '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' - 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' - 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' - 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' - 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF ED ED' - 'ED FF ED ED ED FF ED ED ED FF EC EC EC FF EC EC' - 'EC FF EB EB EB FF E0 E0 E0 FF D0 D0 D0 FF 8D 8D' - '8D FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' - 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' - 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' - 'E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF EF FF 8C 8C' - '8C FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' - 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' - 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF DB DB DB FF CF CF CF FF BC BC BC FF BB BB' - 'BB FF D1 D1 D1 FF DE DE DE FF FF FF FF FF 9A 9A' - '9A FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' - 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' - 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9' - 'D9 FF D2 D2 D2 FF A8 A8 A8 FF B6 B6 B6 FF B1 B1' - 'B1 FF B5 B5 B5 FF D8 D8 D8 FF FC FC FC FF 9C 9C' - '9C FF 00 00 00 FF 00 00 00 AE 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' - 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' - 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' - 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D7 D7' - 'D7 FF C9 C9 C9 FF A6 A6 A6 FF C3 C3 C3 FF B3 B3' - 'B3 FF AD AD AD FF D6 D6 D6 FF F5 F5 F5 FF 76 76' - '76 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' - 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' - 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF DD DD DD FF E1 E1 E1 FF E3 E3' - 'E3 FF E6 E6 E6 FF EA EA EA FF ED ED ED FF ED ED' - 'ED FF EB EB EB FF E7 E7 E7 FF E4 E4 E4 FF E2 E2' - 'E2 FF DE DE DE FF D4 D4 D4 FF D0 D0 D0 FF D2 D2' - 'D2 FF D3 D3 D3 FF C5 C5 C5 FF D0 D0 D0 FF C2 C2' - 'C2 FF BF BF BF FF D9 D9 D9 FF E8 E8 E8 FF 56 56' - '56 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' - 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' - 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF DF DF' - 'DF FF F0 F0 F0 FF EC EC EC FF E1 E1 E1 FF DE DE' - 'DE FF DD DD DD FF DC DC DC FF DB DB DB FF DB DB' - 'DB FF DC DC DC FF DD DD DD FF DE DE DE FF E1 E1' - 'E1 FF EC EC EC FF F1 F1 F1 FF E1 E1 E1 FF D1 D1' - 'D1 FF CE CE CE FF D0 D0 D0 FF CB CB CB FF CE CE' - 'CE FF D1 D1 D1 FF D9 D9 D9 FF D4 D4 D4 FF 3F 3F' - '3F FF 00 00 00 FF 00 00 00 55 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' - 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CA CA CA FF D6 D6 D6 FF ED ED ED FF E6 E6' - 'E6 FF DC DC DC FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF ED ED' - 'ED FF DA DA DA FF CA CA CA FF CD CD CD FF CD CD' - 'CD FF CB CB CB FF DF DF DF FF B8 B8 B8 FF 22 22' - '22 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' - 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' - 'CA FF D4 D4 D4 FF E9 E9 E9 FF DC DC DC FF D0 D0' - 'D0 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D8 D8' - 'D8 FF EA EA EA FF D8 D8 D8 FF C9 C9 C9 FF CA CA' - 'CA FF C9 C9 C9 FF E0 E0 E0 FF A0 A0 A0 FF 08 08' - '08 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' - 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' - 'CE FF E4 E4 E4 FF D4 D4 D4 FF CF CF CF FF D1 D1' - 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF CD CD CD FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CC CC' - 'CC FF D0 D0 D0 FF E2 E2 E2 FF CF CF CF FF C7 C7' - 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 C2 00 00 00 0E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' - '9F FF DD DD DD FF CC CC CC FF CD CD CD FF DB DB' - 'DB FF D6 D6 D6 FF CE CE CE FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF C8 C8 C8 FF CF CF CF FF DA DA DA FF C7 C7' - 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 5A 5A 5A FF 00 00' - '00 FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' - '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF DB DB' - 'DB FF D1 D1 D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF C5 C5' - 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C7 C7 C7 FF D3 D3 D3 FF C8 C8' - 'C8 FF C9 C9 C9 FF DE DE DE FF 42 42 42 FF 00 00' - '00 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' - '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D4 D4' - 'D4 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D0 D0 D0 FF C8 C8' - 'C8 FF C3 C3 C3 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C7 C7 C7 FF C5 C5' - 'C5 FF CB CB CB FF CC CC CC FF 2D 2D 2D FF 00 00' - '00 F8 00 00 00 40 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' - '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF CD CD CD FF C7 C7 C7 FF C4 C4 C4 FF C2 C2' - 'C2 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' - 'C1 FF C1 C1 C1 FF C2 C2 C2 FF BF BF BF FF C0 C0' - 'C0 FF CE CE CE FF B2 B2 B2 FF 1A 1A 1A FF 00 00' - '00 E5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' - '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF CC CC' - 'CC FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D7 D7 D7 FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' - 'D3 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF C6 C6' - 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' - 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' - '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' - '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF D0 D0' - 'D0 FF D2 D2 D2 FF DB DB DB FF D9 D9 D9 FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DB DB DB FF DB DB DB FF DA DA DA FF D9 D9' - 'D9 FF D9 D9 D9 FF CF CF CF FF C5 C5 C5 FF CC CC' - 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' - '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' - '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' - 'DC FF CE CE CE FF D6 D6 D6 FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' - 'DE FF D8 D8 D8 FF CE CE CE FF DD DD DD FF DC DC' - 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' - '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' - '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' - 'E1 FF DE DE DE FF CE CE CE FF D7 D7 D7 FF E1 E1' - 'E1 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF D9 D9' - 'D9 FF CD CD CD FF DA DA DA FF E3 E3 E3 FF D9 D9' - 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' - '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' - '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' - 'E3 FF E4 E4 E4 FF E1 E1 E1 FF D7 D7 D7 FF D2 D2' - 'D2 FF DA DA DA FF E4 E4 E4 FF E5 E5 E5 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E5 E5 E5 FF DC DC DC FF D2 D2 D2 FF D6 D6' - 'D6 FF E0 E0 E0 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' - 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' - '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' - '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF DF DF' - 'DF FF D2 D2 D2 FF D3 D3 D3 FF DE DE DE FF E3 E3' - 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3 E3 FF DE DE' - 'DE FF D4 D4 D4 FF D1 D1 D1 FF DD DD DD FF E7 E7' - 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' - 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' - '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' - 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' - 'EB FF EA EA EA FF E4 E4 E4 FF E0 E0 E0 FF DF DF' - 'DF FF DF DF DF FF DD DD DD FF DC DC DC FF DC DC' - 'DC FF DD DD DD FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E2 E2 E2 FF E9 E9 E9 FF EC EC EC FF EA EA' - 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' - 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' - 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' - 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' - 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' - 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' - 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' - 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' - 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' - 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' - 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' - 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' - 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' - 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' - 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' - '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' - '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' - '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' - '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' - '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'F1 C7 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF F8 07 FF FF 00 00 FF FF' - 'E0 00 00 3F 00 00 FF 00 00 00 00 7F 00 00 FC 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' - '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' - '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' - '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 13 13' - '13 00 18 18 18 00 19 19 19 00 1A 1A 1A 00 1E 1E' - '1E 00 1F 1F 1F 00 20 20 20 00 21 21 21 00 22 22' - '22 00 24 24 24 00 26 26 26 00 27 27 27 00 28 28' - '28 00 29 29 29 00 2A 2A 2A 00 2B 2B 2B 00 2C 2C' - '2C 00 2D 2D 2D 00 2E 2C 2D 00 2F 2F 2F 00 34 34' - '34 00 35 35 35 00 39 39 39 00 3B 3B 3B 00 3D 3D' - '3D 00 3F 3F 3F 00 40 40 40 00 41 41 41 00 42 42' - '42 00 47 47 47 00 48 48 48 00 49 49 49 00 4B 4B' - '4B 00 4F 4F 4F 00 53 53 53 00 56 56 56 00 58 58' - '58 00 59 59 59 00 5A 5A 5A 00 5B 5B 5B 00 5D 5D' - '5D 00 5F 5F 5F 00 61 61 61 00 63 63 63 00 64 64' - '64 00 66 66 66 00 67 67 67 00 68 68 68 00 6A 6A' - '6A 00 6B 6B 6B 00 6C 6C 6C 00 70 70 70 00 71 71' - '71 00 72 72 72 00 73 73 73 00 74 74 74 00 75 75' - '75 00 76 76 76 00 77 77 77 00 78 78 78 00 79 79' - '79 00 7A 7A 7A 00 7C 7C 7C 00 7D 7D 7D 00 7E 7E' - '7E 00 7F 7F 7F 00 2F 99 64 00 1C A8 60 00 0A BF' - '61 00 20 A8 63 00 51 A7 7C 00 17 CE 71 00 00 00' - 'FF 00 80 80 80 00 81 81 81 00 83 83 83 00 84 83' - '84 00 85 85 85 00 87 87 87 00 88 88 88 00 8A 8A' - '8A 00 8C 8C 8C 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' - '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 94 94' - '94 00 97 97 97 00 98 98 98 00 99 99 99 00 9A 9A' - '9A 00 9C 9C 9C 00 9D 9D 9D 00 9F 9F 9F 00 83 AB' - '97 00 96 AB A0 00 90 AF A0 00 99 AC A2 00 95 B2' - 'A3 00 9D B3 A8 00 A0 A0 A0 00 A1 A1 A1 00 A2 A2' - 'A2 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A6 A6' - 'A6 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' - 'AA 00 AB AB AB 00 AD A8 AB 00 AB AC AC 00 AC AC' - 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' - 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B3 B4' - 'B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B8 B4' - 'B6 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BB BB' - 'BB 00 BF BB BD 00 BC BC BC 00 BD BD BD 00 BE BE' - 'BE 00 BF BF BF 00 91 D6 B4 00 91 D8 B5 00 C3 BD' - 'C0 00 C2 BE C0 00 C7 BF C3 00 C0 C0 C0 00 C1 C1' - 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C3 00 C4 C3' - 'C3 00 C4 C3 C4 00 C6 C2 C4 00 C6 C3 C4 00 C6 C3' - 'C5 00 C4 C4 C4 00 C5 C4 C4 00 C5 C5 C5 00 C7 C4' - 'C5 00 C6 C6 C6 00 C7 C7 C7 00 C8 C8 C8 00 C8 C9' - 'C9 00 C9 C9 C9 00 CA CA CA 00 CB CB CB 00 CC CC' - 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' - 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' - 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' - 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' - 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' - 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' - 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' - 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4' - 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' - 'F8 00 F9 F9 F9 00 FA FA FA 00 FC FC FC 00 FF FF' - 'FF 00 00 00 00 00 10 DA 4B 00 F8 0F 0D 01 71 CC' - '43 00 F8 0F 0D 01 40 E3 0C 01 A4 1A 95 00 2C A3' - 'AF 00 C4 F5 AF 00 03 00 00 00 40 E3 0C 01 2F 0C' - '00 00 B8 10 0D 01 30 00 00 00 00 00 00 00 40 00' - '00 00 F8 0F 0D 01 C0 00 00 00 30 00 00 00 00 09' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 30 00' - '00 00 30 00 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 52 52 DF 00 00 00' - '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 52 52 52 DF 00 52' - '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 DF DF DF DF DF DF DF DF DF DF' - 'DF DF DF DF DF DF DF DF DF DF DF 52 52 52 52 52' - '52 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' - 'DF DF DF DF DF DF 53 53 53 53 53 53 53 53 53 53' - '53 53 53 53 53 53 53 53 53 53 53 53 52 52 52 52' - '53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53' - '53 53 53 53 53 53 99 99 99 99 99 99 99 99 99 99' - '99 99 99 99 99 99 99 99 99 99 99 99 52 52 52 52' - '99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99' - '99 99 99 99 99 99 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 52 52 52 52 52' - '52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 52 52 52 99 99 52' - '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 52 52 00 99 99 DF' - '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF DF DF' - 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' - 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 DF DF DF DF 11' - '1A 19 1A 19 19 19 19 19 19 19 19 19 19 19 18 18' - '18 18 18 18 18 18 18 19 19 19 1C 1C 0A DF DF DF' - '00 00 00 00 00 00 00 00 00 00 00 DF DF 14 5F AC' - 'AF AD B0 AF AE AD AB A8 A7 A5 A3 9C 9B 9B 9C 99' - '9A 93 93 90 91 8D 8E 87 86 8A 7F 7D 7C 35 07 DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 01 5A CD CA' - 'C9 B7 57 59 60 64 72 7F 8D 99 9C A7 AD AC AC B8' - 'AC B5 AD B9 AE B6 A8 AA A0 6F 4F 4D 6C 8F 2B DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 0C A8 CE C4' - 'C8 AD 21 23 2D 3F 58 60 68 75 78 7E 89 79 67 91' - '65 89 71 9C 73 91 64 A4 98 50 51 4E 4C 96 56 01' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 17 B3 CC C6' - 'C9 AF 27 33 46 58 5E 63 70 77 7A 80 8C 74 5F 8B' - '5A 81 62 93 63 89 59 9E A2 6E 94 95 6A 9D 5D 01' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 16 B3 CE C8' - 'C9 B3 39 41 4A 57 5D 63 70 77 7A 80 8D 69 55 85' - '48 78 58 8E 5A 84 46 9B A3 A1 6D 6B 97 A3 5C 01' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 16 B3 D0 C9' - 'CA B8 3D 3E 49 57 5D 63 70 77 7A 80 8E 64 40 7F' - '3A 70 45 89 48 7B 38 9B A7 9F A6 A0 93 A5 5C 01' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 15 B3 D1 CB' - 'CD B8 3A 3C 45 54 5A 61 67 73 76 7B 8C 5F 37 75' - '31 64 3B 83 3D 74 2E 9A A9 A5 9C 9B 9A A7 5D 01' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 15 B4 D4 CD' - 'CC C1 77 77 7B 80 82 85 88 8C 8C 8D 91 89 83 92' - '81 8D 83 92 82 8D 7B A5 A9 A7 A3 9C 9B AB 5D DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 14 B5 D5 CD' - 'CD CC CF CD CB CA C8 C6 C4 C3 C1 C0 BD BD BE BA' - 'BB B8 B8 B4 B4 B1 B2 AD AC AB A8 A3 99 AC 5D DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 14 B5 D9 DA' - 'D8 D8 D8 D7 D7 D6 D6 D5 D5 D5 D4 D4 D3 D3 D3 D2' - 'D2 D2 D1 D1 D0 D0 CF CF CF CE CE CD C2 B2 5C DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 13 B8 DE CB' - 'C3 C4 C4 C2 C1 C1 C1 C1 C1 C2 C2 C2 C2 C2 C2 C2' - 'C2 C2 C2 C2 C2 C2 C2 C2 C4 C5 C5 C5 DA D1 5B DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 13 C0 DA BB' - 'A3 8E 93 BA BC BB BB BB BB BB BB BB BB BB BB BB' - 'BB BB BB BB BB BB BB BD B1 90 8E B3 C0 DE 66 DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 0F BC D5 A7' - '79 89 82 9C BC BA BA BA BA BA B9 B9 B9 B9 B9 B9' - 'B9 B9 BA BA BA BA BB B4 78 88 83 87 BA DD 67 DF' - 'DF 00 00 00 00 00 00 00 00 00 DF DF 03 9B D8 90' - '84 9C 7B 8E BA B7 B7 B7 B6 B5 B5 B7 B9 BA BA B9' - 'B7 B5 B5 B5 B6 B7 B9 AB 76 9C 85 7F B8 D7 43 DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 74 D6 B1' - 'A5 B4 93 AB B5 B4 B2 B5 BF C3 C5 C8 CC CF CF CD' - 'C9 C6 C4 C0 B6 B2 B4 B5 A5 B2 9B 93 BB CA 2D DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 4A D1 B3' - 'B1 AD B1 B3 B0 B1 C1 D2 CE C3 C0 BF BE BD BD BE' - 'BF C0 C3 CE D3 C3 B3 B0 B2 AD B0 B3 BB B6 23 DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 2F CB B2' - 'AF AF AF AC B8 CF C8 BE B6 B7 B8 B8 B8 B8 B8 B8' - 'B8 B8 B7 B7 BD C6 CF BC AC AF AF AD C1 8B 12 DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 24 B9 B4' - 'AC AD AC B6 CB BE B2 B3 B4 B4 B4 B4 B4 B4 B4 B4' - 'B4 B4 B4 B4 B3 B2 BA CC BA AB AC AB C2 70 06 DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 12 89 BD' - 'AC AD B0 C6 B6 B1 B3 B2 B2 B2 B2 B1 AF B0 B0 B0' - 'B0 B0 B0 B0 B0 B0 AE B2 C4 B1 A8 AB C4 53 DF DF' - 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 05 69 BF' - 'AE AF BD B8 B0 B2 B2 B2 B2 B2 B2 B1 AE AB AC AC' - 'AC AC AC AC AC AC AC A9 B1 BC A8 AB C4 30 DF DF' - 'DF 00 00 00 00 00 00 00 00 00 00 00 DF DF 55 BF' - 'B1 B3 BD B3 B2 B2 B2 B2 B2 B2 B2 B2 B1 AB A5 A7' - 'A7 A7 A7 A7 A7 A7 A7 A7 A8 B5 A9 AB C0 26 DF DF' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 33 BE' - 'B3 B4 B6 B3 B3 B3 B3 B3 B3 B3 B3 B3 B3 B2 A9 9C' - '9C 9C A3 A3 A3 A3 A3 A3 A3 A8 A5 AD AE 1B DF DF' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 25 BA' - 'B6 B4 B2 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 AF' - 'A8 A3 9B 9A 99 9A 9A 9A 9B 93 99 B0 84 0D DF DF' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 1A AE' - 'B8 B7 AE B7 B8 B8 B8 B8 B8 B8 B8 B8 B8 B8 B8 B9' - 'B8 B7 B5 B1 AE AB A7 A3 9B 85 91 B2 65 07 DF DF' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 0B 82' - 'BD BD B2 B4 BD BB BC BC BC BC BC BC BC BC BC BC' - 'BC BC BC BD BD BC BB BB B1 A5 AE AC 47 02 DF DF' - '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 06 63' - 'BE C1 BE B0 B8 C0 BF BF BF BF BF BF BF BF BF BF' - 'BF BF BF BF BF BF C0 BA B0 BF BE A7 2C DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 44' - 'B5 C4 C3 C0 B0 B9 C3 C4 C2 C2 C2 C2 C2 C2 C2 C2' - 'C2 C2 C2 C2 C3 C3 BB AF BC C5 BB 8E 20 DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 2A' - 'AB C7 C5 C6 C3 B9 B4 BC C6 C7 C6 C6 C6 C6 C6 C6' - 'C6 C6 C7 C7 BE B4 B8 C2 C6 C8 B8 78 10 DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 1F' - '91 C8 C8 C8 C9 C9 C1 B4 B5 C0 C5 C5 C6 C6 C6 C6' - 'C5 C5 C0 B6 B3 BF C9 C9 C8 CA B6 66 08 DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 0E' - '7B C6 CF C9 C8 CE CD CC C6 C2 C1 C1 BF BE BE BF' - 'C1 C1 C1 C4 CB CE CC C7 CD CD B8 5A DF DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 06' - '65 C6 C1 91 9A B8 CE CF CF D0 D0 CF CE CD CD CE' - 'CF D0 D0 CF D0 C6 9B 92 B3 CE B6 42 DF DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' - '5C C2 A3 84 8B 84 CD D3 D2 D2 D2 D2 D2 D2 D2 D2' - 'D2 D2 D2 D2 D5 B7 82 88 89 CD AF 34 DF DF DF 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' - '36 B0 BF BE B7 C6 DB DB DB DB DB DB DB DB DB DB' - 'DB DB DB DB DC D4 C1 BA BE B9 82 1E DF DF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' - '0C 53 92 B5 B9 BD BA BA BA BA BA BA BA BA BA BA' - 'BA BA BA BA BA BB BB B9 AF 82 32 04 DF DF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' - 'DF 09 22 29 28 28 28 28 28 28 28 28 28 28 28 28' - '28 28 28 28 28 28 28 29 29 1D 02 DF DF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF' - 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' - 'DF DF DF DF DF DF DF DF DF DF DF DF 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' - 'DF DF DF DF DF DF DF DF DF DF DF 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF F1 C7 FF FF 00 00 FF FF' - 'F0 87 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'F8 0F FF FF 00 00 FF FF F0 07 FF FF 00 00 FF FF' - 'F2 07 FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' - '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' - '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' - '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' - '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' - '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 24 00 00 00 30 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 FF FF 00 00' - 'FF FF 00 00 00 3C 00 00 00 30 00 00 00 30 00 00' - '00 30 00 00 00 30 00 00 00 30 00 00 00 30 C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00 FF FF 00 00' - 'FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' - 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 26 26 26 FF CD CD CD FF CD CD' - 'CD FF C9 C9 C9 FF C5 C5 C5 FF C2 C2 C2 FF C0 C0' - 'C0 FF BF BF BF FF BA BA BA FF B3 B4 B3 FF AB AC' - 'AC FF 09 09 09 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 30 D1 D1 D1 FF E7 E7 E7 FF 5F 5F' - '5F FF 8F 8F 8F FF A7 A7 A7 FF B9 B9 B9 FF B8 B8' - 'B8 FF 94 94 94 FF B7 B7 B7 FF C6 C3 C5 FF 91 D8' - 'B5 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 33 D1 D1 D1 FF EB EB EB FF 6C 6C' - '6C FF 8A 8A 8A FF A3 A3 A3 FF B9 B9 B9 FF A5 A5' - 'A5 FF 6B 6B 6B FF A4 A4 A4 FF C8 C8 C8 FF C2 C2' - 'C2 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 33 D3 D3 D3 FF F6 F6 F6 FF F5 F5' - 'F5 FF F4 F4 F4 FF F3 F3 F3 FF F1 F1 F1 FF F0 F0' - 'F0 FF EF EF EF FF EE EE EE FF ED ED ED FF EB EB' - 'EB FF 8D 8D 8D FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 25 DA DA DA FF A9 A9 A9 FF C3 C3' - 'C3 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' - 'D7 FF D8 D8 D8 FF D8 D8 D8 FF A8 A8 A8 FF B5 B5' - 'B5 FF 9C 9C 9C FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 7E 7E 7E FF CF CF CF FF D1 D1' - 'D1 FF DF DF DF FF E1 E1 E1 FF DC DC DC FF DC DC' - 'DC FF E1 E1 E1 FF E1 E1 E1 FF D0 D0 D0 FF D1 D1' - 'D1 FF 3F 3F 3F FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 22 22 FF CA CA CA FF E4 E4' - 'E4 FF D1 D1 D1 FF D0 D0 D0 FF CD CD CD FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF E2 E2 E2 FF C9 C9' - 'C9 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF C3 C3' - 'C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF CB CB' - 'CB FF 00 00 00 F8 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 D8 DB DB DB FF D2 D2' - 'D2 FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF CF CF CF FF CA CA' - 'CA FF 00 00 00 B8 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 89 C9 C9 C9 FF E4 E4' - 'E4 FF D2 D2 D2 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4' - 'E4 FF E5 E5 E5 FF D2 D2 D2 FF E4 E4 E4 FF A8 A8' - 'A8 FF 00 00 00 4E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 99 99 99 FF BD BD' - 'BD FF EC EC EC FF EE EE EE FF EC EC EC FF EC EC' - 'EC FF EE EE EE FF E4 E4 E4 FF D1 D1 D1 FF 75 75' - '75 FF 00 00 00 06 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 19 19 19 FF D3 D3' - 'D3 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D9 D9 D9 FF CD CD CD FF 06 06' - '06 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 E0 03 00 00 C0 03 00 00 80 03' - '00 00 80 03 00 00 80 03 00 00 80 03 00 00 C0 03' - '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' - '00 00 C0 03 00 00 E0 07 00 00 F0 0F 00 00' -} */ - -/* BINRES cdrom.ico */ -11 ICON cdrom.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 4E 1F 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 76 20 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 5E 23 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 C6 27 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 2E 2E 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 D6 3C 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 01 01 00 01 02 02 00 02 03 03 00 05 05' - '05 00 06 06 06 00 07 07 07 00 09 09 09 00 0B 0B' - '0B 00 10 10 10 00 13 13 13 00 18 18 18 00 1B 1C' - '1B 00 1E 1E 1E 00 22 26 23 00 23 29 24 00 24 2E' - '25 00 3B 40 3C 00 3E 40 3F 00 40 41 40 00 41 43' - '42 00 42 44 43 00 46 48 47 00 4E 50 4F 00 50 52' - '51 00 54 55 55 00 56 56 56 00 57 57 57 00 57 58' - '58 00 59 59 59 00 5A 5A 5A 00 5A 5B 5B 00 5B 5C' - '5C 00 5D 5E 5E 00 5F 68 5F 00 71 71 72 00 72 72' - '73 00 74 74 74 00 77 76 77 00 78 76 77 00 72 78' - '72 00 79 76 78 00 7A 76 78 00 7B 77 79 00 7D 78' - '7A 00 7F 78 7B 00 7F 7F 7F 00 80 7A 7D 00 81 7C' - '7F 00 0E CE 0E 00 14 C2 15 00 10 CE 10 00 6D 90' - '6D 00 82 7D 80 00 84 80 83 00 86 83 85 00 8D 8B' - '8C 00 90 8F 90 00 95 96 95 00 97 97 97 00 98 98' - '98 00 98 99 99 00 99 9A 9A 00 9B 9C 9B 00 9F A0' - '9F 00 A7 A7 A7 00 A9 A8 A9 00 AB AA AA 00 AD AC' - 'AC 00 AE AE AE 00 B1 B0 B1 00 B3 B2 B3 00 B4 B3' - 'B4 00 B6 B6 B6 00 B8 B8 B8 00 B9 B9 B9 00 BB BB' - 'BB 00 BE BE BE 00 C0 C0 C0 00 C2 C3 C2 00 C3 C3' - 'C2 00 C5 C2 C3 00 C7 C1 C4 00 C9 C3 C5 00 CA C6' - 'C7 00 CA C8 C8 00 CA C9 C9 00 CB CA CA 00 CC CB' - 'CB 00 CD CB CB 00 CD CC CC 00 CD CD CD 00 CE CE' - 'CE 00 CE CF CF 00 CF CF CF 00 D0 D0 D0 00 D1 D1' - 'D1 00 D2 D2 D2 00 D4 D3 D3 00 D4 D4 D4 00 D5 D4' - 'D4 00 D7 D4 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DD DD DD 00 DE DE DE 00 FB D6 D7 00 FD D4' - 'D5 00 FE D4 D6 00 FE D4 DF 00 F7 D9 DA 00 F0 DE' - 'DF 00 EA DB E2 00 FE D3 E9 00 FE D3 ED 00 FE D4' - 'EF 00 F2 DA E8 00 F9 DA EF 00 FE D4 F1 00 FE D5' - 'F4 00 FE D6 F6 00 FC DB F4 00 FE D8 F9 00 FE DB' - 'F9 00 FE DC F8 00 E1 E0 E0 00 E7 E5 E6 00 E7 E6' - 'E6 00 E7 E7 E7 00 EA E3 E3 00 E8 E8 E8 00 E9 E9' - 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' - 'ED 00 EF EE EE 00 F0 EE EF 00 F0 EF F0 00 F1 F0' - 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F2 F3 F3 00 F3 F5' - 'F5 00 F7 F6 F8 00 FA F7 FA 00 FB FA FB 00 FC F8' - 'FC 00 00 00 00 00 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' - '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 88 36' - '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 63 64 72 6F 6D 2E 69 63 6F' - '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 99 99 0D 09 08 0C 99 99 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 99 21 11 45 4C 5D 55 21 14 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 99 23 4D 97 7F 7F 76 71 72 74 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 99 23 75 80 7B 7B 72 71 71 71 94 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 10 28 98 7C 78 7B 72 71 71 6F 94 92 00 00' - '99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99' - '99 10 1F 59 7D 78 78 7B 71 71 6F 93 92 92 00 99' - '08 15 19 17 21 23 1F 1D 1D 1E 1E 1D 1D 1C 1C 1F' - '1F 12 40 81 78 78 78 7B 71 71 8E 91 92 92 99 99' - '37 6A 82 83 50 32 98 8B 84 82 67 64 64 64 61 63' - '1B 17 75 7C 78 7B 78 78 7B 7F 7F 7B 93 92 99 03' - '65 94 89 81 31 31 33 79 5C 5E 5A 5B 5B 5B 67 24' - '0E 23 97 7A 92 77 7B 78 7F 53 6F 7F 8E 8F 99 07' - '83 8D 89 98 34 31 41 52 4E 4E 4E 4E 4E 4E 50 4E' - '2F 27 97 93 93 8C 7A 7F 48 40 23 70 7E 90 99 05' - '92 8B 93 3A 2B 38 2A 25 25 25 25 25 25 25 25 26' - '23 3A 97 92 92 93 92 7E 10 00 00 3A 81 93 99 04' - '92 8F 91 44 39 3A 3F 3F 3F 3F 3F 3D 3C 3C 3C 3E' - '35 40 97 92 92 93 76 7E 11 99 00 52 7E 8D 99 03' - '90 8F 89 90 8A 89 87 86 82 82 82 82 82 82 82 83' - '47 3D 97 92 92 93 8E 7C 53 38 52 81 7E 76 99 02' - '96 96 8A 8D 88 87 87 87 88 88 87 87 87 87 85 8B' - '4B 23 97 92 92 92 8F 8D 7F 81 7F 7F 77 7B 99 01' - '97 82 46 46 66 68 67 67 67 67 66 66 66 67 67 6A' - '50 22 95 93 92 92 92 94 72 71 71 76 7B 78 99 99' - '94 5F 44 44 51 69 66 64 63 63 67 68 66 63 63 64' - '82 23 49 97 92 92 92 94 6F 71 71 76 7B 78 00 99' - '55 86 58 55 5C 5F 60 60 61 64 63 63 63 64 5F 62' - '62 84 20 65 94 92 92 71 71 71 71 76 78 78 00 99' - '3F 86 5A 5C 5B 60 63 63 64 66 66 66 66 66 64 68' - '82 68 3B 2D 97 95 6F 71 71 71 77 7B 7B 7C 00 99' - '22 82 55 56 64 61 60 60 60 5F 61 60 60 61 60 5F' - '5C 62 69 3A 38 73 6F 71 71 77 7B 7B 81 75 00 99' - '11 6C 57 5F 62 5F 5F 5E 5E 5F 62 60 62 62 62 62' - '60 62 5C 5B 39 36 57 72 81 81 98 98 48 3A 00 99' - '0B 57 62 61 60 5E 5F 5F 5F 5E 5E 62 62 62 62 62' - '62 62 66 4D 4A 0C 02 13 19 18 16 15 99 00 00 99' - '08 4A 66 61 61 60 60 60 60 60 61 61 61 61 61 61' - '61 61 64 4C 48 0F 99 00 00 00 00 00 00 00 00 99' - '99 3A 82 66 67 67 67 67 67 67 67 67 63 64 64 64' - '63 64 5E 54 5A 10 99 00 00 00 00 00 00 00 00 99' - '99 23 8A 6D 6E 6D 6B 6B 6B 6B 6B 6B 6C 6D 6D 6C' - '6E 83 84 6E 46 0A 99 00 00 00 00 00 00 00 00 00' - '99 11 84 86 82 82 82 82 86 82 82 82 82 82 82 82' - '83 85 84 83 38 02 99 00 00 00 00 00 00 00 00 00' - '99 0B 82 87 85 88 8B 8A 8A 87 88 88 88 88 87 84' - '85 87 85 84 23 99 99 00 00 00 00 00 00 00 00 00' - '99 99 56 90 69 83 8B 8B 8A 8A 8A 89 8A 8B 8B 8B' - '87 69 89 8B 17 99 99 00 00 00 00 00 00 00 00 00' - '99 99 4F 6B 43 45 92 8F 8F 8F 8F 8D 8F 8F 8F 94' - '54 42 5A 92 12 99 99 00 00 00 00 00 00 00 00 00' - '00 99 24 6E 88 8B 97 97 97 97 97 97 97 97 97 97' - '95 87 83 4C 06 99 00 00 00 00 00 00 00 00 00 00' - '00 99 07 1A 30 2C 29 29 29 29 29 29 29 29 29 29' - '2B 2F 23 10 99 99 00 00 00 00 00 00 00 00 00 00' - '00 00 99 99 99 99 99 99 99 99 99 99 99 99 99 99' - '99 99 99 99 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF 00 FF FF FE 00 FF FF FC 00 FF FF F8 00 FF FF' - 'F0 00 C0 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' - '00 7F C0 00 00 7F C0 00 00 7F C0 00 00 7F E0 00' - '00 FF E0 00 00 FF F0 00 03 FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 05 05 05 00 0C 0F' - '0F 00 0D 11 0E 00 15 15 15 00 36 36 36 00 39 39' - '39 00 40 43 41 00 44 47 45 00 53 53 53 00 5B 60' - '5D 00 67 68 68 00 64 6A 69 00 69 69 69 00 6B 6C' - '6B 00 6E 6E 6E 00 6F 6E 6E 00 6F 70 70 00 72 72' - '72 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F 7F 00 00 FF' - '00 00 75 99 75 00 88 6C 88 00 84 7E 84 00 8B 7E' - '82 00 80 80 80 00 84 84 84 00 93 93 93 00 97 97' - '97 00 9A 98 98 00 9B 9B 9B 00 9D 9D 9D 00 9F 9F' - '9F 00 A0 A0 A0 00 A5 A5 A5 00 A6 A6 A6 00 A8 A2' - 'A8 00 B8 AC B8 00 BB BB BB 00 A6 D4 A6 00 D8 AE' - 'C6 00 CB BD C9 00 C0 C0 C0 00 C2 C2 C2 00 C2 C3' - 'C3 00 C3 C3 C3 00 C8 C8 C8 00 C9 C9 C9 00 CE CE' - 'CE 00 CF CF CF 00 D3 C2 CD 00 D0 D0 D0 00 D1 D1' - 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D6 D0 D6 00 D4 D4' - 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' - 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' - 'DC 00 DE DE DE 00 FF D2 CD 00 FF D2 CE 00 E2 C2' - 'DA 00 FF D8 D7 00 FF D4 D8 00 FA DD DA 00 FD DC' - 'DC 00 FF DE DF 00 F4 D7 EA 00 FF D3 E8 00 FF D6' - 'E8 00 FF D7 EF 00 FF D3 F1 00 FF D3 F2 00 FF D3' - 'F3 00 FF D4 F5 00 FF D7 F7 00 FF D9 F7 00 FD D9' - 'FB 00 E1 E1 E1 00 E3 E4 E3 00 E4 E4 E4 00 E5 E5' - 'E5 00 E6 E6 E6 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' - 'EA 00 EA EB EB 00 EB EB EB 00 ED ED ED 00 FF E3' - 'E1 00 F5 EA EF 00 FF EF EF 00 FD E7 F4 00 FB ED' - 'F4 00 FE E7 FA 00 FF E2 FF 00 FF E9 FF 00 FF ED' - 'FE 00 FF EE FF 00 EE F9 F7 00 F1 F1 F1 00 F1 F3' - 'F2 00 F2 F2 F2 00 F3 F3 F3 00 F0 F5 F2 00 F0 F6' - 'F3 00 F0 F7 F7 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' - 'F6 00 FF F0 FF 00 FF F3 FF 00 FF F6 FF 00 F9 F9' - 'F9 00 FA FA FA 00 FB FB FB 00 FC FC FC 00 FD FD' - 'FD 00 FF FD FE 00 FE FE FE 00 FF FF FF 00 00 00' - '00 00 E7 E5 E6 00 E7 E6 E6 00 E7 E7 E7 00 EA E3' - 'E3 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' - 'EB 00 EC EC EC 00 ED ED ED 00 EF EE EE 00 F0 EE' - 'EF 00 F0 EF F0 00 F1 F0 F0 00 F1 F1 F1 00 F2 F2' - 'F2 00 F2 F3 F3 00 F3 F5 F5 00 F7 F6 F8 00 FA F7' - 'FA 00 FB FA FB 00 FC F8 FC 00 00 00 00 00 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 54 00 00 00 00 00 00 00 03 00' - '00 00 5C 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 63' - '64 72 6F 6D 2E 69 63 6F 00 00 1A 93 4B 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 03 0A 0C 02 00 00 00 00 00 00 00 00 00 00' - '00 0E 6B 68 4B 64 00 82 82 82 82 82 82 82 82 82' - '11 77 53 45 49 73 82 10 26 17 27 25 22 21 23 08' - '4C 52 50 4E 67 71 82 7F 79 16 29 39 33 38 28 09' - '81 63 55 2B 2A 66 82 81 30 18 19 14 14 13 1B 1C' - '80 72 6A 82 07 79 82 81 74 6D 61 60 60 60 6F 1E' - '7E 6E 65 46 56 4F 82 7D 24 38 3D 3B 3D 3C 41 1D' - '5F 74 6C 47 48 51 82 3D 32 32 37 3A 3B 3B 38 58' - '1A 81 4A 44 4D 54 82 20 37 38 35 35 36 37 37 38' - '2E 1F 62 69 78 34 00 0D 43 35 35 35 36 37 37 38' - '36 0B 00 00 00 00 00 06 61 40 3E 3F 3F 3E 3E 42' - '57 12 00 00 00 00 00 01 70 5E 5C 5B 5A 5A 59 60' - '75 05 00 00 00 00 00 82 5D 31 7A 76 74 75 7B 32' - '7C 04 00 00 00 00 00 82 0F 2C 2F 2D 2D 2D 2D 2C' - '1E 82 00 00 00 00 00 00 82 82 82 82 82 82 82 82' - '82 00 00 00 00 00 FF F0 00 00 FF E0 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 0F' - '00 00 80 0F 00 00 80 0F 00 00 80 0F 00 00 80 0F' - '00 00 C0 1F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0C 00 00 00 30 00 00 00 48 00 00 00 90 00 00' - '00 90 00 00 00 90 00 00 00 78 00 00 00 30 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 86 86' - '86 FF 7A 7A 7A FF AA AA AA FF DA DA DA FF F2 F2' - 'F2 FF CE CE CE FF AA AA AA FF 6E 6E 6E FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0C 7A 7A 7A FF 80 80' - '80 FF FF FF FF FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 D4 FF FF D4 D4 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - '00 13 00 00 00 78 6E 6E 6E FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 56 62 62 62 FF E6 E6 E6 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 05 00 00 00 69 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 62 62 62 FF 56 56' - '56 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 9B 00 00 00 FF 21 21 21 FF 2C 2C' - '2C FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 4A 4A 4A FF 62 62' - '62 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 03 01 01 01 FF 8A 8A 8A FF EB EB EB FF E8 E8' - 'E8 FF E8 E8 E8 FF D4 D4 D4 FF 00 C0 00 FF E7 E7' - 'E7 FF E8 E8 E8 FF E3 E3 E3 FF D8 D8 D8 FF D2 D2' - 'D2 FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' - 'C9 FF AA AA AA FF 2E 2E 2E FF 62 62 62 FF DA DA' - 'DA FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 FF FF FF D4 FF FF FF D4' - 'FF FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 15 19 19 19 FF AD A8 AB FF EB EB EB FF E8 E8' - 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF 00 C0' - '00 FF DF DF DF FF D5 D5 D5 FF D2 D2 D2 FF CB CB' - 'CB FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF 40 40 40 FF 2E 2E 2E FF 7A 7A 7A FF F2 F2' - 'F2 FF FF D4 E3 FF F2 F2 F2 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 FF FF FF D4 E3 FF FF D4' - 'E3 FF FF D4 FF FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 34 28 28 28 FF D1 D1 D1 FF EB EB EB FF EB EB' - 'EB FF E8 E8 E8 FF E8 E8 E8 FF 00 FF 00 FF B5 B5' - 'B5 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B6 B6 B6 FF A4 A0 A0 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF B6 B6 B6 FF AA AA AA FF 62 62' - '62 FF FF D4 E3 FF FF D4 F0 FF F2 F2 F2 FF 00 00' - '00 33 28 28 28 FF D1 D1 D1 FF E8 E8 E8 FF EB EB' - 'EB FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF B6 B6 B6 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 E3 FF 6E 6E 6E FF 00 00 00 00 00 00' - '00 00 B6 B6 B6 FF FF D4 F0 FF F2 F2 F2 FF 00 00' - '00 33 27 27 27 FF D2 D2 D2 FF EA EA EA FF EB EB' - 'EB FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' - 'AE FF AF AF AF FF AF AF AF FF AF AF AF FF AF AF' - 'AF FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF CE CE CE FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'E3 FF FF D4 E3 FF 80 80 80 FF 00 00 00 78 00 00' - '00 00 FF D4 F0 FF FF D4 F0 FF F2 F2 F2 FF 00 00' - '00 33 26 26 26 FF D3 D3 D3 FF E8 E8 E8 FF E6 E6' - 'E6 FF E2 E2 E2 FF DB DB DB FF D8 D8 D8 FF D9 D9' - 'D9 FF D2 D2 D2 FF CF CF CF FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CE CE CE FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF C0 C0 C0 FF 62 62 62 FF 80 80' - '80 FF FF D4 F0 FF FF D4 F0 FF FF D4 E3 FF 00 00' - '00 33 24 24 24 FF D6 D6 D6 FF E9 E9 E9 FF E1 E1' - 'E1 FF E2 E2 E2 FF E0 E0 E0 FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF 92 92 92 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 FF FF FF D4 FF FF FF D4' - 'FF FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 34 24 24 24 FF DE DE DE FF D9 D9 D9 FF C4 C4' - 'C4 FF BF BF BF FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF 7A 7A 7A FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 07 05 05 05 FF C2 C2 C2 FF BC BC BC FF B2 B2' - 'B2 FF AB AB AB FF BB BB BB FF D5 D5 D5 FF D5 D5' - 'D5 FF D4 D4 D4 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' - 'D7 FF D8 D8 D8 FF D7 D7 D7 FF D3 D3 D3 FF D3 D3' - 'D3 FF D4 D4 D4 FF D5 D5 D5 FF 62 62 62 FF 86 86' - '86 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 FF A4 A4 A4 FF CF CF CF FF C5 C5' - 'C5 FF BF BF BF FF C9 C9 C9 FF D2 D2 D2 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' - 'D0 FF D4 D4 D4 FF D0 D0 D0 FF D3 D3 D3 FF 62 62' - '62 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 FF 59 59 59 FF D0 D0 D0 FF CD CD' - 'CD FF CD CD CD FF CA CA CA FF D3 D3 D3 FF D3 D3' - 'D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF DB DB DB FF E4 E4 E4 FF D3 D3 D3 FF D3 D3' - 'D3 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 FE 40 40 40 FF D2 D2 D2 FF CA CA' - 'CA FF CA CA CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D3 D3 D3 FF D2 D2 D2 FF D3 D3 D3 FF D2 D2' - 'D2 FF D1 D1 D1 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' - 'D3 FF 6E 6E 6E FF 92 92 92 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 E1 07 07 07 FF DD DD DD FF CC CC' - 'CC FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF C4 C4 C4 FF B3 B3 B3 FF 62 62 62 FF 9E 9E' - '9E FF FF D4 D4 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF CE CE CE FF 9E 9E 9E FF 92 92 92 FF 00 00' - '00 00 00 00 00 B2 00 00 00 FF DD DD DD FF CF CF' - 'CF FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' - 'CF FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF B3 B3 B3 FF B3 B3 B3 FF 00 00 00 FF 00 00' - '00 FF 62 62 62 FF 86 86 86 FF 86 86 86 FF 86 86' - '86 FF 6E 6E 6E FF 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 4B 00 00 00 FE D8 D8 D8 FF D4 D4' - 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF B3 B3 B3 FF B3 B3 B3 FF 00 00 00 CF 00 00' - '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 00 00 00 F2 CC CC CC FF D6 D6' - 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4' - 'C4 FF BD BD BD FF D0 D0 D0 FF 09 09 09 FF 00 00' - '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 02 00 00 00 BF 97 97 97 FF DC DC' - 'DC FF DC DC DC FF DE DE DE FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF E7 E7 E7 FF E7 E7' - 'E7 FF DC DC DC FF C6 C6 C6 FF 00 00 00 FF 00 00' - '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 77 77 77 FF D3 D3' - 'D3 FF E1 E1 E1 FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7 E7 FF E7 E7' - 'E7 FF D9 D9 D9 FF BB BB BB FF 00 00 00 FF 00 00' - '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 62 35 35 35 FF BD BD' - 'BD FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' - 'E6 FF D4 D4 D4 FF 9A 9A 9A FF 00 00 00 ED 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 2D 1E 1E 1E FF AB AB' - 'AB FF ED ED ED FF E7 E7 E7 FF EC EC EC FF EB EB' - 'EB FF ED ED ED FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EC EC EC FF E5 E5 E5 FF EB EB' - 'EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00 00 C3 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 8D 8D' - '8D FF C4 C4 C4 FF B2 B2 B2 FF B2 B2 B2 FF EB EB' - 'EB FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F3 F3 F3 FF D5 D5 D5 FF B6 B6 B6 FF B7 B7' - 'B7 FF CD CD CD FF 61 61 61 FF 00 00 00 85 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 64 64' - '64 FF DD DD DD FF DC DC DC FF E4 E4 E4 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF FA FA FA FF F2 F2 F2 FF D8 D8 D8 FF DC DC' - 'DC FF B0 B0 B0 FF 34 34 34 FF 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' - '00 FF 3D 3D 3D FF 49 49 49 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' - '49 FF 02 02 02 FF 00 00 00 FF 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' - '00 7F 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 D6 00 00 00 5C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF 00 FF FF FE 00 FF FF FC 00 FF FF E0 00 FF FF' - 'F0 00 80 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' - '00 7F C0 00 00 7F C0 00 00 7F E0 00 00 7F E0 00' - '00 FF E0 00 01 FF E0 00 01 FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 08 FF FF 00 00 00 00 00 8F FF FF 08 88' - '88 88 80 FF FF FF 0F FA F7 77 88 FF F7 FF 0F 88' - '88 88 88 FF F0 8F 0F FF FF FF F8 FF F8 FF 0F 77' - '77 77 78 FF FF FF 07 77 77 77 77 7F FF FF 07 77' - '77 77 77 8F FF FF 07 77 77 77 77 70 28 80 08 77' - '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 77' - '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 00' - '00 00 00 00 00 00 FF E0 00 00 FF C0 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01' - '00 00 00 07 00 00 80 07 00 00 80 07 00 00 80 0F' - '00 00 C0 1F 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 77 77 88 00 00' - '00 00 00 00 00 00 00 00 00 08 7F FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 8F FF FF FF FF 00 00' - '00 00 00 00 00 00 00 00 08 FF FF FF FF FF 00 00' - '00 00 00 00 00 00 00 00 87 FF FF FF FF FF 00 08' - '88 88 88 88 88 88 88 80 8F FF FF FF FF FF 00 87' - 'FF 7A FF FF 77 77 77 88 FF FF FF FF FF FF 00 7F' - 'FF AA AF 77 77 77 78 08 FF FF FF F7 FF FF 00 FF' - 'FF 8A 77 77 77 77 77 88 FF FF FF 78 8F FF 00 FF' - 'F8 88 88 88 88 88 88 88 FF FF FF 00 08 FF 00 FF' - 'F7 88 88 88 88 88 88 88 FF FF FF 00 07 FF 00 FF' - 'FF FF FF FF FF FF FF 78 FF FF FF 78 7F FF 00 FF' - 'FF FF FF FF FF FF FF 78 FF FF FF FF FF FF 00 FF' - '77 77 77 77 77 77 77 78 FF FF FF FF FF FF 00 F7' - '77 77 77 77 77 77 77 78 7F FF FF FF FF FF 00 77' - '77 77 77 77 77 77 77 77 87 FF FF FF FF FF 00 87' - '77 77 77 77 77 77 77 77 88 FF FF FF FF FF 00 87' - '77 77 77 77 77 77 77 77 78 8F FF FF FF FF 00 07' - '77 77 77 77 77 77 77 77 77 88 7F FF FF 78 00 07' - '77 77 77 77 77 77 77 77 77 70 02 88 88 70 00 07' - '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 08' - '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 08' - '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' - '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' - '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' - '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' - '77 77 77 77 77 77 77 77 77 00 00 00 00 00 00 00' - '87 77 77 77 77 77 77 77 77 00 00 00 00 00 00 00' - '08 88 88 88 88 88 88 88 80 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF 00 FF FF FE 00 FF FF FC 00 FF FF F8 00 FF FF' - 'F0 00 C0 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' - '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' - '00 7F C0 00 00 7F C0 00 00 7F C0 00 00 7F E0 00' - '00 FF E0 00 00 FF F0 00 03 FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 78 6E 6E 6E FF 62 62' - '62 FF 00 00 00 9C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 62 62 62 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'D4 FF FF D4 D4 FF 00 00 00 00 00 00 00 16 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 42 62 62' - '62 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF F2 F2 F2 FF 00 00 00 54 90 90 90 FF AB AC' - 'AC FF CC CC CC FF C4 C4 C4 FF C2 C2 C2 FF C1 C1' - 'C1 FF BC BC BC FF BD BD BD FF 6E 6E 6E FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'E3 FF F2 F2 F2 FF 00 00 00 FA EA EA EA FF E8 E8' - 'E8 FF 00 FF 00 FF CB CB CB FF C8 C8 C8 FF C8 C8' - 'C8 FF C8 C8 C8 FF C8 C8 C8 FF 56 56 56 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 F0 FF B6 B6 B6 FF FF B1' - 'C7 FF FF D4 E3 FF 00 00 00 F9 EF EF EF FF EB EB' - 'EB FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 62 62 62 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 F0 FF 00 00 00 78 62 62' - '62 FF F2 F2 F2 FF 00 00 00 F9 F7 F7 F7 FF F6 F6' - 'F6 FF F5 F5 F5 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1' - 'F1 FF F0 F0 F0 FF EF EF EF FF 62 62 62 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4 E3 FF FF D4' - 'FF FF FF D4 F0 FF 00 00 00 F7 F3 F3 F3 FF B7 B7' - 'B7 FF DA DA DA FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D8 D8 D8 FF D3 D3 D3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF 00 00 00 73 EF EF EF FF CB CB' - 'CB FF CE CE CE FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D3 D3 D3 FF 7A 7A' - '7A FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF 00 00 00 25 B7 B7 B7 FF CB CB' - 'CB FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4' - 'C4 FF 80 80 80 FF FF D4 D4 FF FF D4 F0 FF FF D4' - 'F0 FF E6 E6 E6 FF 00 00 00 00 5F 5F 5F FF D2 D2' - 'D2 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF 99 99 99 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 18 18 18 FF DB DB' - 'DB FF DE DE DE FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DD DD DD FF DD DD DD FF DD DD DD FF D9 D9' - 'D9 FF 7A 7A 7A FF 00 00 00 0A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 FF E5 E5' - 'E5 FF EB EB EB FF EB EB EB FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E7 E7 E7 FF E6 E6' - 'E6 FF 20 20 20 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 DD E4 E4' - 'E4 FF C1 C1 C1 FF ED ED ED FF EE EE EE FF EB EB' - 'EB FF ED ED ED FF ED ED ED FF C2 C2 C2 FF EC EC' - 'EC FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 44 80 80' - '80 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF B0 B0' - 'B0 FF 00 00 00 ED 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 2C 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 70 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF F0 00 00 FF E0 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 0F' - '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 80 0F' - '00 00 C0 1F 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 08 88 88 80 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '88 87 77 F7 77 88 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 08 87 FF FF FF FF F7 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87' - 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 08 FF FF FF FF FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 08 8F FF' - 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 88 7F FF FF FF FF FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 08 88 FF FF' - 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 08 8F FF FF FF FF FF FF FF FF 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 88 8F FF FF' - 'FF FF FF FF FF FF 00 08 7F FF F7 AA FF FF 77 77' - '77 77 77 70 88 7F FF FF FF FF FF FF FF FF 00 07' - 'FF FF FA AA AF 77 77 77 77 77 77 00 88 FF FF FF' - 'FF FF FF FF FF FF 00 07 FF FF FA AA A7 77 77 77' - '77 77 77 80 88 FF FF FF FF FF 78 87 FF FF 00 07' - 'FF FF FF AA 77 77 77 77 77 77 77 77 87 FF FF FF' - 'FF F7 87 88 FF FF 00 07 FF FF 88 88 88 88 88 88' - '88 88 88 88 87 FF FF FF FF F8 00 08 7F FF 00 07' - 'FF FF 88 88 88 88 88 88 88 88 88 88 87 FF FF FF' - 'FF F8 00 08 7F FF 00 07 FF FF 77 77 77 77 77 77' - '77 77 77 77 87 FF FF FF FF F8 00 08 FF FF 00 07' - 'FF FF F7 77 77 77 77 77 77 77 77 77 87 FF FF FF' - 'FF F7 88 8F FF FF 00 07 FF FF FF FF FF FF FF FF' - 'FF FF FF FF 87 FF FF FF FF FF FF FF FF FF 00 07' - 'FF FF FF 77 77 7F FF FF FF FF FF FF 88 FF FF FF' - 'FF FF FF FF FF FF 00 07 77 77 77 77 77 77 77 77' - '77 77 77 77 88 FF FF FF FF FF FF FF FF FF 00 07' - '77 77 77 77 77 77 77 77 77 77 77 77 78 7F FF FF' - 'FF FF FF FF FF FF 00 07 77 77 77 77 77 77 77 77' - '77 77 77 77 78 8F FF FF FF FF FF FF FF FF 00 07' - '77 77 77 77 77 77 77 77 77 77 77 77 77 87 FF FF' - 'FF FF FF FF FF FF 00 08 77 77 77 77 77 77 77 77' - '77 77 77 77 77 88 7F FF FF FF FF FF FF FF 00 08' - '77 77 77 77 77 77 77 77 77 77 77 77 77 78 8F FF' - 'FF FF FF FF FF FF 00 00 77 77 77 77 77 77 77 77' - '77 77 77 77 77 77 88 FF FF FF FF FF FF FF 00 00' - '77 77 77 77 77 77 77 77 77 77 77 77 77 77 78 87' - 'FF FF FF FF FF F8 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 88 87 FF FF FF 78 88 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '08 88 88 88 80 00 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '00 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' - '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' - '00 77 77 77 77 77 77 77 77 77 77 77 77 77 78 00' - '00 00 00 00 00 00 00 00 00 77 77 77 77 77 77 77' - '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' - '00 87 77 77 77 77 77 77 77 77 77 77 77 77 78 00' - '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' - '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' - '00 87 77 77 77 77 77 77 77 77 77 77 77 77 70 00' - '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' - '77 77 77 77 77 77 80 00 00 00 00 00 00 00 00 00' - '00 00 08 88 88 88 88 88 88 88 88 88 88 80 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF F0 00 00 00 FF FF FF FF E0 00 00 00 FF FF' - 'FF FF C0 00 00 00 FF FF FF FF 80 00 00 00 FF FF' - 'FF FE 00 00 00 00 FF FF FF FE 00 00 00 00 FF FF' - 'FF FC 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 00' - '00 00 00 60 00 00 00 00 00 00 00 20 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' - '00 00 00 07 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' - '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' - '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' - '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' - '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 18 18' - '18 00 19 19 19 00 1E 1E 1E 00 1F 1F 1F 00 20 20' - '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' - '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2A 2A' - '2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E 2E 00 2F 2F' - '2F 00 34 34 34 00 35 35 35 00 39 39 39 00 3D 3D' - '3D 00 40 40 40 00 41 41 41 00 48 48 48 00 49 49' - '49 00 4A 4A 4A 00 4B 4B 4B 00 53 53 53 00 56 56' - '56 00 59 59 59 00 5D 5D 5D 00 5F 5F 5F 00 61 61' - '61 00 62 62 62 00 64 64 64 00 6E 6E 6E 00 75 75' - '75 00 77 77 77 00 7A 7A 7A 00 7E 7E 7E 00 7F 7F' - '7F 00 00 C0 00 00 00 FF 00 00 80 80 80 00 83 83' - '83 00 86 86 86 00 8A 8A 8A 00 8D 8D 8D 00 90 90' - '90 00 92 92 92 00 93 93 93 00 97 97 97 00 99 99' - '99 00 9A 9A 9A 00 9E 9E 9E 00 9F 9F 9F 00 A4 A0' - 'A0 00 A4 A4 A4 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9' - 'A9 00 AA AA AA 00 AB AB AB 00 AD A8 AB 00 AB AC' - 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' - 'B0 00 B2 B2 B2 00 B3 B3 B3 00 B5 B5 B5 00 B6 B6' - 'B6 00 B7 B7 B7 00 B8 B4 B6 00 B8 B8 B8 00 BA BA' - 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' - 'BE 00 BF BF BF 00 FF B1 C7 00 C0 C0 C0 00 C1 C1' - 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5' - 'C5 00 C6 C6 C6 00 C8 C8 C8 00 C8 C9 C9 00 C9 C9' - 'C9 00 CA CA CA 00 CB CB CB 00 CC CC CC 00 CD CD' - 'CD 00 CE CE CE 00 CF CF CF 00 D0 D0 D0 00 D1 D1' - 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' - 'D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9' - 'D9 00 DA DA DA 00 DB DB DB 00 DC DC DC 00 DD DD' - 'DD 00 DE DE DE 00 DF DF DF 00 FF D4 D4 00 FF D4' - 'E3 00 FF D4 F0 00 FF D4 FF 00 E0 E0 E0 00 E1 E1' - 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' - 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' - 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' - 'ED 00 EE EE EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1' - 'F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5' - 'F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9' - 'F9 00 FA FA FA 00 FF FF FF 00 00 00 00 00 78 EE' - '0C 01 78 EE 0C 01 40 00 00 00 40 00 00 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 70 EE 0C 01 00 24 0D 01 01 01' - 'F5 77 78 01 38 00 78 EE 0C 01 E0 19 0D 01 E8 19' - '0D 01 78 01 38 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 BE B3 E7 77 70 EE 0C 01 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 08 04 00 00 E4 00 00 00 08 04 00 00 08 01' - '00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00' - '38 00 BC 18 95 00 C0 18 95 00 B0 19 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 81 E9' - '49 00 00 00 38 00 00 00 00 00 78 EE 0C 01 78 EE' - '0C 01 A4 1A 95 00 40 00 00 00 40 00 00 00 B8 10' - 'E9 77 FF FF FF FF C9 F1 E7 77 16 EA 4B 00 F8 00' - '00 00 B4 1A 95 00 DC E3 49 00 E0 A3 4E 00 FF FF' - 'FF FF 10 00 00 00 10 DA 4B 00 78 EE 0C 01 71 CC' - '43 00 78 EE 0C 01 50 7E 0D 01 A4 1A 95 00 F8 A2' - 'AF 00 C4 F5 AF 00 04 00 00 00 50 7E 0D 01 0F 02' - '00 00 B8 EE 0C 01 10 00 00 00 00 00 00 00 20 00' - '00 00 78 EE 0C 01 40 00 00 00 10 00 00 00 00 01' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 10 00 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 35 2D 2B' - '2B 2B 35 9D 9D 9D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 9D 9D 37 2D 30 47 6B 77' - '93 77 6B 47 35 2D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 9D 9D 30 35 6B 9C 7F 7F 7F' - '7F 7D 7D 7D 7D 5D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 9D 9D 9D 2B 5D 7F 7F 7F 7F 7F 7F' - '7D 7D 7D 7D 7D 93 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 9D 9D 9D 2D 87 7F 7F 7F 7F 7F 7F 7D' - '7D 7D 7D 7D 93 93 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 9D 26 2B 87 7F 7F 7F 7F 7F 7F 7D 7D' - '7D 7D 7D 93 93 93 00 00 00 00 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 23 2B 5F 7F 7F 7F 7F 7F 7F 7D 7D 7D' - '7D 7D 93 93 93 93 00 00 9D 9D 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 2B 26 3B 7F 7F 7F 7F 7F 7F 7F 7D 7D 7D' - '7D 93 93 93 93 93 00 9D 9D 9D 9D 0F 18 17 18 17' - '17 17 17 17 17 17 17 17 17 17 16 16 16 16 16 16' - '16 16 16 23 2B 93 7F 7F 7F 7F 7F 7F 7F 7D 7D 7D' - '93 93 93 93 93 93 00 9D 9D 12 3A 54 4B 4A 49 6A' - '69 68 66 61 60 5F 5F 60 5D 5E 5B 5B 58 59 56 59' - '59 59 2D 26 40 7F 7F 7F 7F 7F 7F 7F 7F 7D 7D 7F' - '7E 7E 93 93 93 93 9D 9D 01 38 49 8C 89 89 89 71' - '33 33 88 89 89 84 7A 75 6F 6A 6A 6A 6A 6A 65 6A' - '47 19 26 2B 77 7F 7F 7F 7F 7F 7F 7F 7F 80 80 80' - '80 80 7F 93 93 93 9D 9D 0B 49 8C 8C 89 89 89 34' - '34 34 33 82 7C 72 69 6F 68 6A 6A 6A 6A 6A 6A 6A' - '1F 19 26 30 93 93 7E 93 7F 7F 7F 7F 7F 80 7F 7E' - '7E 80 80 93 93 93 9D 9D 15 49 8B 8C 8C 89 89 34' - '34 34 34 68 64 64 64 64 64 64 64 64 64 64 64 64' - '3C 1F 26 3B 93 93 93 93 93 7E 7F 7F 7F 7F 52 35' - '3B 5C 7F 7F 7E 93 9D 9D 14 6E 8D 8C 8C 89 89 89' - '34 34 51 51 52 52 52 52 52 52 52 52 52 52 52 52' - '52 52 26 42 93 93 93 93 93 93 93 7F 7F 52 2D 47' - '2B 30 7E 7F 93 93 9D 9D 14 6E 8F 89 8C 89 35 35' - '35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35' - '35 35 2B 52 93 93 93 93 93 93 93 7F 7E 2D 00 00' - '00 2B 52 7F 93 93 9D 9D 13 6E 90 8C 8C 8C 35 35' - '35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35' - '35 35 2B 52 93 93 93 93 93 93 93 7F 7D 2B 9D 00' - '00 2B 52 7F 93 93 9D 9D 13 6F 93 8B 8C 8C 44 44' - '44 48 4C 4E 4D 4D 4D 4D 4D 4D 48 48 48 48 48 48' - '48 48 2B 6B 93 93 93 93 93 93 7E 7F 7E 35 9D 9D' - '00 30 7F 7F 7E 93 9D 9D 12 70 8A 89 87 85 83 78' - '79 75 76 6F 6F 6C 6D 6D 6D 6D 6D 6D 6D 6D 6D 6D' - '6D 6D 2B 6B 93 93 93 93 93 93 93 7F 7F 5D 30 2B' - '35 87 7F 7F 93 7E 9D 9D 12 70 98 99 97 97 97 96' - '96 95 95 94 94 94 93 93 92 92 92 91 91 91 90 90' - '8F 8F 2B 47 93 93 93 93 93 93 93 7E 7F 7F 7E 7D' - '7E 80 80 7F 7F 7F 9D 9D 11 73 9C 8A 82 83 83 81' - '7C 7C 7C 7C 7C 81 81 81 81 81 81 81 81 81 81 81' - '81 81 2B 3B 93 93 93 93 93 93 93 93 93 80 80 80' - '80 80 7F 7F 7F 7F 9D 9D 11 7B 99 76 61 57 5B 75' - '77 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76' - '76 76 2D 30 93 93 93 93 93 93 93 93 93 7E 7D 7D' - '7D 7D 7F 7F 7F 7F 9D 9D 0D 77 94 63 46 53 4E 60' - '77 75 75 75 75 75 74 74 74 74 74 74 74 74 75 75' - '75 75 70 2B 5D 93 93 93 93 93 93 93 93 93 7D 7D' - '7D 7D 7F 7F 7F 7F 9D 9D 03 5F 97 58 4F 60 48 57' - '75 72 72 72 71 70 70 72 74 75 75 74 72 70 70 70' - '71 72 70 2B 37 93 93 93 93 93 93 93 93 7D 7D 7D' - '7D 7D 7F 7F 7F 7F 00 9D 9D 43 95 6C 62 6F 5B 66' - '70 6F 6D 70 6D 6D 72 72 72 72 72 72 72 72 6D 6D' - '71 6D 70 70 2B 52 93 93 93 93 93 93 7D 7D 7D 7D' - '7D 7D 7F 7F 7F 7F 00 9D 9D 31 90 6E 6C 68 6C 6E' - '6B 6C 72 72 72 72 72 72 72 72 72 72 72 72 72 72' - '72 82 70 70 30 30 5C 93 93 93 93 7D 7D 7D 7D 7D' - '7D 7F 7F 7F 7F 7F 00 9D 9D 27 8A 6D 6A 6A 6A 67' - '70 70 70 70 71 72 73 73 73 73 73 73 73 73 72 72' - '78 85 70 70 70 2D 3B 93 93 93 7D 7D 7D 7D 7D 7D' - '7F 7F 7F 7F 7F 7F 00 9D 9D 1F 74 6F 67 68 67 71' - '70 70 70 6E 6F 6F 6F 6F 6F 6F 70 6F 70 70 6F 6F' - '6E 6D 70 70 70 61 2D 3B 93 7D 7D 7D 7D 7D 7D 7F' - '7F 7F 7F 7F 7F 7F 00 9D 9D 10 53 78 67 68 6B 70' - '70 6C 6E 6D 6D 6D 6D 6C 70 70 6B 70 70 70 70 70' - '70 6B 70 70 70 61 61 2D 35 6B 7D 7D 7D 7D 7F 7F' - '7F 7F 7F 7F 87 3B 00 9D 9D 05 41 7A 69 6A 70 70' - '70 6D 6D 6D 6D 6D 6D 70 70 70 70 70 70 70 70 70' - '70 70 70 70 70 61 61 50 3E 2B 40 5D 7D 7F 7F 7F' - '7F 9C 6B 40 2B 3B 00 00 9D 9D 36 7A 6C 6E 70 70' - '6D 6D 6D 6D 6D 6D 6D 6D 6C 70 70 70 70 70 70 70' - '70 70 70 70 70 70 50 50 3E 9D 9D 30 2B 37 37 37' - '37 2B 2D 00 00 00 00 00 9D 9D 29 79 6E 6F 70 70' - '6E 6E 6E 6E 6E 6E 6E 6E 6E 70 70 70 70 70 70 70' - '70 70 70 70 70 70 50 50 3E 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 9D 9D 20 75 71 6F 70 70' - '70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70' - '70 70 70 70 70 70 50 50 3E 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 9D 9D 18 69 73 72 70 70' - '73 73 73 73 73 73 73 73 73 73 73 70 70 70 70 70' - '70 70 70 70 61 70 59 6D 3E 07 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 9D 9D 0A 4E 78 78 7B 7B' - '7B 76 77 77 77 77 77 77 77 77 77 77 7A 7A 7A 7A' - '7A 77 7A 7A 88 76 69 67 30 02 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 9D 9D 06 3D 79 7C 79 7B' - '7B 7B 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A' - '7A 7A 88 88 88 7A 79 63 25 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 2F 70 83 82 7B' - '7B 7B 7B 7B 81 81 81 81 81 81 81 81 81 81 81 81' - '82 82 88 88 88 84 76 57 1D 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 24 66 86 84 85' - '8C 8C 8C 8C 8C 8C 85 85 85 85 85 85 85 85 86 86' - '88 88 88 88 85 87 73 45 0E 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 1C 59 87 87 87' - '88 88 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 88' - '88 88 88 88 87 89 71 3F 08 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 0C 48 85 8E 88' - '87 8D 8C 8B 8E 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C' - '8C 8D 8B 86 8C 8C 73 38 9D 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 9D 9D 06 3E 85 7C 59' - '5E 73 8D 8E 8E 8F 8F 8E 8D 8C 8C 8D 8E 8F 8F 8E' - '8F 85 5F 5A 6E 8D 71 2E 9D 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 9D 9D 39 81 61 4F' - '55 4F 8C 92 91 91 91 91 91 91 91 91 91 91 91 91' - '94 72 4E 52 53 8C 6A 2A 9D 9D 9D 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 9D 9D 2C 6B 7A 79' - '72 85 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A' - '9B 93 7C 75 79 74 4E 1B 9D 9D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 9D 9D 0B 35 5A 70' - '74 78 75 75 75 75 75 75 75 75 75 75 75 75 75 75' - '75 76 76 74 6A 4E 28 04 9D 9D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 9D 9D 9D 09 1E 22' - '21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21' - '21 21 21 22 22 1A 02 9D 9D 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' - '9D 9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF F0 00 00 00 FF FF' - 'FF FF E0 00 00 00 FF FF FF FF C0 00 00 00 FF FF' - 'FF FF 80 00 00 00 FF FF FF FE 00 00 00 00 FF FF' - 'FF FC 00 00 00 00 FF FF FF FC 00 00 00 00 F0 00' - '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 E0 00 00 00 00 00 00 00 60 00 00 00 00' - '00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 C0 00 00 00 00 07 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' - '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' - '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0C 00 00 00 24 00 00 00 30 00 00 00 48 00 00' - '00 78 00 00 00 90 00 00 00 90 00 00 00 90 00 00' - '00 90 00 00 00 78 00 00 00 48 00 00 00 30 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 3C 00 00 00 78 00 00 00 90 80 80 80 FF 6E 6E' - '6E FF 62 62 62 FF 62 62 62 FF 62 62 62 FF 80 80' - '80 FF 00 00 00 B4 00 00 00 9C 00 00 00 90 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 86 86' - '86 FF 6E 6E 6E FF 7A 7A 7A FF AA AA AA FF CE CE' - 'CE FF DA DA DA FF F2 F2 F2 FF DA DA DA FF CE CE' - 'CE FF AA AA AA FF 80 80 80 FF 6E 6E 6E FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 3C 7A 7A 7A FF 80 80' - '80 FF CE CE CE FF FF FF FF FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 24 00 00 00 48 62 62 62 FF C0 C0 C0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' - '00 78 6E 6E 6E FF E6 E6 E6 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 56 56 56 56 FF 62 62' - '62 FF E6 E6 E6 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 42 00 00 00 42 4A 4A 4A FF 62 62 62 FF C2 C2' - 'C2 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' - '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 FF 62 62 62 FF 56 56 56 FF 92 92 92 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' - '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' - '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' - '2A FF 4A 4A 4A FF 62 62 62 FF F2 F2 F2 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' - '90 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' - 'AB FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' - 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2' - 'C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF' - 'BF FF BF BF BF FF BC BC BC FF BD BD BD FF BA BA' - 'BA FF BD BD BD FF BD BD BD FF BD BD BD FF 6E 6E' - '6E FF 56 56 56 FF 9E 9E 9E FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF FF D4 E3 FF FF D4 E3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF AD A8' - 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF D4 D4 D4 FF 00 C0 00 FF 00 C0 00 FF E7 E7' - 'E7 FF E8 E8 E8 FF E8 E8 E8 FF E3 E3 E3 FF DD DD' - 'DD FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' - 'C9 FF CD CD CD FF AA AA AA FF 2E 2E 2E FF 56 56' - '56 FF 62 62 62 FF DA DA DA FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 FF FF FF D4' - 'FF FF FF D4 FF FF FF D4 FF FF FF D4 FF FF FF D4' - 'F0 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 15 00 00 00 F0 19 19 19 FF AD A8 AB FF EB EB' - 'EB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 C0' - '00 FF E1 E1 E1 FF DF DF DF FF D5 D5 D5 FF CC CC' - 'CC FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CD CD CD FF 40 40 40 FF 2E 2E 2E FF 56 56' - '56 FF 7A 7A 7A FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'E3 FF F2 F2 F2 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 FF FF FF D4' - 'F0 FF FF D4 E3 FF FF D4 E3 FF FF D4 FF FF FF D4' - 'FF FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 30 00 00 00 FA 29 29 29 FF AD A8 AB FF EA EA' - 'EA FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF' - '00 FF CB CB CB FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' - 'C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' - 'C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' - 'C8 FF C8 C8 C8 FF 93 93 93 FF 40 40 40 FF 56 56' - '56 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF B6 B6' - 'B6 FF 80 80 80 FF 92 92 92 FF FF B1 C7 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 E3 FF F2 F2 F2 FF 00 00' - '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' - 'EC FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' - 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF B5 B5' - 'B5 FF B5 B5 B5 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF 56 56' - '56 FF A4 A0 A0 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF FF D4 F0 FF B6 B6 B6 FF 6E 6E' - '6E FF AA AA AA FF 62 62 62 FF 7A 7A 7A FF FF D4' - 'E3 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' - 'EE FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 62 62' - '62 FF B6 B6 B6 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF FF D4 E3 FF 6E 6E 6E FF 00 00' - '00 00 00 00 00 00 00 00 00 00 62 62 62 FF B6 B6' - 'B6 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' - 'EF FF EB EB EB FF EB EB EB FF EB EB EB FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 62 62' - '62 FF B6 B6 B6 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF FF D4 D4 FF 62 62 62 FF 00 00' - '00 78 00 00 00 00 00 00 00 00 62 62 62 FF B6 B6' - 'B6 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' - '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' - 'F2 FF EA EA EA FF EB EB EB FF EB EB EB FF A7 A7' - 'A7 FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' - 'AE FF B0 B0 B0 FF AF AF AF FF AF AF AF FF AF AF' - 'AF FF AF AF AF FF AF AF AF FF AF AF AF FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' - 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF 62 62' - '62 FF CE CE CE FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'E3 FF FF D4 F0 FF FF D4 E3 FF 80 80 80 FF 00 00' - '00 78 00 00 00 78 00 00 00 00 7A 7A 7A FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 E3 FF F2 F2 F2 FF 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF E9 E9' - 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' - 'E2 FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' - 'D9 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF 62 62' - '62 FF CE CE CE FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 F0 FF FF D4 F0 FF C0 C0 C0 FF 7A 7A' - '7A FF 62 62 62 FF 80 80 80 FF E6 E6 E6 FF FF D4' - 'F0 FF FF D4 F0 FF F2 F2 F2 FF FF D4 E3 FF 00 00' - '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' - 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' - 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' - 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' - 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' - 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' - 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF 62 62' - '62 FF AA AA AA FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 E3 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'E3 FF FF D4 D4 FF FF D4 E3 FF FF D4 FF FF FF D4' - 'FF FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' - 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' - 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF 62 62' - '62 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 FF FF FF D4' - 'FF FF FF D4 FF FF FF D4 FF FF FF D4 FF FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' - 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' - 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF 6E 6E' - '6E FF 7A 7A 7A FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' - 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' - 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D3 D3' - 'D3 FF 62 62 62 FF C0 C0 C0 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' - 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' - 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' - 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' - 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D3 D3' - 'D3 FF 62 62 62 FF 86 86 86 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' - 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' - 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' - 'D0 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' - 'D0 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0 D0 FF D3 D3' - 'D3 FF D3 D3 D3 FF 62 62 62 FF B6 B6 B6 FF F2 F2' - 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' - 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' - 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' - 'D5 FF D5 D5 D5 FF D5 D5 D5 FF E1 E1 E1 FF D3 D3' - 'D3 FF D3 D3 D3 FF 7A 7A 7A FF 7A 7A 7A FF FF B1' - 'C7 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' - 'F2 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' - 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' - 'CD FF CA CA CA FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' - 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF 6E 6E 6E FF 92 92' - '92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' - 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' - 'CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3' - 'D3 FF D2 D2 D2 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2' - 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF 6E 6E' - '6E FF 92 92 92 FF F2 F2 F2 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' - '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' - 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' - 'CE FF D3 D3 D3 FF D3 D3 D3 FF CF CF CF FF D1 D1' - 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF CF CF CF FF D3 D3 D3 FF D3 D3 D3 FF CE CE' - 'CE FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CE CE CE FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF C4 C4' - 'C4 FF 6E 6E 6E FF 80 80 80 FF CE CE CE FF FF D4' - 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF E6 E6 E6 FF 92 92 92 FF 00 00' - '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' - '9F FF DD DD DD FF CC CC CC FF CD CD CD FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF C4 C4' - 'C4 FF B3 B3 B3 FF 99 99 99 FF 62 62 62 FF 9E 9E' - '9E FF C0 C0 C0 FF FF D4 D4 FF FF D4 F0 FF FF D4' - 'F0 FF FF D4 F0 FF FF D4 F0 FF FF FF FF FF CE CE' - 'CE FF 9E 9E 9E FF 62 62 62 FF 92 92 92 FF 00 00' - '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' - '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF D3 D3' - 'D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' - 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 FF 00 00' - '00 FF 7A 7A 7A FF 62 62 62 FF 86 86 86 FF 86 86' - '86 FF 86 86 86 FF 86 86 86 FF 62 62 62 FF 6E 6E' - '6E FF 00 00 00 24 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' - '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D3 D3' - 'D3 FF D3 D3 D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' - 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 CF 00 00' - '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' - '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' - 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 CF 00 00' - '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' - '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' - 'D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF C4 C4 C4 FF D3 D3 D3 FF BD BD' - 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' - '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' - '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF DE DE' - 'DE FF DE DE DE FF DE DE DE FF D9 D9 D9 FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DA DA DA FF DD DD' - 'DD FF DD DD DD FF E7 E7 E7 FF D9 D9 D9 FF CC CC' - 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' - '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' - '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' - 'DC FF DE DE DE FF DE DE DE FF DE DE DE FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF DD DD DD FF DC DC' - 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' - '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' - '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' - 'E1 FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' - 'DE FF DE DE DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7' - 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E3 E3 E3 FF D9 D9' - 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' - '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' - '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' - 'E3 FF E4 E4 E4 FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' - 'E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' - 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' - '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' - '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' - 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' - 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' - 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' - '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' - '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' - 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' - 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' - 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EA EA' - 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' - 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' - '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' - 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' - 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' - 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' - 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' - 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' - 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' - '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' - 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' - 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' - 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' - 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' - 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' - 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' - 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' - 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' - 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' - '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' - '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' - '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' - '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' - '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF F0 00 00 00 FF FF FF FF E0 00 00 00 FF FF' - 'FF FF C0 00 00 00 FF FF FF FF 80 00 00 00 FF FF' - 'FF FF 00 00 00 00 FF FF FF FE 00 00 00 00 FF FF' - 'FF FC 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 00' - '00 00 00 60 00 00 00 00 00 00 00 20 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' - '00 00 00 01 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' - '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00' -} */ - -/* BINRES ramdisk.ico */ -12 ICON ramdisk.ico -/* { - '00 00 01 00 07 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 76 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 5E 03 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 C6 08 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 EE 09 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 96 18 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 FE 1E 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 A6 44 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 88 00 66 00 00 00 00 00 00 00 00 00 00' - '00 00 08 08 80 E6 00 00 00 00 00 00 00 00 00 00' - '00 00 80 08 07 EE 00 00 00 00 00 00 00 00 00 00' - '00 08 00 08 00 0E 00 60 00 00 00 00 00 00 00 00' - '00 80 00 80 80 08 00 66 00 00 00 00 00 00 00 00' - '08 00 08 00 08 00 80 E6 00 00 00 00 00 00 00 00' - '80 00 80 00 00 80 07 EE 00 00 00 00 00 00 00 08' - '00 08 00 00 00 08 00 0E 00 60 00 00 00 00 00 80' - '00 80 00 08 00 00 80 08 00 66 00 00 00 00 00 80' - '08 00 00 80 80 00 08 00 80 E6 00 00 00 00 00 80' - '80 00 08 08 08 00 00 80 07 EE 00 00 00 00 00 88' - '00 00 80 80 80 00 00 08 00 0E 00 60 00 00 66 07' - '00 00 08 08 00 00 00 00 80 08 00 66 00 00 66 00' - '70 00 00 80 00 08 00 00 08 00 80 E6 00 00 EE EE' - '07 00 00 00 00 00 80 00 00 80 07 EE 00 00 0E E0' - '00 70 00 00 08 00 08 00 00 08 00 0E 00 60 00 00' - '66 07 00 00 00 80 00 80 00 00 80 08 00 66 00 00' - '66 00 70 00 00 08 00 08 00 00 08 00 80 E6 00 00' - 'EE EE 07 00 00 00 80 00 80 00 00 80 07 EE 00 00' - '0E E0 00 70 00 00 08 00 00 00 00 08 00 0E 00 00' - '00 00 66 07 00 00 00 80 00 00 00 00 80 08 00 00' - '00 00 66 00 70 00 00 00 08 88 00 00 08 08 00 00' - '00 00 EE EE 07 00 00 00 80 80 80 00 00 87 00 00' - '00 00 0E E0 00 70 00 00 88 08 80 00 00 70 00 00' - '00 00 00 00 66 07 00 00 80 80 80 00 07 00 00 00' - '00 00 00 00 66 00 70 00 08 88 00 00 70 00 00 00' - '00 00 00 00 EE EE 07 00 00 00 00 07 00 00 00 00' - '00 00 00 00 0E E0 00 70 00 00 00 70 00 00 00 00' - '00 00 00 00 00 00 66 07 00 00 07 00 00 00 00 00' - '00 00 00 00 00 00 66 00 70 00 70 00 00 00 00 00' - '00 00 00 00 00 00 EE EE 07 07 00 00 00 00 00 00' - '00 00 00 00 00 00 0E E0 00 70 00 00 00 00 FF CC' - 'FF FF FF 84 FF FF FF 00 FF FF FE 00 DF FF FC 00' - 'CF FF F8 00 4F FF F0 00 0F FF E0 00 0D FF C0 00' - '0C FF C0 00 04 FF C0 00 00 FF C0 00 00 DF 00 00' - '00 CF 00 00 00 4F 08 00 00 0F 9C 00 00 0D F0 00' - '00 0C F0 00 00 04 F0 80 00 00 F9 C0 00 00 FF 00' - '00 00 FF 00 00 00 FF 08 00 00 FF 9C 00 01 FF F0' - '00 03 FF F0 00 07 FF F0 80 0F FF F9 C0 1F FF FF' - '00 3F FF FF 00 7F FF FF 08 FF FF FF 9D FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 1C 04 04 00 18 18' - '18 00 1A 1A 1A 00 1C 1C 1C 00 36 0E 0E 00 3C 14' - '14 00 34 1C 1C 00 20 20 20 00 24 24 24 00 28 28' - '28 00 30 30 30 00 38 38 38 00 3C 3C 3C 00 40 28' - '28 00 46 46 46 00 48 48 48 00 4C 4C 4C 00 50 50' - '50 00 52 52 52 00 54 54 54 00 56 56 56 00 58 58' - '58 00 68 68 68 00 74 74 74 00 78 78 78 00 7E 7E' - '7E 00 7F 7F 7F 00 00 92 92 00 00 9C 9C 00 00 BC' - 'BC 00 00 C0 C0 00 00 D0 D0 00 00 DF DF 00 00 E3' - 'E3 00 00 E5 E5 00 00 F7 F7 00 00 FB FB 00 00 FF' - 'FF 00 90 90 90 00 A8 A8 A8 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 11 00 00 00 B8 09' - '38 00 00 00 38 00 70 63 0C 01 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 76 00' - '00 00 76 00 00 00 07 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 58 00' - '5A 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' - '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 72' - '61 6D 64 69 73 6B 2E 69 63 6F 00 93 4B 00 14 1A' - '95 00 1F 3B D4 77 11 00 00 00 88 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 70 63 0C 01 76 00 00 00 00 00' - '00 00 C9 F1 E7 77 76 00 00 00 A4 1A 95 00 07 00' - '00 00 00 00 00 00 76 00 00 00 76 00 00 00 07 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 70 63 0C 01 76 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 18 00 1F 00 00' - '00 00 00 00 00 00 00 00 00 00 04 0F 07 26 00 00' - '00 00 00 00 00 00 00 00 00 08 08 04 13 01 00 20' - '00 00 00 00 00 00 00 00 08 08 0A 29 29 15 07 26' - '00 00 00 00 00 00 00 11 04 0A 29 29 29 29 15 01' - '00 20 00 00 00 00 00 1A 03 29 0B 29 29 29 29 15' - '07 26 00 00 00 00 1C 05 0C 29 29 0B 29 29 29 29' - '15 01 00 20 00 00 21 25 00 0D 29 29 0B 29 29 29' - '29 15 07 26 00 00 00 00 1D 06 0D 29 29 16 12 29' - '29 29 15 01 00 1E 00 00 24 25 00 0D 29 29 14 09' - '29 29 29 15 07 23 00 00 00 00 1D 06 0D 29 29 0A' - '02 12 29 29 13 0E 00 00 00 00 24 25 00 0D 29 29' - '19 17 12 29 29 28 00 00 00 00 00 00 1D 06 0D 29' - '10 19 04 29 27 00 00 00 00 00 00 00 24 25 00 0D' - '29 29 29 27 00 00 00 00 00 00 00 00 00 00 1D 06' - '0D 29 27 00 00 00 00 00 00 00 00 00 00 00 21 22' - '00 1A 00 00 00 00 FA FF 00 00 F0 FF 00 00 E0 BF' - '00 00 C0 3F 00 00 80 2F 00 00 80 0F 00 00 00 0B' - '00 00 20 03 00 00 C0 02 00 00 C8 00 00 00 F0 00' - '00 00 F2 00 00 00 FC 01 00 00 FC 83 00 00 FF 07' - '00 00 FF 2F 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '08 0E 00 00 00 00 00 00 08 0E 00 00 00 00 00 00' - '00 80 0E 00 00 00 00 00 00 08 0E 00 00 00 08 00' - '00 00 80 0E 00 00 08 00 00 00 08 0E 00 00 60 00' - '00 00 00 80 0E 00 EE 00 00 00 00 08 0E 00 00 60' - '00 08 80 00 80 06 00 EE 00 00 80 00 08 0E 00 00' - '60 00 00 08 00 80 00 00 EE 00 00 88 80 07 00 00' - '00 60 00 88 00 80 00 00 00 EE 00 00 08 00 00 00' - '00 00 60 00 80 00 00 00 00 00 EE 08 00 00 FA FF' - '00 00 F0 FF 00 00 E0 BF 00 00 C0 3F 00 00 80 2F' - '00 00 80 0F 00 00 00 0B 00 00 20 03 00 00 C0 02' - '00 00 C8 00 00 00 F0 00 00 00 F2 00 00 00 FC 01' - '00 00 FC 83 00 00 FF 07 00 00 FF 2F 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' - '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' - '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' - '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 18 18' - '18 00 19 19 19 00 1E 1E 1E 00 1F 1F 1F 00 20 20' - '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' - '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2B 2B' - '2B 00 2C 2C 2C 00 2F 2F 2F 00 34 34 34 00 35 35' - '35 00 39 39 39 00 3B 3B 3B 00 3D 3D 3D 00 3F 3F' - '3F 00 40 40 40 00 41 41 41 00 47 47 47 00 48 48' - '48 00 49 49 49 00 4B 4B 4B 00 53 53 53 00 56 56' - '56 00 59 59 59 00 5D 5D 5D 00 5F 5F 5F 00 61 61' - '61 00 64 64 64 00 68 68 68 00 6A 6A 6A 00 6C 6C' - '6C 00 70 70 70 00 71 71 71 00 72 72 72 00 74 74' - '74 00 75 75 75 00 77 77 77 00 78 78 78 00 79 79' - '79 00 7A 7A 7A 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F' - '7F 00 00 80 80 00 00 FF FF 00 80 80 80 00 81 81' - '81 00 83 83 83 00 85 85 85 00 87 87 87 00 88 88' - '88 00 8A 8A 8A 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' - '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 97 97' - '97 00 98 98 98 00 99 99 99 00 9A 9A 9A 00 9C 9C' - '9C 00 9D 9D 9D 00 9F 9F 9F 00 A0 A0 A0 00 A2 A2' - 'A2 00 A4 A4 A4 00 A5 A5 A5 00 A7 A7 A7 00 A8 A8' - 'A8 00 A9 A9 A9 00 AB AB AB 00 AD AD AD 00 AE AE' - 'AE 00 B0 B0 B0 00 B2 B2 B2 00 B3 B3 B3 00 B6 B6' - 'B6 00 B7 B7 B7 00 B8 B8 B8 00 B9 B9 B9 00 BA BA' - 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' - 'BE 00 BF BF BF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C2' - 'C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5 C5 00 C6 C6' - 'C6 00 C7 C7 C7 00 C8 C8 C8 00 C9 C9 C9 00 CA CA' - 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' - 'CE 00 CF CF CF 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' - 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' - 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' - 'DA 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' - 'DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' - 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' - 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' - 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' - 'EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2' - 'F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' - 'F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9 F9 00 FA FA' - 'FA 00 FF FF FF 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' - '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 72' - '61 6D 64 69 73 6B 2E 69 63 6F 00 93 4B 00 14 1A' - '95 00 1F 3B D4 77 11 00 00 00 88 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 70 63 0C 01 76 00 00 00 00 00' - '00 00 C9 F1 E7 77 76 00 00 00 A4 1A 95 00 07 00' - '00 00 00 00 00 00 76 00 00 00 76 00 00 00 07 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 70 63 0C 01 76 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4' - 'A4 A4 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D' - '3D A4 A4 3B 3B A4 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4' - '3D 3D A4 3C 3B A4 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4' - '3D A4 68 3C 3C A4 00 A4 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4 A4' - '3D A4 A4 A4 3C A4 00 3B A4 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4 A4 3D' - 'A4 3D A4 A4 3D A4 00 3B 3B 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 3D A4 A4 A4 3D A4' - 'A4 A4 3D A4 A4 3D 00 3C 3B A4 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4' - 'A4 A4 A4 3D A4 A4 68 3C 3C A4 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4' - 'A4 A4 A4 A4 3D A4 A4 A4 3C A4 00 3B A4 00 00 00' - '00 00 00 00 00 00 00 A4 A4 A4 A4 0F 17 16 17 16' - '16 16 16 16 16 16 16 3D A4 A4 A4 3D A4 A4 A4 A4' - '3D A4 A4 A4 A4 3D A4 A4 3D A4 00 3B 3B A4 00 00' - '00 00 00 00 00 00 00 A4 A4 12 47 72 75 73 76 75' - '74 73 71 6F 6E 6D 6C 3D A4 A4 3D A4 A4 A4 A4 3D' - 'A4 3D A4 A4 A4 A4 3D A4 A4 3D A4 3C 3B A4 00 00' - '00 00 00 00 00 00 A4 A4 01 43 93 90 8F 7D 40 42' - '48 4B 52 59 62 68 6B 3D A4 3D A4 A4 A4 A4 3D A4' - '3D A4 3D A4 A4 A4 A4 3D A4 A4 68 3C 3C A4 00 A4' - '00 00 00 00 00 00 A4 A4 0B 6F 94 8A 8E 73 1C 1E' - '26 31 41 48 4F 54 56 3D 3D A4 A4 A4 A4 3D A4 3D' - 'A4 3D A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3C A4 00 3B' - 'A4 00 00 00 00 00 A4 A4 15 79 92 8C 8F 75 21 29' - '36 41 46 4A 51 3B 3B A4 68 A4 A4 A4 A4 A4 3D A4' - '3D A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 3D A4 00 3B' - '3B A4 00 00 00 00 A4 A4 14 79 94 8E 8F 79 2C 32' - '39 40 45 4A 51 3B 3B A4 A4 68 A4 A4 A4 A4 A4 3D' - 'A4 A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 3D A4 3C' - '3B A4 00 00 00 00 A4 A4 14 79 96 8F 90 7E 2F 30' - '38 40 45 4A 51 3C 3C 3C 3C 4E 68 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 68 3C' - '3C A4 00 A4 00 00 A4 A4 13 79 97 91 93 7E 2D 2E' - '35 3E 43 49 4E 4E 3C 3C 4E 4E 4E 68 A4 A4 A4 A4' - 'A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 A4' - '3C A4 00 3B A4 00 A4 A4 13 7A 9A 93 92 87 55 55' - '58 5A 5B 5D 5E 61 61 62 65 3B 3B A4 68 A4 A4 A4' - 'A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4' - '3D A4 A4 3B 3B A4 A4 A4 12 7B 9B 93 93 92 95 93' - '91 90 8E 8C 8A 89 87 86 83 3B 3B A4 A4 68 A4 A4' - 'A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4' - 'A4 3D A4 3C 3B A4 A4 A4 12 7B 9F A0 9E 9E 9E 9D' - '9D 9C 9C 9B 9B 9B 9A 9A 99 3C 3C 3C 3C 99 68 A4' - 'A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D' - 'A4 A4 68 3C 3C A4 A4 A4 11 7E A3 91 89 8A 8A 88' - '87 87 87 87 87 88 88 88 88 88 3C 3C 81 81 81 68' - 'A4 A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 A4 A4 A4 A4' - '3D A4 A4 A4 3C A4 A4 A4 11 86 A0 81 6C 63 67 80' - '82 81 81 81 81 81 81 81 81 81 81 81 81 3B 3B A4' - '68 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 A4 A4 A4' - 'A4 3D A4 A4 3D A4 A4 A4 0D 82 9B 6E 57 5F 5B 6B' - '82 80 80 80 80 80 7F 7F 7F 7F 7F 7F 7F 3B 3B A4' - 'A4 68 A4 A4 A4 A4 A4 A4 A4 A4 3D 3D 3D A4 A4 A4' - 'A4 A4 3D A4 3D A4 A4 A4 03 6A 9E 64 5C 6B 58 63' - '80 7D 7D 7D 7C 7B 7B 7D 7F 80 80 7F 7D 3C 3C 3C' - '3C 7F 68 A4 A4 A4 A4 A4 A4 3D A4 3D A4 3D A4 A4' - 'A4 A4 A4 3D 68 A4 00 A4 A4 53 9C 77 6D 7A 67 71' - '7B 7A 78 7B 85 89 8B 8E 92 95 95 93 8F 8F 3C 3C' - '8F 8F 7F 68 A4 A4 A4 A4 A4 3D 3D A4 3D 3D A4 A4' - 'A4 A4 A4 68 A4 A4 00 A4 A4 39 97 79 77 73 77 79' - '76 77 87 98 94 89 86 85 84 83 83 84 85 86 89 94' - '99 3B 3B A4 68 A4 A4 A4 A4 3D A4 3D A4 3D A4 A4' - 'A4 A4 68 A4 A4 00 00 A4 A4 27 91 78 75 75 75 72' - '7E 95 8E 84 7C 7D 7E 7E 7E 7E 7E 7E 7E 7E 7D 7D' - '83 3B 3B A4 A4 68 A4 A4 A4 A4 3D 3D 3D A4 A4 A4' - 'A4 68 A4 A4 00 00 00 A4 A4 1F 7F 7A 72 73 72 7C' - '91 84 78 79 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A' - '79 3C 3C 3C 3C 4C 68 A4 A4 A4 A4 A4 A4 A4 A4 A4' - '68 A4 A4 00 00 00 00 A4 A4 10 5F 83 72 73 76 8C' - '7C 77 79 78 78 78 78 77 75 76 76 76 76 76 76 76' - '76 76 3C 3C 77 77 4C 68 A4 A4 A4 A4 A4 A4 A4 68' - 'A4 A4 00 00 00 00 00 A4 A4 05 50 85 74 75 83 7E' - '76 78 78 78 78 78 78 77 74 71 72 72 72 72 72 72' - '72 72 72 70 77 3B 3B A4 68 A4 A4 A4 A4 A4 68 A4' - 'A4 00 00 00 00 00 00 00 A4 A4 3F 85 77 79 83 79' - '78 78 78 78 78 78 78 78 77 71 6D 6E 6E 6E 6E 6E' - '6E 6E 6E 6E 6F 3B 3B A4 A4 68 A4 A4 A4 68 A4 A4' - '00 00 00 00 00 00 00 00 A4 A4 29 84 79 7A 7C 79' - '79 79 79 79 79 79 79 79 79 78 70 6B 6B 6B 6C 6C' - '6C 6C 6C 6C 6C 3C 3C 3C 3C 07 68 A4 68 A4 A4 00' - '00 00 00 00 00 00 00 00 A4 A4 20 80 7C 7A 78 7B' - '7B 7B 7B 7B 7B 7B 7B 7B 7B 7B 7B 75 6F 6C 6A 69' - '68 69 69 69 6A 6A 3C 3C 4C 07 A4 68 A4 A4 00 00' - '00 00 00 00 00 00 00 00 A4 A4 17 74 7E 7D 74 7D' - '7E 7E 7E 7E 7E 7E 7E 7E 7E 7E 7E 7F 7E 7D 7B 77' - '74 71 6E 6C 6A 5D 65 78 4C 07 A4 A4 00 00 00 00' - '00 00 00 00 00 00 00 00 A4 A4 0A 5B 83 83 78 7A' - '83 81 82 82 82 82 82 82 82 82 82 82 82 82 82 83' - '83 82 81 81 77 6D 74 72 37 02 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 A4 A4 06 4A 84 87 84 76' - '7E 86 85 85 85 85 85 85 85 85 85 85 85 85 85 85' - '85 85 86 80 76 85 84 6E 25 A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 34 7B 8A 89 86' - '76 7F 89 8A 88 88 88 88 88 88 88 88 88 88 88 88' - '89 89 81 75 82 8B 81 63 1B A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 24 71 8D 8B 8C' - '89 7F 7A 82 8C 8D 8C 8C 8C 8C 8C 8C 8C 8C 8D 8D' - '84 7A 7E 88 8C 8E 7E 56 0E A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 1A 65 8E 8E 8E' - '8F 8F 87 7A 7B 86 8B 8B 8C 8C 8C 8C 8B 8B 86 7C' - '79 85 8F 8F 8E 90 7C 4D 08 A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 0C 58 8C 95 8F' - '8E 94 93 92 8C 88 87 87 85 84 84 85 87 87 87 8A' - '91 94 92 8D 93 93 7E 43 A4 A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 A4 A4 06 4C 8C 87 65' - '69 7E 94 95 95 96 96 95 94 93 93 94 95 96 96 95' - '96 8C 6A 66 79 94 7C 33 A4 A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 44 88 6C 5C' - '60 5C 93 99 98 98 98 98 98 98 98 98 98 98 98 98' - '9B 7D 5B 5E 5F 93 75 2A A4 A4 A4 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 2B 76 85 84' - '7D 8C A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' - 'A2 9A 87 80 84 7F 5B 19 A4 A4 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 0B 3D 66 7B' - '7F 83 80 80 80 80 80 80 80 80 80 80 80 80 80 80' - '80 81 81 7F 75 5B 28 04 A4 A4 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 A4 A4 A4 09 1D 23' - '22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22' - '22 22 22 23 23 18 02 A4 A4 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 A4 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4' - 'A4 A4 A4 A4 A4 A4 A4 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF 0F FF FF 00 00 FF FF' - 'FE 00 FF FF 00 00 FF FF FC 00 FF FF 00 00 FF FF' - 'F8 00 BF FF 00 00 FF FF F0 00 9F FF 00 00 FF FF' - 'E0 00 9F FF 00 00 FF FF E0 00 8F FF 00 00 F0 00' - '00 00 0F FF 00 00 C0 00 00 00 09 FF 00 00 80 00' - '00 00 08 FF 00 00 80 00 00 00 00 FF 00 00 00 00' - '00 00 00 BF 00 00 00 00 00 00 00 9F 00 00 00 00' - '00 00 00 8F 00 00 00 00 00 00 00 0F 00 00 00 00' - '00 00 00 0B 00 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 01 00 00 80 00 00 00 00 03 00 00 80 00' - '00 00 00 07 00 00 80 00 00 00 00 0F 00 00 80 00' - '00 00 00 1F 00 00 C0 00 00 00 00 3F 00 00 C0 00' - '00 00 00 7F 00 00 C0 00 00 00 00 FF 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' - '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' - '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 08 80 06 60 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 88 0E 60 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 08 00 80 7E E0 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 80 00 E0 06 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '08 00 08 08 00 80 06 60 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 80 00 80 00 80 08 0E 60' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08' - '00 08 00 00 08 00 7E E0 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 80 00 80 00 00 00 80 00 E0' - '06 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00' - '08 00 00 80 00 08 00 80 06 60 00 00 00 00 00 00' - '87 77 77 77 77 77 78 00 80 00 08 08 00 00 80 08' - '0E 60 00 00 00 00 00 08 FF F7 88 88 77 77 78 08' - '00 00 80 80 80 00 08 00 7E E0 00 00 00 00 00 07' - 'FF F7 00 88 88 87 78 80 00 08 08 08 00 00 00 80' - '00 E0 06 00 00 00 00 07 FF F7 88 88 88 76 60 70' - '00 00 80 80 00 00 00 08 00 80 06 60 00 00 00 07' - 'FF F7 88 88 88 76 60 07 00 00 08 00 00 80 00 00' - '80 08 0E 60 00 00 00 07 FF F7 88 88 88 7E EE E8' - '70 00 00 00 00 08 00 00 08 00 7E E0 00 00 00 07' - 'FF F7 88 88 88 88 EE 88 87 00 00 00 80 00 80 00' - '00 80 00 E0 06 00 00 07 FF F7 77 77 77 77 77 76' - '60 70 00 00 08 00 08 00 00 08 00 80 06 60 00 07' - 'FF FF FF FF FF FF 77 76 60 07 00 00 00 80 00 80' - '00 00 80 08 0E 60 00 07 FF FF FF FF FF FF FF FE' - 'EE EF 70 00 00 08 00 08 00 00 08 00 7E E0 00 07' - 'FF FF FF 77 77 7F FF FF EE 77 77 00 00 00 80 00' - '00 00 00 80 00 E0 00 07 77 77 F7 77 77 77 77 77' - '77 76 60 70 00 00 08 00 00 00 00 08 00 80 00 07' - '77 77 F7 77 77 77 77 77 77 76 60 07 00 00 00 00' - '88 80 00 00 80 80 00 07 77 7F F7 77 77 77 77 77' - '77 7E EE E7 70 00 00 08 08 08 00 00 08 70 00 07' - 'FF FF 77 77 77 7F FF FF FF FF EE FF 77 00 00 08' - '80 88 00 00 07 00 00 08 77 77 77 77 7F FF 77 77' - '77 77 FF F6 60 70 00 08 08 08 00 00 70 00 00 08' - '77 77 77 7F F7 77 77 77 77 77 77 76 60 07 00 00' - '88 80 00 07 00 00 00 00 77 77 77 F7 77 77 77 77' - '77 77 77 7E EE E8 70 00 00 00 00 70 00 00 00 00' - '77 77 7F 77 77 77 77 77 77 77 77 77 EE 77 87 00' - '00 00 07 00 00 00 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 77 76 60 70 00 00 70 00 00 00 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 77 76 60 07' - '00 07 00 00 00 00 00 00 87 77 77 77 77 77 77 77' - '77 77 77 77 77 7E EE E0 70 70 00 00 00 00 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 77 77 EE 80' - '07 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' - '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' - '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' - '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' - '00 77 77 77 77 77 77 77 77 77 77 77 77 77 78 00' - '00 00 00 00 00 00 00 00 00 7F FF FF F7 77 77 77' - '77 77 77 7F FF FF 78 00 00 00 00 00 00 00 00 00' - '00 8F 77 77 F7 77 77 77 77 77 77 FF 77 7F 78 00' - '00 00 00 00 00 00 00 00 00 8F 77 77 F7 77 77 77' - '77 77 77 F7 77 7F 78 00 00 00 00 00 00 00 00 00' - '00 87 77 7F F7 77 77 77 77 77 77 FF 77 77 70 00' - '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' - '77 77 77 77 77 77 80 00 00 00 00 00 00 00 00 00' - '00 00 08 88 88 88 88 88 88 88 88 88 88 80 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF 01 FF FF 00 00 FF FF FE 00 FF FF 00 00 FF FF' - 'FC 00 FF FF 00 00 FF FF F8 00 BF FF 00 00 FF FF' - 'F0 00 9F FF 00 00 FF FF F0 00 8F FF 00 00 FF FF' - 'E0 00 8F FF 00 00 F0 00 00 00 0F FF 00 00 C0 00' - '00 00 09 FF 00 00 80 00 00 00 08 FF 00 00 80 00' - '00 00 00 FF 00 00 00 00 00 00 00 BF 00 00 00 00' - '00 00 00 9F 00 00 00 00 00 00 00 8F 00 00 00 00' - '00 00 00 0F 00 00 00 00 00 00 00 0B 00 00 00 00' - '00 00 00 09 00 00 00 00 00 00 00 08 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' - '00 00 00 00 00 00 80 00 00 00 00 01 00 00 80 00' - '00 00 00 03 00 00 80 00 00 00 00 07 00 00 80 00' - '00 00 00 0F 00 00 80 00 00 00 00 1F 00 00 C0 00' - '00 00 00 3F 00 00 C0 00 00 00 00 7F 00 00 C0 00' - '00 00 00 FF 00 00 C0 00 00 00 03 FF 00 00 C0 00' - '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' - '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 00 00' - '00 78 00 00 00 78 00 00 00 3C 00 00 00 30 00 00' - '00 6C 00 00 00 6C 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 3C 80 80 80 FF 80 80' - '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3C 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' - '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 3C 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' - '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' - 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' - '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 3E 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3E 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 00 00 FF FF FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 16 00 00 00 34 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 3E 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 05 00 00 00 69 00 00 00 C5 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 30 00 80 80 FF 00 00' - '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' - '00 9B 00 00 00 FF 00 00 00 FF 21 21 21 FF 2C 2C' - '2C FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' - '2B FF 2B 2B 2B FF 2B 2B 2B FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 90 00 00 00 30 00 80 80 FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 54 00 00' - '00 FF 26 26 26 FF 90 90 90 FF CA CA CA FF CD CD' - 'CD FF CB CB CB FF CE CE CE FF CD CD CD FF CC CC' - 'CC FF CB CB CB FF C9 C9 C9 FF C7 C7 C7 FF C6 C6' - 'C6 FF C5 C5 C5 FF C4 C4 C4 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 84 00 FF FF FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' - '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 03 00 00 00 AD 01 01' - '01 FF 8A 8A 8A FF EB EB EB FF E8 E8 E8 FF E7 E7' - 'E7 FF D5 D5 D5 FF 85 85 85 FF 88 88 88 FF 92 92' - '92 FF 98 98 98 FF A2 A2 A2 FF AD AD AD FF BA BA' - 'BA FF C0 C0 C0 FF C3 C3 C3 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' - '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 15 00 00 00 F0 19 19' - '19 FF C7 C7 C7 FF EC EC EC FF E2 E2 E2 FF E6 E6' - 'E6 FF CB CB CB FF 3B 3B 3B FF 3F 3F 3F FF 56 56' - '56 FF 72 72 72 FF 87 87 87 FF 92 92 92 FF 9D 9D' - '9D FF A5 A5 A5 FF A8 A8 A8 FF 80 80 80 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' - 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' - '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 30 00 00 00 FA 29 29' - '29 FF D1 D1 D1 FF EA EA EA FF E4 E4 E4 FF E7 E7' - 'E7 FF CD CD CD FF 47 47 47 FF 5F 5F 5F FF 79 79' - '79 FF 87 87 87 FF 8F 8F 8F FF 97 97 97 FF A0 A0' - 'A0 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 34 00 00 00 F9 28 28' - '28 FF D1 D1 D1 FF EC EC EC FF E6 E6 E6 FF E7 E7' - 'E7 FF D1 D1 D1 FF 68 68 68 FF 74 74 74 FF 7E 7E' - '7E FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' - 'A0 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' - '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' - '00 18 00 00 00 0C 00 00 00 33 00 00 00 F9 28 28' - '28 FF D1 D1 D1 FF EE EE EE FF E7 E7 E7 FF E8 E8' - 'E8 FF D6 D6 D6 FF 70 70 70 FF 71 71 71 FF 7D 7D' - '7D FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' - 'A0 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' - 'FF FF 9C 9C 9C FF C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' - '00 54 00 00 00 3C 00 00 00 33 00 00 00 F9 27 27' - '27 FF D1 D1 D1 FF EF EF EF FF E9 E9 E9 FF EB EB' - 'EB FF D6 D6 D6 FF 6A 6A 6A FF 6C 6C 6C FF 78 78' - '78 FF 81 81 81 FF 8A 8A 8A FF 93 93 93 FF 9C 9C' - '9C FF 9C 9C 9C FF 00 FF FF FF 00 FF FF FF 9C 9C' - '9C FF 9C 9C 9C FF 9C 9C 9C FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' - 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' - '00 84 00 00 00 78 00 00 00 33 00 00 00 F9 27 27' - '27 FF D2 D2 D2 FF F2 F2 F2 FF EB EB EB FF EA EA' - 'EA FF DF DF DF FF A7 A7 A7 FF A7 A7 A7 FF AB AB' - 'AB FF AE AE AE FF B0 B0 B0 FF B3 B3 B3 FF B6 B6' - 'B6 FF B9 B9 B9 FF B9 B9 B9 FF BA BA BA FF BD BD' - 'BD FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' - '80 FF 00 00 00 90 00 00 00 33 00 00 00 F9 26 26' - '26 FF D3 D3 D3 FF F3 F3 F3 FF EB EB EB FF EB EB' - 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF E9 E9' - 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' - 'E2 FF E1 E1 E1 FF DF DF DF FF DE DE DE FF DB DB' - 'DB FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' - '80 FF 00 00 00 90 00 00 00 33 00 00 00 F9 26 26' - '26 FF D3 D3 D3 FF F7 F7 F7 FF F8 F8 F8 FF F6 F6' - 'F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5' - 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3' - 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F1 F1' - 'F1 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' - 'FF FF F1 F1 F1 FF C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 33 00 00 00 F9 24 24' - '24 FF D6 D6 D6 FF FF FF FF FF E9 E9 E9 FF E1 E1' - 'E1 FF E2 E2 E2 FF E2 E2 E2 FF E0 E0 E0 FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' - 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF 00 FF FF FF 00 FF FF FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' - 'FF FF 00 00 00 90 00 00 00 34 00 00 00 FA 24 24' - '24 FF DE DE DE FF F8 F8 F8 FF D9 D9 D9 FF C4 C4' - 'C4 FF BB BB BB FF BF BF BF FF D8 D8 D8 FF DA DA' - 'DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' - 'D9 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 90 00 00 00 25 00 00 00 F7 1F 1F' - '1F FF DA DA DA FF F3 F3 F3 FF C6 C6 C6 FF A9 A9' - 'A9 FF B7 B7 B7 FF B0 B0 B0 FF C3 C3 C3 FF DA DA' - 'DA FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' - 'D7 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 78 00 00 00 07 00 00 00 D0 05 05' - '05 FF C2 C2 C2 FF F6 F6 F6 FF BC BC BC FF B2 B2' - 'B2 FF C3 C3 C3 FF AB AB AB FF BB BB BB FF D8 D8' - 'D8 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' - 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' - 'D7 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D5 D5' - 'D5 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' - 'FF FF D7 D7 D7 FF C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF C0 C0' - 'C0 FF 00 00 00 3C 00 00 00 00 00 00 00 9C 00 00' - '00 FF A4 A4 A4 FF F4 F4 F4 FF CF CF CF FF C5 C5' - 'C5 FF D2 D2 D2 FF BF BF BF FF C9 C9 C9 FF D3 D3' - 'D3 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF DD DD' - 'DD FF E1 E1 E1 FF E3 E3 E3 FF E6 E6 E6 FF EA EA' - 'EA FF ED ED ED FF ED ED ED FF EB EB EB FF E7 E7' - 'E7 FF E7 E7 E7 FF 00 FF FF FF 00 FF FF FF E7 E7' - 'E7 FF E7 E7 E7 FF D7 D7 D7 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 73 00 00' - '00 FF 7E 7E 7E FF EF EF EF FF D1 D1 D1 FF CF CF' - 'CF FF CB CB CB FF CF CF CF FF D1 D1 D1 FF CE CE' - 'CE FF CF CF CF FF DF DF DF FF F0 F0 F0 FF EC EC' - 'EC FF E1 E1 E1 FF DE DE DE FF DD DD DD FF DC DC' - 'DC FF DB DB DB FF DB DB DB FF DC DC DC FF DD DD' - 'DD FF DE DE DE FF E1 E1 E1 FF EC EC EC FF F1 F1' - 'F1 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 59 00 00' - '00 FF 59 59 59 FF E9 E9 E9 FF D0 D0 D0 FF CD CD' - 'CD FF CD CD CD FF CD CD CD FF CA CA CA FF D6 D6' - 'D6 FF ED ED ED FF E6 E6 E6 FF DC DC DC FF D4 D4' - 'D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D5 D5 D5 FF D5 D5 D5 FF DB DB' - 'DB FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 80 80 80 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' - '00 FE 40 40 40 FF D7 D7 D7 FF D2 D2 D2 FF CA CA' - 'CA FF CB CB CB FF CA CA CA FF D4 D4 D4 FF E9 E9' - 'E9 FF DC DC DC FF D0 D0 D0 FF D1 D1 D1 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' - 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' - 'D1 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' - 'FF FF 99 99 99 FF C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 25 00 00' - '00 F8 22 22 22 FF B7 B7 B7 FF DB DB DB FF CA CA' - 'CA FF CB CB CB FF CE CE CE FF E4 E4 E4 FF D4 D4' - 'D4 FF CF CF CF FF D1 D1 D1 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CD CD' - 'CD FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' - 'CE FF CE CE CE FF 00 FF FF FF 00 FF FF FF CF CF' - 'CF FF CF CF CF FF 99 99 99 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 E1 07 07 07 FF 9F 9F 9F FF DD DD DD FF CC CC' - 'CC FF CD CD CD FF DB DB DB FF D6 D6 D6 FF CE CE' - 'CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CC CC' - 'CC FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' - 'CA FF CA CA CA FF CA CA CA FF C8 C8 C8 FF CF CF' - 'CF FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 B2 00 00 00 FF 83 83 83 FF DD DD DD FF CF CF' - 'CF FF D1 D1 D1 FF DB DB DB FF D1 D1 D1 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' - 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' - 'CF FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' - 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C7 C7' - 'C7 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 80 00 00 00 FF 5F 5F 5F FF DC DC DC FF D1 D1' - 'D1 FF D2 D2 D2 FF D4 D4 D4 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D0 D0 D0 FF C8 C8 C8 FF C3 C3 C3 FF C3 C3' - 'C3 FF C3 C3 C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' - 'C4 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' - 'FF FF 09 09 09 FF C0 C0 C0 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 3D 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 4B 00 00 00 FE 41 41 41 FF D8 D8 D8 FF D4 D4' - 'D4 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' - 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CD CD CD FF C7 C7' - 'C7 FF C4 C4 C4 FF C2 C2 C2 FF C1 C1 C1 FF C0 C0' - 'C0 FF C1 C1 C1 FF C1 C1 C1 FF C1 C1 C1 FF C2 C2' - 'C2 FF C2 C2 C2 FF 00 FF FF FF 00 FF FF FF 99 99' - '99 FF 09 09 09 FF 00 00 00 CF C0 C0 C0 FF 00 00' - '00 40 00 00 00 0E 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1A 00 00 00 F2 2C 2C 2C FF CC CC CC FF D6 D6' - 'D6 FF D5 D5 D5 FF CC CC CC FF D5 D5 D5 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' - 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D6 D6' - 'D6 FF D5 D5 D5 FF D3 D3 D3 FF CF CF CF FF CC CC' - 'CC FF C9 C9 C9 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2' - 'C2 FF B3 B3 B3 FF BD BD BD FF D0 D0 D0 FF 99 99' - '99 FF 09 09 09 FF 00 00 00 CF 00 00 00 3E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 09 00 00 00 D8 18 18 18 FF B0 B0 B0 FF DB DB' - 'DB FF DB DB DB FF D0 D0 D0 FF D2 D2 D2 FF DB DB' - 'DB FF D9 D9 D9 FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' - 'DA FF DA DA DA FF DA DA DA FF DB DB DB FF DB DB' - 'DB FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF CF CF' - 'CF FF C5 C5 C5 FF CC CC CC FF CA CA CA FF 7A 7A' - '7A FF 02 02 02 FF 00 00 00 B8 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 02 00 00 00 BF 08 08 08 FF 97 97 97 FF DC DC' - 'DC FF DF DF DF FF DC DC DC FF CE CE CE FF D6 D6' - 'D6 FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' - 'DD FF DD DD DD FF DE DE DE FF D8 D8 D8 FF CE CE' - 'CE FF DD DD DD FF DC DC DC FF C6 C6 C6 FF 53 53' - '53 FF 00 00 00 FF 00 00 00 A0 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 A4 00 00 00 FF 77 77 77 FF D3 D3' - 'D3 FF E2 E2 E2 FF E1 E1 E1 FF DE DE DE FF CE CE' - 'CE FF D7 D7 D7 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' - 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' - 'E1 FF E1 E1 E1 FF D9 D9 D9 FF CD CD CD FF DA DA' - 'DA FF E3 E3 E3 FF D9 D9 D9 FF BB BB BB FF 39 39' - '39 FF 00 00 00 FF 00 00 00 7E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 89 00 00 00 FF 4B 4B 4B FF C9 C9' - 'C9 FF E5 E5 E5 FF E3 E3 E3 FF E4 E4 E4 FF E1 E1' - 'E1 FF D7 D7 D7 FF D2 D2 D2 FF DA DA DA FF E4 E4' - 'E4 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' - 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF DC DC' - 'DC FF D2 D2 D2 FF D6 D6 D6 FF E0 E0 E0 FF E4 E4' - 'E4 FF E6 E6 E6 FF D6 D6 D6 FF A8 A8 A8 FF 20 20' - '20 FF 00 00 00 FD 00 00 00 4E 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 62 00 00 00 FF 35 35 35 FF BD BD' - 'BD FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7' - 'E7 FF E7 E7 E7 FF DF DF DF FF D2 D2 D2 FF D3 D3' - 'D3 FF DE DE DE FF E3 E3 E3 FF E3 E3 E3 FF E4 E4' - 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3' - 'E3 FF E3 E3 E3 FF DE DE DE FF D4 D4 D4 FF D1 D1' - 'D1 FF DD DD DD FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' - 'E6 FF E8 E8 E8 FF D4 D4 D4 FF 9A 9A 9A FF 0B 0B' - '0B FF 00 00 00 ED 00 00 00 2C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2D 00 00 00 F9 1E 1E 1E FF AB AB' - 'AB FF E4 E4 E4 FF ED ED ED FF E7 E7 E7 FF E6 E6' - 'E6 FF EC EC EC FF EB EB EB FF EA EA EA FF E4 E4' - 'E4 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DD DD' - 'DD FF DC DC DC FF DC DC DC FF DD DD DD FF DF DF' - 'DF FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' - 'E9 FF EC EC EC FF EA EA EA FF E5 E5 E5 FF EB EB' - 'EB FF EB EB EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00' - '00 FF 00 00 00 C3 00 00 00 17 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 09 00 00 00 DD 08 08 08 FF 99 99' - '99 FF E4 E4 E4 FF DF DF DF FF BD BD BD FF C1 C1' - 'C1 FF D6 D6 D6 FF EC EC EC FF ED ED ED FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EC EC' - 'EC FF EB EB EB FF EB EB EB FF EC EC EC FF ED ED' - 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EE EE' - 'EE FF E4 E4 E4 FF C2 C2 C2 FF BE BE BE FF D1 D1' - 'D1 FF EC EC EC FF D4 D4 D4 FF 75 75 75 FF 00 00' - '00 FF 00 00 00 9C 00 00 00 06 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 AE 00 00 00 FF 8D 8D' - '8D FF E0 E0 E0 FF C4 C4 C4 FF B2 B2 B2 FF B8 B8' - 'B8 FF B2 B2 B2 FF EB EB EB FF F1 F1 F1 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' - 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' - 'F3 FF D5 D5 D5 FF B0 B0 B0 FF B6 B6 B6 FF B7 B7' - 'B7 FF EB EB EB FF CD CD CD FF 61 61 61 FF 00 00' - '00 FF 00 00 00 85 00 00 00 01 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 64 64' - '64 FF CE CE CE FF DD DD DD FF DC DC DC FF D5 D5' - 'D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' - 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' - 'FA FF F2 F2 F2 FF DF DF DF FF D8 D8 D8 FF DC DC' - 'DC FF D7 D7 D7 FF B0 B0 B0 FF 34 34 34 FF 00 00' - '00 FF 00 00 00 67 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 44 00 00 00 FF 19 19' - '19 FF 80 80 80 FF BE BE BE FF D3 D3 D3 FF D7 D7' - 'D7 FF DB DB DB FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' - 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D7 D7 D7 FF CD CD' - 'CD FF B0 B0 B0 FF 5D 5D 5D FF 06 06 06 FF 00 00' - '00 ED 00 00 00 2B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 02 00 00 00 9C 00 00' - '00 FF 0C 0C 0C FF 3D 3D 3D FF 49 49 49 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' - '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' - '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 FF 00 00' - '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' - '00 7F 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 5C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 2C 00 00 00 7E 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 70 00 00 00 1A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF 80 7F FF 00 00 FF FF' - 'FF 00 7F FF 00 00 FF FF FE 00 0F FF 00 00 FF FF' - 'FC 00 07 FF 00 00 FF FF F8 00 07 FF 00 00 FF FF' - 'F0 00 07 FF 00 00 FF FF E0 00 84 FF 00 00 F0 00' - '00 00 04 7F 00 00 C0 00 00 00 00 7F 00 00 80 00' - '00 00 00 7F 00 00 80 00 00 00 00 0F 00 00 00 00' - '00 00 00 07 00 00 00 00 00 00 00 07 00 00 00 00' - '00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' - '00 00 00 01 00 00 80 00 00 00 00 03 00 00 80 00' - '00 00 00 07 00 00 80 00 00 00 00 0F 00 00 80 00' - '00 00 00 1F 00 00 C0 00 00 00 00 3F 00 00 C0 00' - '00 00 00 7F 00 00 C0 00 00 00 00 FF 00 00 C0 00' - '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' - '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' - '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' - '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' - '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0C 00 00 00 3C 80 80 80 FF 80 80 80 FF 00 00' - '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 3C 80 80 80 FF 00 00 00 FF 80 80 80 FF 80 80' - '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' - '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 3C 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' - '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' - '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0C 00 00 00 3C 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' - '00 3C 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' - '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 24 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' - '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' - '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 0C 00 00 00 24 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' - '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 24 00 00 00 6C 80 80 80 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' - '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' - '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' - '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 FF' - 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' - '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' - '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' - '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' - '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' - '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' - 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' - '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' - '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' - 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' - '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 80 80 80 FF C0 C0 C0 FF 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' - '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' - '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' - 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' - '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' - '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' - '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' - 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' - 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' - '00 3C C0 C0 C0 FF 00 00 00 FF C0 C0 C0 FF 00 00' - '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' - '00 0C 00 00 00 00 C0 C0 C0 FF 00 00 00 18 00 00' - '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00' - '3F FF FE 00 07 FF FC 00 03 FF F8 00 03 FF F0 00' - '03 FF E0 00 00 7F C0 00 00 3F C0 00 00 3F C0 00' - '00 3F C0 00 00 07 00 00 00 03 00 00 00 03 00 00' - '00 03 00 00 00 00 00 00 00 00 80 00 00 00 F0 00' - '00 00 F0 00 00 00 F0 00 00 00 F8 00 00 00 FF 00' - '00 00 FF 00 00 00 FF 00 00 00 FF 80 00 00 FF F0' - '00 00 FF F0 00 01 FF F0 00 03 FF F8 00 07 FF FF' - '00 0F FF FF 00 1F FF FF 00 3F FF FF 84 7F' -} */ - - - -/* BINRES mycomputer.ico */ -15 ICON mycomputer.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 8E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 00' - '05 00 11 11 11 00 22 22 22 00 33 33 33 00 44 44' - '44 00 55 55 55 00 66 66 66 00 6F 6D 70 00 77 77' - '77 00 7F 7F 7F 00 99 33 00 00 CC 33 00 00 99 66' - '33 00 CC 66 00 00 CC 66 33 00 D0 60 38 00 CC 99' - '33 00 CC 99 66 00 FF 99 66 00 FF CC 66 00 88 88' - '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC 99' - '99 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 5E 00 60 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5E 00' - '00 00 00 00 00 00 03 00 00 00 66 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 C0 CE' - '0B 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 6D 79 63 6F 6D 70 75 74 65' - '72 2E 69 63 6F 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 22 22 22 22 01 01 01 02 02' - '02 03 04 03 22 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 0B 1B 1A 1A 1A 1A 19 19 19' - '19 18 0D 18 07 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 22 05 1E 21 20 1E 1E 1D 1D 1D 1B' - '1B 1B 19 1A 0D 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 22 06 20 21 20 20 20 20 1E 1E 1D' - '1D 1D 1A 1A 18 04 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 05 1D 21 21 21 20 20 20 1E 1E' - '1D 1D 1A 1B 0D 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 19 21 21 21 21 20 1E 1E 1E' - '1E 1D 1B 1D 09 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 22 06 1E 21 21 21 20 1A 1B 20' - '1E 1E 1D 19 05 22 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 22 08 20 21 21 21 1E 1E 20' - '20 20 1A 06 22 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 22 07 1B 21 21 21 21 21' - '1E 18 06 22 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 22 03 07 0A 1A 18 09' - '06 22 22 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 22 22 22 22 22 22 22 22 22 22 04 0C 08 22' - '22 22 22 22 22 22 22 22 22 22 00 00 00 00 00 00' - '00 22 06 19 1A 1A 1A 1A 1A 1A 1A 1A 1A 1D 1B 1A' - '19 19 19 19 19 19 19 19 0C 05 22 00 00 00 00 00' - '22 04 1B 21 21 21 21 21 21 21 20 20 20 1E 1E 1E' - '1E 1E 1E 1E 1E 1E 1D 1D 1E 0D 22 00 00 00 00 00' - '22 06 20 21 20 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E' - '1E 1E 1D 1D 1D 1D 1D 1D 1D 1A 04 00 00 00 00 00' - '22 06 20 21 1C 12 12 14 14 15 15 15 15 15 15 15' - '15 15 14 13 12 12 12 1B 1D 1A 04 00 00 00 00 00' - '22 06 20 21 1C 11 12 12 13 14 14 14 14 14 14 14' - '14 13 12 12 12 12 12 1B 1E 1A 04 00 00 00 00 00' - '22 06 20 21 1C 11 12 12 12 13 13 14 14 14 14 13' - '13 12 12 12 12 11 11 1B 1E 1A 04 00 00 00 00 00' - '22 06 20 21 1C 0F 12 12 12 12 12 12 12 12 12 12' - '12 12 12 12 12 11 11 1B 1E 1A 04 00 00 00 00 00' - '22 06 20 21 1C 0E 11 12 12 12 12 12 12 12 12 12' - '12 12 12 11 11 0E 0E 1B 1E 1A 04 00 00 00 00 00' - '22 06 20 21 15 0E 0E 11 11 12 12 12 12 12 12 12' - '12 12 11 0F 0E 0E 0E 1B 1E 1A 03 00 00 00 00 00' - '22 06 20 21 15 0E 0E 11 12 12 12 12 12 12 12 12' - '12 12 12 12 0E 0E 0E 1B 1E 1A 03 00 00 00 00 00' - '22 06 1E 21 15 0E 12 12 12 13 13 14 14 14 14 14' - '13 13 12 12 12 11 0E 1D 20 1A 02 00 00 00 00 00' - '22 06 1E 21 15 11 12 12 13 14 14 14 15 15 15 14' - '14 14 13 12 12 12 11 1B 20 1A 01 00 00 00 00 00' - '22 06 1E 21 15 12 12 13 14 14 15 15 15 15 15 15' - '15 14 14 13 12 12 12 1D 20 1A 01 00 00 00 00 00' - '22 06 1E 21 15 12 13 14 14 15 15 16 16 16 16 16' - '15 15 14 14 13 12 12 1D 21 1A 22 00 00 00 00 00' - '22 06 1E 21 15 12 14 14 15 15 16 16 16 16 16 16' - '16 15 15 14 13 12 12 1F 21 1A 22 00 00 00 00 00' - '22 06 1E 21 15 12 15 15 15 15 15 16 17 17 17 16' - '15 15 15 15 15 12 10 1F 21 1A 22 00 00 00 00 00' - '22 05 1E 21 20 1E 20 20 20 20 20 20 20 20 20 20' - '20 20 20 20 20 1E 1E 21 21 1A 22 00 00 00 00 00' - '22 22 18 21 21 21 21 21 21 21 21 21 21 21 21 21' - '21 21 21 21 21 21 21 21 20 09 22 00 00 00 00 00' - '00 22 05 09 0C 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B' - '0B 0B 0B 0B 0B 0B 0B 0B 08 02 22 00 00 00 00 00' - '00 00 22 22 22 22 22 22 22 22 22 22 22 22 22 22' - '22 22 22 22 22 22 22 22 22 22 00 00 00 00 FF FF' - 'FF FF FF 00 00 FF FF 00 00 FF FE 00 00 FF FE 00' - '00 FF FF 00 00 FF FF 00 00 FF FF 00 00 FF FF 80' - '01 FF FF C0 03 FF FF E0 07 FF F0 00 00 0F E0 00' - '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' - '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' - '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' - '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' - '00 07 C0 00 00 07 E0 00 00 07 F0 00 00 0F 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 01 00 00 00 02 00' - '00 00 03 00 00 00 00 00 05 00 08 00 00 00 11 11' - '11 00 22 22 22 00 33 33 33 00 44 44 44 00 55 55' - '55 00 66 66 66 00 6F 6D 70 00 77 77 77 00 7F 7F' - '7F 00 99 33 00 00 CC 66 00 00 CC 66 33 00 D0 60' - '38 00 CC 66 66 00 CC 99 33 00 CC 99 66 00 FF 99' - '66 00 FF CC 66 00 88 88 88 00 99 99 99 00 AA AA' - 'AA 00 BB BB BB 00 CC 99 99 00 CC CC 99 00 FF CC' - '99 00 CC CC CC 00 DD DD DD 00 EE EE EE 00 FF FF' - 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 15 00 00 00 78 0A' - '38 00 00 00 38 00 B0 6C 38 00 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 96 00' - '00 00 96 00 00 00 09 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 5E 00' - '60 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 5E 00 00 00 00 00 00 00 03 00' - '00 00 66 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 C0 CE 0B 01 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6D' - '79 63 6F 6D 70 75 74 65 72 2E 69 63 6F 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 01 05 05 05 05 05' - '05 01 00 00 00 00 00 00 00 00 0A 1F 1B 1A 1A 19' - '18 08 00 00 00 00 00 00 00 00 0D 22 21 21 20 1F' - '1B 09 00 00 00 00 00 00 00 00 08 21 22 20 20 21' - '1B 07 00 00 00 00 00 00 00 00 00 0A 20 21 21 1B' - '08 00 00 00 00 00 00 00 02 04 04 23 06 0D 0B 06' - '23 05 05 02 00 00 00 03 19 1F 1F 1F 1B 1F 1B 1B' - '1B 1B 1B 0C 23 00 00 06 21 1E 1E 1E 1E 1E 1E 1D' - '1C 15 1D 1B 05 00 00 07 21 15 10 11 12 14 14 11' - '11 10 15 1B 05 00 00 07 21 15 10 11 11 11 11 11' - '11 0F 15 1B 05 00 00 06 21 11 0F 11 11 11 11 11' - '11 0F 15 1B 05 00 00 06 21 13 11 12 14 14 14 14' - '11 10 15 1B 05 00 00 06 20 15 11 14 15 16 15 15' - '14 11 15 1F 05 00 00 06 20 15 14 15 16 17 17 16' - '15 11 1C 1F 04 00 00 05 1F 22 21 21 21 21 21 21' - '21 21 22 1A 23 00 00 00 07 09 09 09 09 09 09 09' - '09 09 09 06 00 00 F0 0F 00 00 F0 0F 00 00 F0 0F' - '00 00 F0 0F 00 00 F8 1F 00 00 C0 03 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 C0 03 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 08 77 77 78 88 88 88 80 00 00 00 00 00 00' - '00 00 07 FF 77 77 77 77 87 80 00 00 00 00 00 00' - '00 00 0F FF FF FF 77 77 77 80 00 00 00 00 00 00' - '00 00 07 FF FF FF 77 77 77 80 00 00 00 00 00 00' - '00 00 08 FF FF FF 77 77 77 80 00 00 00 00 00 00' - '00 00 00 FF FF F7 7F F7 78 00 00 00 00 00 00 00' - '00 00 00 8F FF F7 7F FF 70 00 00 00 00 00 00 00' - '00 00 00 00 7F FF FF 78 00 00 00 00 00 00 00 00' - '00 00 00 00 00 87 88 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 08 80 00 00 00 00 00 00 00 00 00' - '08 77 77 77 77 77 77 88 88 88 88 80 00 00 00 00' - '7F FF FF FF FF FF 7F 77 77 77 77 78 00 00 00 00' - 'FF FF 77 77 77 77 77 77 77 77 77 77 00 00 00 00' - 'FF 73 33 88 87 77 77 88 83 33 37 77 00 00 00 00' - 'FF 73 33 33 88 88 88 83 33 33 37 77 00 00 00 00' - 'FF 73 33 33 33 88 33 33 33 33 37 77 00 00 00 00' - 'FF 73 33 33 33 33 33 33 33 33 37 77 00 00 00 00' - 'FF 83 33 33 33 33 33 33 33 33 37 77 00 00 00 00' - 'FF 83 33 33 33 33 33 33 33 33 37 77 00 00 00 00' - 'FF 83 33 33 33 33 33 33 33 33 37 F7 00 00 00 00' - 'FF 83 33 33 33 38 33 33 33 33 37 F7 00 00 00 00' - 'FF 83 33 33 88 88 88 83 33 33 37 F7 00 00 00 00' - '7F 83 33 88 88 87 88 88 83 33 37 F7 00 00 00 00' - '7F 83 38 88 77 77 77 78 88 33 37 F7 00 00 00 00' - '7F 83 38 88 77 77 77 78 88 33 37 F7 00 00 00 00' - '7F 83 88 87 77 77 77 77 88 83 37 F7 00 00 00 00' - '7F FF FF FF FF FF FF FF FF FF 7F F7 00 00 00 00' - '8F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' - '08 88 88 88 88 88 88 88 88 88 88 80 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00' - '00 FF FE 00 00 7F FE 00 00 7F FE 00 00 7F FE 00' - '00 7F FE 00 00 7F FE 00 00 7F FF 00 00 FF FF 00' - '00 FF FF 80 01 FF F0 00 00 0F E0 00 00 07 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 E0 00 00 07 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '87 77 78 80 00 00 00 00 8F FF 77 78 00 00 00 00' - '0F FF 7F 70 00 00 00 00 08 FF F7 80 00 00 00 00' - '00 08 80 00 00 00 00 87 77 77 77 77 78 00 00 F7' - '77 77 77 78 77 00 00 F8 33 88 83 33 87 00 00 F8' - '33 33 33 33 87 00 00 F3 33 33 33 33 87 00 00 F3' - '38 88 88 33 87 00 00 F8 38 88 88 83 87 00 00 F8' - '88 77 78 83 77 00 00 7F FF FF FF FF F7 00 00 08' - '88 88 88 88 80 00 E0 0F 00 00 E0 07 00 00 E0 07' - '00 00 E0 07 00 00 F0 0F 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 00' - '05 00 08 00 00 00 11 11 11 00 22 22 22 00 33 33' - '33 00 44 44 44 00 55 55 55 00 6D 65 5C 00 69 6E' - '65 00 6F 6D 70 00 77 77 77 00 7F 7F 7F 00 99 33' - '00 00 CC 33 00 00 99 66 33 00 98 69 38 00 CC 66' - '00 00 CC 66 33 00 D0 60 38 00 CC 99 33 00 CC 99' - '66 00 FF 99 66 00 FF CC 66 00 88 88 88 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF CC' - '99 00 CC CC CC 00 DD DD DD 00 EE EE EE 00 FF FF' - 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 5E 00 60 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5E 00' - '00 00 00 00 00 00 03 00 00 00 66 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 C0 CE' - '0B 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 6D 79 63 6F 6D 70 75 74 65' - '72 2E 69 63 6F 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 25 25 25 25 25' - '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' - '25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 25 25 25 25 25 25' - '25 25 25 25 01 01 01 01 01 02 02 03 04 04 03 25' - '25 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 07 1C 1E 1E 1D' - '1D 1D 1D 1D 1D 1D 1D 1C 1C 1C 1C 1B 1B 1B 1B 0A' - '03 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 0A 24 24 23 23' - '22 22 22 22 21 21 21 21 1E 1E 1E 1D 1C 1C 1C 1D' - '07 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 0F 24 24 23 23' - '22 22 22 22 21 21 21 21 1E 1E 1E 1E 1D 1C 1C 1D' - '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 1C 24 24 24 23' - '23 23 23 23 23 22 22 22 21 21 21 1E 1D 1D 1D 1E' - '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 1B 24 24 24 24' - '24 24 24 24 24 23 23 22 22 22 21 21 1E 1D 1D 1E' - '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 25 25 0B 24 24 24 23' - '23 23 22 22 22 22 22 21 21 21 1E 1E 1D 1D 1E 1E' - '07 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 25 08 23 24 24 24' - '24 24 24 23 23 23 23 22 22 22 22 21 1E 1E 1E 1C' - '06 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 25 04 1C 24 24 24' - '24 24 24 24 22 1E 21 22 23 22 22 21 21 1E 1E 09' - '25 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 25 25 06 21 24 24' - '24 24 24 24 1D 1C 1C 21 23 22 22 21 21 22 1B 25' - '25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 25 25 09 21 24' - '24 24 24 24 23 22 22 23 23 23 22 22 22 0E 06 25' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 25 25 08 1E' - '24 24 24 24 24 24 24 24 23 23 23 21 0E 05 25 25' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 25 25 05' - '0A 21 24 24 24 24 24 24 24 22 1C 08 25 25 25 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 25' - '25 06 09 0C 1B 1D 1D 0F 0A 08 04 25 25 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 04 0F 09 25 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 00 00 00 00 00 00 00 00 00' - '00 00 00 25 25 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 0A 1E 1B 07 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 25 25 00 00 00 00 00 00 00' - '00 00 25 25 04 0A 1D 1D 1D 1D 1D 1D 1D 1D 1D 1D' - '1D 1D 1D 1D 21 21 21 1E 1D 1D 1D 1D 1C 1C 1C 1C' - '1C 1C 1C 1C 1C 1C 08 25 25 00 00 00 00 00 00 00' - '00 00 25 25 0E 24 24 24 24 24 24 24 24 24 23 23' - '23 23 23 23 23 22 22 22 22 22 22 22 22 22 22 22' - '22 21 21 21 21 22 21 08 25 25 00 00 00 00 00 00' - '00 25 25 06 22 24 24 24 23 23 23 23 23 23 23 23' - '23 23 22 22 22 22 22 22 22 22 22 21 21 21 21 21' - '21 21 21 21 1E 1E 22 1D 25 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 23 23 23 23 23 23 23 23 23' - '23 23 23 23 23 23 22 22 22 22 22 22 22 22 22 22' - '22 22 21 22 21 1E 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 09 23 24 24 21 18 18 18 1F 1F 1F 20 20' - '20 20 20 20 20 20 20 20 20 20 20 20 1F 1F 1F 18' - '18 18 18 1F 22 21 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 14 15 15 15 15 16 17 17' - '17 17 17 18 18 18 17 17 17 17 17 16 15 15 15 15' - '15 14 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 14 15 15 15 15 16 17 17' - '17 17 17 18 18 18 18 17 17 17 17 16 15 15 15 15' - '15 15 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 14 15 15 15 15 15 16 16' - '17 17 17 17 17 17 17 17 17 16 16 15 15 15 15 15' - '15 15 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 14 15 15 15 15 15 15 15' - '16 16 16 17 17 17 16 16 16 15 15 15 15 15 15 15' - '15 14 10 15 22 21 21 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 11 14 15 15 15 15 15 15' - '15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15' - '14 14 10 15 22 21 22 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 14 14 15 15 15 15 15' - '15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 14' - '14 10 10 15 23 21 22 1D 04 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 11 14 14 15 15 15 15' - '15 15 15 15 15 15 15 15 15 15 15 15 15 14 14 14' - '10 10 10 15 23 21 22 1D 03 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 10 10 14 14 14 14 15' - '15 15 15 15 15 15 15 15 15 15 15 15 14 14 14 10' - '10 10 10 15 23 21 22 1D 03 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 10 10 10 14 14 15 15' - '15 15 15 15 15 15 15 15 15 15 15 15 15 14 14 10' - '10 10 10 15 23 22 22 1D 03 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 10 10 10 15 15 15 15' - '15 15 15 16 16 16 16 15 15 15 15 15 15 15 15 14' - '10 10 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 1F 10 10 14 15 15 15 15 15' - '16 16 16 17 17 17 17 17 16 16 16 15 15 15 15 15' - '15 10 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 18 10 14 15 15 15 15 16 16' - '17 17 17 17 17 17 17 17 17 17 17 16 15 15 15 15' - '15 15 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 18 10 15 15 15 16 16 17 17' - '17 17 18 18 18 18 18 18 17 17 17 17 16 16 15 15' - '15 15 15 15 23 22 22 1D 01 25 00 00 00 00 00 00' - '00 25 25 08 23 24 24 18 14 15 15 15 16 17 17 17' - '18 18 18 18 18 18 18 18 18 18 17 17 17 17 16 15' - '15 15 15 15 23 22 22 1D 01 25 00 00 00 00 00 00' - '00 25 25 08 22 24 24 18 15 15 15 16 17 17 17 18' - '18 18 18 18 19 19 18 18 18 18 18 18 17 17 17 16' - '15 15 15 15 23 22 23 1D 25 25 00 00 00 00 00 00' - '00 25 25 08 22 24 24 18 15 15 16 17 17 17 18 18' - '18 19 19 19 19 19 19 19 19 18 18 18 18 17 17 16' - '16 15 15 15 23 23 23 1D 25 25 00 00 00 00 00 00' - '00 25 25 08 22 24 24 18 14 16 16 17 17 18 18 18' - '19 19 19 19 19 19 19 19 19 19 18 18 18 17 17 17' - '16 15 15 15 23 24 24 1D 25 25 00 00 00 00 00 00' - '00 25 25 07 22 24 24 18 10 15 17 17 17 18 18 19' - '19 19 19 1A 1A 1A 1A 19 19 19 19 18 18 17 17 17' - '16 15 15 15 23 24 24 1D 25 25 00 00 00 00 00 00' - '00 25 25 07 22 24 24 1F 12 15 18 18 18 18 18 18' - '18 18 18 1A 1A 1A 1A 18 18 18 18 18 18 18 18 18' - '18 15 12 13 24 24 24 1D 25 25 00 00 00 00 00 00' - '00 25 25 07 22 24 24 23 23 23 23 23 23 23 23 23' - '23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 22' - '22 22 22 23 24 24 24 1D 25 25 00 00 00 00 00 00' - '00 25 25 06 21 24 24 24 24 24 24 24 24 24 24 24' - '24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24' - '24 24 24 24 24 24 24 0F 25 25 00 00 00 00 00 00' - '00 00 25 25 0A 22 24 24 24 24 24 24 24 24 24 24' - '24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24' - '24 24 24 24 24 24 1D 07 25 25 00 00 00 00 00 00' - '00 00 25 25 01 08 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F' - '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0E 0E 0E' - '0E 0E 0E 0E 0E 0A 06 25 25 00 00 00 00 00 00 00' - '00 00 00 25 25 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 25 25 00 00 00 00 00 00 00' - '00 00 00 00 00 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' - '25 25 25 25 25 25 25 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF F8 00 00 1F FF 00 00 FF F0' - '00 00 0F FF 00 00 FF E0 00 00 0F FF 00 00 FF E0' - '00 00 0F FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F0' - '00 00 0F FF 00 00 FF F0 00 00 1F FF 00 00 FF F8' - '00 00 3F FF 00 00 FF FC 00 00 3F FF 00 00 FF FE' - '00 00 7F FF 00 00 FF FF 00 01 FF FF 00 00 FE 00' - '00 00 00 7F 00 00 F8 00 00 00 00 1F 00 00 F0 00' - '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 1F 00 00 F8 00' - '00 00 00 1F 00 00 FE 00 00 00 00 7F 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' - '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 87 77 77 77 77 78 88 88 88 88 00' - '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' - '77 77 77 77 77 88 87 00 00 00 00 00 00 00 00 00' - '00 00 00 00 08 FF FF F7 77 77 77 77 77 78 87 00' - '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' - 'FF FF 77 77 77 77 77 80 00 00 00 00 00 00 00 00' - '00 00 00 00 08 FF FF FF FF FF FF 77 77 77 77 00' - '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' - 'F7 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 FF FF FF FF FF FF F7 77 77 78 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 8F FF FF' - 'FF 77 7F FF 77 77 78 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 07 FF FF FF 78 87 FF 77 77 80 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 7F FF' - 'FF F7 FF FF 77 78 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 07 FF FF FF FF FF F7 80 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87' - 'FF FF FF FF 80 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 08 87 78 80 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 08 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 87 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' - '77 77 77 77 77 77 77 78 88 78 00 00 00 00 00 00' - '00 8F FF FF FF FF FF FF FF FF FF FF F7 77 77 77' - '77 77 70 00 00 00 00 00 00 7F FF FF FF FF FF FF' - 'FF F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' - '00 FF FF FF FF FF FF FF FF FF FF FF F7 77 77 77' - '77 77 77 00 00 00 00 00 00 FF F7 87 77 77 77 77' - '77 77 77 77 77 77 77 78 87 F7 77 00 00 00 00 00' - '00 FF F7 33 33 33 38 88 88 88 88 88 33 33 33 33' - '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 38 88' - '88 88 88 88 83 33 33 33 33 F7 77 00 00 00 00 00' - '00 FF F7 33 33 33 33 38 88 88 88 83 33 33 33 33' - '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 33 33' - '33 33 33 33 33 33 33 33 33 F7 77 00 00 00 00 00' - '00 FF F7 33 33 33 33 33 33 33 33 33 33 33 33 33' - '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 33 33' - '33 33 33 33 33 33 33 33 13 F7 77 00 00 00 00 00' - '00 FF F7 13 33 33 33 33 33 33 33 33 33 33 33 33' - '13 F7 77 00 00 00 00 00 00 FF F7 13 33 33 33 33' - '33 33 33 33 33 33 33 31 13 F7 77 00 00 00 00 00' - '00 FF F8 11 33 33 33 33 33 33 33 33 33 33 33 11' - '13 F7 77 00 00 00 00 00 00 FF F8 11 13 33 33 33' - '33 33 33 33 33 33 33 11 13 F7 77 00 00 00 00 00' - '00 FF F8 11 33 33 33 33 38 88 83 33 33 33 33 33' - '13 F7 F7 00 00 00 00 00 00 FF F8 13 33 33 33 88' - '88 88 88 88 83 33 33 33 33 F7 F7 00 00 00 00 00' - '00 FF F8 33 33 33 88 88 88 88 88 88 88 33 33 33' - '33 F7 F7 00 00 00 00 00 00 FF F8 33 33 38 88 88' - '88 88 88 88 88 83 33 33 33 F7 F7 00 00 00 00 00' - '00 FF F8 33 33 88 88 88 88 77 78 88 88 88 33 33' - '38 FF F7 00 00 00 00 00 00 FF F8 33 38 88 88 87' - '77 77 77 78 88 88 83 33 38 FF F7 00 00 00 00 00' - '00 FF F8 33 38 88 88 77 77 77 77 77 88 88 88 33' - '33 FF F7 00 00 00 00 00 00 FF F8 33 38 88 87 77' - '77 77 77 77 78 88 83 33 33 FF F7 00 00 00 00 00' - '00 FF F8 38 88 88 87 77 77 77 77 77 78 88 88 88' - '38 FF F7 00 00 00 00 00 00 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF F7 00 00 00 00 00' - '00 7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF F8 00 00 00 00 00 00 8F FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00 00' - '00 00 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF F8' - '00 00 1F FF 00 00 FF F0 00 00 0F FF 00 00 FF E0' - '00 00 0F FF 00 00 FF E0 00 00 0F FF 00 00 FF E0' - '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF E0 00 00 0F FF 00 00 FF F0' - '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F0' - '00 00 1F FF 00 00 FF F8 00 00 3F FF 00 00 FF FC' - '00 00 3F FF 00 00 FF FE 00 00 7F FF 00 00 FF FF' - '00 01 FF FF 00 00 FE 00 00 00 00 7F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' - '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FE 00' - '00 00 00 7F 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 0C 00 00 00 2F 00 00 00 38 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 38 00 00 00 2A 00 00 00 0B 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 43 00 00 00 B0 00 00 00 F4 00 00 00 F8 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F8 00 00 00 DA 00 00 00 85 00 00 00 28 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00' - '00 E2 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 01 01 01 FF 01 01 01 FF 01 01' - '01 FF 01 01 01 FF 01 01 01 FF 02 02 02 FF 02 02' - '02 FF 03 03 03 FF 04 04 04 FF 04 04 04 FF 03 03' - '03 FF 00 00 00 FF 00 00 00 FF 00 00 00 AF 00 00' - '00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 65 00 00' - '00 FF 20 20 20 FF 9B 9B 9B FF B9 B9 B9 FF B5 B5' - 'B5 FF B2 B2 B2 FF B0 B0 B0 FF AE AE AE FF AB AB' - 'AB FF A9 A9 A9 FF A7 A7 A7 FF A4 A4 A4 FF A2 A2' - 'A2 FF 9F 9F 9F FF 9C 9C 9C FF 9B 9B 9B FF 96 96' - '96 FF 8C 8C 8C FF 86 86 86 FF 88 88 88 FF 8E 8E' - '8E FF 5A 5A 5A FF 03 03 03 FF 00 00 00 E9 00 00' - '00 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 A6 00 00' - '00 FF 59 59 59 FF FF FF FF FF FA FA FA FF F1 F1' - 'F1 FF EB EB EB FF E4 E4 E4 FF E0 E0 E0 FF DC DC' - 'DC FF D8 D8 D8 FF D4 D4 D4 FF D0 D0 D0 FF CB CB' - 'CB FF C7 C7 C7 FF C3 C3 C3 FF BF BF BF FF BB BB' - 'BB FF B0 B0 B0 FF 9E 9E 9E FF 97 97 97 FF 9E 9E' - '9E FF B0 B0 B0 FF 25 25 25 FF 00 00 00 FD 00 00' - '00 5A 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 C6 00 00' - '00 FF 82 82 82 FF FF FF FF FF F7 F7 F7 FF F1 F1' - 'F1 FF E9 E9 E9 FF E4 E4 E4 FF DF DF DF FF DA DA' - 'DA FF D6 D6 D6 FF D2 D2 D2 FF CE CE CE FF CA CA' - 'CA FF C7 C7 C7 FF C3 C3 C3 FF BF BF BF FF BB BB' - 'BB FF B8 B8 B8 FF A9 A9 A9 FF 9C 9C 9C FF 98 98' - '98 FF AF AF AF FF 3D 3D 3D FF 00 00 00 FF 00 00' - '00 7C 00 00 00 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 D4 00 00' - '00 FF 92 92 92 FF FF FF FF FF FF FF FF FF F9 F9' - 'F9 FF F6 F6 F6 FF F6 F6 F6 FF F3 F3 F3 FF EF EF' - 'EF FF EC EC EC FF E6 E6 E6 FF E1 E1 E1 FF DC DC' - 'DC FF D6 D6 D6 FF D1 D1 D1 FF CC CC CC FF C6 C6' - 'C6 FF C3 C3 C3 FF AF AF AF FF A5 A5 A5 FF A8 A8' - 'A8 FF B6 B6 B6 FF 44 44 44 FF 00 00 00 FF 00 00' - '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 B5 00 00' - '00 FF 84 84 84 FF FF FF FF FF FF FF FF FF F7 F7' - 'F7 FF FB FB FB FF FD FD FD FF FC FC FC FF FC FC' - 'FC FF FA FA FA FF F8 F8 F8 FF F1 F1 F1 FF EB EB' - 'EB FF E5 E5 E5 FF DF DF DF FF D9 D9 D9 FF D3 D3' - 'D3 FF CF CF CF FF B5 B5 B5 FF A3 A3 A3 FF AD AD' - 'AD FF BB BB BB FF 3D 3D 3D FF 00 00 00 FF 00 00' - '00 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 88 00 00' - '00 FF 5F 5F 5F FF FF FF FF FF FF FF FF FF FB FB' - 'FB FF EF EF EF FF EE EE EE FF E9 E9 E9 FF E3 E3' - 'E3 FF DF DF DF FF DD DD DD FF DA DA DA FF D5 D5' - 'D5 FF D0 D0 D0 FF CC CC CC FF C7 C7 C7 FF C3 C3' - 'C3 FF BE BE BE FF B0 B0 B0 FF B2 B2 B2 FF B4 B4' - 'B4 FF BA BA BA FF 28 28 28 FF 00 00 00 F7 00 00' - '00 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 34 00 00' - '00 FA 2E 2E 2E FF ED ED ED FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FA FA' - 'FA FF F5 F5 F5 FF F4 F4 F4 FF EF EF EF FF EB EB' - 'EB FF E5 E5 E5 FF E0 E0 E0 FF DC DC DC FF D8 D8' - 'D8 FF D2 D2 D2 FF C2 C2 C2 FF BA BA BA FF C1 C1' - 'C1 FF 97 97 97 FF 0A 0A 0A FF 00 00 00 D5 00 00' - '00 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00' - '00 C8 04 04 04 FF 97 97 97 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FD FD FD FF DF DF DF FF BE BE BE FF C4 C4' - 'C4 FF E4 E4 E4 FF E6 E6 E6 FF E1 E1 E1 FF DD DD' - 'DD FF D1 D1 D1 FF C5 C5 C5 FF C2 C2 C2 FF BF BF' - 'BF FF 43 43 43 FF 00 00 00 FF 00 00 00 9A 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 6C 00 00 00 FF 18 18 18 FF D1 D1 D1 FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FE FE FE FF B2 B2 B2 FF 9D 9D 9D FF 98 98' - '98 FF D1 D1 D1 FF ED ED ED FF E5 E5 E5 FF DF DF' - 'DF FF D1 D1 D1 FF CC CC CC FF D5 D5 D5 FF 84 84' - '84 FF 00 00 00 FF 00 00 00 E2 00 00 00 29 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 96 00 00 00 FF 3E 3E 3E FF D1 D1' - 'D1 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF ED ED ED FF DE DE DE FF E1 E1' - 'E1 FF EC EC EC FF EE EE EE FF E7 E7 E7 FF DC DC' - 'DC FF DC DC DC FF D7 D7 D7 FF 7B 7B 7B FF 14 14' - '14 FF 00 00 00 FF 00 00 00 5F 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1A 00 00 00 C6 00 00 00 FF 35 35' - '35 FF C3 C3 C3 FF F9 F9 F9 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FC FC FC FF FC FC' - 'FC FF F7 F7 F7 FF F0 F0 F0 FF EC EC EC FF EB EB' - 'EB FF CF CF CF FF 77 77 77 FF 07 07 07 FF 00 00' - '00 FD 00 00 00 8F 00 00 00 05 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 05 00 00 00 B6 00 00' - '00 FF 08 08 08 FF 58 58 58 FF CB CB CB FF FD FD' - 'FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF F9 F9 F9 FF E3 E3 E3 FF 9E 9E' - '9E FF 31 31 31 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00' - '00 0C 00 00 00 14 00 00 00 14 00 00 00 14 00 00' - '00 14 00 00 00 14 00 00 00 0E 00 00 00 1F 00 00' - '00 7B 00 00 00 E9 00 00 00 FF 10 10 10 FF 3E 3E' - '3E FF 69 69 69 FF 89 89 89 FF B1 B1 B1 FF A2 A2' - 'A2 FF 7E 7E 7E FF 57 57 57 FF 2C 2C 2C FF 04 04' - '04 FF 00 00 00 FF 00 00 00 BF 00 00 00 4F 00 00' - '00 14 00 00 00 11 00 00 00 14 00 00 00 14 00 00' - '00 14 00 00 00 14 00 00 00 14 00 00 00 0C 00 00' - '00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 04 00 00 00 4C 00 00 00 8A 00 00' - '00 AD 00 00 00 BB 00 00 00 B9 00 00 00 B9 00 00' - '00 B9 00 00 00 B9 00 00 00 B9 00 00 00 B5 00 00' - '00 AB 00 00 00 D1 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 04 04 04 FF 7E 7E 7E FF 4B 4B' - '4B FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 F1 00 00 00 BA 00 00 00 AF 00 00' - '00 B7 00 00 00 B9 00 00 00 B9 00 00 00 B9 00 00' - '00 B9 00 00 00 B9 00 00 00 B8 00 00 00 A5 00 00' - '00 85 00 00 00 43 00 00 00 0A 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 06 00 00 00 95 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 54 54 54 FF BD BD BD FF 8A 8A' - '8A FF 1B 1B 1B FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 F0 00 00 00 69 00 00 00 0D 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 7A 00 00 00 FF 04 04 04 FF 5A 5A 5A FF A7 A7' - 'A7 FF AD AD AD FF AB AB AB FF AA AA AA FF AA AA' - 'AA FF AA AA AA FF A9 A9 A9 FF A9 A9 A9 FF A8 A8' - 'A8 FF A8 A8 A8 FF A8 A8 A8 FF A7 A7 A7 FF A6 A6' - 'A6 FF A9 A9 A9 FF C5 C5 C5 FF D3 D3 D3 FF C6 C6' - 'C6 FF B4 B4 B4 FF A3 A3 A3 FF A3 A3 A3 FF A3 A3' - 'A3 FF A2 A2 A2 FF A1 A1 A1 FF A1 A1 A1 FF A1 A1' - 'A1 FF A0 A0 A0 FF A0 A0 A0 FF 9F 9F 9F FF 9F 9F' - '9F FF 9E 9E 9E FF A1 A1 A1 FF 94 94 94 FF 31 31' - '31 FF 00 00 00 FF 00 00 00 F6 00 00 00 5C 00 00' - '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 28 00 00' - '00 EA 00 00 00 FF 78 78 78 FF FA FA FA FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FB FB' - 'FB FF FA FA FA FF F8 F8 F8 FF F7 F7 F7 FF F4 F4' - 'F4 FF F3 F3 F3 FF F2 F2 F2 FF F0 F0 F0 FF EF EF' - 'EF FF EC EC EC FF E6 E6 E6 FF E2 E2 E2 FF E2 E2' - 'E2 FF E3 E3 E3 FF E4 E4 E4 FF E2 E2 E2 FF E0 E0' - 'E0 FF DE DE DE FF DC DC DC FF DB DB DB FF D9 D9' - 'D9 FF D8 D8 D8 FF D6 D6 D6 FF D4 D4 D4 FF D3 D3' - 'D3 FF D0 D0 D0 FF CF CF CF FF DD DD DD FF CB CB' - 'CB FF 39 39 39 FF 00 00 00 FF 00 00 00 AF 00 00' - '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 78 00 00' - '00 FF 17 17 17 FF DF DF DF FF FF FF FF FF F7 F7' - 'F7 FF F6 F8 F8 FF F5 F6 F8 FF F3 F4 F5 FF F1 F3' - 'F4 FF EF F0 F2 FF ED EF F0 FF EC ED EE FF E9 EA' - 'EB FF E8 E9 EA FF E6 E7 E9 FF E4 E6 E7 FF E2 E3' - 'E4 FF E0 E1 E3 FF DF E0 E1 FF DD DE DF FF DB DC' - 'DD FF D9 DB DC FF D8 D8 D9 FF D6 D7 D8 FF D4 D5' - 'D7 FF D2 D4 D4 FF D0 D1 D3 FF CE D0 D1 FF CD CE' - 'CF FF CB CD CE FF CA CB CD FF C7 C9 CA FF C6 C8' - 'C9 FF C4 C6 C7 FF C2 C3 C3 FF C0 C0 C0 FF D9 D9' - 'D9 FF A4 A4 A4 FF 00 00 00 FF 00 00 00 EE 00 00' - '00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 39 39 39 FF F0 F0 F0 FF FF FF FF FF F9 F9' - 'F9 FF F6 F0 EB FF F5 EF EA FF F5 EE EA FF F3 EE' - 'E9 FF F3 ED E9 FF F2 EC E8 FF F2 EC E8 FF F0 EC' - 'E6 FF F0 EB E6 FF F0 EA E6 FF EF EA E4 FF ED E8' - 'E4 FF ED E8 E3 FF EC E7 E2 FF EB E6 E1 FF E9 E5' - 'E0 FF E8 E4 DF FF E7 E2 DD FF E6 E1 DC FF E5 DF' - 'DB FF E3 DE D9 FF E2 DD D8 FF E1 DB D6 FF DF DA' - 'D4 FF DE D8 D3 FF DD D7 D2 FF DB D5 D0 FF D9 D3' - 'CE FF DB D5 D2 FF D3 D2 D2 FF C3 C3 C3 FF CB CB' - 'CB FF AE AE AE FF 05 05 05 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 3C 3C 3C FF F1 F1 F1 FF FF FF FF FF FB FF' - 'FF FF E2 CA B9 FF D8 9B 70 FF DC A2 79 FF DE A7' - '7D FF E1 AA 81 FF E3 AF 85 FF E5 B2 88 FF E8 B6' - '8C FF E9 B9 8E FF EB BB 91 FF ED BE 94 FF EE C0' - '95 FF EF C1 96 FF EF C2 97 FF EF C2 97 FF EE C1' - '97 FF EE C0 95 FF EC BE 93 FF EB BB 90 FF E9 B8' - '8E FF E7 B5 8B FF E5 B1 87 FF E3 AE 84 FF E1 AA' - '81 FF DF A6 7D FF DC A2 79 FF D9 9E 75 FF D6 97' - '6E FF E0 AB 8B FF E5 E3 E2 FF C4 C5 C6 FF CC CC' - 'CC FF AB AB AB FF 06 06 06 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 3A 3A 3A FF F1 F1 F1 FF FF FF FF FF FD FF' - 'FF FF D0 A9 90 FF BC 56 11 FF C3 63 1F FF C6 69' - '26 FF CA 70 2C FF CD 76 32 FF D1 7B 37 FF D4 81' - '3D FF D7 86 41 FF D9 89 44 FF DC 8D 48 FF DD 90' - '4A FF DF 92 4D FF DF 93 4D FF DF 93 4D FF DE 91' - '4C FF DD 90 4A FF DB 8C 46 FF D8 88 43 FF D6 83' - '3F FF D3 7E 3A FF D0 78 34 FF CC 73 2F FF C8 6D' - '2A FF C5 67 24 FF C1 61 1E FF BD 5A 17 FF B6 4E' - '0A FF C4 6F 38 FF E5 E2 E0 FF C7 C8 C9 FF CF CF' - 'CF FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 39 39 39 FF F0 F0 F0 FF FF FF FF FF FF FF' - 'FF FF D1 AC 94 FF BC 5A 19 FF C2 66 26 FF C6 6C' - '2C FF CA 72 32 FF CD 77 37 FF D0 7C 3C FF D3 81' - '40 FF D5 85 44 FF D7 88 47 FF D9 8C 4A FF DA 8E' - '4C FF DC 8F 4D FF DC 90 4E FF DC 90 4E FF DB 8F' - '4D FF DA 8D 4B FF D9 8A 49 FF D6 87 46 FF D4 83' - '42 FF D1 7F 3E FF CE 7A 39 FF CB 75 34 FF C8 70' - '30 FF C5 6A 2B FF C1 64 25 FF BD 5E 1F FF B7 53' - '12 FF C6 73 3F FF E6 E3 E1 FF C8 C9 CA FF D0 D0' - 'D0 FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' - 'FF FF D1 AB 92 FF B9 55 14 FF BF 61 22 FF C3 67' - '28 FF C6 6D 2D FF CA 71 31 FF CC 76 36 FF CF 7B' - '3A FF D1 7E 3D FF D3 81 40 FF D5 85 44 FF D6 87' - '45 FF D7 88 47 FF D7 89 47 FF D7 89 47 FF D7 87' - '47 FF D6 86 45 FF D4 83 42 FF D2 80 3F FF D0 7D' - '3C FF CE 79 38 FF CB 74 34 FF C8 6F 2F FF C5 6A' - '2B FF C2 65 26 FF BE 60 21 FF BA 5A 1B FF B4 4E' - '0F FF C4 70 3C FF E6 E3 E2 FF CA CB CC FF D2 D2' - 'D2 FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' - 'FF FF D0 A9 91 FF B7 51 10 FF BD 5C 1D FF C0 62' - '23 FF C3 67 28 FF C6 6C 2C FF C9 71 30 FF CB 75' - '34 FF CE 78 37 FF CF 7B 3A FF D0 7E 3D FF D1 7F' - '3E FF D2 81 40 FF D3 81 40 FF D2 81 40 FF D2 80' - '3F FF D1 7F 3E FF D0 7C 3C FF CE 79 39 FF CD 76' - '36 FF CA 73 32 FF C7 6E 2E FF C5 6A 2A FF C2 66' - '26 FF BF 60 21 FF BC 5B 1C FF B8 55 17 FF B2 4A' - '0A FF C2 6C 39 FF E7 E4 E3 FF CC CD CE FF D4 D4' - 'D4 FF AB AB AB FF 04 04 04 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 36 36 36 FF EF EF EF FF FF FF FF FF FF FF' - 'FF FF CE A7 8F FF B3 4C 0B FF B9 58 18 FF BC 5D' - '1E FF C0 62 23 FF C3 66 27 FF C5 6A 2B FF C7 6E' - '2E FF C9 71 31 FF CB 74 33 FF CC 76 36 FF CD 78' - '37 FF CE 79 39 FF CE 79 39 FF CE 79 39 FF CE 79' - '38 FF CD 77 37 FF CC 75 35 FF CA 72 32 FF C8 70' - '30 FF C6 6C 2D FF C3 68 29 FF C1 64 25 FF BE 60' - '21 FF BC 5B 1C FF B8 56 18 FF B5 50 12 FF AF 45' - '05 FF BF 68 35 FF E8 E5 E3 FF CD CF D0 FF D6 D6' - 'D6 FF AB AB AB FF 04 04 04 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 36 36 36 FF EE EE EE FF FF FF FF FF FF FF' - 'FF FF CC A4 8C FF B0 46 06 FF B6 51 13 FF B9 57' - '18 FF BC 5B 1D FF BF 60 21 FF C1 64 24 FF C3 67' - '28 FF C5 6A 2B FF C6 6D 2D FF C8 6F 2F FF C9 70' - '30 FF C9 72 32 FF C9 72 32 FF C9 72 32 FF C9 72' - '31 FF C8 70 30 FF C7 6E 2E FF C6 6B 2C FF C4 69' - '2A FF C2 66 26 FF BF 62 22 FF BD 5E 1F FF BA 5A' - '1B FF B8 55 17 FF B5 50 12 FF B2 4B 0D FF AC 40' - '00 FF BC 64 31 FF E9 E5 E4 FF D0 D1 D2 FF D8 D8' - 'D8 FF AA AA AA FF 04 04 04 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 35 35 35 FF ED ED ED FF FF FF FF FF FF FF' - 'FF FF CA A0 88 FF AD 40 00 FF B3 4C 0E FF B5 51' - '13 FF B8 56 17 FF BB 5A 1B FF BD 5D 1E FF BF 61' - '21 FF C0 63 24 FF C1 65 25 FF C2 67 28 FF C3 69' - '29 FF C5 69 2A FF C5 6A 2A FF C5 6A 2A FF C4 69' - '29 FF C4 68 28 FF C2 66 27 FF C0 64 24 FF BF 61' - '22 FF BE 5E 20 FF BC 5B 1D FF BA 58 19 FF B7 54' - '16 FF B5 50 12 FF B2 4B 0D FF AF 46 08 FF A8 3B' - '00 FF BB 62 30 FF EA E7 E5 FF D1 D3 D4 FF D9 D9' - 'D9 FF AA AA AA FF 03 03 03 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 34 34 34 FF EC EC EC FF FF FF FF FF FF FF' - 'FF FF C6 9D 85 FF A9 3A 00 FF AF 46 09 FF B2 4B' - '0E FF B4 4F 12 FF B6 53 15 FF B8 55 17 FF B9 58' - '19 FF BB 5C 1D FF BF 60 22 FF C2 66 27 FF C4 68' - '29 FF C5 6A 2A FF C5 6B 2B FF C5 6B 2B FF C5 6B' - '2B FF C5 69 2A FF C3 68 29 FF C1 65 26 FF BF 60' - '22 FF BB 59 1B FF B7 54 15 FF B4 4F 11 FF B3 4D' - '0F FF B1 4A 0C FF AE 45 08 FF AB 40 03 FF A6 38' - '00 FF BA 61 2F FF EA E7 E6 FF D3 D4 D5 FF DB DB' - 'DB FF A9 A9 A9 FF 03 03 03 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 33 33 33 FF EC EC EC FF FF FF FF FF FF FF' - 'FF FF C4 9A 83 FF A6 37 00 FF AC 40 03 FF AE 45' - '07 FF AF 47 0A FF B3 4D 0F FF B9 57 18 FF BE 5F' - '20 FF C4 68 29 FF C6 6D 2D FF C8 70 30 FF CA 72' - '31 FF CA 73 33 FF CB 74 33 FF CB 74 33 FF CB 73' - '33 FF CA 73 32 FF C9 71 31 FF C8 70 30 FF C7 6D' - '2D FF C4 69 2A FF BF 60 22 FF B8 56 18 FF B3 4D' - '0F FF AC 42 04 FF AA 3F 02 FF A9 3E 01 FF A6 38' - '00 FF BA 61 2F FF EB E8 E6 FF D5 D6 D7 FF DC DC' - 'DC FF A9 A9 A9 FF 03 03 03 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 32 32 32 FF EB EB EB FF FF FF FF FF FF FF' - 'FF FF C3 99 81 FF A6 37 00 FF A9 3D 00 FF A9 3D' - '00 FF B1 49 0C FF C0 63 24 FF C6 6D 2D FF C9 71' - '31 FF CA 74 33 FF CB 75 35 FF CD 78 37 FF CE 79' - '39 FF CF 7B 3A FF CF 7B 3B FF CF 7B 3B FF CF 7B' - '3A FF CE 7A 3A FF CD 79 38 FF CC 76 36 FF CB 74' - '34 FF C9 71 32 FF C7 6E 2F FF C6 6B 2B FF C2 66' - '27 FF B7 54 16 FF AA 40 03 FF A8 3C 00 FF A6 38' - '00 FF BA 61 2F FF EC E9 E7 FF D7 D9 D9 FF DF DF' - 'DF FF A8 A8 A8 FF 02 02 02 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 31 31 31 FF EA EA EA FF FF FF FF FF FF FF' - 'FF FF C2 98 80 FF A5 36 00 FF A8 3C 00 FF B7 55' - '17 FF C4 6A 2A FF C8 70 31 FF CA 73 33 FF CD 76' - '36 FF CE 79 39 FF D0 7C 3B FF D1 7F 3E FF D2 80' - '3F FF D3 82 41 FF D3 83 42 FF D3 83 42 FF D3 82' - '41 FF D3 81 40 FF D2 80 3F FF D0 7D 3C FF CF 7B' - '3A FF CD 78 37 FF CB 74 34 FF C9 71 30 FF C7 6E' - '2E FF C5 6A 2B FF BE 5F 20 FF B0 4A 0C FF A5 36' - '00 FF BA 61 2F FF EC E9 E8 FF D8 DA DA FF E0 E0' - 'E0 FF A7 A7 A7 FF 02 02 02 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 30 30 30 FF E9 E9 E9 FF FF FF FF FF FF FF' - 'FF FF C0 96 7E FF A6 37 00 FF B8 55 17 FF C7 6D' - '2E FF C9 71 31 FF CC 75 35 FF CD 79 39 FF D0 7D' - '3C FF D2 80 3F FF D3 83 42 FF D5 86 44 FF D7 87' - '46 FF D8 89 48 FF D8 8A 48 FF D8 8A 48 FF D8 89' - '48 FF D7 88 47 FF D6 87 45 FF D5 84 43 FF D3 82' - '41 FF D1 7E 3D FF CE 7A 3A FF CD 77 36 FF CA 73' - '33 FF C7 6E 2E FF C5 6B 2B FF C0 63 23 FF AD 41' - '02 FF BA 60 2E FF ED EA E9 FF DA DC DD FF E2 E2' - 'E2 FF A7 A7 A7 FF 02 02 02 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2F 2F 2F FF E8 E8 E8 FF FF FF FF FF FE FF' - 'FF FF BD 92 7B FF AF 45 05 FF C7 6D 2D FF C9 71' - '31 FF CC 76 35 FF CF 7A 3A FF D1 7E 3E FF D4 83' - '42 FF D6 86 46 FF D8 8A 48 FF DA 8D 4B FF DB 8F' - '4D FF DC 90 4E FF DC 91 50 FF DC 91 50 FF DC 91' - '4F FF DC 90 4E FF DA 8E 4C FF D9 8B 49 FF D7 88' - '47 FF D5 84 43 FF D2 80 3F FF D0 7C 3B FF CD 78' - '37 FF CB 73 32 FF C7 6E 2E FF C5 6A 2B FF BC 5B' - '1A FF BD 65 33 FF EE EA E9 FF DC DE DF FF E4 E4' - 'E4 FF A7 A7 A7 FF 01 01 01 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2E 2E 2E FF E7 E7 E7 FF FF FF FF FF FE FF' - 'FF FF BD 93 7B FF BA 57 17 FF C9 71 31 FF CB 74' - '34 FF CE 7A 3A FF D2 7F 3E FF D4 84 43 FF D7 88' - '47 FF DA 8C 4A FF DC 8F 4D FF DE 93 51 FF DF 96' - '54 FF E0 98 56 FF E1 99 56 FF E1 99 56 FF E1 99' - '56 FF E0 97 55 FF DE 94 53 FF DD 91 50 FF DB 8E' - '4C FF D8 8A 48 FF D5 85 44 FF D3 81 40 FF D0 7C' - '3C FF CD 77 37 FF C9 72 32 FF C6 6D 2D FF C2 62' - '21 FF C4 70 3D FF ED EA E8 FF DE DF E0 FF E5 E5' - 'E5 FF A6 A6 A6 FF 01 01 01 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2C 2C 2C FF E5 E5 E5 FF FF FF FF FF FD FF' - 'FF FF BE 96 7E FF C2 64 22 FF CB 74 33 FF CE 79' - '38 FF D1 7F 3E FF D5 84 43 FF D7 89 48 FF DA 8E' - '4C FF DE 92 50 FF E0 96 54 FF E2 9A 58 FF E3 9C' - '5A FF E5 9F 5C FF E6 A0 5D FF E6 A0 5D FF E5 A0' - '5D FF E4 9E 5B FF E3 9B 59 FF E1 98 56 FF DF 94' - '52 FF DC 90 4E FF D8 8B 49 FF D6 86 45 FF D3 81' - '40 FF D0 7C 3B FF CC 77 36 FF C9 70 30 FF C4 68' - '26 FF C8 76 43 FF EE EA E9 FF E1 E2 E3 FF E8 E8' - 'E8 FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2C 2C 2C FF E5 E5 E5 FF FF FF FF FF FD FF' - 'FF FF BC 94 7B FF C4 67 24 FF CD 77 37 FF D0 7C' - '3C FF D4 83 42 FF D7 88 47 FF DB 8D 4C FF DE 93' - '51 FF E1 97 56 FF E3 9C 59 FF E6 A0 5D FF E7 A3' - '60 FF E9 A6 63 FF EA A8 64 FF EA A8 64 FF E9 A7' - '64 FF E8 A5 62 FF E7 A2 5F FF E4 9E 5B FF E2 99' - '57 FF DF 95 53 FF DC 8F 4D FF D8 8A 49 FF D6 86' - '44 FF D2 80 3F FF CF 7A 3A FF CB 74 33 FF C6 6B' - '29 FF C7 76 43 FF F6 F2 F0 FF F4 F5 F6 FF F6 F6' - 'F6 FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2B 2B 2B FF E4 E4 E4 FF FF FF FF FF FD FF' - 'FF FF B7 8D 75 FF BC 5A 19 FF CF 7C 3B FF D2 80' - '3E FF D5 85 44 FF D9 8C 4A FF DD 91 4F FF E0 97' - '55 FF E3 9C 5A FF E6 A1 5E FF E9 A5 63 FF EB A9' - '66 FF ED AD 69 FF EF AF 6B FF EF AF 6C FF EE AF' - '6A FF ED AB 68 FF EA A7 65 FF E7 A3 61 FF E4 9E' - '5C FF E1 99 57 FF DE 93 52 FF DA 8E 4C FF D7 88' - '47 FF D4 82 41 FF D0 7C 3C FF CC 77 36 FF C7 6C' - '2A FF C3 6F 3D FF F7 F3 F2 FF F7 F9 FA FF FC FC' - 'FC FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2A 2A 2A FF E3 E3 E3 FF FF FF FF FF FD FF' - 'FF FF B4 88 70 FF AF 41 01 FF D0 78 34 FF D4 81' - '3E FF D8 87 43 FF DC 8D 49 FF E0 93 4F FF E3 9A' - '55 FF E7 A0 5B FF EB A5 60 FF EE AA 65 FF F1 AF' - '6A FF F3 B3 6E FF F5 B6 70 FF F5 B6 70 FF F4 B5' - '6F FF F2 B2 6C FF F0 AD 67 FF EC A7 62 FF E9 A2' - '5D FF E5 9C 58 FF E1 96 52 FF DE 90 4C FF DA 8A' - '46 FF D6 83 40 FF D2 7D 3A FF CF 78 35 FF C1 5F' - '1B FF BB 5F 2C FF F9 F5 F3 FF F9 FB FB FF FE FE' - 'FE FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 2A 2A 2A FF E3 E3 E3 FF FF FF FF FF FD FF' - 'FF FF B4 95 84 FF A0 4F 23 FF B6 71 43 FF CB 89' - '53 FF CE 8D 57 FF D1 92 5B FF D4 97 61 FF D7 9D' - '66 FF DA A2 6A FF DD A7 6E FF E0 AB 73 FF E4 B0' - '78 FF E6 B4 7B FF E7 B7 7F FF E8 B7 7F FF E6 B6' - '7D FF E5 B2 7A FF E2 AE 76 FF DE A9 71 FF DC A4' - '6C FF D9 9F 68 FF D5 99 63 FF D2 94 5D FF CF 8F' - '59 FF CC 8A 54 FF CA 85 4F FF C3 7E 4A FF A7 5A' - '2C FF B3 73 4F FF FA F8 F7 FF FC FD FD FF FF FF' - 'FF FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' - '00 FF 26 26 26 FF E1 E1 E1 FF FF FF FF FF FF FF' - 'FF FF EC EC ED FF E6 E6 E7 FF E6 E5 E6 FF E9 E7' - 'E5 FF E9 E7 E5 FF E9 E7 E5 FF E9 E7 E5 FF E9 E7' - 'E5 FF E9 E8 E6 FF E9 E8 E6 FF EA E8 E6 FF EA E8' - 'E6 FF EA E8 E6 FF EA E8 E6 FF EA E8 E6 FF EA E8' - 'E6 FF EA E8 E6 FF EA E8 E6 FF E9 E8 E6 FF E8 E7' - 'E5 FF E8 E6 E4 FF E8 E6 E4 FF E8 E6 E4 FF E8 E6' - 'E4 FF E7 E5 E3 FF E7 E5 E3 FF E6 E4 E3 FF E3 E3' - 'E3 FF E9 E9 E9 FF FC FC FC FF FD FD FD FF FF FF' - 'FF FF A4 A4 A4 FF 00 00 00 FF 00 00 00 F7 00 00' - '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 7D 00 00' - '00 FF 0D 0D 0D FF C4 C4 C4 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FE FE FE FF FF FF FF FF FB FB' - 'FB FF 7F 7F 7F FF 00 00 00 FF 00 00 00 F2 00 00' - '00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' - '00 FB 00 00 00 FF 56 56 56 FF E3 E3 E3 FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FD FD FD FF AF AF' - 'AF FF 21 21 21 FF 00 00 00 FF 00 00 00 B9 00 00' - '00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 8D 00 00 00 FF 01 01 01 FF 2F 2F 2F FF 6D 6D' - '6D FF 7D 7D 7D FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' - '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' - '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' - '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' - '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' - '7C FF 7C 7C 7C FF 7C 7C 7C FF 7B 7B 7B FF 7B 7B' - '7B FF 7B 7B 7B FF 7A 7A 7A FF 7A 7A 7A FF 7A 7A' - '7A FF 7A 7A 7A FF 77 77 77 FF 57 57 57 FF 18 18' - '18 FF 00 00 00 FF 00 00 00 FF 00 00 00 57 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 19 00 00 00 B9 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 F5 00 00 00 86 00 00 00 04 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 63 00 00 00 D0 00 00' - '00 F3 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F1 00 00 00 EF 00 00' - '00 B2 00 00 00 3D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' - '00 00 1F FF 00 00 FF F0 00 00 0F FF 00 00 FF E0' - '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 03 FF 00 00 FF C0 00 00 03 FF 00 00 FF C0' - '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' - '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F8' - '00 00 1F FF 00 00 FF F8 00 00 1F FF 00 00 FF FC' - '00 00 7F FF 00 00 FE 00 00 00 00 7F 00 00 F8 00' - '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' - '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 F0 00' - '00 00 00 0F 00 00 FC 00 00 00 00 3F 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' - '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 0B 00 00 00 4B 00 00' - '00 63 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 63 00 00' - '00 3D 00 00 00 05 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 04 00 00 00 AF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 01 01 01 FF 01 01' - '01 FF 01 01 01 FF 02 02 02 FF 02 02 02 FF 02 02' - '02 FF 03 03 03 FF 05 05 05 FF 03 03 03 FF 00 00' - '00 FA 00 00 00 80 00 00 00 03 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 3E 00 00 00 FD 6E 6E 6E FF B7 B7' - 'B7 FF AD AD AD FF A9 A9 A9 FF A5 A5 A5 FF A2 A2' - 'A2 FF 9F 9F 9F FF 9B 9B 9B FF 97 97 97 FF 94 94' - '94 FF 8C 8C 8C FF 83 83 83 FF 85 85 85 FF 38 38' - '38 FF 00 00 00 EA 00 00 00 27 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 67 0F 0F 0F FF D8 D8 D8 FF FF FF' - 'FF FF ED ED ED FF E2 E2 E2 FF DB DB DB FF D3 D3' - 'D3 FF CD CD CD FF C8 C8 C8 FF C2 C2 C2 FF BC BC' - 'BC FF B4 B4 B4 FF 9F 9F 9F FF A2 A2 A2 FF 7F 7F' - '7F FF 00 00 00 FD 00 00 00 47 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 72 1B 1B 1B FF E6 E6 E6 FF FF FF' - 'FF FF F6 F6 F6 FF F5 F5 F5 FF F1 F1 F1 FF EC EC' - 'EC FF E4 E4 E4 FF DC DC DC FF D4 D4 D4 FF CC CC' - 'CC FF C5 C5 C5 FF AB AB AB FF AD AD AD FF 90 90' - '90 FF 04 04 04 FF 00 00 00 50 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 56 0D 0D 0D FF D4 D4 D4 FF FF FF' - 'FF FF F7 F7 F7 FF F8 F8 F8 FF F3 F3 F3 FF F0 F0' - 'F0 FF EC EC EC FF E3 E3 E3 FF DA DA DA FF D2 D2' - 'D2 FF CA CA CA FF B0 B0 B0 FF B8 B8 B8 FF 82 82' - '82 FF 00 00 00 F8 00 00 00 32 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 1F 00 00 00 ED 94 94 94 FF FF FF' - 'FF FF FE FE FE FF FD FD FD FF FA FA FA FF F3 F3' - 'F3 FF E5 E5 E5 FF E1 E1 E1 FF E0 E0 E0 FF DA DA' - 'DA FF D1 D1 D1 FF BF BF BF FF C5 C5 C5 FF 52 52' - '52 FF 00 00 00 CD 00 00 00 0D 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 97 29 29 29 FF E4 E4' - 'E4 FF FF FF FF FF FF FF FF FF FF FF FF FF F0 F0' - 'F0 FF AB AB AB FF B4 B4 B4 FF E8 E8 E8 FF E4 E4' - 'E4 FF D5 D5 D5 FF D3 D3 D3 FF 9D 9D 9D FF 0C 0C' - '0C FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 1C 00 00 00 D8 4C 4C' - '4C FF EC EC EC FF FF FF FF FF FF FF FF FF FA FA' - 'FA FF E2 E2 E2 FF E3 E3 E3 FF F0 F0 F0 FF EA EA' - 'EA FF E6 E6 E6 FF B1 B1 B1 FF 23 23 23 FF 00 00' - '00 B7 00 00 00 08 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 2B 00 00' - '00 D5 33 33 33 FF B4 B4 B4 FF F9 F9 F9 FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FB FB FB FF DC DC' - 'DC FF 89 89 89 FF 1A 1A 1A FF 00 00 00 B6 00 00' - '00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 09 00 00 00 28 00 00' - '00 38 00 00 00 37 00 00 00 37 00 00 00 2C 00 00' - '00 50 00 00 00 CC 03 03 03 FF 31 31 31 FF 67 67' - '67 FF A2 A2 A2 FF 90 90 90 FF 59 59 59 FF 22 22' - '22 FF 00 00 00 FF 00 00 00 B4 00 00 00 41 00 00' - '00 2F 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 27 00 00 00 09 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 32 00 00 00 BE 00 00 00 F7 00 00' - '00 FB 00 00 00 FA 00 00 00 FA 00 00 00 FA 00 00' - '00 F3 00 00 00 F2 00 00 00 FF 00 00 00 FF 05 05' - '05 FF 79 79 79 FF 4C 4C 4C FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FD 00 00 00 F0 00 00 00 F6 00 00' - '00 FA 00 00 00 FA 00 00 00 FA 00 00 00 FB 00 00' - '00 F1 00 00 00 AE 00 00 00 29 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 1B 00 00 00 DB 26 26 26 FF 94 94 94 FF AD AD' - 'AD FF AA AA AA FF A9 A9 A9 FF A7 A7 A7 FF A7 A7' - 'A7 FF A6 A6 A6 FF A4 A4 A4 FF A2 A2 A2 FF AB AB' - 'AB FF CD CD CD FF BF BF BF FF A2 A2 A2 FF 9E 9E' - '9E FF 9E 9E 9E FF 9C 9C 9C FF 9C 9C 9C FF 9B 9B' - '9B FF 9A 9A 9A FF 99 99 99 FF 9B 9B 9B FF 77 77' - '77 FF 11 11 11 FF 00 00 00 C1 00 00 00 14 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 6F 06 06 06 FF C0 C0 C0 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FD FF FF FF FA FD FE FF F7 FA' - 'FC FF F4 F7 F9 FF F1 F4 F6 FF EE F1 F3 FF EA EC' - 'EE FF E2 E4 E6 FF E1 E3 E5 FF E2 E5 E7 FF E1 E2' - 'E5 FF DE E0 E2 FF DA DD DF FF D8 DA DD FF D5 D8' - 'DA FF D3 D6 D8 FF D0 D3 D5 FF CE CF CF FF DD DD' - 'DD FF 81 81 81 FF 00 00 00 FF 00 00 00 4E 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 22 22 22 FF EB EB EB FF FF FF FF FF F3 EA' - 'E4 FF F0 E0 D4 FF EF E1 D6 FF EF E1 D6 FF EF E1' - 'D6 FF EE E1 D6 FF ED E1 D6 FF EC E1 D5 FF EC E0' - 'D5 FF EA DE D3 FF E9 DD D2 FF E7 DA CF FF E5 D8' - 'CD FF E2 D5 CA FF DF D2 C7 FF DD CF C4 FF DB CC' - 'C1 FF D8 C9 BE FF D8 C8 BD FF D2 CE CC FF CB CC' - 'CC FF AB AB AB FF 06 06 06 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 24 24 24 FF EB EB EB FF FF FF FF FF D4 AB' - '8F FF C5 67 26 FF CD 77 39 FF D2 81 42 FF D7 89' - '4A FF DC 91 50 FF E0 97 57 FF E3 9C 5C FF E5 9F' - '5E FF E5 9F 5F FF E4 9E 5D FF E2 9A 5A FF DF 94' - '55 FF DA 8D 4E FF D6 85 47 FF D1 7D 3F FF CC 75' - '37 FF C6 6A 2C FF C5 68 2B FF D8 C3 B5 FF CE D1' - 'D3 FF A9 A9 A9 FF 06 06 06 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 22 22 22 FF EA EA EA FF FF FF FF FF D0 A5' - '89 FF BD 5A 16 FF C6 6A 2A FF CB 73 32 FF D0 7A' - '3A FF D4 82 40 FF D7 87 45 FF DA 8C 49 FF DB 8E' - '4B FF DB 8E 4C FF DA 8D 4A FF D8 89 47 FF D5 84' - '42 FF D2 7E 3C FF CD 76 35 FF C8 6E 2E FF C3 66' - '26 FF BD 5B 1A FF BB 59 1A FF D7 C0 B2 FF D1 D5' - 'D8 FF A9 A9 A9 FF 05 05 05 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 22 22 22 FF EA EA EA FF FF FF FF FF D0 A4' - '88 FF BA 54 12 FF C2 65 25 FF C7 6D 2D FF CB 73' - '34 FF CF 7A 39 FF D2 7F 3E FF D3 82 42 FF D4 84' - '43 FF D5 84 43 FF D4 83 42 FF D2 80 3F FF D0 7C' - '3B FF CD 76 36 FF C8 6F 30 FF C4 68 29 FF BF 60' - '21 FF B9 56 17 FF B8 54 17 FF D8 C1 B3 FF D4 D8' - 'DA FF A9 A9 A9 FF 05 05 05 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 21 21 21 FF E9 E9 E9 FF FF FF FF FF CD A0' - '84 FF B5 4C 0B FF BD 5D 1E FF C1 64 25 FF C5 6B' - '2A FF C9 70 30 FF CB 74 34 FF CD 77 37 FF CD 78' - '38 FF CD 78 38 FF CD 78 37 FF CC 75 35 FF CA 72' - '32 FF C7 6D 2D FF C3 67 27 FF BF 60 21 FF BB 58' - '1A FF B5 4F 10 FF B4 4D 11 FF D8 C0 B2 FF D8 DB' - 'DE FF A9 A9 A9 FF 04 04 04 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 20 20 20 FF E8 E8 E8 FF FF FF FF FF CA 9B' - '80 FF B0 44 02 FF B8 54 15 FF BC 5A 1C FF BF 60' - '21 FF C1 65 25 FF C4 68 28 FF C5 6B 2B FF C6 6C' - '2D FF C6 6D 2D FF C6 6C 2D FF C4 69 2A FF C2 66' - '26 FF C0 61 22 FF BD 5D 1E FF B9 57 19 FF B5 50' - '12 FF B0 47 08 FF B0 46 0A FF D8 C0 B2 FF DA DE' - 'E0 FF A8 A8 A8 FF 04 04 04 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 20 20 20 FF E7 E7 E7 FF FF FF FF FF C6 96' - '7B FF AA 3B 00 FF B2 4A 0D FF B4 4F 11 FF B8 55' - '17 FF BD 5E 1F FF C2 65 25 FF C4 69 2A FF C5 6B' - '2C FF C6 6C 2C FF C6 6C 2C FF C4 69 2A FF C2 65' - '26 FF BE 5E 20 FF B8 55 17 FF B3 4C 0E FF AF 46' - '08 FF AB 3F 01 FF AD 43 06 FF DA C2 B4 FF DE E2' - 'E4 FF A7 A7 A7 FF 03 03 03 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1F 1F 1F FF E6 E6 E6 FF FF FF FF FF C2 93' - '78 FF A5 34 00 FF AB 40 03 FF B6 52 14 FF C1 64' - '26 FF C7 6E 2F FF CA 73 33 FF CC 77 36 FF CD 78' - '38 FF CD 79 38 FF CD 78 38 FF CC 77 37 FF CB 74' - '34 FF C8 6F 30 FF C4 69 2A FF BC 5C 1D FF AF 47' - '0A FF A7 3A 00 FF AC 43 06 FF DB C3 B5 FF E0 E4' - 'E7 FF A7 A7 A7 FF 03 03 03 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1E 1E 1E FF E5 E5 E5 FF FF FF FF FF C1 90' - '76 FF A6 36 00 FF BA 59 1A FF C8 6F 2F FF CC 75' - '35 FF CF 7A 3A FF D1 7F 3E FF D3 82 41 FF D4 83' - '42 FF D4 84 43 FF D4 83 42 FF D3 82 41 FF D1 7E' - '3E FF CF 7A 39 FF CC 75 35 FF C9 70 30 FF C3 67' - '27 FF B3 4D 0E FF AC 42 06 FF DC C4 B6 FF E3 E7' - 'EA FF A7 A7 A7 FF 02 02 02 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1D 1D 1D FF E4 E4 E4 FF FF FF FF FF BE 8E' - '73 FF B7 50 0E FF CA 72 32 FF CD 77 37 FF D1 7D' - '3D FF D4 83 43 FF D8 88 47 FF D9 8C 4B FF DB 8F' - '4D FF DB 8F 4D FF DB 8F 4D FF D9 8C 4B FF D8 88' - '47 FF D4 83 43 FF D1 7D 3D FF CD 76 36 FF C9 70' - '30 FF C4 67 27 FF B5 51 14 FF DC C3 B6 FF E6 EA' - 'EC FF A6 A6 A6 FF 01 01 01 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1C 1C 1C FF E2 E2 E2 FF FF FF FF FF C3 96' - '7A FF C4 65 22 FF CD 76 36 FF D2 7E 3E FF D6 85' - '44 FF DA 8C 4B FF DD 92 50 FF E0 97 54 FF E1 99' - '57 FF E2 99 58 FF E1 99 57 FF E0 97 54 FF DD 92' - '50 FF DA 8C 4B FF D6 85 44 FF D2 7E 3E FF CC 76' - '36 FF C7 6D 2D FF C2 65 27 FF DE C6 B9 FF E8 EB' - 'EE FF A6 A6 A6 FF 01 01 01 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1B 1B 1B FF E1 E1 E1 FF FF FF FF FF C5 9A' - '7E FF C8 6C 28 FF D1 7D 3C FF D6 85 44 FF DA 8D' - '4B FF DF 94 52 FF E3 9B 59 FF E6 A1 5E FF E8 A4' - '62 FF E9 A5 62 FF E8 A4 62 FF E6 A1 5E FF E3 9B' - '59 FF DF 94 52 FF DA 8D 4B FF D6 85 44 FF D0 7D' - '3C FF CA 72 31 FF C7 6D 2E FF E5 CE C1 FF F4 F8' - 'FA FF A7 A7 A7 FF 00 00 00 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1A 1A 1A FF E0 E0 E0 FF FF FF FF FF BC 8D' - '70 FF C7 68 23 FF D4 81 3E FF D9 89 46 FF DE 92' - '4E FF E4 9A 56 FF E9 A2 5E FF ED AA 65 FF F0 AE' - '6A FF F1 B0 6B FF F0 AE 6A FF ED AA 65 FF E9 A2' - '5E FF E4 9A 56 FF DE 92 4E FF D9 89 46 FF D4 80' - '3D FF CE 76 33 FF C2 63 23 FF E9 D0 C2 FF FF FF' - 'FF FF AA AA AA FF 00 00 00 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 1A 1A 1A FF E0 E0 E0 FF FF FF FF FF B5 8D' - '76 FF B4 60 29 FF CF 88 4F FF D4 90 56 FF D9 98' - '5D FF DE A0 65 FF E3 A8 6D FF E7 AF 74 FF EB B5' - '79 FF EC B7 7B FF EB B5 79 FF E7 AF 74 FF E3 A8' - '6D FF DE A0 65 FF D8 98 5D FF D3 90 56 FF CF 87' - '4E FF C7 7C 44 FF B0 5D 2B FF E8 D3 C8 FF FF FF' - 'FF FF AB AB AB FF 00 00 00 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 84 15 15 15 FF DB DB DB FF FF FF FF FF EE EC' - 'EC FF E7 E4 E2 FF EB E7 E4 FF EB E8 E5 FF EC E8' - 'E5 FF EC E9 E6 FF EC E9 E6 FF EC EA E7 FF ED EA' - 'E7 FF ED EA E7 FF ED EA E7 FF EC EA E7 FF EC E9' - 'E6 FF EB E8 E5 FF EA E8 E5 FF EA E7 E4 FF EA E6' - 'E3 FF E8 E4 E2 FF E6 E3 E2 FF F8 F8 F7 FF FF FF' - 'FF FF A7 A7 A7 FF 00 00 00 FF 00 00 00 61 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 6C 00 00 00 FF 8E 8E 8E FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF F4 F4' - 'F4 FF 58 58 58 FF 00 00 00 FD 00 00 00 45 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 16 00 00 00 D5 0A 0A 0A FF 53 53 53 FF 74 74' - '74 FF 72 72 72 FF 72 72 72 FF 72 72 72 FF 72 72' - '72 FF 72 72 72 FF 72 72 72 FF 71 71 71 FF 71 71' - '71 FF 71 71 71 FF 71 71 71 FF 71 71 71 FF 71 71' - '71 FF 71 71 71 FF 71 71 71 FF 71 71 71 FF 70 70' - '70 FF 70 70 70 FF 70 70 70 FF 6F 6F 6F FF 3F 3F' - '3F FF 02 02 02 FF 00 00 00 B2 00 00 00 05 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 28 00 00 00 B1 00 00 00 EF 00 00' - '00 F1 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' - '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F2 00 00' - '00 E8 00 00 00 97 00 00 00 15 00 00 00 00 00 00' - '00 00 00 00 00 00 FF 00 00 FF FE 00 00 7F FE 00' - '00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE 00' - '00 7F FF 00 00 FF FF 00 00 FF FF 80 01 FF F0 00' - '00 0F E0 00 00 07 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' - '00 03 E0 00 00 07 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 03 01 01' - '01 7C 08 08 08 AD 08 08 08 A8 08 08 08 A8 08 08' - '08 A8 08 08 08 A8 08 08 08 AD 01 01 01 6D 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 31 57 57' - '57 FA CE CE CE FF BB BB BB FF B1 B1 B1 FF A8 A8' - 'A8 FF 9D 9D 9D FF 8D 8D 8D FF 30 30 30 F2 00 00' - '00 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 3A 7B 7B' - '7B FC FF FF FF FF F5 F5 F5 FF EC EC EC FF DD DD' - 'DD FF CA CA CA FF BA BA BA FF 4C 4C 4C F7 00 00' - '00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 0D 37 37' - '37 D7 F5 F5 F5 FF FF FF FF FF E2 E2 E2 FF D9 D9' - 'D9 FF E6 E6 E6 FF B7 B7 B7 FF 1C 1C 1C C5 00 00' - '00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 45 59 59 59 EB E5 E5 E5 FF F1 F1 F1 FF EA EA' - 'EA FF C2 C2 C2 FF 3B 3B 3B E1 00 00 00 35 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 12 02 02 02 78 06 06 06 96 05 06' - '06 8A 00 00 00 C6 16 16 16 FF 77 77 77 FF 66 66' - '66 FF 11 11 11 FF 00 00 00 BC 07 07 07 89 07 07' - '07 96 02 02 02 73 00 00 00 0E 00 00 00 00 00 00' - '00 00 03 03 03 9C 94 94 93 FF D1 D4 D7 FF C7 CD' - 'D0 FF C3 C7 CA FF B9 BD C0 FF C2 C6 C9 FF BB BF' - 'C2 FF B0 B4 B8 FF B2 B7 BA FF B0 B5 B9 FF B1 B4' - 'B6 FF 6E 6D 6D FF 00 00 00 84 00 00 00 00 00 00' - '00 00 19 19 1A CC EC ED ED FF ED C9 B1 FF E6 B4' - '8F FF EB BF 9B FF ED C4 A0 FF EB C3 9E FF E8 C0' - '9B FF E5 BA 95 FF DD AF 8B FF D4 9E 79 FF D9 B9' - 'A5 FF B9 BB BD FF 09 0A 0A A8 00 00 00 00 00 00' - '00 00 1A 1B 1B CC EB EC ED FF CC 86 58 FF C2 5E' - '17 FF CE 75 30 FF D5 80 3B FF D8 85 40 FF D6 82' - '3D FF D1 78 34 FF C8 6A 26 FF BA 4F 08 FF CC 8E' - '68 FF B8 BC C0 FF 09 09 09 A8 00 00 00 00 00 00' - '00 00 19 1A 1A CC EA EB EC FF C7 81 57 FF B9 53' - '12 FF C2 66 26 FF C7 6E 2E FF CA 71 32 FF C8 6F' - '30 FF C4 68 29 FF BD 5C 1E FF B1 45 04 FF C9 8C' - '68 FF BA BE C1 FF 08 09 09 A8 00 00 00 00 00 00' - '00 00 18 19 1A CC E9 EA EB FF BE 73 4A FF AF 44' - '03 FF C0 62 23 FF C6 6D 2D FF C9 71 31 FF C8 70' - '30 FF C4 69 2A FF BB 5A 1B FF A9 39 00 FF C7 88' - '65 FF BC C1 C4 FF 08 08 08 A8 00 00 00 00 00 00' - '00 00 18 18 19 CC E6 E7 E8 FF C1 7A 4F FF C2 62' - '1F FF D0 7C 3C FF D5 85 44 FF D7 88 47 FF D7 87' - '46 FF D3 81 40 FF CC 76 36 FF BB 57 13 FF CC 8F' - '6C FF BD C1 C4 FF 07 08 08 A8 00 00 00 00 00 00' - '00 00 16 17 18 CC E3 E4 E4 FF CD 8D 60 FF D0 78' - '33 FF DA 8C 49 FF E2 98 54 FF E6 9F 5B FF E4 9C' - '59 FF DE 92 4F FF D6 84 42 FF C9 6B 26 FF DA A2' - '7C FF C1 C5 C8 FF 07 07 07 A8 00 00 00 00 00 00' - '00 00 17 17 18 CC E4 E4 E5 FF CA 90 6A FF D5 89' - '4B FF E1 9F 63 FF EB AE 71 FF F0 B9 7A FF EE B5' - '77 FF E6 A7 6A FF DC 97 5B FF CC 7B 3D FF DF AD' - '8D FF D0 D4 D7 FF 06 07 07 A8 00 00 00 00 00 00' - '00 00 09 09 09 C1 CB CC CC FF FA F6 F4 FF F2 EE' - 'EA FF F4 F0 EC FF F4 F1 EE FF F4 F2 EE FF F4 F2' - 'EE FF F4 F0 ED FF F2 EF EA FF F0 EB E8 FF FD FA' - 'F8 FF AF AF AF FF 00 00 00 9F 00 00 00 00 00 00' - '00 00 00 00 00 4A 1E 1E 1D E2 45 46 47 F3 43 45' - '46 F0 42 43 45 F0 42 43 44 F0 42 43 44 F0 42 43' - '44 F0 42 43 44 F0 42 43 44 F0 42 44 45 F0 41 42' - '43 F4 16 16 16 D9 00 00 00 39 00 00 00 00 E0 0F' - '00 00 E0 07 00 00 E0 07 00 00 E0 07 00 00 F0 0F' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' - '00 00 80 01 00 00 80 01 00 00 80 01 00 00' -} */ - - - - -/* BINRES desktop.ico */ -34 ICON desktop.ico -/* { - '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' - '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' - '00 00 3E 09 00 00 20 20 00 00 01 00 20 00 A8 10' - '00 00 A6 0E 00 00 10 10 00 00 01 00 20 00 68 04' - '00 00 4E 1F 00 00 10 10 00 00 01 00 04 00 28 01' - '00 00 B6 23 00 00 20 20 00 00 01 00 04 00 E8 02' - '00 00 DE 24 00 00 30 30 00 00 01 00 08 00 A8 0E' - '00 00 C6 27 00 00 30 30 00 00 01 00 20 00 A8 25' - '00 00 6E 36 00 00 30 30 00 00 01 00 04 00 68 06' - '00 00 16 5C 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 11 11 00 33 33 33 00 66 33 00 00 44 44' - '44 00 55 55 55 00 66 66 66 00 77 77 77 00 7F 7F' - '7F 00 99 00 00 00 99 33 00 00 99 33 33 00 CC 33' - '00 00 CC 33 33 00 99 66 00 00 99 66 33 00 CC 66' - '00 00 CC 66 33 00 99 66 66 00 CC 66 66 00 FF 66' - '66 00 99 99 33 00 CC 99 33 00 FF 99 33 00 99 99' - '66 00 CC 99 66 00 FF 99 66 00 CC CC 66 00 FF CC' - '66 00 88 88 88 00 99 99 99 00 AA AA AA 00 BB BB' - 'BB 00 CC 99 99 00 FF 99 99 00 CC CC 99 00 FF CC' - '99 00 99 99 CC 00 CC CC CC 00 DD DD DD 00 FF CC' - 'CC 00 CC FF CC 00 CC CC FF 00 CC FF FF 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 58 00 5A 00 00 EC FD 7F 1A 02' - '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' - 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' - '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' - 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' - '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' - '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 58 00' - '00 00 00 00 00 00 03 00 00 00 60 00 1A 02 40 9F' - '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' - 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' - '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' - '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 00 63' - '38 00 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' - '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' - 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' - '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' - '68 65 6C 6C 33 32 5C 64 65 73 6B 74 6F 70 2E 69' - '63 6F 00 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' - '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' - 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' - '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' - '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' - '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' - 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' - 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' - '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 2E' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 2E 2E' - '04 1F 20 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1E' - '21 1F 1F 1E 1E 1F 1E 1F 1E 1F 06 2E 2E 2E 2E 02' - '2C 2D 2D 2D 2D 2D 2D 2C 2C 2D 2C 2C 2C 2C 28 2C' - '29 27 27 27 27 27 26 26 26 26 27 06 2E 2E 2E 07' - '2D 2D 2D 2D 2D 2D 2C 2D 2C 2A 2D 2C 27 2B 2C 27' - '2A 27 27 29 27 27 2A 27 27 26 26 1E 2E 2E 2E 07' - '2D 2D 28 19 21 1B 22 21 24 24 24 23 24 22 23 24' - '24 22 23 22 21 21 1A 19 23 26 26 1F 2E 2E 2E 1D' - '2D 2D 19 11 10 11 16 16 11 16 13 17 19 16 17 13' - '16 16 11 16 11 10 0B 10 19 26 27 1E 2E 2E 2E 07' - '2D 2D 21 0E 11 11 11 11 11 19 17 19 16 1A 13 16' - '19 11 16 11 10 11 11 0E 13 27 26 1F 2E 2E 2E 07' - '2D 2D 21 10 11 11 0F 11 16 11 11 16 11 16 16 11' - '16 11 11 11 11 0F 10 0C 19 27 26 1E 2E 2E 2E 07' - '2D 2D 19 10 0B 10 11 16 11 11 16 11 16 11 11 16' - '11 11 11 10 0F 10 11 0A 19 26 27 1F 2E 2E 2E 07' - '2D 2D 21 0A 10 0F 10 0D 11 11 0F 11 11 16 11 11' - '11 11 11 11 0C 0A 0C 0E 13 2C 27 1E 2E 2E 2E 07' - '2D 2D 18 0C 0E 0D 11 10 0F 10 11 11 11 11 11 11' - '11 0E 11 0A 12 18 0F 09 16 2A 27 1E 2E 2E 2E 07' - '2D 2D 21 0A 0C 0E 0A 11 11 11 11 16 11 11 11 11' - '11 11 10 0F 2B 2D 1E 0A 13 29 27 1E 2E 2E 2E 07' - '2D 2D 19 0A 0A 0A 11 11 16 11 11 11 16 11 11 16' - '11 16 11 12 27 26 2A 03 16 2C 27 1F 2E 2E 2E 07' - '2D 2D 19 0A 10 11 11 11 11 19 16 11 11 19 11 11' - '17 11 11 0F 20 2C 1E 0A 13 27 27 1E 2E 2E 2E 06' - '2D 2D 21 0A 11 11 16 11 16 16 14 16 19 17 19 16' - '19 11 16 11 11 0F 11 0A 16 2C 2C 1E 2E 2E 2E 07' - '2D 2D 18 10 11 16 11 17 13 16 16 1A 16 19 17 19' - '16 1A 11 15 12 15 0F 11 13 27 2C 1E 2E 2E 2E 06' - '2D 2D 19 11 11 11 16 13 16 19 1A 19 19 1A 19 1A' - '14 16 16 21 20 1F 25 0E 19 2C 2C 1E 2E 2E 2E 07' - '2D 2D 13 11 11 16 19 17 19 17 19 1A 1A 1B 1A 19' - '1B 1A 16 12 2C 27 1F 11 19 2C 2D 1E 2E 2E 2E 06' - '2D 2D 18 11 16 1A 11 19 1A 19 1C 1A 1B 1A 1B 1A' - '1A 19 17 19 20 2C 21 0E 13 2D 2D 1E 2E 2E 2E 06' - '2D 2D 12 10 11 16 19 17 19 1A 19 1C 1A 1C 1A 1B' - '1A 19 19 16 12 0F 15 0D 19 2D 2D 1E 2E 2E 2E 06' - '2D 2D 2C 26 27 27 27 27 27 27 27 27 27 27 27 27' - '27 27 27 28 27 27 28 26 2C 2D 2D 1E 2E 2E 2E 02' - '2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D' - '2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 06 2E 2E 2E 2E' - '05 26 26 27 26 27 27 26 27 26 27 27 26 27 26 27' - '27 26 27 26 27 26 27 26 26 26 1D 2E 2E 2E 2E 2E' - '2E 2E 01 01 01 2E 01 01 01 01 2E 01 01 01 01 2E' - '01 01 01 01 2E 01 01 01 01 2E 2E 2E 2E 00 00 00' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' - '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF FF FF FF FF FF FF C0 00 00 03 80 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00' - '00 03 FF FF FF FF FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 11 00 00 00 00 11' - '00 00 00 00 11 00 11 11 11 00 33 33 33 00 44 44' - '44 00 55 55 55 00 7F 7F 7F 00 99 33 00 00 CC 33' - '00 00 99 66 00 00 99 66 33 00 CC 66 00 00 CC 66' - '33 00 CC 66 66 00 CC 99 33 00 FF 99 33 00 99 99' - '66 00 CC 99 66 00 FF 99 66 00 FF CC 66 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF 99' - '99 00 CC CC 99 00 FF CC 99 00 CC 99 CC 00 99 CC' - 'CC 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 FF FF' - 'CC 00 FF CC FF 00 EE EE EE 00 FF FF FF 00 00 00' - '00 00 DD DD DD 00 FF CC CC 00 CC FF CC 00 CC CC' - 'FF 00 CC FF FF 00 EE EE EE 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' - '95 00 00 00 38 00 A8 44 F9 77 15 00 00 00 78 0A' - '38 00 00 00 38 00 B0 6C 38 00 98 17 95 00 00 00' - '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' - 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 96 00' - '00 00 96 00 00 00 09 00 00 00 B0 18 95 00 00 00' - '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' - '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 00 00 00 00 58 00' - '5A 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' - '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' - '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' - 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' - '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' - 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' - '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' - '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' - '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' - 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' - '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' - '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' - 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' - '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' - '95 00 7F E9 4B 00 00 63 38 00 00 00 00 C0 00 00' - '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' - '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' - '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' - '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' - '65 73 6B 74 6F 70 2E 69 63 6F 00 93 4B 00 14 1A' - '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' - 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' - 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' - '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' - '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' - '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' - 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' - '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 26 26 26 26 26 26 26 26 26 26' - '02 26 26 26 26 26 26 16 1F 1F 18 18 18 18 17 18' - '17 17 17 17 07 26 06 25 25 23 22 24 22 24 20 21' - '20 20 20 20 17 01 06 25 13 10 0E 14 13 13 14 13' - '10 0E 0E 19 18 03 06 25 13 09 10 0E 10 0E 10 0E' - '0E 0E 0B 1C 17 26 06 25 0F 0D 0C 0E 0E 10 0E 0E' - '0E 0B 0A 19 1E 26 06 25 0C 0D 0A 0E 0E 0D 0E 0E' - '0E 17 0C 19 18 26 06 25 0E 09 10 0E 0E 0F 10 0E' - '0C 20 0F 19 1F 26 06 25 0F 0E 0E 10 13 11 13 10' - '0E 0C 0C 1B 1D 02 05 25 13 0E 10 13 14 13 11 13' - '0F 1F 12 1A 18 26 06 25 0E 0E 10 14 10 15 13 11' - '13 17 0E 1B 1F 26 05 25 18 1B 21 1B 20 21 21 20' - '1C 18 1B 24 20 26 04 17 24 24 20 24 24 20 24 20' - '24 24 20 24 07 26 26 26 04 26 04 04 26 04 26 04' - '04 26 04 26 26 26 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 23 00 00 00 58 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' - '00 3D 00 00 00 08 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 6E 00 00 00 E7 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 01 01 01 FF 01 01 01 FF 01 01' - '01 FF 01 01 01 FF 01 01 01 FF 01 01 01 FF 01 01' - '01 FF 01 01 01 FF 02 02 02 FF 02 02 02 FF 02 02' - '02 FF 02 02 02 FF 02 02 02 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 A7 00 00 00 1D 00 00 00 00 00 00' - '00 5D 00 00 00 FF 47 47 47 FF AA AA AA FF B6 B6' - 'B6 FF B2 B2 B2 FF B1 B1 B1 FF B1 B1 B1 FF AF AF' - 'AF FF AE AE AE FF AE AE AE FF AD AD AD FF AC AC' - 'AC FF AC AC AC FF AB AB AB FF AA AA AA FF A9 A9' - 'A9 FF A8 A8 A8 FF A7 A7 A7 FF A7 A7 A7 FF A5 A5' - 'A5 FF A5 A5 A5 FF A4 A4 A4 FF A3 A3 A3 FF A2 A2' - 'A2 FF A1 A1 A1 FF A2 A2 A2 FF A3 A3 A3 FF 64 64' - '64 FF 05 05 05 FF 00 00 00 AB 00 00 00 0A 00 00' - '00 CF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' - 'FF FF FE FF FF FF FC FC FC FF F9 FA FA FF F7 F7' - 'F7 FF F4 F5 F5 FF F2 F3 F3 FF F0 F1 F1 FF EE EE' - 'EE FF EC EC EC FF E9 EA EA FF E7 E7 E7 FF E5 E5' - 'E5 FF E3 E3 E3 FF E0 E0 E1 FF DE DE DE FF DC DC' - 'DC FF D9 D9 DA FF D7 D7 D8 FF D5 D5 D5 FF D3 D3' - 'D3 FF D0 D0 D0 FF CE CE CE FF CE CE CE FF DE DE' - 'DE FF 66 66 66 FF 00 00 00 FD 00 00 00 41 00 00' - '00 F2 7C 7C 7C FF FF FF FF FF FA FA FA FF FA FC' - 'FD FF F9 FC FF FF F7 FA FC FF F4 F7 FA FF F3 F6' - 'F8 FF F1 F3 F6 FF EE F1 F4 FF EC EF F2 FF EA ED' - 'F0 FF E8 EB ED FF E7 E9 EC FF E4 E7 E9 FF E2 E5' - 'E8 FF E1 E3 E6 FF DF E2 E4 FF DD E0 E2 FF DB DE' - 'E1 FF D9 DD DF FF D8 DB DD FF D6 D9 DC FF D4 D8' - 'DA FF D3 D6 D9 FF D0 D2 D4 FF C6 C6 C6 FF CF CF' - 'CF FF A3 A3 A3 FF 01 01 01 FF 00 00 00 63 00 00' - '00 F0 7E 7E 7E FF FF FF FF FF FD FE FE FF E2 C8' - 'B7 FF DA A0 77 FF DE A9 82 FF E1 AE 86 FF E4 B2' - '8A FF E6 B6 8F FF E9 BB 92 FF EA BD 95 FF EC C0' - '98 FF ED C2 9A FF EE C3 9A FF EE C2 9A FF EC C1' - '99 FF EB BF 97 FF E9 BC 94 FF E7 B8 90 FF E4 B4' - '8C FF E2 B0 88 FF DF AB 84 FF DC A6 7F FF D9 A1' - '7A FF D4 97 6E FF E0 B8 9F FF D1 D2 D3 FF CE CF' - 'CF FF A2 A2 A2 FF 01 01 01 FF 00 00 00 61 00 00' - '00 F0 7D 7D 7D FF FF FF FF FF FF FF FF FF CC A0' - '82 FF BD 56 0F FF C5 66 23 FF CA 6E 2B FF CE 76' - '31 FF D2 7D 38 FF D6 83 3E FF D9 89 43 FF DC 8D' - '47 FF DE 90 4A FF DF 91 4B FF DF 91 4B FF DD 8F' - '49 FF DB 8C 46 FF D8 87 42 FF D6 81 3C FF D1 7B' - '37 FF CD 73 2F FF C8 6C 28 FF C4 64 21 FF BF 5C' - '1A FF B6 4B 06 FF CD 87 5B FF D4 D7 D8 FF D1 D2' - 'D3 FF A1 A1 A1 FF 01 01 01 FF 00 00 00 61 00 00' - '00 F0 7B 7B 7B FF FF FF FF FF FF FF FF FF CE A3' - '87 FF BD 59 16 FF C4 68 29 FF C8 6F 30 FF CC 76' - '35 FF D0 7C 3B FF D3 81 40 FF D6 86 44 FF D7 89' - '48 FF D9 8C 4A FF DA 8C 4B FF DA 8C 4B FF D9 8B' - '49 FF D7 88 47 FF D4 84 43 FF D2 7F 3F FF CF 7A' - '3A FF CB 74 34 FF C7 6D 2D FF C3 66 27 FF BE 5E' - '20 FF B6 4E 0D FF CD 8A 60 FF D6 D8 DA FF D4 D4' - 'D5 FF A1 A1 A1 FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 7B 7B 7B FF FF FF FF FF FF FF FF FF CD A1' - '85 FF B9 52 11 FF C0 61 23 FF C4 68 2A FF C8 6F' - '2F FF CB 74 34 FF CE 79 38 FF D1 7D 3C FF D2 80' - '3F FF D4 82 42 FF D3 83 42 FF D3 83 42 FF D3 82' - '41 FF D1 7F 3E FF D0 7C 3B FF CD 77 37 FF CA 72' - '33 FF C7 6D 2D FF C3 66 28 FF BF 60 21 FF BB 59' - '1A FF B2 49 07 FF CB 86 5D FF D8 D9 DB FF D6 D7' - 'D7 FF A1 A1 A1 FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 7A 7A 7A FF FF FF FF FF FF FF FF FF CB 9E' - '82 FF B5 4C 0A FF BC 5B 1C FF C0 62 22 FF C4 67' - '28 FF C6 6C 2C FF C9 70 31 FF CB 74 34 FF CD 77' - '37 FF CD 79 39 FF CE 79 39 FF CE 79 39 FF CE 78' - '37 FF CC 76 36 FF CB 73 33 FF C8 6F 2F FF C5 6B' - '2B FF C2 65 26 FF BF 60 21 FF BC 59 1A FF B7 53' - '15 FF AE 42 01 FF C8 82 5A FF DA DC DC FF D7 D8' - 'D8 FF A0 A0 A0 FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 78 78 78 FF FF FF FF FF FF FF FF FF C7 99' - '7E FF B1 46 03 FF B8 54 15 FF BB 5A 1B FF BE 5F' - '20 FF C1 64 25 FF C4 68 29 FF C5 6B 2C FF C7 6D' - '2E FF C8 6F 2F FF C8 6F 2F FF C8 6F 2F FF C7 6E' - '2E FF C6 6C 2C FF C5 6A 2A FF C2 66 27 FF C0 62' - '23 FF BF 5E 1E FF B7 51 10 FF A9 44 05 FF B2 47' - '07 FF AC 3C 00 FF C6 7F 57 FF DC DE DF FF DA DB' - 'DB FF 9F 9F 9F FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 77 77 77 FF FF FF FF FF FF FF FF FF C4 94' - '79 FF AC 3D 00 FF B3 4C 0F FF B7 52 14 FF B9 57' - '18 FF BB 5A 1C FF BE 5E 1F FF BF 62 23 FF C2 65' - '26 FF C4 68 28 FF C5 69 2A FF C5 69 2A FF C4 69' - '29 FF C2 66 27 FF C0 62 24 FF BD 5E 1F FF BC 5A' - '1A FF AE 4E 12 FF 9A 6B 4D FF AB 92 82 FF 96 57' - '32 FF A4 31 00 FF C6 7E 55 FF DE E0 E2 FF DD DE' - 'DE FF 9E 9E 9E FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 76 76 76 FF FF FF FF FF FF FF FF FF C0 90' - '76 FF A8 37 00 FF AF 45 07 FF B1 49 0B FF B3 4D' - '10 FF B9 57 18 FF C1 64 25 FF C5 6B 2B FF C7 6E' - '2E FF C8 70 30 FF C9 71 31 FF C9 71 31 FF C9 71' - '31 FF C8 70 2F FF C6 6C 2D FF C4 69 29 FF C3 5F' - '1C FF 93 5C 39 FF DC E4 EA FF ED F3 F6 FF A8 A9' - 'AB FF 86 2F 03 FF C9 7D 52 FF DF E1 E3 FF DE DF' - 'DF FF 9E 9E 9E FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 75 75 75 FF FF FF FF FF FF FF FF FF BE 8F' - '74 FF A6 35 00 FF AA 3D 01 FF B0 49 0B FF BD 5E' - '1F FF C6 6C 2C FF CA 72 32 FF CC 75 35 FF CD 77' - '37 FF CE 78 39 FF CE 7A 39 FF CE 7A 39 FF CE 79' - '39 FF CD 78 37 FF CC 75 36 FF CB 73 32 FF C9 6B' - '28 FF 96 71 57 FF DC E2 E7 FF D4 D0 CE FF C7 CD' - 'D1 FF 7B 34 0B FF CA 7D 50 FF E0 E3 E5 FF E0 E1' - 'E2 FF 9D 9D 9D FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 73 73 73 FF FF FF FF FF FF FF FF FF BD 8D' - '72 FF A6 34 00 FF B2 4C 0F FF C4 68 28 FF CA 72' - '32 FF CC 76 36 FF CF 79 39 FF D1 7D 3D FF D2 80' - '3F FF D3 82 42 FF D4 83 42 FF D4 83 42 FF D3 82' - '41 FF D2 81 40 FF D1 7E 3E FF D0 7B 3A FF D2 78' - '34 FF 9E 60 33 FF B4 B5 B4 FF E9 EF F2 FF AC A2' - '9C FF 8D 2C 00 FF C8 7E 54 FF E3 E5 E6 FF E2 E4' - 'E4 FF 9C 9C 9C FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 72 72 72 FF FF FF FF FF FF FF FF FF BA 8A' - '6E FF AF 43 05 FF C6 6C 2C FF CB 74 33 FF CE 77' - '37 FF D1 7D 3C FF D3 82 41 FF D6 86 44 FF D7 89' - '48 FF D9 8C 4A FF D9 8C 4B FF D9 8C 4B FF D9 8C' - '4A FF D8 8A 49 FF D7 87 46 FF D4 83 42 FF D2 7F' - '3F FF D2 78 34 FF AC 65 2F FF 9A 63 3B FF AD 59' - '21 FF B7 49 08 FF C4 7D 55 FF E5 E6 E7 FF E5 E6' - 'E7 FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 6F 6F 6F FF FF FF FF FF FE FF FF FF BA 8B' - '70 FF BF 5D 1A FF CB 73 33 FF CE 78 38 FF D2 7E' - '3E FF D5 84 43 FF D8 8A 48 FF DB 8E 4C FF DE 92' - '50 FF DE 95 53 FF E0 96 54 FF E0 96 54 FF DF 95' - '53 FF DE 93 51 FF DC 8F 4E FF D9 8B 4A FF D8 86' - '43 FF BD 7D 4A FF A6 75 51 FF AA 75 4E FF 9F 6E' - '44 FF B5 59 18 FF CB 86 5D FF E5 E7 E8 FF E7 E7' - 'E8 FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 6E 6E 6E FF FF FF FF FF FC FF FF FF BE 92' - '77 FF C6 67 24 FF CD 77 37 FF D1 7E 3E FF D5 85' - '43 FF D9 8B 4A FF DD 91 4F FF E0 96 54 FF E2 9A' - '58 FF E4 9E 5B FF E5 9F 5D FF E5 9F 5C FF E5 9E' - '5C FF E3 9B 59 FF E0 97 56 FF DE 93 51 FF D9 87' - '42 FF B8 97 7C FF B0 BA C2 FF B0 B5 BA FF A3 AA' - 'A9 FF A9 5B 22 FF D5 91 66 FF E7 E8 E9 FF EA EA' - 'EB FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 6C 6C 6C FF FF FF FF FF FC FF FF FF BC 90' - '74 FF C8 6B 27 FF D0 7B 3B FF D4 83 42 FF D8 8A' - '48 FF DD 91 4F FF E1 97 56 FF E4 9E 5B FF E7 A2' - '60 FF EA A6 63 FF EA A9 65 FF EB A9 66 FF EA A7' - '64 FF E8 A4 61 FF E6 9F 5D FF E2 99 58 FF E1 91' - '4B FF B3 8D 6C FF D1 D6 DB FF E0 E3 E4 FF B3 AF' - 'AD FF B5 60 24 FF D4 92 67 FF F4 F6 F7 FF FA FA' - 'FB FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 6B 6B 6B FF FF FF FF FF FC FF FF FF B3 82' - '67 FF C4 61 1C FF D4 80 3D FF D7 86 44 FF DC 8D' - '4B FF E0 95 52 FF E5 9C 59 FF E9 A3 60 FF ED AA' - '65 FF F0 AF 6A FF F2 B2 6D FF F2 B3 6D FF F1 B0' - '6C FF EE AC 67 FF EA A5 62 FF E6 9F 5B FF E7 99' - '53 FF B5 81 54 FF C4 C5 C6 FF DA DF E1 FF A6 95' - '89 FF BB 5B 17 FF CC 85 5A FF FA FC FD FF FF FF' - 'FF FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' - '00 F0 6A 6A 6A FF FF FF FF FF FD FF FF FF AC 84' - '6D FF AA 52 1C FF CB 80 44 FF D2 88 4A FF D6 8F' - '51 FF DB 96 58 FF DF 9E 60 FF E4 A5 66 FF E8 AC' - '6D FF EC B2 72 FF EE B6 76 FF EE B7 77 FF ED B4' - '74 FF E9 AE 6F FF E5 A8 69 FF E1 A1 62 FF DE 9A' - '5B FF CE 8B 50 FF A9 78 50 FF A5 76 50 FF AD 70' - '41 FF AE 59 20 FF C1 85 64 FF FD FF FF FF FF FF' - 'FF FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' - '00 F3 69 69 69 FF FF FF FF FF FF FF FF FF E2 E0' - 'E0 FF DA D6 D4 FF DE DA D6 FF DF DB D7 FF E0 DB' - 'D7 FF E0 DC D8 FF E0 DC D8 FF E1 DD D9 FF E1 DD' - 'D9 FF E1 DE D9 FF E1 DE DA FF E1 DE DA FF E1 DE' - 'DA FF E1 DD D9 FF E1 DD D9 FF E0 DC D8 FF DF DB' - 'D7 FF E1 DC D7 FF E4 DC D4 FF E3 DA D2 FF E1 D9' - 'D3 FF D8 D5 D3 FF E5 E3 E2 FF FE FE FE FF FF FF' - 'FF FF 9B 9B 9B FF 00 00 00 FF 00 00 00 63 00 00' - '00 DE 3A 3A 3A FF F2 F2 F2 FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE FE' - 'FE FF 67 67 67 FF 00 00 00 FF 00 00 00 45 00 00' - '00 7A 01 01 01 FF 5D 5D 5D FF C3 C3 C3 FF D3 D3' - 'D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' - 'D1 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CF CF' - 'CF FF CE CE CE FF CF CF CF FF C9 C9 C9 FF 7B 7B' - '7B FF 0B 0B 0B FF 00 00 00 BF 00 00 00 0A 00 00' - '00 07 00 00 00 98 00 00 00 FD 08 08 08 FF 11 11' - '11 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' - '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' - '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' - '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' - '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' - '10 FF 10 10 10 FF 11 11 11 FF 0C 0C 0C FF 00 00' - '00 FF 00 00 00 C4 00 00 00 24 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 40 00 00 00 7D 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 59 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF FF FF FF FF FF FF C0 00 00 03 80 00' - '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00' - '00 03 FF FF FF FF FF FF FF FF FF FF FF FF 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 21 00 00 00 92 05 05' - '05 A8 05 05 05 A8 05 05 05 A8 05 05 05 A8 06 06' - '06 A8 06 06 06 A8 06 06 06 A8 06 06 06 A8 06 06' - '06 A8 07 07 07 A8 07 07 07 A8 06 06 06 A8 00 00' - '00 78 00 00 00 0A 0E 0E 0E B9 98 98 98 FF C9 CB' - 'CC FF C2 C4 C6 FF BF C1 C2 FF BC BE BF FF B8 BA' - 'BC FF B6 B8 B9 FF B4 B5 B7 FF B0 B2 B4 FF AE B1' - 'B2 FF AC AE B0 FF AA AC AE FF AC AC AD FF 55 55' - '55 FF 01 01 01 72 43 43 43 F3 FF FF FF FF FD F5' - 'EF FF F8 EC E3 FF F7 EC E3 FF F5 EB E2 FF F2 E9' - 'E0 FF F0 E7 DE FF ED E4 DB FF E9 DF D6 FF E5 DA' - 'D2 FF E1 D5 CC FF DC D0 C7 FF DB D6 D3 FF B0 B0' - 'B1 FF 08 08 08 AB 48 48 49 F1 FD FE FF FF CF 91' - '67 FF CA 71 31 FF D5 85 47 FF DC 90 52 FF E0 99' - '59 FF E2 9B 5B FF E0 98 59 FF DC 90 51 FF D5 84' - '46 FF CB 76 38 FF C4 66 27 FF D4 B1 9B FF B0 B5' - 'B8 FF 08 08 08 A9 46 47 47 F0 FD FE FF FF C8 84' - '58 FF C0 5D 19 FF CA 71 30 FF D0 7B 39 FF D3 81' - '3F FF D4 83 41 FF D3 80 3E FF CF 7A 38 FF C9 6E' - '2E FF C1 61 1F FF B9 51 10 FF D2 AC 96 FF B2 B7' - 'BA FF 08 08 08 A8 45 46 46 F0 FD FE FF FF C3 7D' - '52 FF B8 52 10 FF C0 64 24 FF C5 6B 2B FF C8 70' - '30 FF C9 71 31 FF C8 6F 2F FF C4 6A 2A FF BF 61' - '21 FF B3 50 12 FF B1 44 04 FF D3 AC 96 FF B3 B9' - 'BC FF 07 07 07 A8 44 45 46 F0 FC FE FE FF BC 72' - '48 FF AE 41 02 FF B8 55 17 FF C0 63 23 FF C5 6A' - '2B FF C6 6C 2D FF C5 6B 2B FF C2 63 23 FF B0 5E' - '28 FF BD A9 9D FF A3 61 3D FF D1 A6 8E FF B5 BB' - 'BD FF 06 06 06 A8 43 43 44 F0 FC FD FD FF B7 6D' - '42 FF B1 47 08 FF C5 6A 2B FF CC 76 36 FF D0 7C' - '3B FF D1 7E 3D FF D0 7C 3C FF CF 76 34 FF B4 71' - '41 FF D1 D5 D6 FF A8 79 5E FF CF A4 8C FF B7 BC' - 'BF FF 06 06 06 A8 41 42 43 F0 FA FA FB FF BE 78' - '4D FF C6 69 26 FF D1 7D 3D FF D6 86 45 FF DA 8D' - '4B FF DB 8F 4E FF DB 8D 4C FF D8 88 46 FF CB 7B' - '3E FF 9F 69 41 FF AB 57 21 FF DA B2 9A FF B7 BC' - 'C0 FF 06 06 06 A8 40 41 41 F0 F7 F8 F9 FF C8 88' - '5C FF CF 77 33 FF D8 89 47 FF DF 95 52 FF E4 9E' - '5A FF E6 A1 5E FF E5 9F 5C FF E2 95 4F FF C8 91' - '63 FF BE BF C0 FF B2 86 65 FF E2 B9 9F FF BA C0' - 'C3 FF 05 05 05 A8 3F 40 40 F0 F7 F7 F8 FF BB 79' - '4D FF CD 75 2F FF D8 8B 47 FF E1 9A 55 FF E9 A6' - '61 FF EC AD 67 FF EA A8 63 FF E5 9C 55 FF C9 8A' - '53 FF B9 AF A6 FF AE 72 49 FF E8 BF A5 FF C5 CB' - 'CE FF 04 04 04 A8 3B 3B 3B F4 FF FF FF FF DB C6' - 'BA FF E2 C5 AE FF E8 CE B7 FF EB D4 BC FF EF D9' - 'C1 FF F1 DC C4 FF EF DA C2 FF EC D5 BD FF E7 CD' - 'B6 FF DF C6 B0 FF D8 BA A7 FF F8 ED E7 FF C8 CA' - 'CB FF 02 02 02 AB 0F 0F 0F C7 AA A9 A9 FF E2 E5' - 'E7 FF DE E3 E6 FF DD E1 E5 FF DD E0 E4 FF DC E0' - 'E3 FF DC DF E3 FF DC E0 E3 FF DD E0 E4 FF DD E1' - 'E4 FF DD E0 E2 FF DE E2 E5 FF D8 DA DB FF 66 66' - '65 FF 00 00 00 78 00 00 00 2E 01 01 01 B1 0F 0F' - '0F CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E' - '0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E' - '0E CC 0E 0E 0E CC 0E 0E 0E CC 0C 0C 0C CB 00 00' - '00 8D 00 00 00 0D 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 77' - '77 77 77 77 77 80 8F FF FF FF F7 77 77 70 8F 83' - '88 88 88 83 37 70 8F 83 33 38 33 33 37 70 8F 83' - '33 33 33 33 37 70 8F 83 33 33 33 37 37 70 8F 83' - '33 33 33 87 87 70 8F 83 38 88 88 38 37 70 6F 83' - '88 87 88 87 87 70 0F 83 88 77 78 87 87 70 0F 77' - '77 77 77 77 7F 70 07 FF FF F7 FF FF F7 80 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - '00 00 80 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 80 01 00 00 FF FF 00 00 28 00' - '00 00 20 00 00 00 40 00 00 00 01 00 04 00 00 00' - '00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' - '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' - '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' - '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' - 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 87 77 77 77 77 77 77 77 77' - '77 77 77 77 80 00 00 FF FF FF FF FF FF FF FF F7' - '77 77 77 77 78 00 08 FF FF FF FF FF FF FF FF FF' - '77 77 77 77 77 00 08 FF 77 77 77 77 77 77 77 77' - '77 77 78 77 77 00 08 FF 73 33 33 38 88 88 88 83' - '33 33 33 87 77 00 08 FF 73 33 33 38 88 88 88 83' - '33 33 33 87 77 00 08 FF 73 33 33 33 38 88 83 33' - '33 33 33 87 77 00 08 FF 73 33 33 33 33 33 33 33' - '33 33 33 87 77 00 08 FF 83 33 33 33 33 33 33 33' - '33 33 31 87 78 00 08 FF 81 33 33 33 33 33 33 33' - '33 88 31 8F 78 00 08 FF 81 33 33 33 33 33 33 33' - '33 FF 71 8F 78 00 08 FF 81 13 33 33 33 33 33 33' - '38 F7 71 8F F8 00 08 FF 81 33 33 33 38 88 83 33' - '33 7F 71 8F F8 00 08 FF 83 33 33 88 88 88 88 88' - '33 33 33 8F F8 00 08 FF 83 33 38 88 88 88 88 88' - '88 88 83 8F F8 00 08 FF 83 33 88 88 88 88 88 88' - '88 77 73 8F F8 00 08 FF 83 38 88 88 77 77 77 88' - '88 7F 73 8F F8 00 08 FF 83 38 88 87 77 77 77 78' - '88 77 83 8F F8 00 08 FF 83 88 88 87 77 77 77 77' - '88 88 83 8F F8 00 08 FF F7 77 77 77 77 77 77 77' - '77 77 77 FF F8 00 00 FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF F8 00 00 87 77 77 77 77 77 77 77 77' - '77 77 77 77 80 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF 80 00 00 03 80 00 00 01 00 00' - '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' - '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' - '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' - '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' - '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' - '00 01 80 00 00 03 E0 00 00 0F FF FF FF FF FF FF' - 'FF FF FF FF FF FF 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 11 11 11 00 66 33 00 00 66 33 33 00 66 66' - '33 00 44 44 44 00 55 55 55 00 66 66 66 00 77 77' - '77 00 7F 7F 7F 00 99 33 00 00 99 33 33 00 CC 33' - '00 00 CC 33 33 00 99 66 00 00 99 66 33 00 CC 66' - '00 00 CC 66 33 00 FF 66 33 00 99 66 66 00 CC 66' - '66 00 FF 66 66 00 99 99 33 00 CC 99 33 00 FF 99' - '33 00 FF CC 33 00 99 99 66 00 CC 99 66 00 FF 99' - '66 00 CC CC 66 00 FF CC 66 00 88 88 88 00 99 99' - '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF 99' - '99 00 99 CC 99 00 CC CC 99 00 FF CC 99 00 99 CC' - 'CC 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 FF FF' - 'CC 00 CC CC FF 00 FF CC FF 00 CC FF FF 00 EE EE' - 'EE 00 FF FF FF 00 00 00 00 00 A8 44 F9 77 21 00' - '00 00 B8 0C 38 00 00 00 38 00 F0 B5 0C 01 14 17' - '95 00 00 00 00 00 5C 19 95 00 28 52 0C 01 68 19' - '95 00 77 82 F5 77 98 7F F5 77 3A 8A F5 77 00 04' - '00 00 90 A2 AF 00 10 00 00 00 10 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' - 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' - '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' - 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' - 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' - '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' - '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' - '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 28 81 0C 01 10 AE 0C 01 20 81' - '0C 01 78 01 38 00 78 01 38 00 38 02 38 00 38 56' - '0C 01 01 00 00 00 03 00 00 00 38 02 38 00 F0 56' - '0C 01 F0 56 0C 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' - '00 00 00 00 00 00 58 00 5A 00 30 56 0C 01 30 56' - '0C 01 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' - 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 28 52' - '0C 01 A4 18 95 00 E5 3A F8 77 18 00 00 00 30 56' - '0C 01 00 00 38 00 28 52 0C 01 00 00 00 00 78 19' - '95 00 CA 8C F5 77 78 01 38 00 BE 8E F5 77 08 06' - '38 00 37 90 F5 77 30 52 0C 01 30 52 0C 01 40 00' - '00 00 40 00 00 00 01 00 00 00 18 00 00 00 00 00' - '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' - '95 00 00 00 00 00 00 00 00 00 00 00 00 00 28 52' - '0C 01 28 52 0C 01 01 01 F5 77 78 01 38 00 30 52' - '0C 01 20 81 0C 01 28 81 0C 01 78 01 38 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 BE B3' - 'E7 77 28 52 0C 01 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 08 04 00 00 99 00' - '00 00 08 04 00 00 08 01 00 00 00 00 00 00 00 00' - '00 00 00 00 01 01 00 00 38 00 BC 18 95 00 C0 18' - '95 00 B0 19 95 00 F0 88 FA 77 88 1C F5 77 FF FF' - 'FF FF 37 90 F5 77 81 E9 49 00 00 00 38 00 00 00' - '00 00 30 52 0C 01 30 52 0C 01 A4 1A 95 00 40 00' - '00 00 40 00 00 00 B8 10 E9 77 FF FF FF FF C9 F1' - 'E7 77 16 EA 4B 00 F8 00 00 00 B4 1A 95 00 DC E3' - '49 00 E0 A3 4E 00 FF FF FF FF 10 00 00 00 10 DA' - '4B 00 30 52 0C 01 71 CC 43 00 30 52 0C 01 F0 B5' - '0C 01 A4 1A 95 00 90 A2 AF 00 C4 F5 AF 00 06 00' - '00 00 F0 B5 0C 01 0F 02 00 00 70 52 0C 01 10 00' - '00 00 00 00 00 00 20 00 00 00 30 52 0C 01 40 00' - '00 00 10 00 00 00 00 01 00 00 00 04 00 00 00 00' - '00 00 00 00 00 00 10 00 00 00 10 00 00 00 28 00' - '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' - '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 00 00 00 00 00 00' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 00 00 00 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 00 32 32' - '32 32 05 08 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F' - '1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F' - '1F 1F 1F 1F 1F 1F 1F 08 06 32 32 32 32 32 32 32' - '32 1F 31 31 31 31 31 31 31 31 30 31 30 30 30 30' - '30 30 30 2A 30 2A 30 2A 2A 2A 2A 2A 2A 2A 2A 2A' - '29 2A 29 29 29 29 29 29 30 20 01 32 32 32 32 32' - '05 31 31 31 30 31 30 30 30 30 30 30 30 30 2A 30' - '30 2A 2A 30 2A 2A 2A 2A 2A 2A 2A 29 2A 29 29 29' - '29 29 29 29 29 29 22 29 22 30 07 32 32 32 32 32' - '08 31 31 30 31 30 30 31 30 30 30 30 30 2A 30 2A' - '2A 30 2A 2A 2A 2A 2B 2A 2A 29 2A 29 2A 29 29 29' - '29 29 29 29 29 22 29 22 22 2A 21 32 32 32 32 32' - '20 31 31 31 31 31 31 31 31 31 31 31 30 31 31 31' - '2E 2F 31 30 30 31 2F 30 30 31 2A 2C 2D 31 30 30' - '30 30 30 2A 2E 2C 2A 29 29 29 21 32 32 32 32 32' - '1F 31 31 31 2A 1B 1C 1B 1B 1B 23 1B 24 27 1B 26' - '1E 24 1E 26 24 1D 24 27 1E 23 27 24 1E 23 1C 1D' - '23 1B 1B 1C 1B 1B 2A 29 22 2A 21 32 32 32 32 32' - '1F 31 31 31 29 11 0E 11 11 17 11 17 17 11 1C 11' - '1B 18 1B 1C 17 1C 1B 17 15 17 11 1B 11 17 11 11' - '10 11 11 0E 10 0B 2B 29 29 29 21 32 32 32 32 32' - '1F 31 31 31 2A 11 11 11 11 11 17 11 11 1B 17 1C' - '17 1B 14 17 1C 14 18 1B 17 17 1C 11 17 11 17 11' - '11 0F 11 10 0B 10 29 29 29 29 21 32 32 32 32 32' - '1F 31 31 31 2A 0F 10 11 11 11 11 17 11 11 17 11' - '1C 17 17 1C 17 17 1B 12 1B 11 17 1B 11 17 11 11' - '11 11 10 0B 10 11 26 29 29 2A 21 32 32 32 32 32' - '1F 31 31 31 29 10 0F 11 10 11 17 11 11 17 11 1B' - '17 11 1C 11 17 1B 12 1B 11 1B 11 11 17 11 11 11' - '11 10 0F 11 10 0A 2B 29 29 2A 21 32 32 32 32 32' - '1F 31 31 31 2A 11 10 0B 11 11 11 11 17 11 17 11' - '11 1B 11 17 14 11 17 11 17 11 17 11 11 11 11 10' - '11 0F 10 0A 0D 0E 29 2A 29 29 21 32 32 32 32 32' - '1F 31 31 31 2D 10 0B 10 0F 10 11 0E 11 11 11 11' - '17 11 17 11 11 17 11 17 11 17 11 0F 10 11 11 11' - '0E 11 0C 11 0E 0C 2B 29 29 2A 21 32 32 32 32 32' - '1F 31 31 31 2B 0F 10 11 0C 0F 11 11 11 11 11 11' - '11 17 11 11 17 11 17 11 11 11 11 11 11 11 0E 11' - '0D 0E 11 0A 10 0A 29 2A 29 2A 21 32 32 32 32 32' - '1F 31 31 31 29 0F 0C 0B 0E 11 0C 11 10 0F 11 11' - '11 0E 11 17 11 11 11 0F 11 11 10 11 0F 10 11 11' - '0E 10 0A 10 0A 0A 2B 2A 29 2A 21 32 32 32 32 32' - '1F 31 31 31 29 10 0A 10 0C 0F 11 0E 11 10 11 0E' - '11 11 11 10 0F 11 10 11 10 0F 11 11 10 0B 10 0A' - '0B 03 0A 0A 0C 0E 29 2A 2A 2A 20 32 32 32 32 32' - '1F 31 31 31 2A 0A 0E 0C 0F 10 0A 10 0F 0D 0E 11' - '11 11 11 11 11 11 11 11 11 11 11 10 0F 10 0A 1F' - '22 2A 25 0B 0A 0A 27 2A 29 2A 21 32 32 32 32 32' - '08 31 31 31 29 0B 0C 0E 0A 0C 11 0A 10 11 11 11' - '11 17 11 11 17 11 11 17 11 11 11 11 11 11 04 30' - '31 30 29 07 0A 0A 29 2A 29 30 20 32 32 32 32 32' - '1F 31 31 31 29 10 0A 0A 0C 0F 0A 11 11 17 11 11' - '11 11 17 11 11 17 11 11 11 17 11 11 11 10 13 30' - '29 20 30 08 0A 0A 2B 2A 2A 2A 20 32 32 32 32 32' - '1F 31 31 31 29 0A 0A 0C 0E 0C 17 11 11 11 17 11' - '17 11 11 17 15 11 17 11 1B 11 11 17 11 11 0F 29' - '31 30 31 08 02 10 22 30 29 30 20 32 32 32 32 32' - '08 31 31 31 26 0F 0C 0A 11 17 11 11 11 17 11 1B' - '11 17 17 14 17 17 14 17 11 17 17 11 17 11 0F 07' - '2A 31 21 03 0C 0A 2B 2A 2A 2A 21 32 32 32 32 32' - '1F 31 31 31 29 0A 0E 11 11 11 11 17 11 11 17 11' - '1C 11 1B 18 11 1B 18 14 17 14 17 11 14 17 11 0F' - '0F 04 03 10 0B 0A 26 30 2A 2A 20 32 32 32 32 32' - '08 31 31 31 29 0A 10 11 11 11 17 11 17 1B 12 1B' - '11 1C 17 1B 1B 17 1B 18 1B 17 15 17 17 12 17 11' - '11 0F 11 11 10 0A 2B 30 2A 30 20 32 32 32 32 32' - '08 31 31 31 22 0F 11 11 17 11 11 1B 12 17 1B 17' - '1B 17 1C 18 1B 1C 17 1B 1C 17 17 15 17 17 13 13' - '1A 1B 13 0F 11 10 29 2A 2A 30 20 32 32 32 32 32' - '08 31 31 31 22 11 11 11 11 1B 17 11 1B 12 1B 1C' - '17 1C 17 1B 1C 17 1B 1C 17 1C 1B 17 1B 11 23 20' - '21 1F 28 13 0F 10 29 30 2A 30 20 32 32 32 32 32' - '08 31 31 31 22 10 11 17 11 11 1C 17 17 1B 18 1B' - '1C 1B 1C 1B 1C 1C 1B 1B 1C 17 1C 1B 17 14 1A 29' - '2A 2A 22 13 10 0F 2B 30 2A 30 20 32 32 32 32 32' - '08 31 31 31 22 0F 11 11 1B 17 11 17 1B 1C 1B 18' - '1B 1E 1C 1B 1E 1B 1E 1C 1B 1C 1B 18 1B 18 1A 29' - '2A 29 29 1A 11 11 26 31 31 30 20 32 32 32 32 32' - '08 31 31 31 22 0D 17 11 11 1C 17 15 17 1B 1B 1C' - '1B 1C 1D 1C 1B 1E 1B 1C 1E 1B 1C 1B 1C 17 1B 29' - '2A 2A 2A 13 10 11 2B 2F 30 31 20 32 32 32 32 32' - '08 31 31 31 22 0E 11 14 17 11 1B 17 1B 1C 19 1B' - '1C 1D 1C 1C 1E 24 1E 1E 1B 1C 1D 1C 17 1C 13 20' - '29 22 21 0F 11 0C 29 31 31 31 20 32 32 32 32 32' - '08 31 31 31 21 0A 0C 17 17 17 15 17 18 1B 1C 1C' - '1E 1C 1E 1E 24 1E 1C 1C 1E 1C 1C 17 1C 17 18 11' - '16 11 0F 11 10 0A 2B 31 30 31 1F 32 32 32 32 32' - '07 31 31 31 22 1B 20 1B 23 23 1B 26 23 26 23 26' - '23 26 26 23 26 26 26 26 26 23 26 23 26 23 26 23' - '1B 23 1B 23 1F 1A 2A 31 31 31 20 32 32 32 32 32' - '08 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 31 1F 32 32 32 32 32' - '05 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 30 08 32 32 32 32 32' - '01 20 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' - '31 31 31 31 31 31 31 31 31 21 01 32 32 32 32 32' - '32 01 07 21 29 22 22 22 22 22 22 22 22 22 22 22' - '22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22' - '22 22 22 22 22 22 22 22 08 01 32 32 32 00 00 32' - '32 32 32 32 01 01 01 01 01 01 01 01 01 01 01 01' - '01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01' - '01 01 01 01 01 01 01 01 32 32 32 32 00 00 00 00' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 00 00 00 00 00' - '00 00 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' - '32 32 32 32 32 32 32 32 32 32 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 F0 00' - '00 00 00 0F 00 00 C0 00 00 00 00 03 00 00 80 00' - '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 01 00 00 80 00 00 00 00 03 00 00 C0 00' - '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' - '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' - '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 17 00 00 00 32 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' - '00 28 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 19 00 00 00 75 00 00 00 C8 00 00 00 F4 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' - '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F6 00 00' - '00 D6 00 00 00 90 00 00 00 3F 00 00 00 08 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00' - '00 C7 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 E3 00 00 00 4A 00 00' - '00 06 00 00 00 00 00 00 00 04 00 00 00 B0 00 00' - '00 FF 05 05 05 FF 47 47 47 FF 83 83 83 FF 90 90' - '90 FF 8E 8E 8E FF 8E 8E 8E FF 8E 8E 8E FF 8D 8D' - '8D FF 8D 8D 8D FF 8D 8D 8D FF 8D 8D 8D FF 8C 8C' - '8C FF 8C 8C 8C FF 8C 8C 8C FF 8B 8B 8B FF 8B 8B' - '8B FF 8B 8B 8B FF 8B 8B 8B FF 8B 8B 8B FF 8A 8A' - '8A FF 8A 8A 8A FF 8A 8A 8A FF 89 89 89 FF 89 89' - '89 FF 89 89 89 FF 89 89 89 FF 89 89 89 FF 88 88' - '88 FF 88 88 88 FF 88 88 88 FF 87 87 87 FF 87 87' - '87 FF 87 87 87 FF 87 87 87 FF 87 87 87 FF 87 87' - '87 FF 86 86 86 FF 88 88 88 FF 83 83 83 FF 53 53' - '53 FF 0B 0B 0B FF 00 00 00 FF 00 00 00 D5 00 00' - '00 34 00 00 00 01 00 00 00 52 00 00 00 FF 06 06' - '06 FF 8B 8B 8B FF FB FB FB FF FF FF FF FF FE FE' - 'FE FF FC FC FC FF FA FA FA FF F9 F9 F9 FF F8 F8' - 'F8 FF F6 F6 F6 FF F5 F5 F5 FF F4 F4 F4 FF F2 F2' - 'F2 FF F1 F1 F1 FF F0 F0 F0 FF EE EE EE FF ED ED' - 'ED FF EB EB EB FF EA EA EA FF E9 E9 E9 FF E7 E7' - 'E7 FF E5 E5 E5 FF E5 E5 E5 FF E3 E3 E3 FF E1 E1' - 'E1 FF E0 E0 E0 FF DF DF DF FF DD DD DD FF DC DC' - 'DC FF DB DB DB FF D9 D9 D9 FF D8 D8 D8 FF D6 D6' - 'D6 FF D5 D5 D5 FF D3 D3 D3 FF D2 D2 D2 FF D1 D1' - 'D1 FF CF CF CF FF CD CD CD FF D1 D1 D1 FF EA EA' - 'EA FF 98 98 98 FF 0C 0C 0C FF 00 00 00 FF 00 00' - '00 8D 00 00 00 0A 00 00 00 C3 00 00 00 FF 49 49' - '49 FF FA FA FA FF FE FE FE FF F7 F7 F7 FF F7 F7' - 'F7 FF F5 F5 F5 FF F3 F3 F3 FF F2 F2 F2 FF F0 F0' - 'F0 FF EF EF EF FF EE EE EE FF EC EC EC FF EA EA' - 'EA FF E9 E9 E9 FF E8 E8 E8 FF E6 E6 E6 FF E5 E5' - 'E5 FF E3 E3 E3 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' - 'DF FF DD DD DD FF DC DC DC FF DA DA DA FF D9 D9' - 'D9 FF D8 D8 D8 FF D6 D6 D6 FF D4 D4 D4 FF D3 D3' - 'D3 FF D2 D2 D2 FF D0 D0 D0 FF CF CF CF FF CD CD' - 'CD FF CC CC CC FF CB CB CB FF C9 C9 C9 FF C7 C7' - 'C7 FF C6 C6 C6 FF C5 C5 C5 FF C2 C2 C2 FF C2 C2' - 'C2 FF E6 E6 E6 FF 73 73 73 FF 00 00 00 FF 00 00' - '00 D4 00 00 00 27 00 00 00 F3 00 00 00 FF 84 84' - '84 FF FF FF FF FF FA FA FA FF F8 F8 F8 FF F7 F7' - 'F7 FF F6 F6 F7 FF F4 F5 F5 FF F3 F4 F4 FF F1 F2' - 'F3 FF EF F0 F1 FF EE EF F0 FF ED ED EE FF EA EB' - 'EC FF E9 EA EB FF E8 E8 E9 FF E6 E7 E7 FF E5 E6' - 'E6 FF E3 E4 E5 FF E1 E2 E3 FF E0 E1 E1 FF DF DF' - 'E0 FF DD DE DE FF DC DC DD FF DA DB DB FF D8 D9' - 'DA FF D7 D8 D9 FF D6 D6 D7 FF D4 D4 D5 FF D3 D3' - 'D4 FF D1 D2 D2 FF CF D0 D1 FF CE CF CF FF CD CD' - 'CE FF CB CC CC FF CA CB CB FF C8 C9 CA FF C6 C7' - 'C8 FF C5 C6 C7 FF C4 C4 C4 FF C5 C4 C4 FF C1 C1' - 'C1 FF D7 D7 D7 FF AD AD AD FF 00 00 00 FF 00 00' - '00 F9 00 00 00 38 00 00 00 F0 00 00 00 FF 8F 8F' - '8F FF FF FF FF FF FC FC FC FF FA FA FA FF FB FB' - 'FB FF FC FC FD FF FB FC FC FF FB FB FB FF FA FA' - 'FA FF F9 FA FA FF F9 F9 FA FF F8 F8 F9 FF F7 F8' - 'F8 FF F7 F7 F7 FF F6 F6 F6 FF F5 F5 F6 FF F4 F5' - 'F5 FF F4 F5 F5 FF F3 F4 F4 FF F3 F3 F3 FF F2 F2' - 'F3 FF F2 F2 F2 FF F1 F1 F2 FF F0 F1 F1 FF EF F0' - 'F0 FF EF EF F0 FF EE EF EF FF ED EE EE FF ED ED' - 'EE FF EC ED ED FF EB EC EC FF EB EB EC FF EA EB' - 'EB FF E9 EA EA FF E9 EA EA FF E8 E9 E9 FF E7 E8' - 'E8 FF E8 E8 E8 FF DE DE DE FF C6 C6 C6 FF C4 C4' - 'C4 FF D0 D0 D0 FF AD AD AD FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8D 8D' - '8D FF FF FF FF FF FE FE FE FF FC FC FD FF E3 E1' - 'DF FF D3 99 70 FF D6 93 65 FF D9 99 6B FF DB 9D' - '6E FF DD A1 72 FF E0 A4 76 FF E1 A8 79 FF E4 AC' - '7D FF E6 AF 80 FF E8 B2 83 FF EA B4 85 FF EB B7' - '87 FF EC B9 89 FF ED BA 8B FF EE BB 8B FF EE BB' - '8B FF EE BB 8B FF ED BA 8B FF ED B9 89 FF EB B7' - '87 FF EA B5 86 FF E9 B2 83 FF E6 AF 81 FF E5 AC' - '7E FF E3 A9 7A FF E1 A5 76 FF DF A2 74 FF DD 9E' - '70 FF DB 9A 6C FF D8 97 69 FF D6 93 65 FF D3 8E' - '60 FF D3 8F 62 FF E6 D7 CD FF C9 CC CD FF C5 C5' - 'C5 FF D2 D2 D2 FF AA AA AA FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8B 8B' - '8B FF FF FF FF FF FF FF FF FF FD FF FF FF D8 D3' - 'D1 FF BE 67 2C FF C1 5F 1B FF C5 67 25 FF C8 6C' - '29 FF CB 72 2F FF CE 77 34 FF D0 7C 38 FF D3 80' - '3D FF D6 85 41 FF D9 89 44 FF DB 8C 47 FF DD 8F' - '4B FF DE 91 4C FF DF 93 4E FF E0 95 50 FF E0 95' - '50 FF E0 94 50 FF DF 93 4E FF DE 91 4D FF DC 8F' - '49 FF DB 8B 47 FF D8 88 43 FF D5 84 40 FF D3 7F' - '3C FF D0 7B 37 FF CD 75 32 FF CA 70 2D FF C7 6C' - '29 FF C4 66 23 FF C0 60 1E FF BC 5B 1A FF B9 53' - '11 FF B9 54 13 FF DF C8 B9 FF CC CF D2 FF C6 C6' - 'C6 FF D3 D3 D3 FF AB AB AB FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8B 8B' - '8B FF FF FF FF FF FF FF FF FF FE FF FF FF DA D5' - 'D3 FF BE 6A 32 FF C1 62 21 FF C5 6A 2B FF C7 6F' - '2F FF CA 74 34 FF CD 78 38 FF CF 7D 3C FF D2 81' - '40 FF D5 84 43 FF D7 88 47 FF D8 8B 4A FF DA 8E' - '4C FF DC 90 4E FF DD 92 50 FF DD 92 51 FF DD 92' - '51 FF DD 92 50 FF DD 91 4F FF DB 8F 4E FF DA 8D' - '4B FF D9 8A 49 FF D6 87 46 FF D4 83 42 FF D2 80' - '3F FF CF 7C 3B FF CC 77 37 FF CA 73 32 FF C7 6E' - '2E FF C3 68 29 FF C1 64 24 FF BD 5F 20 FF B9 57' - '18 FF BA 57 1A FF E0 C9 BB FF CD D1 D3 FF C7 C7' - 'C7 FF D5 D5 D5 FF AA AA AA FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8A 8A' - '8A FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' - 'D3 FF BC 68 30 FF BF 5F 1E FF C3 66 27 FF C5 6B' - '2C FF C8 70 30 FF CB 74 34 FF CD 78 38 FF D0 7C' - '3B FF D2 80 3F FF D4 83 42 FF D6 85 44 FF D7 88' - '47 FF D8 8A 48 FF D9 8B 4A FF DA 8C 4B FF DA 8C' - '4B FF D9 8C 4B FF D9 8B 4A FF D8 8A 48 FF D6 87' - '46 FF D5 85 44 FF D4 82 41 FF D1 7E 3E FF D0 7B' - '3B FF CD 77 37 FF CA 73 33 FF C8 6E 2F FF C5 6A' - '2B FF C2 65 26 FF BF 60 21 FF BC 5B 1C FF B7 53' - '15 FF B8 55 18 FF E0 C9 BB FF CE D2 D4 FF C9 C9' - 'C9 FF D6 D6 D6 FF AA AA AA FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8A 8A' - '8A FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' - 'D3 FF BA 65 2D FF BD 5B 1B FF C0 63 24 FF C2 67' - '28 FF C5 6C 2C FF C8 70 30 FF CA 73 34 FF CD 77' - '37 FF CF 7B 3A FF D1 7D 3D FF D2 80 3F FF D4 83' - '42 FF D5 84 43 FF D6 86 45 FF D6 86 45 FF D6 86' - '45 FF D6 86 45 FF D5 85 44 FF D5 84 43 FF D3 82' - '41 FF D2 80 3F FF D1 7D 3C FF CF 7A 39 FF CD 76' - '36 FF CA 73 33 FF C7 6F 2F FF C5 6A 2B FF C2 66' - '27 FF BF 61 22 FF BC 5D 1E FF B9 58 19 FF B5 50' - '12 FF B6 52 15 FF E0 C9 BB FF D0 D4 D6 FF CB CB' - 'CB FF D7 D7 D7 FF A9 A9 A9 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 89 89' - '89 FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' - 'D3 FF B8 62 2A FF BA 57 17 FF BE 5E 20 FF C0 63' - '24 FF C3 67 28 FF C6 6B 2C FF C8 6F 2F FF CA 72' - '32 FF CC 76 35 FF CD 78 38 FF CF 7B 3A FF D0 7D' - '3C FF D1 7E 3D FF D2 80 3F FF D2 80 3F FF D2 80' - '3F FF D2 80 3F FF D2 7F 3E FF D1 7E 3E FF CF 7C' - '3C FF CE 7A 3A FF CD 77 37 FF CB 74 34 FF CA 71' - '32 FF C7 6E 2E FF C5 6A 2B FF C3 66 27 FF C0 62' - '23 FF BD 5D 1F FF BB 59 1A FF B7 54 16 FF B3 4D' - '0F FF B5 4E 11 FF E0 C9 BA FF D1 D5 D7 FF CC CC' - 'CC FF D8 D8 D8 FF A8 A8 A8 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 88 88' - '88 FF FF FF FF FF FF FF FF FF FF FF FF FF DA D5' - 'D3 FF B6 5E 27 FF B7 53 13 FF BB 5A 1C FF BD 5F' - '20 FF C0 63 24 FF C3 66 27 FF C5 6A 2A FF C7 6D' - '2E FF C9 71 31 FF CA 73 33 FF CC 75 35 FF CD 77' - '37 FF CE 79 38 FF CF 7A 3A FF CF 7B 3A FF CF 7B' - '3A FF CF 7A 3A FF CE 7A 39 FF CE 78 38 FF CC 77' - '36 FF CB 75 35 FF CA 72 32 FF C8 6F 2F FF C7 6D' - '2E FF C4 69 2A FF C2 65 26 FF C0 62 23 FF BD 5E' - '1F FF BA 59 1B FF B8 55 17 FF B5 51 13 FF B1 4A' - '0B FF B2 4B 0E FF E0 C8 BA FF D2 D6 D8 FF CD CD' - 'CD FF D9 D9 D9 FF A7 A7 A7 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 87 87' - '87 FF FF FF FF FF FF FF FF FF FF FF FF FF D8 D4' - 'D1 FF B4 5A 23 FF B5 4E 0F FF B9 56 18 FF BB 5A' - '1B FF BD 5E 1F FF C0 62 23 FF C2 65 25 FF C3 68' - '29 FF C6 6B 2C FF C7 6D 2E FF C8 70 30 FF C9 71' - '31 FF CA 73 32 FF CB 74 34 FF CB 75 34 FF CB 75' - '34 FF CB 74 34 FF CB 74 33 FF CA 72 32 FF C9 71' - '31 FF C8 6F 2F FF C6 6D 2D FF C5 6A 2A FF C3 67' - '28 FF C1 64 25 FF BE 60 22 FF BD 5D 1E FF BA 59' - '1A FF B8 55 17 FF B6 51 13 FF B3 4C 0F FF AF 46' - '07 FF AF 47 0A FF DF C7 BA FF D4 D8 DB FF CF CF' - 'CF FF DB DB DB FF A6 A6 A6 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 86 86' - '86 FF FF FF FF FF FF FF FF FF FF FF FF FF D6 D1' - 'CE FF B1 55 1E FF B2 4A 0B FF B6 51 13 FF B7 54' - '16 FF BA 59 1A FF BC 5D 1E FF BE 60 20 FF BF 62' - '23 FF C2 65 26 FF C3 67 28 FF C4 69 2A FF C5 6B' - '2B FF C6 6C 2C FF C7 6D 2E FF C7 6E 2E FF C7 6E' - '2E FF C7 6E 2E FF C6 6D 2E FF C6 6C 2C FF C5 6A' - '2B FF C4 69 29 FF C3 67 28 FF C1 64 25 FF BF 62' - '23 FF BE 5F 20 FF BC 5C 1D FF BC 58 19 FF BD 54' - '12 FF BA 4F 0D FF B7 4C 0C FF B0 48 0A FF AC 41' - '03 FF AD 43 07 FF DF C7 BA FF D6 DA DC FF D0 D0' - 'D0 FF DC DC DC FF A5 A5 A5 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 85 85' - '85 FF FF FF FF FF FF FF FF FF FF FF FF FF D4 CF' - 'CC FF AE 51 1A FF B0 45 06 FF B3 4D 0F FF B4 50' - '12 FF B7 54 16 FF B9 58 19 FF BB 5A 1C FF BC 5D' - '1F FF BE 60 21 FF BF 62 23 FF C0 63 24 FF C1 65' - '25 FF C3 66 26 FF C3 68 28 FF C3 68 29 FF C3 68' - '29 FF C3 68 29 FF C3 67 28 FF C3 66 27 FF C1 65' - '25 FF C0 63 23 FF BF 61 22 FF BD 5E 1F FF BC 5D' - '1E FF BA 5A 1B FF BB 56 17 FF A5 46 0C FF 7D 43' - '1F FF 77 46 27 FF 8D 3B 0B FF AE 41 02 FF AB 3E' - '00 FF AC 42 06 FF E0 C8 BA FF D7 DB DD FF D2 D2' - 'D2 FF DD DD DD FF A3 A3 A3 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 84 84' - '84 FF FF FF FF FF FF FF FF FF FF FF FF FF D1 CD' - 'CA FF AB 4D 16 FF AC 40 01 FF B0 48 0B FF B2 4C' - '0E FF B4 4F 11 FF B6 52 14 FF B7 54 16 FF B8 57' - '18 FF BA 58 1A FF BD 5D 1E FF C0 63 24 FF C3 67' - '27 FF C4 69 29 FF C5 6B 2B FF C5 6B 2C FF C6 6C' - '2C FF C6 6C 2C FF C5 6B 2C FF C5 6B 2B FF C4 69' - '29 FF C2 67 28 FF C1 64 25 FF BE 5F 20 FF BA 59' - '1A FF BA 53 13 FF 97 45 12 FF 9B 8E 85 FF C5 CB' - 'CF FF D3 DB E0 FF AC AD AD FF 83 44 21 FF A9 38' - '00 FF AC 42 06 FF E0 C8 BB FF D8 DC DE FF D3 D3' - 'D3 FF DF DF DF FF A3 A3 A3 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 83 83' - '83 FF FF FF FF FF FF FF FF FF FF FF FF FF CF CA' - 'C7 FF A8 4A 14 FF A9 3C 00 FF AD 43 06 FF B0 47' - '09 FF B1 4A 0B FF B2 4B 0E FF B4 4F 11 FF B8 56' - '18 FF BF 62 22 FF C4 6A 2A FF C7 6E 2E FF C8 70' - '2F FF C9 70 30 FF CA 72 32 FF CA 72 32 FF CA 72' - '32 FF CA 72 32 FF CA 72 32 FF C9 71 31 FF C9 70' - '30 FF C8 6F 2F FF C7 6E 2E FF C5 6B 2C FF C3 67' - '28 FF C0 5B 18 FF 8D 5B 3C FF EA F2 F7 FF F6 F5' - 'F6 FF E6 E5 E4 FF CD D2 D4 FF 6C 64 5E FF 91 2D' - '00 FF AF 43 06 FF E1 C9 BB FF D9 DD E0 FF D4 D4' - 'D4 FF E0 E0 E0 FF A2 A2 A2 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 82 82' - '82 FF FF FF FF FF FF FF FF FF FF FF FF FF CD C8' - 'C5 FF A8 4A 13 FF A9 3B 00 FF AA 3E 02 FF AA 3F' - '02 FF AD 44 07 FF B9 57 18 FF C1 64 24 FF C6 6C' - '2C FF C9 70 30 FF C9 72 32 FF CA 74 34 FF CC 75' - '35 FF CC 76 36 FF CD 78 37 FF CD 78 38 FF CE 79' - '38 FF CE 79 38 FF CD 78 38 FF CD 77 37 FF CC 76' - '36 FF CB 75 35 FF CA 73 33 FF C9 71 31 FF C8 6F' - '30 FF C3 66 24 FF 8C 6B 54 FF DC E2 E6 FF D1 CE' - 'CC FF B1 A5 9F FF E0 E2 E4 FF 7C 7E 80 FF 74 25' - '00 FF B2 44 05 FF E1 C9 BB FF DB DF E1 FF D5 D5' - 'D5 FF E1 E1 E1 FF A1 A1 A1 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 81 81' - '81 FF FF FF FF FF FF FF FF FF FF FF FF FF CB C6' - 'C3 FF A8 49 13 FF A9 3B 00 FF A8 3C 00 FF AE 46' - '09 FF BC 5C 1E FF C7 6E 2E FF C9 70 30 FF CA 72' - '32 FF CB 75 35 FF CD 77 37 FF CE 7A 3A FF CF 7B' - '3B FF D0 7D 3C FF D1 7E 3E FF D1 7F 3E FF D2 7F' - '3E FF D2 7F 3E FF D1 7E 3E FF D1 7E 3D FF D0 7C' - '3C FF CF 7B 3B FF CE 79 39 FF CC 77 36 FF CC 75' - '34 FF CB 6F 2C FF 89 60 42 FF CA D0 D5 FF F2 F2' - 'F2 FF F2 F1 F0 FF FF FF FF FF 7C 72 6D FF 89 29' - '00 FF AF 43 06 FF E2 CA BC FF DD E1 E3 FF D7 D7' - 'D7 FF E2 E2 E2 FF A0 A0 A0 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 80 80' - '80 FF FF FF FF FF FF FF FF FF FF FF FF FF C9 C4' - 'C1 FF A7 48 13 FF A7 39 00 FF B0 49 0B FF C3 68' - '28 FF C7 6F 2F FF C9 71 31 FF CA 74 34 FF CC 77' - '37 FF CE 7A 3A FF D0 7C 3C FF D1 7F 3E FF D2 81' - '40 FF D4 82 41 FF D5 84 43 FF D5 85 44 FF D5 85' - '44 FF D5 85 44 FF D5 84 43 FF D4 84 43 FF D3 82' - '41 FF D2 81 40 FF D1 7F 3E FF CF 7C 3B FF CE 7A' - '39 FF D1 79 37 FF A6 5D 27 FF 6A 65 62 FF E0 E6' - 'EB FF F5 FA FE FF A6 AE B3 FF 79 3C 18 FF AC 39' - '00 FF AC 42 06 FF E2 CA BC FF DE E2 E4 FF D8 D8' - 'D8 FF E4 E4 E4 FF 9E 9E 9E FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7E 7E' - '7E FF FF FF FF FF FF FF FF FF FF FF FF FF C7 C2' - 'C0 FF A5 46 11 FF AE 42 05 FF C2 67 27 FF C7 6E' - '2F FF C9 71 31 FF CB 75 35 FF CD 78 38 FF D0 7C' - '3B FF D2 7F 3F FF D3 82 41 FF D4 84 43 FF D6 86' - '46 FF D7 88 47 FF D8 89 48 FF D8 8A 49 FF D8 8B' - '49 FF D8 8B 49 FF D8 8A 49 FF D8 89 48 FF D6 87' - '47 FF D5 86 45 FF D4 84 43 FF D2 81 3F FF D1 7F' - '3D FF CF 7B 3B FF D2 79 37 FF 9C 56 23 FF 7A 59' - '40 FF 81 63 4D FF 74 41 1E FF B8 5B 1D FF B2 48' - '09 FF AB 41 04 FF E2 CA BC FF DF E3 E5 FF DA DA' - 'DA FF E5 E5 E5 FF 9E 9E 9E FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7D 7D' - '7D FF FF FF FF FF FF FF FF FF FF FF FF FF C5 BF' - 'BD FF A7 48 12 FF BE 5D 1C FF C8 6F 2F FF C9 71' - '31 FF CC 75 35 FF CF 79 39 FF D0 7D 3D FF D3 81' - '40 FF D5 84 43 FF D7 87 46 FF D8 8A 49 FF DA 8C' - '4B FF DB 8E 4C FF DC 90 4E FF DC 91 4F FF DC 91' - '4F FF DC 91 4F FF DC 91 4F FF DB 8F 4D FF DA 8E' - '4C FF D9 8C 4A FF D8 89 48 FF D6 86 45 FF D5 83' - '42 FF D3 81 40 FF CF 7A 38 FF D0 76 32 FF C5 6A' - '26 FF BD 61 1E FF C8 66 22 FF C8 68 27 FF BE 5D' - '1E FF AC 43 07 FF E2 CA BC FF E0 E5 E7 FF DC DC' - 'DC FF E6 E6 E6 FF 9D 9D 9D FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7B 7B' - '7B FF FF FF FF FF FF FF FF FF FF FF FF FF C1 BC' - 'B9 FF B2 5B 24 FF C7 6C 2A FF C9 70 31 FF CB 75' - '35 FF CE 79 39 FF D1 7E 3D FF D2 82 41 FF D5 85' - '44 FF D8 89 48 FF DA 8C 4B FF DC 8F 4D FF DD 92' - '50 FF DE 94 52 FF DF 96 54 FF E0 97 55 FF E0 97' - '55 FF E0 97 55 FF E0 97 54 FF DF 95 53 FF DE 94' - '52 FF DD 91 50 FF DA 8E 4D FF D9 8B 4A FF D8 88' - '47 FF D6 83 40 FF B2 7D 53 FF 96 7C 69 FF A3 86' - '70 FF AD 8E 79 FF 9A 8A 71 FF 8D 62 37 FF C3 63' - '22 FF B7 54 16 FF E2 CA BC FF E3 E6 E8 FF DD DD' - 'DD FF E7 E7 E7 FF 9B 9B 9B FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7A 7A' - '7A FF FF FF FF FF FF FF FF FF FF FF FF FF C0 BA' - 'B8 FF B8 64 2D FF C9 6E 2D FF CA 74 33 FF CD 78' - '38 FF D0 7D 3C FF D3 81 40 FF D5 85 44 FF D8 89' - '48 FF DB 8D 4C FF DD 91 4F FF DF 94 52 FF E0 97' - '55 FF E1 99 57 FF E2 9B 58 FF E3 9C 5A FF E4 9D' - '5A FF E4 9D 5A FF E3 9C 5A FF E2 9B 59 FF E1 99' - '57 FF E0 96 55 FF DE 93 51 FF DC 90 4E FF DB 8D' - '4B FF D2 80 3C FF B2 96 7F FF 96 9F A6 FF A4 A8' - 'AB FF 86 8A 8E FF A9 B9 BC FF 86 78 65 FF B9 5C' - '1C FF C1 61 23 FF E3 CB BD FF E2 E6 E8 FF DE DE' - 'DE FF E8 E8 E8 FF 9A 9A 9A FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 78 78' - '78 FF FF FF FF FF FF FF FF FF FF FF FF FF BE B8' - 'B6 FF BA 68 30 FF CB 71 2F FF CD 76 36 FF CF 7B' - '3B FF D2 80 3F FF D5 85 44 FF D7 89 48 FF DA 8E' - '4C FF DD 92 50 FF DF 96 54 FF E1 99 57 FF E3 9C' - '5A FF E5 9E 5C FF E6 A1 5E FF E7 A2 60 FF E7 A3' - '60 FF E7 A3 60 FF E7 A2 5F FF E6 A1 5E FF E4 9E' - '5B FF E3 9C 59 FF E1 98 56 FF DE 95 53 FF DD 92' - '4F FF D5 85 41 FF A9 8A 71 FF C4 C9 CD FF DC DC' - 'DC FF D7 D7 D7 FF C5 C8 CC FF 90 75 64 FF BB 5F' - '1E FF C5 67 29 FF E7 D0 C2 FF EA EE F0 FF E5 E5' - 'E5 FF EB EB EB FF 99 99 99 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 78 78' - '78 FF FF FF FF FF FF FF FF FF FF FF FF FF BA B5' - 'B2 FF B9 67 2F FF CD 74 32 FF CE 79 39 FF D1 7E' - '3E FF D4 83 42 FF D7 88 47 FF DA 8D 4B FF DD 91' - '4F FF E0 96 54 FF E1 9A 57 FF E4 9D 5B FF E6 A1' - '5E FF E8 A4 61 FF E9 A6 63 FF EA A8 65 FF EB A9' - '65 FF EB A9 65 FF EA A7 64 FF E9 A6 63 FF E7 A4' - '60 FF E6 A0 5E FF E4 9D 5A FF E1 99 57 FF DF 94' - '53 FF DF 8F 48 FF AF 89 69 FF C7 CC D0 FF D6 D6' - 'D6 FF D3 D3 D3 FF C8 CD D2 FF A0 7B 5F FF C6 68' - '24 FF C1 65 26 FF E9 D2 C4 FF F7 FB FD FF F4 F4' - 'F4 FF F6 F6 F6 FF 98 98 98 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 76 76' - '76 FF FF FF FF FF FF FF FF FF FF FF FF FF B8 B2' - 'B0 FF B3 5C 25 FF CE 77 35 FF CF 7B 3B FF D2 80' - '40 FF D5 85 44 FF D9 8A 49 FF DB 8F 4D FF DF 95' - '53 FF E2 99 57 FF E3 9E 5B FF E6 A2 5F FF E9 A6' - '63 FF EB A9 65 FF ED AC 68 FF EE AE 6A FF EF AF' - '6B FF EF AF 6B FF EE AD 6A FF ED AB 68 FF EB A8' - '66 FF E8 A5 62 FF E6 A1 5E FF E3 9D 5A FF E1 98' - '56 FF E2 94 4E FF B4 87 5F FF D1 D5 D8 FF E2 E3' - 'E4 FF E0 E1 E2 FF CE D3 D8 FF AA 79 55 FF CD 6F' - '2A FF B9 58 1A FF E8 CF C2 FF F9 FD FF FF F7 F7' - 'F7 FF F8 F8 F8 FF 97 97 97 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 75 75' - '75 FF FF FF FF FF FF FF FF FF FF FF FF FF B7 B1' - 'AF FF A5 47 10 FF C7 6A 28 FF D2 7F 3E FF D3 83' - '42 FF D7 88 47 FF DA 8D 4C FF DD 92 50 FF E0 98' - '56 FF E4 9C 5A FF E6 A1 5F FF E9 A6 63 FF EC AB' - '67 FF EE AE 6B FF F0 B1 6E FF F2 B4 71 FF F3 B5' - '72 FF F3 B5 71 FF F2 B4 70 FF F0 B1 6E FF ED AD' - '6A FF EB A9 66 FF E8 A5 62 FF E5 A0 5E FF E3 9B' - '59 FF E5 97 54 FF B9 81 50 FF A1 9D 9B FF BD BC' - 'BA FF BD BC BA FF A3 A1 A0 FF AD 70 42 FF C9 69' - '26 FF AD 43 06 FF E9 D0 C3 FF FB FE FF FF F8 F8' - 'F8 FF F9 F9 F9 FF 95 95 95 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 74 74' - '74 FF FF FF FF FF FF FF FF FF FF FF FF FF B2 AD' - 'AB FF 9C 3C 06 FF AE 45 06 FF CF 79 35 FF D6 7F' - '3A FF D9 85 3F FF DC 8A 44 FF DF 90 4A FF E3 96' - '4F FF E7 9C 54 FF EA A1 5A FF ED A7 5F FF F1 AC' - '64 FF F3 B1 68 FF F6 B5 6D FF F8 B9 70 FF FA BB' - '72 FF F9 BA 72 FF F8 B8 6F FF F5 B5 6C FF F2 AF' - '68 FF F0 AA 63 FF ED A6 5D FF E9 A0 58 FF E6 9A' - '53 FF E3 95 4E FF DE 8E 48 FF C2 79 3B FF B7 70' - '36 FF B4 6B 31 FF B6 69 2C FF C9 71 2F FF B1 4C' - '0D FF A5 39 00 FF E9 D1 C3 FF FC FF FF FF FA FA' - 'FA FF FB FB FB FF 94 94 94 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 73 73' - '73 FF FF FF FF FF FF FF FF FF FF FF FF FF C4 C3' - 'C2 FF AE 93 84 FF B1 93 83 FF C2 A0 86 FF CE A5' - '83 FF CE A7 87 FF D0 AA 89 FF D2 AD 8C FF D3 B0' - '8E FF D5 B2 91 FF D7 B5 93 FF D8 B8 96 FF DA BA' - '98 FF DB BC 9B FF DD BF 9D FF DE C1 9F FF DE C2' - 'A0 FF DE C2 A0 FF DE C0 9E FF DC BE 9C FF DB BC' - '9A FF DA B9 98 FF D8 B7 95 FF D6 B4 92 FF D4 B2' - '90 FF D2 AF 8E FF D2 AC 8B FF D3 AA 88 FF D2 A8' - '85 FF D0 A5 82 FF CE A2 7F FF C1 9E 84 FF B0 92' - '82 FF B2 94 83 FF EC E5 E1 FF FD FE FE FF FC FC' - 'FC FF FC FC FC FF 94 94 94 FF 00 00 00 FF 00 00' - '00 F7 00 00 00 37 00 00 00 F4 00 00 00 FF 72 72' - '72 FF FF FF FF FF FF FF FF FF FF FF FF FF FE FE' - 'FE FF FD FF FF FF FD FF FF FF FA FF FF FF F9 FF' - 'FF FF F9 FE FF FF F9 FE FF FF F9 FE FF FF F8 FD' - 'FF FF F8 FD FF FF F8 FD FF FF F8 FC FF FF F7 FC' - 'FF FF F7 FC FF FF F7 FB FF FF F7 FB FF FF F7 FB' - 'FF FF F7 FB FF FF F7 FB FF FF F7 FB FF FF F7 FC' - 'FF FF F7 FC FF FF F8 FC FF FF F7 FC FF FF F7 FC' - 'FF FF F7 FC FF FF F8 FD FF FF F7 FD FF FF F7 FD' - 'FF FF F7 FD FF FF F7 FD FF FF F8 FD FF FF FA FF' - 'FF FF FA FF FF FF FC FD FD FF FB FB FB FF FD FD' - 'FD FF FB FB FB FF 93 93 93 FF 00 00 00 FF 00 00' - '00 FA 00 00 00 37 00 00 00 DD 00 00 00 FF 4B 4B' - '4B FF F5 F5 F5 FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FE FE FE FF FE FE FE FF FD FD FD FF FF FF' - 'FF FF F0 F0 F0 FF 6D 6D 6D FF 00 00 00 FF 00 00' - '00 E7 00 00 00 27 00 00 00 7A 00 00 00 FF 0E 0E' - '0E FF 9A 9A 9A FF FD FD FD FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF F8 F8' - 'F8 FF A4 A4 A4 FF 1B 1B 1B FF 00 00 00 FF 00 00' - '00 9B 00 00 00 04 00 00 00 0F 00 00 00 D8 00 00' - '00 FF 14 14 14 FF 6E 6E 6E FF AC AC AC FF B9 B9' - 'B9 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' - 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' - 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' - 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' - 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' - 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B7 B7' - 'B7 FF B7 B7 B7 FF B7 B7 B7 FF B6 B6 B6 FF B6 B6' - 'B6 FF B6 B6 B6 FF B5 B5 B5 FF B5 B5 B5 FF B5 B5' - 'B5 FF B4 B4 B4 FF B5 B5 B5 FF AB AB AB FF 76 76' - '76 FF 1D 1D 1D FF 00 00 00 FF 00 00 00 FA 00 00' - '00 3C 00 00 00 00 00 00 00 00 00 00 00 52 00 00' - '00 F6 00 00 00 FF 00 00 00 FF 0C 0C 0C FF 16 16' - '16 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' - '15 FF 15 15 15 FF 16 16 16 FF 10 10 10 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 6F 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 39 00 00 00 B0 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' - '00 FF 00 00 00 C1 00 00 00 51 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 49 00 00 00 80 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' - '00 84 00 00 00 84 00 00 00 84 00 00 00 82 00 00' - '00 57 00 00 00 0B 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 F0 00 00 00 00 0F 00 00 C0 00' - '00 00 00 03 00 00 80 00 00 00 00 01 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 01 00 00 80 00' - '00 00 00 03 00 00 C0 00 00 00 00 07 00 00 F0 00' - '00 00 00 0F 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' - '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' - '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' - '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' - 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 80 00 00 00 08' - 'FF FF FF FF FF FF FF FF FF FF FF FF 77 77 77 77' - '77 77 77 F8 00 00 00 8F FF FF FF FF FF FF FF FF' - 'FF 77 77 77 77 77 77 77 77 77 77 7F 80 00 00 8F' - 'FF FF FF FF FF FF FF FF FF 77 77 77 77 77 77 77' - '77 77 77 77 70 00 00 8F FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF 77 77 70 00 00 8F' - 'FF F8 88 87 77 77 77 77 77 77 77 77 77 77 77 88' - '88 88 77 77 70 00 00 8F FF 73 33 33 33 38 88 88' - '88 88 88 88 83 33 33 33 33 33 77 77 70 00 00 8F' - 'FF 73 33 33 33 38 88 88 88 88 88 88 88 33 33 33' - '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 88 88' - '88 88 88 88 83 33 33 33 33 33 77 77 70 00 00 8F' - 'FF 73 33 33 33 33 33 88 88 88 88 83 33 33 33 33' - '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' - '33 33 33 33 33 33 33 33 33 33 77 77 70 00 00 8F' - 'FF 73 33 33 33 33 33 33 33 33 33 33 33 33 33 33' - '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' - '33 33 33 33 33 33 33 33 33 33 77 77 70 00 00 8F' - 'FF 73 33 33 33 33 33 33 33 33 33 33 33 33 33 33' - '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' - '33 33 33 33 33 33 33 33 13 13 77 77 70 00 00 8F' - 'FF 73 13 33 33 33 33 33 33 33 33 33 33 33 38 77' - '73 13 77 77 70 00 00 8F FF 73 13 33 33 33 33 33' - '33 33 33 33 33 33 3F FF 78 13 77 7F 70 00 00 8F' - 'FF 73 11 13 33 33 33 33 33 33 33 33 33 33 8F 77' - 'F8 13 77 7F 70 00 00 8F FF 73 11 33 33 33 33 33' - '33 33 33 33 33 33 87 FF F8 13 7F 7F 70 00 00 8F' - 'FF 73 13 33 33 33 33 38 88 88 88 83 33 33 38 FF' - '71 13 7F 7F 80 00 00 8F FF 73 33 33 33 33 88 88' - '88 88 88 88 83 33 33 38 33 33 7F 7F 80 00 00 8F' - 'FF 73 33 33 33 38 88 88 88 88 88 88 88 83 33 33' - '33 33 7F 7F 80 00 00 8F FF 73 33 33 38 88 88 88' - '88 88 88 88 88 83 88 88 83 33 7F 7F 80 00 00 8F' - 'FF 73 33 33 38 88 88 88 88 88 88 88 88 83 88 78' - '78 33 7F 7F 80 00 00 8F FF 73 33 33 88 88 88 88' - '77 77 77 88 88 88 87 77 78 33 7F FF 80 00 00 8F' - 'FF 73 33 38 88 88 88 77 77 77 77 77 88 88 87 77' - '78 33 7F FF 80 00 00 8F FF 73 33 38 88 88 87 77' - '77 77 77 77 78 88 87 FF 78 33 7F FF 80 00 00 8F' - 'FF 73 33 88 88 88 77 77 77 77 77 77 77 88 88 77' - '78 33 7F FF 80 00 00 8F FF 71 33 33 88 88 77 77' - '77 77 77 77 77 88 83 33 33 31 7F FF 80 00 00 8F' - 'FF 78 87 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 88 FF FF 80 00 00 8F FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF 80 00 00 8F' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF 80 00 00 08 FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 00' - '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77' - '77 77 77 80 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 E0 00 00 00 00 0F 00 00 C0 00' - '00 00 00 07 00 00 80 00 00 00 00 03 00 00 80 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 01 00 00 00 00 00 00 00 01 00 00 80 00' - '00 00 00 03 00 00 C0 00 00 00 00 03 00 00 E0 00' - '00 00 00 0F 00 00 F8 00 00 00 00 3F 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' - 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00' -} */ - - - - -/*--------------------- END FIXME ------------------------*/ - -/* - * Everything that does not depend on language, - * like textless bitmaps etc, go into the - * neutral language. This will prevent them from - * being duplicated for each language. - */ -#include "shell32_xx.rc" - -/* - * Everything specific to any language goes - * in one of the specific files. - * Note that you can and may override resources - * which also have a neutral version. This is to - * get localized bitmaps for example. - */ -#include "shell32_Ca.rc" -#include "shell32_Cn.rc" -#include "shell32_Cs.rc" -#include "shell32_Da.rc" -#include "shell32_De.rc" -#include "shell32_En.rc" -#include "shell32_Eo.rc" -#include "shell32_Es.rc" -#include "shell32_Fi.rc" -#include "shell32_Fr.rc" -#include "shell32_Hu.rc" -#include "shell32_It.rc" -#include "shell32_Ja.rc" -#include "shell32_Ko.rc" -#include "shell32_Nl.rc" -#include "shell32_No.rc" -#include "shell32_Pl.rc" -#include "shell32_Pt.rc" -#include "shell32_Ru.rc" -#include "shell32_Si.rc" -#include "shell32_Sk.rc" -#include "shell32_Sv.rc" -#include "shell32_Uk.rc" -#include "shell32_Wa.rc" -#include "shell32_Zh.rc" +/* + * Top level resource file for shell stuff + * + * Copyright 1998 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winnls.h" +#include "wingdi.h" +#include "shlobj.h" +#include "shresdef.h" + +#include "version.rc" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +shv_accel ACCELERATORS +BEGIN + VK_F5, FCIDM_SHVIEW_REFRESH, VIRTKEY +END + +/* BINRES document.ico */ +1 ICON document.ico +/* { + '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 11 11 00 22 22 22 00 33 33 33 00 55 55' + '55 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 88 88' + '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC CC' + 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' + '00 00 33 00 32 00 5C 00 64 00 6F 00 63 00 75 00' + '6D 00 65 00 6E 00 74 00 2E 00 69 00 63 00 6F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 5A 00 5C 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5A 00' + '00 00 00 00 00 00 03 00 00 00 62 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 64 6F 63 75 6D 65 6E 74 2E' + '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 00 00 00 00 00 00 00 00 00 00 00 00' + '10 01 08 09 09 09 09 09 09 08 09 09 08 09 09 08' + '06 03 10 10 10 00 00 00 00 00 00 00 00 00 00 00' + '10 02 0C 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F' + '0B 08 03 10 10 10 00 00 00 00 00 00 00 00 00 00' + '10 01 0C 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0A 0C 0A 02 10 10 10 00 00 00 00 00 00 00 00 00' + '10 02 0B 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D 0E' + '0A 0D 0D 0A 02 10 10 10 00 00 00 00 00 00 00 00' + '10 01 0C 0E 0D 0D 0D 0D 0D 0D 0E 0D 0D 0E 0D 0D' + '0B 0D 0E 0E 0A 03 10 10 10 00 00 00 00 00 00 00' + '10 02 0C 0E 0D 0D 0D 0E 0D 0D 0D 0D 0E 0D 0E 0D' + '0A 0D 0F 0E 0E 09 02 10 10 00 00 00 00 00 00 00' + '10 01 0C 0E 0D 0E 0D 0D 0D 0E 0D 0E 0D 0D 0E 0D' + '0B 0D 0E 0F 0E 0F 0A 02 10 10 00 00 00 00 00 00' + '10 02 0C 0E 0D 0D 0E 0D 0E 0D 0D 0E 0E 0D 0D 0E' + '0A 0E 0F 0E 0F 0F 0F 0A 02 10 10 10 00 00 00 00' + '10 01 0C 0E 0D 0E 0E 0D 0D 0E 0E 0D 0D 0E 0E 0E' + '0A 0D 0E 0E 0E 0E 0E 0E 09 03 10 10 00 00 00 00' + '10 02 0C 0E 0E 0D 0D 0E 0E 0D 0E 0E 0E 0D 0E 0E' + '0C 0A 0B 0B 0B 0A 0B 0B 0B 06 10 10 00 00 00 00' + '10 01 0C 0F 0D 0E 0E 0D 0E 0E 0D 0E 0D 0E 0D 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0F 09 10 10 00 00 00 00' + '10 02 0C 0E 0E 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0E 08 10 10 00 00 00 00' + '10 01 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0F 0E 0E 0E 0E 0E 0F 0E 09 10 10 00 00 00 00' + '10 01 0C 0F 0E 0E 0E 0E 0F 0E 0F 0E 0E 0E 0F 0E' + '0E 0E 0E 0E 0F 0E 0F 0E 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0E 0F 0E 0F 0E 0F 0E 0F 0F 0F 0E 0F' + '0F 0E 0F 0E 0E 0E 0E 0F 0F 08 10 10 00 00 00 00' + '10 02 0C 0F 0E 0E 0F 0E 0F 0E 0F 0F 0F 0E 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0E 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0F 0E 0E 0F 0E 0F 0E 0F 0E 0F 0F 0E' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0E 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0F 0E 0F 0F 0E 0F 0F 0E 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0F 0F 0E 0F 0F 0E 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0D 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 01 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0A 10 10 00 00 00 00' + '10 02 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 09 10 10 00 00 00 00' + '10 02 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0A 10 10 00 00 00 00' + '10 01 06 08 06 06 06 06 06 06 06 06 06 06 06 06' + '06 06 05 06 05 06 05 05 06 04 10 10 00 00 00 00' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 00 00 E0 00' + '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' + '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' + '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 11 11 11 00 33 33' + '33 00 44 44 44 00 77 77 77 00 7F 7F 7F 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 CC CC CC 00 DD DD' + 'DD 00 EE EE EE 00 FF FF FF 00 00 00 00 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 33 00 32 00 5C 00' + '64 00 6F 00 63 00 75 00 6D 00 65 00 6E 00 74 00' + '2E 00 69 00 63 00 6F 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' + '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' + '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 5A 00' + '5C 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 5A 00 00 00 00 00 00 00 03 00' + '00 00 62 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' + '6F 63 75 6D 65 6E 74 2E 69 63 6F 00 4B 00 14 1A' + '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' + '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' + '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' + '95 00 00 00 00 00 00 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0D 00 00 00 00 00 00 01 07 08 08 07 08 07 08 04' + '0D 0D 00 00 00 00 00 01 09 0B 0A 0B 0B 0B 0A 09' + '06 0D 0D 00 00 00 00 01 0A 0A 0A 0A 0A 0B 0A 09' + '0C 06 0D 0D 00 00 00 01 09 0A 0B 0A 0B 0A 0A 09' + '0C 0C 06 01 0D 00 00 01 0A 0B 0A 0B 0A 0B 0A 09' + '0A 09 0A 04 0D 00 00 01 09 0B 0B 0A 0B 0B 0B 0B' + '0A 0B 0B 08 0D 00 00 01 0A 0C 0B 0B 0B 0B 0B 0B' + '0B 0B 0C 08 0D 00 00 01 0A 0B 0B 0C 0B 0C 0B 0B' + '0C 0B 0C 09 0D 00 00 01 0B 0C 0B 0C 0B 0C 0C 0C' + '0C 0C 0C 08 0D 00 00 01 09 0C 0C 0B 0C 0C 0C 0C' + '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' + '0C 0C 0C 08 0D 00 00 01 0A 0C 0C 0C 0C 0C 0C 0C' + '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' + '0C 0C 0C 09 0D 00 00 01 0B 0C 0C 0C 0C 0C 0C 0C' + '0C 0C 0C 09 0D 00 00 0D 03 03 03 03 03 03 03 02' + '03 02 03 02 0D 00 80 1F 00 00 80 0F 00 00 80 07' + '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08' + '88 87 88 78 88 78 88 88 00 00 00 00 00 00 00 00' + '7F F7 FF 7F FF 7F F7 78 80 00 00 00 00 00 00 04' + '7F 7F 77 F7 F7 F7 FF 8F 88 00 00 00 00 00 00 00' + '7F F7 FF 7F 7F 7F 7F 77 F8 80 00 00 00 00 00 08' + '7F 77 F7 F7 F7 F7 F7 77 FF 88 00 00 00 00 00 00' + '7F F7 7F 7F 7F 7F 7F 7F 7F F8 80 00 00 00 00 08' + '7F 7F F7 F7 F7 F7 F7 77 FF FF 88 00 00 00 00 00' + '7F F7 FF 7F 7F F7 FF 8F FF FF F8 80 00 00 00 08' + '7F 7F 77 F7 FF 7F F7 77 F7 F7 FF 84 00 00 00 00' + '7F F7 FF 7F 7F F7 FF 77 77 77 87 78 00 00 00 08' + '7F 7F F7 FF F7 FF 7F FF 7F F7 FF F7 00 00 00 00' + '7F F7 FF 7F 7F 7F F7 FF F7 FF F7 F8 00 00 00 08' + '7F FF F7 F7 FF F7 FF 7F 7F FF 7F F8 00 00 00 00' + '7F 7F FF FF 7F FF 7F FF F7 FF FF F8 00 00 00 04' + '7F FF 7F F7 FF 7F FF F7 FF FF F7 F7 00 00 00 00' + 'FF FF FF FF FF F7 FF FF 7F F7 FF F8 00 00 00 08' + '7F 7F F7 FF FF FF FF FF FF FF FF F8 00 00 00 00' + '7F FF FF F7 FF FF FF FF FF FF FF F8 00 00 00 08' + '7F FF FF FF FF 7F FF FF FF FF FF F7 00 00 00 00' + 'FF F7 FF FF FF FF FF FF FF FF FF F8 00 00 00 08' + '7F FF FF 7F FF FF FF FF FF FF FF F7 00 00 00 00' + '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 08' + '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' + 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 08' + '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' + 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 04' + '7F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 08' + '7F FF FF FF FF FF FF F7 FF FF FF F7 00 00 00 00' + '88 88 88 88 88 88 88 88 88 88 88 88 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 00' + '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' + '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' + '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 77' + '77 77 78 00 00 00 00 7F F7 FF 7F 80 00 00 04 7F' + '7F 7F 77 F8 00 00 00 77 F7 F7 F7 FF 70 00 00 FF' + '7F 7F 7F 7F 78 00 08 77 FF 7F F7 F7 F7 00 00 FF' + '7F FF 7F 7F F7 00 00 7F FF F7 FF FF F7 00 04 7F' + 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 00 7F' + 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 04 7F' + 'FF FF FF FF F7 00 00 FF FF FF FF FF F7 00 00 88' + '88 88 88 88 88 00 80 1F 00 00 80 0F 00 00 80 07' + '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 11 11 00 22 22 22 00 33 33 33 00 44 44' + '44 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 88 88' + '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC CC' + 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' + '00 00 33 00 32 00 5C 00 64 00 6F 00 63 00 75 00' + '6D 00 65 00 6E 00 74 00 2E 00 69 00 63 00 6F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 5A 00 5C 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5A 00' + '00 00 00 00 00 00 03 00 00 00 62 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 64 6F 63 75 6D 65 6E 74 2E' + '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 10 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 08 08 06 08 08 06 08 06 06 08 06 08' + '06 06 06 06 06 06 06 05 06 05 05 01 10 10 10 10' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0D' + '0E 0E 0E 0E 0E 0E 0E 0E 0E 0C 08 05 01 10 10 10' + '10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0E 0D' + '0D 0D 0D 0E 0D 0D 0D 0E 0E 0B 09 0A 05 01 10 10' + '10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0B 0F 0C 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0D 0D 0D 0D 0D 0D 0D 0D 0D 0B 0A 0D 0A 05 02 10' + '10 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0E 0D 0D 0D 0D 0E 0D 0D 0E 0A 0A 0E 0D 09 06 01' + '10 10 10 10 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0E 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0D 0D 0D 0D 0D 0D 0D 0E 0D 0B 0A 0E 0D 0E 0A 06' + '01 10 10 10 10 00 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0D 0D' + '0D 0D 0D 0E 0D 0D 0D 0D 0E 0B 0A 0E 0E 0E 0E 0A' + '05 01 10 10 10 10 00 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0D 0D 0D 0D 0D 0D 0E 0D' + '0D 0E 0D 0D 0D 0D 0E 0D 0E 0B 0A 0E 0E 0E 0E 0F' + '0A 06 01 10 10 10 10 00 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0E 0D 0D 0D 0E 0D 0D 0D 0D' + '0E 0D 0E 0D 0E 0D 0D 0E 0D 0B 0A 0E 0F 0E 0E 0E' + '0F 0A 05 01 10 10 10 10 00 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0D 0E 0D 0D 0D 0E 0D 0E' + '0D 0D 0D 0E 0D 0D 0E 0D 0E 0B 0A 0F 0E 0E 0F 0E' + '0F 0E 0B 05 02 10 10 10 10 00 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0D 0E 0D 0D 0E 0D 0D 0E 0D' + '0E 0D 0E 0D 0E 0E 0D 0E 0E 0B 0B 0E 0F 0E 0E 0F' + '0E 0F 0F 0B 05 01 10 10 10 10 00 00 00 00 00 00' + '00 10 10 03 0C 0F 0E 0D 0D 0D 0E 0D 0E 0D 0D 0E' + '0D 0E 0D 0E 0D 0D 0E 0D 0E 0B 0A 0F 0E 0F 0F 0F' + '0F 0F 0F 0F 0B 06 01 10 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0E 0D 0E 0D 0D 0E 0E 0D 0E' + '0D 0D 0E 0D 0E 0E 0D 0E 0E 0B 0B 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0B 05 02 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0E 0D 0E 0D 0E 0E 0D 0D 0E 0D' + '0E 0E 0D 0E 0E 0D 0E 0E 0E 0B 09 0B 0B 0B 0A 0B' + '0B 0A 0B 0A 0B 0B 09 05 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0E 0D 0D 0E 0D 0D 0E 0E 0D 0E' + '0D 0E 0E 0D 0E 0E 0E 0D 0E 0D 0C 0C 0C 0C 0C 0C' + '0C 0C 0C 0C 0B 0C 0C 06 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0E 0E 0D 0E 0E 0E 0D 0E 0E' + '0E 0E 0D 0E 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0F 0E 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0E 0D 0E 0E 0D 0E 0E 0E 0D 0E' + '0E 0D 0E 0E 0D 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0F 0D 06 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0D 0E 0E 0E 0E 0D 0E 0D 0E 0E' + '0D 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0F 0E 0E 0E 0E 0E 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0F 0D 06 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F 0E' + '0E 0E 0E 0F 0E 0E 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E' + '0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E' + '0E 0F 0E 0E 0E 0F 0E 06 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0F 0E 0E 0E 0F 0E 0F 0E 0F 0E' + '0F 0E 0E 0E 0E 0E 0E 0F 0E 0E 0E 0E 0E 0E 0E 0F' + '0E 0E 0F 0E 0F 0E 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0E 0E 0E 0F 0E 0E 0E 0F 0E 0F' + '0E 0F 0E 0F 0F 0E 0F 0E 0F 0E 0F 0E 0F 0E 0E 0E' + '0F 0E 0E 0E 0E 0F 0E 06 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0E 0E 0F 0E 0E 0E 0F 0E 0F 0E' + '0F 0E 0F 0F 0E 0F 0F 0F 0E 0F 0F 0F 0E 0F 0E 0F' + '0E 0F 0E 0F 0F 0E 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0E 0E 0E 0F 0E 0F 0E 0E 0F 0F' + '0E 0F 0F 0E 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F 0F 0E' + '0F 0E 0E 0E 0F 0F 0E 06 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0E 0F 0E 0F 0E 0F 0F 0F 0E' + '0F 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0E 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0E 0F 0E 0F 0E 0F 0E 0F 0E 0F' + '0F 0E 0F 0E 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 06 01 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0E 0E 0F 0F 0E 0F 0E 0F 0E' + '0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0E 0F 0F 0E 0E 0F 0F 0F 0F 0F' + '0E 0F 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 06 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0F 0E 0F 0F 0F 0E 0F 0F 0E' + '0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0E 0F 0F 0E 0F 0F 0F 0E 0F 0F' + '0F 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0C 0F 0F 0E 0F 0F 0F 0E 0F 0F 0F 0F' + '0F 0E 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0F 0F 0E 0F 0F 0F 0F 0F 0E 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0F 0E 0F 0F 0F 0F 0E 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0F 0F 0F 0E 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0F 0F 0E 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 03 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0C 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0E 08 10 10 10 00 00 00 00 00' + '00 10 10 04 0D 0F 0F 0F 0F 0F 0F 0F 0F 0E 0F 0F' + '0E 0F 0E 0F 0E 0F 0F 0E 0F 0E 0F 0F 0F 0F 0E 0F' + '0F 0F 0E 0F 0E 0F 0E 09 10 10 10 00 00 00 00 00' + '00 10 10 02 0A 09 09 09 09 09 09 09 09 09 09 09' + '09 09 09 08 09 09 08 09 08 09 08 08 08 08 08 08' + '08 08 08 08 08 08 08 05 10 10 10 00 00 00 00 00' + '00 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 00 00 00 00 00' + '00 00 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10' + '10 10 10 10 10 10 10 10 10 10 00 00 00 00 F0 00' + '00 01 FF FF 00 00 E0 00 00 00 FF FF 00 00 E0 00' + '00 00 7F FF 00 00 E0 00 00 00 3F FF 00 00 E0 00' + '00 00 1F FF 00 00 E0 00 00 00 0F FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 03 FF 00 00 E0 00' + '00 00 01 FF 00 00 E0 00 00 00 00 FF 00 00 E0 00' + '00 00 00 7F 00 00 E0 00 00 00 00 3F 00 00 E0 00' + '00 00 00 1F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 04 00 00 00 29 00 00' + '00 38 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 38 00 00 00 34 00 00 00 19 00 00' + '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 01 00 00 00 76 00 00 00 F1 00 00' + '00 F9 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F8 00 00 00 F2 00 00 00 B2 00 00' + '00 49 00 00 00 05 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 5A 00 00 00 FF 01 01 01 FF 06 06' + '06 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' + '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' + '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 05 05' + '05 FF 05 05 05 FF 05 05 05 FF 05 05 05 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 03 03 03 FF 02 02' + '02 FF 03 03 03 FF 02 02 02 FF 00 00 00 FF 00 00' + '00 D9 00 00 00 39 00 00 00 06 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 2E 2E 2E FF 88 88' + '88 FF 87 87 87 FF 86 86 86 FF 86 86 86 FF 85 85' + '85 FF 84 84 84 FF 84 84 84 FF 83 83 83 FF 82 82' + '82 FF 82 82 82 FF 81 81 81 FF 80 80 80 FF 7F 7F' + '7F FF 7F 7F 7F FF 7E 7E 7E FF 7D 7D 7D FF 7C 7C' + '7C FF 7C 7C 7C FF 7B 7B 7B FF 74 74 74 FF 72 72' + '72 FF 73 73 73 FF 67 67 67 FF 18 18 18 FF 00 00' + '00 FF 00 00 00 D9 00 00 00 58 00 00 00 03 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF C1 C1' + 'C1 FF F2 F2 F2 FF EA EA EA FF EA EA EA FF EA EA' + 'EA FF EA EA EA FF E9 E9 E9 FF E9 E9 E9 FF E9 E9' + 'E9 FF E9 E9 E9 FF E9 E9 E9 FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF E9 E9 E9 FF EB EB EB FF EA EA' + 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF F1 F1' + 'F1 FF C4 C4 C4 FF 8C 8C 8C FF 67 67 67 FF 15 15' + '15 FF 00 00 00 FF 00 00 00 DC 00 00 00 4C 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C8 C8' + 'C8 FF FA FA FA FF DD DD DD FF DE DE DE FF DE DE' + 'DE FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' + 'E2 FF E2 E2 E2 FF E2 E2 E2 FF E3 E3 E3 FF E8 E8' + 'E8 FF BA BA BA FF A3 A3 A3 FF A6 A6 A6 FF 6B 6B' + '6B FF 0B 0B 0B FF 00 00 00 FF 00 00 00 EB 00 00' + '00 4B 00 00 00 03 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C7 C7' + 'C7 FF F9 F9 F9 FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DB DB DB FF DB DB DB FF DB DB' + 'DB FF DC DC DC FF DC DC DC FF DC DC DC FF DC DC' + 'DC FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF E3 E3' + 'E3 FF B7 B7 B7 FF A8 A8 A8 FF DE DE DE FF A8 A8' + 'A8 FF 6C 6C 6C FF 25 25 25 FF 00 00 00 FF 00 00' + '00 DE 00 00 00 57 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 35 35 35 FF C7 C7' + 'C7 FF F9 F9 F9 FF DC DC DC FF DB DB DB FF DB DB' + 'DB FF DC DC DC FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DE DE' + 'DE FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E5 E5' + 'E5 FF B8 B8 B8 FF A7 A7 A7 FF EB EB EB FF DE DE' + 'DE FF A4 A4 A4 FF 72 72 72 FF 17 17 17 FF 00 00' + '00 FF 00 00 00 DC 00 00 00 4C 00 00 00 06 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 36 36 36 FF C8 C8' + 'C8 FF FA FA FA FF DC DC DC FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E6 E6' + 'E6 FF B9 B9 B9 FF A9 A9 A9 FF EA EA EA FF EA EA' + 'EA FF E9 E9 E9 FF B1 B1 B1 FF 72 72 72 FF 14 14' + '14 FF 00 00 00 FF 00 00 00 EB 00 00 00 4B 00 00' + '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' + 'C9 FF FA FA FA FF DD DD DD FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1' + 'E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E7 E7' + 'E7 FF BA BA BA FF AA AA AA FF EC EC EC FF EA EA' + 'EA FF ED ED ED FF EA EA EA FF B2 B2 B2 FF 6A 6A' + '6A FF 1C 1C 1C FF 00 00 00 FF 00 00 00 DE 00 00' + '00 57 00 00 00 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' + 'C9 FF FA FA FA FF DF DF DF FF DE DE DE FF DF DF' + 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' + 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' + 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E8 E8' + 'E8 FF BA BA BA FF AC AC AC FF EF EF EF FF ED ED' + 'ED FF ED ED ED FF F1 F1 F1 FF F1 F1 F1 FF B1 B1' + 'B1 FF 6B 6B 6B FF 13 13 13 FF 00 00 00 FF 00 00' + '00 DC 00 00 00 46 00 00 00 05 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF C9 C9' + 'C9 FF FA FA FA FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' + 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' + 'E2 FF E2 E2 E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E9 E9' + 'E9 FF BB BB BB FF AD AD AD FF F3 F3 F3 FF F1 F1' + 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F4 F4 F4 FF F5 F5' + 'F5 FF B5 B5 B5 FF 70 70 70 FF 14 14 14 FF 00 00' + '00 FF 00 00 00 E0 00 00 00 3F 00 00 00 02 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 37 37 37 FF CA CA' + 'CA FF FB FB FB FF E1 E1 E1 FF E1 E1 E1 FF E1 E1' + 'E1 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2 E2 FF E2 E2' + 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF EA EA' + 'EA FF BC BC BC FF AF AF AF FF F5 F5 F5 FF F3 F3' + 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4 F4 FF F8 F8' + 'F8 FF F4 F4 F4 FF B6 B6 B6 FF 6C 6C 6C FF 22 22' + '22 FF 00 00 00 FF 00 00 00 D4 00 00 00 49 00 00' + '00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CA CA' + 'CA FF FB FB FB FF E2 E2 E2 FF E1 E1 E1 FF E2 E2' + 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF EB EB' + 'EB FF BC BC BC FF B1 B1 B1 FF F8 F8 F8 FF F6 F6' + 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' + 'F8 FF FC FC FC FF FC FC FC FF B5 B5 B5 FF 70 70' + '70 FF 18 18 18 FF 00 00 00 FF 00 00 00 D4 00 00' + '00 3F 00 00 00 05 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CB CB' + 'CB FF FC FC FC FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF EC EC' + 'EC FF BD BD BD FF B3 B3 B3 FF FC FC FC FF F9 F9' + 'F9 FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FF FF FF FF FF FF FF FF BA BA' + 'BA FF 75 75 75 FF 18 18 18 FF 00 00 00 FF 00 00' + '00 E0 00 00 00 3E 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CB CB' + 'CB FF FC FC FC FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF ED ED' + 'ED FF BE BE BE FF B5 B5 B5 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FB FB' + 'FB FF BE BE BE FF 6E 6E 6E FF 1C 1C 1C FF 00 00' + '00 FF 00 00 00 BB 00 00 00 1F 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 38 38 38 FF CC CC' + 'CC FF FC FC FC FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E5 E5 E5 FF E5 E5' + 'E5 FF E6 E6 E6 FF E7 E7 E7 FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF EE EE' + 'EE FF C3 C3 C3 FF 9A 9A 9A FF B9 B9 B9 FF B8 B8' + 'B8 FF B7 B7 B7 FF B7 B7 B7 FF B7 B7 B7 FF B7 B7' + 'B7 FF B6 B6 B6 FF B5 B5 B5 FF B5 B5 B5 FF B8 B8' + 'B8 FF B5 B5 B5 FF 91 91 91 FF 67 67 67 FF 01 01' + '01 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 39 39 39 FF CC CC' + 'CC FF FC FC FC FF E6 E6 E6 FF E7 E7 E7 FF E6 E6' + 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' + 'E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EB EB' + 'EB FF E2 E2 E2 FF CD CD CD FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF C9 C9 C9 FF C9 C9' + 'C9 FF C9 C9 C9 FF C9 C9 C9 FF C9 C9 C9 FF C9 C9' + 'C9 FF CD CD CD FF CC CC CC FF 7A 7A 7A FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 39 39 39 FF CC CC' + 'CC FF FC FC FC FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' + 'E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EA EA' + 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF EB EB' + 'EB FF ED ED ED FF EF EF EF FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' + 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' + 'F2 FF F6 F6 F6 FF EC EC EC FF 7A 7A 7A FF 04 04' + '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CE CE' + 'CE FF FD FD FD FF E9 E9 E9 FF E9 E9 E9 FF EA EA' + 'EA FF E9 E9 E9 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9' + 'E9 FF E9 E9 E9 FF EA EA EA FF EA EA EA FF EA EA' + 'EA FF EA EA EA FF EB EB EB FF EB EB EB FF EA EA' + 'EA FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' + 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' + 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF ED ED' + 'ED FF ED ED ED FF EE EE EE FF EF EF EF FF EF EF' + 'EF FF F2 F2 F2 FF E9 E9 E9 FF 7B 7B 7B FF 04 04' + '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CD CD' + 'CD FF FD FD FD FF EA EA EA FF EB EB EB FF EC EC' + 'EC FF ED ED ED FF EC EC EC FF E9 E9 E9 FF EA EA' + 'EA FF EA EA EA FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EC EC' + 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' + 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' + 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' + 'F0 FF F4 F4 F4 FF E9 E9 E9 FF 7B 7B 7B FF 04 04' + '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3A 3A 3A FF CE CE' + 'CE FF FE FE FE FF EC EC EC FF EC EC EC FF ED ED' + 'ED FF EE EE EE FF EF EF EF FF EE EE EE FF EB EB' + 'EB FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' + 'EC FF EC EC EC FF EC EC EC FF ED ED ED FF ED ED' + 'ED FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' + 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' + 'F1 FF F4 F4 F4 FF EA EA EA FF 7C 7C 7C FF 04 04' + '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CE CE' + 'CE FF FE FE FE FF ED ED ED FF ED ED ED FF EE EE' + 'EE FF EF EF EF FF F0 F0 F0 FF F1 F1 F1 FF F0 F0' + 'F0 FF EE EE EE FF EC EC EC FF EC EC EC FF ED ED' + 'ED FF ED ED ED FF EE EE EE FF EE EE EE FF EE EE' + 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' + 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' + 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F1 F1' + 'F1 FF F5 F5 F5 FF EA EA EA FF 7D 7D 7D FF 04 04' + '04 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CF CF' + 'CF FF FE FE FE FF EE EE EE FF EF EF EF FF F0 F0' + 'F0 FF F0 F0 F0 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' + 'F2 FF F3 F3 F3 FF F1 F1 F1 FF EE EE EE FF EE EE' + 'EE FF EE EE EE FF EE EE EE FF EE EE EE FF EF EF' + 'EF FF EF EF EF FF EF EF EF FF EF EF EF FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' + 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' + 'F3 FF F6 F6 F6 FF EB EB EB FF 7D 7D 7D FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3B 3B 3B FF CF CF' + 'CF FF FF FF FF FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F1 F1 F1 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' + 'F3 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4' + 'F4 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1 F1 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F3 F3' + 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4 F4 FF F4 F4' + 'F4 FF F7 F7 F7 FF EB EB EB FF 7E 7E 7E FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3C 3C 3C FF D0 D0' + 'D0 FF FF FF FF FF F1 F1 F1 FF F1 F1 F1 FF F2 F2' + 'F2 FF F2 F2 F2 FF F3 F3 F3 FF F4 F4 F4 FF F4 F4' + 'F4 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6 F6 FF F7 F7' + 'F7 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' + 'F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F8 F8' + 'F8 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F3 F3' + 'F3 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F4 F4' + 'F4 FF F4 F4 F4 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' + 'F5 FF F8 F8 F8 FF EB EB EB FF 7E 7E 7E FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3D 3D 3D FF D1 D1' + 'D1 FF FF FF FF FF F2 F2 F2 FF F2 F2 F2 FF F3 F3' + 'F3 FF F3 F3 F3 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' + 'F5 FF F6 F6 F6 FF F7 F7 F7 FF F7 F7 F7 FF F8 F8' + 'F8 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF FA FA FA FF FB FB FB FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FA FA FA FF F7 F7 F7 FF F5 F5 F5 FF F5 F5' + 'F5 FF F5 F5 F5 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' + 'F6 FF F9 F9 F9 FF EC EC EC FF 7F 7F 7F FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3D 3D 3D FF D1 D1' + 'D1 FF FF FF FF FF F3 F3 F3 FF F3 F3 F3 FF F4 F4' + 'F4 FF F4 F4 F4 FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' + 'F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' + 'F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF FA FA' + 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FE FE FE FF FD FD FD FF FA FA' + 'FA FF F7 F7 F7 FF F5 F5 F5 FF F6 F6 F6 FF F7 F7' + 'F7 FF FA FA FA FF EC EC EC FF 80 80 80 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D2 D2' + 'D2 FF FF FF FF FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' + 'F5 FF F5 F5 F5 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' + 'F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' + 'FB FF FB FB FB FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FE FE FE FF FB FB FB FF F8 F8 F8 FF F7 F7' + 'F7 FF FB FB FB FF ED ED ED FF 81 81 81 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D2 D2' + 'D2 FF FF FF FF FF F5 F5 F5 FF F6 F6 F6 FF F6 F6' + 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' + 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F9 F9 F9 FF FA FA' + 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' + 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FA FA' + 'FA FF FC FC FC FF ED ED ED FF 80 80 80 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D3 D3' + 'D3 FF FF FF FF FF F6 F6 F6 FF F7 F7 F7 FF F7 F7' + 'F7 FF F7 F7 F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FA FA' + 'FA FF FB FB FB FF FB FB FB FF FC FC FC FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF EE EE EE FF 82 82 82 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3E 3E 3E FF D3 D3' + 'D3 FF FF FF FF FF F7 F7 F7 FF F7 F7 F7 FF F8 F8' + 'F8 FF F9 F9 F9 FF F8 F8 F8 FF F8 F8 F8 FF FA FA' + 'FA FF FA FA FA FF FB FB FB FF FB FB FB FF FB FB' + 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 82 82 82 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D4 D4' + 'D4 FF FF FF FF FF F8 F8 F8 FF F8 F8 F8 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FA FA' + 'FA FF FA FA FA FF FB FB FB FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FC FC FC FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF EF EF EF FF 82 82 82 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D5 D5' + 'D5 FF FF FF FF FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF FA FA FA FF FB FB FB FF FB FB FB FF FB FB' + 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 83 83 83 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 3F 3F 3F FF D5 D5' + 'D5 FF FF FF FF FF FA FA FA FF FA FA FA FF FB FB' + 'FB FF FB FB FB FF FB FB FB FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FC FC FC FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 84 84 84 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 40 40 40 FF D5 D5' + 'D5 FF FF FF FF FF FB FB FB FF FB FB FB FF FB FB' + 'FB FF FC FC FC FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 85 85 85 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 40 40 40 FF D6 D6' + 'D6 FF FF FF FF FF FB FB FB FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 85 85 85 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D6 D6' + 'D6 FF FF FF FF FF FB FB FB FF FC FC FC FF FD FD' + 'FD FF FD FD FD FF FC FC FC FF FD FD FD FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F0 F0 F0 FF 86 86 86 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D6 D6' + 'D6 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F1 F1 F1 FF 87 87 87 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' + 'D7 FF FF FF FF FF FD FD FD FF FD FD FD FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F1 F1 F1 FF 87 87 87 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' + 'D7 FF FF FF FF FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F1 F1 F1 FF 88 88 88 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 41 41 41 FF D7 D7' + 'D7 FF FF FF FF FF FE FE FE FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F1 F1 F1 FF 88 88 88 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 42 42 42 FF D8 D8' + 'D8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F1 F1 F1 FF 89 89 89 FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 42 42 42 FF D9 D9' + 'D9 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F2 F2 F2 FF 8A 8A 8A FF 05 05' + '05 FF 00 00 00 F7 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 84 00 00 00 FF 47 47 47 FF D9 D9' + 'D9 FF FB FB FB FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' + 'F8 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' + 'F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7 F7 FF F7 F7' + 'F7 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' + 'F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5 F5 FF F5 F5' + 'F5 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' + 'F4 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4' + 'F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3' + 'F3 FF F6 F6 F6 FF E8 E8 E8 FF 8F 8F 8F FF 06 06' + '06 FF 00 00 00 F7 00 00 00 38 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 83 00 00 00 FF 2D 2D 2D FF 98 98' + '98 FF 98 98 98 FF 97 97 97 FF 97 97 97 FF 97 97' + '97 FF 96 96 96 FF 95 95 95 FF 95 95 95 FF 95 95' + '95 FF 93 93 93 FF 93 93 93 FF 93 93 93 FF 92 92' + '92 FF 91 91 91 FF 90 90 90 FF 90 90 90 FF 90 90' + '90 FF 8F 8F 8F FF 8F 8F 8F FF 8E 8E 8E FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8B 8B 8B FF 89 89' + '89 FF 89 89 89 FF 88 88 88 FF 88 88 88 FF 86 86' + '86 FF 86 86 86 FF 86 86 86 FF 86 86 86 FF 84 84' + '84 FF 84 84 84 FF 87 87 87 FF 6C 6C 6C FF 04 04' + '04 FF 00 00 00 F7 00 00 00 33 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 47 00 00 00 F5 00 00 00 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' + '04 FF 04 04 04 FF 04 04 04 FF 04 04 04 FF 04 04' + '04 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' + '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' + '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 03 03' + '03 FF 03 03 03 FF 03 03 03 FF 03 03 03 FF 00 00' + '00 FF 00 00 00 C1 00 00 00 14 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 52 00 00 00 EA 00 00' + '00 F3 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F4 00 00' + '00 C7 00 00 00 29 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 F0 00 00 01 FF FF 00 00 E0 00' + '00 00 FF FF 00 00 E0 00 00 00 7F FF 00 00 E0 00' + '00 00 3F FF 00 00 E0 00 00 00 1F FF 00 00 E0 00' + '00 00 0F FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 03 FF 00 00 E0 00 00 00 01 FF 00 00 E0 00' + '00 00 00 FF 00 00 E0 00 00 00 00 7F 00 00 E0 00' + '00 00 00 3F 00 00 E0 00 00 00 00 1F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 F0 00' + '00 00 00 0F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 00 00' + '00 64 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 62 00 00 00 41 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4D 01 01 01 FB 05 05' + '05 FF 03 03 03 FF 03 03 03 FF 02 02 02 FF 02 02' + '02 FF 02 02 02 FF 02 02 02 FF 02 02 02 FF 02 02' + '02 FF 02 02 02 FF 02 02 02 FF 02 02 02 FF 01 01' + '01 FF 00 00 00 FF 03 03 03 FF 01 01 01 FD 00 00' + '00 7F 00 00 00 02 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1A 1A 1A FF 8C 8C' + '8C FF 9F 9F 9F FF 9C 9C 9C FF 9A 9A 9A FF 9A 9A' + '9A FF 99 99 99 FF 99 99 99 FF 97 97 97 FF 97 97' + '97 FF 96 96 96 FF 96 96 96 FF 95 95 95 FF 93 93' + '93 FF 8E 8E 8E FF 7D 7D 7D FF 33 33 33 FF 00 00' + '00 FD 00 00 00 79 00 00 00 02 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' + 'C6 FF F7 F7 F7 FF EA EA EA FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EC EC' + 'EC FF ED ED ED FF EE EE EE FF EE EE EE FF EF EF' + 'EF FF F3 F3 F3 FF B7 B7 B7 FF 94 94 94 FF 34 34' + '34 FF 00 00 00 FD 00 00 00 7A 00 00 00 02 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1C 1C 1C FF C4 C4' + 'C4 FF EB EB EB FF D8 D8 D8 FF DA DA DA FF DB DB' + 'DB FF DB DB DB FF DC DC DC FF DC DC DC FF DC DC' + 'DC FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' + 'DE FF E0 E0 E0 FF AE AE AE FF D1 D1 D1 FF A4 A4' + 'A4 FF 32 32 32 FF 00 00 00 FD 00 00 00 7A 00 00' + '00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1C 1C 1C FF C4 C4' + 'C4 FF ED ED ED FF DB DB DB FF DD DD DD FF DD DD' + 'DD FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' + 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E2 E2 E2 FF AE AE AE FF D9 D9 D9 FF E9 E9' + 'E9 FF A3 A3 A3 FF 2E 2E 2E FF 00 00 00 FD 00 00' + '00 7A 00 00 00 02 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' + 'C6 FF EF EF EF FF DD DD DD FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2' + 'E2 FF E4 E4 E4 FF B0 B0 B0 FF DA DA DA FF F1 F1' + 'F1 FF EC EC EC FF A3 A3 A3 FF 2B 2B 2B FF 00 00' + '00 FD 00 00 00 79 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C6 C6' + 'C6 FF EF EF EF FF DE DE DE FF E0 E0 E0 FF E0 E0' + 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2' + 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E5 E5 E5 FF B1 B1 B1 FF DE DE DE FF F2 F2' + 'F2 FF F4 F4 F4 FF F1 F1 F1 FF A4 A4 A4 FF 2B 2B' + '2B FF 00 00 00 FC 00 00 00 72 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1D 1D 1D FF C7 C7' + 'C7 FF F1 F1 F1 FF E0 E0 E0 FF E2 E2 E2 FF E2 E2' + 'E2 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E7 E7 E7 FF B3 B3 B3 FF E1 E1 E1 FF F6 F6' + 'F6 FF F4 F4 F4 FF F9 F9 F9 FF F6 F6 F6 FF A6 A6' + 'A6 FF 2D 2D 2D FF 00 00 00 F9 00 00 00 6F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C7 C7' + 'C7 FF F1 F1 F1 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5' + 'E5 FF E5 E5 E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6' + 'E6 FF E8 E8 E8 FF B5 B5 B5 FF E8 E8 E8 FF FE FE' + 'FE FF FC FC FC FF FD FD FD FF FF FF FF FF FC FC' + 'FC FF AD AD AD FF 31 31 31 FF 00 00 00 F9 00 00' + '00 6F 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C8 C8' + 'C8 FF F3 F3 F3 FF E3 E3 E3 FF E5 E5 E5 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' + 'E8 FF EA EA EA FF B2 B2 B2 FF D8 D8 D8 FF EC EC' + 'EC FF EA EA EA FF EB EB EB FF EB EB EB FF EF EF' + 'EF FF EA EA EA FF 98 98 98 FF 2C 2C 2C FF 00 00' + '00 F5 00 00 00 42 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1E 1E 1E FF C8 C8' + 'C8 FF F3 F3 F3 FF E5 E5 E5 FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' + 'E8 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9' + 'E9 FF EC EC EC FF C9 C9 C9 FF B3 B3 B3 FF B6 B6' + 'B6 FF B5 B5 B5 FF B5 B5 B5 FF B5 B5 B5 FF B4 B4' + 'B4 FF B6 B6 B6 FF BA BA BA FF 80 80 80 FF 03 03' + '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF C9 C9' + 'C9 FF F5 F5 F5 FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF E9 E9 E9 FF E9 E9 E9 FF E9 E9' + 'E9 FF EA EA EA FF EA EA EA FF EA EA EA FF EB EB' + 'EB FF EB EB EB FF EE EE EE FF EE EE EE FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF EF EF EF FF EF EF' + 'EF FF F0 F0 F0 FF F7 F7 F7 FF 93 93 93 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF CA CA' + 'CA FF F7 F7 F7 FF EA EA EA FF EC EC EC FF EA EA' + 'EA FF E9 E9 E9 FF EA EA EA FF EA EA EA FF EB EB' + 'EB FF EB EB EB FF EC EC EC FF EC EC EC FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' + 'EF FF F1 F1 F1 FF F6 F6 F6 FF 93 93 93 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 1F 1F 1F FF CA CA' + 'CA FF F8 F8 F8 FF EC EC EC FF EE EE EE FF EF EF' + 'EF FF EE EE EE FF EB EB EB FF EB EB EB FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF ED ED ED FF EE EE' + 'EE FF EE EE EE FF EF EF EF FF EF EF EF FF EF EF' + 'EF FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F1 F1' + 'F1 FF F2 F2 F2 FF F7 F7 F7 FF 93 93 93 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CB CB' + 'CB FF F9 F9 F9 FF EE EE EE FF F0 F0 F0 FF F1 F1' + 'F1 FF F2 F2 F2 FF F1 F1 F1 FF EE EE EE FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF EE EE EE FF EF EF' + 'EF FF EF EF EF FF EF EF EF FF F0 F0 F0 FF F1 F1' + 'F1 FF F1 F1 F1 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F3 F3 F3 FF F8 F8 F8 FF 94 94 94 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CC CC' + 'CC FF FB FB FB FF F0 F0 F0 FF F2 F2 F2 FF F2 F2' + 'F2 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4' + 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3' + 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F3 F3 F3 FF F4 F4' + 'F4 FF F5 F5 F5 FF F9 F9 F9 FF 94 94 94 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 20 20 20 FF CD CD' + 'CD FF FB FB FB FF F2 F2 F2 FF F3 F3 F3 FF F4 F4' + 'F4 FF F5 F5 F5 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8' + 'F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF FB FB' + 'FB FF FB FB FB FF FB FB FB FF FA FA FA FF F8 F8' + 'F8 FF F6 F6 F6 FF F5 F5 F5 FF F4 F4 F4 FF F5 F5' + 'F5 FF F6 F6 F6 FF FA FA FA FF 95 95 95 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CE CE' + 'CE FF FD FD FD FF F4 F4 F4 FF F4 F4 F4 FF F6 F6' + 'F6 FF F6 F6 F6 FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' + 'F8 FF FA FA FA FF FA FA FA FF FB FB FB FF FB FB' + 'FB FF FC FC FC FF FD FD FD FF FD FD FD FF FE FE' + 'FE FF FE FE FE FF FC FC FC FF F9 F9 F9 FF F6 F6' + 'F6 FF F7 F7 F7 FF FB FB FB FF 96 96 96 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CE CE' + 'CE FF FE FE FE FF F5 F5 F5 FF F6 F6 F6 FF F7 F7' + 'F7 FF F8 F8 F8 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' + 'FA FF FB FB FB FF FB FB FB FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FD FD' + 'FD FF FB FB FB FF FC FC FC FF 97 97 97 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 21 21 21 FF CF CF' + 'CF FF FF FF FF FF F7 F7 F7 FF F8 F8 F8 FF F8 F8' + 'F8 FF F9 F9 F9 FF FA FA FA FF FA FA FA FF FB FB' + 'FB FF FB FB FB FF FC FC FC FF FC FC FC FF FD FD' + 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 98 98 98 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 22 22 22 FF CF CF' + 'CF FF FF FF FF FF F8 F8 F8 FF F9 F9 F9 FF FA FA' + 'FA FF FA FA FA FF FA FA FA FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 99 99 99 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 22 22 22 FF D0 D0' + 'D0 FF FF FF FF FF F9 F9 F9 FF FA FA FA FF FB FB' + 'FB FF FB FB FB FF FB FB FB FF FC FC FC FF FD FD' + 'FD FF FD FD FD FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 99 99 99 FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D1 D1' + 'D1 FF FF FF FF FF FA FA FA FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9A 9A 9A FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D1 D1' + 'D1 FF FF FF FF FF FC FC FC FF FC FC FC FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9B 9B 9B FF 02 02' + '02 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D2 D2' + 'D2 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FE FE FE FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9C 9C 9C FF 03 03' + '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D3 D3' + 'D3 FF FF FF FF FF FE FE FE FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9D 9D 9D FF 03 03' + '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 23 23 23 FF D3 D3' + 'D3 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9D 9D 9D FF 03 03' + '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 24 24 24 FF D4 D4' + 'D4 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 9E 9E 9E FF 03 03' + '03 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 84 27 27 27 FF D8 D8' + 'D8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FE FE' + 'FE FF FE FE FE FF FE FE FE FF FE FE FE FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FC FC FC FF FC FC FC FF FC FC' + 'FC FF FD FD FD FF FF FF FF FF A3 A3 A3 FF 04 04' + '04 FF 00 00 00 61 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 7F 18 18 18 FF 77 77' + '77 FF 7D 7D 7D FF 7B 7B 7B FF 7A 7A 7A FF 79 79' + '79 FF 79 79 79 FF 78 78 78 FF 78 78 78 FF 77 77' + '77 FF 76 76 76 FF 75 75 75 FF 75 75 75 FF 74 74' + '74 FF 73 73 73 FF 72 72 72 FF 71 71 71 FF 70 70' + '70 FF 70 70 70 FF 6F 6F 6F FF 6E 6E 6E FF 6E 6E' + '6E FF 6D 6D 6D FF 6E 6E 6E FF 59 59 59 FF 03 03' + '03 FF 00 00 00 59 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2A 00 00 00 D3 00 00' + '00 F5 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F6 00 00' + '00 B6 00 00 00 14 00 00 00 00 00 00 00 00 E0 00' + '07 FF C0 00 03 FF C0 00 01 FF C0 00 00 FF C0 00' + '00 7F C0 00 00 3F C0 00 00 1F C0 00 00 1F C0 00' + '00 0F C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 01 01 63 05 05' + '05 AF 04 04 04 A8 04 04 04 A8 04 04 04 A8 04 04' + '04 A8 03 03 03 A8 03 03 03 AA 02 02 02 A0 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 13 13 13 CB A8 A8' + 'A8 FF BC BC BC FF B7 B7 B7 FF B7 B7 B7 FF B6 B6' + 'B6 FF B7 B7 B7 FF B6 B6 B6 FF 7A 7A 7A FF 0F 0F' + '0F D5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 17 17 17 CC D1 D1' + 'D1 FF EA EA EA FF E5 E5 E5 FF E6 E6 E6 FF E7 E7' + 'E7 FF E9 E9 E9 FF E3 E3 E3 FF D0 D0 D0 FF 95 95' + '95 FF 0B 0B 0B D5 00 00 00 28 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 17 17 17 CC CD CD' + 'CD FF E4 E4 E4 FF DF DF DF FF E0 E0 E0 FF E1 E1' + 'E1 FF E2 E2 E2 FF DA DA DA FF CE CE CE FF F9 F9' + 'F9 FF 95 95 95 FF 0A 0A 0A D4 00 00 00 25 00 00' + '00 00 00 00 00 00 00 00 00 00 17 17 17 CC D0 D0' + 'D0 FF E7 E7 E7 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' + 'E4 FF E6 E6 E6 FF DD DD DD FF D2 D2 D2 FF FF FF' + 'FF FF FF FF FF FF 9E 9E 9E FF 0D 0D 0D D1 00 00' + '00 24 00 00 00 00 00 00 00 00 17 17 17 CC D1 D1' + 'D1 FF EB EB EB FF E5 E5 E5 FF E7 E7 E7 FF E7 E7' + 'E7 FF E9 E9 E9 FF E4 E4 E4 FF CB CB CB FF D7 D7' + 'D7 FF D9 D9 D9 FF DF DF DF FF 7C 7C 7C FF 00 00' + '00 9D 00 00 00 00 00 00 00 00 17 17 17 CC D4 D4' + 'D4 FF F0 F0 F0 FF E9 E9 E9 FF E9 E9 E9 FF EA EA' + 'EA FF EB EB EB FF EC EC EC FF E8 E8 E8 FF E4 E4' + 'E4 FF E5 E5 E5 FF EF EF EF FF BC BC BC FF 03 03' + '03 A8 00 00 00 00 00 00 00 00 17 17 17 CC D6 D6' + 'D6 FF F4 F4 F4 FF EF EF EF FF EE EE EE FF ED ED' + 'ED FF ED ED ED FF EE EE EE FF F0 F0 F0 FF F1 F1' + 'F1 FF F1 F1 F1 FF FC FC FC FF BD BD BD FF 02 02' + '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC D8 D8' + 'D8 FF F8 F8 F8 FF F4 F4 F4 FF F5 F5 F5 FF F5 F5' + 'F5 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5' + 'F5 FF F4 F4 F4 FF FE FE FE FF BE BE BE FF 03 03' + '03 A8 00 00 00 00 00 00 00 00 18 18 18 CC DB DB' + 'DB FF FB FB FB FF F6 F6 F6 FF F8 F8 F8 FF FA FA' + 'FA FF FB FB FB FF FC FC FC FF FD FD FD FF FE FE' + 'FE FF FD FD FD FF FF FF FF FF C0 C0 C0 FF 02 02' + '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC DC DC' + 'DC FF FE FE FE FF F9 F9 F9 FF FB FB FB FF FC FC' + 'FC FF FC FC FC FF FD FD FD FF FE FE FE FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF C3 C3 C3 FF 02 02' + '02 A8 00 00 00 00 00 00 00 00 18 18 18 CC DE DE' + 'DE FF FF FF FF FF FC FC FC FF FC FC FC FF FD FD' + 'FD FF FE FE FE FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF C4 C4 C4 FF 03 03' + '03 A8 00 00 00 00 00 00 00 00 18 18 18 CC DF DF' + 'DF FF FF FF FF FF FD FD FD FF FE FE FE FF FE FE' + 'FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF C5 C5 C5 FF 03 03' + '03 A8 00 00 00 00 00 00 00 00 19 19 19 CC E2 E2' + 'E2 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF C7 C7 C7 FF 03 03' + '03 A8 00 00 00 00 00 00 00 00 19 19 19 CC E2 E2' + 'E2 FF FF FF FF FF FD FD FD FF FD FD FD FF FD FD' + 'FD FF FD FD FD FF FD FD FD FF FC FC FC FF FC FC' + 'FC FF FB FB FB FF FF FF FF FF C6 C6 C6 FF 04 04' + '04 A8 00 00 00 00 00 00 00 00 09 09 09 A0 41 41' + '41 F9 46 46 46 F0 44 44 44 F0 44 44 44 F0 43 43' + '43 F0 42 42 42 F0 42 42 42 F0 41 41 41 F0 3F 3F' + '3F F0 3F 3F 3F F0 40 40 40 F0 36 36 36 FB 02 02' + '02 82 00 00 00 00 80 1F 00 00 80 0F 00 00 80 07' + '00 00 80 03 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00' +} */ + + +/* BINRES folder.ico */ +3 ICON folder.ico +/* { + '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 00 00 00 00 11 00 00 00 00 11 00 22 00' + '00 00 33 00 00 00 33 33 00 00 33 33 33 00 44 00' + '00 00 66 33 00 00 66 33 33 00 66 66 33 00 7F 7F' + '7F 00 99 33 00 00 99 33 33 00 99 66 33 00 99 66' + '66 00 CC 66 66 00 FF 99 33 00 FF CC 33 00 99 99' + '66 00 CC 99 66 00 FF 99 66 00 CC CC 66 00 FF CC' + '66 00 BB BB BB 00 CC 99 99 00 FF 99 99 00 CC CC' + '99 00 FF CC 99 00 FF FF 99 00 CC 99 CC 00 CC CC' + 'CC 00 DD DD DD 00 FF CC CC 00 FF FF CC 00 FF CC' + 'FF 00 EE EE EE 00 FF FF FF 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 56 00 58 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' + '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 66 6F 6C 64 65 72 2E 69 63' + '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 27 27 27 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 27 02 03 27 27' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 27 03 04 0D 06 27' + '27 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 27 27 27 09 11 22 1A 06' + '27 27 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 27 27 27 0F 1B 22 26 26 1A' + '05 27 27 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 27 02 08 15 1B 1C 26 26 26 26' + '1A 04 27 27 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 27 27 27 08 1A 1D 1A 26 26 26 26 26' + '25 15 04 27 27 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 27 27 27 0A 1D 1D 1A 1D 1D 26 26 26 26' + '26 25 10 04 27 27 00 00 00 00 00 00 00 00 00 00' + '00 00 27 01 01 10 23 1D 15 23 16 12 18 26 26 26' + '26 26 25 10 01 27 27 00 00 00 00 00 00 00 00 00' + '27 27 02 06 1B 23 1D 1A 22 12 12 16 12 1D 26 26' + '26 25 25 25 10 01 27 27 00 00 00 00 00 00 00 27' + '27 27 0E 22 23 1D 1A 22 18 12 16 12 16 12 18 25' + '26 24 25 23 25 10 01 27 27 00 00 00 00 00 27 01' + '04 15 23 22 22 1C 1D 1B 12 16 12 12 18 16 16 1D' + '23 25 25 21 25 22 10 01 27 27 00 00 00 00 03 06' + '1D 25 25 23 1C 1B 1D 13 16 12 18 16 12 16 18 16' + '1D 25 25 25 22 21 21 0F 01 27 27 00 00 00 27 09' + '22 23 22 22 17 1D 16 12 16 16 12 16 16 18 16 18' + '1B 1D 25 21 21 21 20 22 09 02 27 27 00 00 27 27' + '06 22 23 15 1D 16 12 16 16 13 16 18 12 16 18 1B' + '18 1D 1D 21 21 20 22 20 22 0A 27 27 27 00 00 27' + '27 09 16 1D 16 13 16 16 12 16 12 16 16 18 16 18' + '1D 1D 1E 22 20 22 19 20 19 22 0F 27 27 27 00 00' + '27 27 09 16 12 16 16 12 18 16 16 12 18 16 18 1D' + '1D 1D 22 22 23 20 22 19 22 19 1C 0E 27 27 00 00' + '00 27 27 09 16 16 16 18 16 12 18 16 16 1D 1D 1D' + '22 1E 22 23 22 23 20 19 19 22 1F 14 01 27 00 00' + '00 00 27 27 09 12 18 16 12 16 16 1D 1D 1D 1D 23' + '1D 22 23 22 23 23 25 22 19 19 14 02 27 27 00 00' + '00 00 00 27 27 09 16 18 16 18 1D 1D 1D 1D 22 1D' + '23 22 23 23 23 24 23 25 20 1A 04 27 27 00 00 00' + '00 00 00 00 27 27 09 16 18 1D 22 1D 1D 22 1D 23' + '22 23 22 23 24 23 26 26 1D 07 27 27 00 00 00 00' + '00 00 00 00 00 27 27 09 1D 22 1D 22 1D 22 23 22' + '23 22 26 23 25 23 25 22 0A 27 27 00 00 00 00 00' + '00 00 00 00 00 00 27 27 10 1D 22 1E 22 23 22 23' + '22 23 23 24 23 26 25 0B 27 27 00 00 00 00 00 00' + '00 00 00 00 00 00 27 27 15 23 22 22 23 22 23 24' + '23 25 25 23 26 26 0F 27 27 00 00 00 00 00 00 00' + '00 00 00 00 00 00 27 27 05 1C 23 22 22 23 24 23' + '25 25 23 26 26 10 27 27 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 27 27 04 17 22 23 23 25 25' + '23 25 26 26 15 27 27 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 27 27 04 1D 26 26 25 23' + '26 26 25 22 04 27 27 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 27 27 06 22 25 26 26' + '25 26 22 06 27 27 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 27 27 04 1C 26 26' + '26 23 07 27 27 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 27 27 01 1A 26' + '23 0A 27 27 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 27 27 27 06' + '04 27 27 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 27' + '27 27 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' + '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' + '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' + '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' + '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' + '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' + '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' + '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' + '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 11 00 00 00 00 11' + '00 00 00 00 11 00 11 11 11 00 22 00 00 00 33 00' + '00 00 33 33 00 00 33 00 33 00 22 22 22 00 33 33' + '33 00 66 33 00 00 66 33 33 00 66 66 33 00 44 44' + '44 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 99 66' + '66 00 FF 99 33 00 99 99 66 00 CC 99 66 00 FF 99' + '66 00 FF CC 66 00 CC 99 99 00 CC CC 99 00 FF CC' + '99 00 FF FF 99 00 CC 99 CC 00 CC CC CC 00 DD DD' + 'DD 00 FF CC CC 00 FF FF CC 00 EE EE EE 00 FF FF' + 'FF 00 00 00 00 00 FF CC FF 00 EE EE EE 00 FF FF' + 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' + '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' + '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 56 00' + '58 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 56 00 00 00 00 00 00 00 03 00' + '00 00 5E 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 66' + '6F 6C 64 65 72 2E 69 63 6F 00 1A 93 4B 00 14 1A' + '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' + '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' + '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 01 23 23 00' + '00 00 00 00 00 00 00 00 00 00 00 02 03 12 0C 23' + '00 00 00 00 00 00 00 00 00 00 02 08 15 22 20 0A' + '03 00 00 00 00 00 00 00 23 23 0C 1A 1F 22 22 1F' + '07 03 00 00 00 00 00 01 01 10 1A 1A 13 1A 22 22' + '1D 07 23 00 00 00 23 09 1A 1F 1A 13 16 13 1A 21' + '22 1C 06 02 00 00 05 1F 20 1A 16 16 13 17 16 1A' + '1E 21 19 05 23 00 23 0D 1A 16 13 17 16 16 17 1A' + '1A 1E 1D 18 04 01 00 23 0B 17 16 16 13 16 1A 1A' + '20 1F 1D 1F 14 23 00 00 23 0B 17 16 1A 1A 1F 20' + '1F 21 20 1C 0A 23 00 00 00 23 0C 17 1F 1B 1F 1F' + '20 20 21 0D 23 00 00 00 00 00 23 18 20 1F 20 1F' + '22 22 0F 23 00 00 00 00 00 00 23 0E 1A 21 20 22' + '22 14 23 00 00 00 00 00 00 00 00 23 0C 20 22 22' + '18 02 23 00 00 00 00 00 00 00 00 00 23 0E 1F 1D' + '02 23 00 00 00 00 00 00 00 00 00 00 00 23 02 01' + '23 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' + '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' + '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' + '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' + '00 00 FE 1F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 08 10 00 00 00 00 00 00 00 00 00' + '00 00 00 00 08 BF 81 00 00 00 00 00 00 00 00 00' + '00 00 00 04 1B 7F F8 00 00 00 00 00 00 00 00 00' + '00 00 00 9B 77 FF FF 89 00 00 00 00 00 00 00 00' + '00 00 00 78 7F FF FF F8 20 00 00 00 00 00 00 00' + '00 00 1F B7 78 FF FF F7 10 00 00 00 00 00 00 00' + '00 81 77 8F B7 BF FF FF F8 20 00 00 00 00 00 00' + '08 BF FB FB 8B 8B FF FF F7 18 00 00 00 00 00 00' + '17 7F B7 88 B1 B7 BF FF 7F F8 00 00 00 00 00 0B' + 'FF F8 77 BB 7B 7B 78 FF F7 F7 B0 00 00 00 09 7F' + '7F B7 7B 88 B7 B8 BF BF 7F 77 7B 00 00 00 08 7F' + '7F 87 B8 B7 B8 B8 7B FB F7 F7 F7 90 00 00 00 97' + 'FB 7B 7B 7B 7B 8F B7 BF BF 7F 77 78 00 00 00 08' + 'B7 B8 B7 B8 B8 BB 7B 7B F7 77 77 7F 90 00 00 00' + '1B 7B 8B 7B 87 B7 BF BF 7F F7 77 FB F1 00 00 00' + '08 B8 B7 B7 BB 7B 77 F7 FB FF 77 77 78 00 00 00' + '00 8B 7B 7B B7 77 7F BF BF FF 77 77 80 00 00 00' + '00 08 B8 B7 7B FB F7 F7 F7 FF FF B7 00 00 00 00' + '00 00 1B FB 77 7F BF 7F BF FF FF 78 00 00 00 00' + '00 00 08 BF 7F BF 7F F7 FF BF FF 80 00 00 00 00' + '00 00 00 87 FB F7 FF BF FF FF F8 00 00 00 00 00' + '00 00 00 BF 77 FF BF FF 7F FF 80 00 00 00 00 00' + '00 00 00 07 F7 F7 FF F7 FF F8 00 00 00 00 00 00' + '00 00 00 00 BF 7F 7F FF FF B0 00 00 00 00 00 00' + '00 00 00 00 8B FF FF FF F7 00 00 00 00 00 00 00' + '00 00 00 00 08 7F FF FF 78 00 00 00 00 00 00 00' + '00 00 00 00 00 07 FF F7 80 00 00 00 00 00 00 00' + '00 00 00 00 00 00 8F F8 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' + '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' + '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' + '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' + '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' + '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' + '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' + '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' + '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 01 80 00 00 00 00 00 01 8F 78 00 00 00 00 00' + '1B FF F7 10 00 00 00 4B 8F B7 FF 70 00 00 08 BF' + '7B 8B FF F7 90 00 07 F7 7B 87 B7 F7 70 00 08 7B' + 'B7 BB 7B 7F 77 00 00 8B 7B B7 BF F7 77 B0 00 08' + 'B7 B7 FB FF F7 00 00 00 17 7F BF 7F F8 00 00 00' + '0B F7 FF FF 80 00 00 00 08 7F 7F F8 00 00 00 00' + '00 8F FF 70 00 00 00 00 00 08 F7 00 00 00 00 00' + '00 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' + '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' + '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' + '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' + '00 00 FE 1F 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 00 00 00 00 11 00 00 00 00 11 00 22 00' + '00 00 33 00 00 00 00 22 00 00 33 33 00 00 22 22' + '22 00 44 00 00 00 55 00 00 00 66 00 00 00 66 33' + '00 00 66 33 33 00 66 66 33 00 7F 7F 7F 00 99 33' + '00 00 99 33 33 00 99 66 00 00 99 66 33 00 CC 66' + '00 00 CC 66 33 00 99 66 66 00 CC 66 66 00 CC 99' + '33 00 FF 99 33 00 FF CC 33 00 99 99 66 00 CC 99' + '66 00 FF 99 66 00 CC CC 66 00 FF CC 66 00 BB BB' + 'BB 00 CC 99 99 00 FF 99 99 00 CC CC 99 00 FF CC' + '99 00 FF FF 99 00 CC 99 CC 00 CC CC CC 00 DD DD' + 'DD 00 FF CC CC 00 CC FF CC 00 FF FF CC 00 FF CC' + 'FF 00 EE EE EE 00 FF FF FF 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 56 00 58 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' + '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 66 6F 6C 64 65 72 2E 69 63' + '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 2F 2F 2F 2F 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 2F 2F 2F 2F 2F 2F 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 2F 2F 2F 01 2F 2F 2F 2F 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '2F 2F 2F 2F 09 10 0C 02 2F 2F 2F 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' + '2F 2F 04 11 15 1C 17 09 02 2F 2F 2F 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F 2F' + '2F 05 13 1C 23 2E 2D 1C 0B 2F 2F 2F 2F 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 2F' + '0B 23 22 21 2E 2E 2E 28 1C 0A 2F 2F 2F 2F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 01 0C' + '23 22 18 2E 2E 2E 2E 2E 28 1C 05 2F 2F 2F 2F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2F 2F 2F 2F 04 13 29' + '24 17 2D 2E 2E 2E 2E 2E 2E 28 17 05 02 2F 2F 2F' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 2F 2F 2F 01 05 1C 2D 24' + '15 2D 2E 2E 2E 2E 2E 2E 2E 2E 27 1C 04 01 2F 2F' + '2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 2F 2F 2F 01 0C 24 29 1F 17' + '2D 24 24 2E 2E 2E 2E 2E 2E 2E 2E 28 17 06 2F 2F' + '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2F 2F 2F 2F 05 16 29 29 24 17 29' + '29 19 1D 24 2E 2E 2E 2E 2E 2E 2E 2D 28 17 09 2F' + '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 2F 2F 2F 2F 0C 21 2B 24 24 1D 27 2B' + '19 19 19 1D 29 2E 2E 2E 2E 2E 2D 2E 2E 28 1B 05' + '2F 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 2F 2F 2F 03 10 29 2B 24 29 1D 20 2B 19' + '19 1D 19 19 19 29 2E 2E 2E 2E 2E 2D 2D 2D 29 17' + '04 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' + '00 2F 2F 2F 2F 05 13 29 2B 24 29 1C 1C 2E 1D 19' + '19 19 1D 19 1D 19 2D 2E 2E 2E 2D 2E 2D 2D 2D 27' + '13 04 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00' + '2F 2F 2F 2F 0A 21 2B 2B 24 29 24 21 2E 1D 19 1D' + '19 1D 19 1D 19 1F 19 29 2E 2D 2E 2D 29 2D 28 2D' + '28 15 2F 2F 2F 2F 00 00 00 00 00 00 00 00 00 2F' + '2F 2F 04 13 24 28 29 2B 29 24 1C 2B 24 19 1D 19' + '1D 19 1D 1A 1D 1D 1F 1D 2B 2C 2E 2D 2D 2D 2D 28' + '29 27 15 04 2F 2F 2F 00 00 00 00 00 00 00 2F 2F' + '2F 05 13 29 2E 2B 2B 29 24 1C 2D 24 19 1D 1A 1D' + '19 1D 19 1D 19 1D 1D 1F 1D 25 28 2D 2D 2D 29 28' + '28 28 29 13 01 2F 2F 2F 00 00 00 00 00 00 2F 2F' + '0C 22 2E 2B 29 29 2D 2B 1C 29 1F 1D 1D 19 1D 19' + '1D 1A 1D 19 1D 1F 1D 1D 1F 22 2B 2D 2D 28 28 28' + '28 27 28 27 15 2F 2F 2F 2F 00 00 00 00 00 2F 2F' + '0C 2B 29 2B 29 2B 2B 17 24 24 1D 1D 19 1D 1D 1A' + '1D 1D 19 1D 1F 1D 1D 1F 22 1F 1F 29 28 2D 29 28' + '28 28 27 29 20 15 04 2F 2F 2F 2F 00 00 00 2F 2F' + '2F 10 2B 2D 2B 2D 1D 23 24 1D 19 1D 1F 19 1D 1D' + '1A 1D 1D 19 1D 1F 1F 1D 1F 24 22 1F 29 28 2D 28' + '29 28 29 27 29 20 10 2F 2F 2F 2F 00 00 00 2F 2F' + '2F 2F 10 24 2E 1D 1C 24 19 1D 1F 19 1D 1F 19 1D' + '1D 1D 19 1D 1F 1D 1D 1F 22 1F 1F 24 24 29 2A 29' + '28 27 27 27 27 20 29 13 2F 2F 2F 2F 00 00 00 00' + '2F 2F 2F 11 24 1C 24 1D 1D 19 1D 1D 19 1D 1D 1A' + '1D 19 1F 1D 19 1F 1D 24 1F 22 24 24 24 24 29 28' + '27 29 27 29 20 27 28 24 11 02 2F 2F 2F 2F 00 00' + '00 2F 2F 01 12 1D 1F 1D 1A 1D 19 1D 1F 19 1F 1D' + '19 1D 1D 1A 1D 1D 1D 1F 1D 24 24 24 25 29 2B 29' + '28 27 27 27 27 27 21 27 28 10 2F 2F 2F 2F 00 00' + '00 00 2F 2F 04 14 1D 1D 1D 1D 1F 1D 19 1D 19 1D' + '1F 1D 19 1D 1F 1D 1F 24 24 24 25 29 29 25 29 2B' + '29 28 29 20 29 23 27 26 23 29 13 01 2F 2F 00 00' + '00 00 2F 2F 2F 08 10 19 1D 1F 19 1F 1D 1D 1D 1F' + '1D 19 1D 1D 1D 24 24 24 24 24 29 2B 24 29 2B 2B' + '29 2B 20 20 27 27 26 23 26 27 1C 02 2F 2F 00 00' + '00 00 00 2F 2F 2F 01 14 1D 1D 1D 19 1D 1F 1D 19' + '1D 1F 1D 1F 24 24 24 24 2B 24 24 29 2B 29 29 2B' + '2B 29 2E 27 23 26 23 20 20 21 05 2F 2F 2F 00 00' + '00 00 00 00 2F 2F 2F 03 12 19 1D 1D 1F 19 1F 1D' + '1F 1D 24 24 24 24 29 24 24 29 29 2B 29 2B 2B 29' + '2B 2E 2B 29 27 23 26 27 21 07 2F 2F 2F 00 00 00' + '00 00 00 00 00 00 2F 2F 2F 12 1D 1F 1D 1D 1D 1D' + '24 24 24 24 24 24 24 2B 29 24 2B 29 2B 29 2B 2B' + '2C 2B 2D 2E 28 26 23 21 0D 2F 2F 2F 00 00 00 00' + '00 00 00 00 00 00 2F 2F 2F 03 10 18 1D 1D 1F 24' + '24 29 24 24 2B 24 29 29 24 2B 29 2B 29 2B 2B 2C' + '2B 2D 2D 2E 2B 2B 27 0D 2F 2F 2F 00 00 00 00 00' + '00 00 00 00 00 00 00 00 2F 2F 2F 10 1D 1F 24 29' + '24 24 29 24 24 29 25 29 2B 29 2B 29 2E 29 2B 2D' + '2B 2E 2B 29 2E 2B 13 2F 2F 2F 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2F 2F 2F 0C 24 29 24' + '25 29 24 2B 29 25 29 29 2B 29 2B 2B 29 2B 2D 2B' + '2E 29 2B 2E 2E 13 2F 2F 2F 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 2F 2F 2F 0D 1F 29' + '29 24 29 24 29 29 2B 29 29 2B 29 2D 2B 2D 2D 2B' + '2D 2B 2E 2E 13 01 2F 2F 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 2F 2F 0C 1E 24' + '29 2B 29 2B 29 2B 29 2B 2B 2C 2B 2B 2D 2D 2B 2C' + '2B 2E 2E 1C 01 2F 2F 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 2F 2F 15 2D 29' + '1E 29 2B 29 2B 29 2B 29 2D 2B 2C 2B 2D 2B 2C 2B' + '2E 2D 22 02 01 2F 2F 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 2F 2F 07 22 2B' + '29 24 29 2B 29 2B 2C 2B 2B 2D 2B 2C 2B 2D 2B 2E' + '2E 29 07 2F 2F 2F 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 07 1C' + '2E 23 24 2C 2B 2D 2B 2C 2B 2D 2D 2B 2D 2D 2E 2E' + '24 07 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F 04' + '1B 1D 29 2B 2D 2B 2C 2B 2E 2D 2B 2E 2D 2E 2E 29' + '0C 2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2F 2F 2F' + '01 18 2B 2D 2B 2C 2B 2E 2C 2B 2E 2D 2E 2E 29 0E' + '2F 2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' + '2F 04 1C 2E 2E 2B 2E 2D 2B 2E 2D 2E 2E 2B 13 2F' + '2F 2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2F' + '2F 2F 04 1C 2D 2E 2D 2E 2E 2E 2E 2E 2E 1B 01 2F' + '2F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '2F 2F 2F 2F 1C 2D 2E 2E 2E 2E 2E 2E 1C 01 2F 2F' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 2F 2F 2F 2F 13 2B 2E 2E 2E 2E 1E 01 2F 2F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 2F 2F 2F 0E 29 2E 2D 23 05 2F 2F 2F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 2F 2F 2F 07 13 07 04 2F 2F 2F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2F 2F 2F 2F 2F 2F 2F 2F 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 2F 2F 2F 2F 2F 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FC 3F FF FF 00 00 FF FF' + 'F8 1F FF FF 00 00 FF FF F0 0F FF FF 00 00 FF FF' + 'C0 07 FF FF 00 00 FF FF 80 03 FF FF 00 00 FF FF' + '00 01 FF FF 00 00 FF FC 00 00 FF FF 00 00 FF F8' + '00 00 7F FF 00 00 FF E0 00 00 3F FF 00 00 FF C0' + '00 00 1F FF 00 00 FF 80 00 00 0F FF 00 00 FE 00' + '00 00 0F FF 00 00 FC 00 00 00 03 FF 00 00 F8 00' + '00 00 03 FF 00 00 E0 00 00 00 01 FF 00 00 C0 00' + '00 00 00 FF 00 00 80 00 00 00 00 7F 00 00 00 00' + '00 00 00 3F 00 00 00 00 00 00 00 1F 00 00 00 00' + '00 00 00 07 00 00 00 00 00 00 00 07 00 00 00 00' + '00 00 00 03 00 00 C0 00 00 00 00 00 00 00 E0 00' + '00 00 00 00 00 00 F0 00 00 00 00 00 00 00 F0 00' + '00 00 00 00 00 00 F8 00 00 00 00 00 00 00 FC 00' + '00 00 00 01 00 00 FF 00 00 00 00 03 00 00 FF 00' + '00 00 00 07 00 00 FF C0 00 00 00 0F 00 00 FF E0' + '00 00 00 1F 00 00 FF F0 00 00 00 3F 00 00 FF F8' + '00 00 00 7F 00 00 FF F8 00 00 00 7F 00 00 FF F8' + '00 00 00 FF 00 00 FF F8 00 00 01 FF 00 00 FF FC' + '00 00 03 FF 00 00 FF FE 00 00 07 FF 00 00 FF FF' + '80 00 0F FF 00 00 FF FF 80 00 1F FF 00 00 FF FF' + 'C0 00 3F FF 00 00 FF FF E0 00 7F FF 00 00 FF FF' + 'F8 00 7F FF 00 00 FF FF FC 00 FF FF 00 00 FF FF' + 'FE 01 FF FF 00 00 FF FF FF 07 FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0E 00 00 00 32 00 00 00 2D 00 00 00 0B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 31 00 00' + '00 B1 00 00 00 F6 00 00 00 DF 00 00 00 65 00 00' + '00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 58 00 00 00 F2 00 00' + '00 FF 12 04 00 FF 02 00 00 FF 00 00 00 F6 00 00' + '00 71 00 00 00 08 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 12 00 00 00 9D 00 00 00 F6 00 00 00 FF 59 17' + '00 FF 97 2E 01 FF 6E 20 00 FF 06 00 00 FF 00 00' + '00 F0 00 00 00 65 00 00 00 08 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3A 00 00' + '00 C2 00 00 00 FF 17 03 00 FF 7A 37 1A FF BE 59' + '2D FF CF 9C 89 FF BF 81 6D FF 5A 1E 08 FF 06 00' + '00 FF 00 00 00 EE 00 00 00 5C 00 00 00 08 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 70 00 00 00 F3 00 00' + '00 FF 32 07 00 FF B1 63 41 FF D5 8F 70 FF E3 BF' + 'AF FF FF FF FF FF EA E7 EA FF C0 82 6C FF 64 1B' + '01 FF 00 00 00 FF 00 00 00 EE 00 00 00 5E 00 00' + '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 20 00 00 00 AC 00 00 00 FD 06 00 00 FF 61 1B' + '00 FF D5 9F 86 FF E2 A3 84 FF DB AE 9A FF FD FB' + 'FA FF FF FF FF FF FF FF FF FF E9 E3 E4 FF BD 87' + '77 FF 5A 1A 01 FF 02 00 00 FF 00 00 00 E6 00 00' + '00 52 00 00 00 08 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2A 00 00' + '00 C4 00 00 00 FF 08 00 00 FF 73 29 0F FF EE BD' + 'A5 FF EB AE 8B FF CA 7F 5C FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF E6 DF' + 'E1 FF BE 7A 63 FF 3D 0E 00 FF 00 00 00 FF 00 00' + '00 E2 00 00 00 3D 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 01 00 00 00 6C 00 00 00 E3 00 00' + '00 FF 2F 01 00 FF A7 66 50 FF F5 D0 B8 FF F3 B6' + '8D FF CF 89 67 FF F5 EB E8 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FD FD' + 'FE FF E4 DA DC FF B6 78 61 FF 44 11 00 FF 00 00' + '00 FF 00 00 00 CB 00 00 00 3C 00 00 00 01 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1C 00 00 00 8D 00 00 00 FF 07 00 00 FF 4D 1A' + '07 FF C9 81 63 FF FF E3 CD FF F7 BC 91 FF C7 71' + '47 FF F1 E5 E0 FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF E5 D8 DA FF B3 77 61 FF 33 0E' + '00 FF 00 00 00 FF 00 00 00 C8 00 00 00 33 00 00' + '00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 30 00 00' + '00 D3 00 00 00 FF 0B 00 00 FF 85 36 19 FF E9 B7' + '9F FF FF E6 CB FF F9 B8 88 FF CE 7B 50 FF F2 EE' + 'EF FF FF C8 98 FF FF D7 B6 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FD FE FF FF E5 DA DB FF BE 7D' + '65 FF 30 0B 00 FF 00 00 00 FF 00 00 00 D2 00 00' + '00 33 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 04 00 00 00 72 00 00 00 EA 00 00' + '00 FF 37 0B 00 FF B1 71 56 FF F7 D4 BE FF FF DF' + 'C0 FF FD C3 95 FF D0 80 56 FF E9 D4 CC FF FF D4' + 'AD FF FF 92 39 FF FF 98 44 FF FF D6 B4 FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FE FE FE FF FC FC FB FF F8 F6 F7 FF E4 D9' + 'DA FF B5 80 6B FF 3A 12 02 FF 00 00 00 FF 00 00' + '00 C8 00 00 00 39 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1F 00 00 00 9F 00 00 00 FF 08 00 00 FF 5F 28' + '11 FF D3 93 74 FF FF EF DE FF FF D9 B5 FF FC C5' + '9B FF D5 83 56 FF E6 CE C4 FF FF EB D2 FF FF 93' + '3A FF FF 94 3D FF FF 93 3B FF FF 95 3E FF FF DD' + 'BF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FD FB FB FF FA F8 F8 FF F8 F6 F6 FF F5 F3' + 'F4 FF E7 DA DA FF B6 82 6C FF 2A 0D 00 FF 00 00' + '00 FF 00 00 00 BF 00 00 00 29 00 00 00 02 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3D 00 00' + '00 E1 00 00 00 FF 12 00 00 FF 94 3F 15 FF F3 CF' + 'BC FF FF EC D7 FF FF D1 AC FF FF D8 B4 FF DC 91' + '64 FF E0 C0 B3 FF FF E9 D3 FF FF 99 44 FF FF 96' + '40 FF FF 98 44 FF FF 98 43 FF FF 97 42 FF FF 9B' + '46 FF FF D3 AE FF FF FF FF FF FF FF FF FF FE FD' + 'FD FF FC FA FA FF F9 F6 F6 FF F6 F3 F3 FF F4 F0' + 'F0 FF F1 ED EF FF E3 D6 D6 FF BD 77 57 FF 27 08' + '00 FF 00 00 00 FF 00 00 00 C4 00 00 00 28 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 02 00 00 00 60 00 00 00 DD 00 00' + '00 FF 2F 0C 00 FF A1 5E 3C FF F7 D5 C0 FF FF EA' + 'D2 FF FF D4 B0 FF FF DB B8 FF E3 A2 76 FF D6 9E' + '83 FF FF F8 F1 FF FF AB 64 FF FF 95 3D FF FF 9A' + '46 FF FF 99 46 FF FF 99 45 FF FF 9A 47 FF FF 9C' + '49 FF FF A8 5D FF FF E3 CA FF FF FF FF FF FD FC' + 'FD FF FA F8 F8 FF F7 F5 F5 FF F4 F1 F1 FF F2 EE' + 'EE FF F1 EC EC FF EB E6 E8 FF E1 CF CC FF A2 62' + '43 FF 24 0A 00 FF 00 00 00 FF 00 00 00 A1 00 00' + '00 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 12 00 00 00 9E 00 00 00 FF 00 00 00 FF 59 1E' + '00 FF D5 99 7A FF FF F5 E8 FF FF E4 C7 FF FF D9' + 'B8 FF FF E0 C1 FF ED B6 8E FF D7 A1 86 FF FD FA' + 'F6 FF FF AC 66 FF FF 98 41 FF FF 9C 49 FF FF 9C' + '49 FF FF 9C 49 FF FF 9C 48 FF FF 9C 49 FF FF A0' + '51 FF FF A3 54 FF FF A7 59 FF FE DF C3 FF FB FF' + 'FF FF F9 F7 F8 FF F6 F3 F3 FF F4 F0 F0 FF F1 EC' + 'EC FF EF E9 E8 FF EC E6 E6 FF E9 E3 E5 FF E4 D0' + 'CA FF AE 6B 48 FF 16 02 00 FF 00 00 00 FF 00 00' + '00 B0 00 00 00 1C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 48 00 00' + '00 C8 00 00 00 FF 21 04 00 FF 8E 4B 25 FF EF C7' + 'B0 FF FF F0 DE FF FF E3 C9 FF FF DE C0 FF FF E8' + 'CC FF EF BF 99 FF D2 93 71 FF F9 F0 E9 FF FF BF' + '86 FF FF 98 43 FF FF 9D 4C FF FF 9E 4C FF FF 9D' + '4B FF FF 9D 4B FF FF 9D 4B FF FF 9E 4B FF FF A2' + '53 FF FF A7 59 FF FF AA 5E FF FF B0 6A FF FD D7' + 'B5 FF F7 F8 FC FF F5 F3 F3 FF F2 ED ED FF F0 EA' + 'EA FF ED E7 E7 FF EA E3 E3 FF E9 E1 E1 FF E5 DE' + 'E1 FF E0 CA C3 FF B0 6B 44 FF 23 09 00 FF 00 00' + '00 FE 00 00 00 B1 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4C 00 00 00 EB 00 00' + '00 FF 37 11 00 FF B5 72 4C FF FC DD C8 FF FF F8' + 'E8 FF FF E4 C8 FF FF E3 C8 FF FF E9 CF FF F2 CA' + 'A9 FF D4 92 69 FF F8 EC E3 FF FF C4 8E FF FF 98' + '42 FF FF 9F 4F FF FF A0 4F FF FF A0 4E FF FF 9F' + '4E FF FF 9F 4E FF FF 9F 4D FF FF 9F 4E FF FF A3' + '54 FF FF A8 5C FF FF AD 64 FF FF B0 67 FF FF B4' + '6F FF FA D9 BC FF F4 F0 F1 FF F1 ED EE FF EF E9' + 'E9 FF EC E5 E5 FF E9 E2 E2 FF E7 DE DE FF E5 DC' + 'DC FF E2 DA DD FF E3 CC C3 FF A4 5F 37 FF 25 0B' + '00 FF 00 00 00 FF 00 00 00 A1 00 00 00 25 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 EB 02 00 00 FF 6A 2F' + '0C FF E4 AC 8B FF FF FA EF FF FF F1 DC FF FF E7' + 'CE FF FF E8 D0 FF FF EC D5 FF FC E3 C8 FF D2 8B' + '5F FF F0 D2 BD FF FF C9 96 FF FF 9E 4A FF FF A1' + '51 FF FF A2 52 FF FF A1 51 FF FF A1 51 FF FF A1' + '51 FF FF A1 51 FF FF A1 50 FF FF A1 50 FF FF A5' + '57 FF FF AA 5E FF FF AE 66 FF FF B3 6D FF FF B7' + '72 FF FF B9 74 FF F8 D6 B7 FF EF EC EF FF ED E8' + 'E9 FF EB E4 E4 FF E8 E0 E0 FF E6 DD DD FF E3 DA' + 'D9 FF E0 D6 D6 FF DE D5 D8 FF E2 C7 BD FF AF 63' + '36 FF 16 03 00 FF 00 00 00 FF 00 00 00 B0 00 00' + '00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 ED 06 01 00 FF 7A 3C' + '16 FF F7 CA AA FF FF F4 E0 FF FF E9 D2 FF FF E9' + 'D2 FF FF ED D7 FF FA E1 C7 FF D1 87 58 FF EF C6' + 'A8 FF FF CD 9E FF FF A0 4D FF FF A2 53 FF FF A3' + '54 FF FF A3 54 FF FF A3 54 FF FF A3 53 FF FF A3' + '53 FF FF A3 53 FF FF A3 53 FF FF A3 53 FF FF A7' + '59 FF FF AC 60 FF FF B0 68 FF FF B4 6F FF FF B9' + '76 FF FF BD 7C FF FF C1 81 FF F9 D4 B1 FF EC E6' + 'E8 FF E9 E3 E3 FF E7 DE DE FF E4 DB DB FF E2 D7' + 'D7 FF DF D4 D4 FF DD D1 D0 FF DB D2 D5 FF DF C3' + 'B8 FF A9 5E 30 FF 1D 08 00 FF 00 00 00 FE 00 00' + '00 B1 00 00 00 26 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 7D 00 00 00 FF 08 01' + '00 FF 96 46 13 FF FB CF AC FF FF F4 E1 FF FF EB' + 'D6 FF FF F1 DE FF DF A6 7E FF E2 A8 7F FF FF CF' + 'A1 FF FF A2 52 FF FF A2 52 FF FF A3 54 FF FF A3' + '54 FF FF A3 54 FF FF A3 54 FF FF A3 54 FF FF A3' + '54 FF FF A3 54 FF FF A3 54 FF FF A3 54 FF FF A7' + '5A FF FF AC 62 FF FF B1 69 FF FF B5 71 FF FF BA' + '78 FF FF BF 7F FF FF C3 85 FF FF C6 89 FF F5 D7' + 'B9 FF E8 E1 E3 FF E5 DD DE FF E4 DA DA FF E1 D6' + 'D6 FF DD D3 D3 FF DB CF CF FF D8 CB CB FF D9 CF' + 'D3 FF E6 C9 BA FF 95 50 23 FF 0C 00 00 FF 00 00' + '00 FF 00 00 00 91 00 00 00 17 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 01 00 00 00 7C 00 00' + '00 FF 0B 03 00 FF 89 49 1D FF F7 C4 9A FF FF FC' + 'EC FF DF A8 7F FF DE 98 67 FF FF CC 9D FF FF A8' + '5C FF FF A2 52 FF FF A4 56 FF FF A4 55 FF FF A4' + '55 FF FF A4 55 FF FF A4 55 FF FF A4 55 FF FF A3' + '55 FF FF A3 55 FF FF A3 54 FF FF A3 54 FF FF A7' + '5B FF FF AC 62 FF FF B0 69 FF FF B5 71 FF FF BA' + '78 FF FF BF 80 FF FF C4 87 FF FF C8 8C FF FF CC' + '91 FF F4 D7 B9 FF E4 DB DB FF E1 D8 D9 FF DF D5' + 'D5 FF DD D1 D1 FF DB CE CE FF D8 CA CA FF D4 C6' + 'C6 FF D5 CA CE FF E5 C3 B1 FF 9D 5D 34 FF 0A 00' + '00 FF 00 00 00 FA 00 00 00 99 00 00 00 13 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 76 00 00 00 FC 09 00 00 FF 87 4B 20 FF E7 AE' + '83 FF DF 95 60 FF FD C1 8C FF FF A9 5F FF FF A2' + '53 FF FF A4 57 FF FF A4 57 FF FF A4 57 FF FF A4' + '56 FF FF A4 56 FF FF A4 56 FF FF A4 56 FF FF A4' + '56 FF FF A4 56 FF FF A4 55 FF FF A3 55 FF FF A7' + '5B FF FF AC 62 FF FF B1 6A FF FF B5 71 FF FF BA' + '78 FF FF BE 7E FF FF C4 86 FF FF CA 92 FF FF D2' + '9E FF FF D9 A9 FF F4 DE C6 FF E0 D6 D7 FF DD D2' + 'D3 FF DB CF CF FF D9 CC CC FF D6 C8 C8 FF D3 C4' + 'C4 FF D0 BF BF FF D6 CC D0 FF E6 C5 B3 FF 96 54' + '29 FF 11 05 00 FF 00 00 00 F9 00 00 00 82 00 00' + '00 16 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 5F 00 00 00 FB 0D 03 00 FF B1 50' + '0F FF FD AB 6A FF FF B3 6D FF FF A3 55 FF FF A5' + '58 FF FF A5 58 FF FF A5 58 FF FF A4 58 FF FF A4' + '58 FF FF A4 58 FF FF A4 58 FF FF A4 57 FF FF A4' + '57 FF FF A4 57 FF FF A4 57 FF FF A4 57 FF FF A8' + '5C FF FF AC 63 FF FF B0 69 FF FF B5 70 FF FF BA' + '7A FF FF C3 88 FF FF CF 9D FF FF D7 AB FF FF DB' + 'B4 FF FF E0 BA FF FF E3 BE FF F4 E0 CA FF DD D1' + 'D1 FF D9 CD CE FF D8 CA CA FF D5 C6 C6 FF D2 C3' + 'C3 FF D0 C0 C0 FF CC BA BA FF D0 C3 C6 FF EA CC' + 'BD FF 97 55 26 FF 0D 02 00 FF 00 00 00 FF 00 00' + '00 7D 00 00 00 0E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9E 00 00 00 FF 26 12' + '04 FF B2 5F 23 FF FB 98 48 FF FF AA 5F FF FF A6' + '5A FF FF A6 59 FF FF A6 59 FF FF A6 59 FF FF A6' + '59 FF FF A5 59 FF FF A5 59 FF FF A5 59 FF FF A5' + '58 FF FF A5 58 FF FF A5 58 FF FF A5 58 FF FF A7' + '5B FF FF AC 62 FF FF B5 72 FF FF C2 89 FF FF CB' + '99 FF FF D2 A6 FF FF D7 AD FF FF DA B2 FF FF DD' + 'B8 FF FF E1 BD FF FF E4 C3 FF FF E9 C8 FF F4 E3' + 'CE FF DB CD CC FF D5 C7 C8 FF D4 C5 C5 FF D1 C2' + 'C2 FF CF BE BE FF CC BA BA FF C9 B5 B6 FF CC BD' + 'C0 FF E2 BE AD FF A2 65 3A FF 0E 05 00 FF 00 00' + '00 EC 00 00 00 30 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 14 00 00 00 AC 00 00' + '00 FF 27 12 03 FF A7 53 15 FF F9 93 40 FF FF A7' + '5B FF FF A7 5C FF FF A6 5B FF FF A6 5B FF FF A6' + '5B FF FF A6 5B FF FF A6 5B FF FF A6 5A FF FF A6' + '5A FF FF A6 5A FF FF A5 58 FF FF A5 58 FF FF AE' + '69 FF FF BB 7F FF FF C9 97 FF FF CF A2 FF FF D2' + 'A7 FF FF D5 AC FF FF D9 B1 FF FF DC B8 FF FF E0' + 'BD FF FF E3 C2 FF FF E7 C8 FF FF EA CD FF FF EF' + 'D2 FF F4 E5 D3 FF D7 C9 C8 FF D1 C2 C2 FF D0 C0' + 'C0 FF CE BD BD FF CB B9 B9 FF C8 B5 B5 FF C3 B0' + 'B0 FF D6 C7 CA FF BF 94 78 FF 18 09 00 FF 00 00' + '00 F4 00 00 00 2C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00' + '00 A6 00 00 00 FF 11 08 02 FF A1 4F 12 FF FA 93' + '3F FF FF AC 61 FF FF A7 5D FF FF A7 5C FF FF A6' + '5C FF FF A6 5C FF FF A6 5C FF FF A7 5B FF FF A6' + '5B FF FF A4 57 FF FF A9 60 FF FF BA 7F FF FF C5' + '94 FF FF CB 9C FF FF CE A1 FF FF D1 A6 FF FF D4' + 'AC FF FF D8 B1 FF FF DC B7 FF FF DF BD FF FF E3' + 'C2 FF FF E5 C7 FF FF E8 CC FF FF EC D1 FF FF EE' + 'D6 FF FF F3 DB FF F6 EB D9 FF D3 C3 C3 FF CD BC' + 'BC FF CD BB BB FF CA B7 B7 FF C6 B3 B4 FF CB B9' + 'BC FF BD 92 7B FF 31 19 0B FF 00 00 00 FF 00 00' + '00 8D 00 00 00 03 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 05 00 00 00 A6 00 00 00 FF 16 0B 03 FF A6 54' + '16 FF FA 94 41 FF FF AB 61 FF FF A9 5F FF FF A8' + '5D FF FF A8 5E FF FF A8 5D FF FF A6 5B FF FF A7' + '5D FF FF B2 71 FF FF C2 8E FF FF C8 9A FF FF C9' + '9B FF FF CD A0 FF FF D0 A6 FF FF D4 AC FF FF D7' + 'B1 FF FF DB B7 FF FF DE BC FF FF E1 C1 FF FF E4' + 'C6 FF FF E7 CB FF FF EA D0 FF FF ED D4 FF FF EF' + 'D9 FF FF F2 DD FF FF F8 E3 FF EE E5 D9 FF D1 C1' + 'C0 FF CA B7 B8 FF C8 B5 B5 FF CA B7 B8 FF CB A8' + '9A FF 46 2D 1D FF 00 00 00 FF 00 00 00 C8 00 00' + '00 1F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 87 00 00 00 FF 0D 06' + '02 FF 92 4B 14 FF FD 96 41 FF FF AB 63 FF FF A9' + '60 FF FF A8 5F FF FF A6 5B FF FF AB 64 FF FF C1' + '8C FF FF CB A0 FF FF CC A0 FF FF CB 9F FF FF CD' + 'A2 FF FF D1 A8 FF FF D4 AD FF FF D7 B2 FF FF DA' + 'B8 FF FF DE BD FF FF E1 C2 FF FF E4 C7 FF FF E7' + 'CB FF FF E9 D0 FF FF EC D4 FF FF EF D8 FF FF F1' + 'DD FF FF F4 E1 FF FF F7 E5 FF FF FD EC FF F2 EA' + 'E0 FF CA B8 B6 FF C8 B6 B9 FF CD AD A1 FF 57 35' + '1B FF 00 00 00 FF 00 00 00 D6 00 00 00 18 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 75 00 00' + '00 FD 0C 06 02 FF 7E 42 11 FF F3 91 3F FF FF AC' + '63 FF FF A7 5D FF FF B5 77 FF FF C8 9A FF FF CF' + 'A7 FF FF CE A5 FF FF CF A6 FF FF CF A7 FF FF D1' + 'AA FF FF D4 AF FF FF D8 B4 FF FF DA B9 FF FF DD' + 'BE FF FF E0 C2 FF FF E3 C7 FF FF E6 CC FF FF E9' + 'D0 FF FF EB D4 FF FF EE D8 FF FF F0 DC FF FF F2' + 'E0 FF FF F5 E4 FF FF F8 E9 FF FF F9 EB FF FD F3' + 'E0 FF F3 EC E4 FF DB BD B0 FF 68 46 30 FF 00 00' + '00 FF 00 00 00 D1 00 00 00 32 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 78 00 00 00 F1 00 00 00 FF 7F 43 12 FF EF 90' + '40 FF FF BC 80 FF FF D0 A8 FF FF D3 AD FF FF D2' + 'AC FF FF D2 AD FF FF D3 AD FF FF D3 AE FF FF D5' + 'B1 FF FF D8 B5 FF FF DB BA FF FF DD BF FF FF E0' + 'C4 FF FF E3 C8 FF FF E6 CC FF FF E8 D1 FF FF EB' + 'D5 FF FF ED D8 FF FF EF DC FF FF F2 E0 FF FF F4' + 'E3 FF FF F7 E8 FF FE F5 E6 FF FC EF DC FF FD F7' + 'EA FF FF F0 DA FF 83 5C 3B FF 00 00 00 FF 00 00' + '00 EB 00 00 00 3F 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 54 00 00 00 FD 00 00 00 FF 66 3A' + '14 FF F4 B8 85 FF FF D9 B8 FF FF D6 B3 FF FF D5' + 'B3 FF FF D6 B4 FF FF D6 B5 FF FF D7 B5 FF FF D9' + 'B8 FF FF DC BC FF FF DF C1 FF FF E1 C5 FF FF E4' + 'C9 FF FF E7 CE FF FF E8 D1 FF FF EB D5 FF FF EE' + 'D9 FF FF F0 DD FF FF F1 E0 FF FF F4 E4 FF FF F6' + 'E8 FF FE F2 E1 FF FB EB D7 FF FF FD F6 FF FF F6' + 'E4 FF 9C 66 38 FF 03 00 00 FF 00 00 00 F5 00 00' + '00 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 45 00 00 00 E0 01 00' + '00 FF 78 47 1B FF F2 B5 7F FF FF DC BE FF FF DA' + 'BB FF FF DA BB FF FF DB BC FF FF DB BD FF FF DC' + 'BF FF FF DF C3 FF FF E2 C7 FF FF E4 CB FF FF E6' + 'CF FF FF E9 D4 FF FF EB D6 FF FF ED DA FF FF F0' + 'DE FF FF F2 E1 FF FF F3 E5 FF FF F4 E6 FF FC EE' + 'DB FF FD F1 E0 FF FF FC F5 FF FF F5 E3 FF A7 7A' + '51 FF 07 00 00 FF 00 00 00 F3 00 00 00 60 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 8B 00 00' + '00 FF 69 42 1C FF ED AC 6F FF EE BC 90 FF FF E2' + 'C7 FF FF DE C2 FF FF DE C2 FF FF DF C4 FF FF E0' + 'C5 FF FF E2 C9 FF FF E5 CD FF FF E7 D1 FF FF E9' + 'D4 FF FF EC D8 FF FF EE DB FF FF F0 DF FF FF F1' + 'E2 FF FF F4 E6 FF FE F3 E5 FF FC EB D9 FF FD F2' + 'E2 FF FF FC F4 FF FF FF FE FF CB 9A 6C FF 1A 09' + '00 FF 00 00 00 FF 00 00 00 7D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 02 00' + '00 FF AA 6B 2D FF FF FA EA FF F1 D6 BF FF EC B8' + '88 FF FF E1 C9 FF FF E3 CB FF FF E2 CA FF FF E3' + 'CB FF FF E5 CF FF FF E8 D3 FF FF EA D6 FF FF EC' + 'D9 FF FF ED DD FF FF EF E0 FF FF F2 E3 FF FF F4' + 'E6 FF FD F0 E0 FF FD EF DE FF FE F4 E8 FF FF FB' + 'F4 FF FF FF F7 FF DC B0 84 FF 29 17 09 FF 00 00' + '00 FF 00 00 00 94 00 00 00 0B 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 94 01 00' + '00 FF 51 30 0F FF DF B0 7F FF FF FB F0 FF EF D0' + 'B3 FF F0 C5 9D FF FD E4 CD FF FF E6 D1 FF FF E7' + 'D2 FF FF E8 D5 FF FF EB D9 FF FF ED DC FF FF EF' + 'DF FF FF F0 E2 FF FF F2 E5 FF FF F3 E6 FF FE F0' + 'E1 FF FE F0 E1 FF FE F6 ED FF FF FA F3 FF FF FF' + 'FC FF E5 C3 A0 FF 3B 20 06 FF 00 00 00 FF 00 00' + '00 B0 00 00 00 07 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 1F 00 00' + '00 CC 00 00 00 FF 35 1B 00 FF D4 99 5A FF FF FF' + 'FE FF EC C3 9B FF F4 CE AA FF FF ED DC FF FF EA' + 'D8 FF FF EC DB FF FF EE DF FF FF F0 E1 FF FF F1' + 'E4 FF FF F3 E7 FF FE F2 E6 FF FE EF E0 FF FE F3' + 'E7 FF FF F8 F0 FF FF FA F3 FF FF FF FF FF F3 CD' + 'A6 FF 52 2F 0D FF 00 00 00 FF 00 00 00 B8 00 00' + '00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1A 00 00 00 AE 00 00 00 FF 23 13 01 FF BF 8D' + '56 FF F3 B6 77 FF F6 D4 B6 FF FF F0 E3 FF FF ED' + 'DF FF FF EF E1 FF FF F1 E4 FF FF F3 E7 FF FF F3' + 'E9 FF FE F2 E5 FF FE F2 E6 FF FF F6 ED FF FF F9' + 'F2 FF FF F9 F4 FF FF FF FF FF FB DE BE FF 55 37' + '1A FF 00 00 00 FF 00 00 00 CB 00 00 00 1E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 04 00 00 00 A1 00 00 00 FF 11 07' + '00 FF B5 72 2D FF FF EB CF FF FF F4 EA FF FF F1' + 'E5 FF FF F2 E7 FF FF F4 EA FF FF F4 EB FF FE F3' + 'E9 FF FE F4 EA FF FF F8 F2 FF FF FA F5 FF FF FB' + 'F6 FF FF FF FF FF F7 E5 D0 FF 76 4D 25 FF 00 00' + '00 FF 00 00 00 DB 00 00 00 25 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00' + '00 FF 23 14 04 FF C7 99 68 FF FF FF F2 FF FF F8' + 'F1 FF FF F5 ED FF FE F6 ED FF FE F4 EC FF FE F8' + 'F1 FF FF FA F6 FF FF FB F6 FF FF FC F8 FF FF FF' + 'FF FF FF F4 DE FF 8C 61 34 FF 00 00 00 FF 00 00' + '00 EA 00 00 00 3B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00' + '00 BB 00 00 00 FF 28 17 05 FF C1 9C 74 FF FF F6' + 'E7 FF FF FB F8 FF FE F8 F1 FF FF FA F6 FF FF FC' + 'F8 FF FF FC FA FF FF FD FB FF FF FF FF FF FF FD' + 'F5 FF AA 82 56 FF 0E 05 00 FF 00 00 00 F9 00 00' + '00 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 04 00 00 00 A8 00 00 00 FF 06 00 00 FF AB 84' + '58 FF FF FA EB FF FF FF FF FF FF FE FD FF FF FF' + 'FD FF FF FF FF FF FF FF FF FF FF FF FC FF C9 9B' + '66 FF 0F 05 00 FF 00 00 00 FF 00 00 00 68 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0A 00 00 00 74 00 00 00 FF 0E 05' + '00 FF 79 5C 3A FF FF ED D6 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FE FF C9 A5 7A FF 19 0D' + '00 FF 00 00 00 FF 00 00 00 82 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 67 00 00' + '00 EE 00 00 00 FF 6E 4E 29 FF F0 DD C5 FF FF FF' + 'F4 FF FF F1 DC FF D1 AC 80 FF 36 1D 02 FF 00 00' + '00 FF 00 00 00 8F 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 3F 00 00 00 E0 00 00 00 FF 48 2F 12 FF 87 5D' + '2D FF 53 38 19 FF 12 0A 00 FF 00 00 00 FF 00 00' + '00 AD 00 00 00 08 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 26 00 00 00 BF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 EC 00 00 00 83 00 00' + '00 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0A 00 00 00 75 00 00' + '00 84 00 00 00 60 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FC 3F FF FF 00 00 FF FF F8 1F FF FF 00 00 FF FF' + 'F0 0F FF FF 00 00 FF FF C0 07 FF FF 00 00 FF FF' + '80 03 FF FF 00 00 FF FF 00 01 FF FF 00 00 FF FC' + '00 00 FF FF 00 00 FF F8 00 00 7F FF 00 00 FF E0' + '00 00 3F FF 00 00 FF C0 00 00 1F FF 00 00 FF 80' + '00 00 0F FF 00 00 FE 00 00 00 0F FF 00 00 FC 00' + '00 00 03 FF 00 00 F8 00 00 00 03 FF 00 00 E0 00' + '00 00 01 FF 00 00 C0 00 00 00 00 FF 00 00 80 00' + '00 00 00 7F 00 00 00 00 00 00 00 3F 00 00 00 00' + '00 00 00 1F 00 00 00 00 00 00 00 07 00 00 00 00' + '00 00 00 07 00 00 00 00 00 00 00 03 00 00 C0 00' + '00 00 00 00 00 00 E0 00 00 00 00 00 00 00 F0 00' + '00 00 00 00 00 00 F0 00 00 00 00 00 00 00 F8 00' + '00 00 00 00 00 00 FC 00 00 00 00 01 00 00 FF 00' + '00 00 00 03 00 00 FF 00 00 00 00 07 00 00 FF C0' + '00 00 00 0F 00 00 FF E0 00 00 00 1F 00 00 FF F0' + '00 00 00 3F 00 00 FF F8 00 00 00 7F 00 00 FF F8' + '00 00 00 7F 00 00 FF F8 00 00 00 FF 00 00 FF F8' + '00 00 01 FF 00 00 FF FC 00 00 03 FF 00 00 FF FE' + '00 00 07 FF 00 00 FF FF 80 00 0F FF 00 00 FF FF' + '80 00 1F FF 00 00 FF FF C0 00 3F FF 00 00 FF FF' + 'E0 00 7F FF 00 00 FF FF F8 00 7F FF 00 00 FF FF' + 'FC 00 FF FF 00 00 FF FF FE 01 FF FF 00 00 FF FF' + 'FF 07 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0E 00 00 00 58 00 00' + '00 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 30 00 00 00 C1 09 00 00 FF 00 00' + '00 ED 00 00 00 59 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 61 00 00 00 E9 33 0D 00 FF 97 3E 19 FF 4D 1D' + '0A FF 00 00 00 F0 00 00 00 52 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 14 00 00 00 9A 02 00' + '00 FF 63 32 1D FF C6 78 55 FF F2 DA D2 FF CC A1' + '95 FF 44 17 07 FF 00 00 00 EB 00 00 00 4C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3B 00 00 00 CD 18 03 00 FF 9A 62' + '4A FF E0 9D 7D FF F1 DB D2 FF FF FF FF FF FD FD' + 'FE FF CA 9D 8F FF 3D 15 08 FF 00 00 00 E5 00 00' + '00 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 6F 00 00 00 F1 3B 15 09 FF CB 95 7B FF EE AA' + '83 FF E9 C8 B8 FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FD FC FE FF C8 9B 8D FF 39 14 07 FF 00 00' + '00 E2 00 00 00 3C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 03 00 00 00 80 00 00' + '00 FF 45 1B 0D FF E1 AC 91 FF FC BD 95 FF DB A5' + '8B FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FA F7 F9 FF B5 80 6E FF 1A 05' + '00 FF 00 00 00 CA 00 00 00 1E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1F 00 00 00 AC 07 00 00 FF 74 43' + '2F FF EF C3 A7 FF FC C4 9B FF DB A2 86 FF FA D0' + 'AF FF FF BE 87 FF FF FC FA FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF F4 EB EB FF A8 78' + '67 FF 16 05 00 FF 00 00 00 BB 00 00 00 1B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4A 00 00 00 DA 24 0A 00 FF AB 76 5E FF FF DE' + 'C1 FF FE CB A2 FF DC A0 80 FF F7 D7 BD FF FF 9D' + '49 FF FF 8E 31 FF FF BB 82 FF FF FB F8 FF FF FF' + 'FF FF FF FF FF FF FD FB FB FF FA FA FB FF F3 EA' + 'E9 FF A6 7B 6A FF 16 05 00 FF 00 00 00 B5 00 00' + '00 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 07 00 00 00 82 00 00' + '00 F9 50 28 15 FF D8 A9 8F FF FF E9 CE FF FE D1' + 'AA FF DE A2 81 FF F4 D5 C0 FF FF A6 58 FF FF 96' + '3E FF FF 98 44 FF FF 96 3E FF FF BD 85 FF FF FA' + 'F6 FF FE FF FF FF FA F8 F8 FF F6 F3 F3 FF F4 F2' + 'F3 FF F0 E4 E3 FF A5 74 5E FF 16 05 00 FF 00 00' + '00 B1 00 00 00 16 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 28 00 00 00 B8 0E 00 00 FF 86 55' + '3D FF F6 D3 BA FF FF EB D1 FF FE D9 B7 FF E2 A9' + '88 FF F1 D4 C1 FF FF B0 69 FF FF 98 40 FF FF 9C' + '49 FF FF 9C 48 FF FF 9D 4C FF FF A0 4E FF FF C1' + '89 FF FD F6 F1 FF F8 F9 FB FF F5 F0 F0 FF F1 EB' + 'EB FF EE EA EB FF ED E0 DD FF A6 74 5B FF 16 05' + '00 FF 00 00 00 B1 00 00 00 16 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4F 00 00 00 E2 30 13 04 FF BB 8B 70 FF FF ED' + 'D8 FF FF EB D1 FF FF E3 C7 FF E5 B0 8C FF ED CB' + 'B6 FF FF B9 7A FF FF 99 44 FF FF 9F 4D FF FF 9E' + '4D FF FF 9E 4C FF FF A0 4F FF FF A6 5A FF FF AA' + '5D FF FE C3 8D FF F7 EE E8 FF F2 F0 F2 FF EE E8' + 'E8 FF EB E3 E3 FF E8 E2 E3 FF EA DA D7 FF A7 72' + '56 FF 18 06 00 FF 00 00 00 B1 00 00 00 17 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 EA 53 27 0F FF E8 BF A3 FF FF F9 E7 FF FF EB' + 'D2 FF FF EF D8 FF EA BC 9B FF E7 BB 9E FF FF C0' + '86 FF FF 9C 47 FF FF A2 51 FF FF A1 51 FF FF A1' + '51 FF FF A1 50 FF FF A2 53 FF FF A9 5D FF FF B0' + '68 FF FF B3 6B FF FD C8 94 FF F1 EA E7 FF EC E8' + 'EA FF E9 E1 E1 FF E5 DC DB FF E2 DA DB FF E7 D4' + 'D0 FF A2 65 42 FF 08 00 00 FF 00 00 00 A8 00 00' + '00 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 EB 5F 32 18 FF F9 D2 B3 FF FF F4 DE FF FF EF' + 'DA FF F4 D4 B9 FF E1 A8 82 FF FD C5 93 FF FF A1' + '50 FF FF A2 53 FF FF A3 54 FF FF A3 54 FF FF A3' + '53 FF FF A3 53 FF FF A3 55 FF FF AB 60 FF FF B2' + '6B FF FF B9 76 FF FF BE 7A FF FA D1 A8 FF EC E4' + 'E2 FF E7 DF E2 FF E4 DA DA FF DF D4 D4 FF DD D4' + 'D6 FF E2 C5 B9 FF 7D 4A 2C FF 01 00 00 FF 00 00' + '00 86 00 00 00 05 00 00 00 00 00 00 00 00 00 00' + '00 51 00 00 00 F3 5A 2F 15 FF F1 C8 A5 FF FC E5' + 'CD FF E1 A2 77 FF FB BB 85 FF FF A5 56 FF FF A3' + '53 FF FF A4 55 FF FF A4 55 FF FF A4 55 FF FF A3' + '55 FF FF A3 55 FF FF A4 57 FF FF AB 61 FF FF B3' + '6C FF FF BA 77 FF FF C0 81 FF FF C6 87 FF F9 D4' + 'AC FF E7 DC DA FF E1 D7 D9 FF DE D2 D2 FF DA CD' + 'CD FF D8 CD D0 FF E1 C4 B8 FF 7F 4F 31 FF 01 00' + '00 FF 00 00 00 83 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 48 00 00 00 EB 56 2F 16 FF E3 94' + '5B FF FB B5 79 FF FF A8 5C FF FF A3 55 FF FF A4' + '58 FF FF A4 56 FF FF A4 56 FF FF A4 56 FF FF A4' + '56 FF FF A4 56 FF FF A5 58 FF FF AB 62 FF FF B2' + '6B FF FF B9 76 FF FF C2 85 FF FF CD 97 FF FF D7' + 'A7 FF F8 DF C1 FF E2 D6 D4 FF DB CF D0 FF D9 CB' + 'CB FF D4 C5 C4 FF D3 C6 C8 FF E2 C5 B8 FF 80 51' + '31 FF 02 00 00 FE 00 00 00 79 00 00 00 06 00 00' + '00 00 00 00 00 00 00 00 00 4E 00 00 00 FF 7A 40' + '16 FF FB 9E 51 FF FF AA 5C FF FF A6 5A FF FF A5' + '59 FF FF A5 59 FF FF A5 58 FF FF A5 59 FF FF A5' + '59 FF FF A4 57 FF FF A4 57 FF FF AB 62 FF FF B8' + '76 FF FF C6 8F FF FF D2 A3 FF FF DA B1 FF FF E0' + 'BA FF FF E5 C1 FF F8 E5 CB FF DE D0 CD FF D4 C6' + 'C7 FF D3 C3 C3 FF CE BC BC FF CD BE C0 FF DE C0' + 'B3 FF 85 56 37 FF 06 01 00 FE 00 00 00 4C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 6B 00 00' + '00 FB 6D 37 0D FF F5 92 41 FF FF AC 5F FF FF A7' + '5C FF FF A6 5B FF FF A6 5B FF FF A6 5B FF FF A5' + '59 FF FF A5 58 FF FF AE 68 FF FF C0 87 FF FF CC' + '9D FF FF D3 A9 FF FF D8 B0 FF FF DD B8 FF FF E2' + 'C0 FF FF E7 C8 FF FF EE D0 FF F8 EA D5 FF DA CB' + 'C8 FF CF BE BF FF CD BB BB FF C8 B5 B5 FF D3 C0' + 'C1 FF 9B 77 61 FF 09 03 00 FF 00 00 00 4B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 5B 00 00 00 F7 5D 2F 0C FF F1 90 41 FF FF AD' + '62 FF FF A8 5E FF FF A7 5D FF FF A6 5A FF FF AB' + '64 FF FF BC 83 FF FF C8 98 FF FF CE A1 FF FF D2' + 'A8 FF FF D7 B0 FF FF DC B8 FF FF E1 C0 FF FF E5' + 'C8 FF FF EA CF FF FF EE D6 FF FF F4 DE FF F8 EF' + 'DE FF D6 C6 C4 FF C8 B6 B7 FF D0 BC BD FF A0 80' + '70 FF 10 09 04 FF 00 00 00 8E 00 00 00 04 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 6B 00 00 00 FF 70 3A 0F FF FB 9C' + '4B FF FF AE 64 FF FF A6 5B FF FF AE 6A FF FF C6' + '95 FF FF CD A3 FF FF CD A1 FF FF D1 A8 FF FF D6' + 'B0 FF FF DB B8 FF FF DF C0 FF FF E4 C6 FF FF E8' + 'CD FF FF EC D4 FF FF F0 DB FF FF F3 E1 FF FF FC' + 'EA FF F5 EC E0 FF D3 C2 C3 FF BF A0 95 FF 29 19' + '0C FF 00 00 00 C7 00 00 00 0B 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 69 00 00 00 FB 6F 3C' + '12 FF F7 9B 4C FF FF BC 7F FF FF CD A3 FF FF D1' + 'AB FF FF D0 AA FF FF D2 AC FF FF D6 B1 FF FF DB' + 'B9 FF FF DF C0 FF FF E3 C7 FF FF E7 CD FF FF EB' + 'D4 FF FF EF DA FF FF F3 E0 FF FF F6 E6 FF FE F5' + 'E5 FF FF FF EF FF E9 D0 BA FF 43 2D 20 FF 00 00' + '00 D9 00 00 00 25 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' + '00 F2 60 36 14 FF ED BA 8B FF FF DB B9 FF FF D7' + 'B4 FF FF D6 B5 FF FF D8 B7 FF FF DC BC FF FF E0' + 'C2 FF FF E4 C9 FF FF E8 CF FF FF EB D5 FF FF EF' + 'DB FF FF F2 E1 FF FF F4 E5 FF FE F2 E1 FF FF FA' + 'EE FF F9 EA D3 FF 5B 41 2A FF 00 00 00 E4 00 00' + '00 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4F 00 00 00 F9 A5 74 48 FF FB CF A6 FF FF DE' + 'C1 FF FF DD C0 FF FF DD C1 FF FF E1 C6 FF FF E5' + 'CD FF FF E8 D2 FF FF EC D7 FF FF EE DD FF FF F2' + 'E2 FF FF F3 E4 FF FE F0 DF FF FF F9 EF FF FF F3' + 'E2 FF 70 52 37 FF 00 00 00 F0 00 00 00 42 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 23 03 00 00 FD BF 97 6F FF FF EA D3 FF F4 CC' + 'A9 FF FF E3 CB FF FF E3 CC FF FF E6 CF FF FF EA' + 'D5 FF FF EC DA FF FF EF DF FF FF F2 E4 FF FE F2' + 'E3 FF FE F0 E1 FF FF FA F3 FF FF FA ED FF 83 65' + '48 FF 00 00 00 F6 00 00 00 52 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 12 00 00 00 CD 37 23 0E FF D6 B6 91 FF FD E7' + 'D0 FF F6 D3 B4 FF FF EB D9 FF FF EB D9 FF FF EE' + 'DE FF FF F0 E2 FF FF F2 E6 FF FF F1 E4 FF FE F3' + 'E6 FF FF FA F4 FF FF FE F4 FF 98 79 5A FF 01 00' + '00 FC 00 00 00 65 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1C 00 00 00 D4 24 13 01 FF D7 A8' + '74 FF FE D8 B5 FF FF F1 E5 FF FF EF E1 FF FF F2' + 'E6 FF FF F4 E9 FF FE F2 E5 FF FF F6 EC FF FF FA' + 'F4 FF FF FF FF FF BB 9C 7B FF 06 01 00 FF 00 00' + '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2A 00 00 00 D3 36 1F' + '07 FF EB C5 9C FF FF FF F6 FF FF F4 EA FF FF F5' + 'EB FF FF F4 EB FF FF F7 F0 FF FF FB F7 FF FF FF' + 'FF FF E0 C8 AD FF 29 1A 0B FF 00 00 00 B7 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 22 00 00' + '00 DA 3E 2D 1A FF DE C5 A8 FF FF FF FD FF FF FA' + 'F5 FF FF FB F7 FF FF FD FB FF FF FF FF FF EC D9' + 'C2 FF 3A 27 14 FF 00 00 00 C7 00 00 00 16 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 22 00 00 00 C4 25 18 0A FF C6 B0 95 FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF F4 E5 D3 FF 4B 36' + '20 FF 00 00 00 D6 00 00 00 22 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 10 00 00 00 A6 12 09 01 FF AA 94' + '7A FF FF F6 EA FF F0 DE C8 FF 5E 46 2B FF 00 00' + '00 E3 00 00 00 2E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 84 05 01' + '00 FF 44 31 1A FF 26 19 0A FF 00 00 00 E1 00 00' + '00 3D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 54 00 00 00 84 00 00 00 67 00 00 00 1F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FC' + '7F FF FF F8 3F FF FF F0 1F FF FF C0 0F FF FF 80' + '07 FF FF 00 03 FF FC 00 01 FF F8 00 00 FF F0 00' + '00 7F C0 00 00 3F 80 00 00 1F 00 00 00 0F 00 00' + '00 07 00 00 00 03 00 00 00 01 80 00 00 00 C0 00' + '00 00 E0 00 00 00 F0 00 00 00 F8 00 00 01 FC 00' + '00 03 FE 00 00 07 FF 00 00 0F FF 00 00 1F FF 00' + '00 3F FF 80 00 7F FF C0 00 7F FF E0 00 FF FF F0' + '01 FF FF F8 03 FF FF FC 07 FF FF FF 0F FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 10 00 00 00 8A 00 00 00 67 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 36 1E 0B' + '04 C9 9D 6B 56 FF 5D 3E 32 FE 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 69 4C 2F 21 EF CE 9D' + '87 FF FF FF FE FF F0 E3 DF FF 50 36 2D F9 00 00' + '00 5D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0A 00 00 00 90 71 4F 3D FF EE B2 90 FF FD D2' + 'B5 FF FF FF FD FF FF FF FF FF E8 D7 D1 FF 3C 27' + '1F F3 00 00 00 47 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 1A 0D' + '07 BF A6 83 6D FF FB CC AC FF F7 BA 8F FF FF 9A' + '44 FF FF C3 91 FF FF FD FC FF FF FF FF FF DC C7' + 'C1 FF 38 26 1D E9 00 00 00 40 00 00 00 00 00 00' + '00 00 00 00 00 00 02 01 00 5C 47 33 27 E8 D6 B9' + 'A1 FF FF E0 C2 FF F3 BF 98 FF FF A3 55 FF FF 9A' + '44 FF FF 9D 4A FF FF CB 9D FF F5 F2 F2 FF F6 F2' + 'F5 FF D5 BD B4 FF 39 24 19 E9 00 00 00 3E 00 00' + '00 00 00 00 00 00 29 16 0B F2 F3 D0 B4 FF FF F3' + 'DC FF EF BC 94 FF FE A9 60 FF FF 9F 4D FF FF A1' + '51 FF FF A5 57 FF FF B1 67 FF F9 D1 AA FF E9 E2' + 'E3 FF EA E2 E5 FF CA AB 9D FF 28 17 0D E2 00 00' + '00 2D 00 00 00 00 06 03 02 67 6D 53 3F FB F7 B8' + '88 FF FF AD 65 FF FF A3 52 FF FF A4 56 FF FF A3' + '54 FF FF A7 5A FF FF B5 6F FF FF C5 88 FF F5 D9' + 'BD FF DE D4 D4 FF DE D1 D3 FF BD 9F 92 FF 2D 1E' + '13 D8 00 00 00 2D 00 00 00 00 00 00 00 6E 76 43' + '1B FF FD A4 53 FF FF AA 5D FF FF A5 57 FF FF A4' + '56 FF FF B0 6C FF FF C6 91 FF FF D7 AE FF FF E4' + 'C0 FF F3 E2 D0 FF D3 C5 C5 FF D9 C7 C9 FF A5 85' + '75 FF 06 03 01 9C 00 00 00 00 00 00 00 00 00 00' + '00 6D 6E 3E 18 FF FF A6 58 FF FF AE 65 FF FF BD' + '85 FF FF CC A0 FF FF D7 B2 FF FF E0 C0 FF FF E9' + 'CE FF FF F3 DC FF F3 EA DF FF CB B4 AF FF 3C 30' + '2A EB 01 01 00 32 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 6F 71 43 1E F6 F7 C2 90 FF FF D8' + 'B5 FF FF D7 B4 FF FF DF C1 FF FF E7 CE FF FF EE' + 'DA FF FF F8 E8 FF FF F7 E4 FF 61 51 44 F8 00 00' + '00 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9F D0 AA 86 FF FF E6' + 'CA FF FF E1 C9 FF FF E8 D3 FF FF EE DD FF FF F4' + 'E7 FF FF FC ED FF 7C 6B 5A FD 00 00 00 64 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 43 53 43 32 F4 F3 D2' + 'B0 FF FF F1 E0 FF FF F0 E3 FF FF F4 E8 FF FF FF' + 'FB FF 98 86 75 FF 00 00 00 7D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 4E 59 47' + '34 F4 F5 EA D9 FF FF FF FC FF FF FF FF FF BA AC' + '9C FF 0C 07 03 A2 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 45 47 3C 31 E3 E3 DC D4 FF C9 BE B0 FF 16 10' + '09 B4 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2B 19 12 0A BB 0D 09 03 A0 00 00' + '00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FC 7F 00 00 F8 3F 00 00 F0 1F' + '00 00 C0 0F 00 00 80 07 00 00 00 03 00 00 00 01' + '00 00 00 00 00 00 80 00 00 00 C0 00 00 00 E0 01' + '00 00 F0 03 00 00 F0 07 00 00 F8 07 00 00 FC 0F' + '00 00 FE 1F 00 00' +} */ + +/* BINRES folder_open.ico */ +4 ICON folder_open.ico +/* { + '00 00 01 00 06 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 66 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 0E 09 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 76 0E 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 1E 34 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 C6 44 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 2E 49 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 B7 35 09 00 C4 3D 06 00 B5 44 16 00 B5 48' + '23 00 BE 50 2B 00 CE 48 0F 00 CC 4A 15 00 CB 53' + '1B 00 D4 58 1A 00 DC 66 1F 00 C5 53 26 00 D0 5A' + '22 00 D0 59 31 00 DE 69 20 00 DA 72 2B 00 CE 63' + '3C 00 D5 67 31 00 DF 6F 37 00 DC 72 30 00 E4 6C' + '24 00 EA 78 27 00 EB 6D 31 00 E8 75 36 00 F1 76' + '30 00 BB 6C 4F 00 C4 6D 55 00 C4 76 5D 00 CE 7D' + '5F 00 D2 74 50 00 D4 7A 5B 00 E6 72 41 00 C5 7F' + '6B 00 C8 7B 68 00 DB 7E 65 00 F8 8A 29 00 EF 88' + '35 00 F2 8A 34 00 FD 99 35 00 FC 9B 3B 00 FF A3' + '3A 00 BC 89 79 00 E9 88 46 00 E5 85 4B 00 F5 9A' + '44 00 FD 9D 45 00 F0 95 49 00 FA 9C 4D 00 EA 81' + '5B 00 FF A6 40 00 FF A9 45 00 F4 A0 49 00 FF AD' + '4E 00 FA A0 53 00 FE A9 53 00 FD A6 58 00 FA AA' + '5B 00 FF B2 55 00 FF B3 5C 00 C5 80 6C 00 CB 82' + '6C 00 D5 84 69 00 C3 85 77 00 CA 8B 77 00 D4 89' + '78 00 CD 90 7C 00 DA 9B 7E 00 EF 9D 65 00 ED 97' + '6F 00 F4 9E 63 00 F5 9C 6F 00 E3 8C 78 00 E0 9D' + '7E 00 E8 9A 7D 00 F0 9B 79 00 FA AF 65 00 F6 AB' + '6C 00 FD B2 62 00 FF BA 65 00 FE B6 6E 00 FF BF' + '6D 00 EC A1 76 00 EB A2 7A 00 F2 A6 75 00 F7 AC' + '70 00 F0 A3 7D 00 F5 AC 7F 00 FE B7 71 00 FC BC' + '72 00 F9 BA 7F 00 FE C4 78 00 92 8F 8D 00 91 90' + '8E 00 9F 93 8F 00 93 91 91 00 9B 96 94 00 9C 9B' + '9B 00 BC 8F 82 00 A1 93 8D 00 BC 92 85 00 B1 96' + '8A 00 A3 95 91 00 A5 98 94 00 A0 9E 9F 00 BC 9A' + '93 00 BE 9E 98 00 A8 A0 9C 00 B6 A1 9D 00 B9 A3' + '9F 00 A4 A2 A2 00 A9 A6 A6 00 AD AA A6 00 A9 A5' + 'A8 00 AE AB AC 00 B7 A7 A1 00 B9 A3 A0 00 B6 A8' + 'A3 00 BA AA A5 00 B3 AB AB 00 B5 B1 AD 00 B4 AE' + 'B0 00 BB B3 B7 00 C1 93 84 00 C2 93 89 00 CE 97' + '8B 00 C2 9A 8D 00 CF 99 8A 00 D6 98 87 00 C3 9F' + '92 00 CB 9D 92 00 DF 9D 90 00 E4 9A 88 00 C2 A1' + '97 00 CB A0 92 00 C3 A6 9C 00 C8 A4 99 00 DC A4' + '91 00 DB A9 91 00 D0 A3 99 00 E8 A7 80 00 EC AD' + '83 00 F0 AA 82 00 F3 AB 89 00 F0 B7 80 00 FF BF' + '85 00 F3 B2 8C 00 F8 B1 88 00 F5 BB 8C 00 F8 BE' + '8E 00 F1 AE 9A 00 EE B2 95 00 F7 B8 96 00 C1 AC' + 'A5 00 D7 AA A4 00 C4 B1 AD 00 D7 B0 A1 00 DA B5' + 'A6 00 DA B4 AA 00 D9 BB AF 00 C2 BC BD 00 D0 B3' + 'B2 00 DA BD B4 00 D0 BB BB 00 E0 B2 A5 00 EE BD' + 'A2 00 E3 B4 AA 00 E4 BB AF 00 F1 B6 A7 00 F6 BE' + 'A2 00 F0 BA AB 00 E5 BE B3 00 EC BC B0 00 E2 BF' + 'BB 00 FD C9 86 00 F4 C4 97 00 FF CB 95 00 FB C4' + '9C 00 FE CC 9D 00 FD D1 93 00 FE D5 9C 00 FE DB' + '9E 00 EC C5 AF 00 F4 C2 A5 00 FD CD A1 00 F5 C8' + 'AA 00 F9 CB AB 00 FD D4 A3 00 FF DE A4 00 FD D3' + 'AC 00 FD DB A9 00 E9 C2 B7 00 F1 C2 B5 00 F3 CA' + 'B3 00 FA D2 B3 00 FD DC B5 00 FB D6 BB 00 FB DC' + 'BC 00 FF E0 A5 00 FF E2 AE 00 FF E3 B2 00 FE E6' + 'BE 00 FF E8 BF 00 C3 BF C0 00 D0 C1 C1 00 DB C5' + 'C0 00 DD C6 CC 00 DF CA CB 00 DF CF D0 00 EB C5' + 'C0 00 EB CF CA 00 F9 CD C6 00 FC D3 C5 00 FC DC' + 'C5 00 F0 D3 CA 00 FF D7 CB 00 FA DD CA 00 E0 CF' + 'D0 00 E5 D7 DA 00 FA D8 D1 00 F0 DC D9 00 FE E4' + 'C1 00 FF E9 C3 00 FF EE CE 00 F0 E0 D4 00 FC E2' + 'D3 00 FF EE D0 00 F0 E1 DF 00 FD E5 DA 00 FE EB' + 'DC 00 FF F0 D5 00 FE F2 DD 00 ED DE E0 00 F0 DF' + 'E2 00 F1 E3 E3 00 FD E9 E5 00 F0 E7 EF 00 F1 EB' + 'EC 00 FE F5 E3 00 FF F3 EB 00 FF FA EE 00 F3 EE' + 'F0 00 FE F3 F2 00 FF FA F1 00 FF F7 FF 00 FF F9' + 'FC 00 7F 7F 7F 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 40 B4' + '0C 01 66 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 5F 5F 5F 5C 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 A5 99 98 76 70 60 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 7F 83 88 7E 68 74 71 67 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 65 47 A7 E3 A9 83 7E 68 75 71 6D 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 9D 8E 95 F4 F4 EA BF 82 7C 68 73 71 6D' + '5C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 9B B1 95 F4 F4 F3 F1 E9 D0 83 7F 7A 6B' + '76 6E 5E 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 89 BA 91 F1 F4 F3 F1 F1 EC E8 AB 83 41' + '63 69 76 70 5E 00 00 00 00 00 00 00 00 00 00 00' + '00 00 62 89 C5 93 E0 E3 F1 F1 F0 F0 EB E9 E2 AA' + '83 40 3E 68 6B 71 6D 00 00 00 00 00 00 00 00 00' + '00 00 BE B6 B4 93 B0 90 B7 C3 DF EC EB E9 E2 E7' + 'E7 AC 83 40 3E 7B 6C 71 70 5C 00 00 00 00 00 00' + '00 00 AB C1 C5 94 97 4F 36 37 8F C0 D5 DB E7 E7' + 'E7 D9 D8 AC 82 3D 20 63 6B 77 6D 00 00 00 00 00' + '00 00 95 C2 C7 B0 91 5A 4D 36 2C 2E 43 96 BE D1' + 'D9 D9 D8 CF CF A1 7E 3C 1B 69 CA 00 00 00 00 00' + '00 66 95 C2 C7 B7 8D AD 4E 3A 36 2C 24 18 2B 48' + 'A5 AC D8 CF CF CD CB A0 3D 3E 9F 60 00 00 00 00' + '00 9E C0 C4 C7 BD 55 B2 5A 4E 3A 36 2C 24 15 14' + '12 3D 88 9D CE CD CB A2 8A 20 9F 6D 00 00 00 00' + '00 9E D4 C8 C9 BD 4A BA AD 5A 4E 3A 34 2C 24 15' + '0E 0C 0C 1D 7F 99 A0 A2 A0 21 79 70 00 00 00 00' + '00 9C E1 DD C9 C2 8E BC AD AD 5A 4E 39 36 2C 25' + '15 0E 0C 08 07 10 3C 7B 8A 21 73 6E 00 00 00 00' + '5D A6 E5 DE DD C4 95 B9 B3 B2 AD 5A 4E 3A 36 2D' + '25 15 14 09 08 06 02 04 19 1A 63 6F 00 00 00 00' + 'D0 D3 E5 E1 DE DC B8 A8 B0 B0 AF AD 5A 4E 3A 39' + '32 26 25 15 0A 09 06 01 03 05 20 76 00 00 00 00' + 'D0 E0 E6 E5 E1 DE DD BC 97 97 B0 94 94 90 50 3A' + '34 32 31 26 23 14 09 01 08 0B 1A 76 00 00 00 00' + 'AB E4 E6 E6 E5 E1 DE DD C9 C2 B7 91 8E 97 AF 50' + '39 34 32 31 28 23 14 08 0C 0B 10 75 60 00 00 66' + 'BF ED ED ED E6 E5 E1 DE DD C9 C9 C7 BA 92 97 AD' + '50 39 34 32 31 26 18 17 0F 0C 0D 69 67 00 00 A1' + 'D6 EE F2 ED E6 E6 E5 E1 DE DD C9 C8 C7 B7 52 91' + '59 57 4D 39 32 27 16 2F 33 13 0D 61 6D 00 00 CC' + 'EA F2 F2 EF ED ED E6 E5 DE DE DD C9 C9 C7 B1 8D' + '8E 92 56 4C 38 35 1F 4B 4E 2E 11 3B 70 00 00 A1' + 'F1 F4 F2 F2 F2 ED E6 E6 E5 E1 DE DD C9 C8 C7 C6' + 'BA 94 52 51 53 46 30 54 58 4B 2A 1C 78 00 00 A1' + 'EA EA F1 EE F2 EF ED E6 D7 C3 C4 DC DC C9 C9 C7' + 'C7 C6 C5 B3 93 44 22 49 8E 53 45 1E 77 00 00 74' + '98 9D D2 DA E0 E3 E4 D4 A9 87 86 B5 C1 B9 C1 C2' + 'C7 C7 C7 C5 B4 8C 81 98 84 61 29 3F 00 00 00 00' + '00 5B 98 98 86 A5 A6 A3 98 00 00 72 86 80 86 A4' + 'B9 B7 BA BD BB 8B 9A 00 00 00 00 6A 00 00 00 00' + '00 00 00 00 00 66 5D 66 00 00 00 00 00 00 00 6B' + '7D 85 B6 B0 AE 42 76 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 9A 84 63 64 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FC 3F FF FF FC 0F FF FF FC 03 FF FF F8 00' + 'FF FF F8 00 1F FF F8 00 07 FF F8 00 01 FF F0 00' + '00 7F F0 00 00 0F F0 00 00 07 F0 00 00 07 E0 00' + '00 03 E0 00 00 03 E0 00 00 03 E0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 01 80 00' + '00 01 80 00 00 01 80 00 00 01 80 00 00 01 80 00' + '00 01 80 00 00 03 E0 18 00 7B FE 3F 80 7F FF FF' + 'F0 FF FF FF FF FF FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 B8 47 1D 00 C9 45' + '0E 00 CB 55 1F 00 D7 5F 1F 00 DE 65 1E 00 D0 59' + '28 00 CE 68 3F 00 E2 69 24 00 E7 77 27 00 EB 7B' + '2F 00 F0 7F 39 00 C7 6B 4E 00 DE 7A 45 00 C9 7B' + '60 00 F3 8B 32 00 FD 9C 35 00 BE 80 70 00 BF 91' + '7F 00 F0 96 46 00 F6 99 44 00 F7 99 44 00 E8 8D' + '51 00 ED 8A 5E 00 FD A4 44 00 FF AA 46 00 FF AA' + '49 00 F7 A2 52 00 FF B2 59 00 FF B5 59 00 FF B2' + '5D 00 FF B3 5E 00 C4 84 72 00 EF A1 6B 00 FF B4' + '62 00 FF B5 68 00 F2 A7 73 00 F8 B3 71 00 F8 B5' + '7E 00 FF C3 73 00 FF C5 7A 00 FF C7 7A 00 96 8A' + '85 00 96 90 8E 00 99 91 8E 00 92 91 90 00 96 95' + '94 00 9F 97 94 00 9A 98 97 00 9C 99 98 00 9E 9C' + '9C 00 A6 96 91 00 AD 9C 95 00 B6 9D 93 00 A6 A0' + '9F 00 BB A0 94 00 B7 A0 9B 00 B1 A2 9F 00 BB A0' + '9A 00 A6 A2 A3 00 AE A7 A5 00 AC A7 A8 00 B3 A3' + 'A3 00 BF AB A6 00 BF AE AB 00 B7 AF B0 00 C9 8E' + '82 00 C4 95 8B 00 C9 94 88 00 CD 9A 8E 00 D9 9C' + '85 00 C3 9C 95 00 C2 9E 95 00 CE 9D 91 00 D1 9F' + '94 00 CD A0 90 00 C6 AA 9F 00 DA A3 98 00 DF AA' + '98 00 DF A9 9A 00 DC AB 9F 00 EC B5 8D 00 F1 B2' + '83 00 F3 B3 8B 00 F5 B6 8A 00 F7 B5 8E 00 F7 B8' + '8A 00 EE AC 93 00 F6 BB 99 00 CF B3 A9 00 D9 B0' + 'A0 00 D1 B7 B1 00 D9 BD B2 00 E9 BC A3 00 E5 BE' + 'AF 00 EA BC A8 00 FD C3 8C 00 FF D1 8F 00 FE C7' + '92 00 F8 C3 98 00 F9 C2 9B 00 FC C1 99 00 FF C8' + '9B 00 FA CF 9C 00 FB D0 97 00 FD CD A3 00 F8 CE' + 'AE 00 FC D0 A1 00 F7 D0 AE 00 FF DD AC 00 F4 CB' + 'B0 00 F2 CA B5 00 FF DF B2 00 FF E2 AD 00 FE E0' + 'B3 00 FF E1 B3 00 FF E4 B6 00 FE E0 BA 00 D3 C0' + 'C2 00 DE C1 C1 00 DF C4 C3 00 EF CA C3 00 EA D0' + 'CF 00 F6 D7 CE 00 F6 DA CF 00 F3 DD CD 00 E0 D0' + 'D1 00 EE D6 D4 00 E3 D4 D8 00 FA DF DB 00 FB E2' + 'C7 00 FF E8 C0 00 FF E8 C1 00 FF ED CB 00 FF EC' + 'CC 00 FF ED CC 00 EF E0 DF 00 FB E2 D3 00 FF EB' + 'D2 00 FF F0 D5 00 FF F1 D6 00 FC E5 E0 00 FC E7' + 'E4 00 F0 E6 EA 00 F7 ED ED 00 FB EB EA 00 FF F4' + 'E0 00 FF F9 ED 00 FF FA F6 00 FF F6 FB 00 7F 7F' + '7F 00 F7 B8 96 00 C1 AC A5 00 D7 AA A4 00 C4 B1' + 'AD 00 D7 B0 A1 00 DA B5 A6 00 DA B4 AA 00 D9 BB' + 'AF 00 C2 BC BD 00 D0 B3 B2 00 DA BD B4 00 D0 BB' + 'BB 00 E0 B2 A5 00 EE BD A2 00 E3 B4 AA 00 E4 BB' + 'AF 00 F1 B6 A7 00 F6 BE A2 00 F0 BA AB 00 E5 BE' + 'B3 00 EC BC B0 00 E2 BF BB 00 FD C9 86 00 F4 C4' + '97 00 FF CB 95 00 FB C4 9C 00 FE CC 9D 00 FD D1' + '93 00 FE D5 9C 00 FE DB 9E 00 EC C5 AF 00 F4 C2' + 'A5 00 FD CD A1 00 F5 C8 AA 00 F9 CB AB 00 FD D4' + 'A3 00 FF DE A4 00 FD D3 AC 00 FD DB A9 00 E9 C2' + 'B7 00 F1 C2 B5 00 F3 CA B3 00 FA D2 B3 00 FD DC' + 'B5 00 FB D6 BB 00 FB DC BC 00 FF E0 A5 00 FF E2' + 'AE 00 FF E3 B2 00 FE E6 BE 00 FF E8 BF 00 C3 BF' + 'C0 00 D0 C1 C1 00 DB C5 C0 00 DD C6 CC 00 DF CA' + 'CB 00 DF CF D0 00 EB C5 C0 00 EB CF CA 00 F9 CD' + 'C6 00 FC D3 C5 00 FC DC C5 00 F0 D3 CA 00 FF D7' + 'CB 00 FA DD CA 00 E0 CF D0 00 E5 D7 DA 00 FA D8' + 'D1 00 F0 DC D9 00 FE E4 C1 00 FF E9 C3 00 FF EE' + 'CE 00 F0 E0 D4 00 FC E2 D3 00 FF EE D0 00 F0 E1' + 'DF 00 FD E5 DA 00 FE EB DC 00 FF F0 D5 00 FE F2' + 'DD 00 ED DE E0 00 F0 DF E2 00 F1 E3 E3 00 FD E9' + 'E5 00 F0 E7 EF 00 F1 EB EC 00 FE F5 E3 00 FF F3' + 'EB 00 FF FA EE 00 F3 EE F0 00 FE F3 F2 00 FF FA' + 'F1 00 FF F7 FF 00 FF F9 FC 00 7F 7F 7F 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 40 B4 0C 01 66 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 2F 31 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 45 4F 48 3D 2D 00 00' + '00 00 00 00 00 00 00 00 00 57 8E 81 50 47 3C 2E' + '00 00 00 00 00 00 00 00 00 63 8D 95 90 7F 4E 43' + '3E 30 00 00 00 00 00 00 59 67 65 66 7D 8F 88 7A' + '4D 42 38 3B 00 00 00 00 5A 6D 56 22 1B 21 5F 80' + '7E 78 4A 20 41 00 00 00 6F 74 54 29 1E 14 0A 0D' + '46 77 76 49 40 00 00 00 82 83 58 61 27 1C 15 09' + '04 06 0E 44 3A 00 00 5B 8A 87 6A 64 62 28 1F 18' + '0F 05 02 01 11 00 00 5C 92 8C 86 75 69 55 60 1D' + '19 10 08 03 0C 32 2B 7B 93 92 8C 87 84 70 53 26' + '23 1A 0B 13 07 36 2C 91 94 93 92 8B 85 84 72 6B' + '52 24 17 25 16 39 00 3F 79 7C 89 5E 4C 6E 6C 73' + '71 68 4B 35 12 2A 00 00 00 00 33 00 00 00 00 37' + '5D 51 34 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E7 FF 00 00 E0 FF 00 00 E0 3F' + '00 00 E0 0F 00 00 C0 03 00 00 C0 01 00 00 C0 01' + '00 00 C0 01 00 00 80 01 00 00 80 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 F7 87 00 00 FF FF' + '00 00 FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D5 C9' + 'BE 1C DC C8 BE 54 D4 C6 BE 54 CF C4 BF 54 CB C4' + 'BF 54 CF C7 C2 41 D2 CA C6 2E D6 CE C9 1B DA D3' + 'CD 0C D8 D2 C9 03 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DC C8' + 'BE 54 F0 C5 BC FF DA BF BE FF CA BA BF FF BF B8' + 'BF FF C9 C2 C9 C3 D4 CC D4 8A DF D8 DF 54 EA E7' + 'EA 26 E6 E2 DF 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D8 BE' + 'B4 54 E5 A7 9E FF DE 9C 90 FF D5 96 89 FF CA 95' + '89 FF C6 A1 9B EB C2 AE AD D8 BF BD BF C6 CA C9' + 'CA 96 D3 D0 D1 6B DA D2 D4 43 E1 DA DB 24 DE D7' + 'D4 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 B7' + 'AB 54 E0 91 84 FF E3 95 84 FF E3 9B 88 FF DF A2' + '8F FF D4 9B 8C FF C9 99 8E FF BF 9D 95 FF BF A9' + 'A3 DF C4 B8 B6 BD CF C9 CF 98 DA D4 DA 6C DA D5' + 'D6 47 D1 CC C4 27 D8 D1 CB 17 D8 D0 C9 0A 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 B2' + 'A4 54 E0 84 6F FF EA AB 9A FF F5 C9 BA FF FF DF' + 'D0 FF F4 AF 9A FF E9 8C 75 FF DF 78 5F FF C9 88' + '74 FF BA 9A 8F FF B0 AF B0 FF BA B9 BA DB C5 C4' + 'C5 AE D0 D0 D0 78 E4 DF E4 46 E5 DD DF 1E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 DF C7 BD 71 E7 B4' + 'A6 C6 EA 90 79 FF ED A1 8F FF F4 C1 B6 FF FF F2' + 'EF FF FB E2 DD FF F7 D2 CA FF F4 C1 B4 FF E6 AA' + '98 FF D6 98 84 FF C5 89 7A FF C1 94 8B F3 BD A4' + 'A1 E4 BA BA BA D1 C8 C3 C8 B1 CF C9 CD 89 D0 CD' + 'CA 5B D7 D4 D1 39 D8 D3 CD 1A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 C4 BA A9 F1 B9' + 'A8 FF F4 A9 8A FF F0 A0 8A FF F4 BC B0 FF FF FC' + 'FF FF FF FC FF FF FF F6 F8 FF FF EC EA FF F8 CE' + 'C3 FF EC B3 A2 FF DA 99 89 FF D2 96 89 FF C9 97' + '8D FF BF 9C 95 FF BF A3 9F EF C1 AF AD D5 C5 C1' + 'C0 B0 CF CC CD 8A D3 CF CF 60 D1 C9 C4 33 D4 CE' + 'C8 22 D5 CE C6 10 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 C2 B5 A9 F4 C3' + 'AA FF FF CD A0 FF F4 A9 8A FF F4 B8 AA FF FF FC' + 'FF FF FF FC FF FF FF FA FF FF FF F7 FF FF FF F3' + 'F5 FF FA EB EA FF F0 DF DF FF EF BD B4 FF E9 9B' + '89 FF DF 77 5F FF CA 7F 6A FF BA 8F 7F FF B0 A7' + 'A0 FF B9 B1 B4 F3 C4 BC C4 D2 CF C8 CF 9C DA D7' + 'DA 66 DB D8 D5 32 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 B8 A6 A9 F4 BA' + '9C FF FF D1 A0 FF F4 A7 83 FF F4 B5 A2 FF FF FC' + 'FF FF FF FC FF FF FF FA FF FF FF F7 FF FF FF F3' + 'F5 FF FD EE EE FF FA E9 EA FF F3 DE DC FF ED CF' + 'CA FF EA BC B4 FF E3 A9 9B FF DA 97 83 FF CF 87' + '6A FF C4 8B 78 FB BD 97 8F F0 BA AC AF DD C4 BC' + 'C0 CB CC C5 C9 A8 D0 C8 C9 73 D7 CF D0 50 D7 D0' + 'CD 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 AF 9C A9 F4 B4' + '93 FF FF D9 A5 FF F4 AB 81 FF F4 B5 9D FF FF F8' + 'FA FF FF F9 FD FF FF F9 FF FF FF F7 FF FF FF F3' + 'F5 FF FD F0 F0 FF FA EF F0 FF F3 EF F0 FF F0 EA' + 'EC FF F0 E1 E5 FF EF CA C4 FF EB B2 A3 FF E4 9A' + '7F FF D3 8F 78 FF C7 8C 7C FF BF 91 89 FF C2 9A' + '94 FE C4 A6 A4 EC C4 B4 B9 C9 CB C3 C8 A5 CE C9' + 'CA 77 CC C6 BF 3F D2 CB C6 2E D8 D0 CB 1C DB D3' + 'CF 0C D5 CD C4 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 AA 95 A9 F4 B2' + '90 FF FF E4 B0 FF F5 B6 85 FF F5 BA 9A FF FF F1' + 'F0 FF FF F5 FA FF FF F7 FF FF FF F7 FF FF FF F3' + 'F5 FF FA F0 F0 FF F0 EF F0 FF F0 EF F0 FF F0 EC' + 'EF FF F0 E7 EF FF F0 E3 E5 FF F0 E2 E0 FF F0 E2' + 'E0 FF E5 C0 B5 FF DF 9C 8A FF DF 77 5F FF D4 71' + '55 FF C4 79 64 FF B0 90 8F FF B0 A5 A4 FF B5 B5' + 'B5 EA C0 C0 C0 C0 D4 CF D4 8A E4 DC E4 56 EF E8' + 'EF 26 DB D4 CF 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 D8 C8 BE 38 E6 C6 BD A9 EC B6 A2 E2 F4 BE' + '9A FF FF E0 A5 FF F5 BA 88 FF F5 B6 90 FF FF D3' + 'BA FF FF D2 AF FF FF D9 BB FF FF E7 DF FF FF ED' + 'EA FF FA F0 F0 FF F0 EF F0 FF F0 EF F0 FF F0 EC' + 'EF FF F0 E7 EF FF F0 E3 E5 FF F0 E2 E0 FF F0 E2' + 'E0 FF EC D5 D1 FF E9 C8 C3 FF E9 BC B4 FF DF A8' + '9C FF D6 94 85 FF CF 80 6F FF C8 7F 6F FF C2 88' + '7B F8 BF 9A 94 E9 BF B0 B1 D8 C5 C1 C5 BC CF CC' + 'CF 98 D0 CD CC 6C D7 D3 D1 45 E5 DD DE 23 D8 D0' + 'C9 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DC C8 BE 54 F0 C5 BD FF F3 C0 AD FF F8 C9' + 'A3 FF FF DE A0 FF F5 BD 8A FF F5 B4 8A FF FF C3' + '9F FF FF BD 83 FF FF C0 84 FF FF CB A4 FF FF D2' + 'B3 FF FA D9 C3 FF F0 E1 D5 FF F0 EA E7 FF F0 EC' + 'EF FF F0 E7 EF FF F0 E3 E5 FF EF E1 E0 FF EF E1' + 'E0 FF EF DF E0 FF EF DF E0 FF EF DF E0 FF E5 CB' + 'CA FF DF B2 AC FF DF 95 84 FF D8 89 79 FF D0 84' + '76 FF C9 86 79 FF BF 8F 84 FF BC 9B 93 F5 BF A9' + 'A5 E0 C3 BA B7 BD CD C9 CA 97 DF D7 DF 6F D5 CF' + 'CD 45 D4 CF C8 25 DB D6 CF 0E D5 CE C4 04 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DC C9 BF 54 F0 C7 BF FF FA CA B5 FF FF D2' + 'AA FF FF DE A0 FF F5 BF 8A FF F5 B5 8A FF FF BF' + '9F FF FF B5 74 FF FF AD 59 FF FF A5 4F FF FF A1' + '4F FF FA AC 6A FF F0 C7 A0 FF F0 E1 D5 FF F0 EC' + 'EF FF F0 E7 EF FF F0 E3 E5 FF EF E1 E0 FF EF DF' + 'E0 FF EF DF E0 FF EF DF E0 FF EF DF E0 FF E5 D9' + 'DF FF E0 D4 DA FF E0 D0 D0 FF DF C4 C4 FF DF AB' + 'A4 FF E0 84 6F FF D5 6A 4F FF CA 68 4F FF BF 7F' + '70 FF B5 99 8F FF B5 AC AA F6 BF B8 BF E4 CA C7' + 'CA AE DA DA DA 70 F0 EF F0 2C DC D6 CF 0E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DB C3 B7 54 EF B5 A9 FF F9 D0 B4 FF FF DE' + 'B4 FF FF E2 AA FF FB C7 95 FF F8 BA 8E FF F5 B9' + '95 FF FB BD 7F FF FF B9 6B FF FF AD 59 FF FF A6' + '52 FF FA A4 54 FF F0 A7 60 FF F0 AC 71 FF F0 B5' + '88 FF F0 BF A5 FF F0 D0 C4 FF EF DA D8 FF EF DF' + 'E0 FF EF DF E0 FF EB DD DF FF E5 D9 DF FF E1 D7' + 'DF FF E0 D4 DA FF E0 D0 D0 FF DF CB CC FF DF C3' + 'C1 FF DF B5 AF FF DB A2 96 FF D4 92 81 FF CA 85' + '70 FF C7 7A 64 FF C3 7D 6A FC BF 8C 7F F6 C2 AA' + 'A6 E4 CF C6 C8 C0 E4 DF E4 8A D8 D1 CB 2E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DB BF B2 54 EF AB 9A FF F9 D2 B2 FF FF E5' + 'BA FF FF E4 B0 FF FF CE 9E FF FA BD 91 FF F0 B1' + '8A FF FA C1 83 FF FF C1 74 FF FF B3 5F FF FF AC' + '57 FF FB A4 4F FF F5 9B 44 FF F1 95 41 FF EF 96' + '4B FF EF 9D 65 FF EF AB 84 FF ED B8 9F FF EA C4' + 'B5 FF EA CD C6 FF E6 D3 D4 FF E0 D7 DF FF E0 D5' + 'DB FF E0 D3 D6 FF E0 CF D0 FF DF CF D0 FF DF CF' + 'D0 FF DF CF D0 FF DF C2 C1 FF DA B1 AA FF D0 9A' + '8A FF D0 85 74 FF CC 78 64 FF C4 74 5A FF C0 90' + '84 FF C7 B0 AF EB D9 D2 D9 C5 DB D5 D2 4C D8 D2' + 'C9 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DC BE AF 54 F0 A8 90 FF FA D2 AF FF FF E6' + 'BA FF FF E4 B0 FF FF D4 A4 FF FA BF 94 FF F0 A7' + '80 FF FA BF 80 FF FF C5 75 FF FF B8 60 FF FF B3' + '5F FF FF AD 59 FF FF A5 4F FF F5 9B 45 FF EF 8F' + '3A FF EF 80 30 FF EF 75 25 FF EA 7A 35 FF E0 90' + '60 FF E0 AA 94 FF E0 C2 BE FF E0 D7 DF FF E0 D2' + 'D5 FF E0 CF D0 FF E0 CF D0 FF DF CF D0 FF DF CF' + 'D0 FF DF CF D0 FF DF C9 CF FF DA C4 CA FF D0 C0' + 'C0 FF D0 BA BF FF D0 9F 9A FF D0 6F 50 FF C4 79' + '65 FF C4 97 8F F3 CF C8 CF DD E4 E2 E4 69 E6 E3' + 'DF 1F 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E1 C7' + 'BD 71 EB C1 B4 C6 F0 B8 A4 FF FA D7 B6 FF FF E5' + 'BA FF FF E4 B0 FF FF DE AC FF FA CA 9C FF F0 A7' + '80 FF FA C7 8E FF FF CF 86 FF FF BD 69 FF FF B8' + '63 FF FF B2 5D FF FF AD 59 FF FB A4 4F FF F6 9A' + '44 FF EF 8F 3A FF EF 81 30 FF ED 7A 2E FF EA 7A' + '35 FF E2 7F 46 FF DF 87 5B FF DF 92 74 FF DF A6' + '94 FF DF BA B3 FF E0 CF D0 FF DF CF D0 FF DF CF' + 'D0 FF DF CF D0 FF DF C9 CF FF DA C4 CA FF D0 C0' + 'C0 FF D0 BD BF FF D0 AD A8 FF D0 8E 7A FF C5 7D' + '65 FF C1 8E 7E F9 C5 C2 C5 EF E1 E0 E1 79 E6 E2' + 'DF 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E7 C8' + 'BD A9 F3 C7 BA FF F5 C7 B4 FF FB DC BB FF FF E6' + 'BB FF FF E4 B5 FF FF E4 B1 FF F9 CD 9E FF EF 9F' + '7A FF F9 CA 97 FF FF D6 95 FF FF C4 74 FF FF BD' + '6A FF FF B8 63 FF FF B3 5F FF FF AC 57 FF FB A4' + '4F FF F5 9B 44 FF F1 8E 3A FF EF 81 30 FF EF 75' + '25 FF E4 6D 21 FF DF 6B 26 FF DF 6D 34 FF DB 7F' + '57 FF DA 92 78 FF DA A7 95 FF DA B1 A6 FF DB BC' + 'B8 FF DF C9 CA FF DF C7 CD FF DA C4 CA FF D0 C0' + 'C0 FF D0 BF C0 FF D0 B6 B3 FF D0 A4 9A FF C8 7C' + '65 FF C3 84 71 FD BF BD BF FB DF DC DF 88 E5 E1' + 'DF 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 CC' + 'BF A9 F5 D0 BF FF FF D7 BF FF FF E2 BF FF FF E7' + 'BF FF FF E6 BF FF FF E4 B5 FF F9 C7 9A FF EF 8F' + '70 FF F9 C7 9A FF FF DC A0 FF FF CC 80 FF FF C4' + '74 FF FF BD 6A FF FF B8 60 FF FF B3 5F FF FF AD' + '59 FF FF A5 4F FF F5 9B 45 FF EF 8F 3A FF EF 80' + '30 FF E5 75 25 FF DF 6D 1F FF DF 67 1F FF D5 5D' + '1F FF D0 57 1F FF D0 57 1F FF D0 74 54 FF D5 97' + '89 FF DF BF BF FF DF C4 C9 FF DA C4 CA FF D0 C0' + 'C0 FF D0 BF C0 FF D0 BA BA FF D0 B0 B0 FF D0 78' + '64 FF CA 7A 69 FF BF B7 BF FF DE D7 DE 95 E5 DE' + 'DF 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E5 C0' + 'B1 A9 F4 CA B5 FF FF E6 CA FF FF E7 C3 FF FF E7' + 'BF FF FF E7 BF FF FF E6 BB FF F9 CD A4 FF EF 9E' + '7A FF F9 CE A5 FF FF DD A7 FF FF CC 80 FF FF C9' + '7C FF FF C4 74 FF FF BD 69 FF FF B8 63 FF FF B2' + '5A FF FF AC 4F FF FB A4 4B FF F6 9A 44 FF EF 8F' + '3A FF EB 81 2F FF E6 76 26 FF DF 6D 1F FF DB 65' + '1F FF D6 5E 1F FF D0 57 1F FF CF 5D 2A FF D1 65' + '38 FF D4 6D 4A FF D4 82 69 FF D2 97 89 FF D0 AF' + 'AA FF D0 B9 B8 FF D0 BC BE FF D0 B8 BA FF D0 7B' + '68 FF C7 79 66 FF B5 B2 B5 FF D4 D2 D4 A1 DE DA' + 'D8 4C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E5 BB' + 'AA A9 F4 C7 B1 FF FF EF D5 FF FF EC CA FF FF E9' + 'C3 FF FF E8 C0 FF FF E7 BF FF FA D1 AB FF F0 A7' + '85 FF FA CE AC FF FF DB AC FF FF CE 85 FF FF CC' + '81 FF FF C9 7C FF FF C4 74 FF FF BD 6A FF FF B8' + '5F FF FF B2 55 FF FF AC 54 FF FB A4 4F FF F5 9B' + '44 FF F4 8E 39 FF EF 81 2F FF E5 75 24 FF E1 6D' + '21 FF DB 65 1F FF D5 5C 1F FF D1 55 18 FF CF 4E' + '13 FF CF 48 10 FF CF 58 2B FF CD 6C 4A FF CA 82' + '6A FF C7 91 83 FF C7 9E 96 FF CA A9 A4 FF CE 7C' + '68 FF C7 7B 68 FF B5 A7 A5 FF CE C9 C8 AD D7 D4' + 'D1 58 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 BB' + 'AA A9 F5 C9 B5 FF FF F3 DF FF FF F0 D4 FF FF EC' + 'CA FF FF E8 C0 FF FF E8 C0 FF FA D2 AF FF F0 A7' + '8F FF FA C6 AE FF FF D6 AF FF FF D4 90 FF FF CE' + '85 FF FF CC 80 FF FF CC 80 FF FF C4 74 FF FF BD' + '6A FF FF B8 60 FF FF B3 5F FF FF AD 59 FF FF A5' + '4F FF FF 9B 44 FF F9 8F 39 FF EF 80 2F FF E5 75' + '25 FF DF 6D 1F FF DF 67 1F FF D5 5D 1F FF CF 55' + '1A FF CF 4F 10 FF CF 48 10 FF CA 40 0A FF C0 38' + '00 FF B5 47 1F FF B5 60 45 FF C0 84 70 FF CA 7B' + '64 FF CA 81 6E FF BF 97 8F FF CA BC BA BA D0 CE' + 'CA 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 D9 C9 BE 38 E8 C7 BD A9 F4 C3' + 'B7 E2 FB D1 BF FF FF F1 D5 FF FF EF D1 FF FF ED' + 'CD FF FF EC C9 FF FF E9 C3 FF FA D6 B3 FF F0 B2' + '99 FF F3 BB A4 FF F8 C7 A8 FF FF D6 A5 FF FF D7' + 'A1 FF FF D5 98 FF FF CE 89 FF FF C7 7F FF FF C2' + '74 FF FF BD 69 FF FF B8 63 FF FF B2 5D FF FF AC' + '59 FF FF A8 4F FF FD A2 44 FF F9 99 3A FF F6 8D' + '2F FF F0 82 2A FF E9 77 29 FF DF 69 22 FF D6 5D' + '1D FF CF 54 19 FF CF 4E 13 FF CD 47 0E FF C9 40' + '0A FF B8 38 0E FF B1 3F 1A FF B5 56 30 FF C0 56' + '32 FF C3 68 4B FF BF 8A 7A FF CA B5 B2 C6 D6 D2' + 'D4 73 E5 E3 DF 07 D8 D2 C9 02 00 00 00 00 00 00' + '00 00 00 00 00 00 DC C9 C0 54 F2 C9 C2 FF FA CD' + 'C3 FF FF DA C9 FF FF F1 D5 FF FF EF D1 FF FF EE' + 'CF FF FF EE CF FF FF EB C8 FF FB DE BC FF F5 C7' + 'A9 FF F5 BE A3 FF F6 BE A0 FF FA C7 A0 FF F9 C7' + '9F FF FB C8 9B FF FF C9 94 FF FF CA 8D FF FF C9' + '84 FF FF C6 79 FF FF BE 6B FF FF B8 63 FF FF B3' + '5F FF FF B0 58 FF FF AD 4F FF FF A9 44 FF FF 9F' + '3A FF FB 95 35 FF F4 8C 34 FF ED 7D 2A FF E4 6F' + '22 FF DA 62 1F FF D6 59 18 FF D2 50 13 FF CF 48' + '10 FF B9 32 05 FF B1 30 06 FF B5 44 14 FF BC 46' + '1B FF C0 58 38 FF C0 7D 6A FF C6 AD AA D2 D6 D3' + 'D6 83 F0 EF F0 12 DC D6 CF 06 00 00 00 00 00 00' + '00 00 00 00 00 00 DC CB C4 54 F0 CF CF FF FA D9' + 'CF FF FF E5 D4 FF FF F3 DF FF FF F1 D5 FF FF EF' + 'D0 FF FF EE D0 FF FF EE CF FF FF EC CA FF FF E7' + 'C0 FF FF D0 AA FF FA BB 95 FF F0 A7 80 FF EF 9E' + '80 FF F4 A6 8A FF FF BF A0 FF FF CC A0 FF FF D4' + '9A FF FF D4 90 FF FF C6 7A FF FF BD 6A FF FF B8' + '60 FF FF B3 5F FF FF B0 59 FF FF AF 4F FF FF A9' + '45 FF FF A6 40 FF FF A6 40 FF FF 9A 35 FF FA 8A' + '2A FF F0 78 20 FF E4 67 1F FF D9 59 1A FF CF 4F' + '10 FF B9 34 05 FF B4 34 0A FF C0 4F 1F FF C0 49' + '1F FF C0 54 34 FF C0 6F 5F FF C0 A4 9F DF CF CF' + 'CF 95 F0 EF F0 23 DC D6 CF 0B 00 00 00 00 00 00' + '00 00 00 00 00 00 DC C8 BD 54 F0 C4 BA FF FA E0' + 'CF FF FF EF DB FF FF F3 DF FF FF F2 DB FF FF F1' + 'D6 FF FF EF D0 FF FF EE CF FF FF ED CD FF FF EC' + 'C9 FF FF E1 BC FF FD D8 B1 FF F9 D2 AA FF F9 C8' + 'A3 FF FB C2 9C FF FF BF 95 FF F7 AE 86 FF F4 A8' + '81 FF F4 AD 85 FF FB BC 8C FF FF C4 8A FF FF C7' + '7F FF FF BB 6A FF FF B3 5A FF FF AF 4F FF FF AD' + '4B FF FF AA 46 FF FF A6 40 FF FF A1 3C FF FD 9B' + '35 FF F9 91 2A FF F6 85 29 FF EB 72 24 FF D9 59' + '19 FF BD 3F 0F FF B8 3D 11 FF C9 54 1F FF C3 4F' + '1F FF C3 54 2D FF C9 65 4A FF C2 9D 98 EB CF CA' + 'CF A7 EF EA EF 32 DB D4 CF 11 00 00 00 00 00 00' + '00 00 00 00 00 00 DC C5 B9 54 F0 BD AF FF FA E3' + 'D3 FF FF F6 E3 FF FF F4 DF FF FF F3 DF FF FF F2' + 'DB FF FF F1 D5 FF FF EF D1 FF FF EE CF FF FF EE' + 'CF FF FF EB C8 FF FF E9 C3 FF FF E8 C0 FF FF E0' + 'B8 FF FF D7 AE FF FF CC 9F FF F7 B6 8D FF F4 AB' + '86 FF F4 AA 8A FF F7 B0 8E FF FB BC 93 FF FF CE' + '99 FF FF C3 7A FF FF BA 63 FF FF B2 55 FF FF B0' + '51 FF FF AD 4B FF FF A9 44 FF FF A7 41 FF FF A4' + '3C FF FF A1 35 FF FF 98 31 FF F6 85 2B FF E4 67' + '24 FF CC 50 1D FF C4 4B 1B FF CF 59 1F FF C8 54' + '1F FF C8 55 28 FF CF 5C 3A FF C1 97 8F F6 C9 C4' + 'C9 B7 EA E5 EA 42 DA D3 CD 16 00 00 00 00 00 00' + '00 00 00 00 00 00 DC C4 B9 54 F0 BA AF FF FA E4' + 'DA FF FF F8 EA FF FF F6 E0 FF FF F4 DF FF FF F3' + 'DF FF FF F3 DF FF FF F1 D5 FF FF EF D0 FF FF EE' + 'D0 FF FF EE CF FF FF EC CA FF FF E8 C0 FF FF E8' + 'C0 FF FF E7 BF FF FF E6 BF FF FF E4 B5 FF FF DC' + 'AA FF FF CD A0 FF F4 A3 7F FF F4 A3 84 FF FF CC' + 'B0 FF FF CC 90 FF FF C5 75 FF FF B8 60 FF FF B2' + '55 FF FF AF 4F FF FF AF 4F FF FF A9 45 FF FF A6' + '40 FF FF A6 40 FF FF A1 35 FF FA 92 2F FF F0 78' + '2F FF E4 68 2F FF D9 60 2A FF CF 60 20 FF CF 5A' + '1F FF CF 56 24 FF D0 54 2F FF BA 91 84 FF BF BF' + 'BF C5 E0 DF E0 52 D6 D1 CA 1B 00 00 00 00 00 00' + '00 00 E1 C8 BD 71 EE C7 BC C6 F9 C8 BA FF FD E9' + 'DE FF FF F9 EE FF FF F8 EA FF FF F6 E3 FF FF F4' + 'DF FF FF F3 DF FF FF F2 DB FF FF F1 D6 FF FF EF' + 'D0 FF FF EE CF FF FF ED CD FF FF EC C9 FF FF E9' + 'C3 FF FF E7 BF FF FF E7 BF FF FF E6 BB FF FF E2' + 'B4 FF FF DC AA FF FB C4 98 FF F4 B1 8C FF EA A3' + '85 FF F8 C3 97 FF FF CF 91 FF FF C5 75 FF FF BA' + '63 FF FF B3 56 FF FF AF 4F FF FF AD 4B FF FF AA' + '46 FF FF A6 40 FF FF A4 3C FF FA 93 36 FF F0 72' + '2F FF F2 81 3D FF EF 88 3F FF E4 84 35 FF D6 6A' + '26 FF CF 5A 24 FF D0 54 2F FF C1 86 76 FF C3 B1' + 'AD CB D5 D5 D5 64 D3 CD C6 21 00 00 00 00 00 00' + '00 00 E7 CA C1 AA F6 CE C5 FF FF D6 CA FF FF EE' + 'E3 FF FF FA F0 FF FF FA F0 FF FF F8 E8 FF FF F6' + 'E3 FF FF F4 DF FF FF F3 DF FF FF F2 DB FF FF F1' + 'D5 FF FF EF D1 FF FF EE CF FF FF EF CF FF FF EB' + 'C8 FF FF E9 C3 FF FF E8 C0 FF FF E7 BF FF FF E6' + 'BB FF FF E4 B5 FF FF DA AA FF F8 C2 97 FF EA 9F' + '7A FF F1 B1 8C FF F6 BB 8E FF F9 BB 80 FF FD B8' + '75 FF FF B6 6C FF FF B5 64 FF FF B4 5D FF FF B0' + '53 FF FF A9 45 FF FF A7 41 FF F8 92 3A FF EA 6A' + '2F FF F8 92 48 FF FB A5 51 FF F5 A1 4A FF E2 7E' + '35 FF D6 65 2B FF D0 57 2F FF C4 7D 68 FF C4 A4' + '9D D1 CF CD CF 77 D7 D3 CF 2C DB D6 CF 07 00 00' + '00 00 E6 D0 C9 AA F5 D9 D4 FF FF E4 DF FF FF F2' + 'EA FF FF FA F0 FF FF FA F0 FF FF FA F0 FF FF F8' + 'EA FF FF F6 E0 FF FF F4 DF FF FF F3 DF FF FF F3' + 'DF FF FF F1 D5 FF FF EF CF FF FF EF CF FF FF EF' + 'CF FF FF EC CA FF FF E8 C0 FF FF E8 C0 FF FF E7' + 'BF FF FF E6 BF FF FF E4 B5 FF FF D8 A5 FF FF C0' + '90 FF EA 96 70 FF E5 89 6A FF EF 9A 80 FF F9 AD' + '89 FF FF BA 8F FF FF C0 8F FF FF C0 7A FF FF BA' + '65 FF FF B0 50 FF FF A9 45 FF F4 8E 3A FF E0 60' + '2F FF F4 9A 4F FF FF B8 60 FF FF B8 60 FF F4 97' + '4A FF E4 79 39 FF D0 5F 2F FF C5 77 5A FF C5 9A' + '8F D8 CF C7 CF 8A E4 E2 E4 3C F0 F0 F0 16 00 00' + '00 00 E6 CA C2 AA F5 D6 D1 FF FF EC EA FF FF F6' + 'F4 FF FF FA F6 FF FF FA F0 FF FF FA F0 FF FF F9' + 'EE FF FF F8 EA FF FF F6 E3 FF FF F4 DF FF FF F3' + 'DF FF FF F2 DB FF FF F1 D6 FF FF EF CF FF FF EF' + 'CF FF FF EE CD FF FF EC C9 FF FF E9 C3 FF FF E7' + 'BF FF FF E7 BF FF FF E6 BB FF FF E0 B3 FF FF D7' + 'A5 FF F8 CA 9A FF F6 C0 95 FF F9 BB 94 FF F6 B3' + '89 FF F1 A7 7D FF EA 96 6F FF EA 96 68 FF ED 9B' + '65 FF F5 A4 65 FF FB A9 68 FF F8 9C 61 FF E9 7A' + '4F FF F7 AC 68 FF FF C2 71 FF FF BD 69 FF FB AB' + '5B FF EF 90 48 FF D9 6A 2F FF CF 72 4C FF C8 8F' + '7E DE C5 C1 C5 9B D4 CF CB 38 DC D6 CF 07 00 00' + '00 00 E6 C6 BB AA F5 D4 CD FF FF F4 F5 FF FF F9' + 'FB FF FF FB FB FF FF FA F5 FF FF FA F1 FF FF FA' + 'F0 FF FF FA F0 FF FF F8 E8 FF FF F6 E3 FF FF F4' + 'DF FF FF F3 DF FF FF F2 DB FF FF F1 D5 FF FF EF' + 'D1 FF FF EF CF FF FF EF CF FF FF EB C8 FF FF E9' + 'C3 FF FF E8 C0 FF FF E7 BF FF FF E6 BB FF FF E4' + 'B5 FF FF E4 B1 FF FF DE AC FF FF D3 A4 FF F8 C5' + '96 FF F1 B4 86 FF EA A0 75 FF EA 9E 75 FF EC 9F' + '75 FF F0 A4 74 FF F6 A3 74 FF F4 97 6B FF E9 7F' + '5A FF F4 A3 6C FF F9 B6 75 FF FA B9 74 FF FD B7' + '6D FF F7 A6 5D FF E9 87 44 FF D8 73 48 FF CB 87' + '73 EB C5 C1 C5 C2 CD C7 C1 41 00 00 00 00 00 00' + '00 00 E6 C3 B5 AA F5 D4 CA FF FF FC FF FF FF FC' + 'FF FF FF FC FF FF FF FC FF FF FF FA F5 FF FF FA' + 'F0 FF FF FA F0 FF FF FA F0 FF FF F8 EA FF FF F6' + 'E0 FF FF F4 DF FF FF F3 DF FF FF F3 DF FF FF F1' + 'D5 FF FF EF CF FF FF EF CF FF FF EF CF FF FF EC' + 'CA FF FF E8 C0 FF FF E8 BF FF FF E7 BF FF FF E6' + 'BF FF FF E4 B5 FF FF E4 B0 FF FF E4 B0 FF FF E4' + 'B0 FF FF E2 AA FF FF DE A0 FF FF D7 A0 FF FA C8' + '95 FF F0 B0 7F FF EF 95 6A FF E9 7F 5A FF DF 6F' + '4F FF E9 7F 5A FF EF 93 6A FF F0 AC 80 FF F9 B9' + '80 FF FF BD 7A FF FF B7 6F FF DF 7D 4F FF CF 82' + '6F FF CF C7 CF FF D0 C8 C4 55 00 00 00 00 00 00' + '00 00 EA CB C3 AA F6 D0 CA FF F5 D8 D4 FF F5 D5' + 'CD FF F8 D8 D1 FF FF E1 DF FF FF E8 E2 FF FF F0' + 'E8 FF FF FA F0 FF FF FA F0 FF FF F9 EE FF FF F8' + 'EA FF FF F4 E2 FF FB E3 D0 FF F5 C5 B4 FF F4 BD' + 'A9 FF F4 BD A8 FF F5 C4 AF FF FB D1 B6 FF FF DB' + 'BC FF FF E2 BF FF FF E6 BF FF FF E7 BF FF FF E7' + 'BF FF FF E6 BB FF FF E4 B6 FF FF E4 B0 FF FF E4' + 'B0 FF FF E3 AE FF FF E2 AA FF FF DD A3 FF FD D6' + '9C FF F9 CE 94 FF F3 AF 7F FF E6 98 76 FF D4 89' + '79 FF DF A4 93 FF E8 B0 9C FF EF AC 94 FF EC 99' + '78 FF EA 8D 65 FF EA 87 59 FF DF 69 41 FF D7 7F' + '64 C6 D0 C8 C4 55 D1 C9 C0 1C 00 00 00 00 00 00' + '00 00 E3 CE C6 71 EA CD C6 AA E6 C8 BF AA EC C0' + 'B4 BB F3 C2 B7 D7 FA CE C7 FF FA D4 CE FF FA DB' + 'D3 FF FA E2 D5 FF FA E4 D8 FF FB E7 DC FF FF EC' + 'E0 FF FB E2 D1 FF F6 D1 BF FF F0 B8 A9 FF E8 B1' + 'A2 C6 E5 B0 A2 AA E6 B7 A9 AA F3 C5 B1 E2 F9 CD' + 'B5 FF F9 D0 B4 FF F9 CE AE FF F9 D0 AE FF FA D6' + 'B4 FF FD D9 B4 FF FF DE B4 FF FF E4 B5 FF FF E4' + 'B1 FF FF E4 B0 FF FF E4 B0 FF FF E1 A8 FF FF DF' + 'A3 FF FF DE A0 FF F5 B9 86 FF E3 A3 82 FF CA 9C' + '94 FF D5 B9 B1 C6 DE C2 B8 AA E5 B6 A9 AA DE 9F' + '8D AA DB 91 7B AA DB 8D 74 AA E1 83 66 E2 DE 97' + '7F AA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 BF' + 'B4 33 F0 BC B2 88 F2 C2 B8 FF F0 C1 B8 FF F0 BC' + 'B0 FF F0 B4 A0 FF F0 B8 AA FF F5 C1 B4 FF FF D0' + 'C0 FF F5 BD AA FF F0 BC AA FF F0 CD C0 FF DC CB' + 'BF 55 00 00 00 00 00 00 00 00 E6 CC BF A9 EF C4' + 'B5 FF EF B4 A0 FF EF A2 8A FF EF A2 8A FF F0 B4' + 'A0 FF F9 BF A0 FF FF CF AA FF FF E6 BF FF FF E4' + 'B5 FF FF E4 B0 FF FF E4 B0 FF FF E4 B0 FF FF E2' + 'AA FF FF DE A0 FF F5 B4 80 FF E0 A1 7F FF C0 A7' + 'A0 FF CB BE B4 55 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 E5 CC BF A9 E6 CC' + 'BF AA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 D8 C6' + 'BB 11 DC C5 BA 2D DC C7 BC 55 DC C7 BC 55 DC C5' + 'B9 55 DC C2 B4 55 E9 BC B0 A6 F1 BC B0 C1 F5 C1' + 'B4 A5 F1 BA AD C2 E8 BD B0 A7 DC CB BF 55 D5 CA' + 'BF 1C 00 00 00 00 00 00 00 00 D8 CA BF 38 DB C8' + 'BB 55 DB C2 B4 55 DB BC AD 55 DB BC AD 55 DC C2' + 'B4 55 EC BF AD C6 F4 BA A3 FF F4 B3 95 FF F4 B2' + '91 FF F4 B9 93 FF F5 C6 9A FF FB CF A1 FF FF D9' + 'A7 FF FF E2 AA FF ED A8 7C FF DC 9D 83 FF CA C1' + 'BF FF CF C7 BF 55 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 D8 CA BF 38 D8 CA' + 'BF 38 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 DF C2 B7 51 E6 BF B4 6C E6 BF' + 'B4 50 E5 BE B3 6D DE C2 B7 52 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 DF C2 B7 71 E5 B8 A9 AA E5 A9 94 AA E5 A9' + '94 AA EA B1 9A C6 F5 C0 A4 FF F8 C0 9E FF F8 C2' + '9A FF F4 C7 9A FF E6 9C 77 FF DA 9D 86 E2 D0 CD' + 'CA AA D1 CB C2 38 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 E0 CD C4 54 FF D4 CF FF F4 B6 A5 FF EA 9F' + '85 FF E0 8F 70 FF E0 8F 70 FF DB A2 8A AA 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 D7 CB C0 1C E1 CD C4 55 DD C3 B6 55 DA BB' + 'AB 55 D6 B6 A4 55 D6 B6 A4 55 D5 BC AD 38 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF 00' + '3F FF FF FF 00 00 FF 00 3F FF FF FF 00 00 FF 00' + '07 FF FF FF 00 00 FF 00 00 FF FF FF 00 00 FF 00' + '00 FF FF FF 00 00 FE 00 00 1F FF FF 00 00 FE 00' + '00 03 FF FF 00 00 FE 00 00 03 FF FF 00 00 FE 00' + '00 00 7F FF 00 00 FE 00 00 00 03 FF 00 00 FE 00' + '00 00 03 FF 00 00 F8 00 00 00 00 7F 00 00 F8 00' + '00 00 00 0F 00 00 F8 00 00 00 00 0F 00 00 F8 00' + '00 00 00 0F 00 00 F8 00 00 00 00 07 00 00 F8 00' + '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' + '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' + '00 00 00 07 00 00 F0 00 00 00 00 07 00 00 F0 00' + '00 00 00 07 00 00 C0 00 00 00 00 01 00 00 C0 00' + '00 00 00 01 00 00 C0 00 00 00 00 01 00 00 C0 00' + '00 00 00 01 00 00 C0 00 00 00 00 01 00 00 C0 00' + '00 00 00 01 00 00 80 00 00 00 00 01 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 01 00 00 80 00' + '00 00 00 01 00 00 80 00 00 00 00 01 00 00 80 00' + '00 00 00 07 00 00 F0 00 60 00 03 E7 00 00 F0 00' + '60 00 03 E7 00 00 FF C1 FF 80 03 FF 00 00 FF FF' + 'FF F8 0F FF 00 00 FF FF FF F8 0F FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' + '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 C5' + 'BC FF D0 BC BF FF BF B8 BF FF CF C7 CF A5 DF D8' + 'DF 54 F0 EF F0 0F 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 98' + '8F FF E0 84 6F FF D0 84 6F FF BF 98 90 FF B0 B0' + 'B0 FF C0 C0 C0 B7 DF D7 DF 66 EF E8 EF 1E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 84' + '6F FF F0 BF B0 FF FF DF D0 FF EF 97 80 FF DF 78' + '5F FF BF 90 80 FF B0 AF B0 FF C0 BF C0 C9 D0 D0' + 'D0 78 EF E7 EF 2D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F0 C4 BC FF EF 97' + '7F FF EF 9F 8F FF FF FC FF FF FF FC FF FF FF E7' + 'E0 FF F0 A7 8F FF D0 77 5F FF BF 88 7F FF B0 AF' + 'B0 FF BF B8 BF DB D0 CF D0 8A E0 E0 E0 3C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 EF BF B0 FF FF CD' + 'A0 FF EF 97 80 FF FF FC FF FF FF FC FF FF FF F7' + 'FF FF FF F1 F0 FF F0 DF DF FF EF AD 9F FF DF 77' + '5F FF C0 84 70 FF B0 A7 A0 FF BF B7 BF ED CF C8' + 'CF 9C E0 E0 E0 4B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 EF A7 90 FF FF D4' + 'A0 FF EF 8F 6F FF FF FC FF FF FF FC FF FF FF F7' + 'FF FF FF F1 F0 FF FF EF F0 FF F0 EF F0 FF F0 DF' + 'E0 FF EF AD 9F FF DF 77 50 FF C0 78 60 FF B0 9F' + '9F FF BF B7 BF FE CF C7 CF AE DF D8 DF 5D 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 EF 9A 80 FF FF E4' + 'B0 FF F0 9F 70 FF FF F1 F0 FF FF F7 FF FF FF F7' + 'FF FF FF F1 F0 FF F0 EF F0 FF F0 EF F0 FF F0 E7' + 'EF FF F0 E2 E0 FF F0 E2 E0 FF E0 AF A0 FF DF 77' + '5F FF CF 6F 50 FF B0 90 8F FF B0 B0 B0 FF C0 C0' + 'C0 C0 DF D7 DF 6F EF E8 EF 26 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 F0 C4 BC FF F0 B8 A0 FF FF DE' + 'A0 FF F0 AC 80 FF FF C5 A0 FF FF C0 80 FF FF DF' + 'CF FF FF F1 F0 FF F0 EF F0 FF F0 EF F0 FF F0 E7' + 'EF FF F0 E2 E0 FF F0 E2 E0 FF EF DF E0 FF EF DF' + 'E0 FF E0 B7 B0 FF DF 78 5F FF CF 67 4F FF BF 87' + '7F FF B0 AF B0 FF C0 BF C0 D2 D0 D0 D0 81 EF E7' + 'EF 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 F0 C7 BF FF FF CC B0 FF FF DE' + 'A0 FF F0 B0 80 FF FF BF 9F FF FF B1 5F FF FF A5' + '4F FF FF 9F 50 FF F0 C7 A0 FF F0 EF F0 FF F0 E7' + 'EF FF F0 E2 E0 FF EF DF E0 FF EF DF E0 FF EF DF' + 'E0 FF E0 D7 DF FF E0 D0 D0 FF DF BF BF FF E0 84' + '6F FF D0 5D 3F FF BF 7F 70 FF B0 A7 A0 FF BF B8' + 'BF E4 D0 D0 D0 93 F0 EF F0 2C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 EF AD 9F FF FF E6 BF FF FF E4' + 'B0 FF FF C0 90 FF F0 B7 90 FF FF C7 7F FF FF B1' + '5F FF FF A5 4F FF F0 97 40 FF F0 90 3F FF F0 AC' + '80 FF F0 D4 CF FF EF DF E0 FF EF DF E0 FF E0 D7' + 'DF FF E0 D7 DF FF E0 D0 D0 FF DF CF D0 FF DF CF' + 'D0 FF DF B7 B0 FF D0 88 70 FF D0 5D 3F FF BF 77' + '60 FF BF AF AF FF DF D8 DF BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 F0 A8 90 FF FF E8 C0 FF FF E4' + 'B0 FF FF CC 9F FF F0 A7 80 FF FF CC 80 FF FF B8' + '60 FF FF B1 5F FF FF A5 4F FF F0 97 40 FF EF 80' + '30 FF EF 70 20 FF E0 90 60 FF E0 B8 AF FF E0 D7' + 'DF FF E0 D0 D0 FF E0 CF D0 FF DF CF D0 FF DF CF' + 'D0 FF DF C7 CF FF D0 C0 C0 FF D0 B7 BF FF D0 6F' + '50 FF BF 7F 70 FF CF C8 CF DD F0 F0 F0 2F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F4 C5 BC FF F0 C0 AF FF FF E6 BF FF FF E4' + 'B0 FF FF E4 B0 FF F0 A7 80 FF FF DE A0 FF FF C0' + '6F FF FF B8 60 FF FF B1 5F FF FF A5 4F FF F0 97' + '40 FF EF 80 30 FF EF 70 20 FF DF 67 1F FF DF 70' + '3F FF DF A0 8F FF E0 CF D0 FF DF CF D0 FF DF CF' + 'D0 FF DF C7 CF FF D0 C0 C0 FF D0 BF C0 FF D0 9F' + '90 FF C0 6F 50 FF C0 C0 C0 F9 F0 EF F0 46 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F0 CD C0 FF FF D7 BF FF FF E8 C0 FF FF E6' + 'BF FF FF E4 B0 FF EF 8F 70 FF FF E4 B0 FF FF CC' + '80 FF FF C0 6F FF FF B8 60 FF FF B1 5F FF FF A5' + '4F FF F0 97 40 FF EF 80 30 FF E0 70 20 FF DF 67' + '1F FF D0 58 1F FF D0 57 1F FF D0 84 6F FF DF BF' + 'BF FF DF C7 CF FF D0 C0 C0 FF D0 BF C0 FF D0 B0' + 'B0 FF D0 5D 3F FF BF B7 BF FF EF E8 EF 60 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 EF B4 A0 FF FF EE D0 FF FF E8 C0 FF FF E8' + 'C0 FF FF E6 BF FF F0 A7 80 FF FF E8 C0 FF FF CC' + '80 FF FF CC 80 FF FF C0 6F FF FF B8 60 FF FF B0' + '50 FF FF A5 4F FF F0 97 40 FF EF 80 2F FF E0 70' + '20 FF DF 67 1F FF D0 58 1F FF CF 4F 10 FF CF 45' + '10 FF CF 6F 4F FF D0 A7 9F FF D0 BF C0 FF D0 BC' + 'BF FF D0 5D 3F FF B0 B0 B0 FF E0 DF E0 7C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F0 B4 A0 FF FF F3 DF FF FF EF CF FF FF E8' + 'C0 FF FF E8 C0 FF F0 A7 8F FF FF D7 BF FF FF D4' + '90 FF FF CC 80 FF FF CC 80 FF FF C0 6F FF FF B8' + '60 FF FF B1 5F FF FF A5 4F FF FF 97 3F FF EF 80' + '2F FF E0 70 20 FF DF 67 1F FF D0 58 1F FF CF 4F' + '10 FF CF 45 10 FF C0 38 00 FF B0 4F 30 FF C0 84' + '70 FF D0 77 5F FF BF 97 8F FF D0 D0 D0 98 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 F4 C6' + 'BC FF FF C8 BF FF FF F0 D0 FF FF EE D0 FF FF EF' + 'CF FF FF E8 C0 FF F0 B8 9F FF F0 B4 A0 FF FF D7' + 'B0 FF FF DF AF FF FF CF 8F FF FF C7 7F FF FF C0' + '6F FF FF B8 60 FF FF B1 5F FF FF AF 4F FF FF A6' + '40 FF FF 94 30 FF EF 80 2F FF DF 67 1F FF D0 58' + '1F FF CF 4F 10 FF CF 45 10 FF AF 27 00 FF B0 3F' + '10 FF C0 47 1F FF C0 84 70 FF CF C8 CF B3 F0 F0' + 'F0 0B 00 00 00 00 00 00 00 00 00 00 00 00 F0 CF' + 'CF FF FF DF CF FF FF F3 DF FF FF F0 D0 FF FF EE' + 'D0 FF FF EF CF FF FF E7 C0 FF FF C5 A0 FF F0 A7' + '80 FF EF 9A 80 FF FF BF A0 FF FF D4 A0 FF FF D4' + '90 FF FF C0 6F FF FF B8 60 FF FF B1 5F FF FF AF' + '4F FF FF A6 40 FF FF A6 40 FF FF 94 30 FF F0 78' + '20 FF DF 5F 1F FF CF 4F 10 FF AF 27 00 FF C0 4F' + '1F FF C0 47 1F FF C0 6F 5F FF C0 C0 C0 CF F0 EF' + 'F0 23 00 00 00 00 00 00 00 00 00 00 00 00 F0 BF' + 'B0 FF FF F6 E0 FF FF F3 DF FF FF F3 DF FF FF F0' + 'D0 FF FF EE D0 FF FF EF CF FF FF E8 C0 FF FF E8' + 'C0 FF FF D8 B0 FF FF C0 90 FF EF 8F 6F FF EF 9A' + '80 FF FF C5 A0 FF FF CF 8F FF FF B8 60 FF FF B0' + '50 FF FF AF 4F FF FF A6 40 FF FF A6 40 FF FF 9F' + '30 FF FF 8F 2F FF DF 5F 1F FF B0 37 10 FF CF 57' + '1F FF C0 4F 1F FF CF 60 40 FF BF B7 BF EB EF E8' + 'EF 3B 00 00 00 00 00 00 00 00 00 00 00 00 F0 BA' + 'AF FF FF FA F0 FF FF F6 E0 FF FF F3 DF FF FF F3' + 'DF FF FF F0 D0 FF FF EE D0 FF FF EF CF FF FF E8' + 'C0 FF FF E8 C0 FF FF E6 BF FF FF E4 B0 FF FF CD' + 'A0 FF EF 8F 6F FF FF CC B0 FF FF CC 80 FF FF B8' + '60 FF FF B0 50 FF FF AF 4F FF FF A6 40 FF FF A6' + '40 FF FF 9F 30 FF F0 78 2F FF DF 60 2F FF CF 60' + '20 FF CF 57 1F FF D0 54 2F FF B0 B0 B0 FF E0 DF' + 'E0 52 00 00 00 00 00 00 00 00 F4 C6 BC FF FF D0' + 'C0 FF FF FA F0 FF FF FA F0 FF FF F6 E0 FF FF F3' + 'DF FF FF F3 DF FF FF F0 D0 FF FF EE D0 FF FF EF' + 'CF FF FF E8 C0 FF FF E8 C0 FF FF E6 BF FF FF E4' + 'B0 FF FF CD A0 FF E0 8F 70 FF FF D8 B0 FF FF CC' + '80 FF FF B8 60 FF FF B0 50 FF FF AF 4F FF FF A6' + '40 FF FF A6 40 FF F0 6F 2F FF FF 9F 4F FF F0 97' + '40 FF CF 60 20 FF D0 54 2F FF BF 97 8F FF D0 D0' + 'D0 6E 00 00 00 00 00 00 00 00 F0 D4 CF FF FF E4' + 'DF FF FF FA F0 FF FF FA F0 FF FF FA F0 FF FF F6' + 'E0 FF FF F3 DF FF FF F3 DF FF FF F0 D0 FF FF EF' + 'CF FF FF EF CF FF FF E8 C0 FF FF E8 C0 FF FF E6' + 'BF FF FF E4 B0 FF FF C0 90 FF E0 82 60 FF EF 9A' + '80 FF FF B7 8F FF FF C0 8F FF FF C0 70 FF FF B0' + '50 FF FF A6 40 FF E0 60 2F FF FF B8 60 FF FF B8' + '60 FF EF 87 3F FF D0 5F 2F FF C0 84 70 FF CF C7' + 'CF 8A F0 F0 F0 16 00 00 00 00 F0 C7 BF FF FF F1' + 'F0 FF FF FC FF FF FF FA F0 FF FF FA F0 FF FF FA' + 'F0 FF FF F6 E0 FF FF F3 DF FF FF F3 DF FF FF F0' + 'D0 FF FF EF CF FF FF EF CF FF FF E8 C0 FF FF E8' + 'C0 FF FF E6 BF FF FF E4 B0 FF FF E4 B0 FF FF CC' + '9F FF F0 AC 7F FF E0 82 60 FF E0 82 60 FF F0 9F' + '70 FF FF B0 7F FF EF 88 60 FF FF CC 80 FF FF C0' + '6F FF FF B1 5F FF DF 70 30 FF CF 6F 50 FF C0 BF' + 'C0 A5 00 00 00 00 00 00 00 00 F0 C0 B0 FF FF FC' + 'FF FF FF FC FF FF FF FC FF FF FF FA F0 FF FF FA' + 'F0 FF FF FA F0 FF FF F6 E0 FF FF F3 DF FF FF F3' + 'DF FF FF F0 D0 FF FF EF CF FF FF EF CF FF FF E8' + 'C0 FF FF E8 BF FF FF E6 BF FF FF E4 B0 FF FF E4' + 'B0 FF FF E4 B0 FF FF DE A0 FF FF D4 A0 FF F0 B0' + '7F FF EF 88 60 FF DF 6F 4F FF EF 88 60 FF F0 AC' + '80 FF FF C0 80 FF FF B7 6F FF D0 60 40 FF CF C7' + 'CF FF 00 00 00 00 00 00 00 00 FA D3 D0 FF F0 C7' + 'BF FF F0 BF B0 FF FF D4 CF FF FF E4 DF FF FF FA' + 'F0 FF FF FA F0 FF FF FA F0 FF FF F3 DF FF F0 AF' + '9F FF EF 9F 8F FF F0 AF 9F FF FF CC B0 FF FF DF' + 'BF FF FF E8 C0 FF FF E8 BF FF FF E6 BF FF FF E4' + 'B0 FF FF E4 B0 FF FF E4 B0 FF FF DE A0 FF FF DE' + 'A0 FF F0 AC 7F FF CF 97 8F FF E0 C7 C0 FF EF AD' + '9F FF E0 78 60 FF E0 70 4F FF DF 58 30 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F0 BA AF 4D F2 C2 B8 FF F0 C1 B8 FF F0 B4' + 'A0 FF F0 BA AF FF FF D0 C0 FF F0 B4 A0 FF F0 CD' + 'C0 FF 00 00 00 00 00 00 00 00 F0 CD C0 FF EF B4' + 'A0 FF EF 9A 80 FF F0 B4 A0 FF FF C5 A0 FF FF E6' + 'BF FF FF E4 B0 FF FF E4 B0 FF FF E4 B0 FF FF DE' + 'A0 FF F0 9F 70 FF C0 A7 A0 FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F0 CD C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F0 BA AF B7 F0 BA AF 79 EF B9 AE B9 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F0 BA AF FF EF 9A' + '80 FF EF 9A 80 FF F0 B7 90 FF FF CD A0 FF FF E4' + 'B0 FF E0 82 60 FF D0 CF D0 FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF D4 CF FF EF A7 90 FF E0 8F' + '70 FF E0 8F 70 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FC 0F' + 'FF FF FC 03 FF FF FC 00 FF FF F8 00 3F FF F8 00' + '0F FF F8 00 03 FF F8 00 00 7F F0 00 00 1F F0 00' + '00 07 F0 00 00 07 F0 00 00 03 E0 00 00 03 E0 00' + '00 03 E0 00 00 03 E0 00 00 03 C0 00 00 01 C0 00' + '00 01 C0 00 00 01 C0 00 00 01 80 00 00 01 80 00' + '00 00 80 00 00 01 80 00 00 01 80 00 00 03 E0 18' + '00 7B FE 3F 80 7F FF FF F0 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 D7 C8 BE 01 DD C6 BD 57 CA C1' + 'BF 65 D8 D1 D0 27 DD D7 D1 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 D7 B8 AC 03 DF A0 92 D1 E0 AA' + '9B FD CA A2 98 E7 CC C3 C4 98 D6 D1 CF 38 DC D4' + 'D0 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E4 C3 B7 2A F2 AE 94 F8 FC E7' + 'E4 FF FA DF DB FF DD AC A0 FE C9 9F 97 ED C6 BB' + 'B8 AC D2 CC CA 49 D7 D1 CB 08 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E6 B1 9D 31 F9 C4 99 FD FC E5' + 'E0 FF FF F6 FB FF F7 ED ED FF EE D6 D4 FF DF AA' + '98 FF C8 96 8C F4 C5 B0 B0 BF CD C7 C5 59 DD D5' + 'D3 15 DE D7 D5 01 00 00 00 00 00 00 00 00 00 00' + '00 00 DB C8 BE 02 EA C5 B8 BF FA CF 9C FF FC C1' + '99 FF FF C8 9B FF F3 DD CD FF F0 E6 EA FF EF E0' + 'DF FF EA D0 CF FF DA A3 98 FF CC 8F 83 F8 C4 A8' + 'A2 D0 D3 CB CC 78 DC D8 D2 19 00 00 00 00 00 00' + '00 00 DB C0 B3 03 ED BC A8 D1 FF DD AC FF F7 B8' + '8A FF FF B4 62 FF F7 A2 52 FF EF A1 6B FF EA BC' + 'A8 FF E3 D4 D8 FF E0 D0 D1 FF DF C4 C3 FF D1 9F' + '94 FF C6 85 72 FB D6 CA CB A6 DC D6 D0 05 00 00' + '00 00 E6 C8 BD 2A F6 CD B7 F8 FF E4 B6 FF F5 B6' + '8A FF FF C7 7A FF FF B2 5D FF F6 99 44 FF EB 7B' + '2F FF DE 7A 45 FF D9 9C 85 FF DE C1 C1 FF D3 C0' + 'C2 FF CE 9D 91 FF CA B6 B3 DA E5 E0 DF 10 00 00' + '00 00 E6 BE AD 31 FC E3 C8 FD FF E8 C0 FF F6 BB' + '99 FF FF D1 8F FF FF C3 73 FF FF B2 59 FF F7 99' + '44 FF E7 77 27 FF D7 5F 1F FF D0 59 28 FF C9 7B' + '60 FF C9 94 88 FF C2 A4 9D E7 D7 D3 D1 19 DB C9' + 'C0 03 ED CB C2 BF FF EB D2 FF FF ED CC FF F8 CE' + 'AE FF F9 C2 9B FF FE C7 92 FF FF C5 7A FF FF B3' + '5E FF FD A4 44 FF F3 8B 32 FF DE 65 1E FF C9 45' + '0E FF B8 47 1D FF C2 81 70 F1 E1 DE DC 30 DC C6' + 'BA 04 EE CB BE D1 FF F4 E0 FF FF F1 D6 FF FF EC' + 'CC FF FE E0 BA FF FD CD A3 FF F7 B5 8E FF FD C3' + '8C FF FF B5 59 FF FF AA 46 FF FD 9C 35 FF E2 69' + '24 FF CB 55 1F FF C9 6B 4E FB DC D6 D7 56 E6 CB' + 'C2 3A FA DA D1 F8 FF F9 ED FF FF F4 E0 FF FF F1' + 'D6 FF FF ED CC FF FF E8 C1 FF FF DF B2 FF F3 B3' + '8B FF F8 B5 7E FF FF B5 68 FF FF AA 49 FF F0 7F' + '39 FF F0 96 46 FF CF 68 3F FE D0 C4 C2 7B E7 C8' + 'BD 40 FC EC EB FD FF FA F6 FF FF F9 ED FF FF F4' + 'E0 FF FF F0 D5 FF FF ED CB FF FF E8 C1 FF FE E0' + 'B3 FF FC D0 A1 FF F1 B2 83 FF F2 A7 73 FF ED 8A' + '5E FF F8 B3 71 FF E8 8D 51 FF CB B4 B0 AB E6 CD' + 'C5 25 EB C9 C1 98 F7 D0 C8 EE F8 DC D0 FC FC E3' + 'D4 FD F0 C5 B4 E8 EC C2 B1 A7 F7 CD B1 FA F9 D1' + 'AF FC FF E1 B3 FF FF E2 AD FF FB D0 97 FF D4 A3' + '92 EB DE B3 A3 94 E2 9B 80 A5 DD AC 9A 3F 00 00' + '00 00 D9 C5 BA 02 DE C6 BB 17 E0 C1 B6 2A EA BF' + 'B3 5D DF C4 B8 25 D9 CA BF 05 DD C1 B2 1A E1 C0' + 'B3 30 E8 B9 A5 93 F4 C3 A7 E8 EF B7 8E FA D4 B5' + 'A8 8B D0 C9 C1 01 D9 CA BF 05 D9 CA BF 05 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 DF CA BF 15 D8 B5 A2 1A D6 BA' + 'A9 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 FF' + '00 00 C0 7F 00 00 C0 1F 00 00 C0 03 00 00 80 01' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 FF C7 00 00 FF FF 00 00 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 7F 7F 7F 00 00 99' + '99 00 66 CC CC 00 99 CC FF 00 99 FF FF 00 F8 F8' + 'F8 00 00 00 00 00 E2 69 24 00 E7 77 27 00 EB 7B' + '2F 00 F0 7F 39 00 C7 6B 4E 00 DE 7A 45 00 C9 7B' + '60 00 F3 8B 32 00 FD 9C 35 00 BE 80 70 00 BF 91' + '7F 00 F0 96 46 00 F6 99 44 00 F7 99 44 00 E8 8D' + '51 00 ED 8A 5E 00 FD A4 44 00 FF AA 46 00 FF AA' + '49 00 F7 A2 52 00 FF B2 59 00 FF B5 59 00 FF B2' + '5D 00 FF B3 5E 00 C4 84 72 00 EF A1 6B 00 FF B4' + '62 00 FF B5 68 00 F2 A7 73 00 F8 B3 71 00 F8 B5' + '7E 00 FF C3 73 00 FF C5 7A 00 FF C7 7A 00 96 8A' + '85 00 96 90 8E 00 99 91 8E 00 92 91 90 00 96 95' + '94 00 9F 97 94 00 9A 98 97 00 3C 17 95 00 00 00' + '38 00 A8 44 F9 77 21 00 00 00 B8 0C 38 00 00 00' + '38 00 30 7E 0D 01 14 17 95 00 B1 A2 9F 00 5C 19' + '95 00 00 40 0D 01 68 19 95 00 77 82 F5 77 98 7F' + 'F5 77 3A 8A F5 77 00 04 00 00 C4 A2 AF 00 10 00' + '00 00 10 00 00 00 C9 94 88 00 CD 9A 8E 00 D9 9C' + '85 00 C3 9C 95 00 C2 9E 95 00 CE 9D 91 00 D1 9F' + '94 00 CD A0 90 00 C6 AA 9F 00 DA A3 98 00 DF AA' + '98 00 DF A9 9A 00 DC AB 9F 00 EC B5 8D 00 F1 B2' + '83 00 F3 B3 8B 00 F5 B6 8A 00 F7 B5 8E 00 F7 B8' + '8A 00 EE AC 93 00 F6 BB 99 00 CF B3 A9 00 D9 B0' + 'A0 00 D1 B7 B1 00 D9 BD B2 00 E9 BC A3 00 E5 BE' + 'AF 00 EA BC A8 00 FD C3 8C 00 FF D1 8F 00 FE C7' + '92 00 F8 C3 98 00 F9 C2 9B 00 FC C1 99 00 FF C8' + '9B 00 FA CF 9C 00 FB D0 97 00 FD CD A3 00 F8 CE' + 'AE 00 FC D0 A1 00 F7 D0 AE 00 FF DD AC 00 F4 CB' + 'B0 00 F2 CA B5 00 FF DF B2 00 FF E2 AD 00 FE E0' + 'B3 00 FF E1 B3 00 FF E4 B6 00 FE E0 BA 00 D3 C0' + 'C2 00 A8 01 38 00 10 44 0D 01 40 00 00 00 00 00' + '00 00 A8 01 38 00 38 44 0D 01 38 44 0D 01 E0 D0' + 'D1 00 EE D6 D4 00 E3 D4 D8 00 FA DF DB 00 FB E2' + 'C7 00 FF E8 C0 00 FF E8 C1 00 FF ED CB 00 FF EC' + 'CC 00 08 44 0D 01 08 44 0D 01 FB E2 D3 00 FF EB' + 'D2 00 FF F0 D5 00 FF F1 D6 00 FC E5 E0 00 FC E7' + 'E4 00 F0 E6 EA 00 00 40 0D 01 A4 18 95 00 E5 3A' + 'F8 77 06 00 00 00 08 44 0D 01 00 00 38 00 00 40' + '0D 01 00 00 00 00 78 19 95 00 CA 8C F5 77 78 01' + '38 00 BE 8E F5 77 08 06 38 00 37 90 F5 77 08 40' + '0D 01 08 40 0D 01 40 00 00 00 40 00 00 00 D0 BB' + 'BB 00 E0 B2 A5 00 EE BD A2 00 E3 B4 AA 00 E4 BB' + 'AF 00 F1 B6 A7 00 F6 BE A2 00 F0 BA AB 00 E5 BE' + 'B3 00 EC BC B0 00 00 40 0D 01 00 40 0D 01 F4 C4' + '97 00 78 01 38 00 08 40 0D 01 E0 07 0D 01 E8 07' + '0D 01 78 01 38 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 F5 C8 AA 00 00 40 0D 01 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 C2' + 'B7 00 08 04 00 00 87 00 00 00 08 04 00 00 08 01' + '00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00' + '38 00 BC 18 95 00 C0 18 95 00 B0 19 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 81 E9' + '49 00 00 00 38 00 00 00 00 00 08 40 0D 01 08 40' + '0D 01 A4 1A 95 00 40 00 00 00 40 00 00 00 B8 10' + 'E9 77 FF FF FF FF C9 F1 E7 77 16 EA 4B 00 F8 00' + '00 00 B4 1A 95 00 DC E3 49 00 E0 A3 4E 00 FF FF' + 'FF FF 10 00 00 00 10 DA 4B 00 08 40 0D 01 71 CC' + '43 00 08 40 0D 01 30 7E 0D 01 A4 1A 95 00 C4 A2' + 'AF 00 C4 F5 AF 00 02 00 00 00 30 7E 0D 01 0F 02' + '00 00 48 40 0D 01 10 00 00 00 00 00 00 00 20 00' + '00 00 08 40 0D 01 40 00 00 00 10 00 00 00 00 01' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 10 00 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 07 07 07 07 07 07 07' + '07 07 07 07 07 07 00 00 02 02 02 02 02 02 02 02' + '02 02 02 02 07 07 00 00 02 06 04 05 04 05 04 04' + '04 04 03 02 07 07 00 02 06 05 05 04 05 04 05 04' + '04 04 03 07 02 07 00 02 06 05 05 05 05 05 04 05' + '04 04 02 07 02 07 02 06 05 05 05 05 04 05 05 04' + '05 03 07 03 03 07 02 06 05 05 05 05 05 05 04 05' + '04 03 07 03 03 07 02 02 02 02 02 02 02 02 02 02' + '02 02 03 05 03 07 00 02 06 05 05 05 05 05 05 05' + '05 05 05 05 03 07 00 02 06 05 05 05 05 05 05 05' + '06 06 06 06 03 07 00 02 06 05 05 05 05 05 06 02' + '02 02 02 02 02 00 00 00 02 06 06 06 06 06 02 00' + '00 00 00 00 00 00 00 00 00 02 02 02 02 02 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 FF FF 00 00 E0 00' + '00 00 C0 00 00 00 C0 00 00 00 80 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 00 00 00 80 01 00 00 C0 7F 00 00 E0 FF' + '00 00 FF FF 00 00' +} */ + +/* BINRES floppy.ico */ +5 ICON floppy.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 A6 0E 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 CE 0F 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 01 01 00 02 02 02 00 04 04 04 00 05 05' + '05 00 07 07 07 00 09 09 09 00 0A 0A 0A 00 0C 0C' + '0C 00 0D 0D 0D 00 10 10 10 00 12 12 12 00 13 13' + '13 00 15 15 15 00 16 16 16 00 17 17 17 00 18 18' + '18 00 19 19 19 00 1B 1B 1B 00 1C 1C 1C 00 1E 1E' + '1E 00 1F 1F 1F 00 20 20 20 00 21 21 21 00 23 23' + '23 00 24 24 24 00 25 25 25 00 26 26 26 00 27 27' + '27 00 28 28 24 00 2A 2A 25 00 28 28 28 00 2A 2A' + '2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E 2E 00 32 32' + '32 00 33 33 33 00 34 34 34 00 35 35 35 00 37 37' + '37 00 3B 3B 3B 00 3C 3C 3C 00 3D 3D 3D 00 3F 3F' + '3F 00 40 40 40 00 44 44 44 00 45 45 45 00 46 46' + '46 00 47 47 47 00 48 48 48 00 49 49 49 00 4B 4B' + '4B 00 4C 4C 4C 00 4E 4E 4E 00 50 50 50 00 52 52' + '52 00 57 57 57 00 59 59 59 00 5E 5E 5E 00 61 61' + '61 00 64 64 64 00 65 65 65 00 6A 6A 6A 00 7F 60' + '60 00 71 71 71 00 77 77 77 00 79 79 79 00 7F 7F' + '7F 00 D5 40 40 00 00 C0 00 00 00 FF 00 00 87 80' + '7D 00 8B 86 84 00 8A 8A 8A 00 8C 8C 8C 00 8D 8D' + '8D 00 8E 8E 8E 00 97 97 97 00 99 99 99 00 9A 9A' + '9A 00 9E 9E 9E 00 A3 A3 9E 00 A4 A4 A4 00 A7 A7' + 'A7 00 AA AA AA 00 AB AB AB 00 AD A8 AB 00 AE AE' + 'AE 00 AF AF AF 00 B0 B0 B0 00 B2 B2 B2 00 B5 B5' + 'B5 00 B6 B6 B6 00 B7 B7 B7 00 BB BB BB 00 BC BC' + 'BC 00 BD BD BD 00 BF BF BF 00 EA 80 80 00 CA A8' + '94 00 CC AF 9D 00 E9 B6 99 00 E9 B8 9C 00 CE B6' + 'A6 00 D0 B3 A3 00 EB BE A5 00 D2 C3 B9 00 EC C0' + 'A7 00 EF CC B8 00 C2 C2 C2 00 C4 C4 C4 00 C5 C5' + 'C5 00 C6 C6 C6 00 C8 C9 C9 00 C9 C9 C9 00 CA CA' + 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CF CF' + 'CF 00 D5 CB C4 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' + 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' + 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' + 'D8 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' + 'DE 00 DF DF DF 00 F1 D2 C2 00 F2 D6 C7 00 F4 DD' + 'D0 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3' + 'E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7' + 'E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' + 'EB 00 EC EC EC 00 ED ED ED 00 F0 F0 F0 00 F2 F2' + 'F2 00 F3 F3 F3 00 F9 F9 F9 00 FA FA FA 00 FF FF' + 'FF 00 00 00 00 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 56 00' + '00 00 00 00 00 00 03 00 00 00 5E 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 66 6C 6F 70 70 79 2E 69 63' + '6F 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 2A 2A 2A 2A 40 40 40 40 40 40 40 40 40 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4B 4B 4B 4B A1 A1 A1 A1 A1 A1 A1 A1 A1 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1D 00 4B 08 45 45 45 45 45 45 45 45 45 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1E A1 A1 08 63 63 63 63 63 63 63 63 63 00 A1' + 'A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' + 'A1 03 08 0A 10 9A 94 94 94 94 94 94 94 94 00 A1' + 'A1 17 22 22 21 21 21 21 21 21 21 20 20 20 20 20' + '20 08 08 10 0F 99 94 4F 4F 4F 4F 4F 4F 4F A1 01' + '4A 98 95 95 7E 46 94 95 90 82 7C 77 77 77 72 55' + '23 A1 A1 15 10 97 93 95 95 97 97 98 98 99 A1 11' + '57 98 95 95 47 47 46 89 7F 7C 75 77 77 77 77 2D' + '23 A1 A1 0D 0C 96 94 4F 4F 4F 4F 4F 4F 4F A1 1F' + '7B 98 98 95 95 47 5C 5D 29 29 29 29 29 29 29 5D' + '5D A1 A1 07 09 95 94 90 90 91 91 93 93 94 A1 1F' + '7B 95 98 95 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' + 'A1 19 15 05 07 92 94 4F 4F 4F 4F 4F 4F 4F A1 1C' + '7C 97 98 98 54 56 58 59 59 59 59 56 56 56 56 56' + '56 24 08 A1 A1 92 92 94 94 96 96 97 97 98 A1 1B' + '7D 98 9A 96 95 91 8F 86 82 7C 7C 7A 7A 7A 7A 7A' + '7A 28 02 03 03 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 19' + '80 96 8E 8F 8D 89 89 89 8D 8D 8D 8D 8D 8D 8D 8D' + '8D 2C 09 0B 0E 17 1B 2A 2E 30 30 22 22 22 A1 19' + '88 83 6F 62 82 83 83 83 83 83 83 83 83 83 83 83' + '83 2E 18 12 16 21 27 2E 31 30 30 22 22 22 A1 04' + '6E 60 5B 56 5F 7F 7F 7E 7D 7F 81 82 81 7D 7D 7E' + '7F 34 35 23 25 2F 2E 34 34 2A 24 1A 13 0E 00 A1' + '53 78 70 62 73 7C 7A 7A 7A 7F 7F 7F 7F 7F 7A 7E' + '7A 38 39 27 2C 4B 4B 4B 4B 4B 4B 4B 4B 4B 00 A1' + '3A 7A 77 77 74 7D 7D 7E 7F 80 80 80 80 80 7F 85' + '91 3B 3B 3F 2E 4D A0 49 48 69 6C 66 66 66 00 A1' + '2D 7C 74 74 7E 7D 7D 7C 7C 7C 7C 7D 7C 7D 7C 7B' + '7A 3B 3B 3F 2E 4D A0 49 48 69 6C 66 66 66 00 A1' + '05 87 76 7D 7D 7A 7A 7A 7A 7D 7D 7D 7D 7D 7D 7D' + '7D 3E 3F 41 43 51 A0 38 36 8B 6D 67 66 66 00 A1' + 'A1 87 78 7D 7D 7A 7A 7A 7A 7A 78 7D 7D 7D 7D 7D' + '7D 2A 3F 41 43 55 A0 37 35 8C 8A 6A 66 66 00 A1' + 'A1 82 7E 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D 7D' + '7D A1 A1 A1 A1 52 84 84 84 79 6B 68 65 64 00 A1' + 'A1 76 80 7D 7D 80 80 80 80 80 80 80 7D 7D 7D 76' + '73 6F 6E 61 7A 06 A1 00 00 00 00 00 00 00 00 A1' + 'A1 4E 86 86 88 88 87 87 87 87 87 87 87 87 87 87' + '87 94 94 86 71 A1 A1 00 00 00 00 00 00 00 00 00' + 'A1 42 7D 8E 88 88 88 8D 8D 8D 8D 8D 8D 8D 8D 8E' + '8E 94 94 83 5F A1 A1 00 00 00 00 00 00 00 00 00' + 'A1 27 61 93 93 94 98 98 98 98 98 98 98 98 98 94' + '94 94 93 7E 50 A1 A1 00 00 00 00 00 00 00 00 00' + 'A1 14 56 9A 94 99 98 9A 98 98 98 98 98 98 98 98' + '99 92 98 80 4A A1 A1 00 00 00 00 00 00 00 00 00' + '00 A1 4C 6F 5B 5B 98 9B 9B 9B 9B 9B 9B 9B 9B 9D' + '7F 5D 5E 77 3C A1 A1 00 00 00 00 00 00 00 00 00' + '00 A1 3D 87 86 91 9E 9E 9E 9E 9E 9E 9E 9E 9E 9F' + '9C 82 86 5A 26 A1 00 00 00 00 00 00 00 00 00 00' + '00 A1 A1 2B 33 32 32 32 32 32 32 32 32 32 32 32' + '32 33 33 02 A1 00 00 00 00 00 00 00 00 00 00 00' + '00 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' + 'A1 A1 A1 A1 A1 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF E0 00 FF FF E0 00 FF FF E8 00 FF FF' + 'E0 00 80 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 7F 80 00 00 7F C0 00' + '00 7F C0 00 00 7F C0 00 00 7F E0 00 00 7F E0 00' + '00 FF E0 00 01 FF E0 00 01 FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 01 00 00 01 01' + '01 00 03 06 04 00 05 05 05 00 09 09 09 00 0A 0C' + '0C 00 08 0D 0F 00 13 13 13 00 15 15 15 00 16 16' + '15 00 17 17 17 00 18 18 18 00 19 19 19 00 1D 1D' + '1D 00 1E 1E 1E 00 31 0A 0B 00 1A 1E 20 00 35 19' + '35 00 21 21 21 00 29 23 23 00 30 2A 30 00 31 31' + '31 00 32 33 33 00 34 34 34 00 35 35 35 00 36 36' + '36 00 39 39 39 00 3A 3A 3B 00 3B 3B 3B 00 7A 00' + '00 00 4E 3E 3E 00 3F 41 42 00 44 44 44 00 46 46' + '46 00 4B 4B 4B 00 50 52 52 00 57 57 57 00 59 59' + '59 00 5C 5C 5C 00 5E 5E 5E 00 65 6A 68 00 69 69' + '69 00 6E 6E 6E 00 6F 6E 6E 00 77 6E 69 00 7E 69' + '69 00 72 72 72 00 75 75 75 00 79 73 79 00 79 79' + '79 00 7B 7B 7B 00 7F 7F 7F 00 83 00 00 00 88 70' + '70 00 00 FF 00 00 75 99 75 00 97 97 97 00 9B 9B' + '9B 00 A5 A5 A5 00 A6 A6 A6 00 A8 A2 A8 00 A8 A8' + 'A8 00 A9 A9 A9 00 AF AF AF 00 B8 AC B8 00 B2 B2' + 'B2 00 ED B7 97 00 C0 AE A4 00 DB B7 A2 00 DC B7' + 'A2 00 B7 E6 B7 00 FB C6 A8 00 F9 C7 AB 00 C0 C0' + 'C0 00 C1 C2 C2 00 C2 C2 C2 00 C3 C3 C3 00 C6 CD' + 'CD 00 C7 CE CE 00 C9 C9 C9 00 CA CA CA 00 C8 CF' + 'CF 00 CC CC CC 00 CE CE CE 00 D0 D0 D0 00 D1 D1' + 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' + 'D5 00 D6 D6 D6 00 D7 D7 D7 00 DE D8 D3 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DE DE DE 00 FF C9' + 'C9 00 FF D7 D7 00 FF E3 D0 00 DF E6 E6 00 E0 E0' + 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E4 E4 E4 00 E5 E5' + 'E5 00 E6 E6 E6 00 E8 E3 E1 00 E8 E8 E8 00 E9 E9' + 'E9 00 EA EA EA 00 EB EB EB 00 ED ED ED 00 F3 F3' + 'F3 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6 F6 00 FF F2' + 'FF 00 F9 F9 F9 00 FA FA FA 00 FB FB FB 00 FB FC' + 'FC 00 FC FC FC 00 FF FD FE 00 FE FE FE 00 FF FF' + 'FF 00 00 00 00 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA D8 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 F1 D2' + 'C2 00 F2 D6 C7 00 F4 DD D0 00 E0 E0 E0 00 E1 E1' + 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' + 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' + 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' + 'ED 00 F0 F0 F0 00 F2 F2 F2 00 F3 F3 F3 00 F9 F9' + 'F9 00 FA FA FA 00 FF FF FF 00 00 00 00 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 56 00 00 00 00 00 00 00 03 00' + '00 00 5E 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 66' + '6C 6F 70 70 79 2E 69 63 6F 00 1A 93 4B 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '06 14 36 2E 2E 2E 00 00 00 00 00 00 00 00 00 0A' + '29 10 35 1E 1E 1E 00 7F 7F 7F 7F 7F 7F 7F 7F 01' + '03 1F 63 62 62 62 7F 2C 3D 38 41 40 3E 3C 3F 0D' + '05 24 65 4E 4F 52 7F 7C 76 37 47 31 33 32 42 08' + '7F 23 6B 51 53 53 7F 7D 7D 12 15 19 19 18 19 13' + '7F 23 7D 66 68 69 7F 7E 72 7D 77 75 72 72 7E 28' + '7F 02 7F 0B 0C 04 7F 7B 3B 58 5B 5A 5C 5B 69 25' + '0F 16 1C 20 11 07 7F 5C 54 54 57 59 5A 5A 67 27' + '25 17 6C 44 46 45 7F 3A 57 58 55 55 56 57 66 26' + '2F 22 4B 2D 48 43 00 2A 61 55 55 55 56 57 67 1D' + '0E 21 7A 5D 64 49 00 1B 71 60 5E 5F 5F 5E 5E 6A' + '71 30 7F 00 00 00 00 04 72 6F 6D 6B 6A 6A 69 70' + '75 1A 00 00 00 00 00 7F 6E 50 77 75 73 74 78 54' + '79 09 00 00 00 00 00 7F 2B 4A 4D 4C 4C 4C 4C 4A' + '39 7F 00 00 00 00 00 00 7F 7F 7F 7F 7F 7F 7F 7F' + '7F 00 00 00 00 00 FF C0 00 00 FF 80 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 80 0F' + '00 00 C0 1F 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00' + '00 00 00 09 99 99 00 00 00 00 00 0F FF FF 0F FA' + '77 77 00 0F 88 88 0F F0 00 00 00 0F FF FF 0F F7' + '77 77 70 00 00 00 07 77 77 77 70 00 00 00 07 77' + '77 77 70 08 88 88 07 77 77 77 70 08 87 77 07 77' + '77 77 70 07 8F 77 07 77 77 77 77 70 00 00 08 77' + '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 77' + '77 77 77 70 00 00 00 00 00 00 00 00 00 00 FF 80' + '00 00 FF 80 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 07 00 00 80 07' + '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 04 00 00 00' + '00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 08 88 88 88 88 00 00 00 00 00 00 00 00 00 08' + '88 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '08 09 99 99 99 99 00 00 00 00 00 00 00 00 00 00' + '00 07 77 77 77 77 00 00 00 00 00 00 00 00 00 00' + '00 0F FF FF FF FF 00 00 00 00 00 00 00 00 00 00' + '00 0F F8 88 88 88 00 8F FF 7A FF F7 77 77 77 00' + '00 0F FF FF FF FF 00 7F FF AA A7 77 77 77 70 00' + '00 0F F8 88 88 88 00 7F FF FA 77 00 00 00 07 70' + '00 0F FF FF FF FF 00 7F FF 00 00 00 00 00 00 00' + '00 0F F8 88 88 88 00 7F FF 77 77 77 77 77 77 70' + '00 0F FF FF FF FF 00 7F FF 77 77 77 77 77 77 70' + '00 00 00 00 00 00 00 7F FF FF FF FF FF FF FF F0' + '00 00 00 88 80 00 00 77 77 77 77 77 77 77 77 78' + '00 00 08 88 80 00 00 77 77 77 77 77 77 77 77 78' + '80 08 88 80 00 00 00 77 77 77 77 77 77 77 77 78' + '80 08 88 88 88 88 00 87 77 77 77 77 77 77 77 78' + '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 78' + '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 78' + '88 88 F8 87 77 77 00 07 77 77 77 77 77 77 77 70' + '88 87 F8 8F 77 77 00 07 77 77 77 77 77 77 77 70' + '00 07 77 77 77 77 00 07 77 77 77 77 77 77 77 77' + '77 70 00 00 00 00 00 08 77 77 77 77 77 77 77 77' + '77 70 00 00 00 00 00 08 77 77 77 77 77 77 77 77' + '77 70 00 00 00 00 00 00 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 87 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 87 77 77 77 77 77 77 77' + '77 00 00 00 00 00 00 00 00 88 88 88 88 88 88 88' + '80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF E0 00 FF FF E0 00 FF FF' + 'E0 00 FF FF E8 00 E0 00 00 00 80 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 3F 80 00 00 7F C0 00 00 7F C0 00 00 7F C0 00' + '00 7F E0 00 00 7F E0 00 00 FF E0 00 00 FF E0 00' + '01 FF FF FF FF FF 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 01 01 00 02 02 02 00 03 03 03 00 04 04' + '04 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' + '08 00 09 09 09 00 0A 0A 0A 00 0B 0B 0B 00 0C 0C' + '0C 00 0D 0D 0D 00 0E 0E 0E 00 10 10 10 00 11 11' + '11 00 12 12 10 00 12 12 12 00 13 13 13 00 14 14' + '14 00 15 15 15 00 16 16 14 00 16 16 16 00 17 17' + '17 00 18 18 18 00 19 19 19 00 1B 1B 1B 00 1C 1C' + '1C 00 1E 1E 1E 00 1F 1F 1F 00 22 22 1F 00 20 20' + '20 00 21 21 21 00 22 22 22 00 23 23 23 00 24 24' + '24 00 25 25 25 00 26 26 26 00 27 27 27 00 28 28' + '24 00 2A 2A 25 00 2B 2B 26 00 28 28 28 00 29 29' + '29 00 2A 2A 2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E' + '2E 00 2F 2F 2F 00 30 30 2C 00 30 30 30 00 32 32' + '32 00 33 33 33 00 36 36 30 00 34 34 34 00 35 35' + '35 00 36 36 36 00 37 37 37 00 39 39 39 00 3B 3B' + '3B 00 3C 3C 3C 00 3D 3D 3D 00 3F 3F 3F 00 40 40' + '40 00 41 41 41 00 42 42 42 00 43 43 43 00 44 44' + '44 00 45 45 45 00 46 46 46 00 47 47 47 00 48 48' + '48 00 49 49 49 00 4A 4A 4A 00 4B 4B 4B 00 4C 4C' + '4C 00 4E 4E 4E 00 4F 4F 4F 00 50 50 50 00 52 52' + '52 00 53 53 53 00 54 54 54 00 57 57 57 00 5B 58' + '57 00 59 59 59 00 5D 5D 5D 00 5E 5E 5E 00 5F 5F' + '5F 00 61 61 61 00 64 64 64 00 65 65 65 00 66 66' + '66 00 6D 6A 67 00 6A 6A 6A 00 7F 60 60 00 71 71' + '71 00 75 75 75 00 77 77 77 00 7B 77 75 00 79 79' + '79 00 7A 7A 7A 00 7E 7E 7E 00 7F 7F 7F 00 C0 00' + '00 00 83 7A 75 00 D5 40 40 00 00 C0 00 00 00 FF' + '00 00 87 80 7D 00 80 80 80 00 83 83 83 00 84 84' + '84 00 8B 86 84 00 8A 8A 8A 00 8C 8C 8C 00 8D 8D' + '8D 00 8E 8E 8E 00 90 90 90 00 93 93 93 00 97 97' + '97 00 99 99 99 00 9A 9A 9A 00 9E 9E 9E 00 9F 9F' + '9F 00 A3 A3 9E 00 A4 A4 A4 00 A6 A6 A6 00 A7 A7' + 'A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA AA 00 AB AB' + 'AB 00 AD A8 AB 00 AB AC AC 00 AD AD AD 00 AE AE' + 'AE 00 AF AF AF 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' + 'B2 00 B3 B3 B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7' + 'B7 00 B8 B4 B6 00 B8 B6 B6 00 B8 B8 B8 00 BA BA' + 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' + 'BE 00 BF BF BF 00 EA 80 80 00 CA A8 94 00 CC AF' + '9D 00 E9 B6 99 00 E9 B8 9C 00 CE B6 A6 00 D0 B3' + 'A3 00 D0 BC B0 00 EA BB A0 00 EA BC A1 00 EB BE' + 'A5 00 D2 C3 B9 00 EC C0 A7 00 EC C2 AA 00 ED C5' + 'AE 00 ED C6 AF 00 EE C8 B3 00 EF CC B8 00 F0 CF' + 'BC 00 F0 D0 BE 00 C0 C0 C0 00 C1 C1 C1 00 C2 C2' + 'C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5 C5 00 C6 C6' + 'C6 00 C8 C8 C8 00 C8 C9 C9 00 C9 C9 C9 00 CA CA' + 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' + 'CE 00 CF CF CF 00 D5 CB C4 00 D0 CB C8 00 D7 D2' + 'CE 00 D9 D1 CC 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' + 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' + 'D6 00 D7 D7 D7 00 DC D9 D7 00 D8 D8 D8 00 D9 D9' + 'D9 00 DA DA D8 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 FF C0' + 'C0 00 F1 D2 C2 00 F2 D6 C7 00 F3 D9 CB 00 F4 DD' + 'D0 00 F6 E4 D9 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' + 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' + 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' + 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' + 'EE 00 EF EF EF 00 F9 EE E8 00 F0 F0 F0 00 F1 F1' + 'F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5' + 'F5 00 F6 F6 F6 00 F7 F7 F7 00 FD F9 F7 00 F8 F8' + 'F8 00 F9 F9 F9 00 FA FA FA 00 FF FF FF 00 00 00' + '00 00 C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 F8 F8 F8 F8 F8' + 'F8 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 3D 3D 3D 3D 3D' + 'F8 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 5F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 73 73 73 73 73' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 16 36 36 1F 04' + 'F8 68 68 68 68 68 68 68 68 68 68 68 68 68 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 28 00 00 73 0C' + 'F8 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 6A 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 F8 29 F8 F8 F8 0C' + 'F8 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 00 00' + '00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 11 2A 32 1F 0F' + 'F8 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 00 00' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 04 0C 0C 0F 19' + 'F8 E7 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 00 F8' + 'F8 F8 F8 21 2F 2E 2F 2E 2E 2E 2E 2E 2E 2E 2E 2E' + '2E 2E 2D 2D 2D 2D 2D 2D 2D 2D F8 0C 0C 0F 19 18' + 'F8 E6 E1 79 79 79 79 79 79 79 79 79 79 79 00 F8' + 'F8 26 76 91 87 86 85 BB BA B9 B7 B2 B1 B0 B0 B1' + 'AE AF 99 99 96 97 94 97 97 97 F8 0C 0F 19 19 1D' + 'F8 E5 CF DA DA DA DB DB DB DC DD DD DD DE F8 F8' + '01 72 85 E5 E2 E2 E2 C6 6B 6B E1 E2 E2 DD D1 CB' + 'C4 BB BB BB BB BB B6 BB 83 30 F8 F8 F8 19 1E 19' + 'F8 E4 E0 E1 E2 E2 E3 E4 E4 E4 E5 E5 E5 E6 F8 F8' + '1A 85 E5 E5 E2 E2 E2 6C 6C 6C 6B DB D3 C7 BA C4' + 'B9 BB BB BB BB BB BB BB 40 30 F8 F8 F8 1E 15 13' + 'F8 E3 E1 79 79 79 79 79 79 79 79 79 79 79 F8 F8' + '2C 85 E4 E5 E5 E2 E2 6C 6C 6C 6C B9 B5 5C 5C 5C' + '5C 5C 5C 5C 5C 5C 5C BB 77 40 F8 F8 F8 F8 0E 0F' + 'F8 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 F8 F8' + '2B C3 E6 E5 E5 E2 E2 E2 6C 6C 8E 8E 8F 3C 3C 3C' + '3C 3C 3C 3C 3C 3C 3C 8F 8F 8F F8 F8 F8 F8 0A 0D' + 'F8 E2 E1 DD DD DD DD DE DE DF E0 E0 E0 E1 F8 F8' + '2B C3 E8 E2 E5 E2 E2 F8 F8 F8 F8 F8 F8 F8 F8 F8' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 24 1E 05 07 0A' + 'F8 DF E1 79 79 79 79 79 79 79 79 79 79 79 F8 F8' + '27 C3 E9 E5 E5 E5 E5 6E 3C 3C 3C 3C 3C 3C 3C 3C' + '3C 3C 3C 3C 3C 3C 3C 3C 3C 3C F8 2E 10 02 03 03' + 'F8 D0 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 F8 F8' + '27 C4 ED E4 E5 E5 E5 80 80 84 88 8A 89 89 89 89' + '89 89 84 84 84 84 84 84 84 84 F8 34 0C F8 F8 F8' + 'F8 DF DF E0 E1 E1 E2 E3 E3 E3 E4 E4 E4 E5 F8 F8' + '26 C5 EE E5 E7 E5 E3 E2 E0 DE DC CF D0 CB CC C4' + 'C4 BD C2 C2 C2 C2 C2 C2 C2 C2 F8 3A 02 03 04 04' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + '26 C5 F2 F4 F1 F1 F1 F0 F0 EF EF EE EE EE ED ED' + 'EC EC EC EB EB EB E9 E9 E8 E8 F8 3A 07 09 0B 0D' + '0F 13 1A 1D 27 37 42 46 46 46 46 2F 2F 2F F8 F8' + '24 C8 F7 E3 DB DC DC DA D3 D3 D3 D3 D3 DA DA DA' + 'DA DA DA DA DA DA DA DA DA DA F8 3F 0D 10 12 17' + '1B 21 26 33 3D 44 47 46 46 46 2F 2F 2F 2F F8 F8' + '24 D2 F4 CC B2 95 99 CB CE CC CC CC CC CC CC CC' + 'CC CC CC CC CC CC CC CC CC CC F8 44 23 18 1B 20' + '27 2E 38 40 44 47 4A 46 46 2F 2F 2F 2F 2F F8 F8' + '1E CE EE B4 82 90 8A B1 CE CB CB CB CB CB C9 C9' + 'C9 C9 C9 C9 C9 C9 CB CB CB CB F8 4B 30 1E 25 2E' + '31 3B 43 44 47 4B 49 42 39 2F 23 1C 1C 14 F8 F8' + '05 B0 F1 96 8C B1 84 95 CB C7 C7 C7 C6 C5 C5 C7' + 'C9 CB CB C9 C7 C5 C5 C5 C6 C7 F8 4B 4C 27 30 35' + '3D 45 44 47 4B 4B 45 3D 34 2D 25 1C 1C 17 00 F8' + 'F8 7E EF BD B3 C4 99 B7 C5 C4 C2 C5 C2 C2 C7 C7' + 'C7 C7 C7 C7 C7 C7 C2 C2 C6 C2 F8 50 53 3D 38 3F' + 'F8 73 73 73 73 73 73 73 73 73 73 73 73 73 00 F8' + 'F8 66 E9 C3 BD B9 BD C3 BC BD C7 C7 C7 C7 C7 C7' + 'C7 C7 C7 C7 C7 C7 C7 C7 C7 DB F8 53 57 56 49 45' + 'F8 70 F3 EA D9 D7 AC A8 A2 9D 9D 9D 9D 9D 00 F8' + 'F8 55 E3 C2 BB BB BB B8 C5 C5 C5 C5 C6 C7 C8 C8' + 'C8 C8 C8 C8 C8 C8 C7 C7 CF DE F8 57 57 5B 5E 44' + 'F8 75 F7 BF 71 6D 69 A0 A6 9D 9D 9D 9D 9D 00 F8' + 'F8 40 C9 C4 B8 B9 B8 C6 C5 C5 C5 C3 C4 C4 C4 C4' + 'C4 C4 C5 C4 C5 C5 C4 C4 C3 C2 F8 57 57 5B 5E 44' + 'F8 75 F7 BF 71 6D 69 A0 A6 9D 9D 9D 9D 9D 00 F8' + 'F8 22 90 CF B8 B9 BC C5 C5 BD C3 C2 C2 C2 C2 BD' + 'C5 C5 BC C5 C5 C5 C5 C5 C5 BC F8 57 5B 5E 5E 60' + 'F8 78 F7 92 52 4E 54 AD A9 A3 9D 9D 9D 9D 00 F8' + 'F8 07 7C D1 BA BB C5 C5 C5 C2 C2 C2 C2 C2 C2 C5' + 'C5 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5B 5B 5E 60 64' + 'F8 7B F7 89 50 4D 5D D6 AB A7 9E 9D 9D 9D 00 00' + 'F8 F8 6F D1 BD C3 C5 C5 C2 C2 C2 C2 C2 C2 C2 C2' + 'BD C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5B 5B 5E 64 64' + '3D 83 F7 7F 4F 4C 63 D8 D5 AA A4 9D 9D 9D 00 00' + 'F8 F8 58 D0 C3 C4 C5 C5 C3 C3 C3 C3 C3 C3 C3 C3' + 'C3 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 5E 60 64 66 66' + 'F8 8B F7 DA D3 CA C1 D9 D7 AC A8 A2 A2 9D 00 00' + 'F8 F8 41 CB C6 C4 C5 C5 C5 C5 C5 C5 C5 C5 C5 C5' + 'C5 C5 C5 C5 C5 C5 C5 C5 C5 C5 F8 F8 F8 F8 F8 F8' + 'F8 7D CD CD CD CD C0 BE A5 A1 9F 9C 9C 9B 00 00' + 'F8 F8 2F BA C8 C7 C5 C5 C8 C8 C8 C8 C8 C8 C8 C8' + 'C8 C8 C8 C5 C5 C5 C5 C5 BA B7 B4 B2 B0 8D 97 C2' + '79 09 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00' + 'F8 F8 19 8A CF CF D2 D2 D2 CC CE CE CE CE CE CE' + 'CE CE CE CE D1 D1 D1 D1 D1 CE D1 D1 E1 CC BA B8' + '65 02 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00' + 'F8 F8 08 78 D0 D3 D0 D2 D2 D2 D1 D1 D1 D1 D1 D1' + 'D1 D1 D1 D1 D1 D1 D1 D1 D1 D1 E1 E1 E1 D1 D0 B4' + '51 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 F8 F8 62 C5 DC DB D2 D2 D2 D2 D2 DA DA DA DA' + 'DA DA DA DA DA DA DA DA DB DB E1 E1 E1 DD CC 95' + '3B F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 F8 F8 4B B7 DF DD DE E5 E5 E5 E5 E5 E5 DE DE' + 'DE DE DE DE DE DE DF DF E1 E1 E1 E1 DE E0 C8 81' + '20 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 F8 F8 38 97 E0 E0 E0 E1 E1 E5 E5 E5 E5 E5 E5' + 'E5 E5 E5 E5 E5 E5 E5 E1 E1 E1 E1 E1 E0 E2 C6 7A' + '0B F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 F8 F8 1D 84 DE E7 E1 E0 E6 E5 E4 E7 E5 E5 E5' + 'E5 E5 E5 E5 E5 E5 E5 E5 E5 E6 E4 DF E5 E5 C8 72' + 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 F8 F8 08 79 DE D3 97 AF C8 E6 E7 E7 E8 E8 E7' + 'E6 E5 E5 E6 E7 E8 E8 E7 E8 DE B0 98 C3 E6 C6 61' + 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F8 F8 74 DA B2 8C 93 8C E5 EC EB EB EB EB' + 'EB EB EB EB EB EB EB EB EE C7 8A 8F 90 E5 BB 59' + 'F8 F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F8 F8 5A BC D1 D0 C7 DE F5 F5 F5 F5 F5 F5' + 'F5 F5 F5 F5 F5 F5 F5 F5 F6 ED D3 CB D0 C9 8A 37' + 'F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F8 F8 1A 6E 98 C5 C9 CF CB CB CB CB CB CB' + 'CB CB CB CB CB CB CB CB CB CC CC C9 BB 8A 56 06' + 'F8 F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 F8 F8 F8 0C 3E 49 48 48 48 48 48 48 48 48' + '48 48 48 48 48 48 48 48 48 48 48 49 49 31 02 F8' + 'F8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8' + 'F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 F8 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F3 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 C0 00 00 00 03 FF 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' + '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' + '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07' + '77 77 77 77 77 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 08 88 88 88 88 88 88 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 08 88 88 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 09 99 99 99 99 99 99 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 09' + '99 99 99 99 99 99 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 07 77 77 77 77 77 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07' + '77 77 77 77 77 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 0F FF FF FF FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F' + 'F8 88 88 88 88 88 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 00 00 00 0F 7F FF FF FF FF FF 00 08' + '7F FF F7 AA FF FF 77 77 77 77 77 70 00 00 00 0F' + 'FF FF FF FF FF FF 00 07 FF FF FA AA AF 77 77 77' + '77 77 77 00 00 00 00 0F F8 88 88 88 88 88 00 07' + 'FF FF FA AA A7 78 88 88 88 88 87 80 00 00 00 0F' + 'FF FF FF FF FF FF 00 07 FF FF FF AA 77 70 00 00' + '00 00 07 77 00 00 00 0F FF FF FF FF FF FF 00 07' + 'FF FF F0 00 00 00 00 00 00 00 00 00 00 00 00 0F' + 'F8 88 88 88 88 88 00 07 FF FF F8 00 00 00 00 00' + '00 00 00 00 00 00 00 07 FF FF FF FF FF FF 00 07' + 'FF FF F7 77 77 77 77 77 77 77 77 77 00 00 00 0F' + 'FF FF FF FF FF FF 00 07 FF FF FF FF F7 77 77 77' + '77 77 77 77 00 00 00 00 00 00 00 00 00 00 00 07' + 'FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00' + '00 00 88 88 80 00 00 07 F7 7F FF 77 77 7F FF FF' + 'FF FF FF FF 00 00 00 00 00 08 88 88 00 00 00 07' + '77 77 77 77 77 77 77 77 77 7F 77 F7 08 00 00 00' + '00 88 88 80 00 00 00 07 F7 77 77 77 77 77 77 77' + '77 77 77 77 08 00 00 00 88 88 88 00 00 00 00 07' + '77 77 77 77 77 77 77 77 77 77 77 77 08 80 00 08' + '88 88 80 00 00 00 00 07 77 77 77 77 77 77 77 77' + '77 77 77 77 08 80 00 08 88 88 88 88 88 88 00 08' + '77 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' + 'FF F7 77 77 77 77 00 08 77 77 77 77 77 77 77 77' + '77 77 77 77 08 88 88 08 F7 88 87 77 77 77 00 00' + '77 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' + 'F7 88 87 77 77 77 00 00 77 77 77 77 77 77 77 77' + '77 77 77 77 08 88 88 08 F7 88 87 77 77 77 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 08 88 88 08' + 'F7 88 87 77 77 77 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 08 88 88 07 F7 88 8F 77 77 77 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 08 88 88 07' + 'FF 77 7F 77 77 77 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 00 00 00 07 77 77 77 77 77 77 00 00' + '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '00 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' + '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' + '00 00 00 00 00 00 00 00 00 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' + '00 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' + '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' + '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' + '00 87 77 77 77 77 77 77 77 77 77 77 77 77 78 00' + '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' + '77 77 77 77 77 77 70 00 00 00 00 00 00 00 00 00' + '00 08 77 77 77 77 77 77 77 77 77 77 77 77 80 00' + '00 00 00 00 00 00 00 00 00 00 08 88 88 88 88 88' + '88 88 88 88 88 80 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F3 00 00 00 00 FF FF FF F0 00 00 00 00 F0 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 03 FF 00 00 C0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' + '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' + '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 24 00 00 00 6C 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C' + '3C FF 3C 3C 3C FF 00 00 00 FF 7F 60 60 FF 7F 60' + '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' + '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' + '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 16 16 14 FF 36 36 30 FF 36 36 30 FF 22 22' + '1F FF 04 04 04 FF 00 00 00 FF C0 00 00 FF C0 00' + '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF C0 00' + '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF C0 00' + '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 28 28 24 FF 00 00 00 B4 00 00 00 9C 8C 8C' + '8C FF 0C 0C 0C FF 00 00 00 FF D5 40 40 FF D5 40' + '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' + '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' + '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 FF 2A 2A 25 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 0C 0C 0C FF 00 00 00 FF EA 80 80 FF EA 80' + '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' + '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' + '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 FF 12 12 10 FF 2B 2B 26 FF 30 30 2C FF 22 22' + '1F FF 10 10 10 FF 00 00 00 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' + '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 FF 04 04 04 FF 0C 0C 0C FF 0C 0C 0C FF 10 10' + '10 FF 18 18 18 FF 00 00 00 FF ED ED ED FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' + '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' + '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' + '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 00 00' + '00 FF 0C 0C 0C FF 0C 0C 0C FF 10 10 10 FF 18 18' + '18 FF 17 17 17 FF 00 00 00 FF EC EC EC FF E7 E7' + 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' + '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' + '90 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' + 'AB FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' + 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2' + 'C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF' + 'BF FF BF BF BF FF BC BC BC FF BD BD BD FF BA BA' + 'BA FF BD BD BD FF BD BD BD FF BD BD BD FF 00 00' + '00 FF 0C 0C 0C FF 10 10 10 FF 18 18 18 FF 18 18' + '18 FF 1E 1E 1E FF 00 00 00 FF EB EB EB FF DB DB' + 'DB FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' + 'E1 FF E1 E1 E1 FF E1 E1 E1 FF E2 E2 E2 FF E3 E3' + 'E3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF 00 00' + '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF AD A8' + 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF D4 D4 D4 FF 00 C0 00 FF 00 C0 00 FF E7 E7' + 'E7 FF E8 E8 E8 FF E8 E8 E8 FF E3 E3 E3 FF DD DD' + 'DD FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' + 'C9 FF CD CD CD FF AA AA AA FF 2E 2E 2E FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 18 18 18 FF 1F 1F' + '1F FF 18 18 18 FF 00 00 00 FF EA EA EA FF E6 E6' + 'E6 FF E7 E7 E7 FF E8 E8 E8 FF E8 E8 E8 FF E9 E9' + 'E9 FF EA EA EA FF EA EA EA FF EA EA EA FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF 00 00' + '00 15 00 00 00 F0 19 19 19 FF AD A8 AB FF EB EB' + 'EB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 C0' + '00 FF E1 E1 E1 FF DF DF DF FF D5 D5 D5 FF CC CC' + 'CC FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF 40 40 40 FF 2E 2E 2E FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 1F 1F 1F FF 15 15' + '15 FF 13 13 13 FF 00 00 00 FF E9 E9 E9 FF E7 E7' + 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' + '00 30 00 00 00 FA 29 29 29 FF AD A8 AB FF EA EA' + 'EA FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF' + '00 FF CB CB CB FF C8 C8 C8 FF 66 66 66 FF 66 66' + '66 FF 66 66 66 FF 66 66 66 FF 66 66 66 FF 66 66' + '66 FF 66 66 66 FF 66 66 66 FF 66 66 66 FF 66 66' + '66 FF CD CD CD FF 93 93 93 FF 40 40 40 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 0E 0E' + '0E FF 10 10 10 FF 00 00 00 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' + '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' + 'EC FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF B5 B5' + 'B5 FF B5 B5 B5 FF B6 B6 B6 FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 0A 0A' + '0A FF 0D 0D 0D FF 00 00 00 FF E8 E8 E8 FF E7 E7' + 'E7 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5 E5 FF E6 E6' + 'E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF 00 00' + '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' + 'EE FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 24 24 24 FF 1F 1F 1F FF 05 05 05 FF 07 07' + '07 FF 0A 0A 0A FF 00 00 00 FF E5 E5 E5 FF E7 E7' + 'E7 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 00 00' + '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' + 'EF FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF 80 80 80 FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 00 00' + '00 FF 2B 2B 2B FF 11 11 11 FF 02 02 02 FF 03 03' + '03 FF 03 03 03 FF 00 00 00 FF DC DC DC FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' + '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' + 'F2 FF EA EA EA FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' + 'AE FF B0 B0 B0 FF AF AF AF FF AF AF AF FF AF AF' + 'AF FF AF AF AF FF AF AF AF FF AF AF AF FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF 00 00' + '00 FF 32 32 32 FF 0C 0C 0C FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF E5 E5 E5 FF E5 E5' + 'E5 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8' + 'E8 FF E9 E9 E9 FF E9 E9 E9 FF E9 E9 E9 FF EA EA' + 'EA FF EA EA EA FF EA EA EA FF EB EB EB FF 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' + 'F3 FF EB EB EB FF ED ED ED FF EB EB EB FF E9 E9' + 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' + 'E2 FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' + 'D9 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF 00 00' + '00 FF 37 37 37 FF 02 02 02 FF 03 03 03 FF 04 04' + '04 FF 04 04 04 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' + 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' + 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' + 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' + 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF 00 00' + '00 FF 37 37 37 FF 07 07 07 FF 09 09 09 FF 0B 0B' + '0B FF 0D 0D 0D FF 10 10 10 FF 13 13 13 FF 19 19' + '19 FF 1E 1E 1E FF 27 27 27 FF 34 34 34 FF 42 42' + '42 FF 46 46 46 FF 46 46 46 FF 46 46 46 FF 46 46' + '46 FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' + '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' + 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' + 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF 00 00' + '00 FF 3F 3F 3F FF 0D 0D 0D FF 11 11 11 FF 12 12' + '12 FF 16 16 16 FF 1B 1B 1B FF 21 21 21 FF 26 26' + '26 FF 30 30 30 FF 3C 3C 3C FF 44 44 44 FF 47 47' + '47 FF 46 46 46 FF 46 46 46 FF 46 46 46 FF 2C 2C' + '2C FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' + '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' + 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' + 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF 00 00' + '00 FF 44 44 44 FF 23 23 23 FF 17 17 17 FF 1B 1B' + '1B FF 20 20 20 FF 27 27 27 FF 2B 2B 2B FF 35 35' + '35 FF 40 40 40 FF 44 44 44 FF 47 47 47 FF 4A 4A' + '4A FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' + '2C FF 2C 2C 2C FF 2C 2C 2C FF 2C 2C 2C FF 00 00' + '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' + 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' + 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF 00 00' + '00 FF 4B 4B 4B FF 2E 2E 2E FF 1F 1F 1F FF 25 25' + '25 FF 2B 2B 2B FF 2F 2F 2F FF 39 39 39 FF 43 43' + '43 FF 44 44 44 FF 47 47 47 FF 4B 4B 4B FF 49 49' + '49 FF 42 42 42 FF 36 36 36 FF 2C 2C 2C FF 23 23' + '23 FF 1C 1C 1C FF 1C 1C 1C FF 14 14 14 FF 00 00' + '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' + 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' + 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' + 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF 00 00' + '00 FF 4B 4B 4B FF 4C 4C 4C FF 27 27 27 FF 2E 2E' + '2E FF 33 33 33 FF 3C 3C 3C FF 45 45 45 FF 44 44' + '44 FF 47 47 47 FF 4B 4B 4B FF 4B 4B 4B FF 45 45' + '45 FF 3C 3C 3C FF 32 32 32 FF 2A 2A 2A FF 25 25' + '25 FF 1C 1C 1C FF 1C 1C 1C FF 16 16 16 FF 00 00' + '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' + 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' + 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' + 'D0 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0 D0 FF 00 00' + '00 FF 52 52 52 FF 57 57 57 FF 3C 3C 3C FF 35 35' + '35 FF 3F 3F 3F FF 00 00 00 FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 00 00' + '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' + 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' + 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF E1 E1 E1 FF 00 00' + '00 FF 57 57 57 FF 5E 5E 5E FF 5D 5D 5D FF 49 49' + '49 FF 45 45 45 FF 00 00 00 FF 84 84 84 FF FD F9' + 'F7 FF F9 EE E8 FF F6 E4 D9 FF F3 D9 CB FF F0 CF' + 'BC FF ED C5 AE FF EA BB A0 FF E9 B6 99 FF E9 B6' + '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' + 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CA CA CA FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF 00 00' + '00 FF 5E 5E 5E FF 5E 5E 5E FF 65 65 65 FF 6A 6A' + '6A FF 44 44 44 FF 00 00 00 FF 8E 8E 8E FF FF FF' + 'FF FF D0 CB C8 FF 8B 86 84 FF 87 80 7D FF 83 7A' + '75 FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' + '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' + 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' + 'CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3' + 'D3 FF D2 D2 D2 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2' + 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF 00 00' + '00 FF 5E 5E 5E FF 5E 5E 5E FF 65 65 65 FF 6A 6A' + '6A FF 44 44 44 FF 00 00 00 FF 8E 8E 8E FF FF FF' + 'FF FF D0 CB C8 FF 8B 86 84 FF 87 80 7D FF 83 7A' + '75 FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' + '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' + 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' + 'CE FF D3 D3 D3 FF D3 D3 D3 FF CF CF CF FF D1 D1' + 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF D3 D3 D3 FF D3 D3 D3 FF CE CE' + 'CE FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CE CE CE FF 00 00' + '00 FF 5E 5E 5E FF 65 65 65 FF 6A 6A 6A FF 6A 6A' + '6A FF 71 71 71 FF 00 00 00 FF 97 97 97 FF FF FF' + 'FF FF B8 B6 B6 FF 54 54 54 FF 4F 4F 4F FF 5B 58' + '57 FF F0 D0 BE FF ED C6 AF FF EA BC A1 FF E9 B6' + '99 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' + '9F FF DD DD DD FF CC CC CC FF CD CD CD FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' + '00 FF 65 65 65 FF 6A 6A 6A FF 6A 6A 6A FF 71 71' + '71 FF 79 79 79 FF 00 00 00 FF 9E 9E 9E FF FF FF' + 'FF FF AF AF AF FF 52 52 52 FF 4E 4E 4E FF 6D 6A' + '67 FF F2 D6 C7 FF EF CC B8 FF EC C2 AA FF E9 B8' + '9C FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' + '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF D3 D3' + 'D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' + '00 FF 65 65 65 FF 6A 6A 6A FF 71 71 71 FF 7E 7E' + '7E FF 79 79 79 FF 00 00 00 FF AA AA AA FF FF FF' + 'FF FF A6 A6 A6 FF 50 50 50 FF 4C 4C 4C FF 7B 77' + '75 FF F4 DD D0 FF F1 D2 C2 FF EE C8 B3 FF EB BE' + 'A5 FF E9 B6 99 FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' + '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D3 D3' + 'D3 FF D3 D3 D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' + '00 FF 65 65 65 FF 71 71 71 FF 79 79 79 FF 7E 7E' + '7E FF 7E 7E 7E FF 00 00 00 FF B1 B1 B1 FF FF FF' + 'FF FF E0 E0 E0 FF DF DF DF FF DC D9 D7 FF D9 D1' + 'CC FF F6 E4 D9 FF F3 D9 CB FF F0 CF BC FF ED C5' + 'AE FF EA BB A0 FF EA BB A0 FF E9 B6 99 FF 00 00' + '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' + '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF A3 A3 9E FF DA DA' + 'D8 FF DA DA D8 FF DA DA D8 FF DA DA D8 FF D7 D2' + 'CE FF D5 CB C4 FF D2 C3 B9 FF D0 BC B0 FF CE B6' + 'A6 FF CC AF 9D FF CC AF 9D FF CA A8 94 FF 00 00' + '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' + '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' + 'D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF CC CC CC FF C9 C9 C9 FF C6 C6' + 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' + 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' + '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' + '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF D9 D9 D9 FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DA DA DA FF DD DD' + 'DD FF DD DD DD FF E7 E7 E7 FF D9 D9 D9 FF CC CC' + 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' + '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' + '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' + 'DC FF DE DE DE FF DE DE DE FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF DD DD DD FF DC DC' + 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' + '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' + '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' + 'E1 FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E3 E3 E3 FF D9 D9' + 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' + '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' + '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' + 'E3 FF E4 E4 E4 FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' + 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' + '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' + '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' + 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' + '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' + 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' + 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EA EA' + 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' + 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' + 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' + 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' + 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' + 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' + 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' + 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' + 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' + 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' + 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' + 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' + 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' + 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' + 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' + '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' + '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' + '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' + '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' + '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 FF FF FF F0 00 00 00 00 FF FF' + 'FF F0 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 C0 00 00 00 03 FF 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' + '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' + '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 24 00 00 00 6C 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 3C 3C 3C FF 3C 3C 3C FF 3C 3C 3C FF 3C 3C' + '3C FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' + '60 FF 7F 60 60 FF 7F 60 60 FF 7F 60 60 FF 7F 60' + '60 FF 7F 60 60 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' + '00 04 00 00 00 14 00 00 00 26 00 00 00 2D 00 00' + '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' + '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' + '00 2D 00 00 00 2D 00 00 00 2D 00 00 00 2D 00 00' + '00 2D 28 28 24 FF 00 00 00 8F 8C 8C 8C FF 0C 0C' + '0C FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' + '40 FF D5 40 40 FF D5 40 40 FF D5 40 40 FF D5 40' + '40 FF D5 40 40 FF 00 00 00 00 00 00 00 07 00 00' + '00 23 00 00 00 55 00 00 00 7E 00 00 00 8C 00 00' + '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' + '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' + '00 8C 00 00 00 8C 00 00 00 8C 00 00 00 8C 00 00' + '00 8C 2A 2A 25 FF 00 00 00 FF 00 00 00 FF 0C 0C' + '0C FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' + '80 FF EA 80 80 FF EA 80 80 FF EA 80 80 FF EA 80' + '80 FF EA 80 80 FF 00 00 00 00 00 00 00 1F 00 00' + '00 C2 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 04 04 04 FF 0C 0C 0C FF 10 10 10 FF 18 18' + '18 FF ED ED ED FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF 00 00 00 00 00 00 00 C0 00 00' + '00 FF 21 21 21 FF 2C 2C 2C FF 2C 2C 2C FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 0C 0C 0C FF 0C 0C 0C FF 18 18 18 FF 17 17' + '17 FF EC EC EC FF E7 E7 E7 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 00 00 00 06 01 01 01 FF 8A 8A' + '8A FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF D4 D4' + 'D4 FF 00 C0 00 FF E7 E7 E7 FF E8 E8 E8 FF E3 E3' + 'E3 FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF C8 C9 C9 FF AA AA AA FF 2E 2E' + '2E FF 00 00 00 FF 00 00 00 FF 1F 1F 1F FF 18 18' + '18 FF EA EA EA FF E6 E6 E6 FF E8 E8 E8 FF E8 E8' + 'E8 FF EA EA EA FF EA EA EA FF EB EB EB FF EB EB' + 'EB FF EC EC EC FF 00 00 00 1B 19 19 19 FF AD A8' + 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF 00 FF' + '00 FF 00 FF 00 FF 00 C0 00 FF DF DF DF FF D5 D5' + 'D5 FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF 40 40 40 FF 2E 2E' + '2E FF 00 00 00 FF 00 00 00 FF 15 15 15 FF 13 13' + '13 FF E9 E9 E9 FF E7 E7 E7 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 00 00 00 3A 28 28 28 FF D1 D1' + 'D1 FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 FF 00 FF B5 B5 B5 FF B6 B6 B6 FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF B6 B6 B6 FF B6 B6' + 'B6 FF 00 00 00 FF 00 00 00 FF 0A 0A 0A FF 0D 0D' + '0D FF E8 E8 E8 FF E7 E7 E7 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF 00 00 00 39 28 28 28 FF D1 D1' + 'D1 FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 24 24 24 FF 1F 1F 1F FF 07 07 07 FF 0A 0A' + '0A FF E5 E5 E5 FF E7 E7 E7 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 99 99 99 FF 99 99 99 FF 99 99' + '99 FF 99 99 99 FF 00 00 00 39 27 27 27 FF D2 D2' + 'D2 FF EA EA EA FF EB EB EB FF EB EB EB FF A7 A7' + 'A7 FF AB AB AB FF AE AE AE FF AF AF AF FF AF AF' + 'AF FF AF AF AF FF AF AF AF FF AB AB AB FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' + 'AB FF 32 32 32 FF 0C 0C 0C FF 00 00 00 FF 00 00' + '00 FF E5 E5 E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7' + 'E7 FF E9 E9 E9 FF E9 E9 E9 FF EA EA EA FF EA EA' + 'EA FF EB EB EB FF 00 00 00 39 26 26 26 FF D3 D3' + 'D3 FF EB EB EB FF ED ED ED FF E9 E9 E9 FF E8 E8' + 'E8 FF E4 E4 E4 FF E2 E2 E2 FF DC DC DC FF D8 D8' + 'D8 FF D2 D2 D2 FF D2 D2 D2 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF 37 37 37 FF 02 02 02 FF 04 04 04 FF 04 04' + '04 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 37 24 24 24 FF D6 D6' + 'D6 FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' + 'E0 FF DF DF DF FF DF DF DF FF DF DF DF FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF 3F 3F 3F FF 0D 0D 0D FF 12 12 12 FF 16 16' + '16 FF 21 21 21 FF 26 26 26 FF 3C 3C 3C FF 44 44' + '44 FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' + '2C FF 2C 2C 2C FF 00 00 00 34 24 24 24 FF DE DE' + 'DE FF D9 D9 D9 FF C4 C4 C4 FF BF BF BF FF D8 D8' + 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF 44 44 44 FF 23 23 23 FF 1B 1B 1B FF 20 20' + '20 FF 2B 2B 2B FF 35 35 35 FF 44 44 44 FF 47 47' + '47 FF 46 46 46 FF 46 46 46 FF 2C 2C 2C FF 2C 2C' + '2C FF 2C 2C 2C FF 00 00 00 07 05 05 05 FF C2 C2' + 'C2 FF BC BC BC FF B2 B2 B2 FF AB AB AB FF BB BB' + 'BB FF D5 D5 D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3' + 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D7 D7' + 'D7 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5' + 'D5 FF 4B 4B 4B FF 4C 4C 4C FF 2E 2E 2E FF 33 33' + '33 FF 45 45 45 FF 44 44 44 FF 4B 4B 4B FF 4B 4B' + '4B FF 3C 3C 3C FF 32 32 32 FF 25 25 25 FF 1C 1C' + '1C FF 16 16 16 FF 00 00 00 00 00 00 00 FF A4 A4' + 'A4 FF CF CF CF FF C5 C5 C5 FF BF BF BF FF C9 C9' + 'C9 FF D2 D2 D2 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0' + 'D0 FF 52 52 52 FF 57 57 57 FF 35 35 35 FF 3F 3F' + '3F FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C 8C FF 8C 8C' + '8C FF 8C 8C 8C FF 00 00 00 00 00 00 00 FF 59 59' + '59 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CA CA' + 'CA FF D3 D3 D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5' + 'D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D5 D5 D5 FF DB DB DB FF E4 E4' + 'E4 FF 5E 5E 5E FF 5E 5E 5E FF 6A 6A 6A FF 44 44' + '44 FF 8E 8E 8E FF FF FF FF FF 8B 86 84 FF 87 80' + '7D FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' + '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 FF 40 40' + '40 FF D2 D2 D2 FF CA CA CA FF CA CA CA FF D4 D4' + 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3 D3 FF D2 D2' + 'D2 FF D3 D3 D3 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0' + 'D0 FF 5E 5E 5E FF 5E 5E 5E FF 6A 6A 6A FF 44 44' + '44 FF 8E 8E 8E FF FF FF FF FF 8B 86 84 FF 87 80' + '7D FF D0 B3 A3 FF EC C0 A7 FF E9 B6 99 FF E9 B6' + '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 F4 07 07' + '07 FF DD DD DD FF CC CC CC FF D3 D3 D3 FF D3 D3' + 'D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 65 65 65 FF 6A 6A 6A FF 71 71 71 FF 79 79' + '79 FF 9E 9E 9E FF FF FF FF FF 52 52 52 FF 4E 4E' + '4E FF F2 D6 C7 FF EF CC B8 FF E9 B8 9C FF E9 B6' + '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 BA 00 00' + '00 FF DD DD DD FF CF CF CF FF D3 D3 D3 FF D3 D3' + 'D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 3C 3C 3C FF 6A 6A 6A FF 71 71 71 FF 79 79' + '79 FF AA AA AA FF FF FF FF FF 50 50 50 FF 4C 4C' + '4C FF F4 DD D0 FF F1 D2 C2 FF EB BE A5 FF E9 B6' + '99 FF E9 B6 99 FF 00 00 00 00 00 00 00 4D 00 00' + '00 FF D8 D8 D8 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF A3 A3 9E FF DA DA D8 FF DA DA D8 FF DA DA' + 'D8 FF D5 CB C4 FF D2 C3 B9 FF CE B6 A6 FF CC AF' + '9D FF CA A8 94 FF 00 00 00 00 00 00 00 1A 00 00' + '00 FF CC CC CC FF D6 D6 D6 FF D3 D3 D3 FF D3 D3' + 'D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CC CC CC FF C9 C9' + 'C9 FF C4 C4 C4 FF C2 C2 C2 FF BD BD BD FF D0 D0' + 'D0 FF 09 09 09 FF 00 00 00 FF 00 00 00 6C 00 00' + '00 1D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00' + '00 D2 97 97 97 FF DC DC DC FF DC DC DC FF DE DE' + 'DE FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF E7 E7 E7 FF E7 E7 E7 FF DC DC DC FF C6 C6' + 'C6 FF 00 00 00 FF 00 00 00 FF 00 00 00 59 00 00' + '00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 AF 77 77 77 FF D3 D3 D3 FF E1 E1 E1 FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1' + 'E1 FF E7 E7 E7 FF E7 E7 E7 FF D9 D9 D9 FF BB BB' + 'BB FF 00 00 00 FF 00 00 00 FF 00 00 00 40 00 00' + '00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 66 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E6 E6 E6 FF D4 D4 D4 FF 9A 9A' + '9A FF 00 00 00 FF 00 00 00 A4 00 00 00 2B 00 00' + '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 2D 1E 1E 1E FF AB AB AB FF ED ED ED FF E7 E7' + 'E7 FF EC EC EC FF EB EB EB FF ED ED ED FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EC EC' + 'EC FF E5 E5 E5 FF EB EB EB FF D6 D6 D6 FF 8A 8A' + '8A FF 00 00 00 FF 00 00 00 7B 00 00 00 1B 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 8D 8D 8D FF C4 C4 C4 FF B2 B2' + 'B2 FF B2 B2 B2 FF EB EB EB FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5' + 'D5 FF B6 B6 B6 FF B7 B7 B7 FF CD CD CD FF 61 61' + '61 FF 00 00 00 FF 00 00 00 50 00 00 00 0F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 64 64 64 FF DD DD DD FF DC DC' + 'DC FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA FA FF F2 F2' + 'F2 FF D8 D8 D8 FF DC DC DC FF B0 B0 B0 FF 34 34' + '34 FF 00 00 00 E5 00 00 00 31 00 00 00 04 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9C 00 00 00 FF 3D 3D 3D FF 49 49' + '49 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 49 49 49 FF 49 49 49 FF 02 02 02 FF 00 00' + '00 FF 00 00 00 49 00 00 00 14 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 00 00 00 7F 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FA 00 00' + '00 7C 00 00 00 12 00 00 00 04 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF E0 00 FF FF E0 00 FF FF' + 'E0 00 C0 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 1F 80 00 00 1F C0 00 00 1F C0 00 00 1F C0 00' + '00 1F E0 00 00 3F E0 00 00 3F E0 00 00 7F E0 00' + '00 7F FF FF FF FF 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 00 00 00 FF 00 00 00 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 36 36 30 FF 00 00 00 FF C0 00' + '00 FF C0 00 00 FF C0 00 00 FF C0 00 00 FF 00 00' + '00 00 00 00 00 16 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 FF 30 30 2C FF 00 00 00 FF FF C0' + 'C0 FF FF C0 C0 FF FF C0 C0 FF FF C0 C0 FF 00 00' + '00 54 90 90 90 FF AB AC AC FF CC CC CC FF C4 C4' + 'C4 FF C2 C2 C2 FF C1 C1 C1 FF BC BC BC FF BD BD' + 'BD FF 00 00 00 FF 18 18 18 FF 00 00 00 FF E0 E0' + 'E0 FF E1 E1 E1 FF E2 E2 E2 FF E3 E3 E3 FF 00 00' + '00 FA EA EA EA FF E8 E8 E8 FF 00 FF 00 FF CB CB' + 'CB FF 66 66 66 FF 66 66 66 FF 66 66 66 FF CD CD' + 'CD FF 00 00 00 FF 00 00 00 FF 00 00 00 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' + '00 F9 EF EF EF FF EB EB EB FF 3B 3B 3B FF 3B 3B' + '3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B 3B FF 3B 3B' + '3B FF 00 00 00 FF 02 02 02 FF 00 00 00 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF 00 00' + '00 F9 F7 F7 F7 FF F6 F6 F6 FF F5 F5 F5 FF F3 F3' + 'F3 FF F2 F2 F2 FF F1 F1 F1 FF F0 F0 F0 FF EF EF' + 'EF FF 00 00 00 FF 09 09 09 FF 10 10 10 FF 1E 1E' + '1E FF 42 42 42 FF 46 46 46 FF 2C 2C 2C FF 00 00' + '00 F7 F3 F3 F3 FF B7 B7 B7 FF DA DA DA FF D8 D8' + 'D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' + 'D8 FF 00 00 00 FF 1F 1F 1F FF 2F 2F 2F FF 44 44' + '44 FF 49 49 49 FF 2C 2C 2C FF 1C 1C 1C FF 00 00' + '00 73 EF EF EF FF CB CB CB FF CE CE CE FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF 00 00 00 FF 5D 5D 5D FF 00 00 00 FF F9 EE' + 'E8 FF F0 CF BC FF E9 B6 99 FF E9 B6 99 FF 00 00' + '00 25 B7 B7 B7 FF CB CB CB FF D3 D3 D3 FF D0 D0' + 'D0 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 00 00 00 FF 6A 6A 6A FF 00 00 00 FF B8 B6' + 'B6 FF 5B 58 57 FF EA BC A1 FF E9 B6 99 FF 00 00' + '00 00 5F 5F 5F FF D2 D2 D2 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 00 00 00 FF 79 79 79 FF 00 00 00 FF E0 E0' + 'E0 FF D9 D1 CC FF F0 CF BC FF EA BB A0 FF 00 00' + '00 00 18 18 18 FF DB DB DB FF DE DE DE FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF D9 D9 D9 FF 7A 7A 7A FF 00 00' + '00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF E5 E5 E5 FF EB EB EB FF EB EB' + 'EB FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E7 E7 E7 FF E6 E6 E6 FF 20 20 20 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 DD E4 E4 E4 FF C1 C1 C1 FF ED ED' + 'ED FF EE EE EE FF EB EB EB FF ED ED ED FF ED ED' + 'ED FF C2 C2 C2 FF EC EC EC FF 00 00 00 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 44 80 80 80 FF D7 D7 D7 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D9 D9 D9 FF B0 B0 B0 FF 00 00 00 ED 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2C 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 70 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 80' + '00 00 FF 80 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 80 07 00 00 80 0F' + '00 00 80 0F 00 00 80 0F 00 00 C0 1F 00 00' +} */ + + +/* BINRES drive.ico */ +8 ICON drive.ico +/* { + '00 00 01 00 08 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 86 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 2E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 96 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 7E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 A6 12 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 4E 21 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 F6 46 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 9E 57 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 00 00 00 00 11 00 00 11 11 11 00 22 22' + '22 00 33 33 33 00 44 44 44 00 55 55 55 00 66 66' + '66 00 77 77 77 00 7F 7F 7F 00 00 CC 66 00 66 99' + '99 00 33 CC 99 00 66 CC 99 00 88 88 88 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 99 CC 99 00 CC CC' + 'CC 00 DD DD DD 00 EE EE EE 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 54 00 56 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' + '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 50 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 64 72 69 76 65 2E 69 63 6F' + '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 18 18 18 18 18 18 18 18 18 18 18 18 18 18' + '18 18 18 18 18 02 18 18 18 18 00 00 00 00 00 00' + '00 18 18 03 03 04 03 04 03 03 04 03 03 04 03 03' + '04 03 03 04 03 03 03 04 01 18 18 00 00 00 00 00' + '18 18 06 12 14 12 12 12 12 11 12 12 12 12 12 12' + '12 12 12 12 12 11 0F 10 0C 04 18 18 00 00 00 00' + '18 18 12 16 16 11 07 08 0F 10 11 12 12 11 12 12' + '12 12 12 12 12 12 0D 0B 10 0F 18 18 00 00 00 00' + '18 03 14 16 16 11 06 0F 0F 10 11 11 11 11 10 10' + '11 11 10 11 11 12 13 0E 12 0F 18 18 00 00 00 00' + '18 03 14 16 16 12 09 09 0F 10 10 11 12 0F 0F 10' + '0F 10 0F 10 11 14 12 12 14 10 18 18 00 00 00 00' + '18 03 15 16 16 12 08 0F 0F 10 11 11 12 10 09 0F' + '10 0F 0F 0F 11 14 14 12 14 0F 18 18 00 00 00 00' + '18 03 14 17 15 16 15 15 15 15 15 14 15 14 15 14' + '14 14 14 14 14 14 14 12 14 0F 18 18 00 00 00 00' + '18 03 14 17 17 16 17 17 16 17 16 17 16 17 16 17' + '16 17 16 17 16 16 16 17 15 10 18 18 00 00 00 00' + '18 03 15 16 15 15 15 15 15 15 15 15 15 15 15 15' + '15 15 15 15 15 15 15 15 17 10 18 18 00 00 00 00' + '18 03 15 15 11 11 14 15 15 14 15 15 14 15 14 15' + '14 15 14 15 14 12 11 12 16 10 18 18 00 00 00 00' + '18 18 11 15 12 12 12 14 14 15 15 15 15 16 15 16' + '15 15 15 14 15 11 12 12 16 09 18 18 00 00 00 00' + '18 18 0F 16 14 14 14 15 15 15 16 15 15 15 15 15' + '15 16 15 15 14 15 14 14 16 07 18 18 00 00 00 00' + '00 18 08 16 14 14 14 15 15 15 14 15 15 14 15 14' + '15 14 15 15 16 14 14 14 15 05 18 00 00 00 00 00' + '00 18 05 15 14 14 15 15 14 14 14 14 14 14 14 14' + '14 14 14 14 14 15 14 14 14 03 18 00 00 00 00 00' + '00 18 04 14 14 14 15 14 14 14 15 14 14 14 14 14' + '12 14 14 14 14 14 14 14 11 18 18 00 00 00 00 00' + '00 18 18 12 15 14 15 14 15 14 14 14 15 14 14 12' + '14 12 12 14 14 14 12 15 0F 18 18 00 00 00 00 00' + '00 18 18 10 15 14 14 15 14 15 14 15 14 14 15 15' + '14 12 14 12 12 12 12 14 08 18 18 00 00 00 00 00' + '00 18 18 09 15 15 14 15 14 15 15 15 15 15 14 15' + '15 15 15 15 15 12 14 14 06 18 18 00 00 00 00 00' + '00 00 18 06 15 15 15 14 16 15 15 15 15 15 15 15' + '15 15 15 15 14 15 15 14 05 18 00 00 00 00 00 00' + '00 00 18 05 14 16 15 15 14 15 15 16 15 16 16 15' + '16 15 15 15 15 15 15 11 03 18 00 00 00 00 00 00' + '00 00 18 04 11 15 16 16 16 15 15 15 15 15 15 15' + '15 15 15 15 16 16 15 10 18 18 00 00 00 00 00 00' + '00 00 18 18 11 16 14 14 15 16 16 15 16 15 15 16' + '15 16 16 15 12 15 15 09 18 18 00 00 00 00 00 00' + '00 00 18 18 0F 15 14 12 16 17 17 17 17 17 17 17' + '17 17 17 15 14 14 15 07 18 18 00 00 00 00 00 00' + '00 00 00 18 04 10 15 15 15 15 15 15 15 15 15 15' + '15 15 15 15 15 14 09 03 18 00 00 00 00 00 00 00' + '00 00 00 18 18 03 04 04 04 04 04 04 04 04 04 04' + '04 04 04 04 04 04 18 18 18 00 00 00 00 00 00 00' + '00 00 00 00 18 18 18 18 18 18 18 18 18 18 18 18' + '18 18 18 18 18 18 18 18 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' + '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' + '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 11 00 11 11' + '11 00 22 00 00 00 22 22 22 00 44 44 44 00 55 55' + '55 00 66 66 66 00 77 77 77 00 7F 7F 7F 00 33 CC' + '99 00 88 88 88 00 99 99 99 00 AA AA AA 00 BB BB' + 'BB 00 99 CC 99 00 CC CC CC 00 DD DD DD 00 EE EE' + 'EE 00 00 00 00 00 CC CC CC 00 DD DD DD 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 13 00 00 00 18 0A' + '38 00 00 00 38 00 18 6C 38 00 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 86 00' + '00 00 86 00 00 00 08 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 54 00' + '56 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 54 00 00 00 00 00 00 00 03 00' + '00 00 5C 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 50 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' + '72 69 76 65 2E 69 63 6F 00 00 1A 93 4B 00 14 1A' + '95 00 1F 3B D4 77 13 00 00 00 98 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 18 6C 38 00 86 00 00 00 00 00' + '00 00 C9 F1 E7 77 86 00 00 00 A4 1A 95 00 08 00' + '00 00 00 00 00 00 86 00 00 00 86 00 00 00 08 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 18 6C 38 00 86 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 13 13 02 02 02 02 02 02 02' + '02 02 03 01 13 00 00 13 0C 0E 0B 0C 0D 0E 0D 0E' + '0E 0D 0A 07 13 00 00 02 11 10 07 0B 0D 0D 0C 0C' + '0C 0E 0F 0C 13 00 00 02 11 11 0C 0D 0E 0E 0C 0D' + '0C 0E 10 0D 13 00 00 02 11 12 12 12 11 11 12 11' + '11 11 11 0E 13 00 00 13 10 0E 10 10 11 11 11 11' + '11 10 10 0E 13 00 00 13 0D 10 10 11 11 11 11 11' + '11 10 11 0B 13 00 00 13 0B 11 11 11 10 10 10 11' + '10 10 11 07 13 00 00 13 07 11 10 10 11 10 10 0E' + '10 10 10 06 13 00 00 13 05 10 11 11 10 11 11 10' + '11 10 10 04 13 00 00 13 04 11 11 11 11 11 11 11' + '11 11 0E 02 13 00 00 00 13 0E 11 12 12 12 12 12' + '11 12 0D 13 00 00 00 00 13 08 10 11 11 12 11 12' + '10 10 07 13 00 00 00 00 13 13 04 02 04 02 04 02' + '04 02 13 13 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 80 00 00 00 00 80 82 00 00 00 00 00' + '87 77 77 77 77 77 77 77 77 87 88 88 00 00 00 00' + '7F F7 88 87 87 77 77 77 77 77 2E 88 00 00 00 00' + '7F F8 88 88 78 78 77 88 77 77 77 78 00 00 00 00' + 'F7 F7 88 78 77 77 88 87 88 77 77 78 00 00 00 08' + '7F 77 88 88 87 78 88 78 88 77 77 77 00 00 00 00' + '7F FF 77 77 F7 77 77 77 77 77 77 78 00 00 00 00' + '7F FF FF FF FF FF FF FF FF 7F FF F8 00 00 00 04' + '7F 77 F7 FF 7F 7F 77 F7 F7 FF 77 F8 00 00 00 00' + 'F7 77 7F 77 7F 77 F7 F7 7F 77 77 77 00 00 00 00' + '77 77 77 77 F7 FF 7F 77 F7 77 77 F8 00 00 00 00' + '8F 77 77 FF 7F 77 F7 FF 7F 77 77 F8 00 00 00 00' + '8F 77 7F F7 F7 7F 7F 77 F7 7F 7F 78 00 00 00 00' + '8F 77 F7 77 7F 77 77 F7 7F 77 77 70 00 00 00 00' + '87 7F 77 7F 77 F7 7F 77 77 7F 77 70 00 00 00 00' + '07 77 F7 77 F7 77 77 77 77 77 7F 80 00 00 00 00' + '08 7F 77 F7 77 7F 77 77 77 77 77 80 00 00 00 00' + '08 F7 7F 7F 7F 77 F7 F7 F7 77 77 80 00 00 00 00' + '08 7F 77 F7 F7 FF 7F 7F 7F 77 F7 80 00 00 00 00' + '04 7F 7F 7F 7F 7F F7 F7 F7 F7 77 00 00 00 00 00' + '08 8F FF 77 F7 F7 7F 7F 7F 7F F8 00 00 00 00 00' + '00 77 77 FF 7F 7F F7 F7 FF 77 F8 00 00 00 00 00' + '00 8F 77 FF FF FF FF FF F7 7F 78 00 00 00 00 00' + '00 48 7F 77 F7 F7 7F 7F 77 F7 80 00 00 00 00 00' + '00 00 80 48 08 04 80 80 48 04 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' + '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' + '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '80 00 00 02 00 00 00 87 88 77 77 77 68 00 00 F7' + '88 87 87 87 78 00 08 77 87 77 87 87 77 00 00 FF' + 'F7 FF 7F 7F 77 00 00 77 77 F7 F7 F7 77 00 00 77' + '7F 77 F7 7F 78 00 00 87 F7 7F 77 F7 F8 00 00 8F' + '77 F7 77 77 78 00 00 87 7F 77 7F 77 78 00 00 47' + 'F7 F7 F7 F7 70 00 00 07 F7 FF 7F 7F 70 00 00 08' + '7F 7F F7 F7 80 00 00 00 04 08 00 40 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 11 00 11 11 11 00 22 22 22 00 33 33' + '33 00 44 44 44 00 55 55 55 00 66 66 66 00 77 77' + '77 00 7F 7F 7F 00 00 99 66 00 33 99 66 00 00 CC' + '66 00 33 CC 66 00 66 99 99 00 88 88 88 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 99 CC 99 00 99 FF' + '99 00 99 CC CC 00 CC CC CC 00 DD DD DD 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 13 00 00 00 18 0A 38 00 00 00 38 00 18 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 86 00 00 00 86 00 00 00 08 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 54 00 56 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' + '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 50 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 64 72 69 76 65 2E 69 63 6F' + '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 13 00' + '00 00 98 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 18 6C' + '38 00 86 00 00 00 00 00 00 00 C9 F1 E7 77 86 00' + '00 00 A4 1A 95 00 08 00 00 00 00 00 00 00 86 00' + '00 00 86 00 00 00 08 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 18 6C' + '38 00 86 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 1A 1A 02 03 03 04 03 03 04 03 03' + '04 03 03 04 03 03 03 04 03 03 03 03 04 03 03 04' + '03 03 03 04 01 1A 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 03 10 16 16 16 16 16 16 16 16 16' + '12 16 12 12 16 12 12 12 16 12 12 12 12 12 12 11' + '12 12 11 11 11 07 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 1A 1A 1A 0F 17 18 18 17 0F 0F 10 10 10 11' + '12 16 12 16 16 16 16 17 16 16 16 17 16 16 16 16' + '16 11 0B 0B 13 12 06 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 02 16 18 17 17 16 04 05 06 08 0F 0F' + '11 10 11 11 12 11 10 12 10 12 10 16 10 12 10 16' + '12 0D 0C 0A 0B 16 08 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 16 18 17 18 17 05 06 08 0F 10 10' + '10 11 11 12 12 10 10 12 0F 12 10 12 10 12 0F 12' + '16 10 15 14 0E 16 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 04 17 18 18 17 16 07 08 08 0F 0F 10' + '10 11 11 11 12 11 08 12 08 11 0F 12 0F 12 08 16' + '16 12 11 10 16 12 10 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 16 18 17 18 17 07 08 08 0F 0F 10' + '11 11 11 11 12 10 08 11 07 10 08 11 0F 11 07 12' + '12 16 12 16 12 16 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 17 18 18 17 17 07 07 08 0F 0F 0F' + '10 11 10 11 12 0F 07 11 06 10 07 12 07 11 06 16' + '16 12 16 12 12 16 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 16 18 18 18 17 11 11 11 11 11 12' + '11 12 12 12 12 12 11 12 11 12 12 12 11 12 11 12' + '16 12 16 12 16 12 10 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 17 18 18 18 18 17 18 18 18 17 17' + '18 17 17 17 17 17 17 17 17 17 16 17 16 16 16 16' + '16 16 12 16 12 16 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 16 18 19 19 18 19 19 18 18 18 19' + '18 19 18 19 18 18 18 18 18 18 18 18 18 18 18 18' + '18 18 18 18 17 17 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 17 19 17 17 18 17 17 18 17 17 17' + '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' + '18 17 18 17 19 18 0F 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 17 19 17 16 12 12 17 16 17 17 16' + '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' + '16 12 12 16 17 19 10 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 03 17 18 16 11 11 11 16 17 17 16 17' + '17 16 17 16 17 17 16 17 16 17 16 17 16 17 17 16' + '11 12 11 12 16 19 10 1A 1A 1A 00 00 00 00 00 00' + '00 00 1A 1A 1A 12 19 12 11 16 11 12 17 16 17 17' + '16 17 16 17 16 16 17 16 17 16 17 16 17 17 16 16' + '11 12 12 11 17 19 08 1A 1A 1A 00 00 00 00 00 00' + '00 00 00 1A 1A 11 18 16 16 16 16 16 16 17 16 16' + '17 17 17 18 18 18 18 18 17 18 17 17 16 16 17 16' + '16 16 12 16 16 18 06 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 08 18 17 16 16 16 16 16 16 17 18' + '18 17 17 17 17 17 17 17 17 17 17 18 18 18 16 16' + '16 16 16 16 17 17 04 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 06 18 16 16 16 16 16 17 18 18 17' + '16 17 17 17 16 17 17 16 17 17 16 17 17 17 18 17' + '16 16 16 16 17 12 03 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 05 17 16 16 16 16 16 18 17 16 16' + '16 17 16 16 16 17 16 16 17 16 16 17 16 16 17 18' + '16 16 16 16 17 11 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 03 12 17 16 16 16 18 16 16 17 16' + '17 16 17 16 16 16 16 16 16 16 16 16 16 16 16 16' + '18 16 16 16 17 0F 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 00 1A 1A 1A 10 17 16 16 17 16 17 16 16 16' + '16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16' + '16 17 12 16 17 06 1A 1A 1A 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 0F 17 17 16 17 16 16 17 16 17' + '16 17 16 16 16 16 16 16 12 16 12 16 16 16 12 16' + '16 16 16 16 17 05 1A 1A 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 06 17 16 16 16 17 16 16 16 16' + '16 16 16 16 17 16 16 12 16 12 16 12 16 12 16 12' + '16 12 16 16 17 03 1A 1A 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 05 17 16 17 16 16 17 16 17 16' + '17 16 17 16 16 17 16 16 16 12 16 12 12 12 16 12' + '12 16 12 16 11 03 1A 1A 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 03 16 17 16 16 17 16 17 16 17' + '16 17 16 16 17 16 16 17 16 17 16 16 16 16 12 16' + '16 11 12 16 11 1A 1A 1A 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 02 12 17 17 16 16 17 17 17 17' + '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 16' + '16 16 16 16 08 1A 1A 1A 00 00 00 00 00 00 00 00' + '00 00 00 00 1A 1A 1A 10 17 17 17 16 17 17 17 17' + '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' + '16 17 17 16 06 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 1A 08 17 17 18 17 16 17 17 17' + '17 17 18 17 17 18 17 17 17 17 17 17 18 17 17 16' + '17 17 17 12 04 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 1A 06 16 17 17 18 17 17 16 17' + '17 18 17 18 17 17 18 17 17 18 18 17 17 16 16 18' + '17 18 16 11 03 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 1A 04 12 18 17 17 18 17 17 16' + '17 17 17 17 18 17 17 18 17 17 17 17 16 17 18 17' + '18 17 17 10 1A 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 1A 02 11 18 18 18 18 18 18 18' + '17 17 17 17 17 17 17 17 17 17 17 17 18 18 17 18' + '17 18 17 0F 1A 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 1A 1A 11 17 17 12 12 17 18 18' + '18 18 18 18 18 17 18 18 18 18 18 18 18 17 16 12' + '17 18 16 08 1A 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 1A 1A 0F 17 16 11 12 11 18 18' + '18 18 18 18 18 18 18 18 18 18 18 18 18 17 11 12' + '11 18 16 07 1A 1A 1A 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 1A 1A 07 16 17 17 17 17 19 19' + '19 19 19 19 19 19 19 19 19 19 19 19 19 18 17 17' + '17 17 11 04 1A 1A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 1A 1A 02 0F 12 17 17 17 17 17' + '17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17' + '17 11 07 1A 1A 1A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 1A 1A 1A 1A 05 05 05 05 05 05' + '05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05' + '05 04 1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A' + '1A 1A 1A 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF 00' + '00 00 00 7F 00 00 FC 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' + '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' + '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 16 00 00 00 34 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 35 00 00 00 18 00 00 00 04 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 05 00 00 00 69 00 00 00 C5 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F1 00 00 00 B1 00 00 00 5C 00 00 00 0D 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' + '00 9B 00 00 00 FF 00 00 00 FF 21 21 21 FF 2C 2C' + '2C FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2E 2C 2D FF 2E 2C 2D FF 13 13' + '13 FF 00 00 00 FF 00 00 00 F6 00 00 00 69 00 00' + '00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 54 00 00' + '00 FF 26 26 26 FF 90 90 90 FF CA CA CA FF CD CD' + 'CD FF CB CB CB FF CE CE CE FF CD CD CD FF CC CC' + 'CC FF CB CB CB FF C9 C9 C9 FF C7 C7 C7 FF C6 C6' + 'C6 FF C5 C5 C5 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2' + 'C2 FF C2 C2 C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1' + 'C1 FF BF BF BF FF BF BF BF FF BC BC BC FF BD BD' + 'BD FF BA BA BA FF BB BB BB FF B5 B5 B5 FF B3 B4' + 'B3 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' + 'AB FF 63 63 63 FF 09 09 09 FF 00 00 00 EF 00 00' + '00 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 03 00 00 00 AD 01 01' + '01 FF 8A 8A 8A FF EB EB EB FF E8 E8 E8 FF E7 E7' + 'E7 FF D5 D5 D5 FF 85 85 85 FF 88 88 88 FF 92 92' + '92 FF 98 98 98 FF A2 A2 A2 FF AD AD AD FF BA BA' + 'BA FF C0 C0 C0 FF C3 C3 C3 FF C6 C6 C6 FF CB CB' + 'CB FF CA CA CA FF CA CA CA FF D6 D6 D6 FF CA CA' + 'CA FF D3 D3 D3 FF CB CB CB FF D7 D7 D7 FF CC CC' + 'CC FF D4 D4 D4 FF C7 C7 C7 FF C8 C9 C9 FF C6 C2' + 'C4 FF 9D B3 A8 FF 20 A8 63 FF 1C A8 60 FF 90 AF' + 'A0 FF BF BB BD FF 4F 4F 4F FF 00 00 00 FF 00 00' + '00 81 00 00 00 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 15 00 00 00 F0 19 19' + '19 FF C7 C7 C7 FF EC EC EC FF E2 E2 E2 FF E6 E6' + 'E6 FF CB CB CB FF 3B 3B 3B FF 3F 3F 3F FF 56 56' + '56 FF 72 72 72 FF 87 87 87 FF 92 92 92 FF 9D 9D' + '9D FF A5 A5 A5 FF A8 A8 A8 FF AC AC AC FF B7 B7' + 'B7 FF A9 A9 A9 FF 9C 9C 9C FF BD BD BD FF 99 99' + '99 FF B7 B7 B7 FF A1 A1 A1 FF C3 C3 C3 FF A3 A3' + 'A3 FF BD BD BD FF 98 98 98 FF C5 C4 C4 FF C7 BF' + 'C3 FF 51 A7 7C FF 17 CE 71 FF 0A BF 61 FF 2F 99' + '64 FF C3 BD C0 FF 84 83 84 FF 01 01 01 FF 00 00' + '00 A3 00 00 00 0B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 30 00 00 00 FA 29 29' + '29 FF D1 D1 D1 FF EA EA EA FF E4 E4 E4 FF E7 E7' + 'E7 FF CD CD CD FF 47 47 47 FF 5F 5F 5F FF 79 79' + '79 FF 87 87 87 FF 8F 8F 8F FF 97 97 97 FF A0 A0' + 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF B9 B9' + 'B9 FF A4 A4 A4 FF 90 90 90 FF B8 B8 B8 FF 8A 8A' + '8A FF AF AF AF FF 94 94 94 FF BF BF BF FF 97 97' + '97 FF B7 B7 B7 FF 88 88 88 FF C4 C3 C3 FF C6 C3' + 'C5 FF 95 B2 A3 FF 91 D6 B4 FF 91 D8 B5 FF 83 AB' + '97 FF C4 C1 C3 FF 8E 8E 8E FF 01 01 01 FF 00 00' + '00 B7 00 00 00 13 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 34 00 00 00 F9 28 28' + '28 FF D1 D1 D1 FF EC EC EC FF E6 E6 E6 FF E7 E7' + 'E7 FF D1 D1 D1 FF 68 68 68 FF 74 74 74 FF 7E 7E' + '7E FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' + 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF BA BA' + 'BA FF 9F 9F 9F FF 83 83 83 FF B3 B3 B3 FF 7C 7C' + '7C FF A8 A8 A8 FF 87 87 87 FF BB BB BB FF 8A 8A' + '8A FF B2 B2 B2 FF 79 79 79 FF C2 C2 C2 FF C4 C4' + 'C4 FF C6 C3 C4 FF 99 AC A2 FF 96 AB A0 FF C2 BE' + 'C0 FF C4 C4 C4 FF 8D 8D 8D FF 01 01 01 FF 00 00' + '00 BA 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 28 28' + '28 FF D1 D1 D1 FF EE EE EE FF E7 E7 E7 FF E8 E8' + 'E8 FF D6 D6 D6 FF 70 70 70 FF 71 71 71 FF 7D 7D' + '7D FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' + 'A0 FF A7 A7 A7 FF AA AA AA FF AE AE AE FF BB BB' + 'BB FF 98 98 98 FF 73 73 73 FF AD AD AD FF 6A 6A' + '6A FF A0 A0 A0 FF 78 78 78 FF B7 B7 B7 FF 7C 7C' + '7C FF AB AB AB FF 67 67 67 FF C2 C2 C2 FF C6 C6' + 'C6 FF C4 C3 C4 FF C7 C4 C5 FF C6 C2 C4 FF BF BF' + 'BF FF C5 C5 C5 FF 8D 8D 8D FF 01 01 01 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 27 27' + '27 FF D1 D1 D1 FF EF EF EF FF E9 E9 E9 FF EB EB' + 'EB FF D6 D6 D6 FF 6A 6A 6A FF 6C 6C 6C FF 78 78' + '78 FF 81 81 81 FF 8A 8A 8A FF 93 93 93 FF 9C 9C' + '9C FF A3 A3 A3 FF A6 A6 A6 FF AB AB AB FF B9 B9' + 'B9 FF 90 90 90 FF 66 66 66 FF A5 A5 A5 FF 5B 5B' + '5B FF 98 98 98 FF 6B 6B 6B FF B1 B1 B1 FF 70 70' + '70 FF A4 A4 A4 FF 58 58 58 FF C1 C1 C1 FF C8 C8' + 'C8 FF C5 C5 C5 FF C3 C3 C3 FF C2 C2 C2 FF C1 C1' + 'C1 FF C6 C6 C6 FF 8E 8E 8E FF 01 01 01 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 27 27' + '27 FF D2 D2 D2 FF F2 F2 F2 FF EB EB EB FF EA EA' + 'EA FF DF DF DF FF A7 A7 A7 FF A7 A7 A7 FF AB AB' + 'AB FF AE AE AE FF B0 B0 B0 FF B3 B3 B3 FF B6 B6' + 'B6 FF B9 B9 B9 FF B9 B9 B9 FF BA BA BA FF BD BD' + 'BD FF B7 B7 B7 FF B1 B1 B1 FF BE BE BE FF AF AF' + 'AF FF BA BA BA FF B1 B1 B1 FF BE BE BE FF B0 B0' + 'B0 FF BA BA BA FF AB AB AB FF C5 C5 C5 FF C8 C8' + 'C8 FF C6 C6 C6 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2' + 'C2 FF C9 C9 C9 FF 8E 8E 8E FF 00 00 00 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 26 26' + '26 FF D3 D3 D3 FF F3 F3 F3 FF EB EB EB FF EB EB' + 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF E9 E9' + 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' + 'E2 FF E1 E1 E1 FF DF DF DF FF DE DE DE FF DB DB' + 'DB FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' + 'D9 FF D6 D6 D6 FF D6 D6 D6 FF D2 D2 D2 FF D2 D2' + 'D2 FF CF CF CF FF D0 D0 D0 FF CB CB CB FF CA CA' + 'CA FF C9 C9 C9 FF C7 C7 C7 FF C4 C4 C4 FF C0 C0' + 'C0 FF CA CA CA FF 8E 8E 8E FF 00 00 00 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 26 26' + '26 FF D3 D3 D3 FF F7 F7 F7 FF F8 F8 F8 FF F6 F6' + 'F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5' + 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3' + 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F1 F1' + 'F1 FF F1 F1 F1 FF F1 F1 F1 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF EF EF EF FF EF EF EF FF EE EE' + 'EE FF EE EE EE FF ED ED ED FF ED ED ED FF ED ED' + 'ED FF EC EC EC FF EC EC EC FF EB EB EB FF E0 E0' + 'E0 FF D0 D0 D0 FF 8D 8D 8D FF 00 00 00 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 33 00 00 00 F9 24 24' + '24 FF D6 D6 D6 FF FF FF FF FF E9 E9 E9 FF E1 E1' + 'E1 FF E2 E2 E2 FF E2 E2 E2 FF E0 E0 E0 FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E2 E2' + 'E2 FF E3 E3 E3 FF E3 E3 E3 FF E3 E3 E3 FF F8 F8' + 'F8 FF EF EF EF FF 8C 8C 8C FF 00 00 00 FF 00 00' + '00 B9 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 34 00 00 00 FA 24 24' + '24 FF DE DE DE FF F8 F8 F8 FF D9 D9 D9 FF C4 C4' + 'C4 FF BB BB BB FF BF BF BF FF D8 D8 D8 FF DA DA' + 'DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF DB DB DB FF CF CF' + 'CF FF BC BC BC FF BB BB BB FF D1 D1 D1 FF DE DE' + 'DE FF FF FF FF FF 9A 9A 9A FF 00 00 00 FF 00 00' + '00 BA 00 00 00 14 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 00 00 00 F7 1F 1F' + '1F FF DA DA DA FF F3 F3 F3 FF C6 C6 C6 FF A9 A9' + 'A9 FF B7 B7 B7 FF B0 B0 B0 FF C3 C3 C3 FF DA DA' + 'DA FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D9 D9 D9 FF D2 D2 D2 FF A8 A8' + 'A8 FF B6 B6 B6 FF B1 B1 B1 FF B5 B5 B5 FF D8 D8' + 'D8 FF FC FC FC FF 9C 9C 9C FF 00 00 00 FF 00 00' + '00 AE 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 07 00 00 00 D0 05 05' + '05 FF C2 C2 C2 FF F6 F6 F6 FF BC BC BC FF B2 B2' + 'B2 FF C3 C3 C3 FF AB AB AB FF BB BB BB FF D8 D8' + 'D8 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' + 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' + 'D7 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D5 D5' + 'D5 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4' + 'D4 FF D5 D5 D5 FF D7 D7 D7 FF C9 C9 C9 FF A6 A6' + 'A6 FF C3 C3 C3 FF B3 B3 B3 FF AD AD AD FF D6 D6' + 'D6 FF F5 F5 F5 FF 76 76 76 FF 00 00 00 FF 00 00' + '00 8C 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' + '00 FF A4 A4 A4 FF F4 F4 F4 FF CF CF CF FF C5 C5' + 'C5 FF D2 D2 D2 FF BF BF BF FF C9 C9 C9 FF D3 D3' + 'D3 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF DD DD' + 'DD FF E1 E1 E1 FF E3 E3 E3 FF E6 E6 E6 FF EA EA' + 'EA FF ED ED ED FF ED ED ED FF EB EB EB FF E7 E7' + 'E7 FF E4 E4 E4 FF E2 E2 E2 FF DE DE DE FF D4 D4' + 'D4 FF D0 D0 D0 FF D2 D2 D2 FF D3 D3 D3 FF C5 C5' + 'C5 FF D0 D0 D0 FF C2 C2 C2 FF BF BF BF FF D9 D9' + 'D9 FF E8 E8 E8 FF 56 56 56 FF 00 00 00 FF 00 00' + '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 73 00 00' + '00 FF 7E 7E 7E FF EF EF EF FF D1 D1 D1 FF CF CF' + 'CF FF CB CB CB FF CF CF CF FF D1 D1 D1 FF CE CE' + 'CE FF CF CF CF FF DF DF DF FF F0 F0 F0 FF EC EC' + 'EC FF E1 E1 E1 FF DE DE DE FF DD DD DD FF DC DC' + 'DC FF DB DB DB FF DB DB DB FF DC DC DC FF DD DD' + 'DD FF DE DE DE FF E1 E1 E1 FF EC EC EC FF F1 F1' + 'F1 FF E1 E1 E1 FF D1 D1 D1 FF CE CE CE FF D0 D0' + 'D0 FF CB CB CB FF CE CE CE FF D1 D1 D1 FF D9 D9' + 'D9 FF D4 D4 D4 FF 3F 3F 3F FF 00 00 00 FF 00 00' + '00 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' + '00 FF 59 59 59 FF E9 E9 E9 FF D0 D0 D0 FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CA CA CA FF D6 D6' + 'D6 FF ED ED ED FF E6 E6 E6 FF DC DC DC FF D4 D4' + 'D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D5 D5 D5 FF D5 D5 D5 FF DB DB' + 'DB FF E4 E4 E4 FF ED ED ED FF DA DA DA FF CA CA' + 'CA FF CD CD CD FF CD CD CD FF CB CB CB FF DF DF' + 'DF FF B8 B8 B8 FF 22 22 22 FF 00 00 00 FB 00 00' + '00 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' + '00 FE 40 40 40 FF D7 D7 D7 FF D2 D2 D2 FF CA CA' + 'CA FF CB CB CB FF CA CA CA FF D4 D4 D4 FF E9 E9' + 'E9 FF DC DC DC FF D0 D0 D0 FF D1 D1 D1 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' + 'D1 FF D0 D0 D0 FF D8 D8 D8 FF EA EA EA FF D8 D8' + 'D8 FF C9 C9 C9 FF CA CA CA FF C9 C9 C9 FF E0 E0' + 'E0 FF A0 A0 A0 FF 08 08 08 FF 00 00 00 EB 00 00' + '00 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 25 00 00' + '00 F8 22 22 22 FF B7 B7 B7 FF DB DB DB FF CA CA' + 'CA FF CB CB CB FF CE CE CE FF E4 E4 E4 FF D4 D4' + 'D4 FF CF CF CF FF D1 D1 D1 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CD CD' + 'CD FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CC CC CC FF D0 D0 D0 FF E2 E2' + 'E2 FF CF CF CF FF C7 C7 C7 FF C9 C9 C9 FF E2 E2' + 'E2 FF 80 80 80 FF 00 00 00 FF 00 00 00 C2 00 00' + '00 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 E1 07 07 07 FF 9F 9F 9F FF DD DD DD FF CC CC' + 'CC FF CD CD CD FF DB DB DB FF D6 D6 D6 FF CE CE' + 'CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CC CC' + 'CC FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF C8 C8 C8 FF CF CF' + 'CF FF DA DA DA FF C7 C7 C7 FF C9 C9 C9 FF E2 E2' + 'E2 FF 5A 5A 5A FF 00 00 00 FF 00 00 00 94 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 B2 00 00 00 FF 83 83 83 FF DD DD DD FF CF CF' + 'CF FF D1 D1 D1 FF DB DB DB FF D1 D1 D1 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' + 'CF FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C7 C7' + 'C7 FF D3 D3 D3 FF C8 C8 C8 FF C9 C9 C9 FF DE DE' + 'DE FF 42 42 42 FF 00 00 00 FF 00 00 00 6C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 5F 5F 5F FF DC DC DC FF D1 D1' + 'D1 FF D2 D2 D2 FF D4 D4 D4 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D0 D0 D0 FF C8 C8 C8 FF C3 C3 C3 FF C3 C3' + 'C3 FF C3 C3 C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF C7 C7 C7 FF C5 C5 C5 FF CB CB CB FF CC CC' + 'CC FF 2D 2D 2D FF 00 00 00 F8 00 00 00 40 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4B 00 00 00 FE 41 41 41 FF D8 D8 D8 FF D4 D4' + 'D4 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CD CD CD FF C7 C7' + 'C7 FF C4 C4 C4 FF C2 C2 C2 FF C1 C1 C1 FF C0 C0' + 'C0 FF C1 C1 C1 FF C1 C1 C1 FF C1 C1 C1 FF C2 C2' + 'C2 FF BF BF BF FF C0 C0 C0 FF CE CE CE FF B2 B2' + 'B2 FF 1A 1A 1A FF 00 00 00 E5 00 00 00 28 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1A 00 00 00 F2 2C 2C 2C FF CC CC CC FF D6 D6' + 'D6 FF D5 D5 D5 FF CC CC CC FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D6 D6' + 'D6 FF D5 D5 D5 FF D3 D3 D3 FF CF CF CF FF CC CC' + 'CC FF C9 C9 C9 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2' + 'C2 FF B3 B3 B3 FF BD BD BD FF D0 D0 D0 FF 99 99' + '99 FF 09 09 09 FF 00 00 00 CF 00 00 00 19 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 09 00 00 00 D8 18 18 18 FF B0 B0 B0 FF DB DB' + 'DB FF DB DB DB FF D0 D0 D0 FF D2 D2 D2 FF DB DB' + 'DB FF D9 D9 D9 FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DB DB DB FF DB DB' + 'DB FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF CF CF' + 'CF FF C5 C5 C5 FF CC CC CC FF CA CA CA FF 7A 7A' + '7A FF 02 02 02 FF 00 00 00 B8 00 00 00 0A 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 BF 08 08 08 FF 97 97 97 FF DC DC' + 'DC FF DF DF DF FF DC DC DC FF CE CE CE FF D6 D6' + 'D6 FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DE DE DE FF D8 D8 D8 FF CE CE' + 'CE FF DD DD DD FF DC DC DC FF C6 C6 C6 FF 53 53' + '53 FF 00 00 00 FF 00 00 00 A0 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 A4 00 00 00 FF 77 77 77 FF D3 D3' + 'D3 FF E2 E2 E2 FF E1 E1 E1 FF DE DE DE FF CE CE' + 'CE FF D7 D7 D7 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' + 'E1 FF E1 E1 E1 FF D9 D9 D9 FF CD CD CD FF DA DA' + 'DA FF E3 E3 E3 FF D9 D9 D9 FF BB BB BB FF 39 39' + '39 FF 00 00 00 FF 00 00 00 7E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 89 00 00 00 FF 4B 4B 4B FF C9 C9' + 'C9 FF E5 E5 E5 FF E3 E3 E3 FF E4 E4 E4 FF E1 E1' + 'E1 FF D7 D7 D7 FF D2 D2 D2 FF DA DA DA FF E4 E4' + 'E4 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF DC DC' + 'DC FF D2 D2 D2 FF D6 D6 D6 FF E0 E0 E0 FF E4 E4' + 'E4 FF E6 E6 E6 FF D6 D6 D6 FF A8 A8 A8 FF 20 20' + '20 FF 00 00 00 FD 00 00 00 4E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 62 00 00 00 FF 35 35 35 FF BD BD' + 'BD FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7' + 'E7 FF E7 E7 E7 FF DF DF DF FF D2 D2 D2 FF D3 D3' + 'D3 FF DE DE DE FF E3 E3 E3 FF E3 E3 E3 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3' + 'E3 FF E3 E3 E3 FF DE DE DE FF D4 D4 D4 FF D1 D1' + 'D1 FF DD DD DD FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' + 'E6 FF E8 E8 E8 FF D4 D4 D4 FF 9A 9A 9A FF 0B 0B' + '0B FF 00 00 00 ED 00 00 00 2C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2D 00 00 00 F9 1E 1E 1E FF AB AB' + 'AB FF E4 E4 E4 FF ED ED ED FF E7 E7 E7 FF E6 E6' + 'E6 FF EC EC EC FF EB EB EB FF EA EA EA FF E4 E4' + 'E4 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DD DD' + 'DD FF DC DC DC FF DC DC DC FF DD DD DD FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' + 'E9 FF EC EC EC FF EA EA EA FF E5 E5 E5 FF EB EB' + 'EB FF EB EB EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00' + '00 FF 00 00 00 C3 00 00 00 17 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 09 00 00 00 DD 08 08 08 FF 99 99' + '99 FF E4 E4 E4 FF DF DF DF FF BD BD BD FF C1 C1' + 'C1 FF D6 D6 D6 FF EC EC EC FF ED ED ED FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EC EC' + 'EC FF EB EB EB FF EB EB EB FF EC EC EC FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EE EE' + 'EE FF E4 E4 E4 FF C2 C2 C2 FF BE BE BE FF D1 D1' + 'D1 FF EC EC EC FF D4 D4 D4 FF 75 75 75 FF 00 00' + '00 FF 00 00 00 9C 00 00 00 06 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 AE 00 00 00 FF 8D 8D' + '8D FF E0 E0 E0 FF C4 C4 C4 FF B2 B2 B2 FF B8 B8' + 'B8 FF B2 B2 B2 FF EB EB EB FF F1 F1 F1 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' + 'F3 FF D5 D5 D5 FF B0 B0 B0 FF B6 B6 B6 FF B7 B7' + 'B7 FF EB EB EB FF CD CD CD FF 61 61 61 FF 00 00' + '00 FF 00 00 00 85 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 64 64' + '64 FF CE CE CE FF DD DD DD FF DC DC DC FF D5 D5' + 'D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' + 'FA FF F2 F2 F2 FF DF DF DF FF D8 D8 D8 FF DC DC' + 'DC FF D7 D7 D7 FF B0 B0 B0 FF 34 34 34 FF 00 00' + '00 FF 00 00 00 67 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 44 00 00 00 FF 19 19' + '19 FF 80 80 80 FF BE BE BE FF D3 D3 D3 FF D7 D7' + 'D7 FF DB DB DB FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D7 D7 D7 FF CD CD' + 'CD FF B0 B0 B0 FF 5D 5D 5D FF 06 06 06 FF 00 00' + '00 ED 00 00 00 2B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 9C 00 00' + '00 FF 0C 0C 0C FF 3D 3D 3D FF 49 49 49 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' + '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 FF 00 00' + '00 5C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' + '00 7F 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 5C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2C 00 00 00 7E 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 70 00 00 00 1A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF 00 00 00 00 7F 00 00 FC 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 15 00 00 00 54 00 00 00 63 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 63 00 00 00 50 00 00 00 14 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 33 00 00' + '00 D7 0D 0D 0D FF 1B 1B 1B FF 1C 1C 1C FF 1E 1E' + '1E FF 1D 1D 1D FF 1D 1D 1D FF 1C 1C 1C FF 1B 1B' + '1B FF 1B 1B 1B FF 1B 1B 1B FF 1A 1A 1A FF 1A 1A' + '1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A' + '1A FF 1A 1A 1A FF 1A 1A 1A FF 1A 1A 1A FF 20 1C' + '1E FF 22 1B 1F FF 09 09 09 FF 00 00 00 C3 00 00' + '00 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 07 00 00 00 C9 40 40' + '40 FF BA BA BA FF CB CB CB FF BE BE BE FF B3 B3' + 'B3 FF B4 B4 B4 FF B4 B4 B4 FF B7 B7 B7 FF BB BB' + 'BB FF BB BB BB FF BB BB BB FF BC BC BC FF BE BE' + 'BE FF BD BD BD FF BC BC BC FF BB BB BB FF BA BA' + 'BA FF BA BA BA FF B4 B4 B4 FF B1 AE AF FF 8C A4' + '98 FF 80 A5 93 FF 90 91 91 FF 21 21 21 FF 00 00' + '00 AB 00 00 00 07 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 3D 08 08 08 FD B7 B7' + 'B7 FF F2 F2 F2 FF EE EE EE FF AF AF AF FF 51 51' + '51 FF 6E 6E 6E FF 89 89 89 FF 9A 9A 9A FF AB AB' + 'AB FF B3 B3 B3 FF BC BC BC FF B5 B5 B5 FF B5 B5' + 'B5 FF BC BC BC FF BD BD BD FF BE BE BE FF B7 B7' + 'B7 FF C0 C0 C0 FF C4 C1 C3 FF B7 BF BA FF 2A BF' + '75 FF 0E C0 67 FF 8C B8 A2 FF 80 79 7C FF 00 00' + '00 EC 00 00 00 25 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 58 19 19 19 FF CE CE' + 'CE FF EB EB EB FF EB EB EB FF AA AA AA FF 56 56' + '56 FF 7A 7A 7A FF 8C 8C 8C FF 96 96 96 FF A2 A2' + 'A2 FF A9 A9 A9 FF B4 B4 B4 FF A1 A1 A1 FF 97 97' + '97 FF A1 A1 A1 FF A5 A5 A5 FF A5 A5 A5 FF 9B 9B' + '9B FF A7 A7 A7 FF B3 B1 B2 FF BC C1 BE FF 87 C6' + 'A6 FF 85 CC A8 FF A6 BC B1 FF 94 90 92 FF 02 02' + '02 F9 00 00 00 36 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 5A 18 18 18 FF CC CC' + 'CC FF ED ED ED FF EC EC EC FF B9 B9 B9 FF 6D 6D' + '6D FF 7D 7D 7D FF 8B 8B 8B FF 96 96 96 FF A2 A2' + 'A2 FF A9 A9 A9 FF B6 B6 B6 FF 96 96 96 FF 82 82' + '82 FF 8E 8E 8E FF 93 93 93 FF 94 94 94 FF 86 86' + '86 FF 95 95 95 FF A6 A6 A6 FF C8 C8 C8 FF C2 C0' + 'C1 FF BF BD BE FF C9 C6 C7 FF 8E 8E 8E FF 01 01' + '01 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF CD CD' + 'CD FF F0 F0 F0 FF ED ED ED FF BF BF BF FF 77 77' + '77 FF 85 85 85 FF 91 91 91 FF 9A 9A 9A FF A4 A4' + 'A4 FF AA AA AA FF B5 B5 B5 FF 97 97 97 FF 83 83' + '83 FF 8D 8D 8D FF 92 92 92 FF 93 93 93 FF 86 86' + '86 FF 93 93 93 FF A7 A7 A7 FF CA CA CA FF C4 C3' + 'C4 FF C3 C2 C2 FF C8 C8 C8 FF 8E 8E 8E FF 00 00' + '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF CE CE' + 'CE FF F2 F2 F2 FF EC EC EC FF E6 E6 E6 FF DC DC' + 'DC FF DB DB DB FF DA DA DA FF DA DA DA FF D9 D9' + 'D9 FF D8 D8 D8 FF D7 D7 D7 FF D4 D4 D4 FF D4 D4' + 'D4 FF D2 D2 D2 FF D0 D0 D0 FF CF CF CF FF CC CC' + 'CC FF CB CB CB FF CB CB CB FF CC CC CC FF CA CA' + 'CA FF C7 C7 C7 FF C9 C9 C9 FF 8D 8D 8D FF 00 00' + '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 5A 17 17 17 FF D0 D0' + 'D0 FF FF FF FF FF F8 F8 F8 FF F8 F8 F8 FF F9 F9' + 'F9 FF F8 F8 F8 FF F7 F7 F7 FF F7 F7 F7 FF F6 F6' + 'F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5 F5 FF F5 F5' + 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3' + 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1 F1 FF F2 F2' + 'F2 FF F3 F3 F3 FF E8 E8 E8 FF 8D 8D 8D FF 00 00' + '00 FA 00 00 00 37 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 5B 17 17 17 FF D7 D7' + 'D7 FF F4 F4 F4 FF DB DB DB FF D8 D8 D8 FF DD DD' + 'DD FF DF DF DF FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' + 'DF FF DF DF DF FF E0 E0 E0 FF DD DD DD FF D8 D8' + 'D8 FF E0 E0 E0 FF FB FB FB FF 9C 9C 9C FF 00 00' + '00 FA 00 00 00 38 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 51 11 11 11 FF D3 D3' + 'D3 FF D9 D9 D9 FF AD AD AD FF B0 B0 B0 FF BE BE' + 'BE FF D9 D9 D9 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D7 D7' + 'D7 FF D9 D9 D9 FF D3 D3 D3 FF AF AF AF FF B1 B1' + 'B1 FF B8 B8 B8 FF ED ED ED FF A0 A0 A0 FF 00 00' + '00 F7 00 00 00 2E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2B 00 00 00 F8 B3 B3' + 'B3 FF DC DC DC FF B9 B9 B9 FF BA BA BA FF BC BC' + 'BC FF D5 D5 D5 FF D3 D3 D3 FF D4 D4 D4 FF D8 D8' + 'D8 FF DF DF DF FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' + 'E4 FF E3 E3 E3 FF DF DF DF FF D9 D9 D9 FF D4 D4' + 'D4 FF D3 D3 D3 FF CF CF CF FF BA BA BA FF B8 B8' + 'B8 FF B8 B8 B8 FF E9 E9 E9 FF 7C 7C 7C FF 00 00' + '00 DE 00 00 00 17 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0C 00 00 00 E2 89 89' + '89 FF E5 E5 E5 FF CE CE CE FF D0 D0 D0 FF D0 D0' + 'D0 FF D1 D1 D1 FF DE DE DE FF E5 E5 E5 FF E5 E5' + 'E5 FF E2 E2 E2 FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF E2 E2 E2 FF E6 E6 E6 FF E5 E5' + 'E5 FF DF DF DF FF D2 D2 D2 FF CF CF CF FF CF CF' + 'CF FF D0 D0 D0 FF E6 E6 E6 FF 54 54 54 FF 00 00' + '00 BC 00 00 00 07 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 BB 64 64' + '64 FF E2 E2 E2 FF CB CB CB FF CB CB CB FF CE CE' + 'CE FF E2 E2 E2 FF E0 E0 E0 FF D7 D7 D7 FF D3 D3' + 'D3 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4' + 'D4 FF D4 D4 D4 FF D4 D4 D4 FF D3 D3 D3 FF D7 D7' + 'D7 FF DF DF DF FF E4 E4 E4 FF D1 D1 D1 FF CB CB' + 'CB FF CF CF CF FF D7 D7 D7 FF 34 34 34 FF 00 00' + '00 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 93 3E 3E' + '3E FF DB DB DB FF CC CC CC FF CC CC CC FF DC DC' + 'DC FF D7 D7 D7 FF CF CF CF FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CC CC CC FF D3 D3 D3 FF DC DC DC FF C9 C9' + 'C9 FF CF CF CF FF C2 C2 C2 FF 1A 1A 1A FF 00 00' + '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 6B 21 21' + '21 FF C9 C9 C9 FF D2 D2 D2 FF D3 D3 D3 FF D7 D7' + 'D7 FF CF CF CF FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF CA CA CA FF C7 C7' + 'C7 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' + 'C8 FF C8 C8 C8 FF C7 C7 C7 FF CF CF CF FF CC CC' + 'CC FF D0 D0 D0 FF A9 A9 A9 FF 04 04 04 FF 00 00' + '00 4D 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 44 0B 0B' + '0B FF B1 B1 B1 FF D8 D8 D8 FF D2 D2 D2 FF D2 D2' + 'D2 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D2 D2 D2 FF D1 D1 D1 FF C9 C9' + 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C5 C5 C5 FF C5 C5' + 'C5 FF D2 D2 D2 FF 86 86 86 FF 00 00 00 F3 00 00' + '00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00' + '00 F4 93 93 93 FF DF DF DF FF D2 D2 D2 FF D2 D2' + 'D2 FF D5 D5 D5 FF D4 D4 D4 FF D4 D4 D4 FF D4 D4' + 'D4 FF D4 D4 D4 FF D4 D4 D4 FF D5 D5 D5 FF D5 D5' + 'D5 FF D2 D2 D2 FF CD CD CD FF C7 C7 C7 FF C3 C3' + 'C3 FF C2 C2 C2 FF C2 C2 C2 FF BE BE BE FF BC BC' + 'BC FF D0 D0 D0 FF 67 67 67 FF 00 00 00 D9 00 00' + '00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0B 00 00' + '00 DE 75 75 75 FF DE DE DE FF D7 D7 D7 FF D1 D1' + 'D1 FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF DA DA DA FF DA DA DA FF DA DA DA FF D8 D8' + 'D8 FF D6 D6 D6 FF D5 D5 D5 FF C7 C7 C7 FF C5 C5' + 'C5 FF CD CD CD FF 4B 4B 4B FF 00 00 00 BD 00 00' + '00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 B7 53 53 53 FF D9 D9 D9 FF E1 E1 E1 FF D5 D5' + 'D5 FF D5 D5 D5 FF DF DF DF FF DF DF DF FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF DE DE DE FF DF DF' + 'DF FF E0 E0 E0 FF D7 D7 D7 FF D6 D6 D6 FF DE DE' + 'DE FF C3 C3 C3 FF 2C 2C 2C FF 00 00 00 9A 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 90 31 31 31 FF CB CB CB FF E5 E5 E5 FF E4 E4' + 'E4 FF DA DA DA FF D7 D7 D7 FF DD DD DD FF E2 E2' + 'E2 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E2 E2 E2 FF DE DE' + 'DE FF D7 D7 D7 FF D9 D9 D9 FF E4 E4 E4 FF DF DF' + 'DF FF AB AB AB FF 17 17 17 FF 00 00 00 73 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 67 1A 1A 1A FF B3 B3 B3 FF E8 E8 E8 FF EA EA' + 'EA FF EA EA EA FF E5 E5 E5 FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF DD DD DD FF DC DC DC FF DD DD' + 'DD FF E5 E5 E5 FF E9 E9 E9 FF EC EC EC FF DF DF' + 'DF FF 95 95 95 FF 04 04 04 FF 00 00 00 4D 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 41 07 07 07 FE 9F 9F 9F FF E8 E8 E8 FF CD CD' + 'CD FF CB CB CB FF E7 E7 E7 FF EF EF EF FF ED ED' + 'ED FF EA EA EA FF E9 E9 E9 FF E7 E7 E7 FF E7 E7' + 'E7 FF E8 E8 E8 FF EA EA EA FF EC EC EC FF F0 F0' + 'F0 FF DB DB DB FF C6 C6 C6 FF DC DC DC FF E1 E1' + 'E1 FF 78 78 78 FF 00 00 00 F4 00 00 00 29 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1E 00 00 00 F4 83 83 83 FF E0 E0 E0 FF C9 C9' + 'C9 FF C6 C6 C6 FF EA EA EA FF FA FA FA FF F8 F8' + 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8' + 'F8 FF F8 F8 F8 FF F8 F8 F8 FF F8 F8 F8 FF FB FB' + 'FB FF D9 D9 D9 FF C4 C4 C4 FF D1 D1 D1 FF D2 D2' + 'D2 FF 50 50 50 FF 00 00 00 DA 00 00 00 15 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 BB 24 24 24 FF 98 98 98 FF CF CF' + 'CF FF D2 D2 D2 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D2 D2 D2 FF C8 C8 C8 FF 7C 7C' + '7C FF 0D 0D 0D FF 00 00 00 9A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 31 00 00 00 DF 0F 0F 0F FF 29 29' + '29 FF 29 29 29 FF 28 28 28 FF 28 28 28 FF 28 28' + '28 FF 28 28 28 FF 28 28 28 FF 28 28 28 FF 28 28' + '28 FF 28 28 28 FF 28 28 28 FF 28 28 28 FF 28 28' + '28 FF 28 28 28 FF 2A 2A 2A FF 26 26 26 FF 08 08' + '08 FF 00 00 00 C8 00 00 00 1D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 14 00 00 00 62 00 00' + '00 87 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 86 00 00' + '00 55 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF FF FF FF FF FF FF F0 00 00 0F E0 00' + '00 07 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F8 00 00 1F F8 00' + '00 1F FC 00 00 3F FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 11 04 04' + '04 8A 16 16 16 A8 1B 1B 1B A8 18 18 18 A8 16 16' + '16 A8 15 15 15 A8 16 16 16 A8 15 15 15 A8 15 15' + '15 A8 14 13 14 A8 19 12 16 A8 05 03 04 84 00 00' + '00 0F 00 00 00 00 00 00 00 00 05 05 05 83 9B 9B' + '9B FF C1 C1 C1 FF 83 83 83 FF 9A 9A 9A FF AD AD' + 'AD FF B2 B2 B2 FF B3 B3 B3 FF B5 B5 B5 FF B2 B1' + 'B2 FF AC B2 AF FF 59 B0 84 FF 5B 6C 64 FF 04 01' + '03 71 00 00 00 00 00 00 00 00 13 13 13 B3 DC DC' + 'DC FF CB CB CB FF 65 65 65 FF 8A 8A 8A FF A7 A7' + 'A7 FF AB AB AB FF 95 95 95 FF A2 A2 A2 FF 95 94' + '95 FF BA BF BC FF 8F CC AD FF 93 A1 9A FF 09 06' + '07 95 00 00 00 00 00 00 00 00 13 13 13 B2 D7 D7' + 'D7 FF DE DE DE FF A1 A1 A1 FF AC AC AC FF BA BA' + 'BA FF B7 B7 B7 FF A2 A2 A2 FF A9 A9 A9 FF 9D 9D' + '9D FF C2 C1 C1 FF CF C9 CC FF A2 A0 A1 FF 06 06' + '06 93 00 00 00 00 00 00 00 00 14 14 14 B3 D9 D9' + 'D9 FF ED ED ED FF EA EA EA FF E8 E8 E8 FF E5 E5' + 'E5 FF E5 E5 E5 FF E6 E6 E6 FF E4 E4 E4 FF E4 E4' + 'E4 FF DF DF DF FF E3 E3 E3 FF B2 B2 B2 FF 04 05' + '05 94 00 00 00 00 00 00 00 00 11 11 11 A5 C6 C6' + 'C6 FF BC BC BC FF CA CA CA FF D9 D9 D9 FF DA DA' + 'DA FF DA DA DA FF DB DB DB FF DA DA DA FF DA DA' + 'DA FF C6 C6 C6 FF C5 C5 C5 FF B4 B4 B4 FF 04 04' + '04 8B 00 00 00 00 00 00 00 00 04 04 04 7B A8 A8' + 'A8 FF CE CE CE FF CF CF CF FF DC DC DC FF DD DD' + 'DD FF DE DE DE FF DE DE DE FF DE DE DE FF DC DC' + 'DC FF CF CF CF FF D4 D4 D4 FF 91 91 91 FF 00 00' + '00 69 00 00 00 00 00 00 00 00 00 00 00 53 85 85' + '85 FF DB DB DB FF D7 D7 D7 FF D3 D3 D3 FF D0 D0' + 'D0 FF CE CE CE FF CD CD CD FF CE CE CE FF D0 D0' + 'D0 FF D6 D6 D6 FF D9 D9 D9 FF 6E 6E 6E FE 00 00' + '00 43 00 00 00 00 00 00 00 00 00 00 00 2E 64 64' + '64 FA DD DD DD FF D3 D3 D3 FF D0 D0 D0 FF D1 D1' + 'D1 FF CF CF CF FF C8 C8 C8 FF C4 C4 C4 FF C4 C4' + 'C4 FF C5 C5 C5 FF CF CF CF FF 4D 4D 4D F3 00 00' + '00 20 00 00 00 00 00 00 00 00 00 00 00 0E 42 42' + '42 E8 D7 D7 D7 FF D6 D6 D6 FF D9 D9 D9 FF D8 D8' + 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D4 D4 D4 FF D3 D3' + 'D3 FF CD CD CD FF C5 C5 C5 FF 2C 2C 2C D8 00 00' + '00 0A 00 00 00 00 00 00 00 00 00 00 00 02 22 22' + '22 C5 D1 D1 D1 FF E3 E3 E3 FF DC DC DC FF DF DF' + 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF DE DE' + 'DE FF E5 E5 E5 FF C0 C0 C0 FF 11 11 11 B6 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 08 08' + '08 A1 BE BE BE FF E1 E1 E1 FF EA EA EA FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF E5 E5' + 'E5 FF E5 E5 E5 FF A3 A3 A3 FF 01 01 01 93 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 74 78 78 78 FF C7 C7 C7 FF D9 D9 D9 FF DE DE' + 'DE FF DD DD DD FF DD DD DD FF DF DF DF FF D4 D4' + 'D4 FF C7 C7 C7 FF 60 60 60 FF 00 00 00 65 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 11 04 04 04 94 1D 1D 1D CC 1C 1C 1C CC 1C 1C' + '1C CC 1C 1C 1C CC 1C 1C 1C CC 1C 1C 1C CC 1D 1D' + '1D CC 1B 1B 1B CB 02 02 02 88 00 00 00 0C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 FF FF 00 00' +} */ + +/* BINRES netdrive.ico */ +9 ICON netdrive.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 8E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 02 02 02 00 04 04 04 00 05 06 06 00 06 06' + '06 00 09 09 09 00 0A 0A 0A 00 0C 0C 0C 00 12 12' + '12 00 14 14 14 00 15 15 15 00 16 16 16 00 1D 1D' + '1D 00 1F 1F 1F 00 21 21 21 00 22 22 22 00 23 23' + '23 00 24 24 24 00 25 25 25 00 26 26 26 00 38 38' + '38 00 39 39 39 00 3B 3B 3B 00 00 67 67 00 43 43' + '43 00 46 46 46 00 4A 4A 4A 00 54 4C 50 00 53 53' + '53 00 55 55 55 00 56 56 56 00 58 58 58 00 59 59' + '59 00 5A 58 59 00 5A 5A 5A 00 5B 5B 5B 00 5C 5C' + '5C 00 5D 5D 5D 00 5E 5E 5E 00 65 58 5F 00 60 60' + '60 00 61 61 61 00 62 62 62 00 64 64 64 00 67 67' + '67 00 69 69 69 00 71 71 71 00 72 72 72 00 73 73' + '73 00 75 75 75 00 78 78 78 00 7A 7A 7A 00 7B 7B' + '7B 00 7C 7C 7C 00 7F 7F 7F 00 24 A7 64 00 3C AD' + '74 00 25 DC 7F 00 7D AA 94 00 18 FF FF 00 56 D8' + 'D8 00 81 81 81 00 83 83 83 00 89 89 89 00 8A 8A' + '8A 00 8B 8B 8B 00 8F 8F 8F 00 91 89 8C 00 90 90' + '90 00 91 91 91 00 94 94 94 00 95 95 95 00 97 97' + '97 00 99 99 99 00 9A 9A 9A 00 9C 9C 9C 00 9D 9D' + '9D 00 9E 9E 9E 00 9F 9F 9F 00 A0 91 91 00 94 B6' + 'A4 00 93 BD A9 00 A0 A0 A0 00 A1 A1 A1 00 A3 A3' + 'A3 00 A4 A4 A4 00 A5 A5 A5 00 A8 A8 A8 00 A9 A9' + 'A9 00 AA AA AA 00 AC AC AC 00 AD AD AD 00 AE AE' + 'AE 00 AF AF AF 00 B7 AF AF 00 AD B9 B3 00 B0 B0' + 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' + 'B4 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B9 B9' + 'B9 00 BC BC BC 00 BD BD BD 00 BE BE BE 00 BF BF' + 'BF 00 89 CF CF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C0' + 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C2 00 C5 C2' + 'C4 00 C4 C4 C4 00 C5 C5 C5 00 C6 C5 C6 00 C6 C6' + 'C6 00 C8 C3 C5 00 CC C4 C8 00 C8 C8 C8 00 C9 C9' + 'C9 00 CB C9 CA 00 CA CA CA 00 CB CB CB 00 CC CC' + 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D2 C1' + 'CA 00 D3 C8 CD 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' + 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' + 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' + 'DA 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' + 'DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' + 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' + 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' + 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' + 'EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2' + 'F2 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7' + 'F7 00 F8 F8 F8 00 F9 F9 F9 00 FC FC FC 00 FD FD' + 'FD 00 FF FF FF 00 00 00 00 00 62 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 6E 65 74 64 72 69 76 65 2E' + '69 63 6F 00 4B 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 B2 B2' + 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 17 17 B2' + 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 62 62' + '62 62 62 62 62 62 62 62 62 62 62 5E 6D 3B 3B 6D' + '5E 62 62 62 62 62 62 62 62 62 62 62 62 62 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 3C 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 4F 4F 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 0D 0D B2' + 'B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 00 00 00 00 00 00' + '00 B2 B2 09 26 26 2C 2B 2A 28 26 25 24 1E 1D 22' + '20 1F 1F 1F 1E 21 27 1B 05 B2 B2 00 00 00 00 00' + '00 B2 09 6E AA A0 58 64 68 6F 86 88 8C 8D 92 92' + '91 93 90 8E 82 79 38 51 43 03 B2 00 00 00 00 00' + '00 B2 1E AC 9C 9A 0C 1A 33 41 4C 54 5D 59 4E 4B' + '59 66 56 48 85 3A 39 37 84 13 B2 00 00 00 00 00' + '00 B2 25 A8 9D 99 1C 34 40 46 54 58 64 59 47 44' + '52 60 4A 3F 7D 70 50 5F 73 13 B2 00 00 00 00 00' + '00 B2 23 A9 9F 9E 24 2F 3E 42 4E 56 63 53 32 2E' + '41 52 3D 2C 7F 77 7A 74 6E 12 B2 00 00 00 00 00' + '00 B2 23 AB A2 9E 3D 44 4A 52 58 5B 64 5A 4B 49' + '54 5C 4C 45 7B 76 6F 6F 72 11 B2 00 00 00 00 00' + '00 B2 22 AD A6 A5 AF AE AA A8 A4 A2 9F 9D A0 9E' + '9A 96 96 96 8C 8A 88 7F 75 10 B2 00 00 00 00 00' + '00 B2 20 B1 A5 A3 A2 9D 9D 9C 9D 9D 9E 9D 9D 9D' + '9D 9D 9D 9C 9F A3 A2 AE 8B 0E B2 00 00 00 00 00' + '00 B2 25 B1 78 61 69 8E 8D 8D 8D 8D 8C 8C 8C 8C' + '8D 8D 8D 8E 87 65 65 8C AB 13 B2 00 00 00 00 00' + '00 B2 18 B1 5D 67 57 87 8D 8B 89 87 8A 8B 8B 8A' + '87 88 8A 90 68 62 58 7B 9E 0C B2 00 00 00 00 00' + '00 B2 10 9E 82 86 78 86 82 8F 9A 99 9C A0 A0 9D' + '9A 9B 91 83 83 83 75 8E 6B 06 B2 00 00 00 00 00' + '00 B2 08 87 87 80 81 81 9F 9C 90 8E 8D 8C 8C 8D' + '8E 91 9C 9F 86 7E 81 98 48 B2 B2 00 00 00 00 00' + '00 B2 01 55 8E 7C 81 9B 89 82 86 86 83 86 86 86' + '86 86 81 83 9C 83 78 9F 29 B2 B2 00 00 00 00 00' + '00 B2 B2 31 9A 7C 90 88 82 86 83 86 81 7E 7F 7F' + '7F 7F 7F 7E 80 90 72 A5 15 B2 B2 00 00 00 00 00' + '00 00 B2 19 A0 83 8E 82 86 86 86 86 86 80 71 72' + '75 76 76 76 72 81 76 A1 0A B2 00 00 00 00 00 00' + '00 00 B2 0F A4 87 87 88 87 87 87 87 87 88 81 75' + '6E 6C 6B 6E 6E 6E 78 8C 01 B2 00 00 00 00 00 00' + '00 00 B2 02 94 8F 80 8E 8C 8D 8D 8D 8D 8D 8D 8E' + '8D 8A 86 80 7C 67 7C 63 B2 B2 00 00 00 00 00 00' + '00 00 B2 B2 76 99 89 89 94 92 91 91 91 91 91 91' + '92 92 93 95 8C 89 93 3F B2 B2 00 00 00 00 00 00' + '00 00 00 B2 45 9C 99 8B 8C 96 99 97 97 97 97 97' + '97 99 95 8E 88 9D 8E 1F B2 00 00 00 00 00 00 00' + '00 00 00 B2 2C 9C 9D 9D 95 87 8F 98 99 9A 9A 99' + '98 8F 87 95 9E A1 82 14 B2 00 00 00 00 00 00 00' + '00 00 00 B2 16 93 A0 8F A2 A4 9C 98 97 94 94 97' + '98 9A A4 9A 91 A7 78 0C B2 00 00 00 00 00 00 00' + '00 00 00 B2 13 94 6F 5B 76 A8 A6 A6 A6 A5 A5 A6' + 'A6 A6 A3 65 5B 9D 6A 0B B2 00 00 00 00 00 00 00' + '00 00 00 B2 07 4D A2 9A AB B0 AF AF AF AF AF AF' + 'AF AF AF A7 9C 9B 30 B2 B2 00 00 00 00 00 00 00' + '00 00 00 B2 B2 0B 31 34 33 32 32 32 32 32 32 32' + '32 32 32 33 35 2D 04 B2 00 00 00 00 00 00 00 00' + '00 00 00 00 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2' + 'B2 B2 B2 B2 B2 B2 B2 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF 00 00 00 00 00 00 00 00 FF FE 7F FF FF FE' + '7F FF F0 00 00 0F E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 0C 0C 0C 00 15 15' + '15 00 1F 12 12 00 19 19 19 00 25 20 22 00 29 29' + '29 00 35 35 35 00 3E 3E 3E 00 40 40 40 00 57 57' + '57 00 6D 6D 6D 00 73 73 73 00 75 75 75 00 78 78' + '78 00 7B 7B 7B 00 7D 7D 7D 00 7F 7F 7F 00 89 7D' + '7D 00 66 8E 7A 00 86 7B 81 00 5E CA 93 00 4F D8' + 'D8 00 85 85 85 00 8C 8C 8C 00 8F 8F 8F 00 90 90' + '90 00 91 91 91 00 97 97 97 00 98 95 97 00 99 99' + '99 00 9B 9A 9B 00 9B 9B 9B 00 9F 9F 9F 00 A1 A1' + 'A1 00 A3 A3 A3 00 A5 A5 A5 00 A9 A9 A9 00 AC AC' + 'AC 00 AE AE AE 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' + 'B4 00 B6 B6 B6 00 B8 B8 B8 00 BA BA BA 00 BF BF' + 'BF 00 C1 C1 C1 00 C2 C2 C2 00 C0 C7 C4 00 C4 C4' + 'C4 00 C7 C7 C7 00 CB C9 CA 00 CA CA CA 00 CC CC' + 'CC 00 CD CD CD 00 CF CF CF 00 D4 C9 CF 00 D0 D0' + 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' + 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DF DF' + 'DF 00 E0 E0 E0 00 E1 E1 E1 00 E3 E3 E3 00 E4 E4' + 'E4 00 E6 E6 E6 00 E7 E7 E7 00 E9 E9 E9 00 EA EA' + 'EA 00 EC EC EC 00 ED ED ED 00 EF EF EF 00 F0 F0' + 'F0 00 F3 F3 F3 00 F4 F4 F4 00 F7 F7 F7 00 FC FC' + 'FC 00 00 00 00 00 A9 A9 A9 00 AA AA AA 00 AC AC' + 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B7 AF' + 'AF 00 AD B9 B3 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' + 'B2 00 B3 B3 B3 00 B4 B4 B4 00 B5 B5 B5 00 B6 B6' + 'B6 00 B7 B7 B7 00 B9 B9 B9 00 BC BC BC 00 BD BD' + 'BD 00 BE BE BE 00 BF BF BF 00 89 CF CF 00 C0 C0' + 'C0 00 C1 C1 C1 00 C2 C0 C1 00 C2 C2 C2 00 C3 C3' + 'C3 00 C4 C1 C2 00 C5 C2 C4 00 C4 C4 C4 00 C5 C5' + 'C5 00 C6 C5 C6 00 C6 C6 C6 00 C8 C3 C5 00 CC C4' + 'C8 00 C8 C8 C8 00 C9 C9 C9 00 CB C9 CA 00 CA CA' + 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' + 'CE 00 CF CF CF 00 D2 C1 CA 00 D3 C8 CD 00 D0 D0' + 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' + 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' + 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' + 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' + 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' + 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' + 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F4 F4 F4 00 F5 F5' + 'F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9' + 'F9 00 FC FC FC 00 FD FD FD 00 FF FF FF 00 00 00' + '00 00 62 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6E' + '65 74 64 72 69 76 65 2E 69 63 6F 00 4B 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 17 17 17 17 17 17 12 16 16 12' + '17 17 17 17 17 17 00 00 00 57 57 57 57 03 03 57' + '57 57 57 57 00 00 00 00 07 2B 1A 1C 21 20 21 23' + '22 1D 13 05 00 00 00 57 2B 56 08 18 25 2A 1E 29' + '1F 31 15 14 00 00 00 57 27 55 0B 19 24 26 10 20' + '0F 34 39 0D 00 00 00 57 28 56 56 54 52 4F 51 4E' + '4E 4A 51 0E 00 00 00 57 2A 2C 2E 40 3D 3F 3F 3E' + '42 2C 33 1B 00 00 00 00 11 43 35 47 47 48 48 47' + '48 37 46 0A 00 00 00 00 09 46 43 38 38 36 36 37' + '36 43 4B 04 00 00 00 00 01 50 3B 3A 3A 3A 32 2E' + '2E 30 48 57 00 00 00 00 57 4C 3C 45 43 43 44 44' + '41 36 30 57 00 00 00 00 57 2C 4F 42 46 49 49 47' + '43 52 1B 57 00 00 00 00 57 19 43 4F 53 51 51 53' + '49 4D 0C 57 00 00 00 00 00 06 2E 30 30 30 30 30' + '2F 2D 02 00 00 00 00 00 00 00 57 57 57 57 57 57' + '57 57 00 00 00 00 FF FF 00 00 00 00 00 00 E0 03' + '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' + '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' + '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 60 00 00 00 00 00 00 00 77 77' + '77 77 77 77 77 7E E7 77 77 77 77 77 77 77 00 00' + '00 00 00 00 00 0E E0 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 08 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 88 88 88 88 88 88 88 88 88 88 00 00 00 00 00' + '07 FF 77 77 77 77 77 77 77 77 67 80 00 00 00 00' + '8F FF 08 88 87 77 88 77 78 78 66 70 00 00 00 00' + '8F FF 88 88 77 77 88 77 88 77 77 70 00 00 00 00' + '8F FF 88 88 87 77 88 87 88 77 77 70 00 00 00 00' + '8F FF 88 87 77 77 88 77 88 77 77 70 00 00 00 00' + '8F FF FF FF FF FF FF FF FF 77 77 70 00 00 00 00' + '8F FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00' + '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' + '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' + '0F 77 77 77 FF FF FF FF 77 77 77 70 00 00 00 00' + '07 77 77 FF 77 77 77 77 FF 77 7F 80 00 00 00 00' + '07 77 7F 77 77 77 77 77 77 F7 7F 80 00 00 00 00' + '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' + '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' + '00 F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' + '00 77 77 77 77 77 77 77 77 77 77 00 00 00 00 00' + '00 7F 77 77 77 77 77 77 77 77 78 00 00 00 00 00' + '00 8F F7 7F FF FF FF FF 77 7F 78 00 00 00 00 00' + '00 8F FF 77 7F FF FF F7 77 FF 70 00 00 00 00 00' + '00 07 F7 FF FF F7 7F FF FF 7F 70 00 00 00 00 00' + '00 07 77 7F FF FF FF FF F7 7F 70 00 00 00 00 00' + '00 08 FF FF FF FF FF FF FF FF 80 00 00 00 00 00' + '00 00 88 88 88 88 88 88 88 88 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF 00 00 00 00 00 00 00 00 FF FE 7F FF FF FE' + '7F FF F0 00 00 0F E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 88 88' + '88 8E E8 88 88 88 00 00 00 00 00 00 00 00 00 07' + '88 88 87 78 80 00 00 7F 08 77 87 87 88 00 00 7F' + '88 77 88 87 78 00 00 7F FF FF FF FF F8 00 00 77' + '77 77 77 77 78 00 00 87 7F FF FF F7 78 00 00 07' + '77 77 77 77 F0 00 00 0F 77 77 77 77 F0 00 00 0F' + '77 77 77 77 70 00 00 07 F7 7F FF 7F 80 00 00 08' + '7F FF FF FF 80 00 00 00 77 77 77 77 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 E0 03' + '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' + '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' + '00 00 F0 0F 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 01 01 00 02 02 02 00 05 05 05 00 06 06' + '06 00 07 07 07 00 08 08 08 00 09 09 09 00 0B 0B' + '0B 00 0C 0C 0C 00 13 13 13 00 18 18 18 00 19 19' + '19 00 1A 1A 1A 00 1E 1E 1E 00 1F 1F 1F 00 20 20' + '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' + '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2A 2A' + '2A 00 2B 2B 2B 00 2C 2C 2C 00 2D 2D 2D 00 2E 2C' + '2D 00 2F 2F 2F 00 34 34 34 00 35 35 35 00 39 39' + '39 00 3B 3B 3B 00 3D 3D 3D 00 3F 3F 3F 00 40 40' + '40 00 41 41 41 00 42 42 42 00 47 47 47 00 48 48' + '48 00 49 49 49 00 4B 4B 4B 00 4F 4F 4F 00 53 53' + '53 00 56 56 56 00 58 58 58 00 59 59 59 00 5A 5A' + '5A 00 5B 5B 5B 00 5D 5D 5D 00 5F 5F 5F 00 61 61' + '61 00 63 63 63 00 64 64 64 00 66 66 66 00 67 67' + '67 00 68 68 68 00 6A 6A 6A 00 6B 6B 6B 00 6C 6C' + '6C 00 70 70 70 00 71 71 71 00 72 72 72 00 73 73' + '73 00 74 74 74 00 75 75 75 00 76 76 76 00 77 77' + '77 00 78 78 78 00 79 79 79 00 7A 7A 7A 00 7C 7C' + '7C 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F 7F 00 2F 99' + '64 00 1C A8 60 00 0A BF 61 00 20 A8 63 00 51 A7' + '7C 00 17 CE 71 00 00 DC DC 00 00 FF FF 00 6B FF' + 'FF 00 80 80 80 00 81 81 81 00 83 83 83 00 84 83' + '84 00 85 85 85 00 87 87 87 00 88 88 88 00 8A 8A' + '8A 00 8C 8C 8C 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' + '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 94 94' + '94 00 97 97 97 00 98 98 98 00 99 99 99 00 9A 9A' + '9A 00 9C 9C 9C 00 9D 9D 9D 00 9F 9F 9F 00 83 AB' + '97 00 96 AB A0 00 90 AF A0 00 99 AC A2 00 95 B2' + 'A3 00 9D B3 A8 00 A0 A0 A0 00 A1 A1 A1 00 A2 A2' + 'A2 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A6 A6' + 'A6 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' + 'AA 00 AB AB AB 00 AD A8 AB 00 AB AC AC 00 AC AC' + 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' + 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B3 B4' + 'B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B8 B4' + 'B6 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BB BB' + 'BB 00 BF BB BD 00 BC BC BC 00 BD BD BD 00 BE BE' + 'BE 00 BF BF BF 00 91 D6 B4 00 91 D8 B5 00 C3 BD' + 'C0 00 C2 BE C0 00 C7 BF C3 00 C0 C0 C0 00 C1 C1' + 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C3 00 C4 C3' + 'C3 00 C4 C3 C4 00 C6 C2 C4 00 C6 C3 C4 00 C6 C3' + 'C5 00 C4 C4 C4 00 C5 C4 C4 00 C5 C5 C5 00 C7 C4' + 'C5 00 C6 C6 C6 00 C7 C7 C7 00 C8 C8 C8 00 C8 C9' + 'C9 00 C9 C9 C9 00 CA CA CA 00 CB CB CB 00 CC CC' + 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' + 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' + 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' + 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' + 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' + 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' + 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' + 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4' + 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' + 'F8 00 F9 F9 F9 00 FA FA FA 00 FC FC FC 00 FF FF' + 'FF 00 00 00 00 00 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 52 52 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 55 55' + '55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55' + '55 55 55 55 52 53 53 52 55 55 55 55 55 55 55 55' + '55 55 55 55 55 55 55 55 55 55 55 55 55 55 9B 9B' + '9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B' + '9B 9B 9B 9B 54 54 54 54 9B 9B 9B 9B 9B 9B 9B 9B' + '9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 9B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 54 54 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9B 9B E1 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9B 9B E1 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 E1 E1 E1 E1 11 1A 19 1A 19 19 19 19 19' + '19 19 19 19 19 19 18 18 18 18 18 18 18 18 18 19' + '19 19 1C 1C 0A E1 E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 E1 E1 14 61 AE B1 AF B2 B1 B0 AF AD AA' + 'A9 A7 A5 9E 9D 9D 9E 9B 9C 95 95 92 93 8F 90 89' + '88 8C 81 7F 7E 35 07 E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 01 5C CF CC CB B9 59 5B 62 66 74 81' + '8F 9B 9E A9 AF AE AE BA AE B7 AF BB B0 B8 AA AC' + 'A2 71 4F 4D 6E 91 2B E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 0C AA D0 C6 CA AF 21 23 2D 3F 5A 62' + '6A 77 7A 80 8B 7B 69 93 67 8B 73 9E 75 93 66 A6' + '9A 50 51 4E 4C 98 58 01 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 17 B5 CE C8 CB B1 27 33 46 5A 60 65' + '72 79 7C 82 8E 76 61 8D 5C 83 64 95 65 8B 5B A0' + 'A4 70 96 97 6C 9F 5F 01 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 16 B5 D0 CA CB B5 39 41 4A 59 5F 65' + '72 79 7C 82 8F 6B 57 87 48 7A 5A 90 5C 86 46 9D' + 'A5 A3 6F 6D 99 A5 5E 01 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 16 B5 D2 CB CC BA 3D 3E 49 59 5F 65' + '72 79 7C 82 90 66 40 81 3A 72 45 8B 48 7D 38 9D' + 'A9 A1 A8 A2 95 A7 5E 01 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 15 B5 D3 CD CF BA 3A 3C 45 56 5C 63' + '69 75 78 7D 8E 61 37 77 31 66 3B 85 3D 76 2E 9C' + 'AB A7 9E 9D 9C A9 5F 01 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 15 B6 D6 CF CE C3 79 79 7D 82 84 87' + '8A 8E 8E 8F 93 8B 85 94 83 8F 85 94 84 8F 7D A7' + 'AB A9 A5 9E 9D AD 5F E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 14 B7 D7 CF CF CE D1 CF CD CC CA C8' + 'C6 C5 C3 C2 BF BF C0 BC BD BA BA B6 B6 B3 B4 AF' + 'AE AD AA A5 9B AE 5F E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 14 B7 DB DC DA DA DA D9 D9 D8 D8 D7' + 'D7 D7 D6 D6 D5 D5 D5 D4 D4 D4 D3 D3 D2 D2 D1 D1' + 'D1 D0 D0 CF C4 B4 5E E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 13 BA E0 CD C5 C6 C6 C4 C3 C3 C3 C3' + 'C3 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4' + 'C6 C7 C7 C7 DC D3 5D E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 13 C2 DC BD A5 90 95 BC BE BD BD BD' + 'BD BD BD BD BD BD BD BD BD BD BD BD BD BD BD BF' + 'B3 92 90 B5 C2 E0 68 E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 0F BE D7 A9 7B 8B 84 9E BE BC BC BC' + 'BC BC BB BB BB BB BB BB BB BB BC BC BC BC BD B6' + '7A 8A 85 89 BC DF 69 E1 E1 00 00 00 00 00 00 00' + '00 00 E1 E1 03 9D DA 92 86 9E 7D 90 BC B9 B9 B9' + 'B8 B7 B7 B9 BB BC BC BB B9 B7 B7 B7 B8 B9 BB AD' + '78 9E 87 81 BA D9 43 E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 76 D8 B3 A7 B6 95 AD B7 B6 B4 B7' + 'C1 C5 C7 CA CE D1 D1 CF CB C8 C6 C2 B8 B4 B6 B7' + 'A7 B4 9D 95 BD CC 2D E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 4A D3 B5 B3 AF B3 B5 B2 B3 C3 D4' + 'D0 C5 C2 C1 C0 BF BF C0 C1 C2 C5 D0 D5 C5 B5 B2' + 'B4 AF B2 B5 BD B8 23 E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 2F CD B4 B1 B1 B1 AE BA D1 CA C0' + 'B8 B9 BA BA BA BA BA BA BA BA B9 B9 BF C8 D1 BE' + 'AE B1 B1 AF C3 8D 12 E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 24 BB B6 AE AF AE B8 CD C0 B4 B5' + 'B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B6 B5 B4 BC CE' + 'BC AD AE AD C4 72 06 E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 12 8B BF AE AF B2 C8 B8 B3 B5 B4' + 'B4 B4 B4 B3 B1 B2 B2 B2 B2 B2 B2 B2 B2 B2 B0 B4' + 'C6 B3 AA AD C6 55 E1 E1 E1 00 00 00 00 00 00 00' + '00 00 00 E1 E1 05 6B C1 B0 B1 BF BA B2 B4 B4 B4' + 'B4 B4 B4 B3 B0 AD AE AE AE AE AE AE AE AE AE AB' + 'B3 BE AA AD C6 30 E1 E1 E1 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 57 C1 B3 B5 BF B5 B4 B4 B4 B4' + 'B4 B4 B4 B4 B3 AD A7 A9 A9 A9 A9 A9 A9 A9 A9 A9' + 'AA B7 AB AD C2 26 E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 33 C0 B5 B6 B8 B5 B5 B5 B5 B5' + 'B5 B5 B5 B5 B5 B4 AB 9E 9E 9E A5 A5 A5 A5 A5 A5' + 'A5 AA A7 AF B0 1B E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 25 BC B8 B6 B4 B7 B7 B7 B7 B7' + 'B7 B7 B7 B7 B7 B7 B7 B1 AA A5 9D 9C 9B 9C 9C 9C' + '9D 95 9B B2 86 0D E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 1A B0 BA B9 B0 B9 BA BA BA BA' + 'BA BA BA BA BA BA BA BB BA B9 B7 B3 B0 AD A9 A5' + '9D 87 93 B4 67 07 E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 0B 84 BF BF B4 B6 BF BD BE BE' + 'BE BE BE BE BE BE BE BE BE BE BE BF BF BE BD BD' + 'B3 A7 B0 AE 47 02 E1 E1 00 00 00 00 00 00 00 00' + '00 00 00 00 E1 E1 06 65 C0 C3 C0 B2 BA C2 C1 C1' + 'C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C1 C2 BC' + 'B2 C1 C0 A9 2C E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 E1 E1 44 B7 C6 C5 C2 B2 BB C5 C6' + 'C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C4 C5 C5 BD B1' + 'BE C7 BD 90 20 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 E1 E1 2A AD C9 C7 C8 C5 BB B6 BE' + 'C8 C9 C8 C8 C8 C8 C8 C8 C8 C8 C9 C9 C0 B6 BA C4' + 'C8 CA BA 7A 10 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 E1 E1 1F 93 CA CA CA CB CB C3 B6' + 'B7 C2 C7 C7 C8 C8 C8 C8 C7 C7 C2 B8 B5 C1 CB CB' + 'CA CC B8 68 08 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 E1 E1 0E 7D C8 D1 CB CA D0 CF CE' + 'C8 C4 C3 C3 C1 C0 C0 C1 C3 C3 C3 C6 CD D0 CE C9' + 'CF CF BA 5C E1 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 E1 E1 06 67 C8 C3 93 9C BA D0 D1' + 'D1 D2 D2 D1 D0 CF CF D0 D1 D2 D2 D1 D2 C8 9D 94' + 'B5 D0 B8 42 E1 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E1 E1 5E C4 A5 86 8D 86 CF D5' + 'D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D4 D7 B9 84 8A' + '8B CF B1 34 E1 E1 E1 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E1 E1 36 B2 C1 C0 B9 C8 DD DD' + 'DD DD DD DD DD DD DD DD DD DD DD DD DE D6 C3 BC' + 'C0 BB 84 1E E1 E1 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E1 E1 0C 55 94 B7 BB BF BC BC' + 'BC BC BC BC BC BC BC BC BC BC BC BC BC BD BD BB' + 'B1 84 32 04 E1 E1 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E1 E1 E1 09 22 29 28 28 28 28' + '28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 29' + '29 1D 02 E1 E1 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1' + 'E1 E1 E1 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FE 3F FF FF 00 00 FF FF' + 'FE 3F FF FF 00 00 FF FF FE 3F FF FF 00 00 FC 00' + '00 00 00 7F 00 00 F8 00 00 00 00 3F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' + '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0E E0 00 00 00 00 00 00 00 00 00 00 00 88 88' + '88 88 88 88 88 88 88 88 88 EE EE 88 88 88 88 88' + '88 88 88 88 88 88 77 77 77 77 77 77 77 77 77 77' + '77 EE EE 77 77 77 77 77 77 77 77 77 77 77 00 00' + '00 00 00 00 00 00 00 00 00 0E E0 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 07 70 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 07 70 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' + '00 08 FF F7 88 88 77 77 77 77 77 77 77 77 77 77' + '66 87 80 00 00 00 00 00 00 07 FF F7 00 88 88 87' + '77 77 87 87 77 77 87 78 66 67 80 00 00 00 00 00' + '00 07 FF F7 88 88 88 77 77 77 87 87 87 87 87 77' + '77 87 80 00 00 00 00 00 00 07 FF F7 88 88 88 77' + '77 78 87 87 87 87 87 77 77 77 80 00 00 00 00 00' + '00 07 FF F7 88 88 88 77 77 78 87 87 87 87 87 77' + '77 77 80 00 00 00 00 00 00 07 FF F7 88 88 88 87' + '77 78 87 88 87 87 87 77 77 77 80 00 00 00 00 00' + '00 07 FF F7 77 77 77 77 77 77 77 77 77 77 77 77' + '77 77 80 00 00 00 00 00 00 07 FF FF FF FF FF FF' + '77 77 77 77 77 77 77 77 77 77 80 00 00 00 00 00' + '00 07 FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF F7 80 00 00 00 00 00 00 07 FF FF FF 77 77 7F' + 'FF FF FF FF FF FF FF FF FF FF 80 00 00 00 00 00' + '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 7F 80 00 00 00 00 00' + '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 7F' + 'FF FF FF FF F7 77 77 77 77 7F 80 00 00 00 00 00' + '00 08 F7 77 77 77 7F FF 77 77 77 77 FF FF 77 77' + '77 77 00 00 00 00 00 00 00 08 F7 77 77 7F F7 77' + '77 77 77 77 77 7F F7 77 77 77 00 00 00 00 00 00' + '00 00 77 77 77 F7 77 77 77 77 77 77 77 77 7F 77' + '77 F7 00 00 00 00 00 00 00 00 77 77 7F 77 77 77' + '77 77 77 77 77 77 77 F7 77 F8 00 00 00 00 00 00' + '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 F8 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' + '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 70 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' + '00 00 07 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 00 00 07 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' + '00 00 08 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 00 00 08 7F F7 77 77 77' + '77 77 77 77 77 77 77 7F 77 00 00 00 00 00 00 00' + '00 00 08 7F FF F7 77 77 77 77 77 77 77 77 7F FF' + '77 00 00 00 00 00 00 00 00 00 00 7F FF FF 77 77' + '77 77 77 77 77 77 FF FF 78 00 00 00 00 00 00 00' + '00 00 00 7F FF FF FF FF 77 77 77 77 7F FF FF FF' + '78 00 00 00 00 00 00 00 00 00 00 8F 77 77 FF FF' + 'FF FF FF FF FF FF 77 7F 78 00 00 00 00 00 00 00' + '00 00 00 8F 77 77 FF FF FF FF FF FF FF F7 77 7F' + '78 00 00 00 00 00 00 00 00 00 00 87 77 7F FF FF' + 'FF FF FF FF FF FF 77 77 70 00 00 00 00 00 00 00' + '00 00 00 08 77 77 77 77 77 77 77 77 77 77 77 77' + '80 00 00 00 00 00 00 00 00 00 00 00 08 88 88 88' + '88 88 88 88 88 88 88 80 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FE 3F FF FF 00 00 FF FF FE 3F FF FF 00 00 FF FF' + 'FE 3F FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' + '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' + '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' + '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 48 00 00' + '00 78 00 00 00 78 00 00 00 48 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 DC DC FF 00 DC' + 'DC FF 00 00 00 B4 00 00 00 9C 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 00 DC DC FF 00 FF FF FF 00 FF' + 'FF FF 00 DC DC FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF 6B FF FF FF 6B FF FF FF 6B FF' + 'FF FF 6B FF FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 6B FF FF FF 6B FF' + 'FF FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 C0 C0 C0 FF C0 C0' + 'C0 FF 00 00 00 92 00 00 00 37 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 C0 C0 C0 FF C0 C0' + 'C0 FF 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 35 00 00 00 18 00 00' + '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' + '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F1 00 00 00 B1 00 00' + '00 5C 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' + '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' + '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' + '2D FF 2E 2C 2D FF 13 13 13 FF 00 00 00 FF 00 00' + '00 F6 00 00 00 69 00 00 00 09 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' + '90 FF CA CA CA FF CD CD CD FF CB CB CB FF CE CE' + 'CE FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' + 'C9 FF C7 C7 C7 FF C6 C6 C6 FF C5 C5 C5 FF C4 C4' + 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2 C2 FF C3 C3' + 'C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF BF FF BF BF' + 'BF FF BC BC BC FF BD BD BD FF BA BA BA FF BB BB' + 'BB FF B5 B5 B5 FF B3 B4 B3 FF B8 B4 B6 FF AD AD' + 'AD FF AB AC AC FF AD A8 AB FF 63 63 63 FF 09 09' + '09 FF 00 00 00 EF 00 00 00 42 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF EB EB' + 'EB FF E8 E8 E8 FF E7 E7 E7 FF D5 D5 D5 FF 85 85' + '85 FF 88 88 88 FF 92 92 92 FF 98 98 98 FF A2 A2' + 'A2 FF AD AD AD FF BA BA BA FF C0 C0 C0 FF C3 C3' + 'C3 FF C6 C6 C6 FF CB CB CB FF CA CA CA FF CA CA' + 'CA FF D6 D6 D6 FF CA CA CA FF D3 D3 D3 FF CB CB' + 'CB FF D7 D7 D7 FF CC CC CC FF D4 D4 D4 FF C7 C7' + 'C7 FF C8 C9 C9 FF C6 C2 C4 FF 9D B3 A8 FF 20 A8' + '63 FF 1C A8 60 FF 90 AF A0 FF BF BB BD FF 4F 4F' + '4F FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 15 00 00 00 F0 19 19 19 FF C7 C7 C7 FF EC EC' + 'EC FF E2 E2 E2 FF E6 E6 E6 FF CB CB CB FF 3B 3B' + '3B FF 3F 3F 3F FF 56 56 56 FF 72 72 72 FF 87 87' + '87 FF 92 92 92 FF 9D 9D 9D FF A5 A5 A5 FF A8 A8' + 'A8 FF AC AC AC FF B7 B7 B7 FF A9 A9 A9 FF 9C 9C' + '9C FF BD BD BD FF 99 99 99 FF B7 B7 B7 FF A1 A1' + 'A1 FF C3 C3 C3 FF A3 A3 A3 FF BD BD BD FF 98 98' + '98 FF C5 C4 C4 FF C7 BF C3 FF 51 A7 7C FF 17 CE' + '71 FF 0A BF 61 FF 2F 99 64 FF C3 BD C0 FF 84 83' + '84 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 30 00 00 00 FA 29 29 29 FF D1 D1 D1 FF EA EA' + 'EA FF E4 E4 E4 FF E7 E7 E7 FF CD CD CD FF 47 47' + '47 FF 5F 5F 5F FF 79 79 79 FF 87 87 87 FF 8F 8F' + '8F FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF B9 B9 B9 FF A4 A4 A4 FF 90 90' + '90 FF B8 B8 B8 FF 8A 8A 8A FF AF AF AF FF 94 94' + '94 FF BF BF BF FF 97 97 97 FF B7 B7 B7 FF 88 88' + '88 FF C4 C3 C3 FF C6 C3 C5 FF 95 B2 A3 FF 91 D6' + 'B4 FF 91 D8 B5 FF 83 AB 97 FF C4 C1 C3 FF 8E 8E' + '8E FF 01 01 01 FF 00 00 00 B7 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' + 'EC FF E6 E6 E6 FF E7 E7 E7 FF D1 D1 D1 FF 68 68' + '68 FF 74 74 74 FF 7E 7E 7E FF 85 85 85 FF 8E 8E' + '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF BA BA BA FF 9F 9F 9F FF 83 83' + '83 FF B3 B3 B3 FF 7C 7C 7C FF A8 A8 A8 FF 87 87' + '87 FF BB BB BB FF 8A 8A 8A FF B2 B2 B2 FF 79 79' + '79 FF C2 C2 C2 FF C4 C4 C4 FF C6 C3 C4 FF 99 AC' + 'A2 FF 96 AB A0 FF C2 BE C0 FF C4 C4 C4 FF 8D 8D' + '8D FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' + 'EE FF E7 E7 E7 FF E8 E8 E8 FF D6 D6 D6 FF 70 70' + '70 FF 71 71 71 FF 7D 7D 7D FF 85 85 85 FF 8E 8E' + '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF BB BB BB FF 98 98 98 FF 73 73' + '73 FF AD AD AD FF 6A 6A 6A FF A0 A0 A0 FF 78 78' + '78 FF B7 B7 B7 FF 7C 7C 7C FF AB AB AB FF 67 67' + '67 FF C2 C2 C2 FF C6 C6 C6 FF C4 C3 C4 FF C7 C4' + 'C5 FF C6 C2 C4 FF BF BF BF FF C5 C5 C5 FF 8D 8D' + '8D FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' + 'EF FF E9 E9 E9 FF EB EB EB FF D6 D6 D6 FF 6A 6A' + '6A FF 6C 6C 6C FF 78 78 78 FF 81 81 81 FF 8A 8A' + '8A FF 93 93 93 FF 9C 9C 9C FF A3 A3 A3 FF A6 A6' + 'A6 FF AB AB AB FF B9 B9 B9 FF 90 90 90 FF 66 66' + '66 FF A5 A5 A5 FF 5B 5B 5B FF 98 98 98 FF 6B 6B' + '6B FF B1 B1 B1 FF 70 70 70 FF A4 A4 A4 FF 58 58' + '58 FF C1 C1 C1 FF C8 C8 C8 FF C5 C5 C5 FF C3 C3' + 'C3 FF C2 C2 C2 FF C1 C1 C1 FF C6 C6 C6 FF 8E 8E' + '8E FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' + 'F2 FF EB EB EB FF EA EA EA FF DF DF DF FF A7 A7' + 'A7 FF A7 A7 A7 FF AB AB AB FF AE AE AE FF B0 B0' + 'B0 FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF B9 B9' + 'B9 FF BA BA BA FF BD BD BD FF B7 B7 B7 FF B1 B1' + 'B1 FF BE BE BE FF AF AF AF FF BA BA BA FF B1 B1' + 'B1 FF BE BE BE FF B0 B0 B0 FF BA BA BA FF AB AB' + 'AB FF C5 C5 C5 FF C8 C8 C8 FF C6 C6 C6 FF C4 C4' + 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C9 C9 C9 FF 8E 8E' + '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' + 'F3 FF EB EB EB FF EB EB EB FF EA EA EA FF ED ED' + 'ED FF EB EB EB FF E9 E9 E9 FF E8 E8 E8 FF E6 E6' + 'E6 FF E4 E4 E4 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' + 'DF FF DE DE DE FF DB DB DB FF DB DB DB FF DC DC' + 'DC FF D8 D8 D8 FF D9 D9 D9 FF D6 D6 D6 FF D6 D6' + 'D6 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' + 'D0 FF CB CB CB FF CA CA CA FF C9 C9 C9 FF C7 C7' + 'C7 FF C4 C4 C4 FF C0 C0 C0 FF CA CA CA FF 8E 8E' + '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' + 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' + 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' + 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' + 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF ED ED' + 'ED FF ED ED ED FF ED ED ED FF EC EC EC FF EC EC' + 'EC FF EB EB EB FF E0 E0 E0 FF D0 D0 D0 FF 8D 8D' + '8D FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' + 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' + 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF EF FF 8C 8C' + '8C FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' + 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' + 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF DB DB DB FF CF CF CF FF BC BC BC FF BB BB' + 'BB FF D1 D1 D1 FF DE DE DE FF FF FF FF FF 9A 9A' + '9A FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' + 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' + 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9' + 'D9 FF D2 D2 D2 FF A8 A8 A8 FF B6 B6 B6 FF B1 B1' + 'B1 FF B5 B5 B5 FF D8 D8 D8 FF FC FC FC FF 9C 9C' + '9C FF 00 00 00 FF 00 00 00 AE 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' + 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' + 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' + 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D7 D7' + 'D7 FF C9 C9 C9 FF A6 A6 A6 FF C3 C3 C3 FF B3 B3' + 'B3 FF AD AD AD FF D6 D6 D6 FF F5 F5 F5 FF 76 76' + '76 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' + 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' + 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF DD DD DD FF E1 E1 E1 FF E3 E3' + 'E3 FF E6 E6 E6 FF EA EA EA FF ED ED ED FF ED ED' + 'ED FF EB EB EB FF E7 E7 E7 FF E4 E4 E4 FF E2 E2' + 'E2 FF DE DE DE FF D4 D4 D4 FF D0 D0 D0 FF D2 D2' + 'D2 FF D3 D3 D3 FF C5 C5 C5 FF D0 D0 D0 FF C2 C2' + 'C2 FF BF BF BF FF D9 D9 D9 FF E8 E8 E8 FF 56 56' + '56 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' + 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' + 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF DF DF' + 'DF FF F0 F0 F0 FF EC EC EC FF E1 E1 E1 FF DE DE' + 'DE FF DD DD DD FF DC DC DC FF DB DB DB FF DB DB' + 'DB FF DC DC DC FF DD DD DD FF DE DE DE FF E1 E1' + 'E1 FF EC EC EC FF F1 F1 F1 FF E1 E1 E1 FF D1 D1' + 'D1 FF CE CE CE FF D0 D0 D0 FF CB CB CB FF CE CE' + 'CE FF D1 D1 D1 FF D9 D9 D9 FF D4 D4 D4 FF 3F 3F' + '3F FF 00 00 00 FF 00 00 00 55 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' + 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CA CA CA FF D6 D6 D6 FF ED ED ED FF E6 E6' + 'E6 FF DC DC DC FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF ED ED' + 'ED FF DA DA DA FF CA CA CA FF CD CD CD FF CD CD' + 'CD FF CB CB CB FF DF DF DF FF B8 B8 B8 FF 22 22' + '22 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' + 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' + 'CA FF D4 D4 D4 FF E9 E9 E9 FF DC DC DC FF D0 D0' + 'D0 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D8 D8' + 'D8 FF EA EA EA FF D8 D8 D8 FF C9 C9 C9 FF CA CA' + 'CA FF C9 C9 C9 FF E0 E0 E0 FF A0 A0 A0 FF 08 08' + '08 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' + 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' + 'CE FF E4 E4 E4 FF D4 D4 D4 FF CF CF CF FF D1 D1' + 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF CD CD CD FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CC CC' + 'CC FF D0 D0 D0 FF E2 E2 E2 FF CF CF CF FF C7 C7' + 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 C2 00 00 00 0E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' + '9F FF DD DD DD FF CC CC CC FF CD CD CD FF DB DB' + 'DB FF D6 D6 D6 FF CE CE CE FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF C8 C8 C8 FF CF CF CF FF DA DA DA FF C7 C7' + 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 5A 5A 5A FF 00 00' + '00 FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' + '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF DB DB' + 'DB FF D1 D1 D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF C5 C5' + 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C7 C7 C7 FF D3 D3 D3 FF C8 C8' + 'C8 FF C9 C9 C9 FF DE DE DE FF 42 42 42 FF 00 00' + '00 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' + '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D4 D4' + 'D4 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D0 D0 D0 FF C8 C8' + 'C8 FF C3 C3 C3 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C7 C7 C7 FF C5 C5' + 'C5 FF CB CB CB FF CC CC CC FF 2D 2D 2D FF 00 00' + '00 F8 00 00 00 40 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' + '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF CD CD CD FF C7 C7 C7 FF C4 C4 C4 FF C2 C2' + 'C2 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' + 'C1 FF C1 C1 C1 FF C2 C2 C2 FF BF BF BF FF C0 C0' + 'C0 FF CE CE CE FF B2 B2 B2 FF 1A 1A 1A FF 00 00' + '00 E5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' + '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF CC CC' + 'CC FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D7 D7 D7 FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' + 'D3 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF C6 C6' + 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' + 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' + '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' + '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF D0 D0' + 'D0 FF D2 D2 D2 FF DB DB DB FF D9 D9 D9 FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DB DB DB FF DB DB DB FF DA DA DA FF D9 D9' + 'D9 FF D9 D9 D9 FF CF CF CF FF C5 C5 C5 FF CC CC' + 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' + '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' + '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' + 'DC FF CE CE CE FF D6 D6 D6 FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' + 'DE FF D8 D8 D8 FF CE CE CE FF DD DD DD FF DC DC' + 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' + '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' + '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' + 'E1 FF DE DE DE FF CE CE CE FF D7 D7 D7 FF E1 E1' + 'E1 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF D9 D9' + 'D9 FF CD CD CD FF DA DA DA FF E3 E3 E3 FF D9 D9' + 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' + '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' + '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' + 'E3 FF E4 E4 E4 FF E1 E1 E1 FF D7 D7 D7 FF D2 D2' + 'D2 FF DA DA DA FF E4 E4 E4 FF E5 E5 E5 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E5 E5 E5 FF DC DC DC FF D2 D2 D2 FF D6 D6' + 'D6 FF E0 E0 E0 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' + 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' + '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' + '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF DF DF' + 'DF FF D2 D2 D2 FF D3 D3 D3 FF DE DE DE FF E3 E3' + 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3 E3 FF DE DE' + 'DE FF D4 D4 D4 FF D1 D1 D1 FF DD DD DD FF E7 E7' + 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' + 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' + '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' + 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' + 'EB FF EA EA EA FF E4 E4 E4 FF E0 E0 E0 FF DF DF' + 'DF FF DF DF DF FF DD DD DD FF DC DC DC FF DC DC' + 'DC FF DD DD DD FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E2 E2 E2 FF E9 E9 E9 FF EC EC EC FF EA EA' + 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' + 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' + 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' + 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' + 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' + 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' + 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' + 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' + 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' + 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' + 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' + 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' + 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' + 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' + 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' + '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' + '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' + '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' + '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' + '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FE 1F FF FF 00 00 FF FF' + 'FE 1F FF FF 00 00 FF 00 00 00 00 7F 00 00 FC 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' + '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 DC DC FF 00 DC DC FF 00 00 00 9C 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 00 FF FF FF 00 FF FF FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 6B FF FF FF 6B FF FF FF 00 00 00 30 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 C0 C0 C0 FF C0 C0 C0 FF 00 00 00 37 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 C5 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F1 00 00' + '00 B1 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 21 21' + '21 FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2B 2B' + '2B FF 2B 2B 2B FF 2E 2C 2D FF 13 13 13 FF 00 00' + '00 FF 00 00 00 69 00 00 00 09 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 AD 01 01 01 FF EB EB EB FF E8 E8' + 'E8 FF D5 D5 D5 FF 85 85 85 FF 92 92 92 FF 98 98' + '98 FF AD AD AD FF BA BA BA FF C3 C3 C3 FF C6 C6' + 'C6 FF CA CA CA FF CA CA CA FF CA CA CA FF D3 D3' + 'D3 FF D7 D7 D7 FF CC CC CC FF C7 C7 C7 FF C8 C9' + 'C9 FF 9D B3 A8 FF 20 A8 63 FF 90 AF A0 FF BF BB' + 'BD FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F0 19 19 19 FF EC EC EC FF E2 E2' + 'E2 FF CB CB CB FF 3B 3B 3B FF 56 56 56 FF 72 72' + '72 FF 92 92 92 FF 9D 9D 9D FF A8 A8 A8 FF AC AC' + 'AC FF A9 A9 A9 FF 9C 9C 9C FF 99 99 99 FF B7 B7' + 'B7 FF C3 C3 C3 FF A3 A3 A3 FF 98 98 98 FF C5 C4' + 'C4 FF 51 A7 7C FF 17 CE 71 FF 2F 99 64 FF C3 BD' + 'C0 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 28 28 28 FF EC EC EC FF E6 E6' + 'E6 FF D1 D1 D1 FF 68 68 68 FF 7E 7E 7E FF 85 85' + '85 FF 97 97 97 FF A0 A0 A0 FF AA AA AA FF AE AE' + 'AE FF 9F 9F 9F FF 83 83 83 FF 7C 7C 7C FF A8 A8' + 'A8 FF BB BB BB FF 8A 8A 8A FF 79 79 79 FF C2 C2' + 'C2 FF C6 C3 C4 FF 99 AC A2 FF C2 BE C0 FF C4 C4' + 'C4 FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 28 28 28 FF EE EE EE FF E7 E7' + 'E7 FF D6 D6 D6 FF 70 70 70 FF 7D 7D 7D FF 85 85' + '85 FF 97 97 97 FF A0 A0 A0 FF AA AA AA FF AE AE' + 'AE FF 98 98 98 FF 73 73 73 FF 6A 6A 6A FF A0 A0' + 'A0 FF B7 B7 B7 FF 7C 7C 7C FF 67 67 67 FF C2 C2' + 'C2 FF C4 C3 C4 FF C7 C4 C5 FF BF BF BF FF C5 C5' + 'C5 FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 27 27 27 FF F2 F2 F2 FF EB EB' + 'EB FF DF DF DF FF A7 A7 A7 FF AB AB AB FF AE AE' + 'AE FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF BA BA' + 'BA FF B7 B7 B7 FF B1 B1 B1 FF AF AF AF FF BA BA' + 'BA FF BE BE BE FF B0 B0 B0 FF AB AB AB FF C5 C5' + 'C5 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2 C2 FF C9 C9' + 'C9 FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 26 26 26 FF F3 F3 F3 FF EB EB' + 'EB FF EA EA EA FF ED ED ED FF E9 E9 E9 FF E8 E8' + 'E8 FF E4 E4 E4 FF E2 E2 E2 FF DF DF DF FF DE DE' + 'DE FF DB DB DB FF DC DC DC FF D9 D9 D9 FF D6 D6' + 'D6 FF D2 D2 D2 FF D2 D2 D2 FF D0 D0 D0 FF CB CB' + 'CB FF C9 C9 C9 FF C7 C7 C7 FF C0 C0 C0 FF CA CA' + 'CA FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 24 24 24 FF FF FF FF FF E9 E9' + 'E9 FF E2 E2 E2 FF E2 E2 E2 FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E3 E3 E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF' + 'EF FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FA 24 24 24 FF F8 F8 F8 FF D9 D9' + 'D9 FF BB BB BB FF BF BF BF FF DA DA DA FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF DB DB' + 'DB FF BC BC BC FF BB BB BB FF DE DE DE FF FF FF' + 'FF FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 D0 05 05 05 FF F6 F6 F6 FF BC BC' + 'BC FF C3 C3 C3 FF AB AB AB FF D8 D8 D8 FF D5 D5' + 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D5 D5' + 'D5 FF D8 D8 D8 FF D8 D8 D8 FF D5 D5 D5 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D7 D7 D7 FF C9 C9' + 'C9 FF C3 C3 C3 FF B3 B3 B3 FF D6 D6 D6 FF F5 F5' + 'F5 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9C 00 00 00 FF F4 F4 F4 FF CF CF' + 'CF FF D2 D2 D2 FF BF BF BF FF D3 D3 D3 FF D2 D2' + 'D2 FF D3 D3 D3 FF DD DD DD FF E3 E3 E3 FF E6 E6' + 'E6 FF ED ED ED FF ED ED ED FF E7 E7 E7 FF E4 E4' + 'E4 FF DE DE DE FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' + 'D3 FF D0 D0 D0 FF C2 C2 C2 FF D9 D9 D9 FF E8 E8' + 'E8 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 59 00 00 00 FF E9 E9 E9 FF D0 D0' + 'D0 FF CD CD CD FF CD CD CD FF D6 D6 D6 FF ED ED' + 'ED FF DC DC DC FF D4 D4 D4 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D5 D5 D5 FF DB DB DB FF ED ED ED FF DA DA' + 'DA FF CD CD CD FF CD CD CD FF DF DF DF FF B8 B8' + 'B8 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3E 00 00 00 FE D7 D7 D7 FF D2 D2' + 'D2 FF CB CB CB FF CA CA CA FF E9 E9 E9 FF DC DC' + 'DC FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D8 D8 D8 FF EA EA' + 'EA FF C9 C9 C9 FF CA CA CA FF E0 E0 E0 FF A0 A0' + 'A0 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 E1 9F 9F 9F FF DD DD' + 'DD FF CD CD CD FF DB DB DB FF CE CE CE FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' + 'CF FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF C8 C8' + 'C8 FF DA DA DA FF C7 C7 C7 FF E2 E2 E2 FF 5A 5A' + '5A FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 B2 83 83 83 FF DD DD' + 'DD FF D1 D1 D1 FF DB DB DB FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF D3 D3 D3 FF C8 C8 C8 FF DE DE DE FF 42 42' + '42 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4B 41 41 41 FF D8 D8' + 'D8 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C7 C7 C7 FF C4 C4' + 'C4 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' + 'C1 FF BF BF BF FF C0 C0 C0 FF B2 B2 B2 FF 1A 1A' + '1A FF 00 00 00 28 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1A 2C 2C 2C FF CC CC' + 'CC FF D5 D5 D5 FF CC CC CC FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF CF CF CF FF CC CC CC FF C6 C6 C6 FF C4 C4' + 'C4 FF B3 B3 B3 FF BD BD BD FF 99 99 99 FF 09 09' + '09 FF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 08 08 08 FF 97 97' + '97 FF DF DF DF FF DC DC DC FF D6 D6 D6 FF DE DE' + 'DE FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DE DE DE FF D8 D8' + 'D8 FF DD DD DD FF DC DC DC FF 53 53 53 FF 00 00' + '00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 77 77' + '77 FF E2 E2 E2 FF E1 E1 E1 FF CE CE CE FF D7 D7' + 'D7 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF D9 D9 D9 FF CD CD' + 'CD FF E3 E3 E3 FF D9 D9 D9 FF 39 39 39 FF 00 00' + '00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 35 35' + '35 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7' + 'E7 FF D2 D2 D2 FF D3 D3 D3 FF E3 E3 E3 FF E3 E3' + 'E3 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3' + 'E3 FF D4 D4 D4 FF D1 D1 D1 FF E7 E7 E7 FF E7 E7' + 'E7 FF E8 E8 E8 FF D4 D4 D4 FF 0B 0B 0B FF 00 00' + '00 ED 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 1E 1E' + '1E FF E4 E4 E4 FF ED ED ED FF E6 E6 E6 FF EC EC' + 'EC FF EA EA EA FF E4 E4 E4 FF DF DF DF FF DF DF' + 'DF FF DC DC DC FF DC DC DC FF DF DF DF FF DF DF' + 'DF FF E2 E2 E2 FF E9 E9 E9 FF EA EA EA FF E5 E5' + 'E5 FF EB EB EB FF D6 D6 D6 FF 00 00 00 FF 00 00' + '00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 AE 00 00' + '00 FF E0 E0 E0 FF C4 C4 C4 FF B8 B8 B8 FF B2 B2' + 'B2 FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F3 F3 F3 FF B0 B0 B0 FF B6 B6' + 'B6 FF EB EB EB FF CD CD CD FF 00 00 00 FF 00 00' + '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00' + '00 FF CE CE CE FF DD DD DD FF D5 D5 D5 FF E4 E4' + 'E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF DF DF DF FF D8 D8' + 'D8 FF D7 D7 D7 FF B0 B0 B0 FF 00 00 00 FF 00 00' + '00 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00' + '00 9C 0C 0C 0C FF 3D 3D 3D FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 49 49' + '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 5C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 06 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF 00 00 00 00 00 00' + '00 00 FF FE 3F FF FF FE 3F FF F0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 F0 00 00 0F F0 00 00 0F F0 00' + '00 0F F0 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 3F FC 00' + '00 7F FF FF FF FF 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 78 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF 6B FF FF FF 6B FF' + 'FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 26 26 26 FF CD CD CD FF CD CD' + 'CD FF C9 C9 C9 FF C5 C5 C5 FF C2 C2 C2 FF C0 C0' + 'C0 FF BF BF BF FF BA BA BA FF B3 B4 B3 FF AB AC' + 'AC FF 09 09 09 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 30 D1 D1 D1 FF E7 E7 E7 FF 5F 5F' + '5F FF 8F 8F 8F FF A7 A7 A7 FF B9 B9 B9 FF B8 B8' + 'B8 FF 94 94 94 FF B7 B7 B7 FF C6 C3 C5 FF 91 D8' + 'B5 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 33 D1 D1 D1 FF EB EB EB FF 6C 6C' + '6C FF 8A 8A 8A FF A3 A3 A3 FF B9 B9 B9 FF A5 A5' + 'A5 FF 6B 6B 6B FF A4 A4 A4 FF C8 C8 C8 FF C2 C2' + 'C2 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 33 D3 D3 D3 FF F6 F6 F6 FF F5 F5' + 'F5 FF F4 F4 F4 FF F3 F3 F3 FF F1 F1 F1 FF F0 F0' + 'F0 FF EF EF EF FF EE EE EE FF ED ED ED FF EB EB' + 'EB FF 8D 8D 8D FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 25 DA DA DA FF A9 A9 A9 FF C3 C3' + 'C3 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' + 'D7 FF D8 D8 D8 FF D8 D8 D8 FF A8 A8 A8 FF B5 B5' + 'B5 FF 9C 9C 9C FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 7E 7E 7E FF CF CF CF FF D1 D1' + 'D1 FF DF DF DF FF E1 E1 E1 FF DC DC DC FF DC DC' + 'DC FF E1 E1 E1 FF E1 E1 E1 FF D0 D0 D0 FF D1 D1' + 'D1 FF 3F 3F 3F FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 22 22 FF CA CA CA FF E4 E4' + 'E4 FF D1 D1 D1 FF D0 D0 D0 FF CD CD CD FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF E2 E2 E2 FF C9 C9' + 'C9 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF C3 C3' + 'C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF CB CB' + 'CB FF 00 00 00 F8 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 D8 DB DB DB FF D2 D2' + 'D2 FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF CF CF CF FF CA CA' + 'CA FF 00 00 00 B8 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 89 C9 C9 C9 FF E4 E4' + 'E4 FF D2 D2 D2 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4' + 'E4 FF E5 E5 E5 FF D2 D2 D2 FF E4 E4 E4 FF A8 A8' + 'A8 FF 00 00 00 4E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 99 99 99 FF BD BD' + 'BD FF EC EC EC FF EE EE EE FF EC EC EC FF EC EC' + 'EC FF EE EE EE FF E4 E4 E4 FF D1 D1 D1 FF 75 75' + '75 FF 00 00 00 06 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 19 19 19 FF D3 D3' + 'D3 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D9 D9 D9 FF CD CD CD FF 06 06' + '06 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E0 03 00 00 C0 03 00 00 80 03' + '00 00 80 03 00 00 80 03 00 00 80 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 E0 07 00 00 F0 0F 00 00' +} */ + +/* BINRES netdrive2.ico */ +10 ICON netdrive2.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 8E 11 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 5E 23 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 C6 29 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 6E 4F 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 02 02 02 00 04 04 04 00 05 06 06 00 06 06' + '06 00 00 00 0D 00 09 09 09 00 0A 0A 0A 00 0C 0C' + '0C 00 12 12 12 00 14 14 14 00 15 15 15 00 16 16' + '16 00 1F 1F 10 00 1D 1D 1D 00 00 00 20 00 00 00' + '2C 00 00 00 2D 00 21 21 21 00 22 22 22 00 23 23' + '23 00 24 24 24 00 25 25 25 00 26 26 26 00 38 38' + '38 00 39 39 39 00 3B 3B 3B 00 43 43 43 00 46 46' + '46 00 4A 4A 4A 00 54 4C 50 00 53 53 53 00 55 55' + '55 00 56 56 56 00 59 59 52 00 5A 5A 53 00 5C 5C' + '55 00 5D 5D 56 00 58 58 58 00 59 59 59 00 5A 58' + '59 00 5A 5A 5A 00 5B 5B 5B 00 5C 5C 5C 00 5D 5D' + '5D 00 5E 5E 5E 00 65 58 5F 00 60 60 60 00 61 61' + '61 00 62 62 62 00 64 64 64 00 67 67 67 00 69 69' + '69 00 71 71 71 00 72 72 72 00 73 73 73 00 75 75' + '75 00 78 78 78 00 7A 7A 7A 00 7B 7B 7B 00 7C 7C' + '7C 00 7F 7F 7F 00 24 A7 64 00 3C AD 74 00 25 DC' + '7F 00 7C 7C A3 00 00 00 C9 00 00 00 CD 00 00 00' + 'D3 00 00 00 D8 00 00 00 FF 00 2B 2B FF 00 7D AA' + '94 00 81 81 81 00 83 83 83 00 89 89 89 00 8A 8A' + '8A 00 8B 8B 8B 00 8F 8F 8F 00 91 89 8C 00 90 90' + '90 00 91 91 91 00 94 94 94 00 95 95 95 00 97 97' + '97 00 99 99 99 00 9A 9A 9A 00 9C 9C 9C 00 9D 9D' + '9D 00 9E 9E 9E 00 9F 9F 9F 00 94 B6 A4 00 93 BD' + 'A9 00 A0 A0 A0 00 A1 A1 A1 00 A3 A3 A3 00 A4 A4' + 'A4 00 A5 A5 A5 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' + 'AA 00 AC AC AC 00 AD AD AD 00 AE AE AE 00 AF AF' + 'AF 00 B8 B8 A7 00 AA AA BC 00 AD B9 B3 00 B0 B0' + 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B4 B4' + 'B4 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B9 B9' + 'B9 00 BC BC BC 00 BD BD BD 00 BE BE BE 00 BF BF' + 'BF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C0 C1 00 C2 C2' + 'C2 00 C3 C3 C3 00 C4 C1 C2 00 C5 C2 C4 00 C4 C4' + 'C4 00 C5 C5 C5 00 C6 C5 C6 00 C6 C6 C6 00 C8 C3' + 'C5 00 CC C4 C8 00 C8 C8 C8 00 C9 C9 C9 00 CB C9' + 'CA 00 CA CA CA 00 CB CB CB 00 CC CC CC 00 CD CD' + 'CD 00 CE CE CE 00 CF CF CF 00 D2 C1 CA 00 D3 C8' + 'CD 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3' + 'D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7' + 'D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA DA 00 DB DB' + 'DB 00 DC DC DC 00 DD DD DD 00 DE DE DE 00 DF DF' + 'DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3' + 'E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7' + 'E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' + 'EB 00 EC EC EC 00 ED ED ED 00 EE EE EE 00 EF EF' + 'EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2 F2 00 F4 F4' + 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' + 'F8 00 F9 F9 F9 00 FC FC FC 00 FD FD FD 00 FF FF' + 'FF 00 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 08 6C' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 6E 65 74 64 72 69 76 65 32' + '2E 69 63 6F 00 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 42 45 BD 00 45' + '42 BD 00 00 00 00 00 00 00 00 00 00 00 00 BD BD' + 'BD BD BD BD BD BD BD BD BD BD BD 05 46 43 43 46' + '05 BD BD BD BD BD BD BD BD BD BD BD BD BD 6E 6E' + '6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 69 41 46 46 41' + '69 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 6E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 47 46 46 47' + 'BD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 44 46 6A 6A 46' + '44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 BD BD BD BD BD BD BD BD BD 10 0F 0D 0D 0F' + '11 BD BD BD BD BD BD BD BD 00 00 00 00 00 00 00' + '00 BD BD 0A 2D 2D 33 32 31 2F 2D 25 24 21 20 23' + '22 26 26 26 21 28 2E 1E 06 BD 00 00 00 00 00 00' + '00 BD 0A 79 B5 AB 63 70 74 7A 91 93 97 98 9D 9D' + '9C 9E 9B 99 8D 84 3F 5C 4F 03 BD 00 00 00 00 00' + '00 BD 21 B7 A7 A5 0E 1D 3A 4D 58 5F 68 64 5A 57' + '64 72 61 54 90 48 40 3E 8F 17 BD 00 00 00 00 00' + '00 BD 2C B3 A8 A4 1F 3B 4C 52 5F 63 70 64 53 50' + '5D 6C 56 4B 88 7B 5B 6B 7E 17 BD 00 00 00 00 00' + '00 BD 2A B4 AA A9 2B 36 4A 4E 5A 61 6F 5E 39 35' + '4D 5D 49 33 8A 82 85 7F 79 16 BD 00 00 00 00 00' + '00 BD 2A B6 AD A9 49 50 56 5D 63 66 70 65 57 55' + '5F 67 58 51 86 81 7A 7A 7D 15 BD 00 00 00 00 00' + '00 BD 29 B8 B1 B0 BA B9 B5 B3 AF AD AA A8 AB A9' + 'A5 A1 A1 A1 97 95 93 8A 80 14 BD 00 00 00 00 00' + '00 BD 27 BC B0 AE AD A8 A8 A7 A8 A8 A9 A8 A8 A8' + 'A8 A8 A8 A7 AA AE AD B9 96 12 BD 00 00 00 00 00' + '00 BD 2C BC 83 6D 75 99 98 98 98 98 97 97 97 97' + '98 98 98 99 92 71 71 97 B6 17 BD 00 00 00 00 00' + '00 BD 1B BC 68 73 62 92 98 96 94 92 95 96 96 95' + '92 93 95 9B 74 6E 63 86 A9 0E BD 00 00 00 00 00' + '00 BD 14 A9 8D 91 83 91 8D 9A A5 A4 A7 AB AB A8' + 'A5 A6 9C 8E 8E 8E 80 99 77 07 BD 00 00 00 00 00' + '00 BD 09 92 92 8B 8C 8C AA A7 9B 99 98 97 97 98' + '99 9C A7 AA 91 89 8C A3 54 BD BD 00 00 00 00 00' + '00 BD 01 60 99 87 8C A6 94 8D 91 91 8E 91 91 91' + '91 91 8C 8E A7 8E 83 AA 30 BD BD 00 00 00 00 00' + '00 BD BD 38 A5 87 9B 93 8D 91 8E 91 8C 89 8A 8A' + '8A 8A 8A 89 8B 9B 7D B0 19 BD BD 00 00 00 00 00' + '00 00 BD 1C AB 8E 99 8D 91 91 91 91 91 8B 7C 7D' + '80 81 81 81 7D 8C 81 AC 0B BD 00 00 00 00 00 00' + '00 00 BD 13 AF 92 92 93 92 92 92 92 92 93 8C 80' + '79 78 77 79 79 79 83 97 01 BD 00 00 00 00 00 00' + '00 00 BD 02 9F 9A 8B 99 97 98 98 98 98 98 98 99' + '98 95 91 8B 87 73 87 6F BD BD 00 00 00 00 00 00' + '00 00 BD BD 81 A4 94 94 9F 9D 9C 9C 9C 9C 9C 9C' + '9D 9D 9E A0 97 94 9E 4B BD BD 00 00 00 00 00 00' + '00 00 00 BD 51 A7 A4 96 97 A1 A4 A2 A2 A2 A2 A2' + 'A2 A4 A0 99 93 A8 99 26 BD 00 00 00 00 00 00 00' + '00 00 00 BD 33 A7 A8 A8 A0 92 9A A3 A4 A5 A5 A4' + 'A3 9A 92 A0 A9 AC 8D 18 BD 00 00 00 00 00 00 00' + '00 00 00 BD 1A 9E AB 9A AD AF A7 A3 A2 9F 9F A2' + 'A3 A5 AF A5 9C B2 83 0E BD 00 00 00 00 00 00 00' + '00 00 00 BD 17 9F 7A 66 81 B3 B1 B1 B1 B0 B0 B1' + 'B1 B1 AE 71 66 A8 76 0C BD 00 00 00 00 00 00 00' + '00 00 00 BD 08 59 AD A5 B6 BB BA BA BA BA BA BA' + 'BA BA BA B2 A7 A6 37 BD BD 00 00 00 00 00 00 00' + '00 00 00 BD BD 0C 38 3B 3A 39 39 39 39 39 39 39' + '39 39 39 3A 3C 34 04 BD 00 00 00 00 00 00 00 00' + '00 00 00 00 BD BD BD BD BD BD BD BD BD BD BD BD' + 'BD BD BD BD BD BD BD 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' + '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF FF F8' + '1F FF F0 00 00 1F E0 00 00 0F E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 06 06 06 00 09 09' + '09 00 19 19 19 00 22 22 22 00 26 26 26 00 3F 3F' + '3F 00 5F 5F 5F 00 6B 6B 6B 00 6C 6C 6C 00 75 75' + '75 00 7E 7E 7E 00 7F 7F 7F 00 00 00 FF 00 8A 8A' + '8A 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F 8F 00 94 94' + '94 00 99 99 99 00 9C 9C 9C 00 A3 A3 A3 00 A4 A4' + 'A4 00 A5 A5 A5 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9' + 'A9 00 AB AC AC 00 B3 B4 B3 00 B5 B5 B5 00 B7 B7' + 'B7 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BD BD' + 'BD 00 BF BF BF 00 91 D8 B5 00 C0 C0 C0 00 C2 C2' + 'C2 00 C3 C3 C3 00 C6 C3 C5 00 C4 C4 C4 00 C5 C5' + 'C5 00 C8 C8 C8 00 C9 C9 C9 00 CA CA CA 00 CB CB' + 'CB 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' + 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D7 D7' + 'D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA DA 00 DB DB' + 'DB 00 DC DC DC 00 DF DF DF 00 E1 E1 E1 00 E2 E2' + 'E2 00 E4 E4 E4 00 E5 E5 E5 00 E7 E7 E7 00 EB EB' + 'EB 00 EC EC EC 00 ED ED ED 00 EE EE EE 00 EF EF' + 'EF 00 F0 F0 F0 00 F1 F1 F1 00 F3 F3 F3 00 F4 F4' + 'F4 00 F5 F5 F5 00 F6 F6 F6 00 00 00 00 00 8F 8F' + '8F 00 91 89 8C 00 90 90 90 00 91 91 91 00 94 94' + '94 00 95 95 95 00 97 97 97 00 99 99 99 00 9A 9A' + '9A 00 9C 9C 9C 00 9D 9D 9D 00 9E 9E 9E 00 9F 9F' + '9F 00 94 B6 A4 00 93 BD A9 00 A0 A0 A0 00 A1 A1' + 'A1 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A8 A8' + 'A8 00 A9 A9 A9 00 AA AA AA 00 AC AC AC 00 AD AD' + 'AD 00 AE AE AE 00 AF AF AF 00 B8 B8 A7 00 AA AA' + 'BC 00 AD B9 B3 00 B0 B0 B0 00 B1 B1 B1 00 B2 B2' + 'B2 00 B3 B3 B3 00 B4 B4 B4 00 B5 B5 B5 00 B6 B6' + 'B6 00 B7 B7 B7 00 B9 B9 B9 00 BC BC BC 00 BD BD' + 'BD 00 BE BE BE 00 BF BF BF 00 C0 C0 C0 00 C1 C1' + 'C1 00 C2 C0 C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1' + 'C2 00 C5 C2 C4 00 C4 C4 C4 00 C5 C5 C5 00 C6 C5' + 'C6 00 C6 C6 C6 00 C8 C3 C5 00 CC C4 C8 00 C8 C8' + 'C8 00 C9 C9 C9 00 CB C9 CA 00 CA CA CA 00 CB CB' + 'CB 00 CC CC CC 00 CD CD CD 00 CE CE CE 00 CF CF' + 'CF 00 D2 C1 CA 00 D3 C8 CD 00 D0 D0 D0 00 D1 D1' + 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' + 'D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9' + 'D9 00 DA DA DA 00 DB DB DB 00 DC DC DC 00 DD DD' + 'DD 00 DE DE DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1' + 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' + 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' + 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' + 'ED 00 EE EE EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1' + 'F1 00 F2 F2 F2 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' + 'F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9 F9 00 FC FC' + 'FC 00 FD FD FD 00 FF FF FF 00 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 08 6C 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6E' + '65 74 64 72 69 76 65 32 2E 69 63 6F 00 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 4D 4D 4D 4D 4D 4D 4D 0D 0D 4D' + '4D 4D 4D 4D 4D 4D 25 25 25 25 25 25 25 0D 0D 25' + '25 25 25 25 25 25 00 00 00 4D 4D 4D 4D 4D 4D 4D' + '4D 4D 4D 4D 00 00 00 00 05 2F 2F 2C 2A 26 25 23' + '21 1C 1B 02 00 00 00 4D 33 41 07 11 18 20 1F 12' + '1E 28 24 10 00 00 00 4D 33 42 09 0E 15 20 17 08' + '16 2B 26 10 00 00 00 4D 35 4C 4B 4A 49 48 47 46' + '45 44 42 0F 00 00 00 4D 39 1A 27 37 37 36 36 37' + '37 19 1D 14 00 00 00 00 0B 31 33 3C 3D 3B 3B 3D' + '3D 32 33 06 00 00 00 00 04 2D 3F 33 32 2F 30 30' + '30 3E 2C 4D 00 00 00 00 4D 33 33 33 33 33 27 29' + '29 29 2E 4D 00 00 00 00 4D 3A 34 39 39 39 39 39' + '39 31 2D 4D 00 00 00 00 4D 2C 3F 34 40 3F 3F 40' + '34 3F 19 4D 00 00 00 00 4D 13 22 43 45 43 43 45' + '3F 33 0A 4D 00 00 00 00 00 03 35 37 37 37 37 37' + '38 2F 01 00 00 00 00 00 00 00 4D 4D 4D 4D 4D 4D' + '4D 4D 00 00 00 00 00 00 00 00 00 00 00 00 E0 03' + '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' + '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' + '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 0C C0 0C C0 00 00 00 00 00 00 00 00' + '00 00 00 00 00 CC CC 00 00 00 00 00 00 00 77 77' + '77 77 77 77 77 8C C8 77 77 77 77 77 77 77 00 00' + '00 00 00 00 00 CC CC 00 00 00 00 00 00 00 00 00' + '00 00 00 00 0C C7 7C C0 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 88 88 88 88 88 88 88 88 88 88 00 00 00 00 00' + '07 FF 77 77 77 77 77 77 77 77 67 80 00 00 00 00' + '8F FF 08 88 87 77 88 77 78 78 66 70 00 00 00 00' + '8F FF 88 88 77 77 88 77 88 77 77 70 00 00 00 00' + '8F FF 88 88 87 77 88 87 88 77 77 70 00 00 00 00' + '8F FF 88 87 77 77 88 77 88 77 77 70 00 00 00 00' + '8F FF FF FF FF FF FF FF FF 77 77 70 00 00 00 00' + '8F FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00' + '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' + '8F 77 77 77 77 77 77 77 77 77 77 F0 00 00 00 00' + '0F 77 77 77 FF FF FF FF 77 77 77 70 00 00 00 00' + '07 77 77 FF 77 77 77 77 FF 77 7F 80 00 00 00 00' + '07 77 7F 77 77 77 77 77 77 F7 7F 80 00 00 00 00' + '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' + '08 F7 77 77 77 77 77 77 77 77 7F 00 00 00 00 00' + '00 F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' + '00 77 77 77 77 77 77 77 77 77 77 00 00 00 00 00' + '00 7F 77 77 77 77 77 77 77 77 78 00 00 00 00 00' + '00 8F F7 7F FF FF FF FF 77 7F 78 00 00 00 00 00' + '00 8F FF 77 7F FF FF F7 77 FF 70 00 00 00 00 00' + '00 07 F7 FF FF F7 7F FF FF 7F 70 00 00 00 00 00' + '00 07 77 7F FF FF FF FF F7 7F 70 00 00 00 00 00' + '00 08 FF FF FF FF FF FF FF FF 80 00 00 00 00 00' + '00 00 88 88 88 88 88 88 88 88 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' + '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF FF F8' + '1F FF F0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 0F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 0C C0 00 00 00 77 77' + '77 7C C7 77 77 77 00 00 00 00 00 00 00 00 00 07' + '77 77 77 77 70 00 00 7F 88 77 78 77 78 00 00 7F' + '88 77 78 77 78 00 00 7F FF FF FF FF F8 00 00 77' + '77 77 77 77 78 00 00 87 77 F7 7F F7 70 00 00 07' + 'F7 77 77 7F 70 00 00 07 77 77 77 77 70 00 00 07' + '77 77 77 77 70 00 00 07 F7 FF FF 7F 70 00 00 08' + '7F FF FF F7 80 00 00 00 77 77 77 77 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 03' + '00 00 C0 03 00 00 80 03 00 00 80 03 00 00 80 03' + '00 00 80 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 E0 07' + '00 00 F0 0F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' + '00 00 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF 00 00 00 9C 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 00 00 FF FF 00 00' + 'FF FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF 00 00 00 3C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 01 00 00 00 04 00 00 00 09 00 00' + '00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00' + '00 09 00 00 FF FF 00 00 FF FF C0 C0 C0 FF C0 C0' + 'C0 FF 00 00 FF FF 00 00 FF FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 05 00 00 00 C5 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F1 00 00 00 B1 00 00 00 0D 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' + '00 9B 00 00 00 FF 21 21 21 FF 2B 2B 2B FF 2C 2C' + '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' + '2D FF 13 13 13 FF 00 00 00 FF 00 00 00 69 00 00' + '00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 AD 01 01' + '01 FF EB EB EB FF E8 E8 E8 FF D5 D5 D5 FF 85 85' + '85 FF 92 92 92 FF 98 98 98 FF AD AD AD FF BA BA' + 'BA FF C3 C3 C3 FF C6 C6 C6 FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF D3 D3 D3 FF D7 D7 D7 FF CC CC' + 'CC FF C7 C7 C7 FF C8 C9 C9 FF 9D B3 A8 FF 20 A8' + '63 FF 90 AF A0 FF BF BB BD FF 00 00 00 FF 00 00' + '00 81 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F0 19 19' + '19 FF EC EC EC FF E2 E2 E2 FF CB CB CB FF 3B 3B' + '3B FF 56 56 56 FF 72 72 72 FF 92 92 92 FF 9D 9D' + '9D FF A8 A8 A8 FF AC AC AC FF A9 A9 A9 FF 9C 9C' + '9C FF 99 99 99 FF B7 B7 B7 FF C3 C3 C3 FF A3 A3' + 'A3 FF 98 98 98 FF C5 C4 C4 FF 51 A7 7C FF 17 CE' + '71 FF 2F 99 64 FF C3 BD C0 FF 01 01 01 FF 00 00' + '00 A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 28 28' + '28 FF EC EC EC FF E6 E6 E6 FF D1 D1 D1 FF 68 68' + '68 FF 7E 7E 7E FF 85 85 85 FF 97 97 97 FF A0 A0' + 'A0 FF AA AA AA FF AE AE AE FF 9F 9F 9F FF 83 83' + '83 FF 7C 7C 7C FF A8 A8 A8 FF BB BB BB FF 8A 8A' + '8A FF 79 79 79 FF C2 C2 C2 FF C6 C3 C4 FF 99 AC' + 'A2 FF C2 BE C0 FF C4 C4 C4 FF 01 01 01 FF 00 00' + '00 BA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 28 28' + '28 FF EE EE EE FF E7 E7 E7 FF D6 D6 D6 FF 70 70' + '70 FF 7D 7D 7D FF 85 85 85 FF 97 97 97 FF A0 A0' + 'A0 FF AA AA AA FF AE AE AE FF 98 98 98 FF 73 73' + '73 FF 6A 6A 6A FF A0 A0 A0 FF B7 B7 B7 FF 7C 7C' + '7C FF 67 67 67 FF C2 C2 C2 FF C4 C3 C4 FF C7 C4' + 'C5 FF BF BF BF FF C5 C5 C5 FF 01 01 01 FF 00 00' + '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 27 27' + '27 FF F2 F2 F2 FF EB EB EB FF DF DF DF FF A7 A7' + 'A7 FF AB AB AB FF AE AE AE FF B3 B3 B3 FF B6 B6' + 'B6 FF B9 B9 B9 FF BA BA BA FF B7 B7 B7 FF B1 B1' + 'B1 FF AF AF AF FF BA BA BA FF BE BE BE FF B0 B0' + 'B0 FF AB AB AB FF C5 C5 C5 FF C6 C6 C6 FF C4 C4' + 'C4 FF C2 C2 C2 FF C9 C9 C9 FF 00 00 00 FF 00 00' + '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 26 26' + '26 FF F3 F3 F3 FF EB EB EB FF EA EA EA FF ED ED' + 'ED FF E9 E9 E9 FF E8 E8 E8 FF E4 E4 E4 FF E2 E2' + 'E2 FF DF DF DF FF DE DE DE FF DB DB DB FF DC DC' + 'DC FF D9 D9 D9 FF D6 D6 D6 FF D2 D2 D2 FF D2 D2' + 'D2 FF D0 D0 D0 FF CB CB CB FF C9 C9 C9 FF C7 C7' + 'C7 FF C0 C0 C0 FF CA CA CA FF 00 00 00 FF 00 00' + '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 F9 24 24' + '24 FF FF FF FF FF E9 E9 E9 FF E2 E2 E2 FF E2 E2' + 'E2 FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E3 E3 E3 FF E3 E3' + 'E3 FF F8 F8 F8 FF EF EF EF FF 00 00 00 FF 00 00' + '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FA 24 24' + '24 FF F8 F8 F8 FF D9 D9 D9 FF BB BB BB FF BF BF' + 'BF FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF DB DB DB FF BC BC BC FF BB BB' + 'BB FF DE DE DE FF FF FF FF FF 00 00 00 FF 00 00' + '00 BA 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 D0 05 05' + '05 FF F6 F6 F6 FF BC BC BC FF C3 C3 C3 FF AB AB' + 'AB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' + 'D4 FF D3 D3 D3 FF D5 D5 D5 FF D8 D8 D8 FF D8 D8' + 'D8 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3 D3 FF D4 D4' + 'D4 FF D7 D7 D7 FF C9 C9 C9 FF C3 C3 C3 FF B3 B3' + 'B3 FF D6 D6 D6 FF F5 F5 F5 FF 00 00 00 FF 00 00' + '00 8C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' + '00 FF F4 F4 F4 FF CF CF CF FF D2 D2 D2 FF BF BF' + 'BF FF D3 D3 D3 FF D2 D2 D2 FF D3 D3 D3 FF DD DD' + 'DD FF E3 E3 E3 FF E6 E6 E6 FF ED ED ED FF ED ED' + 'ED FF E7 E7 E7 FF E4 E4 E4 FF DE DE DE FF D4 D4' + 'D4 FF D2 D2 D2 FF D3 D3 D3 FF D0 D0 D0 FF C2 C2' + 'C2 FF D9 D9 D9 FF E8 E8 E8 FF 00 00 00 FF 00 00' + '00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00' + '00 FF E9 E9 E9 FF D0 D0 D0 FF CD CD CD FF CD CD' + 'CD FF D6 D6 D6 FF ED ED ED FF DC DC DC FF D4 D4' + 'D4 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5 D5 FF DB DB' + 'DB FF ED ED ED FF DA DA DA FF CD CD CD FF CD CD' + 'CD FF DF DF DF FF B8 B8 B8 FF 00 00 00 FB 00 00' + '00 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' + '00 FE D7 D7 D7 FF D2 D2 D2 FF CB CB CB FF CA CA' + 'CA FF E9 E9 E9 FF DC DC DC FF D1 D1 D1 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' + 'D1 FF D8 D8 D8 FF EA EA EA FF C9 C9 C9 FF CA CA' + 'CA FF E0 E0 E0 FF A0 A0 A0 FF 00 00 00 EB 00 00' + '00 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 E1 9F 9F 9F FF DD DD DD FF CD CD CD FF DB DB' + 'DB FF CE CE CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF C8 C8 C8 FF DA DA DA FF C7 C7' + 'C7 FF E2 E2 E2 FF 5A 5A 5A FF 00 00 00 94 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 B2 83 83 83 FF DD DD DD FF D1 D1 D1 FF DB DB' + 'DB FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF C9 C9 C9 FF C5 C5' + 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF D3 D3 D3 FF C8 C8' + 'C8 FF DE DE DE FF 42 42 42 FF 00 00 00 6C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4B 41 41 41 FF D8 D8 D8 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF C7 C7 C7 FF C4 C4 C4 FF C1 C1 C1 FF C0 C0' + 'C0 FF C1 C1 C1 FF C1 C1 C1 FF BF BF BF FF C0 C0' + 'C0 FF B2 B2 B2 FF 1A 1A 1A FF 00 00 00 28 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1A 2C 2C 2C FF CC CC CC FF D5 D5 D5 FF CC CC' + 'CC FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D5 D5 D5 FF CF CF CF FF CC CC' + 'CC FF C6 C6 C6 FF C4 C4 C4 FF B3 B3 B3 FF BD BD' + 'BD FF 99 99 99 FF 09 09 09 FF 00 00 00 19 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 08 08 08 FF 97 97 97 FF DF DF DF FF DC DC' + 'DC FF D6 D6 D6 FF DE DE DE FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DE DE DE FF D8 D8 D8 FF DD DD DD FF DC DC' + 'DC FF 53 53 53 FF 00 00 00 FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 77 77 77 FF E2 E2 E2 FF E1 E1' + 'E1 FF CE CE CE FF D7 D7 D7 FF E2 E2 E2 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' + 'E1 FF D9 D9 D9 FF CD CD CD FF E3 E3 E3 FF D9 D9' + 'D9 FF 39 39 39 FF 00 00 00 FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF 35 35 35 FF E6 E6 E6 FF E6 E6' + 'E6 FF E7 E7 E7 FF E7 E7 E7 FF D2 D2 D2 FF D3 D3' + 'D3 FF E3 E3 E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4' + 'E4 FF E3 E3 E3 FF E3 E3 E3 FF D4 D4 D4 FF D1 D1' + 'D1 FF E7 E7 E7 FF E7 E7 E7 FF E8 E8 E8 FF D4 D4' + 'D4 FF 0B 0B 0B FF 00 00 00 ED 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 F9 1E 1E 1E FF E4 E4 E4 FF ED ED' + 'ED FF E6 E6 E6 FF EC EC EC FF EA EA EA FF E4 E4' + 'E4 FF DF DF DF FF DF DF DF FF DC DC DC FF DC DC' + 'DC FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' + 'E9 FF EA EA EA FF E5 E5 E5 FF EB EB EB FF D6 D6' + 'D6 FF 00 00 00 FF 00 00 00 C3 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 AE 00 00 00 FF E0 E0 E0 FF C4 C4' + 'C4 FF B8 B8 B8 FF B2 B2 B2 FF F1 F1 F1 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' + 'F3 FF B0 B0 B0 FF B6 B6 B6 FF EB EB EB FF CD CD' + 'CD FF 00 00 00 FF 00 00 00 85 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 80 00 00 00 FF CE CE CE FF DD DD' + 'DD FF D5 D5 D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' + 'FA FF DF DF DF FF D8 D8 D8 FF D7 D7 D7 FF B0 B0' + 'B0 FF 00 00 00 FF 00 00 00 67 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 02 00 00 00 9C 0C 0C 0C FF 3D 3D' + '3D FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 49 49 49 FF 2F 2F 2F FF 02 02' + '02 FF 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 06 00 00 00 F1 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 D6 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' + '8F FF 00 00 00 00 00 00 00 00 FF FC 1F FF F8 00' + '1F FF F0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 E0 00' + '00 07 E0 00 00 07 E0 00 00 07 E0 00 00 07 F0 00' + '00 0F F0 00 00 0F F0 00 00 0F F0 00 00 1F F8 00' + '00 1F F8 00 00 1F F8 00 00 1F F8 00 00 1F F8 00' + '00 1F F8 00 00 3F FC 00 00 7F FF FF FF FF 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' + '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + 'CC 00 00 CC 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 CC C0 0C CC 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '0C CC CC C0 00 00 00 00 00 00 00 00 00 00 88 88' + '88 88 88 88 88 88 88 88 88 CC CC 88 88 88 88 88' + '88 88 88 88 88 88 77 77 77 77 77 77 77 77 77 77' + '77 CC CC 77 77 77 77 77 77 77 77 77 77 77 00 00' + '00 00 00 00 00 00 00 00 0C CC CC C0 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + 'CC C7 7C CC 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 CC 07 70 CC 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' + '00 08 FF F7 88 88 77 77 77 77 77 77 77 77 77 77' + '66 87 80 00 00 00 00 00 00 07 FF F7 00 88 88 87' + '77 77 87 87 77 77 87 78 66 67 80 00 00 00 00 00' + '00 07 FF F7 88 88 88 77 77 77 87 87 87 87 87 77' + '77 87 80 00 00 00 00 00 00 07 FF F7 88 88 88 77' + '77 78 87 87 87 87 87 77 77 77 80 00 00 00 00 00' + '00 07 FF F7 88 88 88 77 77 78 87 87 87 87 87 77' + '77 77 80 00 00 00 00 00 00 07 FF F7 88 88 88 87' + '77 78 87 88 87 87 87 77 77 77 80 00 00 00 00 00' + '00 07 FF F7 77 77 77 77 77 77 77 77 77 77 77 77' + '77 77 80 00 00 00 00 00 00 07 FF FF FF FF FF FF' + '77 77 77 77 77 77 77 77 77 77 80 00 00 00 00 00' + '00 07 FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF F7 80 00 00 00 00 00 00 07 FF FF FF 77 77 7F' + 'FF FF FF FF FF FF FF FF FF FF 80 00 00 00 00 00' + '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 7F 80 00 00 00 00 00' + '00 07 F7 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 7F 80 00 00 00 00 00 00 07 F7 77 77 77 77 7F' + 'FF FF FF FF F7 77 77 77 77 7F 80 00 00 00 00 00' + '00 08 F7 77 77 77 7F FF 77 77 77 77 FF FF 77 77' + '77 77 00 00 00 00 00 00 00 08 F7 77 77 7F F7 77' + '77 77 77 77 77 7F F7 77 77 77 00 00 00 00 00 00' + '00 00 77 77 77 F7 77 77 77 77 77 77 77 77 7F 77' + '77 F7 00 00 00 00 00 00 00 00 77 77 7F 77 77 77' + '77 77 77 77 77 77 77 F7 77 F8 00 00 00 00 00 00' + '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 F8 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 78 00 00 00 00 00 00' + '00 00 87 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 70 00 00 00 00 00 00 00 00 87 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' + '00 00 07 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 00 00 07 77 77 77 77 77' + '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' + '00 00 08 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 80 00 00 00 00 00 00 00 00 08 7F F7 77 FF FF' + 'FF FF FF FF FF FF 77 7F 77 00 00 00 00 00 00 00' + '00 00 08 7F FF F7 77 FF FF FF FF FF FF 77 7F FF' + '77 00 00 00 00 00 00 00 00 00 00 7F FF FF 77 77' + 'FF FF FF FF 77 77 FF FF 78 00 00 00 00 00 00 00' + '00 00 00 7F FF FF FF FF 77 77 77 77 7F FF FF FF' + '78 00 00 00 00 00 00 00 00 00 00 8F 77 77 FF FF' + 'FF FF FF FF FF FF 77 7F 78 00 00 00 00 00 00 00' + '00 00 00 8F 77 77 FF FF FF FF FF FF FF F7 77 7F' + '78 00 00 00 00 00 00 00 00 00 00 87 77 7F FF FF' + 'FF FF FF FF FF FF 77 77 70 00 00 00 00 00 00 00' + '00 00 00 08 77 77 77 77 77 77 77 77 77 77 77 77' + '80 00 00 00 00 00 00 00 00 00 00 00 08 88 88 88' + '88 88 88 88 88 88 88 80 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF F1 C7 FF FF 00 00 FF FF' + 'F0 07 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'F8 0F FF FF 00 00 FF FF F0 07 FF FF 00 00 FF FF' + 'F2 07 FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' + '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' + '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' + '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + 'FF FF 00 00 FF FF 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 FF FF 00 00 FF FF 00 00' + '00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 30 00 00 00 24 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 30 00 00' + '00 30 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' + '00 3C 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 9C 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 90 00 00 00 90 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' + 'FF FF 00 00 FF FF 00 00 FF FF 00 00 00 3C 00 00' + '00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + 'FF FF 00 00 FF FF 00 00 FF FF C0 C0 C0 FF C0 C0' + 'C0 FF 00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00' + '00 15 00 00 00 09 00 00 00 09 00 00 00 09 00 00' + '00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00' + '00 09 00 00 00 09 00 00 00 09 00 00 00 07 00 00' + '00 04 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + 'FF FF 00 00 FF FF 00 00 00 37 C0 C0 C0 FF C0 C0' + 'C0 FF 00 00 00 37 00 00 FF FF 00 00 FF FF 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 35 00 00 00 18 00 00' + '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' + '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F1 00 00 00 B1 00 00' + '00 5C 00 00 00 0D 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' + '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' + '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2E 2C' + '2D FF 2E 2C 2D FF 13 13 13 FF 00 00 00 FF 00 00' + '00 F6 00 00 00 69 00 00 00 09 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' + '90 FF CA CA CA FF CD CD CD FF CB CB CB FF CE CE' + 'CE FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' + 'C9 FF C7 C7 C7 FF C6 C6 C6 FF C5 C5 C5 FF C4 C4' + 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2 C2 FF C3 C3' + 'C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF BF FF BF BF' + 'BF FF BC BC BC FF BD BD BD FF BA BA BA FF BB BB' + 'BB FF B5 B5 B5 FF B3 B4 B3 FF B8 B4 B6 FF AD AD' + 'AD FF AB AC AC FF AD A8 AB FF 63 63 63 FF 09 09' + '09 FF 00 00 00 EF 00 00 00 42 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF EB EB' + 'EB FF E8 E8 E8 FF E7 E7 E7 FF D5 D5 D5 FF 85 85' + '85 FF 88 88 88 FF 92 92 92 FF 98 98 98 FF A2 A2' + 'A2 FF AD AD AD FF BA BA BA FF C0 C0 C0 FF C3 C3' + 'C3 FF C6 C6 C6 FF CB CB CB FF CA CA CA FF CA CA' + 'CA FF D6 D6 D6 FF CA CA CA FF D3 D3 D3 FF CB CB' + 'CB FF D7 D7 D7 FF CC CC CC FF D4 D4 D4 FF C7 C7' + 'C7 FF C8 C9 C9 FF C6 C2 C4 FF 9D B3 A8 FF 20 A8' + '63 FF 1C A8 60 FF 90 AF A0 FF BF BB BD FF 4F 4F' + '4F FF 00 00 00 FF 00 00 00 81 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 15 00 00 00 F0 19 19 19 FF C7 C7 C7 FF EC EC' + 'EC FF E2 E2 E2 FF E6 E6 E6 FF CB CB CB FF 3B 3B' + '3B FF 3F 3F 3F FF 56 56 56 FF 72 72 72 FF 87 87' + '87 FF 92 92 92 FF 9D 9D 9D FF A5 A5 A5 FF A8 A8' + 'A8 FF AC AC AC FF B7 B7 B7 FF A9 A9 A9 FF 9C 9C' + '9C FF BD BD BD FF 99 99 99 FF B7 B7 B7 FF A1 A1' + 'A1 FF C3 C3 C3 FF A3 A3 A3 FF BD BD BD FF 98 98' + '98 FF C5 C4 C4 FF C7 BF C3 FF 51 A7 7C FF 17 CE' + '71 FF 0A BF 61 FF 2F 99 64 FF C3 BD C0 FF 84 83' + '84 FF 01 01 01 FF 00 00 00 A3 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 30 00 00 00 FA 29 29 29 FF D1 D1 D1 FF EA EA' + 'EA FF E4 E4 E4 FF E7 E7 E7 FF CD CD CD FF 47 47' + '47 FF 5F 5F 5F FF 79 79 79 FF 87 87 87 FF 8F 8F' + '8F FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF B9 B9 B9 FF A4 A4 A4 FF 90 90' + '90 FF B8 B8 B8 FF 8A 8A 8A FF AF AF AF FF 94 94' + '94 FF BF BF BF FF 97 97 97 FF B7 B7 B7 FF 88 88' + '88 FF C4 C3 C3 FF C6 C3 C5 FF 95 B2 A3 FF 91 D6' + 'B4 FF 91 D8 B5 FF 83 AB 97 FF C4 C1 C3 FF 8E 8E' + '8E FF 01 01 01 FF 00 00 00 B7 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' + 'EC FF E6 E6 E6 FF E7 E7 E7 FF D1 D1 D1 FF 68 68' + '68 FF 74 74 74 FF 7E 7E 7E FF 85 85 85 FF 8E 8E' + '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF BA BA BA FF 9F 9F 9F FF 83 83' + '83 FF B3 B3 B3 FF 7C 7C 7C FF A8 A8 A8 FF 87 87' + '87 FF BB BB BB FF 8A 8A 8A FF B2 B2 B2 FF 79 79' + '79 FF C2 C2 C2 FF C4 C4 C4 FF C6 C3 C4 FF 99 AC' + 'A2 FF 96 AB A0 FF C2 BE C0 FF C4 C4 C4 FF 8D 8D' + '8D FF 01 01 01 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' + 'EE FF E7 E7 E7 FF E8 E8 E8 FF D6 D6 D6 FF 70 70' + '70 FF 71 71 71 FF 7D 7D 7D FF 85 85 85 FF 8E 8E' + '8E FF 97 97 97 FF A0 A0 A0 FF A7 A7 A7 FF AA AA' + 'AA FF AE AE AE FF BB BB BB FF 98 98 98 FF 73 73' + '73 FF AD AD AD FF 6A 6A 6A FF A0 A0 A0 FF 78 78' + '78 FF B7 B7 B7 FF 7C 7C 7C FF AB AB AB FF 67 67' + '67 FF C2 C2 C2 FF C6 C6 C6 FF C4 C3 C4 FF C7 C4' + 'C5 FF C6 C2 C4 FF BF BF BF FF C5 C5 C5 FF 8D 8D' + '8D FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' + 'EF FF E9 E9 E9 FF EB EB EB FF D6 D6 D6 FF 6A 6A' + '6A FF 6C 6C 6C FF 78 78 78 FF 81 81 81 FF 8A 8A' + '8A FF 93 93 93 FF 9C 9C 9C FF A3 A3 A3 FF A6 A6' + 'A6 FF AB AB AB FF B9 B9 B9 FF 90 90 90 FF 66 66' + '66 FF A5 A5 A5 FF 5B 5B 5B FF 98 98 98 FF 6B 6B' + '6B FF B1 B1 B1 FF 70 70 70 FF A4 A4 A4 FF 58 58' + '58 FF C1 C1 C1 FF C8 C8 C8 FF C5 C5 C5 FF C3 C3' + 'C3 FF C2 C2 C2 FF C1 C1 C1 FF C6 C6 C6 FF 8E 8E' + '8E FF 01 01 01 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' + 'F2 FF EB EB EB FF EA EA EA FF DF DF DF FF A7 A7' + 'A7 FF A7 A7 A7 FF AB AB AB FF AE AE AE FF B0 B0' + 'B0 FF B3 B3 B3 FF B6 B6 B6 FF B9 B9 B9 FF B9 B9' + 'B9 FF BA BA BA FF BD BD BD FF B7 B7 B7 FF B1 B1' + 'B1 FF BE BE BE FF AF AF AF FF BA BA BA FF B1 B1' + 'B1 FF BE BE BE FF B0 B0 B0 FF BA BA BA FF AB AB' + 'AB FF C5 C5 C5 FF C8 C8 C8 FF C6 C6 C6 FF C4 C4' + 'C4 FF C3 C3 C3 FF C2 C2 C2 FF C9 C9 C9 FF 8E 8E' + '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F3 F3' + 'F3 FF EB EB EB FF EB EB EB FF EA EA EA FF ED ED' + 'ED FF EB EB EB FF E9 E9 E9 FF E8 E8 E8 FF E6 E6' + 'E6 FF E4 E4 E4 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' + 'DF FF DE DE DE FF DB DB DB FF DB DB DB FF DC DC' + 'DC FF D8 D8 D8 FF D9 D9 D9 FF D6 D6 D6 FF D6 D6' + 'D6 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' + 'D0 FF CB CB CB FF CA CA CA FF C9 C9 C9 FF C7 C7' + 'C7 FF C4 C4 C4 FF C0 C0 C0 FF CA CA CA FF 8E 8E' + '8E FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' + 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' + 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' + 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' + 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF ED ED' + 'ED FF ED ED ED FF ED ED ED FF EC EC EC FF EC EC' + 'EC FF EB EB EB FF E0 E0 E0 FF D0 D0 D0 FF 8D 8D' + '8D FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' + 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' + 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E2 E2 E2 FF E3 E3 E3 FF E3 E3' + 'E3 FF E3 E3 E3 FF F8 F8 F8 FF EF EF EF FF 8C 8C' + '8C FF 00 00 00 FF 00 00 00 B9 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' + 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' + 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF DB DB DB FF CF CF CF FF BC BC BC FF BB BB' + 'BB FF D1 D1 D1 FF DE DE DE FF FF FF FF FF 9A 9A' + '9A FF 00 00 00 FF 00 00 00 BA 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' + 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' + 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9' + 'D9 FF D2 D2 D2 FF A8 A8 A8 FF B6 B6 B6 FF B1 B1' + 'B1 FF B5 B5 B5 FF D8 D8 D8 FF FC FC FC FF 9C 9C' + '9C FF 00 00 00 FF 00 00 00 AE 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' + 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' + 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' + 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D7 D7' + 'D7 FF C9 C9 C9 FF A6 A6 A6 FF C3 C3 C3 FF B3 B3' + 'B3 FF AD AD AD FF D6 D6 D6 FF F5 F5 F5 FF 76 76' + '76 FF 00 00 00 FF 00 00 00 8C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' + 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' + 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF DD DD DD FF E1 E1 E1 FF E3 E3' + 'E3 FF E6 E6 E6 FF EA EA EA FF ED ED ED FF ED ED' + 'ED FF EB EB EB FF E7 E7 E7 FF E4 E4 E4 FF E2 E2' + 'E2 FF DE DE DE FF D4 D4 D4 FF D0 D0 D0 FF D2 D2' + 'D2 FF D3 D3 D3 FF C5 C5 C5 FF D0 D0 D0 FF C2 C2' + 'C2 FF BF BF BF FF D9 D9 D9 FF E8 E8 E8 FF 56 56' + '56 FF 00 00 00 FF 00 00 00 72 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' + 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' + 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF DF DF' + 'DF FF F0 F0 F0 FF EC EC EC FF E1 E1 E1 FF DE DE' + 'DE FF DD DD DD FF DC DC DC FF DB DB DB FF DB DB' + 'DB FF DC DC DC FF DD DD DD FF DE DE DE FF E1 E1' + 'E1 FF EC EC EC FF F1 F1 F1 FF E1 E1 E1 FF D1 D1' + 'D1 FF CE CE CE FF D0 D0 D0 FF CB CB CB FF CE CE' + 'CE FF D1 D1 D1 FF D9 D9 D9 FF D4 D4 D4 FF 3F 3F' + '3F FF 00 00 00 FF 00 00 00 55 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' + 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CA CA CA FF D6 D6 D6 FF ED ED ED FF E6 E6' + 'E6 FF DC DC DC FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF ED ED' + 'ED FF DA DA DA FF CA CA CA FF CD CD CD FF CD CD' + 'CD FF CB CB CB FF DF DF DF FF B8 B8 B8 FF 22 22' + '22 FF 00 00 00 FB 00 00 00 3A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' + 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' + 'CA FF D4 D4 D4 FF E9 E9 E9 FF DC DC DC FF D0 D0' + 'D0 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D8 D8' + 'D8 FF EA EA EA FF D8 D8 D8 FF C9 C9 C9 FF CA CA' + 'CA FF C9 C9 C9 FF E0 E0 E0 FF A0 A0 A0 FF 08 08' + '08 FF 00 00 00 EB 00 00 00 22 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' + 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' + 'CE FF E4 E4 E4 FF D4 D4 D4 FF CF CF CF FF D1 D1' + 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF CD CD CD FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CC CC' + 'CC FF D0 D0 D0 FF E2 E2 E2 FF CF CF CF FF C7 C7' + 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 C2 00 00 00 0E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' + '9F FF DD DD DD FF CC CC CC FF CD CD CD FF DB DB' + 'DB FF D6 D6 D6 FF CE CE CE FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF C8 C8 C8 FF CF CF CF FF DA DA DA FF C7 C7' + 'C7 FF C9 C9 C9 FF E2 E2 E2 FF 5A 5A 5A FF 00 00' + '00 FF 00 00 00 94 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' + '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF DB DB' + 'DB FF D1 D1 D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF C9 C9 C9 FF C5 C5' + 'C5 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C7 C7 C7 FF D3 D3 D3 FF C8 C8' + 'C8 FF C9 C9 C9 FF DE DE DE FF 42 42 42 FF 00 00' + '00 FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' + '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D4 D4' + 'D4 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D0 D0 D0 FF C8 C8' + 'C8 FF C3 C3 C3 FF C3 C3 C3 FF C3 C3 C3 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C7 C7 C7 FF C5 C5' + 'C5 FF CB CB CB FF CC CC CC FF 2D 2D 2D FF 00 00' + '00 F8 00 00 00 40 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' + '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF CD CD CD FF C7 C7 C7 FF C4 C4 C4 FF C2 C2' + 'C2 FF C1 C1 C1 FF C0 C0 C0 FF C1 C1 C1 FF C1 C1' + 'C1 FF C1 C1 C1 FF C2 C2 C2 FF BF BF BF FF C0 C0' + 'C0 FF CE CE CE FF B2 B2 B2 FF 1A 1A 1A FF 00 00' + '00 E5 00 00 00 28 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' + '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF CC CC' + 'CC FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D7 D7 D7 FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' + 'D3 FF CF CF CF FF CC CC CC FF C9 C9 C9 FF C6 C6' + 'C6 FF C4 C4 C4 FF C2 C2 C2 FF B3 B3 B3 FF BD BD' + 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' + '00 CF 00 00 00 19 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' + '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF D0 D0' + 'D0 FF D2 D2 D2 FF DB DB DB FF D9 D9 D9 FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DB DB DB FF DB DB DB FF DA DA DA FF D9 D9' + 'D9 FF D9 D9 D9 FF CF CF CF FF C5 C5 C5 FF CC CC' + 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' + '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' + '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' + 'DC FF CE CE CE FF D6 D6 D6 FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DE DE' + 'DE FF D8 D8 D8 FF CE CE CE FF DD DD DD FF DC DC' + 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' + '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' + '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' + 'E1 FF DE DE DE FF CE CE CE FF D7 D7 D7 FF E1 E1' + 'E1 FF E2 E2 E2 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF D9 D9' + 'D9 FF CD CD CD FF DA DA DA FF E3 E3 E3 FF D9 D9' + 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' + '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' + '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' + 'E3 FF E4 E4 E4 FF E1 E1 E1 FF D7 D7 D7 FF D2 D2' + 'D2 FF DA DA DA FF E4 E4 E4 FF E5 E5 E5 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E5 E5 E5 FF DC DC DC FF D2 D2 D2 FF D6 D6' + 'D6 FF E0 E0 E0 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' + 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' + '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' + '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF DF DF' + 'DF FF D2 D2 D2 FF D3 D3 D3 FF DE DE DE FF E3 E3' + 'E3 FF E3 E3 E3 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E3 E3 E3 FF E3 E3 E3 FF DE DE' + 'DE FF D4 D4 D4 FF D1 D1 D1 FF DD DD DD FF E7 E7' + 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' + 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' + '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' + 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' + 'EB FF EA EA EA FF E4 E4 E4 FF E0 E0 E0 FF DF DF' + 'DF FF DF DF DF FF DD DD DD FF DC DC DC FF DC DC' + 'DC FF DD DD DD FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E2 E2 E2 FF E9 E9 E9 FF EC EC EC FF EA EA' + 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' + 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' + 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' + 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' + 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' + 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' + 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' + 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' + 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' + 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' + 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' + 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' + 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' + 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' + 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' + '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' + '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' + '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' + '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' + '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'F1 C7 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF F8 07 FF FF 00 00 FF FF' + 'E0 00 00 3F 00 00 FF 00 00 00 00 7F 00 00 FC 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FF 00 00 00 00 7F 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 01 FF 00 00 FF 80 00 00 03 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' + '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' + '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' + '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 13 13' + '13 00 18 18 18 00 19 19 19 00 1A 1A 1A 00 1E 1E' + '1E 00 1F 1F 1F 00 20 20 20 00 21 21 21 00 22 22' + '22 00 24 24 24 00 26 26 26 00 27 27 27 00 28 28' + '28 00 29 29 29 00 2A 2A 2A 00 2B 2B 2B 00 2C 2C' + '2C 00 2D 2D 2D 00 2E 2C 2D 00 2F 2F 2F 00 34 34' + '34 00 35 35 35 00 39 39 39 00 3B 3B 3B 00 3D 3D' + '3D 00 3F 3F 3F 00 40 40 40 00 41 41 41 00 42 42' + '42 00 47 47 47 00 48 48 48 00 49 49 49 00 4B 4B' + '4B 00 4F 4F 4F 00 53 53 53 00 56 56 56 00 58 58' + '58 00 59 59 59 00 5A 5A 5A 00 5B 5B 5B 00 5D 5D' + '5D 00 5F 5F 5F 00 61 61 61 00 63 63 63 00 64 64' + '64 00 66 66 66 00 67 67 67 00 68 68 68 00 6A 6A' + '6A 00 6B 6B 6B 00 6C 6C 6C 00 70 70 70 00 71 71' + '71 00 72 72 72 00 73 73 73 00 74 74 74 00 75 75' + '75 00 76 76 76 00 77 77 77 00 78 78 78 00 79 79' + '79 00 7A 7A 7A 00 7C 7C 7C 00 7D 7D 7D 00 7E 7E' + '7E 00 7F 7F 7F 00 2F 99 64 00 1C A8 60 00 0A BF' + '61 00 20 A8 63 00 51 A7 7C 00 17 CE 71 00 00 00' + 'FF 00 80 80 80 00 81 81 81 00 83 83 83 00 84 83' + '84 00 85 85 85 00 87 87 87 00 88 88 88 00 8A 8A' + '8A 00 8C 8C 8C 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' + '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 94 94' + '94 00 97 97 97 00 98 98 98 00 99 99 99 00 9A 9A' + '9A 00 9C 9C 9C 00 9D 9D 9D 00 9F 9F 9F 00 83 AB' + '97 00 96 AB A0 00 90 AF A0 00 99 AC A2 00 95 B2' + 'A3 00 9D B3 A8 00 A0 A0 A0 00 A1 A1 A1 00 A2 A2' + 'A2 00 A3 A3 A3 00 A4 A4 A4 00 A5 A5 A5 00 A6 A6' + 'A6 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9 A9 00 AA AA' + 'AA 00 AB AB AB 00 AD A8 AB 00 AB AC AC 00 AC AC' + 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' + 'B0 00 B1 B1 B1 00 B2 B2 B2 00 B3 B3 B3 00 B3 B4' + 'B3 00 B5 B5 B5 00 B6 B6 B6 00 B7 B7 B7 00 B8 B4' + 'B6 00 B8 B8 B8 00 B9 B9 B9 00 BA BA BA 00 BB BB' + 'BB 00 BF BB BD 00 BC BC BC 00 BD BD BD 00 BE BE' + 'BE 00 BF BF BF 00 91 D6 B4 00 91 D8 B5 00 C3 BD' + 'C0 00 C2 BE C0 00 C7 BF C3 00 C0 C0 C0 00 C1 C1' + 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C1 C3 00 C4 C3' + 'C3 00 C4 C3 C4 00 C6 C2 C4 00 C6 C3 C4 00 C6 C3' + 'C5 00 C4 C4 C4 00 C5 C4 C4 00 C5 C5 C5 00 C7 C4' + 'C5 00 C6 C6 C6 00 C7 C7 C7 00 C8 C8 C8 00 C8 C9' + 'C9 00 C9 C9 C9 00 CA CA CA 00 CB CB CB 00 CC CC' + 'CC 00 CD CD CD 00 CE CE CE 00 CF CF CF 00 D0 D0' + 'D0 00 D1 D1 D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4' + 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 DF DF DF 00 E0 E0' + 'E0 00 E1 E1 E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4' + 'E4 00 E5 E5 E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8' + 'E8 00 E9 E9 E9 00 EA EA EA 00 EB EB EB 00 EC EC' + 'EC 00 ED ED ED 00 EE EE EE 00 EF EF EF 00 F0 F0' + 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4' + 'F4 00 F5 F5 F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8' + 'F8 00 F9 F9 F9 00 FA FA FA 00 FC FC FC 00 FF FF' + 'FF 00 00 00 00 00 10 DA 4B 00 F8 0F 0D 01 71 CC' + '43 00 F8 0F 0D 01 40 E3 0C 01 A4 1A 95 00 2C A3' + 'AF 00 C4 F5 AF 00 03 00 00 00 40 E3 0C 01 2F 0C' + '00 00 B8 10 0D 01 30 00 00 00 00 00 00 00 40 00' + '00 00 F8 0F 0D 01 C0 00 00 00 30 00 00 00 00 09' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 30 00' + '00 00 30 00 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 52 52 DF 00 00 00' + '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 52 52 52 DF 00 52' + '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 DF DF DF DF DF DF DF DF DF DF' + 'DF DF DF DF DF DF DF DF DF DF DF 52 52 52 52 52' + '52 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' + 'DF DF DF DF DF DF 53 53 53 53 53 53 53 53 53 53' + '53 53 53 53 53 53 53 53 53 53 53 53 52 52 52 52' + '53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53' + '53 53 53 53 53 53 99 99 99 99 99 99 99 99 99 99' + '99 99 99 99 99 99 99 99 99 99 99 99 52 52 52 52' + '99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99' + '99 99 99 99 99 99 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 52 52 52 52 52' + '52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 52 52 52 99 99 52' + '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 52 52 00 99 99 DF' + '52 52 DF 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF DF DF' + 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' + 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 DF DF DF DF 11' + '1A 19 1A 19 19 19 19 19 19 19 19 19 19 19 18 18' + '18 18 18 18 18 18 18 19 19 19 1C 1C 0A DF DF DF' + '00 00 00 00 00 00 00 00 00 00 00 DF DF 14 5F AC' + 'AF AD B0 AF AE AD AB A8 A7 A5 A3 9C 9B 9B 9C 99' + '9A 93 93 90 91 8D 8E 87 86 8A 7F 7D 7C 35 07 DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 01 5A CD CA' + 'C9 B7 57 59 60 64 72 7F 8D 99 9C A7 AD AC AC B8' + 'AC B5 AD B9 AE B6 A8 AA A0 6F 4F 4D 6C 8F 2B DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 0C A8 CE C4' + 'C8 AD 21 23 2D 3F 58 60 68 75 78 7E 89 79 67 91' + '65 89 71 9C 73 91 64 A4 98 50 51 4E 4C 96 56 01' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 17 B3 CC C6' + 'C9 AF 27 33 46 58 5E 63 70 77 7A 80 8C 74 5F 8B' + '5A 81 62 93 63 89 59 9E A2 6E 94 95 6A 9D 5D 01' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 16 B3 CE C8' + 'C9 B3 39 41 4A 57 5D 63 70 77 7A 80 8D 69 55 85' + '48 78 58 8E 5A 84 46 9B A3 A1 6D 6B 97 A3 5C 01' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 16 B3 D0 C9' + 'CA B8 3D 3E 49 57 5D 63 70 77 7A 80 8E 64 40 7F' + '3A 70 45 89 48 7B 38 9B A7 9F A6 A0 93 A5 5C 01' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 15 B3 D1 CB' + 'CD B8 3A 3C 45 54 5A 61 67 73 76 7B 8C 5F 37 75' + '31 64 3B 83 3D 74 2E 9A A9 A5 9C 9B 9A A7 5D 01' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 15 B4 D4 CD' + 'CC C1 77 77 7B 80 82 85 88 8C 8C 8D 91 89 83 92' + '81 8D 83 92 82 8D 7B A5 A9 A7 A3 9C 9B AB 5D DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 14 B5 D5 CD' + 'CD CC CF CD CB CA C8 C6 C4 C3 C1 C0 BD BD BE BA' + 'BB B8 B8 B4 B4 B1 B2 AD AC AB A8 A3 99 AC 5D DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 14 B5 D9 DA' + 'D8 D8 D8 D7 D7 D6 D6 D5 D5 D5 D4 D4 D3 D3 D3 D2' + 'D2 D2 D1 D1 D0 D0 CF CF CF CE CE CD C2 B2 5C DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 13 B8 DE CB' + 'C3 C4 C4 C2 C1 C1 C1 C1 C1 C2 C2 C2 C2 C2 C2 C2' + 'C2 C2 C2 C2 C2 C2 C2 C2 C4 C5 C5 C5 DA D1 5B DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 13 C0 DA BB' + 'A3 8E 93 BA BC BB BB BB BB BB BB BB BB BB BB BB' + 'BB BB BB BB BB BB BB BD B1 90 8E B3 C0 DE 66 DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 0F BC D5 A7' + '79 89 82 9C BC BA BA BA BA BA B9 B9 B9 B9 B9 B9' + 'B9 B9 BA BA BA BA BB B4 78 88 83 87 BA DD 67 DF' + 'DF 00 00 00 00 00 00 00 00 00 DF DF 03 9B D8 90' + '84 9C 7B 8E BA B7 B7 B7 B6 B5 B5 B7 B9 BA BA B9' + 'B7 B5 B5 B5 B6 B7 B9 AB 76 9C 85 7F B8 D7 43 DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 74 D6 B1' + 'A5 B4 93 AB B5 B4 B2 B5 BF C3 C5 C8 CC CF CF CD' + 'C9 C6 C4 C0 B6 B2 B4 B5 A5 B2 9B 93 BB CA 2D DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 4A D1 B3' + 'B1 AD B1 B3 B0 B1 C1 D2 CE C3 C0 BF BE BD BD BE' + 'BF C0 C3 CE D3 C3 B3 B0 B2 AD B0 B3 BB B6 23 DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 2F CB B2' + 'AF AF AF AC B8 CF C8 BE B6 B7 B8 B8 B8 B8 B8 B8' + 'B8 B8 B7 B7 BD C6 CF BC AC AF AF AD C1 8B 12 DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 24 B9 B4' + 'AC AD AC B6 CB BE B2 B3 B4 B4 B4 B4 B4 B4 B4 B4' + 'B4 B4 B4 B4 B3 B2 BA CC BA AB AC AB C2 70 06 DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 12 89 BD' + 'AC AD B0 C6 B6 B1 B3 B2 B2 B2 B2 B1 AF B0 B0 B0' + 'B0 B0 B0 B0 B0 B0 AE B2 C4 B1 A8 AB C4 53 DF DF' + 'DF 00 00 00 00 00 00 00 00 00 00 DF DF 05 69 BF' + 'AE AF BD B8 B0 B2 B2 B2 B2 B2 B2 B1 AE AB AC AC' + 'AC AC AC AC AC AC AC A9 B1 BC A8 AB C4 30 DF DF' + 'DF 00 00 00 00 00 00 00 00 00 00 00 DF DF 55 BF' + 'B1 B3 BD B3 B2 B2 B2 B2 B2 B2 B2 B2 B1 AB A5 A7' + 'A7 A7 A7 A7 A7 A7 A7 A7 A8 B5 A9 AB C0 26 DF DF' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 33 BE' + 'B3 B4 B6 B3 B3 B3 B3 B3 B3 B3 B3 B3 B3 B2 A9 9C' + '9C 9C A3 A3 A3 A3 A3 A3 A3 A8 A5 AD AE 1B DF DF' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 25 BA' + 'B6 B4 B2 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 B5 AF' + 'A8 A3 9B 9A 99 9A 9A 9A 9B 93 99 B0 84 0D DF DF' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 1A AE' + 'B8 B7 AE B7 B8 B8 B8 B8 B8 B8 B8 B8 B8 B8 B8 B9' + 'B8 B7 B5 B1 AE AB A7 A3 9B 85 91 B2 65 07 DF DF' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 0B 82' + 'BD BD B2 B4 BD BB BC BC BC BC BC BC BC BC BC BC' + 'BC BC BC BD BD BC BB BB B1 A5 AE AC 47 02 DF DF' + '00 00 00 00 00 00 00 00 00 00 00 00 DF DF 06 63' + 'BE C1 BE B0 B8 C0 BF BF BF BF BF BF BF BF BF BF' + 'BF BF BF BF BF BF C0 BA B0 BF BE A7 2C DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 44' + 'B5 C4 C3 C0 B0 B9 C3 C4 C2 C2 C2 C2 C2 C2 C2 C2' + 'C2 C2 C2 C2 C3 C3 BB AF BC C5 BB 8E 20 DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 2A' + 'AB C7 C5 C6 C3 B9 B4 BC C6 C7 C6 C6 C6 C6 C6 C6' + 'C6 C6 C7 C7 BE B4 B8 C2 C6 C8 B8 78 10 DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 1F' + '91 C8 C8 C8 C9 C9 C1 B4 B5 C0 C5 C5 C6 C6 C6 C6' + 'C5 C5 C0 B6 B3 BF C9 C9 C8 CA B6 66 08 DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 0E' + '7B C6 CF C9 C8 CE CD CC C6 C2 C1 C1 BF BE BE BF' + 'C1 C1 C1 C4 CB CE CC C7 CD CD B8 5A DF DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF 06' + '65 C6 C1 91 9A B8 CE CF CF D0 D0 CF CE CD CD CE' + 'CF D0 D0 CF D0 C6 9B 92 B3 CE B6 42 DF DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' + '5C C2 A3 84 8B 84 CD D3 D2 D2 D2 D2 D2 D2 D2 D2' + 'D2 D2 D2 D2 D5 B7 82 88 89 CD AF 34 DF DF DF 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' + '36 B0 BF BE B7 C6 DB DB DB DB DB DB DB DB DB DB' + 'DB DB DB DB DC D4 C1 BA BE B9 82 1E DF DF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' + '0C 53 92 B5 B9 BD BA BA BA BA BA BA BA BA BA BA' + 'BA BA BA BA BA BB BB B9 AF 82 32 04 DF DF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF DF' + 'DF 09 22 29 28 28 28 28 28 28 28 28 28 28 28 28' + '28 28 28 28 28 28 28 29 29 1D 02 DF DF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 DF' + 'DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' + 'DF DF DF DF DF DF DF DF DF DF DF DF 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 DF DF DF DF DF DF DF DF DF DF DF DF DF DF DF' + 'DF DF DF DF DF DF DF DF DF DF DF 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF F1 C7 FF FF 00 00 FF FF' + 'F0 87 FF FF 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'F8 0F FF FF 00 00 FF FF F0 07 FF FF 00 00 FF FF' + 'F2 07 FF FF 00 00 FC 00 00 00 00 7F 00 00 F8 00' + '00 00 00 3F 00 00 F8 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 3F 00 00 FC 00 00 00 00 3F 00 00 FC 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FE 00' + '00 00 00 7F 00 00 FE 00 00 00 00 7F 00 00 FF 00' + '00 00 00 7F 00 00 FF 00 00 00 00 FF 00 00 FF 00' + '00 00 00 FF 00 00 FF 00 00 00 01 FF 00 00 FF 80' + '00 00 03 FF 00 00 FF E0 00 00 07 FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 24 00 00 00 30 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 FF FF 00 00' + 'FF FF 00 00 00 3C 00 00 00 30 00 00 00 30 00 00' + '00 30 00 00 00 30 00 00 00 30 00 00 00 30 C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00 FF FF 00 00' + 'FF FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0' + 'C0 FF C0 C0 C0 FF C0 C0 C0 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 26 26 26 FF CD CD CD FF CD CD' + 'CD FF C9 C9 C9 FF C5 C5 C5 FF C2 C2 C2 FF C0 C0' + 'C0 FF BF BF BF FF BA BA BA FF B3 B4 B3 FF AB AC' + 'AC FF 09 09 09 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 30 D1 D1 D1 FF E7 E7 E7 FF 5F 5F' + '5F FF 8F 8F 8F FF A7 A7 A7 FF B9 B9 B9 FF B8 B8' + 'B8 FF 94 94 94 FF B7 B7 B7 FF C6 C3 C5 FF 91 D8' + 'B5 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 33 D1 D1 D1 FF EB EB EB FF 6C 6C' + '6C FF 8A 8A 8A FF A3 A3 A3 FF B9 B9 B9 FF A5 A5' + 'A5 FF 6B 6B 6B FF A4 A4 A4 FF C8 C8 C8 FF C2 C2' + 'C2 FF 8E 8E 8E FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 33 D3 D3 D3 FF F6 F6 F6 FF F5 F5' + 'F5 FF F4 F4 F4 FF F3 F3 F3 FF F1 F1 F1 FF F0 F0' + 'F0 FF EF EF EF FF EE EE EE FF ED ED ED FF EB EB' + 'EB FF 8D 8D 8D FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 25 DA DA DA FF A9 A9 A9 FF C3 C3' + 'C3 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' + 'D7 FF D8 D8 D8 FF D8 D8 D8 FF A8 A8 A8 FF B5 B5' + 'B5 FF 9C 9C 9C FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 7E 7E 7E FF CF CF CF FF D1 D1' + 'D1 FF DF DF DF FF E1 E1 E1 FF DC DC DC FF DC DC' + 'DC FF E1 E1 E1 FF E1 E1 E1 FF D0 D0 D0 FF D1 D1' + 'D1 FF 3F 3F 3F FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 22 22 FF CA CA CA FF E4 E4' + 'E4 FF D1 D1 D1 FF D0 D0 D0 FF CD CD CD FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF E2 E2 E2 FF C9 C9' + 'C9 FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF C3 C3' + 'C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF CB CB' + 'CB FF 00 00 00 F8 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 D8 DB DB DB FF D2 D2' + 'D2 FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF CF CF CF FF CA CA' + 'CA FF 00 00 00 B8 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 89 C9 C9 C9 FF E4 E4' + 'E4 FF D2 D2 D2 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4' + 'E4 FF E5 E5 E5 FF D2 D2 D2 FF E4 E4 E4 FF A8 A8' + 'A8 FF 00 00 00 4E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 99 99 99 FF BD BD' + 'BD FF EC EC EC FF EE EE EE FF EC EC EC FF EC EC' + 'EC FF EE EE EE FF E4 E4 E4 FF D1 D1 D1 FF 75 75' + '75 FF 00 00 00 06 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 19 19 19 FF D3 D3' + 'D3 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D9 D9 D9 FF CD CD CD FF 06 06' + '06 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 E0 03 00 00 C0 03 00 00 80 03' + '00 00 80 03 00 00 80 03 00 00 80 03 00 00 C0 03' + '00 00 C0 03 00 00 C0 03 00 00 C0 03 00 00 C0 03' + '00 00 C0 03 00 00 E0 07 00 00 F0 0F 00 00' +} */ + +/* BINRES cdrom.ico */ +11 ICON cdrom.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 4E 1F 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 76 20 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 5E 23 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 C6 27 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 2E 2E 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 D6 3C 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 01 01 00 01 02 02 00 02 03 03 00 05 05' + '05 00 06 06 06 00 07 07 07 00 09 09 09 00 0B 0B' + '0B 00 10 10 10 00 13 13 13 00 18 18 18 00 1B 1C' + '1B 00 1E 1E 1E 00 22 26 23 00 23 29 24 00 24 2E' + '25 00 3B 40 3C 00 3E 40 3F 00 40 41 40 00 41 43' + '42 00 42 44 43 00 46 48 47 00 4E 50 4F 00 50 52' + '51 00 54 55 55 00 56 56 56 00 57 57 57 00 57 58' + '58 00 59 59 59 00 5A 5A 5A 00 5A 5B 5B 00 5B 5C' + '5C 00 5D 5E 5E 00 5F 68 5F 00 71 71 72 00 72 72' + '73 00 74 74 74 00 77 76 77 00 78 76 77 00 72 78' + '72 00 79 76 78 00 7A 76 78 00 7B 77 79 00 7D 78' + '7A 00 7F 78 7B 00 7F 7F 7F 00 80 7A 7D 00 81 7C' + '7F 00 0E CE 0E 00 14 C2 15 00 10 CE 10 00 6D 90' + '6D 00 82 7D 80 00 84 80 83 00 86 83 85 00 8D 8B' + '8C 00 90 8F 90 00 95 96 95 00 97 97 97 00 98 98' + '98 00 98 99 99 00 99 9A 9A 00 9B 9C 9B 00 9F A0' + '9F 00 A7 A7 A7 00 A9 A8 A9 00 AB AA AA 00 AD AC' + 'AC 00 AE AE AE 00 B1 B0 B1 00 B3 B2 B3 00 B4 B3' + 'B4 00 B6 B6 B6 00 B8 B8 B8 00 B9 B9 B9 00 BB BB' + 'BB 00 BE BE BE 00 C0 C0 C0 00 C2 C3 C2 00 C3 C3' + 'C2 00 C5 C2 C3 00 C7 C1 C4 00 C9 C3 C5 00 CA C6' + 'C7 00 CA C8 C8 00 CA C9 C9 00 CB CA CA 00 CC CB' + 'CB 00 CD CB CB 00 CD CC CC 00 CD CD CD 00 CE CE' + 'CE 00 CE CF CF 00 CF CF CF 00 D0 D0 D0 00 D1 D1' + 'D1 00 D2 D2 D2 00 D4 D3 D3 00 D4 D4 D4 00 D5 D4' + 'D4 00 D7 D4 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DD DD DD 00 DE DE DE 00 FB D6 D7 00 FD D4' + 'D5 00 FE D4 D6 00 FE D4 DF 00 F7 D9 DA 00 F0 DE' + 'DF 00 EA DB E2 00 FE D3 E9 00 FE D3 ED 00 FE D4' + 'EF 00 F2 DA E8 00 F9 DA EF 00 FE D4 F1 00 FE D5' + 'F4 00 FE D6 F6 00 FC DB F4 00 FE D8 F9 00 FE DB' + 'F9 00 FE DC F8 00 E1 E0 E0 00 E7 E5 E6 00 E7 E6' + 'E6 00 E7 E7 E7 00 EA E3 E3 00 E8 E8 E8 00 E9 E9' + 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' + 'ED 00 EF EE EE 00 F0 EE EF 00 F0 EF F0 00 F1 F0' + 'F0 00 F1 F1 F1 00 F2 F2 F2 00 F2 F3 F3 00 F3 F5' + 'F5 00 F7 F6 F8 00 FA F7 FA 00 FB FA FB 00 FC F8' + 'FC 00 00 00 00 00 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 54 00' + '00 00 00 00 00 00 03 00 00 00 5C 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 88 36' + '0C 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 63 64 72 6F 6D 2E 69 63 6F' + '00 00 1A 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 99 99 0D 09 08 0C 99 99 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 99 21 11 45 4C 5D 55 21 14 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 99 23 4D 97 7F 7F 76 71 72 74 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 99 23 75 80 7B 7B 72 71 71 71 94 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 10 28 98 7C 78 7B 72 71 71 6F 94 92 00 00' + '99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99' + '99 10 1F 59 7D 78 78 7B 71 71 6F 93 92 92 00 99' + '08 15 19 17 21 23 1F 1D 1D 1E 1E 1D 1D 1C 1C 1F' + '1F 12 40 81 78 78 78 7B 71 71 8E 91 92 92 99 99' + '37 6A 82 83 50 32 98 8B 84 82 67 64 64 64 61 63' + '1B 17 75 7C 78 7B 78 78 7B 7F 7F 7B 93 92 99 03' + '65 94 89 81 31 31 33 79 5C 5E 5A 5B 5B 5B 67 24' + '0E 23 97 7A 92 77 7B 78 7F 53 6F 7F 8E 8F 99 07' + '83 8D 89 98 34 31 41 52 4E 4E 4E 4E 4E 4E 50 4E' + '2F 27 97 93 93 8C 7A 7F 48 40 23 70 7E 90 99 05' + '92 8B 93 3A 2B 38 2A 25 25 25 25 25 25 25 25 26' + '23 3A 97 92 92 93 92 7E 10 00 00 3A 81 93 99 04' + '92 8F 91 44 39 3A 3F 3F 3F 3F 3F 3D 3C 3C 3C 3E' + '35 40 97 92 92 93 76 7E 11 99 00 52 7E 8D 99 03' + '90 8F 89 90 8A 89 87 86 82 82 82 82 82 82 82 83' + '47 3D 97 92 92 93 8E 7C 53 38 52 81 7E 76 99 02' + '96 96 8A 8D 88 87 87 87 88 88 87 87 87 87 85 8B' + '4B 23 97 92 92 92 8F 8D 7F 81 7F 7F 77 7B 99 01' + '97 82 46 46 66 68 67 67 67 67 66 66 66 67 67 6A' + '50 22 95 93 92 92 92 94 72 71 71 76 7B 78 99 99' + '94 5F 44 44 51 69 66 64 63 63 67 68 66 63 63 64' + '82 23 49 97 92 92 92 94 6F 71 71 76 7B 78 00 99' + '55 86 58 55 5C 5F 60 60 61 64 63 63 63 64 5F 62' + '62 84 20 65 94 92 92 71 71 71 71 76 78 78 00 99' + '3F 86 5A 5C 5B 60 63 63 64 66 66 66 66 66 64 68' + '82 68 3B 2D 97 95 6F 71 71 71 77 7B 7B 7C 00 99' + '22 82 55 56 64 61 60 60 60 5F 61 60 60 61 60 5F' + '5C 62 69 3A 38 73 6F 71 71 77 7B 7B 81 75 00 99' + '11 6C 57 5F 62 5F 5F 5E 5E 5F 62 60 62 62 62 62' + '60 62 5C 5B 39 36 57 72 81 81 98 98 48 3A 00 99' + '0B 57 62 61 60 5E 5F 5F 5F 5E 5E 62 62 62 62 62' + '62 62 66 4D 4A 0C 02 13 19 18 16 15 99 00 00 99' + '08 4A 66 61 61 60 60 60 60 60 61 61 61 61 61 61' + '61 61 64 4C 48 0F 99 00 00 00 00 00 00 00 00 99' + '99 3A 82 66 67 67 67 67 67 67 67 67 63 64 64 64' + '63 64 5E 54 5A 10 99 00 00 00 00 00 00 00 00 99' + '99 23 8A 6D 6E 6D 6B 6B 6B 6B 6B 6B 6C 6D 6D 6C' + '6E 83 84 6E 46 0A 99 00 00 00 00 00 00 00 00 00' + '99 11 84 86 82 82 82 82 86 82 82 82 82 82 82 82' + '83 85 84 83 38 02 99 00 00 00 00 00 00 00 00 00' + '99 0B 82 87 85 88 8B 8A 8A 87 88 88 88 88 87 84' + '85 87 85 84 23 99 99 00 00 00 00 00 00 00 00 00' + '99 99 56 90 69 83 8B 8B 8A 8A 8A 89 8A 8B 8B 8B' + '87 69 89 8B 17 99 99 00 00 00 00 00 00 00 00 00' + '99 99 4F 6B 43 45 92 8F 8F 8F 8F 8D 8F 8F 8F 94' + '54 42 5A 92 12 99 99 00 00 00 00 00 00 00 00 00' + '00 99 24 6E 88 8B 97 97 97 97 97 97 97 97 97 97' + '95 87 83 4C 06 99 00 00 00 00 00 00 00 00 00 00' + '00 99 07 1A 30 2C 29 29 29 29 29 29 29 29 29 29' + '2B 2F 23 10 99 99 00 00 00 00 00 00 00 00 00 00' + '00 00 99 99 99 99 99 99 99 99 99 99 99 99 99 99' + '99 99 99 99 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF 00 FF FF FE 00 FF FF FC 00 FF FF F8 00 FF FF' + 'F0 00 C0 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' + '00 7F C0 00 00 7F C0 00 00 7F C0 00 00 7F E0 00' + '00 FF E0 00 00 FF F0 00 03 FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 05 05 05 00 0C 0F' + '0F 00 0D 11 0E 00 15 15 15 00 36 36 36 00 39 39' + '39 00 40 43 41 00 44 47 45 00 53 53 53 00 5B 60' + '5D 00 67 68 68 00 64 6A 69 00 69 69 69 00 6B 6C' + '6B 00 6E 6E 6E 00 6F 6E 6E 00 6F 70 70 00 72 72' + '72 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F 7F 00 00 FF' + '00 00 75 99 75 00 88 6C 88 00 84 7E 84 00 8B 7E' + '82 00 80 80 80 00 84 84 84 00 93 93 93 00 97 97' + '97 00 9A 98 98 00 9B 9B 9B 00 9D 9D 9D 00 9F 9F' + '9F 00 A0 A0 A0 00 A5 A5 A5 00 A6 A6 A6 00 A8 A2' + 'A8 00 B8 AC B8 00 BB BB BB 00 A6 D4 A6 00 D8 AE' + 'C6 00 CB BD C9 00 C0 C0 C0 00 C2 C2 C2 00 C2 C3' + 'C3 00 C3 C3 C3 00 C8 C8 C8 00 C9 C9 C9 00 CE CE' + 'CE 00 CF CF CF 00 D3 C2 CD 00 D0 D0 D0 00 D1 D1' + 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D6 D0 D6 00 D4 D4' + 'D4 00 D5 D5 D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8' + 'D8 00 D9 D9 D9 00 DA DA DA 00 DB DB DB 00 DC DC' + 'DC 00 DE DE DE 00 FF D2 CD 00 FF D2 CE 00 E2 C2' + 'DA 00 FF D8 D7 00 FF D4 D8 00 FA DD DA 00 FD DC' + 'DC 00 FF DE DF 00 F4 D7 EA 00 FF D3 E8 00 FF D6' + 'E8 00 FF D7 EF 00 FF D3 F1 00 FF D3 F2 00 FF D3' + 'F3 00 FF D4 F5 00 FF D7 F7 00 FF D9 F7 00 FD D9' + 'FB 00 E1 E1 E1 00 E3 E4 E3 00 E4 E4 E4 00 E5 E5' + 'E5 00 E6 E6 E6 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' + 'EA 00 EA EB EB 00 EB EB EB 00 ED ED ED 00 FF E3' + 'E1 00 F5 EA EF 00 FF EF EF 00 FD E7 F4 00 FB ED' + 'F4 00 FE E7 FA 00 FF E2 FF 00 FF E9 FF 00 FF ED' + 'FE 00 FF EE FF 00 EE F9 F7 00 F1 F1 F1 00 F1 F3' + 'F2 00 F2 F2 F2 00 F3 F3 F3 00 F0 F5 F2 00 F0 F6' + 'F3 00 F0 F7 F7 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' + 'F6 00 FF F0 FF 00 FF F3 FF 00 FF F6 FF 00 F9 F9' + 'F9 00 FA FA FA 00 FB FB FB 00 FC FC FC 00 FD FD' + 'FD 00 FF FD FE 00 FE FE FE 00 FF FF FF 00 00 00' + '00 00 E7 E5 E6 00 E7 E6 E6 00 E7 E7 E7 00 EA E3' + 'E3 00 E8 E8 E8 00 E9 E9 E9 00 EA EA EA 00 EB EB' + 'EB 00 EC EC EC 00 ED ED ED 00 EF EE EE 00 F0 EE' + 'EF 00 F0 EF F0 00 F1 F0 F0 00 F1 F1 F1 00 F2 F2' + 'F2 00 F2 F3 F3 00 F3 F5 F5 00 F7 F6 F8 00 FA F7' + 'FA 00 FB FA FB 00 FC F8 FC 00 00 00 00 00 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 54 00 00 00 00 00 00 00 03 00' + '00 00 5C 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 63' + '64 72 6F 6D 2E 69 63 6F 00 00 1A 93 4B 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 03 0A 0C 02 00 00 00 00 00 00 00 00 00 00' + '00 0E 6B 68 4B 64 00 82 82 82 82 82 82 82 82 82' + '11 77 53 45 49 73 82 10 26 17 27 25 22 21 23 08' + '4C 52 50 4E 67 71 82 7F 79 16 29 39 33 38 28 09' + '81 63 55 2B 2A 66 82 81 30 18 19 14 14 13 1B 1C' + '80 72 6A 82 07 79 82 81 74 6D 61 60 60 60 6F 1E' + '7E 6E 65 46 56 4F 82 7D 24 38 3D 3B 3D 3C 41 1D' + '5F 74 6C 47 48 51 82 3D 32 32 37 3A 3B 3B 38 58' + '1A 81 4A 44 4D 54 82 20 37 38 35 35 36 37 37 38' + '2E 1F 62 69 78 34 00 0D 43 35 35 35 36 37 37 38' + '36 0B 00 00 00 00 00 06 61 40 3E 3F 3F 3E 3E 42' + '57 12 00 00 00 00 00 01 70 5E 5C 5B 5A 5A 59 60' + '75 05 00 00 00 00 00 82 5D 31 7A 76 74 75 7B 32' + '7C 04 00 00 00 00 00 82 0F 2C 2F 2D 2D 2D 2D 2C' + '1E 82 00 00 00 00 00 00 82 82 82 82 82 82 82 82' + '82 00 00 00 00 00 FF F0 00 00 FF E0 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 0F' + '00 00 80 0F 00 00 80 0F 00 00 80 0F 00 00 80 0F' + '00 00 C0 1F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0C 00 00 00 30 00 00 00 48 00 00 00 90 00 00' + '00 90 00 00 00 90 00 00 00 78 00 00 00 30 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 86 86' + '86 FF 7A 7A 7A FF AA AA AA FF DA DA DA FF F2 F2' + 'F2 FF CE CE CE FF AA AA AA FF 6E 6E 6E FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0C 7A 7A 7A FF 80 80' + '80 FF FF FF FF FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 D4 FF FF D4 D4 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + '00 13 00 00 00 78 6E 6E 6E FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 56 62 62 62 FF E6 E6 E6 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 05 00 00 00 69 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 62 62 62 FF 56 56' + '56 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 9B 00 00 00 FF 21 21 21 FF 2C 2C' + '2C FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 4A 4A 4A FF 62 62' + '62 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 03 01 01 01 FF 8A 8A 8A FF EB EB EB FF E8 E8' + 'E8 FF E8 E8 E8 FF D4 D4 D4 FF 00 C0 00 FF E7 E7' + 'E7 FF E8 E8 E8 FF E3 E3 E3 FF D8 D8 D8 FF D2 D2' + 'D2 FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' + 'C9 FF AA AA AA FF 2E 2E 2E FF 62 62 62 FF DA DA' + 'DA FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 FF FF FF D4 FF FF FF D4' + 'FF FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 15 19 19 19 FF AD A8 AB FF EB EB EB FF E8 E8' + 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF 00 C0' + '00 FF DF DF DF FF D5 D5 D5 FF D2 D2 D2 FF CB CB' + 'CB FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF 40 40 40 FF 2E 2E 2E FF 7A 7A 7A FF F2 F2' + 'F2 FF FF D4 E3 FF F2 F2 F2 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 FF FF FF D4 E3 FF FF D4' + 'E3 FF FF D4 FF FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 34 28 28 28 FF D1 D1 D1 FF EB EB EB FF EB EB' + 'EB FF E8 E8 E8 FF E8 E8 E8 FF 00 FF 00 FF B5 B5' + 'B5 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B6 B6 B6 FF A4 A0 A0 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF B6 B6 B6 FF AA AA AA FF 62 62' + '62 FF FF D4 E3 FF FF D4 F0 FF F2 F2 F2 FF 00 00' + '00 33 28 28 28 FF D1 D1 D1 FF E8 E8 E8 FF EB EB' + 'EB FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF B6 B6 B6 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 E3 FF 6E 6E 6E FF 00 00 00 00 00 00' + '00 00 B6 B6 B6 FF FF D4 F0 FF F2 F2 F2 FF 00 00' + '00 33 27 27 27 FF D2 D2 D2 FF EA EA EA FF EB EB' + 'EB FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' + 'AE FF AF AF AF FF AF AF AF FF AF AF AF FF AF AF' + 'AF FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF CE CE CE FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'E3 FF FF D4 E3 FF 80 80 80 FF 00 00 00 78 00 00' + '00 00 FF D4 F0 FF FF D4 F0 FF F2 F2 F2 FF 00 00' + '00 33 26 26 26 FF D3 D3 D3 FF E8 E8 E8 FF E6 E6' + 'E6 FF E2 E2 E2 FF DB DB DB FF D8 D8 D8 FF D9 D9' + 'D9 FF D2 D2 D2 FF CF CF CF FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CE CE CE FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF C0 C0 C0 FF 62 62 62 FF 80 80' + '80 FF FF D4 F0 FF FF D4 F0 FF FF D4 E3 FF 00 00' + '00 33 24 24 24 FF D6 D6 D6 FF E9 E9 E9 FF E1 E1' + 'E1 FF E2 E2 E2 FF E0 E0 E0 FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF 92 92 92 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 FF FF FF D4 FF FF FF D4' + 'FF FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 34 24 24 24 FF DE DE DE FF D9 D9 D9 FF C4 C4' + 'C4 FF BF BF BF FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF 7A 7A 7A FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 07 05 05 05 FF C2 C2 C2 FF BC BC BC FF B2 B2' + 'B2 FF AB AB AB FF BB BB BB FF D5 D5 D5 FF D5 D5' + 'D5 FF D4 D4 D4 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' + 'D7 FF D8 D8 D8 FF D7 D7 D7 FF D3 D3 D3 FF D3 D3' + 'D3 FF D4 D4 D4 FF D5 D5 D5 FF 62 62 62 FF 86 86' + '86 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 FF A4 A4 A4 FF CF CF CF FF C5 C5' + 'C5 FF BF BF BF FF C9 C9 C9 FF D2 D2 D2 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' + 'D0 FF D4 D4 D4 FF D0 D0 D0 FF D3 D3 D3 FF 62 62' + '62 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 FF 59 59 59 FF D0 D0 D0 FF CD CD' + 'CD FF CD CD CD FF CA CA CA FF D3 D3 D3 FF D3 D3' + 'D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF DB DB DB FF E4 E4 E4 FF D3 D3 D3 FF D3 D3' + 'D3 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 FE 40 40 40 FF D2 D2 D2 FF CA CA' + 'CA FF CA CA CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D3 D3 D3 FF D2 D2 D2 FF D3 D3 D3 FF D2 D2' + 'D2 FF D1 D1 D1 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' + 'D3 FF 6E 6E 6E FF 92 92 92 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 E1 07 07 07 FF DD DD DD FF CC CC' + 'CC FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF C4 C4 C4 FF B3 B3 B3 FF 62 62 62 FF 9E 9E' + '9E FF FF D4 D4 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF CE CE CE FF 9E 9E 9E FF 92 92 92 FF 00 00' + '00 00 00 00 00 B2 00 00 00 FF DD DD DD FF CF CF' + 'CF FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' + 'CF FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF B3 B3 B3 FF B3 B3 B3 FF 00 00 00 FF 00 00' + '00 FF 62 62 62 FF 86 86 86 FF 86 86 86 FF 86 86' + '86 FF 6E 6E 6E FF 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 4B 00 00 00 FE D8 D8 D8 FF D4 D4' + 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF B3 B3 B3 FF B3 B3 B3 FF 00 00 00 CF 00 00' + '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 00 00 00 F2 CC CC CC FF D6 D6' + 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4' + 'C4 FF BD BD BD FF D0 D0 D0 FF 09 09 09 FF 00 00' + '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 02 00 00 00 BF 97 97 97 FF DC DC' + 'DC FF DC DC DC FF DE DE DE FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF E7 E7 E7 FF E7 E7' + 'E7 FF DC DC DC FF C6 C6 C6 FF 00 00 00 FF 00 00' + '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 77 77 77 FF D3 D3' + 'D3 FF E1 E1 E1 FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7 E7 FF E7 E7' + 'E7 FF D9 D9 D9 FF BB BB BB FF 00 00 00 FF 00 00' + '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 62 35 35 35 FF BD BD' + 'BD FF E6 E6 E6 FF E6 E6 E6 FF E7 E7 E7 FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' + 'E6 FF D4 D4 D4 FF 9A 9A 9A FF 00 00 00 ED 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 2D 1E 1E 1E FF AB AB' + 'AB FF ED ED ED FF E7 E7 E7 FF EC EC EC FF EB EB' + 'EB FF ED ED ED FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EC EC EC FF E5 E5 E5 FF EB EB' + 'EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00 00 C3 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 8D 8D' + '8D FF C4 C4 C4 FF B2 B2 B2 FF B2 B2 B2 FF EB EB' + 'EB FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F3 F3 F3 FF D5 D5 D5 FF B6 B6 B6 FF B7 B7' + 'B7 FF CD CD CD FF 61 61 61 FF 00 00 00 85 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FF 64 64' + '64 FF DD DD DD FF DC DC DC FF E4 E4 E4 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF FA FA FA FF F2 F2 F2 FF D8 D8 D8 FF DC DC' + 'DC FF B0 B0 B0 FF 34 34 34 FF 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 9C 00 00' + '00 FF 3D 3D 3D FF 49 49 49 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' + '49 FF 02 02 02 FF 00 00 00 FF 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' + '00 7F 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 D6 00 00 00 5C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF 00 FF FF FE 00 FF FF FC 00 FF FF E0 00 FF FF' + 'F0 00 80 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' + '00 7F C0 00 00 7F C0 00 00 7F E0 00 00 7F E0 00' + '00 FF E0 00 01 FF E0 00 01 FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 08 FF FF 00 00 00 00 00 8F FF FF 08 88' + '88 88 80 FF FF FF 0F FA F7 77 88 FF F7 FF 0F 88' + '88 88 88 FF F0 8F 0F FF FF FF F8 FF F8 FF 0F 77' + '77 77 78 FF FF FF 07 77 77 77 77 7F FF FF 07 77' + '77 77 77 8F FF FF 07 77 77 77 77 70 28 80 08 77' + '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 77' + '77 77 77 70 00 00 00 77 77 77 77 70 00 00 00 00' + '00 00 00 00 00 00 FF E0 00 00 FF C0 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01' + '00 00 00 07 00 00 80 07 00 00 80 07 00 00 80 0F' + '00 00 C0 1F 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 77 77 88 00 00' + '00 00 00 00 00 00 00 00 00 08 7F FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 8F FF FF FF FF 00 00' + '00 00 00 00 00 00 00 00 08 FF FF FF FF FF 00 00' + '00 00 00 00 00 00 00 00 87 FF FF FF FF FF 00 08' + '88 88 88 88 88 88 88 80 8F FF FF FF FF FF 00 87' + 'FF 7A FF FF 77 77 77 88 FF FF FF FF FF FF 00 7F' + 'FF AA AF 77 77 77 78 08 FF FF FF F7 FF FF 00 FF' + 'FF 8A 77 77 77 77 77 88 FF FF FF 78 8F FF 00 FF' + 'F8 88 88 88 88 88 88 88 FF FF FF 00 08 FF 00 FF' + 'F7 88 88 88 88 88 88 88 FF FF FF 00 07 FF 00 FF' + 'FF FF FF FF FF FF FF 78 FF FF FF 78 7F FF 00 FF' + 'FF FF FF FF FF FF FF 78 FF FF FF FF FF FF 00 FF' + '77 77 77 77 77 77 77 78 FF FF FF FF FF FF 00 F7' + '77 77 77 77 77 77 77 78 7F FF FF FF FF FF 00 77' + '77 77 77 77 77 77 77 77 87 FF FF FF FF FF 00 87' + '77 77 77 77 77 77 77 77 88 FF FF FF FF FF 00 87' + '77 77 77 77 77 77 77 77 78 8F FF FF FF FF 00 07' + '77 77 77 77 77 77 77 77 77 88 7F FF FF 78 00 07' + '77 77 77 77 77 77 77 77 77 70 02 88 88 70 00 07' + '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 08' + '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 08' + '77 77 77 77 77 77 77 77 77 70 00 00 00 00 00 00' + '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' + '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' + '77 77 77 77 77 77 77 77 77 80 00 00 00 00 00 00' + '77 77 77 77 77 77 77 77 77 00 00 00 00 00 00 00' + '87 77 77 77 77 77 77 77 77 00 00 00 00 00 00 00' + '08 88 88 88 88 88 88 88 80 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF 00 FF FF FE 00 FF FF FC 00 FF FF F8 00 FF FF' + 'F0 00 C0 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 18 00 00 00 08 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 80 00 00 00 80 00 00 00 80 00 00 00 80 00' + '00 01 80 00 00 7F 80 00 00 7F 80 00 00 7F C0 00' + '00 7F C0 00 00 7F C0 00 00 7F C0 00 00 7F E0 00' + '00 FF E0 00 00 FF F0 00 03 FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 78 6E 6E 6E FF 62 62' + '62 FF 00 00 00 9C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 62 62 62 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'D4 FF FF D4 D4 FF 00 00 00 00 00 00 00 16 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 42 62 62' + '62 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF F2 F2 F2 FF 00 00 00 54 90 90 90 FF AB AC' + 'AC FF CC CC CC FF C4 C4 C4 FF C2 C2 C2 FF C1 C1' + 'C1 FF BC BC BC FF BD BD BD FF 6E 6E 6E FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'E3 FF F2 F2 F2 FF 00 00 00 FA EA EA EA FF E8 E8' + 'E8 FF 00 FF 00 FF CB CB CB FF C8 C8 C8 FF C8 C8' + 'C8 FF C8 C8 C8 FF C8 C8 C8 FF 56 56 56 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 F0 FF B6 B6 B6 FF FF B1' + 'C7 FF FF D4 E3 FF 00 00 00 F9 EF EF EF FF EB EB' + 'EB FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 62 62 62 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 F0 FF 00 00 00 78 62 62' + '62 FF F2 F2 F2 FF 00 00 00 F9 F7 F7 F7 FF F6 F6' + 'F6 FF F5 F5 F5 FF F3 F3 F3 FF F2 F2 F2 FF F1 F1' + 'F1 FF F0 F0 F0 FF EF EF EF FF 62 62 62 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4 E3 FF FF D4' + 'FF FF FF D4 F0 FF 00 00 00 F7 F3 F3 F3 FF B7 B7' + 'B7 FF DA DA DA FF D8 D8 D8 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D8 D8 D8 FF D3 D3 D3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF 00 00 00 73 EF EF EF FF CB CB' + 'CB FF CE CE CE FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D3 D3 D3 FF 7A 7A' + '7A FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF 00 00 00 25 B7 B7 B7 FF CB CB' + 'CB FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4' + 'C4 FF 80 80 80 FF FF D4 D4 FF FF D4 F0 FF FF D4' + 'F0 FF E6 E6 E6 FF 00 00 00 00 5F 5F 5F FF D2 D2' + 'D2 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF 99 99 99 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 18 18 18 FF DB DB' + 'DB FF DE DE DE FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DD DD DD FF DD DD DD FF DD DD DD FF D9 D9' + 'D9 FF 7A 7A 7A FF 00 00 00 0A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 FF E5 E5' + 'E5 FF EB EB EB FF EB EB EB FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E7 E7 E7 FF E6 E6' + 'E6 FF 20 20 20 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 DD E4 E4' + 'E4 FF C1 C1 C1 FF ED ED ED FF EE EE EE FF EB EB' + 'EB FF ED ED ED FF ED ED ED FF C2 C2 C2 FF EC EC' + 'EC FF 00 00 00 FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 44 80 80' + '80 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF B0 B0' + 'B0 FF 00 00 00 ED 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 2C 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 70 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF F0 00 00 FF E0 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 0F' + '00 00 80 07 00 00 80 0F 00 00 80 0F 00 00 80 0F' + '00 00 C0 1F 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 08 88 88 80 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '88 87 77 F7 77 88 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 08 87 FF FF FF FF F7 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87' + 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 08 FF FF FF FF FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 08 8F FF' + 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 88 7F FF FF FF FF FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 08 88 FF FF' + 'FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 08 8F FF FF FF FF FF FF FF FF 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 88 8F FF FF' + 'FF FF FF FF FF FF 00 08 7F FF F7 AA FF FF 77 77' + '77 77 77 70 88 7F FF FF FF FF FF FF FF FF 00 07' + 'FF FF FA AA AF 77 77 77 77 77 77 00 88 FF FF FF' + 'FF FF FF FF FF FF 00 07 FF FF FA AA A7 77 77 77' + '77 77 77 80 88 FF FF FF FF FF 78 87 FF FF 00 07' + 'FF FF FF AA 77 77 77 77 77 77 77 77 87 FF FF FF' + 'FF F7 87 88 FF FF 00 07 FF FF 88 88 88 88 88 88' + '88 88 88 88 87 FF FF FF FF F8 00 08 7F FF 00 07' + 'FF FF 88 88 88 88 88 88 88 88 88 88 87 FF FF FF' + 'FF F8 00 08 7F FF 00 07 FF FF 77 77 77 77 77 77' + '77 77 77 77 87 FF FF FF FF F8 00 08 FF FF 00 07' + 'FF FF F7 77 77 77 77 77 77 77 77 77 87 FF FF FF' + 'FF F7 88 8F FF FF 00 07 FF FF FF FF FF FF FF FF' + 'FF FF FF FF 87 FF FF FF FF FF FF FF FF FF 00 07' + 'FF FF FF 77 77 7F FF FF FF FF FF FF 88 FF FF FF' + 'FF FF FF FF FF FF 00 07 77 77 77 77 77 77 77 77' + '77 77 77 77 88 FF FF FF FF FF FF FF FF FF 00 07' + '77 77 77 77 77 77 77 77 77 77 77 77 78 7F FF FF' + 'FF FF FF FF FF FF 00 07 77 77 77 77 77 77 77 77' + '77 77 77 77 78 8F FF FF FF FF FF FF FF FF 00 07' + '77 77 77 77 77 77 77 77 77 77 77 77 77 87 FF FF' + 'FF FF FF FF FF FF 00 08 77 77 77 77 77 77 77 77' + '77 77 77 77 77 88 7F FF FF FF FF FF FF FF 00 08' + '77 77 77 77 77 77 77 77 77 77 77 77 77 78 8F FF' + 'FF FF FF FF FF FF 00 00 77 77 77 77 77 77 77 77' + '77 77 77 77 77 77 88 FF FF FF FF FF FF FF 00 00' + '77 77 77 77 77 77 77 77 77 77 77 77 77 77 78 87' + 'FF FF FF FF FF F8 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 88 87 FF FF FF 78 88 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '08 88 88 88 80 00 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '00 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' + '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' + '00 77 77 77 77 77 77 77 77 77 77 77 77 77 78 00' + '00 00 00 00 00 00 00 00 00 77 77 77 77 77 77 77' + '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' + '00 87 77 77 77 77 77 77 77 77 77 77 77 77 78 00' + '00 00 00 00 00 00 00 00 00 87 77 77 77 77 77 77' + '77 77 77 77 77 77 78 00 00 00 00 00 00 00 00 00' + '00 87 77 77 77 77 77 77 77 77 77 77 77 77 70 00' + '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' + '77 77 77 77 77 77 80 00 00 00 00 00 00 00 00 00' + '00 00 08 88 88 88 88 88 88 88 88 88 88 80 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF F0 00 00 00 FF FF FF FF E0 00 00 00 FF FF' + 'FF FF C0 00 00 00 FF FF FF FF 80 00 00 00 FF FF' + 'FF FE 00 00 00 00 FF FF FF FE 00 00 00 00 FF FF' + 'FF FC 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 00' + '00 00 00 60 00 00 00 00 00 00 00 20 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' + '00 00 00 07 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' + '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' + '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' + '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' + '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 18 18' + '18 00 19 19 19 00 1E 1E 1E 00 1F 1F 1F 00 20 20' + '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' + '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2A 2A' + '2A 00 2B 2B 2B 00 2C 2C 2C 00 2E 2E 2E 00 2F 2F' + '2F 00 34 34 34 00 35 35 35 00 39 39 39 00 3D 3D' + '3D 00 40 40 40 00 41 41 41 00 48 48 48 00 49 49' + '49 00 4A 4A 4A 00 4B 4B 4B 00 53 53 53 00 56 56' + '56 00 59 59 59 00 5D 5D 5D 00 5F 5F 5F 00 61 61' + '61 00 62 62 62 00 64 64 64 00 6E 6E 6E 00 75 75' + '75 00 77 77 77 00 7A 7A 7A 00 7E 7E 7E 00 7F 7F' + '7F 00 00 C0 00 00 00 FF 00 00 80 80 80 00 83 83' + '83 00 86 86 86 00 8A 8A 8A 00 8D 8D 8D 00 90 90' + '90 00 92 92 92 00 93 93 93 00 97 97 97 00 99 99' + '99 00 9A 9A 9A 00 9E 9E 9E 00 9F 9F 9F 00 A4 A0' + 'A0 00 A4 A4 A4 00 A7 A7 A7 00 A8 A8 A8 00 A9 A9' + 'A9 00 AA AA AA 00 AB AB AB 00 AD A8 AB 00 AB AC' + 'AC 00 AD AD AD 00 AE AE AE 00 AF AF AF 00 B0 B0' + 'B0 00 B2 B2 B2 00 B3 B3 B3 00 B5 B5 B5 00 B6 B6' + 'B6 00 B7 B7 B7 00 B8 B4 B6 00 B8 B8 B8 00 BA BA' + 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' + 'BE 00 BF BF BF 00 FF B1 C7 00 C0 C0 C0 00 C1 C1' + 'C1 00 C2 C2 C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5' + 'C5 00 C6 C6 C6 00 C8 C8 C8 00 C8 C9 C9 00 C9 C9' + 'C9 00 CA CA CA 00 CB CB CB 00 CC CC CC 00 CD CD' + 'CD 00 CE CE CE 00 CF CF CF 00 D0 D0 D0 00 D1 D1' + 'D1 00 D2 D2 D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5' + 'D5 00 D6 D6 D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9' + 'D9 00 DA DA DA 00 DB DB DB 00 DC DC DC 00 DD DD' + 'DD 00 DE DE DE 00 DF DF DF 00 FF D4 D4 00 FF D4' + 'E3 00 FF D4 F0 00 FF D4 FF 00 E0 E0 E0 00 E1 E1' + 'E1 00 E2 E2 E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5' + 'E5 00 E6 E6 E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9' + 'E9 00 EA EA EA 00 EB EB EB 00 EC EC EC 00 ED ED' + 'ED 00 EE EE EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1' + 'F1 00 F2 F2 F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5' + 'F5 00 F6 F6 F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9' + 'F9 00 FA FA FA 00 FF FF FF 00 00 00 00 00 78 EE' + '0C 01 78 EE 0C 01 40 00 00 00 40 00 00 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 70 EE 0C 01 00 24 0D 01 01 01' + 'F5 77 78 01 38 00 78 EE 0C 01 E0 19 0D 01 E8 19' + '0D 01 78 01 38 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 BE B3 E7 77 70 EE 0C 01 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 08 04 00 00 E4 00 00 00 08 04 00 00 08 01' + '00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00' + '38 00 BC 18 95 00 C0 18 95 00 B0 19 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 81 E9' + '49 00 00 00 38 00 00 00 00 00 78 EE 0C 01 78 EE' + '0C 01 A4 1A 95 00 40 00 00 00 40 00 00 00 B8 10' + 'E9 77 FF FF FF FF C9 F1 E7 77 16 EA 4B 00 F8 00' + '00 00 B4 1A 95 00 DC E3 49 00 E0 A3 4E 00 FF FF' + 'FF FF 10 00 00 00 10 DA 4B 00 78 EE 0C 01 71 CC' + '43 00 78 EE 0C 01 50 7E 0D 01 A4 1A 95 00 F8 A2' + 'AF 00 C4 F5 AF 00 04 00 00 00 50 7E 0D 01 0F 02' + '00 00 B8 EE 0C 01 10 00 00 00 00 00 00 00 20 00' + '00 00 78 EE 0C 01 40 00 00 00 10 00 00 00 00 01' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 10 00 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 35 2D 2B' + '2B 2B 35 9D 9D 9D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 9D 9D 37 2D 30 47 6B 77' + '93 77 6B 47 35 2D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 9D 9D 30 35 6B 9C 7F 7F 7F' + '7F 7D 7D 7D 7D 5D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 9D 9D 9D 2B 5D 7F 7F 7F 7F 7F 7F' + '7D 7D 7D 7D 7D 93 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 9D 9D 9D 2D 87 7F 7F 7F 7F 7F 7F 7D' + '7D 7D 7D 7D 93 93 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 9D 26 2B 87 7F 7F 7F 7F 7F 7F 7D 7D' + '7D 7D 7D 93 93 93 00 00 00 00 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 23 2B 5F 7F 7F 7F 7F 7F 7F 7D 7D 7D' + '7D 7D 93 93 93 93 00 00 9D 9D 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 2B 26 3B 7F 7F 7F 7F 7F 7F 7F 7D 7D 7D' + '7D 93 93 93 93 93 00 9D 9D 9D 9D 0F 18 17 18 17' + '17 17 17 17 17 17 17 17 17 17 16 16 16 16 16 16' + '16 16 16 23 2B 93 7F 7F 7F 7F 7F 7F 7F 7D 7D 7D' + '93 93 93 93 93 93 00 9D 9D 12 3A 54 4B 4A 49 6A' + '69 68 66 61 60 5F 5F 60 5D 5E 5B 5B 58 59 56 59' + '59 59 2D 26 40 7F 7F 7F 7F 7F 7F 7F 7F 7D 7D 7F' + '7E 7E 93 93 93 93 9D 9D 01 38 49 8C 89 89 89 71' + '33 33 88 89 89 84 7A 75 6F 6A 6A 6A 6A 6A 65 6A' + '47 19 26 2B 77 7F 7F 7F 7F 7F 7F 7F 7F 80 80 80' + '80 80 7F 93 93 93 9D 9D 0B 49 8C 8C 89 89 89 34' + '34 34 33 82 7C 72 69 6F 68 6A 6A 6A 6A 6A 6A 6A' + '1F 19 26 30 93 93 7E 93 7F 7F 7F 7F 7F 80 7F 7E' + '7E 80 80 93 93 93 9D 9D 15 49 8B 8C 8C 89 89 34' + '34 34 34 68 64 64 64 64 64 64 64 64 64 64 64 64' + '3C 1F 26 3B 93 93 93 93 93 7E 7F 7F 7F 7F 52 35' + '3B 5C 7F 7F 7E 93 9D 9D 14 6E 8D 8C 8C 89 89 89' + '34 34 51 51 52 52 52 52 52 52 52 52 52 52 52 52' + '52 52 26 42 93 93 93 93 93 93 93 7F 7F 52 2D 47' + '2B 30 7E 7F 93 93 9D 9D 14 6E 8F 89 8C 89 35 35' + '35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35' + '35 35 2B 52 93 93 93 93 93 93 93 7F 7E 2D 00 00' + '00 2B 52 7F 93 93 9D 9D 13 6E 90 8C 8C 8C 35 35' + '35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35' + '35 35 2B 52 93 93 93 93 93 93 93 7F 7D 2B 9D 00' + '00 2B 52 7F 93 93 9D 9D 13 6F 93 8B 8C 8C 44 44' + '44 48 4C 4E 4D 4D 4D 4D 4D 4D 48 48 48 48 48 48' + '48 48 2B 6B 93 93 93 93 93 93 7E 7F 7E 35 9D 9D' + '00 30 7F 7F 7E 93 9D 9D 12 70 8A 89 87 85 83 78' + '79 75 76 6F 6F 6C 6D 6D 6D 6D 6D 6D 6D 6D 6D 6D' + '6D 6D 2B 6B 93 93 93 93 93 93 93 7F 7F 5D 30 2B' + '35 87 7F 7F 93 7E 9D 9D 12 70 98 99 97 97 97 96' + '96 95 95 94 94 94 93 93 92 92 92 91 91 91 90 90' + '8F 8F 2B 47 93 93 93 93 93 93 93 7E 7F 7F 7E 7D' + '7E 80 80 7F 7F 7F 9D 9D 11 73 9C 8A 82 83 83 81' + '7C 7C 7C 7C 7C 81 81 81 81 81 81 81 81 81 81 81' + '81 81 2B 3B 93 93 93 93 93 93 93 93 93 80 80 80' + '80 80 7F 7F 7F 7F 9D 9D 11 7B 99 76 61 57 5B 75' + '77 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76' + '76 76 2D 30 93 93 93 93 93 93 93 93 93 7E 7D 7D' + '7D 7D 7F 7F 7F 7F 9D 9D 0D 77 94 63 46 53 4E 60' + '77 75 75 75 75 75 74 74 74 74 74 74 74 74 75 75' + '75 75 70 2B 5D 93 93 93 93 93 93 93 93 93 7D 7D' + '7D 7D 7F 7F 7F 7F 9D 9D 03 5F 97 58 4F 60 48 57' + '75 72 72 72 71 70 70 72 74 75 75 74 72 70 70 70' + '71 72 70 2B 37 93 93 93 93 93 93 93 93 7D 7D 7D' + '7D 7D 7F 7F 7F 7F 00 9D 9D 43 95 6C 62 6F 5B 66' + '70 6F 6D 70 6D 6D 72 72 72 72 72 72 72 72 6D 6D' + '71 6D 70 70 2B 52 93 93 93 93 93 93 7D 7D 7D 7D' + '7D 7D 7F 7F 7F 7F 00 9D 9D 31 90 6E 6C 68 6C 6E' + '6B 6C 72 72 72 72 72 72 72 72 72 72 72 72 72 72' + '72 82 70 70 30 30 5C 93 93 93 93 7D 7D 7D 7D 7D' + '7D 7F 7F 7F 7F 7F 00 9D 9D 27 8A 6D 6A 6A 6A 67' + '70 70 70 70 71 72 73 73 73 73 73 73 73 73 72 72' + '78 85 70 70 70 2D 3B 93 93 93 7D 7D 7D 7D 7D 7D' + '7F 7F 7F 7F 7F 7F 00 9D 9D 1F 74 6F 67 68 67 71' + '70 70 70 6E 6F 6F 6F 6F 6F 6F 70 6F 70 70 6F 6F' + '6E 6D 70 70 70 61 2D 3B 93 7D 7D 7D 7D 7D 7D 7F' + '7F 7F 7F 7F 7F 7F 00 9D 9D 10 53 78 67 68 6B 70' + '70 6C 6E 6D 6D 6D 6D 6C 70 70 6B 70 70 70 70 70' + '70 6B 70 70 70 61 61 2D 35 6B 7D 7D 7D 7D 7F 7F' + '7F 7F 7F 7F 87 3B 00 9D 9D 05 41 7A 69 6A 70 70' + '70 6D 6D 6D 6D 6D 6D 70 70 70 70 70 70 70 70 70' + '70 70 70 70 70 61 61 50 3E 2B 40 5D 7D 7F 7F 7F' + '7F 9C 6B 40 2B 3B 00 00 9D 9D 36 7A 6C 6E 70 70' + '6D 6D 6D 6D 6D 6D 6D 6D 6C 70 70 70 70 70 70 70' + '70 70 70 70 70 70 50 50 3E 9D 9D 30 2B 37 37 37' + '37 2B 2D 00 00 00 00 00 9D 9D 29 79 6E 6F 70 70' + '6E 6E 6E 6E 6E 6E 6E 6E 6E 70 70 70 70 70 70 70' + '70 70 70 70 70 70 50 50 3E 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 9D 9D 20 75 71 6F 70 70' + '70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70' + '70 70 70 70 70 70 50 50 3E 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 9D 9D 18 69 73 72 70 70' + '73 73 73 73 73 73 73 73 73 73 73 70 70 70 70 70' + '70 70 70 70 61 70 59 6D 3E 07 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 9D 9D 0A 4E 78 78 7B 7B' + '7B 76 77 77 77 77 77 77 77 77 77 77 7A 7A 7A 7A' + '7A 77 7A 7A 88 76 69 67 30 02 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 9D 9D 06 3D 79 7C 79 7B' + '7B 7B 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A' + '7A 7A 88 88 88 7A 79 63 25 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 2F 70 83 82 7B' + '7B 7B 7B 7B 81 81 81 81 81 81 81 81 81 81 81 81' + '82 82 88 88 88 84 76 57 1D 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 24 66 86 84 85' + '8C 8C 8C 8C 8C 8C 85 85 85 85 85 85 85 85 86 86' + '88 88 88 88 85 87 73 45 0E 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 1C 59 87 87 87' + '88 88 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 88' + '88 88 88 88 87 89 71 3F 08 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 0C 48 85 8E 88' + '87 8D 8C 8B 8E 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C 8C' + '8C 8D 8B 86 8C 8C 73 38 9D 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 9D 9D 06 3E 85 7C 59' + '5E 73 8D 8E 8E 8F 8F 8E 8D 8C 8C 8D 8E 8F 8F 8E' + '8F 85 5F 5A 6E 8D 71 2E 9D 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 9D 9D 39 81 61 4F' + '55 4F 8C 92 91 91 91 91 91 91 91 91 91 91 91 91' + '94 72 4E 52 53 8C 6A 2A 9D 9D 9D 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 9D 9D 2C 6B 7A 79' + '72 85 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A 9A' + '9B 93 7C 75 79 74 4E 1B 9D 9D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 9D 9D 0B 35 5A 70' + '74 78 75 75 75 75 75 75 75 75 75 75 75 75 75 75' + '75 76 76 74 6A 4E 28 04 9D 9D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 9D 9D 9D 09 1E 22' + '21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21' + '21 21 21 22 22 1A 02 9D 9D 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D 9D' + '9D 9D 9D 9D 9D 9D 9D 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF F0 00 00 00 FF FF' + 'FF FF E0 00 00 00 FF FF FF FF C0 00 00 00 FF FF' + 'FF FF 80 00 00 00 FF FF FF FE 00 00 00 00 FF FF' + 'FF FC 00 00 00 00 FF FF FF FC 00 00 00 00 F0 00' + '00 00 00 00 00 00 C0 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 E0 00 00 00 00 00 00 00 60 00 00 00 00' + '00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 C0 00 00 00 00 07 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' + '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' + '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0C 00 00 00 24 00 00 00 30 00 00 00 48 00 00' + '00 78 00 00 00 90 00 00 00 90 00 00 00 90 00 00' + '00 90 00 00 00 78 00 00 00 48 00 00 00 30 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 3C 00 00 00 78 00 00 00 90 80 80 80 FF 6E 6E' + '6E FF 62 62 62 FF 62 62 62 FF 62 62 62 FF 80 80' + '80 FF 00 00 00 B4 00 00 00 9C 00 00 00 90 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 86 86' + '86 FF 6E 6E 6E FF 7A 7A 7A FF AA AA AA FF CE CE' + 'CE FF DA DA DA FF F2 F2 F2 FF DA DA DA FF CE CE' + 'CE FF AA AA AA FF 80 80 80 FF 6E 6E 6E FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 3C 7A 7A 7A FF 80 80' + '80 FF CE CE CE FF FF FF FF FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 24 00 00 00 48 62 62 62 FF C0 C0 C0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' + '00 78 6E 6E 6E FF E6 E6 E6 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 56 56 56 56 FF 62 62' + '62 FF E6 E6 E6 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 16 00 00 00 34 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 42 00 00 00 42 4A 4A 4A FF 62 62 62 FF C2 C2' + 'C2 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 69 00 00' + '00 C5 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 FF 62 62 62 FF 56 56 56 FF 92 92 92 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 05 00 00 00 9B 00 00 00 FF 00 00' + '00 FF 21 21 21 FF 2C 2C 2C FF 2B 2B 2B FF 2C 2C' + '2C FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A 2A FF 2A 2A' + '2A FF 4A 4A 4A FF 62 62 62 FF F2 F2 F2 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 00 00 00 00 54 00 00 00 FF 26 26 26 FF 90 90' + '90 FF B8 B4 B6 FF AD AD AD FF AB AC AC FF AD A8' + 'AB FF CD CD CD FF CC CC CC FF CB CB CB FF C9 C9' + 'C9 FF C4 C4 C4 FF C3 C3 C3 FF C2 C2 C2 FF C2 C2' + 'C2 FF C3 C3 C3 FF C0 C0 C0 FF C1 C1 C1 FF BF BF' + 'BF FF BF BF BF FF BC BC BC FF BD BD BD FF BA BA' + 'BA FF BD BD BD FF BD BD BD FF BD BD BD FF 6E 6E' + '6E FF 56 56 56 FF 9E 9E 9E FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF FF D4 E3 FF FF D4 E3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 03 00 00 00 AD 01 01 01 FF 8A 8A 8A FF AD A8' + 'AB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF D4 D4 D4 FF 00 C0 00 FF 00 C0 00 FF E7 E7' + 'E7 FF E8 E8 E8 FF E8 E8 E8 FF E3 E3 E3 FF DD DD' + 'DD FF D8 D8 D8 FF D2 D2 D2 FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF C8 C9' + 'C9 FF CD CD CD FF AA AA AA FF 2E 2E 2E FF 56 56' + '56 FF 62 62 62 FF DA DA DA FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 FF FF FF D4' + 'FF FF FF D4 FF FF FF D4 FF FF FF D4 FF FF FF D4' + 'F0 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 15 00 00 00 F0 19 19 19 FF AD A8 AB FF EB EB' + 'EB FF EB EB EB FF E8 E8 E8 FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 C0' + '00 FF E1 E1 E1 FF DF DF DF FF D5 D5 D5 FF CC CC' + 'CC FF D2 D2 D2 FF CB CB CB FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CD CD CD FF 40 40 40 FF 2E 2E 2E FF 56 56' + '56 FF 7A 7A 7A FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'E3 FF F2 F2 F2 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 FF FF FF D4' + 'F0 FF FF D4 E3 FF FF D4 E3 FF FF D4 FF FF FF D4' + 'FF FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 30 00 00 00 FA 29 29 29 FF AD A8 AB FF EA EA' + 'EA FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF' + '00 FF CB CB CB FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' + 'C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' + 'C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8 C8 FF C8 C8' + 'C8 FF C8 C8 C8 FF 93 93 93 FF 40 40 40 FF 56 56' + '56 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF B6 B6' + 'B6 FF 80 80 80 FF 92 92 92 FF FF B1 C7 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 E3 FF F2 F2 F2 FF 00 00' + '00 34 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EC EC' + 'EC FF EB EB EB FF EB EB EB FF E8 E8 E8 FF E8 E8' + 'E8 FF E8 E8 E8 FF 00 FF 00 FF 00 FF 00 FF B5 B5' + 'B5 FF B5 B5 B5 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B6 B6 B6 FF B6 B6 B6 FF 56 56' + '56 FF A4 A0 A0 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF FF D4 F0 FF B6 B6 B6 FF 6E 6E' + '6E FF AA AA AA FF 62 62 62 FF 7A 7A 7A FF FF D4' + 'E3 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 33 00 00 00 F9 28 28 28 FF D1 D1 D1 FF EE EE' + 'EE FF E8 E8 E8 FF EB EB EB FF E8 E8 E8 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 62 62' + '62 FF B6 B6 B6 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF FF D4 E3 FF 6E 6E 6E FF 00 00' + '00 00 00 00 00 00 00 00 00 00 62 62 62 FF B6 B6' + 'B6 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 33 00 00 00 F9 27 27 27 FF D1 D1 D1 FF EF EF' + 'EF FF EB EB EB FF EB EB EB FF EB EB EB FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 62 62' + '62 FF B6 B6 B6 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF FF D4 D4 FF 62 62 62 FF 00 00' + '00 78 00 00 00 00 00 00 00 00 62 62 62 FF B6 B6' + 'B6 FF FF D4 F0 FF F2 F2 F2 FF F2 F2 F2 FF 00 00' + '00 33 00 00 00 F9 27 27 27 FF D2 D2 D2 FF F2 F2' + 'F2 FF EA EA EA FF EB EB EB FF EB EB EB FF A7 A7' + 'A7 FF A7 A7 A7 FF A7 A7 A7 FF AB AB AB FF AE AE' + 'AE FF B0 B0 B0 FF AF AF AF FF AF AF AF FF AF AF' + 'AF FF AF AF AF FF AF AF AF FF AF AF AF FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF AB AB' + 'AB FF AB AB AB FF AB AB AB FF AB AB AB FF 62 62' + '62 FF CE CE CE FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'E3 FF FF D4 F0 FF FF D4 E3 FF 80 80 80 FF 00 00' + '00 78 00 00 00 78 00 00 00 00 7A 7A 7A FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 E3 FF F2 F2 F2 FF 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF E9 E9' + 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' + 'E2 FF DB DB DB FF DC DC DC FF D8 D8 D8 FF D9 D9' + 'D9 FF D2 D2 D2 FF D2 D2 D2 FF CF CF CF FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF 62 62' + '62 FF CE CE CE FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 F0 FF FF D4 F0 FF C0 C0 C0 FF 7A 7A' + '7A FF 62 62 62 FF 80 80 80 FF E6 E6 E6 FF FF D4' + 'F0 FF FF D4 F0 FF F2 F2 F2 FF FF D4 E3 FF 00 00' + '00 33 00 00 00 F9 26 26 26 FF D3 D3 D3 FF F7 F7' + 'F7 FF F8 F8 F8 FF F6 F6 F6 FF F6 F6 F6 FF F6 F6' + 'F6 FF F5 F5 F5 FF F5 F5 F5 FF F4 F4 F4 FF F4 F4' + 'F4 FF F3 F3 F3 FF F3 F3 F3 FF F3 F3 F3 FF F2 F2' + 'F2 FF F2 F2 F2 FF F1 F1 F1 FF F1 F1 F1 FF F1 F1' + 'F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF EF EF' + 'EF FF EF EF EF FF EE EE EE FF EE EE EE FF 62 62' + '62 FF AA AA AA FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 E3 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'E3 FF FF D4 D4 FF FF D4 E3 FF FF D4 FF FF FF D4' + 'FF FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 33 00 00 00 F9 24 24 24 FF D6 D6 D6 FF FF FF' + 'FF FF E9 E9 E9 FF E1 E1 E1 FF E2 E2 E2 FF E2 E2' + 'E2 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF 62 62' + '62 FF 92 92 92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 FF FF FF D4' + 'FF FF FF D4 FF FF FF D4 FF FF FF D4 FF FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 34 00 00 00 FA 24 24 24 FF DE DE DE FF F8 F8' + 'F8 FF D9 D9 D9 FF C4 C4 C4 FF BB BB BB FF BF BF' + 'BF FF D8 D8 D8 FF DA DA DA FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF 6E 6E' + '6E FF 7A 7A 7A FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 E3 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 25 00 00 00 F7 1F 1F 1F FF DA DA DA FF F3 F3' + 'F3 FF C6 C6 C6 FF A9 A9 A9 FF B7 B7 B7 FF B0 B0' + 'B0 FF C3 C3 C3 FF DA DA DA FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D3 D3' + 'D3 FF 62 62 62 FF C0 C0 C0 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 07 00 00 00 D0 05 05 05 FF C2 C2 C2 FF F6 F6' + 'F6 FF BC BC BC FF B2 B2 B2 FF C3 C3 C3 FF AB AB' + 'AB FF BB BB BB FF D8 D8 D8 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D4 D4 D4 FF D3 D3 D3 FF D3 D3' + 'D3 FF D5 D5 D5 FF D7 D7 D7 FF D8 D8 D8 FF D8 D8' + 'D8 FF D7 D7 D7 FF D5 D5 D5 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D3 D3' + 'D3 FF 62 62 62 FF 86 86 86 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 9C 00 00 00 FF A4 A4 A4 FF F4 F4' + 'F4 FF CF CF CF FF C5 C5 C5 FF D2 D2 D2 FF BF BF' + 'BF FF C9 C9 C9 FF D3 D3 D3 FF D2 D2 D2 FF D0 D0' + 'D0 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D0 D0' + 'D0 FF D0 D0 D0 FF D4 D4 D4 FF D0 D0 D0 FF D3 D3' + 'D3 FF D3 D3 D3 FF 62 62 62 FF B6 B6 B6 FF F2 F2' + 'F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF F2 F2 F2 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 73 00 00 00 FF 7E 7E 7E FF EF EF' + 'EF FF D1 D1 D1 FF CF CF CF FF CB CB CB FF CF CF' + 'CF FF D1 D1 D1 FF CE CE CE FF CF CF CF FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5' + 'D5 FF D5 D5 D5 FF D5 D5 D5 FF E1 E1 E1 FF D3 D3' + 'D3 FF D3 D3 D3 FF 7A 7A 7A FF 7A 7A 7A FF FF B1' + 'C7 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2' + 'F2 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 59 00 00 00 FF 59 59 59 FF E9 E9' + 'E9 FF D0 D0 D0 FF CD CD CD FF CD CD CD FF CD CD' + 'CD FF CA CA CA FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D4 D4 D4 FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D5 D5' + 'D5 FF D5 D5 D5 FF DB DB DB FF E4 E4 E4 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF 6E 6E 6E FF 92 92' + '92 FF F2 F2 F2 FF F2 F2 F2 FF F2 F2 F2 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 3E 00 00 00 FE 40 40 40 FF D7 D7' + 'D7 FF D2 D2 D2 FF CA CA CA FF CB CB CB FF CA CA' + 'CA FF D4 D4 D4 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D1 D1 D1 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D3 D3' + 'D3 FF D2 D2 D2 FF D3 D3 D3 FF D3 D3 D3 FF D2 D2' + 'D2 FF D2 D2 D2 FF D1 D1 D1 FF D0 D0 D0 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF 6E 6E' + '6E FF 92 92 92 FF F2 F2 F2 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'D4 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF 00 00' + '00 00 00 00 00 25 00 00 00 F8 22 22 22 FF B7 B7' + 'B7 FF DB DB DB FF CA CA CA FF CB CB CB FF CE CE' + 'CE FF D3 D3 D3 FF D3 D3 D3 FF CF CF CF FF D1 D1' + 'D1 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF CF CF CF FF D3 D3 D3 FF D3 D3 D3 FF CE CE' + 'CE FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CE CE CE FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF C4 C4' + 'C4 FF 6E 6E 6E FF 80 80 80 FF CE CE CE FF FF D4' + 'D4 FF FF D4 D4 FF FF D4 D4 FF FF D4 D4 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF E6 E6 E6 FF 92 92 92 FF 00 00' + '00 00 00 00 00 0C 00 00 00 E1 07 07 07 FF 9F 9F' + '9F FF DD DD DD FF CC CC CC FF CD CD CD FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF C4 C4 C4 FF C4 C4' + 'C4 FF B3 B3 B3 FF 99 99 99 FF 62 62 62 FF 9E 9E' + '9E FF C0 C0 C0 FF FF D4 D4 FF FF D4 F0 FF FF D4' + 'F0 FF FF D4 F0 FF FF D4 F0 FF FF FF FF FF CE CE' + 'CE FF 9E 9E 9E FF 62 62 62 FF 92 92 92 FF 00 00' + '00 00 00 00 00 00 00 00 00 B2 00 00 00 FF 83 83' + '83 FF DD DD DD FF CF CF CF FF D1 D1 D1 FF D3 D3' + 'D3 FF D3 D3 D3 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF CF CF CF FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' + 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 FF 00 00' + '00 FF 7A 7A 7A FF 62 62 62 FF 86 86 86 FF 86 86' + '86 FF 86 86 86 FF 86 86 86 FF 62 62 62 FF 6E 6E' + '6E FF 00 00 00 24 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 5F 5F' + '5F FF DC DC DC FF D1 D1 D1 FF D2 D2 D2 FF D3 D3' + 'D3 FF D3 D3 D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' + 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 CF 00 00' + '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 4B 00 00 00 FE 41 41' + '41 FF D8 D8 D8 FF D4 D4 D4 FF D2 D2 D2 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF B3 B3' + 'B3 FF B3 B3 B3 FF 99 99 99 FF 00 00 00 CF 00 00' + '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1A 00 00 00 F2 2C 2C' + '2C FF CC CC CC FF D6 D6 D6 FF D5 D5 D5 FF D3 D3' + 'D3 FF D3 D3 D3 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF C4 C4 C4 FF D3 D3 D3 FF BD BD' + 'BD FF D0 D0 D0 FF 99 99 99 FF 09 09 09 FF 00 00' + '00 CF 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 D8 18 18' + '18 FF B0 B0 B0 FF DB DB DB FF DB DB DB FF DE DE' + 'DE FF DE DE DE FF DE DE DE FF D9 D9 D9 FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DA DA DA FF DD DD' + 'DD FF DD DD DD FF E7 E7 E7 FF D9 D9 D9 FF CC CC' + 'CC FF CA CA CA FF 7A 7A 7A FF 02 02 02 FF 00 00' + '00 B8 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 BF 08 08' + '08 FF 97 97 97 FF DC DC DC FF DF DF DF FF DC DC' + 'DC FF DE DE DE FF DE DE DE FF DE DE DE FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF DD DD DD FF DC DC' + 'DC FF C6 C6 C6 FF 53 53 53 FF 00 00 00 FF 00 00' + '00 A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 00 00' + '00 FF 77 77 77 FF D3 D3 D3 FF E2 E2 E2 FF E1 E1' + 'E1 FF DE DE DE FF DE DE DE FF DE DE DE FF DE DE' + 'DE FF DE DE DE FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E1 E1 E1 FF E1 E1 E1 FF E7 E7' + 'E7 FF E7 E7 E7 FF E7 E7 E7 FF E3 E3 E3 FF D9 D9' + 'D9 FF BB BB BB FF 39 39 39 FF 00 00 00 FF 00 00' + '00 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 89 00 00' + '00 FF 4B 4B 4B FF C9 C9 C9 FF E5 E5 E5 FF E3 E3' + 'E3 FF E4 E4 E4 FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E5 E5' + 'E5 FF E5 E5 E5 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E4 E4 E4 FF E6 E6 E6 FF D6 D6' + 'D6 FF A8 A8 A8 FF 20 20 20 FF 00 00 00 FD 00 00' + '00 4E 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 62 00 00' + '00 FF 35 35 35 FF BD BD BD FF E6 E6 E6 FF E6 E6' + 'E6 FF E6 E6 E6 FF E7 E7 E7 FF E7 E7 E7 FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF E7 E7 E7 FF E7 E7 E7 FF E7 E7 E7 FF E7 E7' + 'E7 FF E7 E7 E7 FF E6 E6 E6 FF E8 E8 E8 FF D4 D4' + 'D4 FF 9A 9A 9A FF 0B 0B 0B FF 00 00 00 ED 00 00' + '00 2C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2D 00 00' + '00 F9 1E 1E 1E FF AB AB AB FF E4 E4 E4 FF ED ED' + 'ED FF E7 E7 E7 FF E6 E6 E6 FF EC EC EC FF EB EB' + 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EB EB EB FF EB EB' + 'EB FF EB EB EB FF EB EB EB FF EC EC EC FF EA EA' + 'EA FF E5 E5 E5 FF EB EB EB FF EB EB EB FF D6 D6' + 'D6 FF 8A 8A 8A FF 00 00 00 FF 00 00 00 C3 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 09 00 00' + '00 DD 08 08 08 FF 99 99 99 FF E4 E4 E4 FF DF DF' + 'DF FF BD BD BD FF C1 C1 C1 FF D6 D6 D6 FF EC EC' + 'EC FF ED ED ED FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EC EC EC FF EB EB EB FF EB EB' + 'EB FF EC EC EC FF ED ED ED FF EE EE EE FF EE EE' + 'EE FF ED ED ED FF EE EE EE FF E4 E4 E4 FF C2 C2' + 'C2 FF BE BE BE FF D1 D1 D1 FF EC EC EC FF D4 D4' + 'D4 FF 75 75 75 FF 00 00 00 FF 00 00 00 9C 00 00' + '00 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 AE 00 00 00 FF 8D 8D 8D FF E0 E0 E0 FF C4 C4' + 'C4 FF B2 B2 B2 FF B8 B8 B8 FF B2 B2 B2 FF EB EB' + 'EB FF F1 F1 F1 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F3 F3 F3 FF D5 D5 D5 FF B0 B0' + 'B0 FF B6 B6 B6 FF B7 B7 B7 FF EB EB EB FF CD CD' + 'CD FF 61 61 61 FF 00 00 00 FF 00 00 00 85 00 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 64 64 64 FF CE CE CE FF DD DD' + 'DD FF DC DC DC FF D5 D5 D5 FF E4 E4 E4 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF FA FA FA FF F2 F2 F2 FF DF DF' + 'DF FF D8 D8 D8 FF DC DC DC FF D7 D7 D7 FF B0 B0' + 'B0 FF 34 34 34 FF 00 00 00 FF 00 00 00 67 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 44 00 00 00 FF 19 19 19 FF 80 80 80 FF BE BE' + 'BE FF D3 D3 D3 FF D7 D7 D7 FF DB DB DB FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D9 D9 D9 FF D9 D9' + 'D9 FF D7 D7 D7 FF CD CD CD FF B0 B0 B0 FF 5D 5D' + '5D FF 06 06 06 FF 00 00 00 ED 00 00 00 2B 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 9C 00 00 00 FF 0C 0C 0C FF 3D 3D' + '3D FF 49 49 49 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 49 49 49 FF 49 49 49 FF 2F 2F 2F FF 02 02' + '02 FF 00 00 00 FF 00 00 00 5C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 06 00 00 00 7F 00 00 00 F1 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 D6 00 00 00 5C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00' + '00 7E 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 70 00 00' + '00 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF F0 00 00 00 FF FF FF FF E0 00 00 00 FF FF' + 'FF FF C0 00 00 00 FF FF FF FF 80 00 00 00 FF FF' + 'FF FF 00 00 00 00 FF FF FF FE 00 00 00 00 FF FF' + 'FF FC 00 00 00 00 F0 00 00 00 00 00 00 00 C0 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 00' + '00 00 00 60 00 00 00 00 00 00 00 20 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 C0 00' + '00 00 00 01 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' + '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00' +} */ + +/* BINRES ramdisk.ico */ +12 ICON ramdisk.ico +/* { + '00 00 01 00 07 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 76 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 5E 03 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 C6 08 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 EE 09 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 96 18 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 FE 1E 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 A6 44 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 88 00 66 00 00 00 00 00 00 00 00 00 00' + '00 00 08 08 80 E6 00 00 00 00 00 00 00 00 00 00' + '00 00 80 08 07 EE 00 00 00 00 00 00 00 00 00 00' + '00 08 00 08 00 0E 00 60 00 00 00 00 00 00 00 00' + '00 80 00 80 80 08 00 66 00 00 00 00 00 00 00 00' + '08 00 08 00 08 00 80 E6 00 00 00 00 00 00 00 00' + '80 00 80 00 00 80 07 EE 00 00 00 00 00 00 00 08' + '00 08 00 00 00 08 00 0E 00 60 00 00 00 00 00 80' + '00 80 00 08 00 00 80 08 00 66 00 00 00 00 00 80' + '08 00 00 80 80 00 08 00 80 E6 00 00 00 00 00 80' + '80 00 08 08 08 00 00 80 07 EE 00 00 00 00 00 88' + '00 00 80 80 80 00 00 08 00 0E 00 60 00 00 66 07' + '00 00 08 08 00 00 00 00 80 08 00 66 00 00 66 00' + '70 00 00 80 00 08 00 00 08 00 80 E6 00 00 EE EE' + '07 00 00 00 00 00 80 00 00 80 07 EE 00 00 0E E0' + '00 70 00 00 08 00 08 00 00 08 00 0E 00 60 00 00' + '66 07 00 00 00 80 00 80 00 00 80 08 00 66 00 00' + '66 00 70 00 00 08 00 08 00 00 08 00 80 E6 00 00' + 'EE EE 07 00 00 00 80 00 80 00 00 80 07 EE 00 00' + '0E E0 00 70 00 00 08 00 00 00 00 08 00 0E 00 00' + '00 00 66 07 00 00 00 80 00 00 00 00 80 08 00 00' + '00 00 66 00 70 00 00 00 08 88 00 00 08 08 00 00' + '00 00 EE EE 07 00 00 00 80 80 80 00 00 87 00 00' + '00 00 0E E0 00 70 00 00 88 08 80 00 00 70 00 00' + '00 00 00 00 66 07 00 00 80 80 80 00 07 00 00 00' + '00 00 00 00 66 00 70 00 08 88 00 00 70 00 00 00' + '00 00 00 00 EE EE 07 00 00 00 00 07 00 00 00 00' + '00 00 00 00 0E E0 00 70 00 00 00 70 00 00 00 00' + '00 00 00 00 00 00 66 07 00 00 07 00 00 00 00 00' + '00 00 00 00 00 00 66 00 70 00 70 00 00 00 00 00' + '00 00 00 00 00 00 EE EE 07 07 00 00 00 00 00 00' + '00 00 00 00 00 00 0E E0 00 70 00 00 00 00 FF CC' + 'FF FF FF 84 FF FF FF 00 FF FF FE 00 DF FF FC 00' + 'CF FF F8 00 4F FF F0 00 0F FF E0 00 0D FF C0 00' + '0C FF C0 00 04 FF C0 00 00 FF C0 00 00 DF 00 00' + '00 CF 00 00 00 4F 08 00 00 0F 9C 00 00 0D F0 00' + '00 0C F0 00 00 04 F0 80 00 00 F9 C0 00 00 FF 00' + '00 00 FF 00 00 00 FF 08 00 00 FF 9C 00 01 FF F0' + '00 03 FF F0 00 07 FF F0 80 0F FF F9 C0 1F FF FF' + '00 3F FF FF 00 7F FF FF 08 FF FF FF 9D FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 1C 04 04 00 18 18' + '18 00 1A 1A 1A 00 1C 1C 1C 00 36 0E 0E 00 3C 14' + '14 00 34 1C 1C 00 20 20 20 00 24 24 24 00 28 28' + '28 00 30 30 30 00 38 38 38 00 3C 3C 3C 00 40 28' + '28 00 46 46 46 00 48 48 48 00 4C 4C 4C 00 50 50' + '50 00 52 52 52 00 54 54 54 00 56 56 56 00 58 58' + '58 00 68 68 68 00 74 74 74 00 78 78 78 00 7E 7E' + '7E 00 7F 7F 7F 00 00 92 92 00 00 9C 9C 00 00 BC' + 'BC 00 00 C0 C0 00 00 D0 D0 00 00 DF DF 00 00 E3' + 'E3 00 00 E5 E5 00 00 F7 F7 00 00 FB FB 00 00 FF' + 'FF 00 90 90 90 00 A8 A8 A8 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 11 00 00 00 B8 09' + '38 00 00 00 38 00 70 63 0C 01 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 76 00' + '00 00 76 00 00 00 07 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 58 00' + '5A 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' + '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 72' + '61 6D 64 69 73 6B 2E 69 63 6F 00 93 4B 00 14 1A' + '95 00 1F 3B D4 77 11 00 00 00 88 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 70 63 0C 01 76 00 00 00 00 00' + '00 00 C9 F1 E7 77 76 00 00 00 A4 1A 95 00 07 00' + '00 00 00 00 00 00 76 00 00 00 76 00 00 00 07 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 70 63 0C 01 76 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 18 00 1F 00 00' + '00 00 00 00 00 00 00 00 00 00 04 0F 07 26 00 00' + '00 00 00 00 00 00 00 00 00 08 08 04 13 01 00 20' + '00 00 00 00 00 00 00 00 08 08 0A 29 29 15 07 26' + '00 00 00 00 00 00 00 11 04 0A 29 29 29 29 15 01' + '00 20 00 00 00 00 00 1A 03 29 0B 29 29 29 29 15' + '07 26 00 00 00 00 1C 05 0C 29 29 0B 29 29 29 29' + '15 01 00 20 00 00 21 25 00 0D 29 29 0B 29 29 29' + '29 15 07 26 00 00 00 00 1D 06 0D 29 29 16 12 29' + '29 29 15 01 00 1E 00 00 24 25 00 0D 29 29 14 09' + '29 29 29 15 07 23 00 00 00 00 1D 06 0D 29 29 0A' + '02 12 29 29 13 0E 00 00 00 00 24 25 00 0D 29 29' + '19 17 12 29 29 28 00 00 00 00 00 00 1D 06 0D 29' + '10 19 04 29 27 00 00 00 00 00 00 00 24 25 00 0D' + '29 29 29 27 00 00 00 00 00 00 00 00 00 00 1D 06' + '0D 29 27 00 00 00 00 00 00 00 00 00 00 00 21 22' + '00 1A 00 00 00 00 FA FF 00 00 F0 FF 00 00 E0 BF' + '00 00 C0 3F 00 00 80 2F 00 00 80 0F 00 00 00 0B' + '00 00 20 03 00 00 C0 02 00 00 C8 00 00 00 F0 00' + '00 00 F2 00 00 00 FC 01 00 00 FC 83 00 00 FF 07' + '00 00 FF 2F 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '08 0E 00 00 00 00 00 00 08 0E 00 00 00 00 00 00' + '00 80 0E 00 00 00 00 00 00 08 0E 00 00 00 08 00' + '00 00 80 0E 00 00 08 00 00 00 08 0E 00 00 60 00' + '00 00 00 80 0E 00 EE 00 00 00 00 08 0E 00 00 60' + '00 08 80 00 80 06 00 EE 00 00 80 00 08 0E 00 00' + '60 00 00 08 00 80 00 00 EE 00 00 88 80 07 00 00' + '00 60 00 88 00 80 00 00 00 EE 00 00 08 00 00 00' + '00 00 60 00 80 00 00 00 00 00 EE 08 00 00 FA FF' + '00 00 F0 FF 00 00 E0 BF 00 00 C0 3F 00 00 80 2F' + '00 00 80 0F 00 00 00 0B 00 00 20 03 00 00 C0 02' + '00 00 C8 00 00 00 F0 00 00 00 F2 00 00 00 FC 01' + '00 00 FC 83 00 00 FF 07 00 00 FF 2F 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 08 00 00 00' + '00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 01 01 00 02 02' + '02 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08' + '08 00 09 09 09 00 0B 0B 0B 00 0C 0C 0C 00 18 18' + '18 00 19 19 19 00 1E 1E 1E 00 1F 1F 1F 00 20 20' + '20 00 21 21 21 00 22 22 22 00 24 24 24 00 26 26' + '26 00 27 27 27 00 28 28 28 00 29 29 29 00 2B 2B' + '2B 00 2C 2C 2C 00 2F 2F 2F 00 34 34 34 00 35 35' + '35 00 39 39 39 00 3B 3B 3B 00 3D 3D 3D 00 3F 3F' + '3F 00 40 40 40 00 41 41 41 00 47 47 47 00 48 48' + '48 00 49 49 49 00 4B 4B 4B 00 53 53 53 00 56 56' + '56 00 59 59 59 00 5D 5D 5D 00 5F 5F 5F 00 61 61' + '61 00 64 64 64 00 68 68 68 00 6A 6A 6A 00 6C 6C' + '6C 00 70 70 70 00 71 71 71 00 72 72 72 00 74 74' + '74 00 75 75 75 00 77 77 77 00 78 78 78 00 79 79' + '79 00 7A 7A 7A 00 7D 7D 7D 00 7E 7E 7E 00 7F 7F' + '7F 00 00 80 80 00 00 FF FF 00 80 80 80 00 81 81' + '81 00 83 83 83 00 85 85 85 00 87 87 87 00 88 88' + '88 00 8A 8A 8A 00 8D 8D 8D 00 8E 8E 8E 00 8F 8F' + '8F 00 90 90 90 00 92 92 92 00 93 93 93 00 97 97' + '97 00 98 98 98 00 99 99 99 00 9A 9A 9A 00 9C 9C' + '9C 00 9D 9D 9D 00 9F 9F 9F 00 A0 A0 A0 00 A2 A2' + 'A2 00 A4 A4 A4 00 A5 A5 A5 00 A7 A7 A7 00 A8 A8' + 'A8 00 A9 A9 A9 00 AB AB AB 00 AD AD AD 00 AE AE' + 'AE 00 B0 B0 B0 00 B2 B2 B2 00 B3 B3 B3 00 B6 B6' + 'B6 00 B7 B7 B7 00 B8 B8 B8 00 B9 B9 B9 00 BA BA' + 'BA 00 BB BB BB 00 BC BC BC 00 BD BD BD 00 BE BE' + 'BE 00 BF BF BF 00 C0 C0 C0 00 C1 C1 C1 00 C2 C2' + 'C2 00 C3 C3 C3 00 C4 C4 C4 00 C5 C5 C5 00 C6 C6' + 'C6 00 C7 C7 C7 00 C8 C8 C8 00 C9 C9 C9 00 CA CA' + 'CA 00 CB CB CB 00 CC CC CC 00 CD CD CD 00 CE CE' + 'CE 00 CF CF CF 00 D0 D0 D0 00 D1 D1 D1 00 D2 D2' + 'D2 00 D3 D3 D3 00 D4 D4 D4 00 D5 D5 D5 00 D6 D6' + 'D6 00 D7 D7 D7 00 D8 D8 D8 00 D9 D9 D9 00 DA DA' + 'DA 00 DB DB DB 00 DC DC DC 00 DD DD DD 00 DE DE' + 'DE 00 DF DF DF 00 E0 E0 E0 00 E1 E1 E1 00 E2 E2' + 'E2 00 E3 E3 E3 00 E4 E4 E4 00 E5 E5 E5 00 E6 E6' + 'E6 00 E7 E7 E7 00 E8 E8 E8 00 E9 E9 E9 00 EA EA' + 'EA 00 EB EB EB 00 EC EC EC 00 ED ED ED 00 EE EE' + 'EE 00 EF EF EF 00 F0 F0 F0 00 F1 F1 F1 00 F2 F2' + 'F2 00 F3 F3 F3 00 F4 F4 F4 00 F5 F5 F5 00 F6 F6' + 'F6 00 F7 F7 F7 00 F8 F8 F8 00 F9 F9 F9 00 FA FA' + 'FA 00 FF FF FF 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' + '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 88 36 0C 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 72' + '61 6D 64 69 73 6B 2E 69 63 6F 00 93 4B 00 14 1A' + '95 00 1F 3B D4 77 11 00 00 00 88 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 70 63 0C 01 76 00 00 00 00 00' + '00 00 C9 F1 E7 77 76 00 00 00 A4 1A 95 00 07 00' + '00 00 00 00 00 00 76 00 00 00 76 00 00 00 07 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 70 63 0C 01 76 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4' + 'A4 A4 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D' + '3D A4 A4 3B 3B A4 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4' + '3D 3D A4 3C 3B A4 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4' + '3D A4 68 3C 3C A4 00 A4 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4 A4' + '3D A4 A4 A4 3C A4 00 3B A4 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 3D A4 A4 A4 3D' + 'A4 3D A4 A4 3D A4 00 3B 3B 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 3D A4 A4 A4 3D A4' + 'A4 A4 3D A4 A4 3D 00 3C 3B A4 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4' + 'A4 A4 A4 3D A4 A4 68 3C 3C A4 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4' + 'A4 A4 A4 A4 3D A4 A4 A4 3C A4 00 3B A4 00 00 00' + '00 00 00 00 00 00 00 A4 A4 A4 A4 0F 17 16 17 16' + '16 16 16 16 16 16 16 3D A4 A4 A4 3D A4 A4 A4 A4' + '3D A4 A4 A4 A4 3D A4 A4 3D A4 00 3B 3B A4 00 00' + '00 00 00 00 00 00 00 A4 A4 12 47 72 75 73 76 75' + '74 73 71 6F 6E 6D 6C 3D A4 A4 3D A4 A4 A4 A4 3D' + 'A4 3D A4 A4 A4 A4 3D A4 A4 3D A4 3C 3B A4 00 00' + '00 00 00 00 00 00 A4 A4 01 43 93 90 8F 7D 40 42' + '48 4B 52 59 62 68 6B 3D A4 3D A4 A4 A4 A4 3D A4' + '3D A4 3D A4 A4 A4 A4 3D A4 A4 68 3C 3C A4 00 A4' + '00 00 00 00 00 00 A4 A4 0B 6F 94 8A 8E 73 1C 1E' + '26 31 41 48 4F 54 56 3D 3D A4 A4 A4 A4 3D A4 3D' + 'A4 3D A4 A4 A4 A4 A4 A4 3D A4 A4 A4 3C A4 00 3B' + 'A4 00 00 00 00 00 A4 A4 15 79 92 8C 8F 75 21 29' + '36 41 46 4A 51 3B 3B A4 68 A4 A4 A4 A4 A4 3D A4' + '3D A4 A4 A4 A4 A4 A4 A4 A4 3D A4 A4 3D A4 00 3B' + '3B A4 00 00 00 00 A4 A4 14 79 94 8E 8F 79 2C 32' + '39 40 45 4A 51 3B 3B A4 A4 68 A4 A4 A4 A4 A4 3D' + 'A4 A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 3D A4 3C' + '3B A4 00 00 00 00 A4 A4 14 79 96 8F 90 7E 2F 30' + '38 40 45 4A 51 3C 3C 3C 3C 4E 68 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 68 3C' + '3C A4 00 A4 00 00 A4 A4 13 79 97 91 93 7E 2D 2E' + '35 3E 43 49 4E 4E 3C 3C 4E 4E 4E 68 A4 A4 A4 A4' + 'A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4 A4' + '3C A4 00 3B A4 00 A4 A4 13 7A 9A 93 92 87 55 55' + '58 5A 5B 5D 5E 61 61 62 65 3B 3B A4 68 A4 A4 A4' + 'A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4 A4' + '3D A4 A4 3B 3B A4 A4 A4 12 7B 9B 93 93 92 95 93' + '91 90 8E 8C 8A 89 87 86 83 3B 3B A4 A4 68 A4 A4' + 'A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D A4' + 'A4 3D A4 3C 3B A4 A4 A4 12 7B 9F A0 9E 9E 9E 9D' + '9D 9C 9C 9B 9B 9B 9A 9A 99 3C 3C 3C 3C 99 68 A4' + 'A4 A4 A4 A4 A4 3D A4 A4 A4 3D A4 A4 A4 A4 A4 3D' + 'A4 A4 68 3C 3C A4 A4 A4 11 7E A3 91 89 8A 8A 88' + '87 87 87 87 87 88 88 88 88 88 3C 3C 81 81 81 68' + 'A4 A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 A4 A4 A4 A4' + '3D A4 A4 A4 3C A4 A4 A4 11 86 A0 81 6C 63 67 80' + '82 81 81 81 81 81 81 81 81 81 81 81 81 3B 3B A4' + '68 A4 A4 A4 A4 A4 A4 3D A4 A4 A4 A4 A4 A4 A4 A4' + 'A4 3D A4 A4 3D A4 A4 A4 0D 82 9B 6E 57 5F 5B 6B' + '82 80 80 80 80 80 7F 7F 7F 7F 7F 7F 7F 3B 3B A4' + 'A4 68 A4 A4 A4 A4 A4 A4 A4 A4 3D 3D 3D A4 A4 A4' + 'A4 A4 3D A4 3D A4 A4 A4 03 6A 9E 64 5C 6B 58 63' + '80 7D 7D 7D 7C 7B 7B 7D 7F 80 80 7F 7D 3C 3C 3C' + '3C 7F 68 A4 A4 A4 A4 A4 A4 3D A4 3D A4 3D A4 A4' + 'A4 A4 A4 3D 68 A4 00 A4 A4 53 9C 77 6D 7A 67 71' + '7B 7A 78 7B 85 89 8B 8E 92 95 95 93 8F 8F 3C 3C' + '8F 8F 7F 68 A4 A4 A4 A4 A4 3D 3D A4 3D 3D A4 A4' + 'A4 A4 A4 68 A4 A4 00 A4 A4 39 97 79 77 73 77 79' + '76 77 87 98 94 89 86 85 84 83 83 84 85 86 89 94' + '99 3B 3B A4 68 A4 A4 A4 A4 3D A4 3D A4 3D A4 A4' + 'A4 A4 68 A4 A4 00 00 A4 A4 27 91 78 75 75 75 72' + '7E 95 8E 84 7C 7D 7E 7E 7E 7E 7E 7E 7E 7E 7D 7D' + '83 3B 3B A4 A4 68 A4 A4 A4 A4 3D 3D 3D A4 A4 A4' + 'A4 68 A4 A4 00 00 00 A4 A4 1F 7F 7A 72 73 72 7C' + '91 84 78 79 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A 7A' + '79 3C 3C 3C 3C 4C 68 A4 A4 A4 A4 A4 A4 A4 A4 A4' + '68 A4 A4 00 00 00 00 A4 A4 10 5F 83 72 73 76 8C' + '7C 77 79 78 78 78 78 77 75 76 76 76 76 76 76 76' + '76 76 3C 3C 77 77 4C 68 A4 A4 A4 A4 A4 A4 A4 68' + 'A4 A4 00 00 00 00 00 A4 A4 05 50 85 74 75 83 7E' + '76 78 78 78 78 78 78 77 74 71 72 72 72 72 72 72' + '72 72 72 70 77 3B 3B A4 68 A4 A4 A4 A4 A4 68 A4' + 'A4 00 00 00 00 00 00 00 A4 A4 3F 85 77 79 83 79' + '78 78 78 78 78 78 78 78 77 71 6D 6E 6E 6E 6E 6E' + '6E 6E 6E 6E 6F 3B 3B A4 A4 68 A4 A4 A4 68 A4 A4' + '00 00 00 00 00 00 00 00 A4 A4 29 84 79 7A 7C 79' + '79 79 79 79 79 79 79 79 79 78 70 6B 6B 6B 6C 6C' + '6C 6C 6C 6C 6C 3C 3C 3C 3C 07 68 A4 68 A4 A4 00' + '00 00 00 00 00 00 00 00 A4 A4 20 80 7C 7A 78 7B' + '7B 7B 7B 7B 7B 7B 7B 7B 7B 7B 7B 75 6F 6C 6A 69' + '68 69 69 69 6A 6A 3C 3C 4C 07 A4 68 A4 A4 00 00' + '00 00 00 00 00 00 00 00 A4 A4 17 74 7E 7D 74 7D' + '7E 7E 7E 7E 7E 7E 7E 7E 7E 7E 7E 7F 7E 7D 7B 77' + '74 71 6E 6C 6A 5D 65 78 4C 07 A4 A4 00 00 00 00' + '00 00 00 00 00 00 00 00 A4 A4 0A 5B 83 83 78 7A' + '83 81 82 82 82 82 82 82 82 82 82 82 82 82 82 83' + '83 82 81 81 77 6D 74 72 37 02 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 A4 A4 06 4A 84 87 84 76' + '7E 86 85 85 85 85 85 85 85 85 85 85 85 85 85 85' + '85 85 86 80 76 85 84 6E 25 A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 34 7B 8A 89 86' + '76 7F 89 8A 88 88 88 88 88 88 88 88 88 88 88 88' + '89 89 81 75 82 8B 81 63 1B A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 24 71 8D 8B 8C' + '89 7F 7A 82 8C 8D 8C 8C 8C 8C 8C 8C 8C 8C 8D 8D' + '84 7A 7E 88 8C 8E 7E 56 0E A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 1A 65 8E 8E 8E' + '8F 8F 87 7A 7B 86 8B 8B 8C 8C 8C 8C 8B 8B 86 7C' + '79 85 8F 8F 8E 90 7C 4D 08 A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 0C 58 8C 95 8F' + '8E 94 93 92 8C 88 87 87 85 84 84 85 87 87 87 8A' + '91 94 92 8D 93 93 7E 43 A4 A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 A4 A4 06 4C 8C 87 65' + '69 7E 94 95 95 96 96 95 94 93 93 94 95 96 96 95' + '96 8C 6A 66 79 94 7C 33 A4 A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 44 88 6C 5C' + '60 5C 93 99 98 98 98 98 98 98 98 98 98 98 98 98' + '9B 7D 5B 5E 5F 93 75 2A A4 A4 A4 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 2B 76 85 84' + '7D 8C A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1 A1' + 'A2 9A 87 80 84 7F 5B 19 A4 A4 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 0B 3D 66 7B' + '7F 83 80 80 80 80 80 80 80 80 80 80 80 80 80 80' + '80 81 81 7F 75 5B 28 04 A4 A4 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 A4 A4 A4 09 1D 23' + '22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22' + '22 22 22 23 23 18 02 A4 A4 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 A4 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4 A4' + 'A4 A4 A4 A4 A4 A4 A4 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF 0F FF FF 00 00 FF FF' + 'FE 00 FF FF 00 00 FF FF FC 00 FF FF 00 00 FF FF' + 'F8 00 BF FF 00 00 FF FF F0 00 9F FF 00 00 FF FF' + 'E0 00 9F FF 00 00 FF FF E0 00 8F FF 00 00 F0 00' + '00 00 0F FF 00 00 C0 00 00 00 09 FF 00 00 80 00' + '00 00 08 FF 00 00 80 00 00 00 00 FF 00 00 00 00' + '00 00 00 BF 00 00 00 00 00 00 00 9F 00 00 00 00' + '00 00 00 8F 00 00 00 00 00 00 00 0F 00 00 00 00' + '00 00 00 0B 00 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 01 00 00 80 00 00 00 00 03 00 00 80 00' + '00 00 00 07 00 00 80 00 00 00 00 0F 00 00 80 00' + '00 00 00 1F 00 00 C0 00 00 00 00 3F 00 00 C0 00' + '00 00 00 7F 00 00 C0 00 00 00 00 FF 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' + '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' + '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 08 80 06 60 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 88 0E 60 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 08 00 80 7E E0 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 80 00 E0 06 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '08 00 08 08 00 80 06 60 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 80 00 80 00 80 08 0E 60' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08' + '00 08 00 00 08 00 7E E0 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 80 00 80 00 00 00 80 00 E0' + '06 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00' + '08 00 00 80 00 08 00 80 06 60 00 00 00 00 00 00' + '87 77 77 77 77 77 78 00 80 00 08 08 00 00 80 08' + '0E 60 00 00 00 00 00 08 FF F7 88 88 77 77 78 08' + '00 00 80 80 80 00 08 00 7E E0 00 00 00 00 00 07' + 'FF F7 00 88 88 87 78 80 00 08 08 08 00 00 00 80' + '00 E0 06 00 00 00 00 07 FF F7 88 88 88 76 60 70' + '00 00 80 80 00 00 00 08 00 80 06 60 00 00 00 07' + 'FF F7 88 88 88 76 60 07 00 00 08 00 00 80 00 00' + '80 08 0E 60 00 00 00 07 FF F7 88 88 88 7E EE E8' + '70 00 00 00 00 08 00 00 08 00 7E E0 00 00 00 07' + 'FF F7 88 88 88 88 EE 88 87 00 00 00 80 00 80 00' + '00 80 00 E0 06 00 00 07 FF F7 77 77 77 77 77 76' + '60 70 00 00 08 00 08 00 00 08 00 80 06 60 00 07' + 'FF FF FF FF FF FF 77 76 60 07 00 00 00 80 00 80' + '00 00 80 08 0E 60 00 07 FF FF FF FF FF FF FF FE' + 'EE EF 70 00 00 08 00 08 00 00 08 00 7E E0 00 07' + 'FF FF FF 77 77 7F FF FF EE 77 77 00 00 00 80 00' + '00 00 00 80 00 E0 00 07 77 77 F7 77 77 77 77 77' + '77 76 60 70 00 00 08 00 00 00 00 08 00 80 00 07' + '77 77 F7 77 77 77 77 77 77 76 60 07 00 00 00 00' + '88 80 00 00 80 80 00 07 77 7F F7 77 77 77 77 77' + '77 7E EE E7 70 00 00 08 08 08 00 00 08 70 00 07' + 'FF FF 77 77 77 7F FF FF FF FF EE FF 77 00 00 08' + '80 88 00 00 07 00 00 08 77 77 77 77 7F FF 77 77' + '77 77 FF F6 60 70 00 08 08 08 00 00 70 00 00 08' + '77 77 77 7F F7 77 77 77 77 77 77 76 60 07 00 00' + '88 80 00 07 00 00 00 00 77 77 77 F7 77 77 77 77' + '77 77 77 7E EE E8 70 00 00 00 00 70 00 00 00 00' + '77 77 7F 77 77 77 77 77 77 77 77 77 EE 77 87 00' + '00 00 07 00 00 00 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 77 76 60 70 00 00 70 00 00 00 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 77 76 60 07' + '00 07 00 00 00 00 00 00 87 77 77 77 77 77 77 77' + '77 77 77 77 77 7E EE E0 70 70 00 00 00 00 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 77 77 EE 80' + '07 00 00 00 00 00 00 00 07 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '07 77 77 77 77 77 77 77 77 77 77 77 77 77 77 80' + '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '08 77 77 77 77 77 77 77 77 77 77 77 77 77 77 00' + '00 00 00 00 00 00 00 00 08 77 77 77 77 77 77 77' + '77 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' + '00 77 77 77 77 77 77 77 77 77 77 77 77 77 78 00' + '00 00 00 00 00 00 00 00 00 7F FF FF F7 77 77 77' + '77 77 77 7F FF FF 78 00 00 00 00 00 00 00 00 00' + '00 8F 77 77 F7 77 77 77 77 77 77 FF 77 7F 78 00' + '00 00 00 00 00 00 00 00 00 8F 77 77 F7 77 77 77' + '77 77 77 F7 77 7F 78 00 00 00 00 00 00 00 00 00' + '00 87 77 7F F7 77 77 77 77 77 77 FF 77 77 70 00' + '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' + '77 77 77 77 77 77 80 00 00 00 00 00 00 00 00 00' + '00 00 08 88 88 88 88 88 88 88 88 88 88 80 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF 01 FF FF 00 00 FF FF FE 00 FF FF 00 00 FF FF' + 'FC 00 FF FF 00 00 FF FF F8 00 BF FF 00 00 FF FF' + 'F0 00 9F FF 00 00 FF FF F0 00 8F FF 00 00 FF FF' + 'E0 00 8F FF 00 00 F0 00 00 00 0F FF 00 00 C0 00' + '00 00 09 FF 00 00 80 00 00 00 08 FF 00 00 80 00' + '00 00 00 FF 00 00 00 00 00 00 00 BF 00 00 00 00' + '00 00 00 9F 00 00 00 00 00 00 00 8F 00 00 00 00' + '00 00 00 0F 00 00 00 00 00 00 00 0B 00 00 00 00' + '00 00 00 09 00 00 00 00 00 00 00 08 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00' + '00 00 00 00 00 00 80 00 00 00 00 01 00 00 80 00' + '00 00 00 03 00 00 80 00 00 00 00 07 00 00 80 00' + '00 00 00 0F 00 00 80 00 00 00 00 1F 00 00 C0 00' + '00 00 00 3F 00 00 C0 00 00 00 00 7F 00 00 C0 00' + '00 00 00 FF 00 00 C0 00 00 00 03 FF 00 00 C0 00' + '00 00 07 FF 00 00 C0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 F0 00 00 00 07 FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 1F FF 00 00 F8 00 00 00 3F FF 00 00 FE 00' + '00 00 7F FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 00 00' + '00 78 00 00 00 78 00 00 00 3C 00 00 00 30 00 00' + '00 6C 00 00 00 6C 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 3C 80 80 80 FF 80 80' + '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3C 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' + '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 3C 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' + '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3C 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' + 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' + '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 3E 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3E 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 00 00 FF FF FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 16 00 00 00 34 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 3E 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 05 00 00 00 69 00 00 00 C5 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 30 00 80 80 FF 00 00' + '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00' + '00 9B 00 00 00 FF 00 00 00 FF 21 21 21 FF 2C 2C' + '2C FF 2B 2B 2B FF 2C 2C 2C FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B 2B FF 2B 2B' + '2B FF 2B 2B 2B FF 2B 2B 2B FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 90 00 00 00 30 00 80 80 FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 54 00 00' + '00 FF 26 26 26 FF 90 90 90 FF CA CA CA FF CD CD' + 'CD FF CB CB CB FF CE CE CE FF CD CD CD FF CC CC' + 'CC FF CB CB CB FF C9 C9 C9 FF C7 C7 C7 FF C6 C6' + 'C6 FF C5 C5 C5 FF C4 C4 C4 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 84 00 FF FF FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' + '00 18 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 03 00 00 00 AD 01 01' + '01 FF 8A 8A 8A FF EB EB EB FF E8 E8 E8 FF E7 E7' + 'E7 FF D5 D5 D5 FF 85 85 85 FF 88 88 88 FF 92 92' + '92 FF 98 98 98 FF A2 A2 A2 FF AD AD AD FF BA BA' + 'BA FF C0 C0 C0 FF C3 C3 C3 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' + '00 54 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 15 00 00 00 F0 19 19' + '19 FF C7 C7 C7 FF EC EC EC FF E2 E2 E2 FF E6 E6' + 'E6 FF CB CB CB FF 3B 3B 3B FF 3F 3F 3F FF 56 56' + '56 FF 72 72 72 FF 87 87 87 FF 92 92 92 FF 9D 9D' + '9D FF A5 A5 A5 FF A8 A8 A8 FF 80 80 80 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' + 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' + '00 84 00 00 00 78 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 30 00 00 00 FA 29 29' + '29 FF D1 D1 D1 FF EA EA EA FF E4 E4 E4 FF E7 E7' + 'E7 FF CD CD CD FF 47 47 47 FF 5F 5F 5F FF 79 79' + '79 FF 87 87 87 FF 8F 8F 8F FF 97 97 97 FF A0 A0' + 'A0 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 34 00 00 00 F9 28 28' + '28 FF D1 D1 D1 FF EC EC EC FF E6 E6 E6 FF E7 E7' + 'E7 FF D1 D1 D1 FF 68 68 68 FF 74 74 74 FF 7E 7E' + '7E FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' + 'A0 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' + '80 FF 00 00 00 90 00 00 00 30 00 00 00 0C 00 00' + '00 18 00 00 00 0C 00 00 00 33 00 00 00 F9 28 28' + '28 FF D1 D1 D1 FF EE EE EE FF E7 E7 E7 FF E8 E8' + 'E8 FF D6 D6 D6 FF 70 70 70 FF 71 71 71 FF 7D 7D' + '7D FF 85 85 85 FF 8E 8E 8E FF 97 97 97 FF A0 A0' + 'A0 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' + 'FF FF 9C 9C 9C FF C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 30 00 00 00 24 00 00' + '00 54 00 00 00 3C 00 00 00 33 00 00 00 F9 27 27' + '27 FF D1 D1 D1 FF EF EF EF FF E9 E9 E9 FF EB EB' + 'EB FF D6 D6 D6 FF 6A 6A 6A FF 6C 6C 6C FF 78 78' + '78 FF 81 81 81 FF 8A 8A 8A FF 93 93 93 FF 9C 9C' + '9C FF 9C 9C 9C FF 00 FF FF FF 00 FF FF FF 9C 9C' + '9C FF 9C 9C 9C FF 9C 9C 9C FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' + 'FF FF 00 00 00 9C 00 00 00 48 00 80 80 FF 00 00' + '00 84 00 00 00 78 00 00 00 33 00 00 00 F9 27 27' + '27 FF D2 D2 D2 FF F2 F2 F2 FF EB EB EB FF EA EA' + 'EA FF DF DF DF FF A7 A7 A7 FF A7 A7 A7 FF AB AB' + 'AB FF AE AE AE FF B0 B0 B0 FF B3 B3 B3 FF B6 B6' + 'B6 FF B9 B9 B9 FF B9 B9 B9 FF BA BA BA FF BD BD' + 'BD FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 00 00 84 00 80 80 FF 00 80' + '80 FF 00 00 00 90 00 00 00 33 00 00 00 F9 26 26' + '26 FF D3 D3 D3 FF F3 F3 F3 FF EB EB EB FF EB EB' + 'EB FF EA EA EA FF ED ED ED FF EB EB EB FF E9 E9' + 'E9 FF E8 E8 E8 FF E6 E6 E6 FF E4 E4 E4 FF E2 E2' + 'E2 FF E1 E1 E1 FF DF DF DF FF DE DE DE FF DB DB' + 'DB FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 B4 00 FF FF FF 00 80' + '80 FF 00 00 00 90 00 00 00 33 00 00 00 F9 26 26' + '26 FF D3 D3 D3 FF F7 F7 F7 FF F8 F8 F8 FF F6 F6' + 'F6 FF F6 F6 F6 FF F6 F6 F6 FF F5 F5 F5 FF F5 F5' + 'F5 FF F4 F4 F4 FF F4 F4 F4 FF F3 F3 F3 FF F3 F3' + 'F3 FF F3 F3 F3 FF F2 F2 F2 FF F2 F2 F2 FF F1 F1' + 'F1 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' + 'FF FF F1 F1 F1 FF C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 FF FF FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 33 00 00 00 F9 24 24' + '24 FF D6 D6 D6 FF FF FF FF FF E9 E9 E9 FF E1 E1' + 'E1 FF E2 E2 E2 FF E2 E2 E2 FF E0 E0 E0 FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF DF DF DF FF DF DF' + 'DF FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF 00 FF FF FF 00 FF FF FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 FF' + 'FF FF 00 00 00 90 00 00 00 34 00 00 00 FA 24 24' + '24 FF DE DE DE FF F8 F8 F8 FF D9 D9 D9 FF C4 C4' + 'C4 FF BB BB BB FF BF BF BF FF D8 D8 D8 FF DA DA' + 'DA FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9 D9 FF D9 D9' + 'D9 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 90 00 00 00 25 00 00 00 F7 1F 1F' + '1F FF DA DA DA FF F3 F3 F3 FF C6 C6 C6 FF A9 A9' + 'A9 FF B7 B7 B7 FF B0 B0 B0 FF C3 C3 C3 FF DA DA' + 'DA FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7 D7 FF D7 D7' + 'D7 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 78 00 00 00 07 00 00 00 D0 05 05' + '05 FF C2 C2 C2 FF F6 F6 F6 FF BC BC BC FF B2 B2' + 'B2 FF C3 C3 C3 FF AB AB AB FF BB BB BB FF D8 D8' + 'D8 FF D5 D5 D5 FF D5 D5 D5 FF D5 D5 D5 FF D4 D4' + 'D4 FF D3 D3 D3 FF D3 D3 D3 FF D5 D5 D5 FF D7 D7' + 'D7 FF D8 D8 D8 FF D8 D8 D8 FF D7 D7 D7 FF D5 D5' + 'D5 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' + 'FF FF D7 D7 D7 FF C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF C0 C0' + 'C0 FF 00 00 00 3C 00 00 00 00 00 00 00 9C 00 00' + '00 FF A4 A4 A4 FF F4 F4 F4 FF CF CF CF FF C5 C5' + 'C5 FF D2 D2 D2 FF BF BF BF FF C9 C9 C9 FF D3 D3' + 'D3 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF DD DD' + 'DD FF E1 E1 E1 FF E3 E3 E3 FF E6 E6 E6 FF EA EA' + 'EA FF ED ED ED FF ED ED ED FF EB EB EB FF E7 E7' + 'E7 FF E7 E7 E7 FF 00 FF FF FF 00 FF FF FF E7 E7' + 'E7 FF E7 E7 E7 FF D7 D7 D7 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 73 00 00' + '00 FF 7E 7E 7E FF EF EF EF FF D1 D1 D1 FF CF CF' + 'CF FF CB CB CB FF CF CF CF FF D1 D1 D1 FF CE CE' + 'CE FF CF CF CF FF DF DF DF FF F0 F0 F0 FF EC EC' + 'EC FF E1 E1 E1 FF DE DE DE FF DD DD DD FF DC DC' + 'DC FF DB DB DB FF DB DB DB FF DC DC DC FF DD DD' + 'DD FF DE DE DE FF E1 E1 E1 FF EC EC EC FF F1 F1' + 'F1 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 59 00 00' + '00 FF 59 59 59 FF E9 E9 E9 FF D0 D0 D0 FF CD CD' + 'CD FF CD CD CD FF CD CD CD FF CA CA CA FF D6 D6' + 'D6 FF ED ED ED FF E6 E6 E6 FF DC DC DC FF D4 D4' + 'D4 FF D5 D5 D5 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D5 D5 D5 FF D5 D5 D5 FF DB DB' + 'DB FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 80 80 80 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3E 00 00' + '00 FE 40 40 40 FF D7 D7 D7 FF D2 D2 D2 FF CA CA' + 'CA FF CB CB CB FF CA CA CA FF D4 D4 D4 FF E9 E9' + 'E9 FF DC DC DC FF D0 D0 D0 FF D1 D1 D1 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2' + 'D2 FF D2 D2 D2 FF D2 D2 D2 FF D2 D2 D2 FF D1 D1' + 'D1 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' + 'FF FF 99 99 99 FF C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 25 00 00' + '00 F8 22 22 22 FF B7 B7 B7 FF DB DB DB FF CA CA' + 'CA FF CB CB CB FF CE CE CE FF E4 E4 E4 FF D4 D4' + 'D4 FF CF CF CF FF D1 D1 D1 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CD CD' + 'CD FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF CE CE CE FF CE CE CE FF CE CE' + 'CE FF CE CE CE FF 00 FF FF FF 00 FF FF FF CF CF' + 'CF FF CF CF CF FF 99 99 99 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 E1 07 07 07 FF 9F 9F 9F FF DD DD DD FF CC CC' + 'CC FF CD CD CD FF DB DB DB FF D6 D6 D6 FF CE CE' + 'CE FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CC CC' + 'CC FF C9 C9 C9 FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF CA CA CA FF CA CA' + 'CA FF CA CA CA FF CA CA CA FF C8 C8 C8 FF CF CF' + 'CF FF 00 80 80 FF 00 80 80 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 B2 00 00 00 FF 83 83 83 FF DD DD DD FF CF CF' + 'CF FF D1 D1 D1 FF DB DB DB FF D1 D1 D1 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0' + 'D0 FF D0 D0 D0 FF D0 D0 D0 FF D0 D0 D0 FF CF CF' + 'CF FF C9 C9 C9 FF C5 C5 C5 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6' + 'C6 FF C6 C6 C6 FF C6 C6 C6 FF C6 C6 C6 FF C7 C7' + 'C7 FF 00 80 80 FF 00 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 80 00 00 00 FF 5F 5F 5F FF DC DC DC FF D1 D1' + 'D1 FF D2 D2 D2 FF D4 D4 D4 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D0 D0 D0 FF C8 C8 C8 FF C3 C3 C3 FF C3 C3' + 'C3 FF C3 C3 C3 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4 C4 FF C4 C4' + 'C4 FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 FF' + 'FF FF 09 09 09 FF C0 C0 C0 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 3D 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 4B 00 00 00 FE 41 41 41 FF D8 D8 D8 FF D4 D4' + 'D4 FF D2 D2 D2 FF D0 D0 D0 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3 D3 FF D3 D3' + 'D3 FF D3 D3 D3 FF D3 D3 D3 FF CD CD CD FF C7 C7' + 'C7 FF C4 C4 C4 FF C2 C2 C2 FF C1 C1 C1 FF C0 C0' + 'C0 FF C1 C1 C1 FF C1 C1 C1 FF C1 C1 C1 FF C2 C2' + 'C2 FF C2 C2 C2 FF 00 FF FF FF 00 FF FF FF 99 99' + '99 FF 09 09 09 FF 00 00 00 CF C0 C0 C0 FF 00 00' + '00 40 00 00 00 0E 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1A 00 00 00 F2 2C 2C 2C FF CC CC CC FF D6 D6' + 'D6 FF D5 D5 D5 FF CC CC CC FF D5 D5 D5 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6 D6 FF D6 D6' + 'D6 FF D6 D6 D6 FF D6 D6 D6 FF D7 D7 D7 FF D6 D6' + 'D6 FF D5 D5 D5 FF D3 D3 D3 FF CF CF CF FF CC CC' + 'CC FF C9 C9 C9 FF C6 C6 C6 FF C4 C4 C4 FF C2 C2' + 'C2 FF B3 B3 B3 FF BD BD BD FF D0 D0 D0 FF 99 99' + '99 FF 09 09 09 FF 00 00 00 CF 00 00 00 3E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 09 00 00 00 D8 18 18 18 FF B0 B0 B0 FF DB DB' + 'DB FF DB DB DB FF D0 D0 D0 FF D2 D2 D2 FF DB DB' + 'DB FF D9 D9 D9 FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DA DA DA FF DA DA' + 'DA FF DA DA DA FF DA DA DA FF DB DB DB FF DB DB' + 'DB FF DA DA DA FF D9 D9 D9 FF D9 D9 D9 FF CF CF' + 'CF FF C5 C5 C5 FF CC CC CC FF CA CA CA FF 7A 7A' + '7A FF 02 02 02 FF 00 00 00 B8 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 02 00 00 00 BF 08 08 08 FF 97 97 97 FF DC DC' + 'DC FF DF DF DF FF DC DC DC FF CE CE CE FF D6 D6' + 'D6 FF DE DE DE FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DD DD DD FF DD DD DD FF DD DD' + 'DD FF DD DD DD FF DE DE DE FF D8 D8 D8 FF CE CE' + 'CE FF DD DD DD FF DC DC DC FF C6 C6 C6 FF 53 53' + '53 FF 00 00 00 FF 00 00 00 A0 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 A4 00 00 00 FF 77 77 77 FF D3 D3' + 'D3 FF E2 E2 E2 FF E1 E1 E1 FF DE DE DE FF CE CE' + 'CE FF D7 D7 D7 FF E1 E1 E1 FF E2 E2 E2 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0' + 'E0 FF E0 E0 E0 FF E0 E0 E0 FF E0 E0 E0 FF E1 E1' + 'E1 FF E1 E1 E1 FF D9 D9 D9 FF CD CD CD FF DA DA' + 'DA FF E3 E3 E3 FF D9 D9 D9 FF BB BB BB FF 39 39' + '39 FF 00 00 00 FF 00 00 00 7E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 89 00 00 00 FF 4B 4B 4B FF C9 C9' + 'C9 FF E5 E5 E5 FF E3 E3 E3 FF E4 E4 E4 FF E1 E1' + 'E1 FF D7 D7 D7 FF D2 D2 D2 FF DA DA DA FF E4 E4' + 'E4 FF E5 E5 E5 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4' + 'E4 FF E4 E4 E4 FF E5 E5 E5 FF E5 E5 E5 FF DC DC' + 'DC FF D2 D2 D2 FF D6 D6 D6 FF E0 E0 E0 FF E4 E4' + 'E4 FF E6 E6 E6 FF D6 D6 D6 FF A8 A8 A8 FF 20 20' + '20 FF 00 00 00 FD 00 00 00 4E 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 62 00 00 00 FF 35 35 35 FF BD BD' + 'BD FF E6 E6 E6 FF E6 E6 E6 FF E6 E6 E6 FF E7 E7' + 'E7 FF E7 E7 E7 FF DF DF DF FF D2 D2 D2 FF D3 D3' + 'D3 FF DE DE DE FF E3 E3 E3 FF E3 E3 E3 FF E4 E4' + 'E4 FF E4 E4 E4 FF E4 E4 E4 FF E4 E4 E4 FF E3 E3' + 'E3 FF E3 E3 E3 FF DE DE DE FF D4 D4 D4 FF D1 D1' + 'D1 FF DD DD DD FF E7 E7 E7 FF E7 E7 E7 FF E6 E6' + 'E6 FF E8 E8 E8 FF D4 D4 D4 FF 9A 9A 9A FF 0B 0B' + '0B FF 00 00 00 ED 00 00 00 2C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2D 00 00 00 F9 1E 1E 1E FF AB AB' + 'AB FF E4 E4 E4 FF ED ED ED FF E7 E7 E7 FF E6 E6' + 'E6 FF EC EC EC FF EB EB EB FF EA EA EA FF E4 E4' + 'E4 FF E0 E0 E0 FF DF DF DF FF DF DF DF FF DD DD' + 'DD FF DC DC DC FF DC DC DC FF DD DD DD FF DF DF' + 'DF FF DF DF DF FF DF DF DF FF E2 E2 E2 FF E9 E9' + 'E9 FF EC EC EC FF EA EA EA FF E5 E5 E5 FF EB EB' + 'EB FF EB EB EB FF D6 D6 D6 FF 8A 8A 8A FF 00 00' + '00 FF 00 00 00 C3 00 00 00 17 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 09 00 00 00 DD 08 08 08 FF 99 99' + '99 FF E4 E4 E4 FF DF DF DF FF BD BD BD FF C1 C1' + 'C1 FF D6 D6 D6 FF EC EC EC FF ED ED ED FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EC EC' + 'EC FF EB EB EB FF EB EB EB FF EC EC EC FF ED ED' + 'ED FF EE EE EE FF EE EE EE FF ED ED ED FF EE EE' + 'EE FF E4 E4 E4 FF C2 C2 C2 FF BE BE BE FF D1 D1' + 'D1 FF EC EC EC FF D4 D4 D4 FF 75 75 75 FF 00 00' + '00 FF 00 00 00 9C 00 00 00 06 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 AE 00 00 00 FF 8D 8D' + '8D FF E0 E0 E0 FF C4 C4 C4 FF B2 B2 B2 FF B8 B8' + 'B8 FF B2 B2 B2 FF EB EB EB FF F1 F1 F1 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0' + 'F0 FF F0 F0 F0 FF F0 F0 F0 FF F0 F0 F0 FF F3 F3' + 'F3 FF D5 D5 D5 FF B0 B0 B0 FF B6 B6 B6 FF B7 B7' + 'B7 FF EB EB EB FF CD CD CD FF 61 61 61 FF 00 00' + '00 FF 00 00 00 85 00 00 00 01 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 80 00 00 00 FF 64 64' + '64 FF CE CE CE FF DD DD DD FF DC DC DC FF D5 D5' + 'D5 FF E4 E4 E4 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9' + 'F9 FF F9 F9 F9 FF F9 F9 F9 FF F9 F9 F9 FF FA FA' + 'FA FF F2 F2 F2 FF DF DF DF FF D8 D8 D8 FF DC DC' + 'DC FF D7 D7 D7 FF B0 B0 B0 FF 34 34 34 FF 00 00' + '00 FF 00 00 00 67 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 44 00 00 00 FF 19 19' + '19 FF 80 80 80 FF BE BE BE FF D3 D3 D3 FF D7 D7' + 'D7 FF DB DB DB FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8 D8 FF D8 D8' + 'D8 FF D9 D9 D9 FF D9 D9 D9 FF D7 D7 D7 FF CD CD' + 'CD FF B0 B0 B0 FF 5D 5D 5D FF 06 06 06 FF 00 00' + '00 ED 00 00 00 2B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 02 00 00 00 9C 00 00' + '00 FF 0C 0C 0C FF 3D 3D 3D FF 49 49 49 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 48 48 48 FF 48 48' + '48 FF 48 48 48 FF 48 48 48 FF 49 49 49 FF 49 49' + '49 FF 2F 2F 2F FF 02 02 02 FF 00 00 00 FF 00 00' + '00 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00' + '00 7F 00 00 00 F1 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 D6 00 00 00 5C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 2C 00 00 00 7E 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 70 00 00 00 1A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF 80 7F FF 00 00 FF FF' + 'FF 00 7F FF 00 00 FF FF FE 00 0F FF 00 00 FF FF' + 'FC 00 07 FF 00 00 FF FF F8 00 07 FF 00 00 FF FF' + 'F0 00 07 FF 00 00 FF FF E0 00 84 FF 00 00 F0 00' + '00 00 04 7F 00 00 C0 00 00 00 00 7F 00 00 80 00' + '00 00 00 7F 00 00 80 00 00 00 00 0F 00 00 00 00' + '00 00 00 07 00 00 00 00 00 00 00 07 00 00 00 00' + '00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00' + '00 00 00 01 00 00 80 00 00 00 00 03 00 00 80 00' + '00 00 00 07 00 00 80 00 00 00 00 0F 00 00 80 00' + '00 00 00 1F 00 00 C0 00 00 00 00 3F 00 00 C0 00' + '00 00 00 7F 00 00 C0 00 00 00 00 FF 00 00 C0 00' + '00 00 03 FF 00 00 C0 00 00 00 07 FF 00 00 C0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 E0 00' + '00 00 07 FF 00 00 E0 00 00 00 07 FF 00 00 F0 00' + '00 00 07 FF 00 00 F0 00 00 00 0F FF 00 00 F0 00' + '00 00 0F FF 00 00 F0 00 00 00 1F FF 00 00 F8 00' + '00 00 3F FF 00 00 FE 00 00 00 7F FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0C 00 00 00 3C 80 80 80 FF 80 80 80 FF 00 00' + '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 3C 80 80 80 FF 00 00 00 FF 80 80 80 FF 80 80' + '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' + '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 3C 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' + '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' + '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0C 00 00 00 3C 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00 00' + '00 3C 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0C 00 00 00 3C 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' + '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 24 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' + '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' + '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 0C 00 00 00 24 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' + '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 24 00 00 00 6C 80 80 80 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' + '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' + '00 78 00 00 00 24 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' + '00 90 00 00 00 30 00 00 00 0C 00 00 00 18 00 FF' + 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' + '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' + '00 90 00 00 00 30 00 00 00 24 00 00 00 54 00 00' + '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' + '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' + '00 9C 00 00 00 48 00 80 80 FF 00 00 00 84 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 B4 00 00 00 84 00 80 80 FF 00 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 B4 00 FF FF FF 00 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' + 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' + '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 FF FF FF 00 FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' + '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 FF FF FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' + 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' + '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 80 80 80 FF C0 C0 C0 FF 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' + '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 80 80 80 FF 00 00 00 FF 80 80 80 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 80 80 80 FF 00 00 00 FF 80 80' + '80 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 80 80 80 FF 80 80 80 FF 80 80 80 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' + 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' + '00 48 C0 C0 C0 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' + '00 30 00 00 00 6C C0 C0 C0 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF C0 C0 C0 FF 00 00 00 3C 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF C0 C0 C0 FF 00 00 00 3C 00 00 00 0C 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80' + '80 FF 00 80 80 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF C0 C0' + 'C0 FF 00 00 00 3C 00 00 00 0C 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF' + 'FF FF 00 FF FF FF 00 FF FF FF 00 FF FF FF 00 00' + '00 3C C0 C0 C0 FF 00 00 00 FF C0 C0 C0 FF 00 00' + '00 3C 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 FF FF FF 00 FF FF FF 00 00 00 24 00 00' + '00 0C 00 00 00 00 C0 C0 C0 FF 00 00 00 18 00 00' + '00 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00' + '3F FF FE 00 07 FF FC 00 03 FF F8 00 03 FF F0 00' + '03 FF E0 00 00 7F C0 00 00 3F C0 00 00 3F C0 00' + '00 3F C0 00 00 07 00 00 00 03 00 00 00 03 00 00' + '00 03 00 00 00 00 00 00 00 00 80 00 00 00 F0 00' + '00 00 F0 00 00 00 F0 00 00 00 F8 00 00 00 FF 00' + '00 00 FF 00 00 00 FF 00 00 00 FF 80 00 00 FF F0' + '00 00 FF F0 00 01 FF F0 00 03 FF F8 00 07 FF FF' + '00 0F FF FF 00 1F FF FF 00 3F FF FF 84 7F' +} */ + + + +/* BINRES mycomputer.ico */ +15 ICON mycomputer.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 A6 0E 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 8E 11 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 B6 12 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 5E 21 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 C6 27 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 6E 4D 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 16 5E 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 00' + '05 00 11 11 11 00 22 22 22 00 33 33 33 00 44 44' + '44 00 55 55 55 00 66 66 66 00 6F 6D 70 00 77 77' + '77 00 7F 7F 7F 00 99 33 00 00 CC 33 00 00 99 66' + '33 00 CC 66 00 00 CC 66 33 00 D0 60 38 00 CC 99' + '33 00 CC 99 66 00 FF 99 66 00 FF CC 66 00 88 88' + '88 00 99 99 99 00 AA AA AA 00 BB BB BB 00 CC 99' + '99 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 5E 00 60 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5E 00' + '00 00 00 00 00 00 03 00 00 00 66 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 C0 CE' + '0B 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 6D 79 63 6F 6D 70 75 74 65' + '72 2E 69 63 6F 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 22 22 22 22 01 01 01 02 02' + '02 03 04 03 22 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 0B 1B 1A 1A 1A 1A 19 19 19' + '19 18 0D 18 07 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 22 05 1E 21 20 1E 1E 1D 1D 1D 1B' + '1B 1B 19 1A 0D 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 22 06 20 21 20 20 20 20 1E 1E 1D' + '1D 1D 1A 1A 18 04 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 05 1D 21 21 21 20 20 20 1E 1E' + '1D 1D 1A 1B 0D 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 19 21 21 21 21 20 1E 1E 1E' + '1E 1D 1B 1D 09 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 22 06 1E 21 21 21 20 1A 1B 20' + '1E 1E 1D 19 05 22 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 22 08 20 21 21 21 1E 1E 20' + '20 20 1A 06 22 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 22 07 1B 21 21 21 21 21' + '1E 18 06 22 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 22 03 07 0A 1A 18 09' + '06 22 22 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 22 22 22 22 22 22 22 22 22 22 04 0C 08 22' + '22 22 22 22 22 22 22 22 22 22 00 00 00 00 00 00' + '00 22 06 19 1A 1A 1A 1A 1A 1A 1A 1A 1A 1D 1B 1A' + '19 19 19 19 19 19 19 19 0C 05 22 00 00 00 00 00' + '22 04 1B 21 21 21 21 21 21 21 20 20 20 1E 1E 1E' + '1E 1E 1E 1E 1E 1E 1D 1D 1E 0D 22 00 00 00 00 00' + '22 06 20 21 20 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E 1E' + '1E 1E 1D 1D 1D 1D 1D 1D 1D 1A 04 00 00 00 00 00' + '22 06 20 21 1C 12 12 14 14 15 15 15 15 15 15 15' + '15 15 14 13 12 12 12 1B 1D 1A 04 00 00 00 00 00' + '22 06 20 21 1C 11 12 12 13 14 14 14 14 14 14 14' + '14 13 12 12 12 12 12 1B 1E 1A 04 00 00 00 00 00' + '22 06 20 21 1C 11 12 12 12 13 13 14 14 14 14 13' + '13 12 12 12 12 11 11 1B 1E 1A 04 00 00 00 00 00' + '22 06 20 21 1C 0F 12 12 12 12 12 12 12 12 12 12' + '12 12 12 12 12 11 11 1B 1E 1A 04 00 00 00 00 00' + '22 06 20 21 1C 0E 11 12 12 12 12 12 12 12 12 12' + '12 12 12 11 11 0E 0E 1B 1E 1A 04 00 00 00 00 00' + '22 06 20 21 15 0E 0E 11 11 12 12 12 12 12 12 12' + '12 12 11 0F 0E 0E 0E 1B 1E 1A 03 00 00 00 00 00' + '22 06 20 21 15 0E 0E 11 12 12 12 12 12 12 12 12' + '12 12 12 12 0E 0E 0E 1B 1E 1A 03 00 00 00 00 00' + '22 06 1E 21 15 0E 12 12 12 13 13 14 14 14 14 14' + '13 13 12 12 12 11 0E 1D 20 1A 02 00 00 00 00 00' + '22 06 1E 21 15 11 12 12 13 14 14 14 15 15 15 14' + '14 14 13 12 12 12 11 1B 20 1A 01 00 00 00 00 00' + '22 06 1E 21 15 12 12 13 14 14 15 15 15 15 15 15' + '15 14 14 13 12 12 12 1D 20 1A 01 00 00 00 00 00' + '22 06 1E 21 15 12 13 14 14 15 15 16 16 16 16 16' + '15 15 14 14 13 12 12 1D 21 1A 22 00 00 00 00 00' + '22 06 1E 21 15 12 14 14 15 15 16 16 16 16 16 16' + '16 15 15 14 13 12 12 1F 21 1A 22 00 00 00 00 00' + '22 06 1E 21 15 12 15 15 15 15 15 16 17 17 17 16' + '15 15 15 15 15 12 10 1F 21 1A 22 00 00 00 00 00' + '22 05 1E 21 20 1E 20 20 20 20 20 20 20 20 20 20' + '20 20 20 20 20 1E 1E 21 21 1A 22 00 00 00 00 00' + '22 22 18 21 21 21 21 21 21 21 21 21 21 21 21 21' + '21 21 21 21 21 21 21 21 20 09 22 00 00 00 00 00' + '00 22 05 09 0C 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B' + '0B 0B 0B 0B 0B 0B 0B 0B 08 02 22 00 00 00 00 00' + '00 00 22 22 22 22 22 22 22 22 22 22 22 22 22 22' + '22 22 22 22 22 22 22 22 22 22 00 00 00 00 FF FF' + 'FF FF FF 00 00 FF FF 00 00 FF FE 00 00 FF FE 00' + '00 FF FF 00 00 FF FF 00 00 FF FF 00 00 FF FF 80' + '01 FF FF C0 03 FF FF E0 07 FF F0 00 00 0F E0 00' + '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' + '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' + '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' + '00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00' + '00 07 C0 00 00 07 E0 00 00 07 F0 00 00 0F 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 01 00 00 00 02 00' + '00 00 03 00 00 00 00 00 05 00 08 00 00 00 11 11' + '11 00 22 22 22 00 33 33 33 00 44 44 44 00 55 55' + '55 00 66 66 66 00 6F 6D 70 00 77 77 77 00 7F 7F' + '7F 00 99 33 00 00 CC 66 00 00 CC 66 33 00 D0 60' + '38 00 CC 66 66 00 CC 99 33 00 CC 99 66 00 FF 99' + '66 00 FF CC 66 00 88 88 88 00 99 99 99 00 AA AA' + 'AA 00 BB BB BB 00 CC 99 99 00 CC CC 99 00 FF CC' + '99 00 CC CC CC 00 DD DD DD 00 EE EE EE 00 FF FF' + 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 15 00 00 00 78 0A' + '38 00 00 00 38 00 B0 6C 38 00 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 96 00' + '00 00 96 00 00 00 09 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 5E 00' + '60 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 5E 00 00 00 00 00 00 00 03 00' + '00 00 66 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 C0 CE 0B 01 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 6D' + '79 63 6F 6D 70 75 74 65 72 2E 69 63 6F 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 01 05 05 05 05 05' + '05 01 00 00 00 00 00 00 00 00 0A 1F 1B 1A 1A 19' + '18 08 00 00 00 00 00 00 00 00 0D 22 21 21 20 1F' + '1B 09 00 00 00 00 00 00 00 00 08 21 22 20 20 21' + '1B 07 00 00 00 00 00 00 00 00 00 0A 20 21 21 1B' + '08 00 00 00 00 00 00 00 02 04 04 23 06 0D 0B 06' + '23 05 05 02 00 00 00 03 19 1F 1F 1F 1B 1F 1B 1B' + '1B 1B 1B 0C 23 00 00 06 21 1E 1E 1E 1E 1E 1E 1D' + '1C 15 1D 1B 05 00 00 07 21 15 10 11 12 14 14 11' + '11 10 15 1B 05 00 00 07 21 15 10 11 11 11 11 11' + '11 0F 15 1B 05 00 00 06 21 11 0F 11 11 11 11 11' + '11 0F 15 1B 05 00 00 06 21 13 11 12 14 14 14 14' + '11 10 15 1B 05 00 00 06 20 15 11 14 15 16 15 15' + '14 11 15 1F 05 00 00 06 20 15 14 15 16 17 17 16' + '15 11 1C 1F 04 00 00 05 1F 22 21 21 21 21 21 21' + '21 21 22 1A 23 00 00 00 07 09 09 09 09 09 09 09' + '09 09 09 06 00 00 F0 0F 00 00 F0 0F 00 00 F0 0F' + '00 00 F0 0F 00 00 F8 1F 00 00 C0 03 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 C0 03 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 08 77 77 78 88 88 88 80 00 00 00 00 00 00' + '00 00 07 FF 77 77 77 77 87 80 00 00 00 00 00 00' + '00 00 0F FF FF FF 77 77 77 80 00 00 00 00 00 00' + '00 00 07 FF FF FF 77 77 77 80 00 00 00 00 00 00' + '00 00 08 FF FF FF 77 77 77 80 00 00 00 00 00 00' + '00 00 00 FF FF F7 7F F7 78 00 00 00 00 00 00 00' + '00 00 00 8F FF F7 7F FF 70 00 00 00 00 00 00 00' + '00 00 00 00 7F FF FF 78 00 00 00 00 00 00 00 00' + '00 00 00 00 00 87 88 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 08 80 00 00 00 00 00 00 00 00 00' + '08 77 77 77 77 77 77 88 88 88 88 80 00 00 00 00' + '7F FF FF FF FF FF 7F 77 77 77 77 78 00 00 00 00' + 'FF FF 77 77 77 77 77 77 77 77 77 77 00 00 00 00' + 'FF 73 33 88 87 77 77 88 83 33 37 77 00 00 00 00' + 'FF 73 33 33 88 88 88 83 33 33 37 77 00 00 00 00' + 'FF 73 33 33 33 88 33 33 33 33 37 77 00 00 00 00' + 'FF 73 33 33 33 33 33 33 33 33 37 77 00 00 00 00' + 'FF 83 33 33 33 33 33 33 33 33 37 77 00 00 00 00' + 'FF 83 33 33 33 33 33 33 33 33 37 77 00 00 00 00' + 'FF 83 33 33 33 33 33 33 33 33 37 F7 00 00 00 00' + 'FF 83 33 33 33 38 33 33 33 33 37 F7 00 00 00 00' + 'FF 83 33 33 88 88 88 83 33 33 37 F7 00 00 00 00' + '7F 83 33 88 88 87 88 88 83 33 37 F7 00 00 00 00' + '7F 83 38 88 77 77 77 78 88 33 37 F7 00 00 00 00' + '7F 83 38 88 77 77 77 78 88 33 37 F7 00 00 00 00' + '7F 83 88 87 77 77 77 77 88 83 37 F7 00 00 00 00' + '7F FF FF FF FF FF FF FF FF FF 7F F7 00 00 00 00' + '8F FF FF FF FF FF FF FF FF FF FF F8 00 00 00 00' + '08 88 88 88 88 88 88 88 88 88 88 80 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF 00' + '00 FF FE 00 00 7F FE 00 00 7F FE 00 00 7F FE 00' + '00 7F FE 00 00 7F FE 00 00 7F FF 00 00 FF FF 00' + '00 FF FF 80 01 FF F0 00 00 0F E0 00 00 07 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 E0 00 00 07 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00' + '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '87 77 78 80 00 00 00 00 8F FF 77 78 00 00 00 00' + '0F FF 7F 70 00 00 00 00 08 FF F7 80 00 00 00 00' + '00 08 80 00 00 00 00 87 77 77 77 77 78 00 00 F7' + '77 77 77 78 77 00 00 F8 33 88 83 33 87 00 00 F8' + '33 33 33 33 87 00 00 F3 33 33 33 33 87 00 00 F3' + '38 88 88 33 87 00 00 F8 38 88 88 83 87 00 00 F8' + '88 77 78 83 77 00 00 7F FF FF FF FF F7 00 00 08' + '88 88 88 88 80 00 E0 0F 00 00 E0 07 00 00 E0 07' + '00 00 E0 07 00 00 F0 0F 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 00' + '05 00 08 00 00 00 11 11 11 00 22 22 22 00 33 33' + '33 00 44 44 44 00 55 55 55 00 6D 65 5C 00 69 6E' + '65 00 6F 6D 70 00 77 77 77 00 7F 7F 7F 00 99 33' + '00 00 CC 33 00 00 99 66 33 00 98 69 38 00 CC 66' + '00 00 CC 66 33 00 D0 60 38 00 CC 99 33 00 CC 99' + '66 00 FF 99 66 00 FF CC 66 00 88 88 88 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF CC' + '99 00 CC CC CC 00 DD DD DD 00 EE EE EE 00 FF FF' + 'FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 5E 00 60 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 5E 00' + '00 00 00 00 00 00 03 00 00 00 66 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 C0 CE' + '0B 01 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 6D 79 63 6F 6D 70 75 74 65' + '72 2E 69 63 6F 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 25 25 25 25 25' + '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' + '25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 25 25 25 25 25 25' + '25 25 25 25 01 01 01 01 01 02 02 03 04 04 03 25' + '25 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 07 1C 1E 1E 1D' + '1D 1D 1D 1D 1D 1D 1D 1C 1C 1C 1C 1B 1B 1B 1B 0A' + '03 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 0A 24 24 23 23' + '22 22 22 22 21 21 21 21 1E 1E 1E 1D 1C 1C 1C 1D' + '07 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 0F 24 24 23 23' + '22 22 22 22 21 21 21 21 1E 1E 1E 1E 1D 1C 1C 1D' + '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 1C 24 24 24 23' + '23 23 23 23 23 22 22 22 21 21 21 1E 1D 1D 1D 1E' + '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 1B 24 24 24 24' + '24 24 24 24 24 23 23 22 22 22 21 21 1E 1D 1D 1E' + '09 25 25 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 25 25 0B 24 24 24 23' + '23 23 22 22 22 22 22 21 21 21 1E 1E 1D 1D 1E 1E' + '07 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 25 08 23 24 24 24' + '24 24 24 23 23 23 23 22 22 22 22 21 1E 1E 1E 1C' + '06 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 25 04 1C 24 24 24' + '24 24 24 24 22 1E 21 22 23 22 22 21 21 1E 1E 09' + '25 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 25 25 06 21 24 24' + '24 24 24 24 1D 1C 1C 21 23 22 22 21 21 22 1B 25' + '25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 25 25 09 21 24' + '24 24 24 24 23 22 22 23 23 23 22 22 22 0E 06 25' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 25 25 08 1E' + '24 24 24 24 24 24 24 24 23 23 23 21 0E 05 25 25' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 25 25 05' + '0A 21 24 24 24 24 24 24 24 22 1C 08 25 25 25 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 25 25' + '25 06 09 0C 1B 1D 1D 0F 0A 08 04 25 25 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 04 0F 09 25 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 00 00 00 00 00 00 00 00 00' + '00 00 00 25 25 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 0A 1E 1B 07 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 25 25 00 00 00 00 00 00 00' + '00 00 25 25 04 0A 1D 1D 1D 1D 1D 1D 1D 1D 1D 1D' + '1D 1D 1D 1D 21 21 21 1E 1D 1D 1D 1D 1C 1C 1C 1C' + '1C 1C 1C 1C 1C 1C 08 25 25 00 00 00 00 00 00 00' + '00 00 25 25 0E 24 24 24 24 24 24 24 24 24 23 23' + '23 23 23 23 23 22 22 22 22 22 22 22 22 22 22 22' + '22 21 21 21 21 22 21 08 25 25 00 00 00 00 00 00' + '00 25 25 06 22 24 24 24 23 23 23 23 23 23 23 23' + '23 23 22 22 22 22 22 22 22 22 22 21 21 21 21 21' + '21 21 21 21 1E 1E 22 1D 25 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 23 23 23 23 23 23 23 23 23' + '23 23 23 23 23 23 22 22 22 22 22 22 22 22 22 22' + '22 22 21 22 21 1E 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 09 23 24 24 21 18 18 18 1F 1F 1F 20 20' + '20 20 20 20 20 20 20 20 20 20 20 20 1F 1F 1F 18' + '18 18 18 1F 22 21 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 14 15 15 15 15 16 17 17' + '17 17 17 18 18 18 17 17 17 17 17 16 15 15 15 15' + '15 14 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 14 15 15 15 15 16 17 17' + '17 17 17 18 18 18 18 17 17 17 17 16 15 15 15 15' + '15 15 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 14 15 15 15 15 15 16 16' + '17 17 17 17 17 17 17 17 17 16 16 15 15 15 15 15' + '15 15 14 15 22 21 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 14 15 15 15 15 15 15 15' + '16 16 16 17 17 17 16 16 16 15 15 15 15 15 15 15' + '15 14 10 15 22 21 21 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 11 14 15 15 15 15 15 15' + '15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15' + '14 14 10 15 22 21 22 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 14 14 15 15 15 15 15' + '15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 14' + '14 10 10 15 23 21 22 1D 04 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 11 14 14 15 15 15 15' + '15 15 15 15 15 15 15 15 15 15 15 15 15 14 14 14' + '10 10 10 15 23 21 22 1D 03 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 10 10 14 14 14 14 15' + '15 15 15 15 15 15 15 15 15 15 15 15 14 14 14 10' + '10 10 10 15 23 21 22 1D 03 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 10 10 10 14 14 15 15' + '15 15 15 15 15 15 15 15 15 15 15 15 15 14 14 10' + '10 10 10 15 23 22 22 1D 03 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 10 10 10 15 15 15 15' + '15 15 15 16 16 16 16 15 15 15 15 15 15 15 15 14' + '10 10 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 1F 10 10 14 15 15 15 15 15' + '16 16 16 17 17 17 17 17 16 16 16 15 15 15 15 15' + '15 10 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 18 10 14 15 15 15 15 16 16' + '17 17 17 17 17 17 17 17 17 17 17 16 15 15 15 15' + '15 15 10 15 23 22 22 1D 02 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 18 10 15 15 15 16 16 17 17' + '17 17 18 18 18 18 18 18 17 17 17 17 16 16 15 15' + '15 15 15 15 23 22 22 1D 01 25 00 00 00 00 00 00' + '00 25 25 08 23 24 24 18 14 15 15 15 16 17 17 17' + '18 18 18 18 18 18 18 18 18 18 17 17 17 17 16 15' + '15 15 15 15 23 22 22 1D 01 25 00 00 00 00 00 00' + '00 25 25 08 22 24 24 18 15 15 15 16 17 17 17 18' + '18 18 18 18 19 19 18 18 18 18 18 18 17 17 17 16' + '15 15 15 15 23 22 23 1D 25 25 00 00 00 00 00 00' + '00 25 25 08 22 24 24 18 15 15 16 17 17 17 18 18' + '18 19 19 19 19 19 19 19 19 18 18 18 18 17 17 16' + '16 15 15 15 23 23 23 1D 25 25 00 00 00 00 00 00' + '00 25 25 08 22 24 24 18 14 16 16 17 17 18 18 18' + '19 19 19 19 19 19 19 19 19 19 18 18 18 17 17 17' + '16 15 15 15 23 24 24 1D 25 25 00 00 00 00 00 00' + '00 25 25 07 22 24 24 18 10 15 17 17 17 18 18 19' + '19 19 19 1A 1A 1A 1A 19 19 19 19 18 18 17 17 17' + '16 15 15 15 23 24 24 1D 25 25 00 00 00 00 00 00' + '00 25 25 07 22 24 24 1F 12 15 18 18 18 18 18 18' + '18 18 18 1A 1A 1A 1A 18 18 18 18 18 18 18 18 18' + '18 15 12 13 24 24 24 1D 25 25 00 00 00 00 00 00' + '00 25 25 07 22 24 24 23 23 23 23 23 23 23 23 23' + '23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 22' + '22 22 22 23 24 24 24 1D 25 25 00 00 00 00 00 00' + '00 25 25 06 21 24 24 24 24 24 24 24 24 24 24 24' + '24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24' + '24 24 24 24 24 24 24 0F 25 25 00 00 00 00 00 00' + '00 00 25 25 0A 22 24 24 24 24 24 24 24 24 24 24' + '24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24' + '24 24 24 24 24 24 1D 07 25 25 00 00 00 00 00 00' + '00 00 25 25 01 08 0D 0F 0F 0F 0F 0F 0F 0F 0F 0F' + '0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0E 0E 0E' + '0E 0E 0E 0E 0E 0A 06 25 25 00 00 00 00 00 00 00' + '00 00 00 25 25 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 25 25 00 00 00 00 00 00 00' + '00 00 00 00 00 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25' + '25 25 25 25 25 25 25 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF F8 00 00 1F FF 00 00 FF F0' + '00 00 0F FF 00 00 FF E0 00 00 0F FF 00 00 FF E0' + '00 00 0F FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F0' + '00 00 0F FF 00 00 FF F0 00 00 1F FF 00 00 FF F8' + '00 00 3F FF 00 00 FF FC 00 00 3F FF 00 00 FF FE' + '00 00 7F FF 00 00 FF FF 00 01 FF FF 00 00 FE 00' + '00 00 00 7F 00 00 F8 00 00 00 00 1F 00 00 F0 00' + '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 1F 00 00 F8 00' + '00 00 00 1F 00 00 FE 00 00 00 00 7F 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 04 00 00 00' + '00 00 80 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 87 77 77 77 77 78 88 88 88 88 00' + '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' + '77 77 77 77 77 88 87 00 00 00 00 00 00 00 00 00' + '00 00 00 00 08 FF FF F7 77 77 77 77 77 78 87 00' + '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' + 'FF FF 77 77 77 77 77 80 00 00 00 00 00 00 00 00' + '00 00 00 00 08 FF FF FF FF FF FF 77 77 77 77 00' + '00 00 00 00 00 00 00 00 00 00 00 00 08 FF FF FF' + 'F7 77 77 77 77 77 77 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 FF FF FF FF FF FF F7 77 77 78 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 8F FF FF' + 'FF 77 7F FF 77 77 78 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 07 FF FF FF 78 87 FF 77 77 80 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 7F FF' + 'FF F7 FF FF 77 78 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 07 FF FF FF FF FF F7 80 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87' + 'FF FF FF FF 80 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 08 87 78 80 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 08 80 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 87 80 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 08 77 77 77 77 77 77' + '77 77 77 77 77 77 77 78 88 78 00 00 00 00 00 00' + '00 8F FF FF FF FF FF FF FF FF FF FF F7 77 77 77' + '77 77 70 00 00 00 00 00 00 7F FF FF FF FF FF FF' + 'FF F7 77 77 77 77 77 77 77 77 77 00 00 00 00 00' + '00 FF FF FF FF FF FF FF FF FF FF FF F7 77 77 77' + '77 77 77 00 00 00 00 00 00 FF F7 87 77 77 77 77' + '77 77 77 77 77 77 77 78 87 F7 77 00 00 00 00 00' + '00 FF F7 33 33 33 38 88 88 88 88 88 33 33 33 33' + '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 38 88' + '88 88 88 88 83 33 33 33 33 F7 77 00 00 00 00 00' + '00 FF F7 33 33 33 33 38 88 88 88 83 33 33 33 33' + '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 33 33' + '33 33 33 33 33 33 33 33 33 F7 77 00 00 00 00 00' + '00 FF F7 33 33 33 33 33 33 33 33 33 33 33 33 33' + '33 F7 77 00 00 00 00 00 00 FF F7 33 33 33 33 33' + '33 33 33 33 33 33 33 33 13 F7 77 00 00 00 00 00' + '00 FF F7 13 33 33 33 33 33 33 33 33 33 33 33 33' + '13 F7 77 00 00 00 00 00 00 FF F7 13 33 33 33 33' + '33 33 33 33 33 33 33 31 13 F7 77 00 00 00 00 00' + '00 FF F8 11 33 33 33 33 33 33 33 33 33 33 33 11' + '13 F7 77 00 00 00 00 00 00 FF F8 11 13 33 33 33' + '33 33 33 33 33 33 33 11 13 F7 77 00 00 00 00 00' + '00 FF F8 11 33 33 33 33 38 88 83 33 33 33 33 33' + '13 F7 F7 00 00 00 00 00 00 FF F8 13 33 33 33 88' + '88 88 88 88 83 33 33 33 33 F7 F7 00 00 00 00 00' + '00 FF F8 33 33 33 88 88 88 88 88 88 88 33 33 33' + '33 F7 F7 00 00 00 00 00 00 FF F8 33 33 38 88 88' + '88 88 88 88 88 83 33 33 33 F7 F7 00 00 00 00 00' + '00 FF F8 33 33 88 88 88 88 77 78 88 88 88 33 33' + '38 FF F7 00 00 00 00 00 00 FF F8 33 38 88 88 87' + '77 77 77 78 88 88 83 33 38 FF F7 00 00 00 00 00' + '00 FF F8 33 38 88 88 77 77 77 77 77 88 88 88 33' + '33 FF F7 00 00 00 00 00 00 FF F8 33 38 88 87 77' + '77 77 77 77 78 88 83 33 33 FF F7 00 00 00 00 00' + '00 FF F8 38 88 88 87 77 77 77 77 77 78 88 88 88' + '38 FF F7 00 00 00 00 00 00 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF F7 00 00 00 00 00' + '00 7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF F8 00 00 00 00 00 00 8F FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 70 00 00 00 00 00' + '00 00 88 88 88 88 88 88 88 88 88 88 88 88 88 88' + '88 88 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF F8' + '00 00 1F FF 00 00 FF F0 00 00 0F FF 00 00 FF E0' + '00 00 0F FF 00 00 FF E0 00 00 0F FF 00 00 FF E0' + '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF E0 00 00 0F FF 00 00 FF F0' + '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F0' + '00 00 1F FF 00 00 FF F8 00 00 3F FF 00 00 FF FC' + '00 00 3F FF 00 00 FF FE 00 00 7F FF 00 00 FF FF' + '00 01 FF FF 00 00 FE 00 00 00 00 7F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 1F 00 00 F0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 E0 00 00 00 00 0F 00 00 E0 00' + '00 00 00 0F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 1F 00 00 F8 00 00 00 00 1F 00 00 FE 00' + '00 00 00 7F 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 20 00 00 00 00 00 00 24 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 0C 00 00 00 2F 00 00 00 38 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 38 00 00 00 2A 00 00 00 0B 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 43 00 00 00 B0 00 00 00 F4 00 00 00 F8 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F8 00 00 00 DA 00 00 00 85 00 00 00 28 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 11 00 00' + '00 E2 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 01 01 01 FF 01 01 01 FF 01 01' + '01 FF 01 01 01 FF 01 01 01 FF 02 02 02 FF 02 02' + '02 FF 03 03 03 FF 04 04 04 FF 04 04 04 FF 03 03' + '03 FF 00 00 00 FF 00 00 00 FF 00 00 00 AF 00 00' + '00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 65 00 00' + '00 FF 20 20 20 FF 9B 9B 9B FF B9 B9 B9 FF B5 B5' + 'B5 FF B2 B2 B2 FF B0 B0 B0 FF AE AE AE FF AB AB' + 'AB FF A9 A9 A9 FF A7 A7 A7 FF A4 A4 A4 FF A2 A2' + 'A2 FF 9F 9F 9F FF 9C 9C 9C FF 9B 9B 9B FF 96 96' + '96 FF 8C 8C 8C FF 86 86 86 FF 88 88 88 FF 8E 8E' + '8E FF 5A 5A 5A FF 03 03 03 FF 00 00 00 E9 00 00' + '00 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 A6 00 00' + '00 FF 59 59 59 FF FF FF FF FF FA FA FA FF F1 F1' + 'F1 FF EB EB EB FF E4 E4 E4 FF E0 E0 E0 FF DC DC' + 'DC FF D8 D8 D8 FF D4 D4 D4 FF D0 D0 D0 FF CB CB' + 'CB FF C7 C7 C7 FF C3 C3 C3 FF BF BF BF FF BB BB' + 'BB FF B0 B0 B0 FF 9E 9E 9E FF 97 97 97 FF 9E 9E' + '9E FF B0 B0 B0 FF 25 25 25 FF 00 00 00 FD 00 00' + '00 5A 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 C6 00 00' + '00 FF 82 82 82 FF FF FF FF FF F7 F7 F7 FF F1 F1' + 'F1 FF E9 E9 E9 FF E4 E4 E4 FF DF DF DF FF DA DA' + 'DA FF D6 D6 D6 FF D2 D2 D2 FF CE CE CE FF CA CA' + 'CA FF C7 C7 C7 FF C3 C3 C3 FF BF BF BF FF BB BB' + 'BB FF B8 B8 B8 FF A9 A9 A9 FF 9C 9C 9C FF 98 98' + '98 FF AF AF AF FF 3D 3D 3D FF 00 00 00 FF 00 00' + '00 7C 00 00 00 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 D4 00 00' + '00 FF 92 92 92 FF FF FF FF FF FF FF FF FF F9 F9' + 'F9 FF F6 F6 F6 FF F6 F6 F6 FF F3 F3 F3 FF EF EF' + 'EF FF EC EC EC FF E6 E6 E6 FF E1 E1 E1 FF DC DC' + 'DC FF D6 D6 D6 FF D1 D1 D1 FF CC CC CC FF C6 C6' + 'C6 FF C3 C3 C3 FF AF AF AF FF A5 A5 A5 FF A8 A8' + 'A8 FF B6 B6 B6 FF 44 44 44 FF 00 00 00 FF 00 00' + '00 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 B5 00 00' + '00 FF 84 84 84 FF FF FF FF FF FF FF FF FF F7 F7' + 'F7 FF FB FB FB FF FD FD FD FF FC FC FC FF FC FC' + 'FC FF FA FA FA FF F8 F8 F8 FF F1 F1 F1 FF EB EB' + 'EB FF E5 E5 E5 FF DF DF DF FF D9 D9 D9 FF D3 D3' + 'D3 FF CF CF CF FF B5 B5 B5 FF A3 A3 A3 FF AD AD' + 'AD FF BB BB BB FF 3D 3D 3D FF 00 00 00 FF 00 00' + '00 68 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 88 00 00' + '00 FF 5F 5F 5F FF FF FF FF FF FF FF FF FF FB FB' + 'FB FF EF EF EF FF EE EE EE FF E9 E9 E9 FF E3 E3' + 'E3 FF DF DF DF FF DD DD DD FF DA DA DA FF D5 D5' + 'D5 FF D0 D0 D0 FF CC CC CC FF C7 C7 C7 FF C3 C3' + 'C3 FF BE BE BE FF B0 B0 B0 FF B2 B2 B2 FF B4 B4' + 'B4 FF BA BA BA FF 28 28 28 FF 00 00 00 F7 00 00' + '00 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 34 00 00' + '00 FA 2E 2E 2E FF ED ED ED FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FA FA' + 'FA FF F5 F5 F5 FF F4 F4 F4 FF EF EF EF FF EB EB' + 'EB FF E5 E5 E5 FF E0 E0 E0 FF DC DC DC FF D8 D8' + 'D8 FF D2 D2 D2 FF C2 C2 C2 FF BA BA BA FF C1 C1' + 'C1 FF 97 97 97 FF 0A 0A 0A FF 00 00 00 D5 00 00' + '00 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00' + '00 C8 04 04 04 FF 97 97 97 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FD FD FD FF DF DF DF FF BE BE BE FF C4 C4' + 'C4 FF E4 E4 E4 FF E6 E6 E6 FF E1 E1 E1 FF DD DD' + 'DD FF D1 D1 D1 FF C5 C5 C5 FF C2 C2 C2 FF BF BF' + 'BF FF 43 43 43 FF 00 00 00 FF 00 00 00 9A 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 6C 00 00 00 FF 18 18 18 FF D1 D1 D1 FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FE FE FE FF B2 B2 B2 FF 9D 9D 9D FF 98 98' + '98 FF D1 D1 D1 FF ED ED ED FF E5 E5 E5 FF DF DF' + 'DF FF D1 D1 D1 FF CC CC CC FF D5 D5 D5 FF 84 84' + '84 FF 00 00 00 FF 00 00 00 E2 00 00 00 29 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 96 00 00 00 FF 3E 3E 3E FF D1 D1' + 'D1 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF ED ED ED FF DE DE DE FF E1 E1' + 'E1 FF EC EC EC FF EE EE EE FF E7 E7 E7 FF DC DC' + 'DC FF DC DC DC FF D7 D7 D7 FF 7B 7B 7B FF 14 14' + '14 FF 00 00 00 FF 00 00 00 5F 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1A 00 00 00 C6 00 00 00 FF 35 35' + '35 FF C3 C3 C3 FF F9 F9 F9 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FC FC FC FF FC FC' + 'FC FF F7 F7 F7 FF F0 F0 F0 FF EC EC EC FF EB EB' + 'EB FF CF CF CF FF 77 77 77 FF 07 07 07 FF 00 00' + '00 FD 00 00 00 8F 00 00 00 05 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 05 00 00 00 B6 00 00' + '00 FF 08 08 08 FF 58 58 58 FF CB CB CB FF FD FD' + 'FD FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF F9 F9 F9 FF E3 E3 E3 FF 9E 9E' + '9E FF 31 31 31 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00' + '00 0C 00 00 00 14 00 00 00 14 00 00 00 14 00 00' + '00 14 00 00 00 14 00 00 00 0E 00 00 00 1F 00 00' + '00 7B 00 00 00 E9 00 00 00 FF 10 10 10 FF 3E 3E' + '3E FF 69 69 69 FF 89 89 89 FF B1 B1 B1 FF A2 A2' + 'A2 FF 7E 7E 7E FF 57 57 57 FF 2C 2C 2C FF 04 04' + '04 FF 00 00 00 FF 00 00 00 BF 00 00 00 4F 00 00' + '00 14 00 00 00 11 00 00 00 14 00 00 00 14 00 00' + '00 14 00 00 00 14 00 00 00 14 00 00 00 0C 00 00' + '00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 04 00 00 00 4C 00 00 00 8A 00 00' + '00 AD 00 00 00 BB 00 00 00 B9 00 00 00 B9 00 00' + '00 B9 00 00 00 B9 00 00 00 B9 00 00 00 B5 00 00' + '00 AB 00 00 00 D1 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 04 04 04 FF 7E 7E 7E FF 4B 4B' + '4B FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 F1 00 00 00 BA 00 00 00 AF 00 00' + '00 B7 00 00 00 B9 00 00 00 B9 00 00 00 B9 00 00' + '00 B9 00 00 00 B9 00 00 00 B8 00 00 00 A5 00 00' + '00 85 00 00 00 43 00 00 00 0A 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 06 00 00 00 95 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 54 54 54 FF BD BD BD FF 8A 8A' + '8A FF 1B 1B 1B FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 F0 00 00 00 69 00 00 00 0D 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 7A 00 00 00 FF 04 04 04 FF 5A 5A 5A FF A7 A7' + 'A7 FF AD AD AD FF AB AB AB FF AA AA AA FF AA AA' + 'AA FF AA AA AA FF A9 A9 A9 FF A9 A9 A9 FF A8 A8' + 'A8 FF A8 A8 A8 FF A8 A8 A8 FF A7 A7 A7 FF A6 A6' + 'A6 FF A9 A9 A9 FF C5 C5 C5 FF D3 D3 D3 FF C6 C6' + 'C6 FF B4 B4 B4 FF A3 A3 A3 FF A3 A3 A3 FF A3 A3' + 'A3 FF A2 A2 A2 FF A1 A1 A1 FF A1 A1 A1 FF A1 A1' + 'A1 FF A0 A0 A0 FF A0 A0 A0 FF 9F 9F 9F FF 9F 9F' + '9F FF 9E 9E 9E FF A1 A1 A1 FF 94 94 94 FF 31 31' + '31 FF 00 00 00 FF 00 00 00 F6 00 00 00 5C 00 00' + '00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 28 00 00' + '00 EA 00 00 00 FF 78 78 78 FF FA FA FA FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FE FE FE FF FB FB' + 'FB FF FA FA FA FF F8 F8 F8 FF F7 F7 F7 FF F4 F4' + 'F4 FF F3 F3 F3 FF F2 F2 F2 FF F0 F0 F0 FF EF EF' + 'EF FF EC EC EC FF E6 E6 E6 FF E2 E2 E2 FF E2 E2' + 'E2 FF E3 E3 E3 FF E4 E4 E4 FF E2 E2 E2 FF E0 E0' + 'E0 FF DE DE DE FF DC DC DC FF DB DB DB FF D9 D9' + 'D9 FF D8 D8 D8 FF D6 D6 D6 FF D4 D4 D4 FF D3 D3' + 'D3 FF D0 D0 D0 FF CF CF CF FF DD DD DD FF CB CB' + 'CB FF 39 39 39 FF 00 00 00 FF 00 00 00 AF 00 00' + '00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 78 00 00' + '00 FF 17 17 17 FF DF DF DF FF FF FF FF FF F7 F7' + 'F7 FF F6 F8 F8 FF F5 F6 F8 FF F3 F4 F5 FF F1 F3' + 'F4 FF EF F0 F2 FF ED EF F0 FF EC ED EE FF E9 EA' + 'EB FF E8 E9 EA FF E6 E7 E9 FF E4 E6 E7 FF E2 E3' + 'E4 FF E0 E1 E3 FF DF E0 E1 FF DD DE DF FF DB DC' + 'DD FF D9 DB DC FF D8 D8 D9 FF D6 D7 D8 FF D4 D5' + 'D7 FF D2 D4 D4 FF D0 D1 D3 FF CE D0 D1 FF CD CE' + 'CF FF CB CD CE FF CA CB CD FF C7 C9 CA FF C6 C8' + 'C9 FF C4 C6 C7 FF C2 C3 C3 FF C0 C0 C0 FF D9 D9' + 'D9 FF A4 A4 A4 FF 00 00 00 FF 00 00 00 EE 00 00' + '00 33 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 39 39 39 FF F0 F0 F0 FF FF FF FF FF F9 F9' + 'F9 FF F6 F0 EB FF F5 EF EA FF F5 EE EA FF F3 EE' + 'E9 FF F3 ED E9 FF F2 EC E8 FF F2 EC E8 FF F0 EC' + 'E6 FF F0 EB E6 FF F0 EA E6 FF EF EA E4 FF ED E8' + 'E4 FF ED E8 E3 FF EC E7 E2 FF EB E6 E1 FF E9 E5' + 'E0 FF E8 E4 DF FF E7 E2 DD FF E6 E1 DC FF E5 DF' + 'DB FF E3 DE D9 FF E2 DD D8 FF E1 DB D6 FF DF DA' + 'D4 FF DE D8 D3 FF DD D7 D2 FF DB D5 D0 FF D9 D3' + 'CE FF DB D5 D2 FF D3 D2 D2 FF C3 C3 C3 FF CB CB' + 'CB FF AE AE AE FF 05 05 05 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 3C 3C 3C FF F1 F1 F1 FF FF FF FF FF FB FF' + 'FF FF E2 CA B9 FF D8 9B 70 FF DC A2 79 FF DE A7' + '7D FF E1 AA 81 FF E3 AF 85 FF E5 B2 88 FF E8 B6' + '8C FF E9 B9 8E FF EB BB 91 FF ED BE 94 FF EE C0' + '95 FF EF C1 96 FF EF C2 97 FF EF C2 97 FF EE C1' + '97 FF EE C0 95 FF EC BE 93 FF EB BB 90 FF E9 B8' + '8E FF E7 B5 8B FF E5 B1 87 FF E3 AE 84 FF E1 AA' + '81 FF DF A6 7D FF DC A2 79 FF D9 9E 75 FF D6 97' + '6E FF E0 AB 8B FF E5 E3 E2 FF C4 C5 C6 FF CC CC' + 'CC FF AB AB AB FF 06 06 06 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 3A 3A 3A FF F1 F1 F1 FF FF FF FF FF FD FF' + 'FF FF D0 A9 90 FF BC 56 11 FF C3 63 1F FF C6 69' + '26 FF CA 70 2C FF CD 76 32 FF D1 7B 37 FF D4 81' + '3D FF D7 86 41 FF D9 89 44 FF DC 8D 48 FF DD 90' + '4A FF DF 92 4D FF DF 93 4D FF DF 93 4D FF DE 91' + '4C FF DD 90 4A FF DB 8C 46 FF D8 88 43 FF D6 83' + '3F FF D3 7E 3A FF D0 78 34 FF CC 73 2F FF C8 6D' + '2A FF C5 67 24 FF C1 61 1E FF BD 5A 17 FF B6 4E' + '0A FF C4 6F 38 FF E5 E2 E0 FF C7 C8 C9 FF CF CF' + 'CF FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 39 39 39 FF F0 F0 F0 FF FF FF FF FF FF FF' + 'FF FF D1 AC 94 FF BC 5A 19 FF C2 66 26 FF C6 6C' + '2C FF CA 72 32 FF CD 77 37 FF D0 7C 3C FF D3 81' + '40 FF D5 85 44 FF D7 88 47 FF D9 8C 4A FF DA 8E' + '4C FF DC 8F 4D FF DC 90 4E FF DC 90 4E FF DB 8F' + '4D FF DA 8D 4B FF D9 8A 49 FF D6 87 46 FF D4 83' + '42 FF D1 7F 3E FF CE 7A 39 FF CB 75 34 FF C8 70' + '30 FF C5 6A 2B FF C1 64 25 FF BD 5E 1F FF B7 53' + '12 FF C6 73 3F FF E6 E3 E1 FF C8 C9 CA FF D0 D0' + 'D0 FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' + 'FF FF D1 AB 92 FF B9 55 14 FF BF 61 22 FF C3 67' + '28 FF C6 6D 2D FF CA 71 31 FF CC 76 36 FF CF 7B' + '3A FF D1 7E 3D FF D3 81 40 FF D5 85 44 FF D6 87' + '45 FF D7 88 47 FF D7 89 47 FF D7 89 47 FF D7 87' + '47 FF D6 86 45 FF D4 83 42 FF D2 80 3F FF D0 7D' + '3C FF CE 79 38 FF CB 74 34 FF C8 6F 2F FF C5 6A' + '2B FF C2 65 26 FF BE 60 21 FF BA 5A 1B FF B4 4E' + '0F FF C4 70 3C FF E6 E3 E2 FF CA CB CC FF D2 D2' + 'D2 FF AC AC AC FF 05 05 05 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' + 'FF FF D0 A9 91 FF B7 51 10 FF BD 5C 1D FF C0 62' + '23 FF C3 67 28 FF C6 6C 2C FF C9 71 30 FF CB 75' + '34 FF CE 78 37 FF CF 7B 3A FF D0 7E 3D FF D1 7F' + '3E FF D2 81 40 FF D3 81 40 FF D2 81 40 FF D2 80' + '3F FF D1 7F 3E FF D0 7C 3C FF CE 79 39 FF CD 76' + '36 FF CA 73 32 FF C7 6E 2E FF C5 6A 2A FF C2 66' + '26 FF BF 60 21 FF BC 5B 1C FF B8 55 17 FF B2 4A' + '0A FF C2 6C 39 FF E7 E4 E3 FF CC CD CE FF D4 D4' + 'D4 FF AB AB AB FF 04 04 04 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 36 36 36 FF EF EF EF FF FF FF FF FF FF FF' + 'FF FF CE A7 8F FF B3 4C 0B FF B9 58 18 FF BC 5D' + '1E FF C0 62 23 FF C3 66 27 FF C5 6A 2B FF C7 6E' + '2E FF C9 71 31 FF CB 74 33 FF CC 76 36 FF CD 78' + '37 FF CE 79 39 FF CE 79 39 FF CE 79 39 FF CE 79' + '38 FF CD 77 37 FF CC 75 35 FF CA 72 32 FF C8 70' + '30 FF C6 6C 2D FF C3 68 29 FF C1 64 25 FF BE 60' + '21 FF BC 5B 1C FF B8 56 18 FF B5 50 12 FF AF 45' + '05 FF BF 68 35 FF E8 E5 E3 FF CD CF D0 FF D6 D6' + 'D6 FF AB AB AB FF 04 04 04 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 36 36 36 FF EE EE EE FF FF FF FF FF FF FF' + 'FF FF CC A4 8C FF B0 46 06 FF B6 51 13 FF B9 57' + '18 FF BC 5B 1D FF BF 60 21 FF C1 64 24 FF C3 67' + '28 FF C5 6A 2B FF C6 6D 2D FF C8 6F 2F FF C9 70' + '30 FF C9 72 32 FF C9 72 32 FF C9 72 32 FF C9 72' + '31 FF C8 70 30 FF C7 6E 2E FF C6 6B 2C FF C4 69' + '2A FF C2 66 26 FF BF 62 22 FF BD 5E 1F FF BA 5A' + '1B FF B8 55 17 FF B5 50 12 FF B2 4B 0D FF AC 40' + '00 FF BC 64 31 FF E9 E5 E4 FF D0 D1 D2 FF D8 D8' + 'D8 FF AA AA AA FF 04 04 04 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 35 35 35 FF ED ED ED FF FF FF FF FF FF FF' + 'FF FF CA A0 88 FF AD 40 00 FF B3 4C 0E FF B5 51' + '13 FF B8 56 17 FF BB 5A 1B FF BD 5D 1E FF BF 61' + '21 FF C0 63 24 FF C1 65 25 FF C2 67 28 FF C3 69' + '29 FF C5 69 2A FF C5 6A 2A FF C5 6A 2A FF C4 69' + '29 FF C4 68 28 FF C2 66 27 FF C0 64 24 FF BF 61' + '22 FF BE 5E 20 FF BC 5B 1D FF BA 58 19 FF B7 54' + '16 FF B5 50 12 FF B2 4B 0D FF AF 46 08 FF A8 3B' + '00 FF BB 62 30 FF EA E7 E5 FF D1 D3 D4 FF D9 D9' + 'D9 FF AA AA AA FF 03 03 03 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 34 34 34 FF EC EC EC FF FF FF FF FF FF FF' + 'FF FF C6 9D 85 FF A9 3A 00 FF AF 46 09 FF B2 4B' + '0E FF B4 4F 12 FF B6 53 15 FF B8 55 17 FF B9 58' + '19 FF BB 5C 1D FF BF 60 22 FF C2 66 27 FF C4 68' + '29 FF C5 6A 2A FF C5 6B 2B FF C5 6B 2B FF C5 6B' + '2B FF C5 69 2A FF C3 68 29 FF C1 65 26 FF BF 60' + '22 FF BB 59 1B FF B7 54 15 FF B4 4F 11 FF B3 4D' + '0F FF B1 4A 0C FF AE 45 08 FF AB 40 03 FF A6 38' + '00 FF BA 61 2F FF EA E7 E6 FF D3 D4 D5 FF DB DB' + 'DB FF A9 A9 A9 FF 03 03 03 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 33 33 33 FF EC EC EC FF FF FF FF FF FF FF' + 'FF FF C4 9A 83 FF A6 37 00 FF AC 40 03 FF AE 45' + '07 FF AF 47 0A FF B3 4D 0F FF B9 57 18 FF BE 5F' + '20 FF C4 68 29 FF C6 6D 2D FF C8 70 30 FF CA 72' + '31 FF CA 73 33 FF CB 74 33 FF CB 74 33 FF CB 73' + '33 FF CA 73 32 FF C9 71 31 FF C8 70 30 FF C7 6D' + '2D FF C4 69 2A FF BF 60 22 FF B8 56 18 FF B3 4D' + '0F FF AC 42 04 FF AA 3F 02 FF A9 3E 01 FF A6 38' + '00 FF BA 61 2F FF EB E8 E6 FF D5 D6 D7 FF DC DC' + 'DC FF A9 A9 A9 FF 03 03 03 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 32 32 32 FF EB EB EB FF FF FF FF FF FF FF' + 'FF FF C3 99 81 FF A6 37 00 FF A9 3D 00 FF A9 3D' + '00 FF B1 49 0C FF C0 63 24 FF C6 6D 2D FF C9 71' + '31 FF CA 74 33 FF CB 75 35 FF CD 78 37 FF CE 79' + '39 FF CF 7B 3A FF CF 7B 3B FF CF 7B 3B FF CF 7B' + '3A FF CE 7A 3A FF CD 79 38 FF CC 76 36 FF CB 74' + '34 FF C9 71 32 FF C7 6E 2F FF C6 6B 2B FF C2 66' + '27 FF B7 54 16 FF AA 40 03 FF A8 3C 00 FF A6 38' + '00 FF BA 61 2F FF EC E9 E7 FF D7 D9 D9 FF DF DF' + 'DF FF A8 A8 A8 FF 02 02 02 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 31 31 31 FF EA EA EA FF FF FF FF FF FF FF' + 'FF FF C2 98 80 FF A5 36 00 FF A8 3C 00 FF B7 55' + '17 FF C4 6A 2A FF C8 70 31 FF CA 73 33 FF CD 76' + '36 FF CE 79 39 FF D0 7C 3B FF D1 7F 3E FF D2 80' + '3F FF D3 82 41 FF D3 83 42 FF D3 83 42 FF D3 82' + '41 FF D3 81 40 FF D2 80 3F FF D0 7D 3C FF CF 7B' + '3A FF CD 78 37 FF CB 74 34 FF C9 71 30 FF C7 6E' + '2E FF C5 6A 2B FF BE 5F 20 FF B0 4A 0C FF A5 36' + '00 FF BA 61 2F FF EC E9 E8 FF D8 DA DA FF E0 E0' + 'E0 FF A7 A7 A7 FF 02 02 02 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 30 30 30 FF E9 E9 E9 FF FF FF FF FF FF FF' + 'FF FF C0 96 7E FF A6 37 00 FF B8 55 17 FF C7 6D' + '2E FF C9 71 31 FF CC 75 35 FF CD 79 39 FF D0 7D' + '3C FF D2 80 3F FF D3 83 42 FF D5 86 44 FF D7 87' + '46 FF D8 89 48 FF D8 8A 48 FF D8 8A 48 FF D8 89' + '48 FF D7 88 47 FF D6 87 45 FF D5 84 43 FF D3 82' + '41 FF D1 7E 3D FF CE 7A 3A FF CD 77 36 FF CA 73' + '33 FF C7 6E 2E FF C5 6B 2B FF C0 63 23 FF AD 41' + '02 FF BA 60 2E FF ED EA E9 FF DA DC DD FF E2 E2' + 'E2 FF A7 A7 A7 FF 02 02 02 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2F 2F 2F FF E8 E8 E8 FF FF FF FF FF FE FF' + 'FF FF BD 92 7B FF AF 45 05 FF C7 6D 2D FF C9 71' + '31 FF CC 76 35 FF CF 7A 3A FF D1 7E 3E FF D4 83' + '42 FF D6 86 46 FF D8 8A 48 FF DA 8D 4B FF DB 8F' + '4D FF DC 90 4E FF DC 91 50 FF DC 91 50 FF DC 91' + '4F FF DC 90 4E FF DA 8E 4C FF D9 8B 49 FF D7 88' + '47 FF D5 84 43 FF D2 80 3F FF D0 7C 3B FF CD 78' + '37 FF CB 73 32 FF C7 6E 2E FF C5 6A 2B FF BC 5B' + '1A FF BD 65 33 FF EE EA E9 FF DC DE DF FF E4 E4' + 'E4 FF A7 A7 A7 FF 01 01 01 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2E 2E 2E FF E7 E7 E7 FF FF FF FF FF FE FF' + 'FF FF BD 93 7B FF BA 57 17 FF C9 71 31 FF CB 74' + '34 FF CE 7A 3A FF D2 7F 3E FF D4 84 43 FF D7 88' + '47 FF DA 8C 4A FF DC 8F 4D FF DE 93 51 FF DF 96' + '54 FF E0 98 56 FF E1 99 56 FF E1 99 56 FF E1 99' + '56 FF E0 97 55 FF DE 94 53 FF DD 91 50 FF DB 8E' + '4C FF D8 8A 48 FF D5 85 44 FF D3 81 40 FF D0 7C' + '3C FF CD 77 37 FF C9 72 32 FF C6 6D 2D FF C2 62' + '21 FF C4 70 3D FF ED EA E8 FF DE DF E0 FF E5 E5' + 'E5 FF A6 A6 A6 FF 01 01 01 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2C 2C 2C FF E5 E5 E5 FF FF FF FF FF FD FF' + 'FF FF BE 96 7E FF C2 64 22 FF CB 74 33 FF CE 79' + '38 FF D1 7F 3E FF D5 84 43 FF D7 89 48 FF DA 8E' + '4C FF DE 92 50 FF E0 96 54 FF E2 9A 58 FF E3 9C' + '5A FF E5 9F 5C FF E6 A0 5D FF E6 A0 5D FF E5 A0' + '5D FF E4 9E 5B FF E3 9B 59 FF E1 98 56 FF DF 94' + '52 FF DC 90 4E FF D8 8B 49 FF D6 86 45 FF D3 81' + '40 FF D0 7C 3B FF CC 77 36 FF C9 70 30 FF C4 68' + '26 FF C8 76 43 FF EE EA E9 FF E1 E2 E3 FF E8 E8' + 'E8 FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2C 2C 2C FF E5 E5 E5 FF FF FF FF FF FD FF' + 'FF FF BC 94 7B FF C4 67 24 FF CD 77 37 FF D0 7C' + '3C FF D4 83 42 FF D7 88 47 FF DB 8D 4C FF DE 93' + '51 FF E1 97 56 FF E3 9C 59 FF E6 A0 5D FF E7 A3' + '60 FF E9 A6 63 FF EA A8 64 FF EA A8 64 FF E9 A7' + '64 FF E8 A5 62 FF E7 A2 5F FF E4 9E 5B FF E2 99' + '57 FF DF 95 53 FF DC 8F 4D FF D8 8A 49 FF D6 86' + '44 FF D2 80 3F FF CF 7A 3A FF CB 74 33 FF C6 6B' + '29 FF C7 76 43 FF F6 F2 F0 FF F4 F5 F6 FF F6 F6' + 'F6 FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2B 2B 2B FF E4 E4 E4 FF FF FF FF FF FD FF' + 'FF FF B7 8D 75 FF BC 5A 19 FF CF 7C 3B FF D2 80' + '3E FF D5 85 44 FF D9 8C 4A FF DD 91 4F FF E0 97' + '55 FF E3 9C 5A FF E6 A1 5E FF E9 A5 63 FF EB A9' + '66 FF ED AD 69 FF EF AF 6B FF EF AF 6C FF EE AF' + '6A FF ED AB 68 FF EA A7 65 FF E7 A3 61 FF E4 9E' + '5C FF E1 99 57 FF DE 93 52 FF DA 8E 4C FF D7 88' + '47 FF D4 82 41 FF D0 7C 3C FF CC 77 36 FF C7 6C' + '2A FF C3 6F 3D FF F7 F3 F2 FF F7 F9 FA FF FC FC' + 'FC FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2A 2A 2A FF E3 E3 E3 FF FF FF FF FF FD FF' + 'FF FF B4 88 70 FF AF 41 01 FF D0 78 34 FF D4 81' + '3E FF D8 87 43 FF DC 8D 49 FF E0 93 4F FF E3 9A' + '55 FF E7 A0 5B FF EB A5 60 FF EE AA 65 FF F1 AF' + '6A FF F3 B3 6E FF F5 B6 70 FF F5 B6 70 FF F4 B5' + '6F FF F2 B2 6C FF F0 AD 67 FF EC A7 62 FF E9 A2' + '5D FF E5 9C 58 FF E1 96 52 FF DE 90 4C FF DA 8A' + '46 FF D6 83 40 FF D2 7D 3A FF CF 78 35 FF C1 5F' + '1B FF BB 5F 2C FF F9 F5 F3 FF F9 FB FB FF FE FE' + 'FE FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 2A 2A 2A FF E3 E3 E3 FF FF FF FF FF FD FF' + 'FF FF B4 95 84 FF A0 4F 23 FF B6 71 43 FF CB 89' + '53 FF CE 8D 57 FF D1 92 5B FF D4 97 61 FF D7 9D' + '66 FF DA A2 6A FF DD A7 6E FF E0 AB 73 FF E4 B0' + '78 FF E6 B4 7B FF E7 B7 7F FF E8 B7 7F FF E6 B6' + '7D FF E5 B2 7A FF E2 AE 76 FF DE A9 71 FF DC A4' + '6C FF D9 9F 68 FF D5 99 63 FF D2 94 5D FF CF 8F' + '59 FF CC 8A 54 FF CA 85 4F FF C3 7E 4A FF A7 5A' + '2C FF B3 73 4F FF FA F8 F7 FF FC FD FD FF FF FF' + 'FF FF A5 A5 A5 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 84 00 00' + '00 FF 26 26 26 FF E1 E1 E1 FF FF FF FF FF FF FF' + 'FF FF EC EC ED FF E6 E6 E7 FF E6 E5 E6 FF E9 E7' + 'E5 FF E9 E7 E5 FF E9 E7 E5 FF E9 E7 E5 FF E9 E7' + 'E5 FF E9 E8 E6 FF E9 E8 E6 FF EA E8 E6 FF EA E8' + 'E6 FF EA E8 E6 FF EA E8 E6 FF EA E8 E6 FF EA E8' + 'E6 FF EA E8 E6 FF EA E8 E6 FF E9 E8 E6 FF E8 E7' + 'E5 FF E8 E6 E4 FF E8 E6 E4 FF E8 E6 E4 FF E8 E6' + 'E4 FF E7 E5 E3 FF E7 E5 E3 FF E6 E4 E3 FF E3 E3' + 'E3 FF E9 E9 E9 FF FC FC FC FF FD FD FD FF FF FF' + 'FF FF A4 A4 A4 FF 00 00 00 FF 00 00 00 F7 00 00' + '00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 7D 00 00' + '00 FF 0D 0D 0D FF C4 C4 C4 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FE FE FE FF FF FF FF FF FB FB' + 'FB FF 7F 7F 7F FF 00 00 00 FF 00 00 00 F2 00 00' + '00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 37 00 00' + '00 FB 00 00 00 FF 56 56 56 FF E3 E3 E3 FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FD FD FD FF AF AF' + 'AF FF 21 21 21 FF 00 00 00 FF 00 00 00 B9 00 00' + '00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 8D 00 00 00 FF 01 01 01 FF 2F 2F 2F FF 6D 6D' + '6D FF 7D 7D 7D FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' + '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' + '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' + '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' + '7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C 7C FF 7C 7C' + '7C FF 7C 7C 7C FF 7C 7C 7C FF 7B 7B 7B FF 7B 7B' + '7B FF 7B 7B 7B FF 7A 7A 7A FF 7A 7A 7A FF 7A 7A' + '7A FF 7A 7A 7A FF 77 77 77 FF 57 57 57 FF 18 18' + '18 FF 00 00 00 FF 00 00 00 FF 00 00 00 57 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 19 00 00 00 B9 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 F5 00 00 00 86 00 00 00 04 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 63 00 00 00 D0 00 00' + '00 F3 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F1 00 00 00 EF 00 00' + '00 B2 00 00 00 3D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF F8' + '00 00 1F FF 00 00 FF F0 00 00 0F FF 00 00 FF E0' + '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 03 FF 00 00 FF C0 00 00 03 FF 00 00 FF C0' + '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 07 FF 00 00 FF E0 00 00 07 FF 00 00 FF E0' + '00 00 0F FF 00 00 FF F0 00 00 0F FF 00 00 FF F8' + '00 00 1F FF 00 00 FF F8 00 00 1F FF 00 00 FF FC' + '00 00 7F FF 00 00 FE 00 00 00 00 7F 00 00 F8 00' + '00 00 00 1F 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 E0 00 00 00 00 07 00 00 E0 00' + '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 F0 00' + '00 00 00 0F 00 00 FC 00 00 00 00 3F 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 20 00 00 00' + '00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 0B 00 00 00 4B 00 00' + '00 63 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 63 00 00' + '00 3D 00 00 00 05 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 04 00 00 00 AF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 01 01 01 FF 01 01' + '01 FF 01 01 01 FF 02 02 02 FF 02 02 02 FF 02 02' + '02 FF 03 03 03 FF 05 05 05 FF 03 03 03 FF 00 00' + '00 FA 00 00 00 80 00 00 00 03 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 3E 00 00 00 FD 6E 6E 6E FF B7 B7' + 'B7 FF AD AD AD FF A9 A9 A9 FF A5 A5 A5 FF A2 A2' + 'A2 FF 9F 9F 9F FF 9B 9B 9B FF 97 97 97 FF 94 94' + '94 FF 8C 8C 8C FF 83 83 83 FF 85 85 85 FF 38 38' + '38 FF 00 00 00 EA 00 00 00 27 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 67 0F 0F 0F FF D8 D8 D8 FF FF FF' + 'FF FF ED ED ED FF E2 E2 E2 FF DB DB DB FF D3 D3' + 'D3 FF CD CD CD FF C8 C8 C8 FF C2 C2 C2 FF BC BC' + 'BC FF B4 B4 B4 FF 9F 9F 9F FF A2 A2 A2 FF 7F 7F' + '7F FF 00 00 00 FD 00 00 00 47 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 72 1B 1B 1B FF E6 E6 E6 FF FF FF' + 'FF FF F6 F6 F6 FF F5 F5 F5 FF F1 F1 F1 FF EC EC' + 'EC FF E4 E4 E4 FF DC DC DC FF D4 D4 D4 FF CC CC' + 'CC FF C5 C5 C5 FF AB AB AB FF AD AD AD FF 90 90' + '90 FF 04 04 04 FF 00 00 00 50 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 56 0D 0D 0D FF D4 D4 D4 FF FF FF' + 'FF FF F7 F7 F7 FF F8 F8 F8 FF F3 F3 F3 FF F0 F0' + 'F0 FF EC EC EC FF E3 E3 E3 FF DA DA DA FF D2 D2' + 'D2 FF CA CA CA FF B0 B0 B0 FF B8 B8 B8 FF 82 82' + '82 FF 00 00 00 F8 00 00 00 32 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 1F 00 00 00 ED 94 94 94 FF FF FF' + 'FF FF FE FE FE FF FD FD FD FF FA FA FA FF F3 F3' + 'F3 FF E5 E5 E5 FF E1 E1 E1 FF E0 E0 E0 FF DA DA' + 'DA FF D1 D1 D1 FF BF BF BF FF C5 C5 C5 FF 52 52' + '52 FF 00 00 00 CD 00 00 00 0D 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 97 29 29 29 FF E4 E4' + 'E4 FF FF FF FF FF FF FF FF FF FF FF FF FF F0 F0' + 'F0 FF AB AB AB FF B4 B4 B4 FF E8 E8 E8 FF E4 E4' + 'E4 FF D5 D5 D5 FF D3 D3 D3 FF 9D 9D 9D FF 0C 0C' + '0C FF 00 00 00 6C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 1C 00 00 00 D8 4C 4C' + '4C FF EC EC EC FF FF FF FF FF FF FF FF FF FA FA' + 'FA FF E2 E2 E2 FF E3 E3 E3 FF F0 F0 F0 FF EA EA' + 'EA FF E6 E6 E6 FF B1 B1 B1 FF 23 23 23 FF 00 00' + '00 B7 00 00 00 08 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 2B 00 00' + '00 D5 33 33 33 FF B4 B4 B4 FF F9 F9 F9 FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FB FB FB FF DC DC' + 'DC FF 89 89 89 FF 1A 1A 1A FF 00 00 00 B6 00 00' + '00 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 09 00 00 00 28 00 00' + '00 38 00 00 00 37 00 00 00 37 00 00 00 2C 00 00' + '00 50 00 00 00 CC 03 03 03 FF 31 31 31 FF 67 67' + '67 FF A2 A2 A2 FF 90 90 90 FF 59 59 59 FF 22 22' + '22 FF 00 00 00 FF 00 00 00 B4 00 00 00 41 00 00' + '00 2F 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 27 00 00 00 09 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 32 00 00 00 BE 00 00 00 F7 00 00' + '00 FB 00 00 00 FA 00 00 00 FA 00 00 00 FA 00 00' + '00 F3 00 00 00 F2 00 00 00 FF 00 00 00 FF 05 05' + '05 FF 79 79 79 FF 4C 4C 4C FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FD 00 00 00 F0 00 00 00 F6 00 00' + '00 FA 00 00 00 FA 00 00 00 FA 00 00 00 FB 00 00' + '00 F1 00 00 00 AE 00 00 00 29 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 1B 00 00 00 DB 26 26 26 FF 94 94 94 FF AD AD' + 'AD FF AA AA AA FF A9 A9 A9 FF A7 A7 A7 FF A7 A7' + 'A7 FF A6 A6 A6 FF A4 A4 A4 FF A2 A2 A2 FF AB AB' + 'AB FF CD CD CD FF BF BF BF FF A2 A2 A2 FF 9E 9E' + '9E FF 9E 9E 9E FF 9C 9C 9C FF 9C 9C 9C FF 9B 9B' + '9B FF 9A 9A 9A FF 99 99 99 FF 9B 9B 9B FF 77 77' + '77 FF 11 11 11 FF 00 00 00 C1 00 00 00 14 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 6F 06 06 06 FF C0 C0 C0 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FD FF FF FF FA FD FE FF F7 FA' + 'FC FF F4 F7 F9 FF F1 F4 F6 FF EE F1 F3 FF EA EC' + 'EE FF E2 E4 E6 FF E1 E3 E5 FF E2 E5 E7 FF E1 E2' + 'E5 FF DE E0 E2 FF DA DD DF FF D8 DA DD FF D5 D8' + 'DA FF D3 D6 D8 FF D0 D3 D5 FF CE CF CF FF DD DD' + 'DD FF 81 81 81 FF 00 00 00 FF 00 00 00 4E 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 22 22 22 FF EB EB EB FF FF FF FF FF F3 EA' + 'E4 FF F0 E0 D4 FF EF E1 D6 FF EF E1 D6 FF EF E1' + 'D6 FF EE E1 D6 FF ED E1 D6 FF EC E1 D5 FF EC E0' + 'D5 FF EA DE D3 FF E9 DD D2 FF E7 DA CF FF E5 D8' + 'CD FF E2 D5 CA FF DF D2 C7 FF DD CF C4 FF DB CC' + 'C1 FF D8 C9 BE FF D8 C8 BD FF D2 CE CC FF CB CC' + 'CC FF AB AB AB FF 06 06 06 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 24 24 24 FF EB EB EB FF FF FF FF FF D4 AB' + '8F FF C5 67 26 FF CD 77 39 FF D2 81 42 FF D7 89' + '4A FF DC 91 50 FF E0 97 57 FF E3 9C 5C FF E5 9F' + '5E FF E5 9F 5F FF E4 9E 5D FF E2 9A 5A FF DF 94' + '55 FF DA 8D 4E FF D6 85 47 FF D1 7D 3F FF CC 75' + '37 FF C6 6A 2C FF C5 68 2B FF D8 C3 B5 FF CE D1' + 'D3 FF A9 A9 A9 FF 06 06 06 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 22 22 22 FF EA EA EA FF FF FF FF FF D0 A5' + '89 FF BD 5A 16 FF C6 6A 2A FF CB 73 32 FF D0 7A' + '3A FF D4 82 40 FF D7 87 45 FF DA 8C 49 FF DB 8E' + '4B FF DB 8E 4C FF DA 8D 4A FF D8 89 47 FF D5 84' + '42 FF D2 7E 3C FF CD 76 35 FF C8 6E 2E FF C3 66' + '26 FF BD 5B 1A FF BB 59 1A FF D7 C0 B2 FF D1 D5' + 'D8 FF A9 A9 A9 FF 05 05 05 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 22 22 22 FF EA EA EA FF FF FF FF FF D0 A4' + '88 FF BA 54 12 FF C2 65 25 FF C7 6D 2D FF CB 73' + '34 FF CF 7A 39 FF D2 7F 3E FF D3 82 42 FF D4 84' + '43 FF D5 84 43 FF D4 83 42 FF D2 80 3F FF D0 7C' + '3B FF CD 76 36 FF C8 6F 30 FF C4 68 29 FF BF 60' + '21 FF B9 56 17 FF B8 54 17 FF D8 C1 B3 FF D4 D8' + 'DA FF A9 A9 A9 FF 05 05 05 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 21 21 21 FF E9 E9 E9 FF FF FF FF FF CD A0' + '84 FF B5 4C 0B FF BD 5D 1E FF C1 64 25 FF C5 6B' + '2A FF C9 70 30 FF CB 74 34 FF CD 77 37 FF CD 78' + '38 FF CD 78 38 FF CD 78 37 FF CC 75 35 FF CA 72' + '32 FF C7 6D 2D FF C3 67 27 FF BF 60 21 FF BB 58' + '1A FF B5 4F 10 FF B4 4D 11 FF D8 C0 B2 FF D8 DB' + 'DE FF A9 A9 A9 FF 04 04 04 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 20 20 20 FF E8 E8 E8 FF FF FF FF FF CA 9B' + '80 FF B0 44 02 FF B8 54 15 FF BC 5A 1C FF BF 60' + '21 FF C1 65 25 FF C4 68 28 FF C5 6B 2B FF C6 6C' + '2D FF C6 6D 2D FF C6 6C 2D FF C4 69 2A FF C2 66' + '26 FF C0 61 22 FF BD 5D 1E FF B9 57 19 FF B5 50' + '12 FF B0 47 08 FF B0 46 0A FF D8 C0 B2 FF DA DE' + 'E0 FF A8 A8 A8 FF 04 04 04 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 20 20 20 FF E7 E7 E7 FF FF FF FF FF C6 96' + '7B FF AA 3B 00 FF B2 4A 0D FF B4 4F 11 FF B8 55' + '17 FF BD 5E 1F FF C2 65 25 FF C4 69 2A FF C5 6B' + '2C FF C6 6C 2C FF C6 6C 2C FF C4 69 2A FF C2 65' + '26 FF BE 5E 20 FF B8 55 17 FF B3 4C 0E FF AF 46' + '08 FF AB 3F 01 FF AD 43 06 FF DA C2 B4 FF DE E2' + 'E4 FF A7 A7 A7 FF 03 03 03 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1F 1F 1F FF E6 E6 E6 FF FF FF FF FF C2 93' + '78 FF A5 34 00 FF AB 40 03 FF B6 52 14 FF C1 64' + '26 FF C7 6E 2F FF CA 73 33 FF CC 77 36 FF CD 78' + '38 FF CD 79 38 FF CD 78 38 FF CC 77 37 FF CB 74' + '34 FF C8 6F 30 FF C4 69 2A FF BC 5C 1D FF AF 47' + '0A FF A7 3A 00 FF AC 43 06 FF DB C3 B5 FF E0 E4' + 'E7 FF A7 A7 A7 FF 03 03 03 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1E 1E 1E FF E5 E5 E5 FF FF FF FF FF C1 90' + '76 FF A6 36 00 FF BA 59 1A FF C8 6F 2F FF CC 75' + '35 FF CF 7A 3A FF D1 7F 3E FF D3 82 41 FF D4 83' + '42 FF D4 84 43 FF D4 83 42 FF D3 82 41 FF D1 7E' + '3E FF CF 7A 39 FF CC 75 35 FF C9 70 30 FF C3 67' + '27 FF B3 4D 0E FF AC 42 06 FF DC C4 B6 FF E3 E7' + 'EA FF A7 A7 A7 FF 02 02 02 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1D 1D 1D FF E4 E4 E4 FF FF FF FF FF BE 8E' + '73 FF B7 50 0E FF CA 72 32 FF CD 77 37 FF D1 7D' + '3D FF D4 83 43 FF D8 88 47 FF D9 8C 4B FF DB 8F' + '4D FF DB 8F 4D FF DB 8F 4D FF D9 8C 4B FF D8 88' + '47 FF D4 83 43 FF D1 7D 3D FF CD 76 36 FF C9 70' + '30 FF C4 67 27 FF B5 51 14 FF DC C3 B6 FF E6 EA' + 'EC FF A6 A6 A6 FF 01 01 01 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1C 1C 1C FF E2 E2 E2 FF FF FF FF FF C3 96' + '7A FF C4 65 22 FF CD 76 36 FF D2 7E 3E FF D6 85' + '44 FF DA 8C 4B FF DD 92 50 FF E0 97 54 FF E1 99' + '57 FF E2 99 58 FF E1 99 57 FF E0 97 54 FF DD 92' + '50 FF DA 8C 4B FF D6 85 44 FF D2 7E 3E FF CC 76' + '36 FF C7 6D 2D FF C2 65 27 FF DE C6 B9 FF E8 EB' + 'EE FF A6 A6 A6 FF 01 01 01 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1B 1B 1B FF E1 E1 E1 FF FF FF FF FF C5 9A' + '7E FF C8 6C 28 FF D1 7D 3C FF D6 85 44 FF DA 8D' + '4B FF DF 94 52 FF E3 9B 59 FF E6 A1 5E FF E8 A4' + '62 FF E9 A5 62 FF E8 A4 62 FF E6 A1 5E FF E3 9B' + '59 FF DF 94 52 FF DA 8D 4B FF D6 85 44 FF D0 7D' + '3C FF CA 72 31 FF C7 6D 2E FF E5 CE C1 FF F4 F8' + 'FA FF A7 A7 A7 FF 00 00 00 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1A 1A 1A FF E0 E0 E0 FF FF FF FF FF BC 8D' + '70 FF C7 68 23 FF D4 81 3E FF D9 89 46 FF DE 92' + '4E FF E4 9A 56 FF E9 A2 5E FF ED AA 65 FF F0 AE' + '6A FF F1 B0 6B FF F0 AE 6A FF ED AA 65 FF E9 A2' + '5E FF E4 9A 56 FF DE 92 4E FF D9 89 46 FF D4 80' + '3D FF CE 76 33 FF C2 63 23 FF E9 D0 C2 FF FF FF' + 'FF FF AA AA AA FF 00 00 00 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 1A 1A 1A FF E0 E0 E0 FF FF FF FF FF B5 8D' + '76 FF B4 60 29 FF CF 88 4F FF D4 90 56 FF D9 98' + '5D FF DE A0 65 FF E3 A8 6D FF E7 AF 74 FF EB B5' + '79 FF EC B7 7B FF EB B5 79 FF E7 AF 74 FF E3 A8' + '6D FF DE A0 65 FF D8 98 5D FF D3 90 56 FF CF 87' + '4E FF C7 7C 44 FF B0 5D 2B FF E8 D3 C8 FF FF FF' + 'FF FF AB AB AB FF 00 00 00 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 84 15 15 15 FF DB DB DB FF FF FF FF FF EE EC' + 'EC FF E7 E4 E2 FF EB E7 E4 FF EB E8 E5 FF EC E8' + 'E5 FF EC E9 E6 FF EC E9 E6 FF EC EA E7 FF ED EA' + 'E7 FF ED EA E7 FF ED EA E7 FF EC EA E7 FF EC E9' + 'E6 FF EB E8 E5 FF EA E8 E5 FF EA E7 E4 FF EA E6' + 'E3 FF E8 E4 E2 FF E6 E3 E2 FF F8 F8 F7 FF FF FF' + 'FF FF A7 A7 A7 FF 00 00 00 FF 00 00 00 61 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 6C 00 00 00 FF 8E 8E 8E FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF F4 F4' + 'F4 FF 58 58 58 FF 00 00 00 FD 00 00 00 45 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 16 00 00 00 D5 0A 0A 0A FF 53 53 53 FF 74 74' + '74 FF 72 72 72 FF 72 72 72 FF 72 72 72 FF 72 72' + '72 FF 72 72 72 FF 72 72 72 FF 71 71 71 FF 71 71' + '71 FF 71 71 71 FF 71 71 71 FF 71 71 71 FF 71 71' + '71 FF 71 71 71 FF 71 71 71 FF 71 71 71 FF 70 70' + '70 FF 70 70 70 FF 70 70 70 FF 6F 6F 6F FF 3F 3F' + '3F FF 02 02 02 FF 00 00 00 B2 00 00 00 05 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 28 00 00 00 B1 00 00 00 EF 00 00' + '00 F1 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F0 00 00' + '00 F0 00 00 00 F0 00 00 00 F0 00 00 00 F2 00 00' + '00 E8 00 00 00 97 00 00 00 15 00 00 00 00 00 00' + '00 00 00 00 00 00 FF 00 00 FF FE 00 00 7F FE 00' + '00 7F FE 00 00 7F FE 00 00 7F FE 00 00 7F FE 00' + '00 7F FF 00 00 FF FF 00 00 FF FF 80 01 FF F0 00' + '00 0F E0 00 00 07 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 C0 00 00 03 C0 00 00 03 C0 00 00 03 C0 00' + '00 03 E0 00 00 07 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 20 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 03 01 01' + '01 7C 08 08 08 AD 08 08 08 A8 08 08 08 A8 08 08' + '08 A8 08 08 08 A8 08 08 08 AD 01 01 01 6D 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 31 57 57' + '57 FA CE CE CE FF BB BB BB FF B1 B1 B1 FF A8 A8' + 'A8 FF 9D 9D 9D FF 8D 8D 8D FF 30 30 30 F2 00 00' + '00 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 3A 7B 7B' + '7B FC FF FF FF FF F5 F5 F5 FF EC EC EC FF DD DD' + 'DD FF CA CA CA FF BA BA BA FF 4C 4C 4C F7 00 00' + '00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 0D 37 37' + '37 D7 F5 F5 F5 FF FF FF FF FF E2 E2 E2 FF D9 D9' + 'D9 FF E6 E6 E6 FF B7 B7 B7 FF 1C 1C 1C C5 00 00' + '00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 45 59 59 59 EB E5 E5 E5 FF F1 F1 F1 FF EA EA' + 'EA FF C2 C2 C2 FF 3B 3B 3B E1 00 00 00 35 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 12 02 02 02 78 06 06 06 96 05 06' + '06 8A 00 00 00 C6 16 16 16 FF 77 77 77 FF 66 66' + '66 FF 11 11 11 FF 00 00 00 BC 07 07 07 89 07 07' + '07 96 02 02 02 73 00 00 00 0E 00 00 00 00 00 00' + '00 00 03 03 03 9C 94 94 93 FF D1 D4 D7 FF C7 CD' + 'D0 FF C3 C7 CA FF B9 BD C0 FF C2 C6 C9 FF BB BF' + 'C2 FF B0 B4 B8 FF B2 B7 BA FF B0 B5 B9 FF B1 B4' + 'B6 FF 6E 6D 6D FF 00 00 00 84 00 00 00 00 00 00' + '00 00 19 19 1A CC EC ED ED FF ED C9 B1 FF E6 B4' + '8F FF EB BF 9B FF ED C4 A0 FF EB C3 9E FF E8 C0' + '9B FF E5 BA 95 FF DD AF 8B FF D4 9E 79 FF D9 B9' + 'A5 FF B9 BB BD FF 09 0A 0A A8 00 00 00 00 00 00' + '00 00 1A 1B 1B CC EB EC ED FF CC 86 58 FF C2 5E' + '17 FF CE 75 30 FF D5 80 3B FF D8 85 40 FF D6 82' + '3D FF D1 78 34 FF C8 6A 26 FF BA 4F 08 FF CC 8E' + '68 FF B8 BC C0 FF 09 09 09 A8 00 00 00 00 00 00' + '00 00 19 1A 1A CC EA EB EC FF C7 81 57 FF B9 53' + '12 FF C2 66 26 FF C7 6E 2E FF CA 71 32 FF C8 6F' + '30 FF C4 68 29 FF BD 5C 1E FF B1 45 04 FF C9 8C' + '68 FF BA BE C1 FF 08 09 09 A8 00 00 00 00 00 00' + '00 00 18 19 1A CC E9 EA EB FF BE 73 4A FF AF 44' + '03 FF C0 62 23 FF C6 6D 2D FF C9 71 31 FF C8 70' + '30 FF C4 69 2A FF BB 5A 1B FF A9 39 00 FF C7 88' + '65 FF BC C1 C4 FF 08 08 08 A8 00 00 00 00 00 00' + '00 00 18 18 19 CC E6 E7 E8 FF C1 7A 4F FF C2 62' + '1F FF D0 7C 3C FF D5 85 44 FF D7 88 47 FF D7 87' + '46 FF D3 81 40 FF CC 76 36 FF BB 57 13 FF CC 8F' + '6C FF BD C1 C4 FF 07 08 08 A8 00 00 00 00 00 00' + '00 00 16 17 18 CC E3 E4 E4 FF CD 8D 60 FF D0 78' + '33 FF DA 8C 49 FF E2 98 54 FF E6 9F 5B FF E4 9C' + '59 FF DE 92 4F FF D6 84 42 FF C9 6B 26 FF DA A2' + '7C FF C1 C5 C8 FF 07 07 07 A8 00 00 00 00 00 00' + '00 00 17 17 18 CC E4 E4 E5 FF CA 90 6A FF D5 89' + '4B FF E1 9F 63 FF EB AE 71 FF F0 B9 7A FF EE B5' + '77 FF E6 A7 6A FF DC 97 5B FF CC 7B 3D FF DF AD' + '8D FF D0 D4 D7 FF 06 07 07 A8 00 00 00 00 00 00' + '00 00 09 09 09 C1 CB CC CC FF FA F6 F4 FF F2 EE' + 'EA FF F4 F0 EC FF F4 F1 EE FF F4 F2 EE FF F4 F2' + 'EE FF F4 F0 ED FF F2 EF EA FF F0 EB E8 FF FD FA' + 'F8 FF AF AF AF FF 00 00 00 9F 00 00 00 00 00 00' + '00 00 00 00 00 4A 1E 1E 1D E2 45 46 47 F3 43 45' + '46 F0 42 43 45 F0 42 43 44 F0 42 43 44 F0 42 43' + '44 F0 42 43 44 F0 42 43 44 F0 42 44 45 F0 41 42' + '43 F4 16 16 16 D9 00 00 00 39 00 00 00 00 E0 0F' + '00 00 E0 07 00 00 E0 07 00 00 E0 07 00 00 F0 0F' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01' + '00 00 80 01 00 00 80 01 00 00 80 01 00 00' +} */ + + + + +/* BINRES desktop.ico */ +34 ICON desktop.ico +/* { + '00 00 01 00 09 00 20 20 00 00 01 00 08 00 A8 08' + '00 00 96 00 00 00 10 10 00 00 01 00 08 00 68 05' + '00 00 3E 09 00 00 20 20 00 00 01 00 20 00 A8 10' + '00 00 A6 0E 00 00 10 10 00 00 01 00 20 00 68 04' + '00 00 4E 1F 00 00 10 10 00 00 01 00 04 00 28 01' + '00 00 B6 23 00 00 20 20 00 00 01 00 04 00 E8 02' + '00 00 DE 24 00 00 30 30 00 00 01 00 08 00 A8 0E' + '00 00 C6 27 00 00 30 30 00 00 01 00 20 00 A8 25' + '00 00 6E 36 00 00 30 30 00 00 01 00 04 00 68 06' + '00 00 16 5C 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 08 00 00 00 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 11 11 00 33 33 33 00 66 33 00 00 44 44' + '44 00 55 55 55 00 66 66 66 00 77 77 77 00 7F 7F' + '7F 00 99 00 00 00 99 33 00 00 99 33 33 00 CC 33' + '00 00 CC 33 33 00 99 66 00 00 99 66 33 00 CC 66' + '00 00 CC 66 33 00 99 66 66 00 CC 66 66 00 FF 66' + '66 00 99 99 33 00 CC 99 33 00 FF 99 33 00 99 99' + '66 00 CC 99 66 00 FF 99 66 00 CC CC 66 00 FF CC' + '66 00 88 88 88 00 99 99 99 00 AA AA AA 00 BB BB' + 'BB 00 CC 99 99 00 FF 99 99 00 CC CC 99 00 FF CC' + '99 00 99 99 CC 00 CC CC CC 00 DD DD DD 00 FF CC' + 'CC 00 CC FF CC 00 CC CC FF 00 CC FF FF 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 58 00 5A 00 00 EC FD 7F 1A 02' + '00 00 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 FF FF' + 'FF FF E2 D8 F5 77 7D 9B F5 77 94 B6 01 00 00 00' + '05 00 F4 17 95 00 80 00 10 C0 B4 1A 95 00 F0 88' + 'FA 77 88 1C F5 77 FF FF FF FF 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 9B B2 E7 77 B7 00 00 00 02 00' + '00 00 A4 1A 95 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 00' + '00 00 02 00 00 00 01 01 F5 77 00 EC FD 7F 58 00' + '00 00 00 00 00 00 03 00 00 00 60 00 1A 02 40 9F' + '07 00 00 00 00 00 40 9F 07 00 05 00 00 00 BE B3' + 'E7 77 4C 19 95 00 A3 B4 E7 77 F8 00 00 00 00 00' + '00 C0 00 00 00 00 00 00 00 00 02 00 00 00 80 00' + '00 00 00 00 00 00 8C 1A 95 00 7F E9 4B 00 00 63' + '38 00 00 00 00 C0 00 00 00 00 80 1A 95 00 02 00' + '00 00 80 00 00 00 00 00 00 00 C0 27 95 00 C4 F5' + 'AF 00 02 00 00 00 44 3A 5C 6F 73 65 78 70 65 72' + '74 73 5C 72 65 61 63 74 6F 73 5C 6C 69 62 5C 73' + '68 65 6C 6C 33 32 5C 64 65 73 6B 74 6F 70 2E 69' + '63 6F 00 93 4B 00 14 1A 95 00 1F 3B D4 77 15 00' + '00 00 A8 00 00 00 4F 3B D4 77 E0 19 95 00 33 3B' + 'D4 77 64 C5 F5 77 A9 F1 E7 77 F8 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 1A 95 00 B0 6C' + '38 00 96 00 00 00 00 00 00 00 C9 F1 E7 77 96 00' + '00 00 A4 1A 95 00 09 00 00 00 00 00 00 00 96 00' + '00 00 96 00 00 00 09 00 00 00 F4 19 95 00 33 3B' + 'D4 77 B4 1A 95 00 09 48 E9 77 B8 10 E9 77 FF FF' + 'FF FF C9 F1 E7 77 16 EA 4B 00 F8 00 00 00 B0 6C' + '38 00 96 00 00 00 58 1A 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 2E' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 2E 2E' + '04 1F 20 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1E' + '21 1F 1F 1E 1E 1F 1E 1F 1E 1F 06 2E 2E 2E 2E 02' + '2C 2D 2D 2D 2D 2D 2D 2C 2C 2D 2C 2C 2C 2C 28 2C' + '29 27 27 27 27 27 26 26 26 26 27 06 2E 2E 2E 07' + '2D 2D 2D 2D 2D 2D 2C 2D 2C 2A 2D 2C 27 2B 2C 27' + '2A 27 27 29 27 27 2A 27 27 26 26 1E 2E 2E 2E 07' + '2D 2D 28 19 21 1B 22 21 24 24 24 23 24 22 23 24' + '24 22 23 22 21 21 1A 19 23 26 26 1F 2E 2E 2E 1D' + '2D 2D 19 11 10 11 16 16 11 16 13 17 19 16 17 13' + '16 16 11 16 11 10 0B 10 19 26 27 1E 2E 2E 2E 07' + '2D 2D 21 0E 11 11 11 11 11 19 17 19 16 1A 13 16' + '19 11 16 11 10 11 11 0E 13 27 26 1F 2E 2E 2E 07' + '2D 2D 21 10 11 11 0F 11 16 11 11 16 11 16 16 11' + '16 11 11 11 11 0F 10 0C 19 27 26 1E 2E 2E 2E 07' + '2D 2D 19 10 0B 10 11 16 11 11 16 11 16 11 11 16' + '11 11 11 10 0F 10 11 0A 19 26 27 1F 2E 2E 2E 07' + '2D 2D 21 0A 10 0F 10 0D 11 11 0F 11 11 16 11 11' + '11 11 11 11 0C 0A 0C 0E 13 2C 27 1E 2E 2E 2E 07' + '2D 2D 18 0C 0E 0D 11 10 0F 10 11 11 11 11 11 11' + '11 0E 11 0A 12 18 0F 09 16 2A 27 1E 2E 2E 2E 07' + '2D 2D 21 0A 0C 0E 0A 11 11 11 11 16 11 11 11 11' + '11 11 10 0F 2B 2D 1E 0A 13 29 27 1E 2E 2E 2E 07' + '2D 2D 19 0A 0A 0A 11 11 16 11 11 11 16 11 11 16' + '11 16 11 12 27 26 2A 03 16 2C 27 1F 2E 2E 2E 07' + '2D 2D 19 0A 10 11 11 11 11 19 16 11 11 19 11 11' + '17 11 11 0F 20 2C 1E 0A 13 27 27 1E 2E 2E 2E 06' + '2D 2D 21 0A 11 11 16 11 16 16 14 16 19 17 19 16' + '19 11 16 11 11 0F 11 0A 16 2C 2C 1E 2E 2E 2E 07' + '2D 2D 18 10 11 16 11 17 13 16 16 1A 16 19 17 19' + '16 1A 11 15 12 15 0F 11 13 27 2C 1E 2E 2E 2E 06' + '2D 2D 19 11 11 11 16 13 16 19 1A 19 19 1A 19 1A' + '14 16 16 21 20 1F 25 0E 19 2C 2C 1E 2E 2E 2E 07' + '2D 2D 13 11 11 16 19 17 19 17 19 1A 1A 1B 1A 19' + '1B 1A 16 12 2C 27 1F 11 19 2C 2D 1E 2E 2E 2E 06' + '2D 2D 18 11 16 1A 11 19 1A 19 1C 1A 1B 1A 1B 1A' + '1A 19 17 19 20 2C 21 0E 13 2D 2D 1E 2E 2E 2E 06' + '2D 2D 12 10 11 16 19 17 19 1A 19 1C 1A 1C 1A 1B' + '1A 19 19 16 12 0F 15 0D 19 2D 2D 1E 2E 2E 2E 06' + '2D 2D 2C 26 27 27 27 27 27 27 27 27 27 27 27 27' + '27 27 27 28 27 27 28 26 2C 2D 2D 1E 2E 2E 2E 02' + '2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D' + '2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 06 2E 2E 2E 2E' + '05 26 26 27 26 27 27 26 27 26 27 27 26 27 26 27' + '27 26 27 26 27 26 27 26 26 26 1D 2E 2E 2E 2E 2E' + '2E 2E 01 01 01 2E 01 01 01 01 2E 01 01 01 01 2E' + '01 01 01 01 2E 01 01 01 01 2E 2E 2E 2E 00 00 00' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E' + '2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF FF FF FF FF FF FF C0 00 00 03 80 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00' + '00 03 FF FF FF FF FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 08 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 11 00 00 00 00 11' + '00 00 00 00 11 00 11 11 11 00 33 33 33 00 44 44' + '44 00 55 55 55 00 7F 7F 7F 00 99 33 00 00 CC 33' + '00 00 99 66 00 00 99 66 33 00 CC 66 00 00 CC 66' + '33 00 CC 66 66 00 CC 99 33 00 FF 99 33 00 99 99' + '66 00 CC 99 66 00 FF 99 66 00 FF CC 66 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF 99' + '99 00 CC CC 99 00 FF CC 99 00 CC 99 CC 00 99 CC' + 'CC 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 FF FF' + 'CC 00 FF CC FF 00 EE EE EE 00 FF FF FF 00 00 00' + '00 00 DD DD DD 00 FF CC CC 00 CC FF CC 00 CC CC' + 'FF 00 CC FF FF 00 EE EE EE 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17' + '95 00 00 00 38 00 A8 44 F9 77 15 00 00 00 78 0A' + '38 00 00 00 38 00 B0 6C 38 00 98 17 95 00 00 00' + '00 00 E0 19 95 00 F0 88 FA 77 70 38 F5 77 FF FF' + 'FF FF A8 44 F9 77 70 7D F5 77 3A 8A F5 77 96 00' + '00 00 96 00 00 00 09 00 00 00 B0 18 95 00 00 00' + '00 00 CB 44 F9 77 38 9F 07 00 CD 8B F5 77 78 13' + '05 00 37 90 F5 77 00 00 00 00 3E 8A F5 77 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 00 00 00 00 58 00' + '5A 00 00 EC FD 7F 1A 02 00 00 4C 16 95 00 40 9F' + '07 00 FC 15 95 00 FF FF FF FF B4 1A 95 00 45 00' + '00 00 28 02 00 00 FF FF FF FF E2 D8 F5 77 7D 9B' + 'F5 77 94 B6 01 00 00 00 05 00 F4 17 95 00 80 00' + '10 C0 B4 1A 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 00 00 00 00 3E 8A F5 77 9B B2' + 'E7 77 B7 00 00 00 02 00 00 00 A4 1A 95 00 01 00' + '00 00 18 00 00 00 00 00 00 00 10 19 95 00 42 00' + '00 00 00 00 00 00 F4 18 95 00 00 00 00 00 00 00' + '00 00 00 00 00 00 0C 00 00 00 02 00 00 00 01 01' + 'F5 77 00 EC FD 7F 58 00 00 00 00 00 00 00 03 00' + '00 00 60 00 1A 02 40 9F 07 00 00 00 00 00 40 9F' + '07 00 05 00 00 00 BE B3 E7 77 4C 19 95 00 A3 B4' + 'E7 77 F8 00 00 00 00 00 00 C0 00 00 00 00 00 00' + '00 00 02 00 00 00 80 00 00 00 00 00 00 00 8C 1A' + '95 00 7F E9 4B 00 00 63 38 00 00 00 00 C0 00 00' + '00 00 80 1A 95 00 02 00 00 00 80 00 00 00 00 00' + '00 00 C0 27 95 00 C4 F5 AF 00 02 00 00 00 44 3A' + '5C 6F 73 65 78 70 65 72 74 73 5C 72 65 61 63 74' + '6F 73 5C 6C 69 62 5C 73 68 65 6C 6C 33 32 5C 64' + '65 73 6B 74 6F 70 2E 69 63 6F 00 93 4B 00 14 1A' + '95 00 1F 3B D4 77 15 00 00 00 A8 00 00 00 4F 3B' + 'D4 77 E0 19 95 00 33 3B D4 77 64 C5 F5 77 A9 F1' + 'E7 77 F8 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 1A 95 00 B0 6C 38 00 96 00 00 00 00 00' + '00 00 C9 F1 E7 77 96 00 00 00 A4 1A 95 00 09 00' + '00 00 00 00 00 00 96 00 00 00 96 00 00 00 09 00' + '00 00 F4 19 95 00 33 3B D4 77 B4 1A 95 00 09 48' + 'E9 77 B8 10 E9 77 FF FF FF FF C9 F1 E7 77 16 EA' + '4B 00 F8 00 00 00 B0 6C 38 00 96 00 00 00 58 1A' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 26 26 26 26 26 26 26 26 26 26' + '02 26 26 26 26 26 26 16 1F 1F 18 18 18 18 17 18' + '17 17 17 17 07 26 06 25 25 23 22 24 22 24 20 21' + '20 20 20 20 17 01 06 25 13 10 0E 14 13 13 14 13' + '10 0E 0E 19 18 03 06 25 13 09 10 0E 10 0E 10 0E' + '0E 0E 0B 1C 17 26 06 25 0F 0D 0C 0E 0E 10 0E 0E' + '0E 0B 0A 19 1E 26 06 25 0C 0D 0A 0E 0E 0D 0E 0E' + '0E 17 0C 19 18 26 06 25 0E 09 10 0E 0E 0F 10 0E' + '0C 20 0F 19 1F 26 06 25 0F 0E 0E 10 13 11 13 10' + '0E 0C 0C 1B 1D 02 05 25 13 0E 10 13 14 13 11 13' + '0F 1F 12 1A 18 26 06 25 0E 0E 10 14 10 15 13 11' + '13 17 0E 1B 1F 26 05 25 18 1B 21 1B 20 21 21 20' + '1C 18 1B 24 20 26 04 17 24 24 20 24 24 20 24 20' + '24 24 20 24 07 26 26 26 04 26 04 04 26 04 26 04' + '04 26 04 26 26 26 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 FF FF 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 20 00 00 00 00 00 00 10 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 23 00 00 00 58 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 61 00 00 00 61 00 00 00 61 00 00 00 61 00 00' + '00 3D 00 00 00 08 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 6E 00 00 00 E7 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 01 01 01 FF 01 01 01 FF 01 01' + '01 FF 01 01 01 FF 01 01 01 FF 01 01 01 FF 01 01' + '01 FF 01 01 01 FF 02 02 02 FF 02 02 02 FF 02 02' + '02 FF 02 02 02 FF 02 02 02 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 A7 00 00 00 1D 00 00 00 00 00 00' + '00 5D 00 00 00 FF 47 47 47 FF AA AA AA FF B6 B6' + 'B6 FF B2 B2 B2 FF B1 B1 B1 FF B1 B1 B1 FF AF AF' + 'AF FF AE AE AE FF AE AE AE FF AD AD AD FF AC AC' + 'AC FF AC AC AC FF AB AB AB FF AA AA AA FF A9 A9' + 'A9 FF A8 A8 A8 FF A7 A7 A7 FF A7 A7 A7 FF A5 A5' + 'A5 FF A5 A5 A5 FF A4 A4 A4 FF A3 A3 A3 FF A2 A2' + 'A2 FF A1 A1 A1 FF A2 A2 A2 FF A3 A3 A3 FF 64 64' + '64 FF 05 05 05 FF 00 00 00 AB 00 00 00 0A 00 00' + '00 CF 38 38 38 FF F0 F0 F0 FF FF FF FF FF FF FF' + 'FF FF FE FF FF FF FC FC FC FF F9 FA FA FF F7 F7' + 'F7 FF F4 F5 F5 FF F2 F3 F3 FF F0 F1 F1 FF EE EE' + 'EE FF EC EC EC FF E9 EA EA FF E7 E7 E7 FF E5 E5' + 'E5 FF E3 E3 E3 FF E0 E0 E1 FF DE DE DE FF DC DC' + 'DC FF D9 D9 DA FF D7 D7 D8 FF D5 D5 D5 FF D3 D3' + 'D3 FF D0 D0 D0 FF CE CE CE FF CE CE CE FF DE DE' + 'DE FF 66 66 66 FF 00 00 00 FD 00 00 00 41 00 00' + '00 F2 7C 7C 7C FF FF FF FF FF FA FA FA FF FA FC' + 'FD FF F9 FC FF FF F7 FA FC FF F4 F7 FA FF F3 F6' + 'F8 FF F1 F3 F6 FF EE F1 F4 FF EC EF F2 FF EA ED' + 'F0 FF E8 EB ED FF E7 E9 EC FF E4 E7 E9 FF E2 E5' + 'E8 FF E1 E3 E6 FF DF E2 E4 FF DD E0 E2 FF DB DE' + 'E1 FF D9 DD DF FF D8 DB DD FF D6 D9 DC FF D4 D8' + 'DA FF D3 D6 D9 FF D0 D2 D4 FF C6 C6 C6 FF CF CF' + 'CF FF A3 A3 A3 FF 01 01 01 FF 00 00 00 63 00 00' + '00 F0 7E 7E 7E FF FF FF FF FF FD FE FE FF E2 C8' + 'B7 FF DA A0 77 FF DE A9 82 FF E1 AE 86 FF E4 B2' + '8A FF E6 B6 8F FF E9 BB 92 FF EA BD 95 FF EC C0' + '98 FF ED C2 9A FF EE C3 9A FF EE C2 9A FF EC C1' + '99 FF EB BF 97 FF E9 BC 94 FF E7 B8 90 FF E4 B4' + '8C FF E2 B0 88 FF DF AB 84 FF DC A6 7F FF D9 A1' + '7A FF D4 97 6E FF E0 B8 9F FF D1 D2 D3 FF CE CF' + 'CF FF A2 A2 A2 FF 01 01 01 FF 00 00 00 61 00 00' + '00 F0 7D 7D 7D FF FF FF FF FF FF FF FF FF CC A0' + '82 FF BD 56 0F FF C5 66 23 FF CA 6E 2B FF CE 76' + '31 FF D2 7D 38 FF D6 83 3E FF D9 89 43 FF DC 8D' + '47 FF DE 90 4A FF DF 91 4B FF DF 91 4B FF DD 8F' + '49 FF DB 8C 46 FF D8 87 42 FF D6 81 3C FF D1 7B' + '37 FF CD 73 2F FF C8 6C 28 FF C4 64 21 FF BF 5C' + '1A FF B6 4B 06 FF CD 87 5B FF D4 D7 D8 FF D1 D2' + 'D3 FF A1 A1 A1 FF 01 01 01 FF 00 00 00 61 00 00' + '00 F0 7B 7B 7B FF FF FF FF FF FF FF FF FF CE A3' + '87 FF BD 59 16 FF C4 68 29 FF C8 6F 30 FF CC 76' + '35 FF D0 7C 3B FF D3 81 40 FF D6 86 44 FF D7 89' + '48 FF D9 8C 4A FF DA 8C 4B FF DA 8C 4B FF D9 8B' + '49 FF D7 88 47 FF D4 84 43 FF D2 7F 3F FF CF 7A' + '3A FF CB 74 34 FF C7 6D 2D FF C3 66 27 FF BE 5E' + '20 FF B6 4E 0D FF CD 8A 60 FF D6 D8 DA FF D4 D4' + 'D5 FF A1 A1 A1 FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 7B 7B 7B FF FF FF FF FF FF FF FF FF CD A1' + '85 FF B9 52 11 FF C0 61 23 FF C4 68 2A FF C8 6F' + '2F FF CB 74 34 FF CE 79 38 FF D1 7D 3C FF D2 80' + '3F FF D4 82 42 FF D3 83 42 FF D3 83 42 FF D3 82' + '41 FF D1 7F 3E FF D0 7C 3B FF CD 77 37 FF CA 72' + '33 FF C7 6D 2D FF C3 66 28 FF BF 60 21 FF BB 59' + '1A FF B2 49 07 FF CB 86 5D FF D8 D9 DB FF D6 D7' + 'D7 FF A1 A1 A1 FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 7A 7A 7A FF FF FF FF FF FF FF FF FF CB 9E' + '82 FF B5 4C 0A FF BC 5B 1C FF C0 62 22 FF C4 67' + '28 FF C6 6C 2C FF C9 70 31 FF CB 74 34 FF CD 77' + '37 FF CD 79 39 FF CE 79 39 FF CE 79 39 FF CE 78' + '37 FF CC 76 36 FF CB 73 33 FF C8 6F 2F FF C5 6B' + '2B FF C2 65 26 FF BF 60 21 FF BC 59 1A FF B7 53' + '15 FF AE 42 01 FF C8 82 5A FF DA DC DC FF D7 D8' + 'D8 FF A0 A0 A0 FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 78 78 78 FF FF FF FF FF FF FF FF FF C7 99' + '7E FF B1 46 03 FF B8 54 15 FF BB 5A 1B FF BE 5F' + '20 FF C1 64 25 FF C4 68 29 FF C5 6B 2C FF C7 6D' + '2E FF C8 6F 2F FF C8 6F 2F FF C8 6F 2F FF C7 6E' + '2E FF C6 6C 2C FF C5 6A 2A FF C2 66 27 FF C0 62' + '23 FF BF 5E 1E FF B7 51 10 FF A9 44 05 FF B2 47' + '07 FF AC 3C 00 FF C6 7F 57 FF DC DE DF FF DA DB' + 'DB FF 9F 9F 9F FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 77 77 77 FF FF FF FF FF FF FF FF FF C4 94' + '79 FF AC 3D 00 FF B3 4C 0F FF B7 52 14 FF B9 57' + '18 FF BB 5A 1C FF BE 5E 1F FF BF 62 23 FF C2 65' + '26 FF C4 68 28 FF C5 69 2A FF C5 69 2A FF C4 69' + '29 FF C2 66 27 FF C0 62 24 FF BD 5E 1F FF BC 5A' + '1A FF AE 4E 12 FF 9A 6B 4D FF AB 92 82 FF 96 57' + '32 FF A4 31 00 FF C6 7E 55 FF DE E0 E2 FF DD DE' + 'DE FF 9E 9E 9E FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 76 76 76 FF FF FF FF FF FF FF FF FF C0 90' + '76 FF A8 37 00 FF AF 45 07 FF B1 49 0B FF B3 4D' + '10 FF B9 57 18 FF C1 64 25 FF C5 6B 2B FF C7 6E' + '2E FF C8 70 30 FF C9 71 31 FF C9 71 31 FF C9 71' + '31 FF C8 70 2F FF C6 6C 2D FF C4 69 29 FF C3 5F' + '1C FF 93 5C 39 FF DC E4 EA FF ED F3 F6 FF A8 A9' + 'AB FF 86 2F 03 FF C9 7D 52 FF DF E1 E3 FF DE DF' + 'DF FF 9E 9E 9E FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 75 75 75 FF FF FF FF FF FF FF FF FF BE 8F' + '74 FF A6 35 00 FF AA 3D 01 FF B0 49 0B FF BD 5E' + '1F FF C6 6C 2C FF CA 72 32 FF CC 75 35 FF CD 77' + '37 FF CE 78 39 FF CE 7A 39 FF CE 7A 39 FF CE 79' + '39 FF CD 78 37 FF CC 75 36 FF CB 73 32 FF C9 6B' + '28 FF 96 71 57 FF DC E2 E7 FF D4 D0 CE FF C7 CD' + 'D1 FF 7B 34 0B FF CA 7D 50 FF E0 E3 E5 FF E0 E1' + 'E2 FF 9D 9D 9D FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 73 73 73 FF FF FF FF FF FF FF FF FF BD 8D' + '72 FF A6 34 00 FF B2 4C 0F FF C4 68 28 FF CA 72' + '32 FF CC 76 36 FF CF 79 39 FF D1 7D 3D FF D2 80' + '3F FF D3 82 42 FF D4 83 42 FF D4 83 42 FF D3 82' + '41 FF D2 81 40 FF D1 7E 3E FF D0 7B 3A FF D2 78' + '34 FF 9E 60 33 FF B4 B5 B4 FF E9 EF F2 FF AC A2' + '9C FF 8D 2C 00 FF C8 7E 54 FF E3 E5 E6 FF E2 E4' + 'E4 FF 9C 9C 9C FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 72 72 72 FF FF FF FF FF FF FF FF FF BA 8A' + '6E FF AF 43 05 FF C6 6C 2C FF CB 74 33 FF CE 77' + '37 FF D1 7D 3C FF D3 82 41 FF D6 86 44 FF D7 89' + '48 FF D9 8C 4A FF D9 8C 4B FF D9 8C 4B FF D9 8C' + '4A FF D8 8A 49 FF D7 87 46 FF D4 83 42 FF D2 7F' + '3F FF D2 78 34 FF AC 65 2F FF 9A 63 3B FF AD 59' + '21 FF B7 49 08 FF C4 7D 55 FF E5 E6 E7 FF E5 E6' + 'E7 FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 6F 6F 6F FF FF FF FF FF FE FF FF FF BA 8B' + '70 FF BF 5D 1A FF CB 73 33 FF CE 78 38 FF D2 7E' + '3E FF D5 84 43 FF D8 8A 48 FF DB 8E 4C FF DE 92' + '50 FF DE 95 53 FF E0 96 54 FF E0 96 54 FF DF 95' + '53 FF DE 93 51 FF DC 8F 4E FF D9 8B 4A FF D8 86' + '43 FF BD 7D 4A FF A6 75 51 FF AA 75 4E FF 9F 6E' + '44 FF B5 59 18 FF CB 86 5D FF E5 E7 E8 FF E7 E7' + 'E8 FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 6E 6E 6E FF FF FF FF FF FC FF FF FF BE 92' + '77 FF C6 67 24 FF CD 77 37 FF D1 7E 3E FF D5 85' + '43 FF D9 8B 4A FF DD 91 4F FF E0 96 54 FF E2 9A' + '58 FF E4 9E 5B FF E5 9F 5D FF E5 9F 5C FF E5 9E' + '5C FF E3 9B 59 FF E0 97 56 FF DE 93 51 FF D9 87' + '42 FF B8 97 7C FF B0 BA C2 FF B0 B5 BA FF A3 AA' + 'A9 FF A9 5B 22 FF D5 91 66 FF E7 E8 E9 FF EA EA' + 'EB FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 6C 6C 6C FF FF FF FF FF FC FF FF FF BC 90' + '74 FF C8 6B 27 FF D0 7B 3B FF D4 83 42 FF D8 8A' + '48 FF DD 91 4F FF E1 97 56 FF E4 9E 5B FF E7 A2' + '60 FF EA A6 63 FF EA A9 65 FF EB A9 66 FF EA A7' + '64 FF E8 A4 61 FF E6 9F 5D FF E2 99 58 FF E1 91' + '4B FF B3 8D 6C FF D1 D6 DB FF E0 E3 E4 FF B3 AF' + 'AD FF B5 60 24 FF D4 92 67 FF F4 F6 F7 FF FA FA' + 'FB FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 6B 6B 6B FF FF FF FF FF FC FF FF FF B3 82' + '67 FF C4 61 1C FF D4 80 3D FF D7 86 44 FF DC 8D' + '4B FF E0 95 52 FF E5 9C 59 FF E9 A3 60 FF ED AA' + '65 FF F0 AF 6A FF F2 B2 6D FF F2 B3 6D FF F1 B0' + '6C FF EE AC 67 FF EA A5 62 FF E6 9F 5B FF E7 99' + '53 FF B5 81 54 FF C4 C5 C6 FF DA DF E1 FF A6 95' + '89 FF BB 5B 17 FF CC 85 5A FF FA FC FD FF FF FF' + 'FF FF 9B 9B 9B FF 00 00 00 FF 00 00 00 61 00 00' + '00 F0 6A 6A 6A FF FF FF FF FF FD FF FF FF AC 84' + '6D FF AA 52 1C FF CB 80 44 FF D2 88 4A FF D6 8F' + '51 FF DB 96 58 FF DF 9E 60 FF E4 A5 66 FF E8 AC' + '6D FF EC B2 72 FF EE B6 76 FF EE B7 77 FF ED B4' + '74 FF E9 AE 6F FF E5 A8 69 FF E1 A1 62 FF DE 9A' + '5B FF CE 8B 50 FF A9 78 50 FF A5 76 50 FF AD 70' + '41 FF AE 59 20 FF C1 85 64 FF FD FF FF FF FF FF' + 'FF FF 9A 9A 9A FF 00 00 00 FF 00 00 00 61 00 00' + '00 F3 69 69 69 FF FF FF FF FF FF FF FF FF E2 E0' + 'E0 FF DA D6 D4 FF DE DA D6 FF DF DB D7 FF E0 DB' + 'D7 FF E0 DC D8 FF E0 DC D8 FF E1 DD D9 FF E1 DD' + 'D9 FF E1 DE D9 FF E1 DE DA FF E1 DE DA FF E1 DE' + 'DA FF E1 DD D9 FF E1 DD D9 FF E0 DC D8 FF DF DB' + 'D7 FF E1 DC D7 FF E4 DC D4 FF E3 DA D2 FF E1 D9' + 'D3 FF D8 D5 D3 FF E5 E3 E2 FF FE FE FE FF FF FF' + 'FF FF 9B 9B 9B FF 00 00 00 FF 00 00 00 63 00 00' + '00 DE 3A 3A 3A FF F2 F2 F2 FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE FE' + 'FE FF 67 67 67 FF 00 00 00 FF 00 00 00 45 00 00' + '00 7A 01 01 01 FF 5D 5D 5D FF C3 C3 C3 FF D3 D3' + 'D3 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1 D1 FF D1 D1' + 'D1 FF D0 D0 D0 FF D0 D0 D0 FF CF CF CF FF CF CF' + 'CF FF CE CE CE FF CF CF CF FF C9 C9 C9 FF 7B 7B' + '7B FF 0B 0B 0B FF 00 00 00 BF 00 00 00 0A 00 00' + '00 07 00 00 00 98 00 00 00 FD 08 08 08 FF 11 11' + '11 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' + '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' + '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' + '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' + '10 FF 10 10 10 FF 10 10 10 FF 10 10 10 FF 10 10' + '10 FF 10 10 10 FF 11 11 11 FF 0C 0C 0C FF 00 00' + '00 FF 00 00 00 C4 00 00 00 24 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 40 00 00 00 7D 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 59 00 00 00 0A 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF FF FF FF FF FF FF C0 00 00 03 80 00' + '00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 01 C0 00' + '00 03 FF FF FF FF FF FF FF FF FF FF FF FF 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 21 00 00 00 92 05 05' + '05 A8 05 05 05 A8 05 05 05 A8 05 05 05 A8 06 06' + '06 A8 06 06 06 A8 06 06 06 A8 06 06 06 A8 06 06' + '06 A8 07 07 07 A8 07 07 07 A8 06 06 06 A8 00 00' + '00 78 00 00 00 0A 0E 0E 0E B9 98 98 98 FF C9 CB' + 'CC FF C2 C4 C6 FF BF C1 C2 FF BC BE BF FF B8 BA' + 'BC FF B6 B8 B9 FF B4 B5 B7 FF B0 B2 B4 FF AE B1' + 'B2 FF AC AE B0 FF AA AC AE FF AC AC AD FF 55 55' + '55 FF 01 01 01 72 43 43 43 F3 FF FF FF FF FD F5' + 'EF FF F8 EC E3 FF F7 EC E3 FF F5 EB E2 FF F2 E9' + 'E0 FF F0 E7 DE FF ED E4 DB FF E9 DF D6 FF E5 DA' + 'D2 FF E1 D5 CC FF DC D0 C7 FF DB D6 D3 FF B0 B0' + 'B1 FF 08 08 08 AB 48 48 49 F1 FD FE FF FF CF 91' + '67 FF CA 71 31 FF D5 85 47 FF DC 90 52 FF E0 99' + '59 FF E2 9B 5B FF E0 98 59 FF DC 90 51 FF D5 84' + '46 FF CB 76 38 FF C4 66 27 FF D4 B1 9B FF B0 B5' + 'B8 FF 08 08 08 A9 46 47 47 F0 FD FE FF FF C8 84' + '58 FF C0 5D 19 FF CA 71 30 FF D0 7B 39 FF D3 81' + '3F FF D4 83 41 FF D3 80 3E FF CF 7A 38 FF C9 6E' + '2E FF C1 61 1F FF B9 51 10 FF D2 AC 96 FF B2 B7' + 'BA FF 08 08 08 A8 45 46 46 F0 FD FE FF FF C3 7D' + '52 FF B8 52 10 FF C0 64 24 FF C5 6B 2B FF C8 70' + '30 FF C9 71 31 FF C8 6F 2F FF C4 6A 2A FF BF 61' + '21 FF B3 50 12 FF B1 44 04 FF D3 AC 96 FF B3 B9' + 'BC FF 07 07 07 A8 44 45 46 F0 FC FE FE FF BC 72' + '48 FF AE 41 02 FF B8 55 17 FF C0 63 23 FF C5 6A' + '2B FF C6 6C 2D FF C5 6B 2B FF C2 63 23 FF B0 5E' + '28 FF BD A9 9D FF A3 61 3D FF D1 A6 8E FF B5 BB' + 'BD FF 06 06 06 A8 43 43 44 F0 FC FD FD FF B7 6D' + '42 FF B1 47 08 FF C5 6A 2B FF CC 76 36 FF D0 7C' + '3B FF D1 7E 3D FF D0 7C 3C FF CF 76 34 FF B4 71' + '41 FF D1 D5 D6 FF A8 79 5E FF CF A4 8C FF B7 BC' + 'BF FF 06 06 06 A8 41 42 43 F0 FA FA FB FF BE 78' + '4D FF C6 69 26 FF D1 7D 3D FF D6 86 45 FF DA 8D' + '4B FF DB 8F 4E FF DB 8D 4C FF D8 88 46 FF CB 7B' + '3E FF 9F 69 41 FF AB 57 21 FF DA B2 9A FF B7 BC' + 'C0 FF 06 06 06 A8 40 41 41 F0 F7 F8 F9 FF C8 88' + '5C FF CF 77 33 FF D8 89 47 FF DF 95 52 FF E4 9E' + '5A FF E6 A1 5E FF E5 9F 5C FF E2 95 4F FF C8 91' + '63 FF BE BF C0 FF B2 86 65 FF E2 B9 9F FF BA C0' + 'C3 FF 05 05 05 A8 3F 40 40 F0 F7 F7 F8 FF BB 79' + '4D FF CD 75 2F FF D8 8B 47 FF E1 9A 55 FF E9 A6' + '61 FF EC AD 67 FF EA A8 63 FF E5 9C 55 FF C9 8A' + '53 FF B9 AF A6 FF AE 72 49 FF E8 BF A5 FF C5 CB' + 'CE FF 04 04 04 A8 3B 3B 3B F4 FF FF FF FF DB C6' + 'BA FF E2 C5 AE FF E8 CE B7 FF EB D4 BC FF EF D9' + 'C1 FF F1 DC C4 FF EF DA C2 FF EC D5 BD FF E7 CD' + 'B6 FF DF C6 B0 FF D8 BA A7 FF F8 ED E7 FF C8 CA' + 'CB FF 02 02 02 AB 0F 0F 0F C7 AA A9 A9 FF E2 E5' + 'E7 FF DE E3 E6 FF DD E1 E5 FF DD E0 E4 FF DC E0' + 'E3 FF DC DF E3 FF DC E0 E3 FF DD E0 E4 FF DD E1' + 'E4 FF DD E0 E2 FF DE E2 E5 FF D8 DA DB FF 66 66' + '65 FF 00 00 00 78 00 00 00 2E 01 01 01 B1 0F 0F' + '0F CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E' + '0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E 0E CC 0E 0E' + '0E CC 0E 0E 0E CC 0E 0E 0E CC 0C 0C 0C CB 00 00' + '00 8D 00 00 00 0D 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 FF FF 00 00 28 00 00 00 10 00 00 00 20 00' + '00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 77' + '77 77 77 77 77 80 8F FF FF FF F7 77 77 70 8F 83' + '88 88 88 83 37 70 8F 83 33 38 33 33 37 70 8F 83' + '33 33 33 33 37 70 8F 83 33 33 33 37 37 70 8F 83' + '33 33 33 87 87 70 8F 83 38 88 88 38 37 70 6F 83' + '88 87 88 87 87 70 0F 83 88 77 78 87 87 70 0F 77' + '77 77 77 77 7F 70 07 FF FF F7 FF FF F7 80 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + '00 00 80 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 80 01 00 00 FF FF 00 00 28 00' + '00 00 20 00 00 00 40 00 00 00 01 00 04 00 00 00' + '00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 80' + '00 00 80 80 00 00 00 00 80 00 80 00 80 00 00 80' + '80 00 C0 C0 C0 00 80 80 80 00 FF 00 00 00 00 FF' + '00 00 FF FF 00 00 00 00 FF 00 FF 00 FF 00 00 FF' + 'FF 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 87 77 77 77 77 77 77 77 77' + '77 77 77 77 80 00 00 FF FF FF FF FF FF FF FF F7' + '77 77 77 77 78 00 08 FF FF FF FF FF FF FF FF FF' + '77 77 77 77 77 00 08 FF 77 77 77 77 77 77 77 77' + '77 77 78 77 77 00 08 FF 73 33 33 38 88 88 88 83' + '33 33 33 87 77 00 08 FF 73 33 33 38 88 88 88 83' + '33 33 33 87 77 00 08 FF 73 33 33 33 38 88 83 33' + '33 33 33 87 77 00 08 FF 73 33 33 33 33 33 33 33' + '33 33 33 87 77 00 08 FF 83 33 33 33 33 33 33 33' + '33 33 31 87 78 00 08 FF 81 33 33 33 33 33 33 33' + '33 88 31 8F 78 00 08 FF 81 33 33 33 33 33 33 33' + '33 FF 71 8F 78 00 08 FF 81 13 33 33 33 33 33 33' + '38 F7 71 8F F8 00 08 FF 81 33 33 33 38 88 83 33' + '33 7F 71 8F F8 00 08 FF 83 33 33 88 88 88 88 88' + '33 33 33 8F F8 00 08 FF 83 33 38 88 88 88 88 88' + '88 88 83 8F F8 00 08 FF 83 33 88 88 88 88 88 88' + '88 77 73 8F F8 00 08 FF 83 38 88 88 77 77 77 88' + '88 7F 73 8F F8 00 08 FF 83 38 88 87 77 77 77 78' + '88 77 83 8F F8 00 08 FF 83 88 88 87 77 77 77 77' + '88 88 83 8F F8 00 08 FF F7 77 77 77 77 77 77 77' + '77 77 77 FF F8 00 00 FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF F8 00 00 87 77 77 77 77 77 77 77 77' + '77 77 77 77 80 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF 80 00 00 03 80 00 00 01 00 00' + '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' + '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' + '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' + '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' + '00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00' + '00 01 80 00 00 03 E0 00 00 0F FF FF FF FF FF FF' + 'FF FF FF FF FF FF 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 08 00 00 00 00 00 00 09 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 11 11 11 00 66 33 00 00 66 33 33 00 66 66' + '33 00 44 44 44 00 55 55 55 00 66 66 66 00 77 77' + '77 00 7F 7F 7F 00 99 33 00 00 99 33 33 00 CC 33' + '00 00 CC 33 33 00 99 66 00 00 99 66 33 00 CC 66' + '00 00 CC 66 33 00 FF 66 33 00 99 66 66 00 CC 66' + '66 00 FF 66 66 00 99 99 33 00 CC 99 33 00 FF 99' + '33 00 FF CC 33 00 99 99 66 00 CC 99 66 00 FF 99' + '66 00 CC CC 66 00 FF CC 66 00 88 88 88 00 99 99' + '99 00 AA AA AA 00 BB BB BB 00 CC 99 99 00 FF 99' + '99 00 99 CC 99 00 CC CC 99 00 FF CC 99 00 99 CC' + 'CC 00 CC CC CC 00 DD DD DD 00 FF CC CC 00 FF FF' + 'CC 00 CC CC FF 00 FF CC FF 00 CC FF FF 00 EE EE' + 'EE 00 FF FF FF 00 00 00 00 00 A8 44 F9 77 21 00' + '00 00 B8 0C 38 00 00 00 38 00 F0 B5 0C 01 14 17' + '95 00 00 00 00 00 5C 19 95 00 28 52 0C 01 68 19' + '95 00 77 82 F5 77 98 7F F5 77 3A 8A F5 77 00 04' + '00 00 90 A2 AF 00 10 00 00 00 10 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 C0 17 95 00 00 00 38 00 A8 44' + 'F9 77 15 00 00 00 78 0A 38 00 00 00 38 00 B0 6C' + '38 00 98 17 95 00 00 00 00 00 E0 19 95 00 F0 88' + 'FA 77 70 38 F5 77 FF FF FF FF A8 44 F9 77 70 7D' + 'F5 77 3A 8A F5 77 96 00 00 00 96 00 00 00 09 00' + '00 00 B0 18 95 00 00 00 00 00 CB 44 F9 77 38 9F' + '07 00 CD 8B F5 77 78 13 05 00 37 90 F5 77 00 00' + '00 00 3E 8A F5 77 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 28 81 0C 01 10 AE 0C 01 20 81' + '0C 01 78 01 38 00 78 01 38 00 38 02 38 00 38 56' + '0C 01 01 00 00 00 03 00 00 00 38 02 38 00 F0 56' + '0C 01 F0 56 0C 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00' + '00 00 00 00 00 00 58 00 5A 00 30 56 0C 01 30 56' + '0C 01 4C 16 95 00 40 9F 07 00 FC 15 95 00 FF FF' + 'FF FF B4 1A 95 00 45 00 00 00 28 02 00 00 28 52' + '0C 01 A4 18 95 00 E5 3A F8 77 18 00 00 00 30 56' + '0C 01 00 00 38 00 28 52 0C 01 00 00 00 00 78 19' + '95 00 CA 8C F5 77 78 01 38 00 BE 8E F5 77 08 06' + '38 00 37 90 F5 77 30 52 0C 01 30 52 0C 01 40 00' + '00 00 40 00 00 00 01 00 00 00 18 00 00 00 00 00' + '00 00 10 19 95 00 42 00 00 00 00 00 00 00 F4 18' + '95 00 00 00 00 00 00 00 00 00 00 00 00 00 28 52' + '0C 01 28 52 0C 01 01 01 F5 77 78 01 38 00 30 52' + '0C 01 20 81 0C 01 28 81 0C 01 78 01 38 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 BE B3' + 'E7 77 28 52 0C 01 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 08 04 00 00 99 00' + '00 00 08 04 00 00 08 01 00 00 00 00 00 00 00 00' + '00 00 00 00 01 01 00 00 38 00 BC 18 95 00 C0 18' + '95 00 B0 19 95 00 F0 88 FA 77 88 1C F5 77 FF FF' + 'FF FF 37 90 F5 77 81 E9 49 00 00 00 38 00 00 00' + '00 00 30 52 0C 01 30 52 0C 01 A4 1A 95 00 40 00' + '00 00 40 00 00 00 B8 10 E9 77 FF FF FF FF C9 F1' + 'E7 77 16 EA 4B 00 F8 00 00 00 B4 1A 95 00 DC E3' + '49 00 E0 A3 4E 00 FF FF FF FF 10 00 00 00 10 DA' + '4B 00 30 52 0C 01 71 CC 43 00 30 52 0C 01 F0 B5' + '0C 01 A4 1A 95 00 90 A2 AF 00 C4 F5 AF 00 06 00' + '00 00 F0 B5 0C 01 0F 02 00 00 70 52 0C 01 10 00' + '00 00 00 00 00 00 20 00 00 00 30 52 0C 01 40 00' + '00 00 10 00 00 00 00 01 00 00 00 04 00 00 00 00' + '00 00 00 00 00 00 10 00 00 00 10 00 00 00 28 00' + '00 00 10 00 00 00 20 00 00 00 01 00 20 00 00 00' + '00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 00 00 00 00 00 00' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 00 00 00 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 00 32 32' + '32 32 05 08 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F' + '1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F 1F' + '1F 1F 1F 1F 1F 1F 1F 08 06 32 32 32 32 32 32 32' + '32 1F 31 31 31 31 31 31 31 31 30 31 30 30 30 30' + '30 30 30 2A 30 2A 30 2A 2A 2A 2A 2A 2A 2A 2A 2A' + '29 2A 29 29 29 29 29 29 30 20 01 32 32 32 32 32' + '05 31 31 31 30 31 30 30 30 30 30 30 30 30 2A 30' + '30 2A 2A 30 2A 2A 2A 2A 2A 2A 2A 29 2A 29 29 29' + '29 29 29 29 29 29 22 29 22 30 07 32 32 32 32 32' + '08 31 31 30 31 30 30 31 30 30 30 30 30 2A 30 2A' + '2A 30 2A 2A 2A 2A 2B 2A 2A 29 2A 29 2A 29 29 29' + '29 29 29 29 29 22 29 22 22 2A 21 32 32 32 32 32' + '20 31 31 31 31 31 31 31 31 31 31 31 30 31 31 31' + '2E 2F 31 30 30 31 2F 30 30 31 2A 2C 2D 31 30 30' + '30 30 30 2A 2E 2C 2A 29 29 29 21 32 32 32 32 32' + '1F 31 31 31 2A 1B 1C 1B 1B 1B 23 1B 24 27 1B 26' + '1E 24 1E 26 24 1D 24 27 1E 23 27 24 1E 23 1C 1D' + '23 1B 1B 1C 1B 1B 2A 29 22 2A 21 32 32 32 32 32' + '1F 31 31 31 29 11 0E 11 11 17 11 17 17 11 1C 11' + '1B 18 1B 1C 17 1C 1B 17 15 17 11 1B 11 17 11 11' + '10 11 11 0E 10 0B 2B 29 29 29 21 32 32 32 32 32' + '1F 31 31 31 2A 11 11 11 11 11 17 11 11 1B 17 1C' + '17 1B 14 17 1C 14 18 1B 17 17 1C 11 17 11 17 11' + '11 0F 11 10 0B 10 29 29 29 29 21 32 32 32 32 32' + '1F 31 31 31 2A 0F 10 11 11 11 11 17 11 11 17 11' + '1C 17 17 1C 17 17 1B 12 1B 11 17 1B 11 17 11 11' + '11 11 10 0B 10 11 26 29 29 2A 21 32 32 32 32 32' + '1F 31 31 31 29 10 0F 11 10 11 17 11 11 17 11 1B' + '17 11 1C 11 17 1B 12 1B 11 1B 11 11 17 11 11 11' + '11 10 0F 11 10 0A 2B 29 29 2A 21 32 32 32 32 32' + '1F 31 31 31 2A 11 10 0B 11 11 11 11 17 11 17 11' + '11 1B 11 17 14 11 17 11 17 11 17 11 11 11 11 10' + '11 0F 10 0A 0D 0E 29 2A 29 29 21 32 32 32 32 32' + '1F 31 31 31 2D 10 0B 10 0F 10 11 0E 11 11 11 11' + '17 11 17 11 11 17 11 17 11 17 11 0F 10 11 11 11' + '0E 11 0C 11 0E 0C 2B 29 29 2A 21 32 32 32 32 32' + '1F 31 31 31 2B 0F 10 11 0C 0F 11 11 11 11 11 11' + '11 17 11 11 17 11 17 11 11 11 11 11 11 11 0E 11' + '0D 0E 11 0A 10 0A 29 2A 29 2A 21 32 32 32 32 32' + '1F 31 31 31 29 0F 0C 0B 0E 11 0C 11 10 0F 11 11' + '11 0E 11 17 11 11 11 0F 11 11 10 11 0F 10 11 11' + '0E 10 0A 10 0A 0A 2B 2A 29 2A 21 32 32 32 32 32' + '1F 31 31 31 29 10 0A 10 0C 0F 11 0E 11 10 11 0E' + '11 11 11 10 0F 11 10 11 10 0F 11 11 10 0B 10 0A' + '0B 03 0A 0A 0C 0E 29 2A 2A 2A 20 32 32 32 32 32' + '1F 31 31 31 2A 0A 0E 0C 0F 10 0A 10 0F 0D 0E 11' + '11 11 11 11 11 11 11 11 11 11 11 10 0F 10 0A 1F' + '22 2A 25 0B 0A 0A 27 2A 29 2A 21 32 32 32 32 32' + '08 31 31 31 29 0B 0C 0E 0A 0C 11 0A 10 11 11 11' + '11 17 11 11 17 11 11 17 11 11 11 11 11 11 04 30' + '31 30 29 07 0A 0A 29 2A 29 30 20 32 32 32 32 32' + '1F 31 31 31 29 10 0A 0A 0C 0F 0A 11 11 17 11 11' + '11 11 17 11 11 17 11 11 11 17 11 11 11 10 13 30' + '29 20 30 08 0A 0A 2B 2A 2A 2A 20 32 32 32 32 32' + '1F 31 31 31 29 0A 0A 0C 0E 0C 17 11 11 11 17 11' + '17 11 11 17 15 11 17 11 1B 11 11 17 11 11 0F 29' + '31 30 31 08 02 10 22 30 29 30 20 32 32 32 32 32' + '08 31 31 31 26 0F 0C 0A 11 17 11 11 11 17 11 1B' + '11 17 17 14 17 17 14 17 11 17 17 11 17 11 0F 07' + '2A 31 21 03 0C 0A 2B 2A 2A 2A 21 32 32 32 32 32' + '1F 31 31 31 29 0A 0E 11 11 11 11 17 11 11 17 11' + '1C 11 1B 18 11 1B 18 14 17 14 17 11 14 17 11 0F' + '0F 04 03 10 0B 0A 26 30 2A 2A 20 32 32 32 32 32' + '08 31 31 31 29 0A 10 11 11 11 17 11 17 1B 12 1B' + '11 1C 17 1B 1B 17 1B 18 1B 17 15 17 17 12 17 11' + '11 0F 11 11 10 0A 2B 30 2A 30 20 32 32 32 32 32' + '08 31 31 31 22 0F 11 11 17 11 11 1B 12 17 1B 17' + '1B 17 1C 18 1B 1C 17 1B 1C 17 17 15 17 17 13 13' + '1A 1B 13 0F 11 10 29 2A 2A 30 20 32 32 32 32 32' + '08 31 31 31 22 11 11 11 11 1B 17 11 1B 12 1B 1C' + '17 1C 17 1B 1C 17 1B 1C 17 1C 1B 17 1B 11 23 20' + '21 1F 28 13 0F 10 29 30 2A 30 20 32 32 32 32 32' + '08 31 31 31 22 10 11 17 11 11 1C 17 17 1B 18 1B' + '1C 1B 1C 1B 1C 1C 1B 1B 1C 17 1C 1B 17 14 1A 29' + '2A 2A 22 13 10 0F 2B 30 2A 30 20 32 32 32 32 32' + '08 31 31 31 22 0F 11 11 1B 17 11 17 1B 1C 1B 18' + '1B 1E 1C 1B 1E 1B 1E 1C 1B 1C 1B 18 1B 18 1A 29' + '2A 29 29 1A 11 11 26 31 31 30 20 32 32 32 32 32' + '08 31 31 31 22 0D 17 11 11 1C 17 15 17 1B 1B 1C' + '1B 1C 1D 1C 1B 1E 1B 1C 1E 1B 1C 1B 1C 17 1B 29' + '2A 2A 2A 13 10 11 2B 2F 30 31 20 32 32 32 32 32' + '08 31 31 31 22 0E 11 14 17 11 1B 17 1B 1C 19 1B' + '1C 1D 1C 1C 1E 24 1E 1E 1B 1C 1D 1C 17 1C 13 20' + '29 22 21 0F 11 0C 29 31 31 31 20 32 32 32 32 32' + '08 31 31 31 21 0A 0C 17 17 17 15 17 18 1B 1C 1C' + '1E 1C 1E 1E 24 1E 1C 1C 1E 1C 1C 17 1C 17 18 11' + '16 11 0F 11 10 0A 2B 31 30 31 1F 32 32 32 32 32' + '07 31 31 31 22 1B 20 1B 23 23 1B 26 23 26 23 26' + '23 26 26 23 26 26 26 26 26 23 26 23 26 23 26 23' + '1B 23 1B 23 1F 1A 2A 31 31 31 20 32 32 32 32 32' + '08 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 31 1F 32 32 32 32 32' + '05 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 30 08 32 32 32 32 32' + '01 20 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31' + '31 31 31 31 31 31 31 31 31 21 01 32 32 32 32 32' + '32 01 07 21 29 22 22 22 22 22 22 22 22 22 22 22' + '22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22' + '22 22 22 22 22 22 22 22 08 01 32 32 32 00 00 32' + '32 32 32 32 01 01 01 01 01 01 01 01 01 01 01 01' + '01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01' + '01 01 01 01 01 01 01 01 32 32 32 32 00 00 00 00' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 00 00 00 00 00' + '00 00 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32' + '32 32 32 32 32 32 32 32 32 32 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 F0 00' + '00 00 00 0F 00 00 C0 00 00 00 00 03 00 00 80 00' + '00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 01 00 00 80 00 00 00 00 03 00 00 C0 00' + '00 00 00 07 00 00 F0 00 00 00 00 0F 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 28 00' + '00 00 30 00 00 00 60 00 00 00 01 00 20 00 00 00' + '00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 17 00 00 00 32 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 37 00 00 00 37 00 00 00 37 00 00 00 37 00 00' + '00 28 00 00 00 0C 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 19 00 00 00 75 00 00 00 C8 00 00 00 F4 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F7 00 00' + '00 F7 00 00 00 F7 00 00 00 F7 00 00 00 F6 00 00' + '00 D6 00 00 00 90 00 00 00 3F 00 00 00 08 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00' + '00 C7 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 E3 00 00 00 4A 00 00' + '00 06 00 00 00 00 00 00 00 04 00 00 00 B0 00 00' + '00 FF 05 05 05 FF 47 47 47 FF 83 83 83 FF 90 90' + '90 FF 8E 8E 8E FF 8E 8E 8E FF 8E 8E 8E FF 8D 8D' + '8D FF 8D 8D 8D FF 8D 8D 8D FF 8D 8D 8D FF 8C 8C' + '8C FF 8C 8C 8C FF 8C 8C 8C FF 8B 8B 8B FF 8B 8B' + '8B FF 8B 8B 8B FF 8B 8B 8B FF 8B 8B 8B FF 8A 8A' + '8A FF 8A 8A 8A FF 8A 8A 8A FF 89 89 89 FF 89 89' + '89 FF 89 89 89 FF 89 89 89 FF 89 89 89 FF 88 88' + '88 FF 88 88 88 FF 88 88 88 FF 87 87 87 FF 87 87' + '87 FF 87 87 87 FF 87 87 87 FF 87 87 87 FF 87 87' + '87 FF 86 86 86 FF 88 88 88 FF 83 83 83 FF 53 53' + '53 FF 0B 0B 0B FF 00 00 00 FF 00 00 00 D5 00 00' + '00 34 00 00 00 01 00 00 00 52 00 00 00 FF 06 06' + '06 FF 8B 8B 8B FF FB FB FB FF FF FF FF FF FE FE' + 'FE FF FC FC FC FF FA FA FA FF F9 F9 F9 FF F8 F8' + 'F8 FF F6 F6 F6 FF F5 F5 F5 FF F4 F4 F4 FF F2 F2' + 'F2 FF F1 F1 F1 FF F0 F0 F0 FF EE EE EE FF ED ED' + 'ED FF EB EB EB FF EA EA EA FF E9 E9 E9 FF E7 E7' + 'E7 FF E5 E5 E5 FF E5 E5 E5 FF E3 E3 E3 FF E1 E1' + 'E1 FF E0 E0 E0 FF DF DF DF FF DD DD DD FF DC DC' + 'DC FF DB DB DB FF D9 D9 D9 FF D8 D8 D8 FF D6 D6' + 'D6 FF D5 D5 D5 FF D3 D3 D3 FF D2 D2 D2 FF D1 D1' + 'D1 FF CF CF CF FF CD CD CD FF D1 D1 D1 FF EA EA' + 'EA FF 98 98 98 FF 0C 0C 0C FF 00 00 00 FF 00 00' + '00 8D 00 00 00 0A 00 00 00 C3 00 00 00 FF 49 49' + '49 FF FA FA FA FF FE FE FE FF F7 F7 F7 FF F7 F7' + 'F7 FF F5 F5 F5 FF F3 F3 F3 FF F2 F2 F2 FF F0 F0' + 'F0 FF EF EF EF FF EE EE EE FF EC EC EC FF EA EA' + 'EA FF E9 E9 E9 FF E8 E8 E8 FF E6 E6 E6 FF E5 E5' + 'E5 FF E3 E3 E3 FF E2 E2 E2 FF E1 E1 E1 FF DF DF' + 'DF FF DD DD DD FF DC DC DC FF DA DA DA FF D9 D9' + 'D9 FF D8 D8 D8 FF D6 D6 D6 FF D4 D4 D4 FF D3 D3' + 'D3 FF D2 D2 D2 FF D0 D0 D0 FF CF CF CF FF CD CD' + 'CD FF CC CC CC FF CB CB CB FF C9 C9 C9 FF C7 C7' + 'C7 FF C6 C6 C6 FF C5 C5 C5 FF C2 C2 C2 FF C2 C2' + 'C2 FF E6 E6 E6 FF 73 73 73 FF 00 00 00 FF 00 00' + '00 D4 00 00 00 27 00 00 00 F3 00 00 00 FF 84 84' + '84 FF FF FF FF FF FA FA FA FF F8 F8 F8 FF F7 F7' + 'F7 FF F6 F6 F7 FF F4 F5 F5 FF F3 F4 F4 FF F1 F2' + 'F3 FF EF F0 F1 FF EE EF F0 FF ED ED EE FF EA EB' + 'EC FF E9 EA EB FF E8 E8 E9 FF E6 E7 E7 FF E5 E6' + 'E6 FF E3 E4 E5 FF E1 E2 E3 FF E0 E1 E1 FF DF DF' + 'E0 FF DD DE DE FF DC DC DD FF DA DB DB FF D8 D9' + 'DA FF D7 D8 D9 FF D6 D6 D7 FF D4 D4 D5 FF D3 D3' + 'D4 FF D1 D2 D2 FF CF D0 D1 FF CE CF CF FF CD CD' + 'CE FF CB CC CC FF CA CB CB FF C8 C9 CA FF C6 C7' + 'C8 FF C5 C6 C7 FF C4 C4 C4 FF C5 C4 C4 FF C1 C1' + 'C1 FF D7 D7 D7 FF AD AD AD FF 00 00 00 FF 00 00' + '00 F9 00 00 00 38 00 00 00 F0 00 00 00 FF 8F 8F' + '8F FF FF FF FF FF FC FC FC FF FA FA FA FF FB FB' + 'FB FF FC FC FD FF FB FC FC FF FB FB FB FF FA FA' + 'FA FF F9 FA FA FF F9 F9 FA FF F8 F8 F9 FF F7 F8' + 'F8 FF F7 F7 F7 FF F6 F6 F6 FF F5 F5 F6 FF F4 F5' + 'F5 FF F4 F5 F5 FF F3 F4 F4 FF F3 F3 F3 FF F2 F2' + 'F3 FF F2 F2 F2 FF F1 F1 F2 FF F0 F1 F1 FF EF F0' + 'F0 FF EF EF F0 FF EE EF EF FF ED EE EE FF ED ED' + 'EE FF EC ED ED FF EB EC EC FF EB EB EC FF EA EB' + 'EB FF E9 EA EA FF E9 EA EA FF E8 E9 E9 FF E7 E8' + 'E8 FF E8 E8 E8 FF DE DE DE FF C6 C6 C6 FF C4 C4' + 'C4 FF D0 D0 D0 FF AD AD AD FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8D 8D' + '8D FF FF FF FF FF FE FE FE FF FC FC FD FF E3 E1' + 'DF FF D3 99 70 FF D6 93 65 FF D9 99 6B FF DB 9D' + '6E FF DD A1 72 FF E0 A4 76 FF E1 A8 79 FF E4 AC' + '7D FF E6 AF 80 FF E8 B2 83 FF EA B4 85 FF EB B7' + '87 FF EC B9 89 FF ED BA 8B FF EE BB 8B FF EE BB' + '8B FF EE BB 8B FF ED BA 8B FF ED B9 89 FF EB B7' + '87 FF EA B5 86 FF E9 B2 83 FF E6 AF 81 FF E5 AC' + '7E FF E3 A9 7A FF E1 A5 76 FF DF A2 74 FF DD 9E' + '70 FF DB 9A 6C FF D8 97 69 FF D6 93 65 FF D3 8E' + '60 FF D3 8F 62 FF E6 D7 CD FF C9 CC CD FF C5 C5' + 'C5 FF D2 D2 D2 FF AA AA AA FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8B 8B' + '8B FF FF FF FF FF FF FF FF FF FD FF FF FF D8 D3' + 'D1 FF BE 67 2C FF C1 5F 1B FF C5 67 25 FF C8 6C' + '29 FF CB 72 2F FF CE 77 34 FF D0 7C 38 FF D3 80' + '3D FF D6 85 41 FF D9 89 44 FF DB 8C 47 FF DD 8F' + '4B FF DE 91 4C FF DF 93 4E FF E0 95 50 FF E0 95' + '50 FF E0 94 50 FF DF 93 4E FF DE 91 4D FF DC 8F' + '49 FF DB 8B 47 FF D8 88 43 FF D5 84 40 FF D3 7F' + '3C FF D0 7B 37 FF CD 75 32 FF CA 70 2D FF C7 6C' + '29 FF C4 66 23 FF C0 60 1E FF BC 5B 1A FF B9 53' + '11 FF B9 54 13 FF DF C8 B9 FF CC CF D2 FF C6 C6' + 'C6 FF D3 D3 D3 FF AB AB AB FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8B 8B' + '8B FF FF FF FF FF FF FF FF FF FE FF FF FF DA D5' + 'D3 FF BE 6A 32 FF C1 62 21 FF C5 6A 2B FF C7 6F' + '2F FF CA 74 34 FF CD 78 38 FF CF 7D 3C FF D2 81' + '40 FF D5 84 43 FF D7 88 47 FF D8 8B 4A FF DA 8E' + '4C FF DC 90 4E FF DD 92 50 FF DD 92 51 FF DD 92' + '51 FF DD 92 50 FF DD 91 4F FF DB 8F 4E FF DA 8D' + '4B FF D9 8A 49 FF D6 87 46 FF D4 83 42 FF D2 80' + '3F FF CF 7C 3B FF CC 77 37 FF CA 73 32 FF C7 6E' + '2E FF C3 68 29 FF C1 64 24 FF BD 5F 20 FF B9 57' + '18 FF BA 57 1A FF E0 C9 BB FF CD D1 D3 FF C7 C7' + 'C7 FF D5 D5 D5 FF AA AA AA FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8A 8A' + '8A FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' + 'D3 FF BC 68 30 FF BF 5F 1E FF C3 66 27 FF C5 6B' + '2C FF C8 70 30 FF CB 74 34 FF CD 78 38 FF D0 7C' + '3B FF D2 80 3F FF D4 83 42 FF D6 85 44 FF D7 88' + '47 FF D8 8A 48 FF D9 8B 4A FF DA 8C 4B FF DA 8C' + '4B FF D9 8C 4B FF D9 8B 4A FF D8 8A 48 FF D6 87' + '46 FF D5 85 44 FF D4 82 41 FF D1 7E 3E FF D0 7B' + '3B FF CD 77 37 FF CA 73 33 FF C8 6E 2F FF C5 6A' + '2B FF C2 65 26 FF BF 60 21 FF BC 5B 1C FF B7 53' + '15 FF B8 55 18 FF E0 C9 BB FF CE D2 D4 FF C9 C9' + 'C9 FF D6 D6 D6 FF AA AA AA FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 8A 8A' + '8A FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' + 'D3 FF BA 65 2D FF BD 5B 1B FF C0 63 24 FF C2 67' + '28 FF C5 6C 2C FF C8 70 30 FF CA 73 34 FF CD 77' + '37 FF CF 7B 3A FF D1 7D 3D FF D2 80 3F FF D4 83' + '42 FF D5 84 43 FF D6 86 45 FF D6 86 45 FF D6 86' + '45 FF D6 86 45 FF D5 85 44 FF D5 84 43 FF D3 82' + '41 FF D2 80 3F FF D1 7D 3C FF CF 7A 39 FF CD 76' + '36 FF CA 73 33 FF C7 6F 2F FF C5 6A 2B FF C2 66' + '27 FF BF 61 22 FF BC 5D 1E FF B9 58 19 FF B5 50' + '12 FF B6 52 15 FF E0 C9 BB FF D0 D4 D6 FF CB CB' + 'CB FF D7 D7 D7 FF A9 A9 A9 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 89 89' + '89 FF FF FF FF FF FF FF FF FF FF FF FF FF DA D6' + 'D3 FF B8 62 2A FF BA 57 17 FF BE 5E 20 FF C0 63' + '24 FF C3 67 28 FF C6 6B 2C FF C8 6F 2F FF CA 72' + '32 FF CC 76 35 FF CD 78 38 FF CF 7B 3A FF D0 7D' + '3C FF D1 7E 3D FF D2 80 3F FF D2 80 3F FF D2 80' + '3F FF D2 80 3F FF D2 7F 3E FF D1 7E 3E FF CF 7C' + '3C FF CE 7A 3A FF CD 77 37 FF CB 74 34 FF CA 71' + '32 FF C7 6E 2E FF C5 6A 2B FF C3 66 27 FF C0 62' + '23 FF BD 5D 1F FF BB 59 1A FF B7 54 16 FF B3 4D' + '0F FF B5 4E 11 FF E0 C9 BA FF D1 D5 D7 FF CC CC' + 'CC FF D8 D8 D8 FF A8 A8 A8 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 88 88' + '88 FF FF FF FF FF FF FF FF FF FF FF FF FF DA D5' + 'D3 FF B6 5E 27 FF B7 53 13 FF BB 5A 1C FF BD 5F' + '20 FF C0 63 24 FF C3 66 27 FF C5 6A 2A FF C7 6D' + '2E FF C9 71 31 FF CA 73 33 FF CC 75 35 FF CD 77' + '37 FF CE 79 38 FF CF 7A 3A FF CF 7B 3A FF CF 7B' + '3A FF CF 7A 3A FF CE 7A 39 FF CE 78 38 FF CC 77' + '36 FF CB 75 35 FF CA 72 32 FF C8 6F 2F FF C7 6D' + '2E FF C4 69 2A FF C2 65 26 FF C0 62 23 FF BD 5E' + '1F FF BA 59 1B FF B8 55 17 FF B5 51 13 FF B1 4A' + '0B FF B2 4B 0E FF E0 C8 BA FF D2 D6 D8 FF CD CD' + 'CD FF D9 D9 D9 FF A7 A7 A7 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 87 87' + '87 FF FF FF FF FF FF FF FF FF FF FF FF FF D8 D4' + 'D1 FF B4 5A 23 FF B5 4E 0F FF B9 56 18 FF BB 5A' + '1B FF BD 5E 1F FF C0 62 23 FF C2 65 25 FF C3 68' + '29 FF C6 6B 2C FF C7 6D 2E FF C8 70 30 FF C9 71' + '31 FF CA 73 32 FF CB 74 34 FF CB 75 34 FF CB 75' + '34 FF CB 74 34 FF CB 74 33 FF CA 72 32 FF C9 71' + '31 FF C8 6F 2F FF C6 6D 2D FF C5 6A 2A FF C3 67' + '28 FF C1 64 25 FF BE 60 22 FF BD 5D 1E FF BA 59' + '1A FF B8 55 17 FF B6 51 13 FF B3 4C 0F FF AF 46' + '07 FF AF 47 0A FF DF C7 BA FF D4 D8 DB FF CF CF' + 'CF FF DB DB DB FF A6 A6 A6 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 86 86' + '86 FF FF FF FF FF FF FF FF FF FF FF FF FF D6 D1' + 'CE FF B1 55 1E FF B2 4A 0B FF B6 51 13 FF B7 54' + '16 FF BA 59 1A FF BC 5D 1E FF BE 60 20 FF BF 62' + '23 FF C2 65 26 FF C3 67 28 FF C4 69 2A FF C5 6B' + '2B FF C6 6C 2C FF C7 6D 2E FF C7 6E 2E FF C7 6E' + '2E FF C7 6E 2E FF C6 6D 2E FF C6 6C 2C FF C5 6A' + '2B FF C4 69 29 FF C3 67 28 FF C1 64 25 FF BF 62' + '23 FF BE 5F 20 FF BC 5C 1D FF BC 58 19 FF BD 54' + '12 FF BA 4F 0D FF B7 4C 0C FF B0 48 0A FF AC 41' + '03 FF AD 43 07 FF DF C7 BA FF D6 DA DC FF D0 D0' + 'D0 FF DC DC DC FF A5 A5 A5 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 85 85' + '85 FF FF FF FF FF FF FF FF FF FF FF FF FF D4 CF' + 'CC FF AE 51 1A FF B0 45 06 FF B3 4D 0F FF B4 50' + '12 FF B7 54 16 FF B9 58 19 FF BB 5A 1C FF BC 5D' + '1F FF BE 60 21 FF BF 62 23 FF C0 63 24 FF C1 65' + '25 FF C3 66 26 FF C3 68 28 FF C3 68 29 FF C3 68' + '29 FF C3 68 29 FF C3 67 28 FF C3 66 27 FF C1 65' + '25 FF C0 63 23 FF BF 61 22 FF BD 5E 1F FF BC 5D' + '1E FF BA 5A 1B FF BB 56 17 FF A5 46 0C FF 7D 43' + '1F FF 77 46 27 FF 8D 3B 0B FF AE 41 02 FF AB 3E' + '00 FF AC 42 06 FF E0 C8 BA FF D7 DB DD FF D2 D2' + 'D2 FF DD DD DD FF A3 A3 A3 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 84 84' + '84 FF FF FF FF FF FF FF FF FF FF FF FF FF D1 CD' + 'CA FF AB 4D 16 FF AC 40 01 FF B0 48 0B FF B2 4C' + '0E FF B4 4F 11 FF B6 52 14 FF B7 54 16 FF B8 57' + '18 FF BA 58 1A FF BD 5D 1E FF C0 63 24 FF C3 67' + '27 FF C4 69 29 FF C5 6B 2B FF C5 6B 2C FF C6 6C' + '2C FF C6 6C 2C FF C5 6B 2C FF C5 6B 2B FF C4 69' + '29 FF C2 67 28 FF C1 64 25 FF BE 5F 20 FF BA 59' + '1A FF BA 53 13 FF 97 45 12 FF 9B 8E 85 FF C5 CB' + 'CF FF D3 DB E0 FF AC AD AD FF 83 44 21 FF A9 38' + '00 FF AC 42 06 FF E0 C8 BB FF D8 DC DE FF D3 D3' + 'D3 FF DF DF DF FF A3 A3 A3 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 83 83' + '83 FF FF FF FF FF FF FF FF FF FF FF FF FF CF CA' + 'C7 FF A8 4A 14 FF A9 3C 00 FF AD 43 06 FF B0 47' + '09 FF B1 4A 0B FF B2 4B 0E FF B4 4F 11 FF B8 56' + '18 FF BF 62 22 FF C4 6A 2A FF C7 6E 2E FF C8 70' + '2F FF C9 70 30 FF CA 72 32 FF CA 72 32 FF CA 72' + '32 FF CA 72 32 FF CA 72 32 FF C9 71 31 FF C9 70' + '30 FF C8 6F 2F FF C7 6E 2E FF C5 6B 2C FF C3 67' + '28 FF C0 5B 18 FF 8D 5B 3C FF EA F2 F7 FF F6 F5' + 'F6 FF E6 E5 E4 FF CD D2 D4 FF 6C 64 5E FF 91 2D' + '00 FF AF 43 06 FF E1 C9 BB FF D9 DD E0 FF D4 D4' + 'D4 FF E0 E0 E0 FF A2 A2 A2 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 82 82' + '82 FF FF FF FF FF FF FF FF FF FF FF FF FF CD C8' + 'C5 FF A8 4A 13 FF A9 3B 00 FF AA 3E 02 FF AA 3F' + '02 FF AD 44 07 FF B9 57 18 FF C1 64 24 FF C6 6C' + '2C FF C9 70 30 FF C9 72 32 FF CA 74 34 FF CC 75' + '35 FF CC 76 36 FF CD 78 37 FF CD 78 38 FF CE 79' + '38 FF CE 79 38 FF CD 78 38 FF CD 77 37 FF CC 76' + '36 FF CB 75 35 FF CA 73 33 FF C9 71 31 FF C8 6F' + '30 FF C3 66 24 FF 8C 6B 54 FF DC E2 E6 FF D1 CE' + 'CC FF B1 A5 9F FF E0 E2 E4 FF 7C 7E 80 FF 74 25' + '00 FF B2 44 05 FF E1 C9 BB FF DB DF E1 FF D5 D5' + 'D5 FF E1 E1 E1 FF A1 A1 A1 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 81 81' + '81 FF FF FF FF FF FF FF FF FF FF FF FF FF CB C6' + 'C3 FF A8 49 13 FF A9 3B 00 FF A8 3C 00 FF AE 46' + '09 FF BC 5C 1E FF C7 6E 2E FF C9 70 30 FF CA 72' + '32 FF CB 75 35 FF CD 77 37 FF CE 7A 3A FF CF 7B' + '3B FF D0 7D 3C FF D1 7E 3E FF D1 7F 3E FF D2 7F' + '3E FF D2 7F 3E FF D1 7E 3E FF D1 7E 3D FF D0 7C' + '3C FF CF 7B 3B FF CE 79 39 FF CC 77 36 FF CC 75' + '34 FF CB 6F 2C FF 89 60 42 FF CA D0 D5 FF F2 F2' + 'F2 FF F2 F1 F0 FF FF FF FF FF 7C 72 6D FF 89 29' + '00 FF AF 43 06 FF E2 CA BC FF DD E1 E3 FF D7 D7' + 'D7 FF E2 E2 E2 FF A0 A0 A0 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 80 80' + '80 FF FF FF FF FF FF FF FF FF FF FF FF FF C9 C4' + 'C1 FF A7 48 13 FF A7 39 00 FF B0 49 0B FF C3 68' + '28 FF C7 6F 2F FF C9 71 31 FF CA 74 34 FF CC 77' + '37 FF CE 7A 3A FF D0 7C 3C FF D1 7F 3E FF D2 81' + '40 FF D4 82 41 FF D5 84 43 FF D5 85 44 FF D5 85' + '44 FF D5 85 44 FF D5 84 43 FF D4 84 43 FF D3 82' + '41 FF D2 81 40 FF D1 7F 3E FF CF 7C 3B FF CE 7A' + '39 FF D1 79 37 FF A6 5D 27 FF 6A 65 62 FF E0 E6' + 'EB FF F5 FA FE FF A6 AE B3 FF 79 3C 18 FF AC 39' + '00 FF AC 42 06 FF E2 CA BC FF DE E2 E4 FF D8 D8' + 'D8 FF E4 E4 E4 FF 9E 9E 9E FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7E 7E' + '7E FF FF FF FF FF FF FF FF FF FF FF FF FF C7 C2' + 'C0 FF A5 46 11 FF AE 42 05 FF C2 67 27 FF C7 6E' + '2F FF C9 71 31 FF CB 75 35 FF CD 78 38 FF D0 7C' + '3B FF D2 7F 3F FF D3 82 41 FF D4 84 43 FF D6 86' + '46 FF D7 88 47 FF D8 89 48 FF D8 8A 49 FF D8 8B' + '49 FF D8 8B 49 FF D8 8A 49 FF D8 89 48 FF D6 87' + '47 FF D5 86 45 FF D4 84 43 FF D2 81 3F FF D1 7F' + '3D FF CF 7B 3B FF D2 79 37 FF 9C 56 23 FF 7A 59' + '40 FF 81 63 4D FF 74 41 1E FF B8 5B 1D FF B2 48' + '09 FF AB 41 04 FF E2 CA BC FF DF E3 E5 FF DA DA' + 'DA FF E5 E5 E5 FF 9E 9E 9E FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7D 7D' + '7D FF FF FF FF FF FF FF FF FF FF FF FF FF C5 BF' + 'BD FF A7 48 12 FF BE 5D 1C FF C8 6F 2F FF C9 71' + '31 FF CC 75 35 FF CF 79 39 FF D0 7D 3D FF D3 81' + '40 FF D5 84 43 FF D7 87 46 FF D8 8A 49 FF DA 8C' + '4B FF DB 8E 4C FF DC 90 4E FF DC 91 4F FF DC 91' + '4F FF DC 91 4F FF DC 91 4F FF DB 8F 4D FF DA 8E' + '4C FF D9 8C 4A FF D8 89 48 FF D6 86 45 FF D5 83' + '42 FF D3 81 40 FF CF 7A 38 FF D0 76 32 FF C5 6A' + '26 FF BD 61 1E FF C8 66 22 FF C8 68 27 FF BE 5D' + '1E FF AC 43 07 FF E2 CA BC FF E0 E5 E7 FF DC DC' + 'DC FF E6 E6 E6 FF 9D 9D 9D FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7B 7B' + '7B FF FF FF FF FF FF FF FF FF FF FF FF FF C1 BC' + 'B9 FF B2 5B 24 FF C7 6C 2A FF C9 70 31 FF CB 75' + '35 FF CE 79 39 FF D1 7E 3D FF D2 82 41 FF D5 85' + '44 FF D8 89 48 FF DA 8C 4B FF DC 8F 4D FF DD 92' + '50 FF DE 94 52 FF DF 96 54 FF E0 97 55 FF E0 97' + '55 FF E0 97 55 FF E0 97 54 FF DF 95 53 FF DE 94' + '52 FF DD 91 50 FF DA 8E 4D FF D9 8B 4A FF D8 88' + '47 FF D6 83 40 FF B2 7D 53 FF 96 7C 69 FF A3 86' + '70 FF AD 8E 79 FF 9A 8A 71 FF 8D 62 37 FF C3 63' + '22 FF B7 54 16 FF E2 CA BC FF E3 E6 E8 FF DD DD' + 'DD FF E7 E7 E7 FF 9B 9B 9B FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 7A 7A' + '7A FF FF FF FF FF FF FF FF FF FF FF FF FF C0 BA' + 'B8 FF B8 64 2D FF C9 6E 2D FF CA 74 33 FF CD 78' + '38 FF D0 7D 3C FF D3 81 40 FF D5 85 44 FF D8 89' + '48 FF DB 8D 4C FF DD 91 4F FF DF 94 52 FF E0 97' + '55 FF E1 99 57 FF E2 9B 58 FF E3 9C 5A FF E4 9D' + '5A FF E4 9D 5A FF E3 9C 5A FF E2 9B 59 FF E1 99' + '57 FF E0 96 55 FF DE 93 51 FF DC 90 4E FF DB 8D' + '4B FF D2 80 3C FF B2 96 7F FF 96 9F A6 FF A4 A8' + 'AB FF 86 8A 8E FF A9 B9 BC FF 86 78 65 FF B9 5C' + '1C FF C1 61 23 FF E3 CB BD FF E2 E6 E8 FF DE DE' + 'DE FF E8 E8 E8 FF 9A 9A 9A FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 78 78' + '78 FF FF FF FF FF FF FF FF FF FF FF FF FF BE B8' + 'B6 FF BA 68 30 FF CB 71 2F FF CD 76 36 FF CF 7B' + '3B FF D2 80 3F FF D5 85 44 FF D7 89 48 FF DA 8E' + '4C FF DD 92 50 FF DF 96 54 FF E1 99 57 FF E3 9C' + '5A FF E5 9E 5C FF E6 A1 5E FF E7 A2 60 FF E7 A3' + '60 FF E7 A3 60 FF E7 A2 5F FF E6 A1 5E FF E4 9E' + '5B FF E3 9C 59 FF E1 98 56 FF DE 95 53 FF DD 92' + '4F FF D5 85 41 FF A9 8A 71 FF C4 C9 CD FF DC DC' + 'DC FF D7 D7 D7 FF C5 C8 CC FF 90 75 64 FF BB 5F' + '1E FF C5 67 29 FF E7 D0 C2 FF EA EE F0 FF E5 E5' + 'E5 FF EB EB EB FF 99 99 99 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 78 78' + '78 FF FF FF FF FF FF FF FF FF FF FF FF FF BA B5' + 'B2 FF B9 67 2F FF CD 74 32 FF CE 79 39 FF D1 7E' + '3E FF D4 83 42 FF D7 88 47 FF DA 8D 4B FF DD 91' + '4F FF E0 96 54 FF E1 9A 57 FF E4 9D 5B FF E6 A1' + '5E FF E8 A4 61 FF E9 A6 63 FF EA A8 65 FF EB A9' + '65 FF EB A9 65 FF EA A7 64 FF E9 A6 63 FF E7 A4' + '60 FF E6 A0 5E FF E4 9D 5A FF E1 99 57 FF DF 94' + '53 FF DF 8F 48 FF AF 89 69 FF C7 CC D0 FF D6 D6' + 'D6 FF D3 D3 D3 FF C8 CD D2 FF A0 7B 5F FF C6 68' + '24 FF C1 65 26 FF E9 D2 C4 FF F7 FB FD FF F4 F4' + 'F4 FF F6 F6 F6 FF 98 98 98 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 76 76' + '76 FF FF FF FF FF FF FF FF FF FF FF FF FF B8 B2' + 'B0 FF B3 5C 25 FF CE 77 35 FF CF 7B 3B FF D2 80' + '40 FF D5 85 44 FF D9 8A 49 FF DB 8F 4D FF DF 95' + '53 FF E2 99 57 FF E3 9E 5B FF E6 A2 5F FF E9 A6' + '63 FF EB A9 65 FF ED AC 68 FF EE AE 6A FF EF AF' + '6B FF EF AF 6B FF EE AD 6A FF ED AB 68 FF EB A8' + '66 FF E8 A5 62 FF E6 A1 5E FF E3 9D 5A FF E1 98' + '56 FF E2 94 4E FF B4 87 5F FF D1 D5 D8 FF E2 E3' + 'E4 FF E0 E1 E2 FF CE D3 D8 FF AA 79 55 FF CD 6F' + '2A FF B9 58 1A FF E8 CF C2 FF F9 FD FF FF F7 F7' + 'F7 FF F8 F8 F8 FF 97 97 97 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 75 75' + '75 FF FF FF FF FF FF FF FF FF FF FF FF FF B7 B1' + 'AF FF A5 47 10 FF C7 6A 28 FF D2 7F 3E FF D3 83' + '42 FF D7 88 47 FF DA 8D 4C FF DD 92 50 FF E0 98' + '56 FF E4 9C 5A FF E6 A1 5F FF E9 A6 63 FF EC AB' + '67 FF EE AE 6B FF F0 B1 6E FF F2 B4 71 FF F3 B5' + '72 FF F3 B5 71 FF F2 B4 70 FF F0 B1 6E FF ED AD' + '6A FF EB A9 66 FF E8 A5 62 FF E5 A0 5E FF E3 9B' + '59 FF E5 97 54 FF B9 81 50 FF A1 9D 9B FF BD BC' + 'BA FF BD BC BA FF A3 A1 A0 FF AD 70 42 FF C9 69' + '26 FF AD 43 06 FF E9 D0 C3 FF FB FE FF FF F8 F8' + 'F8 FF F9 F9 F9 FF 95 95 95 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 74 74' + '74 FF FF FF FF FF FF FF FF FF FF FF FF FF B2 AD' + 'AB FF 9C 3C 06 FF AE 45 06 FF CF 79 35 FF D6 7F' + '3A FF D9 85 3F FF DC 8A 44 FF DF 90 4A FF E3 96' + '4F FF E7 9C 54 FF EA A1 5A FF ED A7 5F FF F1 AC' + '64 FF F3 B1 68 FF F6 B5 6D FF F8 B9 70 FF FA BB' + '72 FF F9 BA 72 FF F8 B8 6F FF F5 B5 6C FF F2 AF' + '68 FF F0 AA 63 FF ED A6 5D FF E9 A0 58 FF E6 9A' + '53 FF E3 95 4E FF DE 8E 48 FF C2 79 3B FF B7 70' + '36 FF B4 6B 31 FF B6 69 2C FF C9 71 2F FF B1 4C' + '0D FF A5 39 00 FF E9 D1 C3 FF FC FF FF FF FA FA' + 'FA FF FB FB FB FF 94 94 94 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F0 00 00 00 FF 73 73' + '73 FF FF FF FF FF FF FF FF FF FF FF FF FF C4 C3' + 'C2 FF AE 93 84 FF B1 93 83 FF C2 A0 86 FF CE A5' + '83 FF CE A7 87 FF D0 AA 89 FF D2 AD 8C FF D3 B0' + '8E FF D5 B2 91 FF D7 B5 93 FF D8 B8 96 FF DA BA' + '98 FF DB BC 9B FF DD BF 9D FF DE C1 9F FF DE C2' + 'A0 FF DE C2 A0 FF DE C0 9E FF DC BE 9C FF DB BC' + '9A FF DA B9 98 FF D8 B7 95 FF D6 B4 92 FF D4 B2' + '90 FF D2 AF 8E FF D2 AC 8B FF D3 AA 88 FF D2 A8' + '85 FF D0 A5 82 FF CE A2 7F FF C1 9E 84 FF B0 92' + '82 FF B2 94 83 FF EC E5 E1 FF FD FE FE FF FC FC' + 'FC FF FC FC FC FF 94 94 94 FF 00 00 00 FF 00 00' + '00 F7 00 00 00 37 00 00 00 F4 00 00 00 FF 72 72' + '72 FF FF FF FF FF FF FF FF FF FF FF FF FF FE FE' + 'FE FF FD FF FF FF FD FF FF FF FA FF FF FF F9 FF' + 'FF FF F9 FE FF FF F9 FE FF FF F9 FE FF FF F8 FD' + 'FF FF F8 FD FF FF F8 FD FF FF F8 FC FF FF F7 FC' + 'FF FF F7 FC FF FF F7 FB FF FF F7 FB FF FF F7 FB' + 'FF FF F7 FB FF FF F7 FB FF FF F7 FB FF FF F7 FC' + 'FF FF F7 FC FF FF F8 FC FF FF F7 FC FF FF F7 FC' + 'FF FF F7 FC FF FF F8 FD FF FF F7 FD FF FF F7 FD' + 'FF FF F7 FD FF FF F7 FD FF FF F8 FD FF FF FA FF' + 'FF FF FA FF FF FF FC FD FD FF FB FB FB FF FD FD' + 'FD FF FB FB FB FF 93 93 93 FF 00 00 00 FF 00 00' + '00 FA 00 00 00 37 00 00 00 DD 00 00 00 FF 4B 4B' + '4B FF F5 F5 F5 FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FE FE FE FF FE FE FE FF FD FD FD FF FF FF' + 'FF FF F0 F0 F0 FF 6D 6D 6D FF 00 00 00 FF 00 00' + '00 E7 00 00 00 27 00 00 00 7A 00 00 00 FF 0E 0E' + '0E FF 9A 9A 9A FF FD FD FD FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF F8 F8' + 'F8 FF A4 A4 A4 FF 1B 1B 1B FF 00 00 00 FF 00 00' + '00 9B 00 00 00 04 00 00 00 0F 00 00 00 D8 00 00' + '00 FF 14 14 14 FF 6E 6E 6E FF AC AC AC FF B9 B9' + 'B9 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' + 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' + 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' + 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' + 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8' + 'B8 FF B8 B8 B8 FF B8 B8 B8 FF B8 B8 B8 FF B7 B7' + 'B7 FF B7 B7 B7 FF B7 B7 B7 FF B6 B6 B6 FF B6 B6' + 'B6 FF B6 B6 B6 FF B5 B5 B5 FF B5 B5 B5 FF B5 B5' + 'B5 FF B4 B4 B4 FF B5 B5 B5 FF AB AB AB FF 76 76' + '76 FF 1D 1D 1D FF 00 00 00 FF 00 00 00 FA 00 00' + '00 3C 00 00 00 00 00 00 00 00 00 00 00 52 00 00' + '00 F6 00 00 00 FF 00 00 00 FF 0C 0C 0C FF 16 16' + '16 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 15 15 15 FF 15 15 15 FF 15 15' + '15 FF 15 15 15 FF 16 16 16 FF 10 10 10 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 6F 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 39 00 00 00 B0 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 FF 00 00 00 FF 00 00 00 FF 00 00' + '00 FF 00 00 00 C1 00 00 00 51 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 49 00 00 00 80 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 84 00 00' + '00 84 00 00 00 84 00 00 00 84 00 00 00 82 00 00' + '00 57 00 00 00 0B 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 F0 00 00 00 00 0F 00 00 C0 00' + '00 00 00 03 00 00 80 00 00 00 00 01 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 01 00 00 80 00' + '00 00 00 03 00 00 C0 00 00 00 00 07 00 00 F0 00' + '00 00 00 0F 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 28 00 00 00 30 00 00 00 60 00' + '00 00 01 00 04 00 00 00 00 00 80 04 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 80 00 00 00 00 80 00 00 80 80 00 00 00 00' + '80 00 80 00 80 00 00 80 80 00 C0 C0 C0 00 80 80' + '80 00 FF 00 00 00 00 FF 00 00 FF FF 00 00 00 00' + 'FF 00 FF 00 FF 00 00 FF FF 00 FF FF FF 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 88 88 88 88 88 88 88 88' + '88 88 88 88 88 88 88 88 88 88 88 80 00 00 00 08' + 'FF FF FF FF FF FF FF FF FF FF FF FF 77 77 77 77' + '77 77 77 F8 00 00 00 8F FF FF FF FF FF FF FF FF' + 'FF 77 77 77 77 77 77 77 77 77 77 7F 80 00 00 8F' + 'FF FF FF FF FF FF FF FF FF 77 77 77 77 77 77 77' + '77 77 77 77 70 00 00 8F FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF 77 77 70 00 00 8F' + 'FF F8 88 87 77 77 77 77 77 77 77 77 77 77 77 88' + '88 88 77 77 70 00 00 8F FF 73 33 33 33 38 88 88' + '88 88 88 88 83 33 33 33 33 33 77 77 70 00 00 8F' + 'FF 73 33 33 33 38 88 88 88 88 88 88 88 33 33 33' + '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 88 88' + '88 88 88 88 83 33 33 33 33 33 77 77 70 00 00 8F' + 'FF 73 33 33 33 33 33 88 88 88 88 83 33 33 33 33' + '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' + '33 33 33 33 33 33 33 33 33 33 77 77 70 00 00 8F' + 'FF 73 33 33 33 33 33 33 33 33 33 33 33 33 33 33' + '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' + '33 33 33 33 33 33 33 33 33 33 77 77 70 00 00 8F' + 'FF 73 33 33 33 33 33 33 33 33 33 33 33 33 33 33' + '33 33 77 77 70 00 00 8F FF 73 33 33 33 33 33 33' + '33 33 33 33 33 33 33 33 13 13 77 77 70 00 00 8F' + 'FF 73 13 33 33 33 33 33 33 33 33 33 33 33 38 77' + '73 13 77 77 70 00 00 8F FF 73 13 33 33 33 33 33' + '33 33 33 33 33 33 3F FF 78 13 77 7F 70 00 00 8F' + 'FF 73 11 13 33 33 33 33 33 33 33 33 33 33 8F 77' + 'F8 13 77 7F 70 00 00 8F FF 73 11 33 33 33 33 33' + '33 33 33 33 33 33 87 FF F8 13 7F 7F 70 00 00 8F' + 'FF 73 13 33 33 33 33 38 88 88 88 83 33 33 38 FF' + '71 13 7F 7F 80 00 00 8F FF 73 33 33 33 33 88 88' + '88 88 88 88 83 33 33 38 33 33 7F 7F 80 00 00 8F' + 'FF 73 33 33 33 38 88 88 88 88 88 88 88 83 33 33' + '33 33 7F 7F 80 00 00 8F FF 73 33 33 38 88 88 88' + '88 88 88 88 88 83 88 88 83 33 7F 7F 80 00 00 8F' + 'FF 73 33 33 38 88 88 88 88 88 88 88 88 83 88 78' + '78 33 7F 7F 80 00 00 8F FF 73 33 33 88 88 88 88' + '77 77 77 88 88 88 87 77 78 33 7F FF 80 00 00 8F' + 'FF 73 33 38 88 88 88 77 77 77 77 77 88 88 87 77' + '78 33 7F FF 80 00 00 8F FF 73 33 38 88 88 87 77' + '77 77 77 77 78 88 87 FF 78 33 7F FF 80 00 00 8F' + 'FF 73 33 88 88 88 77 77 77 77 77 77 77 88 88 77' + '78 33 7F FF 80 00 00 8F FF 71 33 33 88 88 77 77' + '77 77 77 77 77 88 83 33 33 31 7F FF 80 00 00 8F' + 'FF 78 87 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 88 FF FF 80 00 00 8F FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF 80 00 00 8F' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF 80 00 00 08 FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF F7 00 00 00 00' + '87 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77' + '77 77 77 80 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 E0 00 00 00 00 0F 00 00 C0 00' + '00 00 00 07 00 00 80 00 00 00 00 03 00 00 80 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 01 00 00 00 00 00 00 00 01 00 00 80 00' + '00 00 00 03 00 00 C0 00 00 00 00 03 00 00 E0 00' + '00 00 00 0F 00 00 F8 00 00 00 00 3F 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00 FF FF' + 'FF FF FF FF 00 00 FF FF FF FF FF FF 00 00' +} */ + + + + +/*--------------------- END FIXME ------------------------*/ + +/* + * Everything that does not depend on language, + * like textless bitmaps etc, go into the + * neutral language. This will prevent them from + * being duplicated for each language. + */ +#include "shell32_xx.rc" + +/* + * Everything specific to any language goes + * in one of the specific files. + * Note that you can and may override resources + * which also have a neutral version. This is to + * get localized bitmaps for example. + */ +#include "shell32_Ca.rc" +#include "shell32_Cn.rc" +#include "shell32_Cs.rc" +#include "shell32_Da.rc" +#include "shell32_De.rc" +#include "shell32_En.rc" +#include "shell32_Eo.rc" +#include "shell32_Es.rc" +#include "shell32_Fi.rc" +#include "shell32_Fr.rc" +#include "shell32_Hu.rc" +#include "shell32_It.rc" +#include "shell32_Ja.rc" +#include "shell32_Ko.rc" +#include "shell32_Nl.rc" +#include "shell32_No.rc" +#include "shell32_Pl.rc" +#include "shell32_Pt.rc" +#include "shell32_Ru.rc" +#include "shell32_Si.rc" +#include "shell32_Sk.rc" +#include "shell32_Sv.rc" +#include "shell32_Uk.rc" +#include "shell32_Wa.rc" +#include "shell32_Zh.rc" diff --git a/reactos/lib/shell32/shresdef.h b/reactos/lib/shell32/shresdef.h index c3c454a4806..d7419cc70f7 100644 --- a/reactos/lib/shell32/shresdef.h +++ b/reactos/lib/shell32/shresdef.h @@ -1,92 +1,92 @@ -/* - * Copyright 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_SHELL_RES_H -#define __WINE_SHELL_RES_H - -/* - columntitles for the shellview -*/ -#define IDS_SHV_COLUMN1 7 -#define IDS_SHV_COLUMN2 8 -#define IDS_SHV_COLUMN3 9 -#define IDS_SHV_COLUMN4 10 -#define IDS_SHV_COLUMN5 11 -#define IDS_SHV_COLUMN6 12 -#define IDS_SHV_COLUMN7 13 -#define IDS_SHV_COLUMN8 14 -#define IDS_SHV_COLUMN9 15 - -#define IDS_DESKTOP 20 -#define IDS_MYCOMPUTER 21 - -#define IDS_SELECT 22 -#define IDS_OPEN 23 -#define IDS_VIEW_LARGE 24 -#define IDS_VIEW_SMALL 25 -#define IDS_VIEW_LIST 26 -#define IDS_VIEW_DETAILS 27 - -#define IDS_CREATEFOLDER_DENIED 30 -#define IDS_CREATEFOLDER_CAPTION 31 -#define IDS_DELETEITEM_CAPTION 32 -#define IDS_DELETEFOLDER_CAPTION 33 -#define IDS_DELETEITEM_TEXT 34 -#define IDS_DELETEMULTIPLE_TEXT 35 -#define IDS_OVERWRITEFILE_CAPTION 36 -#define IDS_OVERWRITEFILE_TEXT 37 - -#define IDS_RESTART_TITLE 40 -#define IDS_RESTART_PROMPT 41 -#define IDS_SHUTDOWN_TITLE 42 -#define IDS_SHUTDOWN_PROMPT 43 - -#define IDS_PROGRAMS 45 -#define IDS_PERSONAL 46 -#define IDS_FAVORITES 47 -#define IDS_STARTUP 48 -#define IDS_RECENT 49 -#define IDS_SENDTO 50 -#define IDS_STARTMENU 51 -#define IDS_MYMUSIC 52 -#define IDS_MYVIDEO 53 -#define IDS_DESKTOPDIRECTORY 54 -#define IDS_NETHOOD 55 -#define IDS_TEMPLATES 56 -#define IDS_APPDATA 57 -#define IDS_PRINTHOOD 58 -#define IDS_LOCAL_APPDATA 59 -#define IDS_INTERNET_CACHE 60 -#define IDS_COOKIES 61 -#define IDS_HISTORY 62 -#define IDS_PROGRAM_FILES 63 -#define IDS_MYPICTURES 64 -#define IDS_PROGRAM_FILES_COMMON 65 -#define IDS_COMMON_DOCUMENTS 66 -#define IDS_ADMINTOOLS 67 -#define IDS_COMMON_MUSIC 68 -#define IDS_COMMON_PICTURES 69 -#define IDS_COMMON_VIDEO 70 -#define IDS_CDBURN_AREA 71 - -/* browse for folder dialog box */ -#define IDD_STATUS 0x3743 -#define IDD_TITLE 0x3742 -#define IDD_TREEVIEW 0x3741 - -#endif +/* + * Copyright 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHELL_RES_H +#define __WINE_SHELL_RES_H + +/* + columntitles for the shellview +*/ +#define IDS_SHV_COLUMN1 7 +#define IDS_SHV_COLUMN2 8 +#define IDS_SHV_COLUMN3 9 +#define IDS_SHV_COLUMN4 10 +#define IDS_SHV_COLUMN5 11 +#define IDS_SHV_COLUMN6 12 +#define IDS_SHV_COLUMN7 13 +#define IDS_SHV_COLUMN8 14 +#define IDS_SHV_COLUMN9 15 + +#define IDS_DESKTOP 20 +#define IDS_MYCOMPUTER 21 + +#define IDS_SELECT 22 +#define IDS_OPEN 23 +#define IDS_VIEW_LARGE 24 +#define IDS_VIEW_SMALL 25 +#define IDS_VIEW_LIST 26 +#define IDS_VIEW_DETAILS 27 + +#define IDS_CREATEFOLDER_DENIED 30 +#define IDS_CREATEFOLDER_CAPTION 31 +#define IDS_DELETEITEM_CAPTION 32 +#define IDS_DELETEFOLDER_CAPTION 33 +#define IDS_DELETEITEM_TEXT 34 +#define IDS_DELETEMULTIPLE_TEXT 35 +#define IDS_OVERWRITEFILE_CAPTION 36 +#define IDS_OVERWRITEFILE_TEXT 37 + +#define IDS_RESTART_TITLE 40 +#define IDS_RESTART_PROMPT 41 +#define IDS_SHUTDOWN_TITLE 42 +#define IDS_SHUTDOWN_PROMPT 43 + +#define IDS_PROGRAMS 45 +#define IDS_PERSONAL 46 +#define IDS_FAVORITES 47 +#define IDS_STARTUP 48 +#define IDS_RECENT 49 +#define IDS_SENDTO 50 +#define IDS_STARTMENU 51 +#define IDS_MYMUSIC 52 +#define IDS_MYVIDEO 53 +#define IDS_DESKTOPDIRECTORY 54 +#define IDS_NETHOOD 55 +#define IDS_TEMPLATES 56 +#define IDS_APPDATA 57 +#define IDS_PRINTHOOD 58 +#define IDS_LOCAL_APPDATA 59 +#define IDS_INTERNET_CACHE 60 +#define IDS_COOKIES 61 +#define IDS_HISTORY 62 +#define IDS_PROGRAM_FILES 63 +#define IDS_MYPICTURES 64 +#define IDS_PROGRAM_FILES_COMMON 65 +#define IDS_COMMON_DOCUMENTS 66 +#define IDS_ADMINTOOLS 67 +#define IDS_COMMON_MUSIC 68 +#define IDS_COMMON_PICTURES 69 +#define IDS_COMMON_VIDEO 70 +#define IDS_CDBURN_AREA 71 + +/* browse for folder dialog box */ +#define IDD_STATUS 0x3743 +#define IDD_TITLE 0x3742 +#define IDD_TREEVIEW 0x3741 + +#endif diff --git a/reactos/lib/shell32/shv_bg_cmenu.c b/reactos/lib/shell32/shv_bg_cmenu.c index 40d3afd84a2..9dd5dc6cb90 100644 --- a/reactos/lib/shell32/shv_bg_cmenu.c +++ b/reactos/lib/shell32/shv_bg_cmenu.c @@ -1,445 +1,445 @@ -/* - * IContextMenu - * ShellView Background Context Menu (shv_bg_cm) - * - * Copyright 1999 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "wine/debug.h" - -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "shlguid.h" -#include "shlobj.h" - -#include "shell32_main.h" -#include "shellfolder.h" -#include "undocshell.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************************************************************** -* IContextMenu Implementation -*/ -typedef struct -{ - IContextMenu2Vtbl *lpVtbl; - IShellFolder* pSFParent; - DWORD ref; -} BgCmImpl; - - -static struct IContextMenu2Vtbl cmvt; - -/************************************************************************** -* ISVBgCm_Constructor() -*/ -IContextMenu2 *ISvBgCm_Constructor(IShellFolder* pSFParent) -{ - BgCmImpl* cm; - - cm = (BgCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl)); - cm->lpVtbl = &cmvt; - cm->ref = 1; - cm->pSFParent = pSFParent; - if(pSFParent) IShellFolder_AddRef(pSFParent); - - TRACE("(%p)->()\n",cm); - return (IContextMenu2*)cm; -} - -/************************************************************************** -* ISVBgCm_fnQueryInterface -*/ -static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IContextMenu) || - IsEqualIID(riid, &IID_IContextMenu2)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ - { - FIXME("-- LPSHELLEXTINIT pointer requested\n"); - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* ISVBgCm_fnAddRef -*/ -static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This, This->ref); - - return ++(This->ref); -} - -/************************************************************************** -* ISVBgCm_fnRelease -*/ -static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IContextMenu(%p)\n",This); - - if(This->pSFParent) - IShellFolder_Release(This->pSFParent); - - HeapFree(GetProcessHeap(),0,This); - return 0; - } - - return This->ref; -} - -/************************************************************************** -* ISVBgCm_fnQueryContextMenu() -*/ - -static HRESULT WINAPI ISVBgCm_fnQueryContextMenu( - IContextMenu2 *iface, - HMENU hMenu, - UINT indexMenu, - UINT idCmdFirst, - UINT idCmdLast, - UINT uFlags) -{ - HMENU hMyMenu; - UINT idMax; - HRESULT hr; - - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", - This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - - - hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002"); - if (uFlags & CMF_DEFAULTONLY) - { - HMENU ourMenu = GetSubMenu(hMyMenu,0); - UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED); - UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED); - if (newDef != oldDef) - SetMenuDefaultItem(hMenu,newDef,TRUE); - if (newDef!=0xFFFFFFFF) - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1); - else - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); - } - else - { - idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu, - idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1); - } - DestroyMenu(hMyMenu); - - TRACE("(%p)->returning 0x%lx\n",This,hr); - return hr; -} - -/************************************************************************** -* DoNewFolder -*/ -static void DoNewFolder( - IContextMenu2 *iface, - IShellView *psv) -{ - BgCmImpl *This = (BgCmImpl *)iface; - ISFHelper * psfhlp; - char szName[MAX_PATH]; - - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp); - if (psfhlp) - { - LPITEMIDLIST pidl; - ISFHelper_GetUniqueName(psfhlp, szName, MAX_PATH); - ISFHelper_AddFolder(psfhlp, 0, szName, &pidl); - - if(psv) - { - /* if we are in a shellview do labeledit */ - IShellView_SelectItem(psv, - pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE - |SVSI_FOCUSED|SVSI_SELECT)); - } - SHFree(pidl); - - ISFHelper_Release(psfhlp); - } -} - -/************************************************************************** -* DoPaste -*/ -static BOOL DoPaste( - IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - BOOL bSuccess = FALSE; - IDataObject * pda; - - TRACE("\n"); - - if(SUCCEEDED(OleGetClipboard(&pda))) - { - STGMEDIUM medium; - FORMATETC formatetc; - - TRACE("pda=%p\n", pda); - - /* Set the FORMATETC structure*/ - InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); - - /* Get the pidls from IDataObject */ - if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) - { - LPITEMIDLIST * apidl; - LPITEMIDLIST pidl; - IShellFolder *psfFrom = NULL, *psfDesktop; - - LPIDA lpcida = GlobalLock(medium.u.hGlobal); - TRACE("cida=%p\n", lpcida); - - apidl = _ILCopyCidaToaPidl(&pidl, lpcida); - - /* bind to the source shellfolder */ - SHGetDesktopFolder(&psfDesktop); - if(psfDesktop) - { - IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); - IShellFolder_Release(psfDesktop); - } - - if (psfFrom) - { - /* get source and destination shellfolder */ - ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); - IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc); - - /* do the copy/move */ - if (psfhlpdst && psfhlpsrc) - { - ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); - /* FIXME handle move - ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); - */ - } - if(psfhlpdst) ISFHelper_Release(psfhlpdst); - if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); - IShellFolder_Release(psfFrom); - } - - _ILFreeaPidl(apidl, lpcida->cidl); - SHFree(pidl); - - /* release the medium*/ - ReleaseStgMedium(&medium); - } - IDataObject_Release(pda); - } -#if 0 - HGLOBAL hMem; - - OpenClipboard(NULL); - hMem = GetClipboardData(CF_HDROP); - - if(hMem) - { - char * pDropFiles = (char *)GlobalLock(hMem); - if(pDropFiles) - { - int len, offset = sizeof(DROPFILESTRUCT); - - while( pDropFiles[offset] != 0) - { - len = strlen(pDropFiles + offset); - TRACE("%s\n", pDropFiles + offset); - offset += len+1; - } - } - GlobalUnlock(hMem); - } - CloseClipboard(); -#endif - return bSuccess; -} - -/************************************************************************** -* ISVBgCm_fnInvokeCommand() -*/ -static HRESULT WINAPI ISVBgCm_fnInvokeCommand( - IContextMenu2 *iface, - LPCMINVOKECOMMANDINFO lpcmi) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV = NULL; - HWND hWndSV = 0; - - TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); - - /* get the active IShellView */ - if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - IShellView_GetWindow(lpSV, &hWndSV); - } - } - - if(HIWORD(lpcmi->lpVerb)) - { - TRACE("%s\n",lpcmi->lpVerb); - - if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA)) - { - DoNewFolder(iface, lpSV); - } - else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA)) - { - if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 ); - } - else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA)) - { - if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 ); - } - else - { - FIXME("please report: unknown verb %s\n",lpcmi->lpVerb); - } - } - else - { - switch(LOWORD(lpcmi->lpVerb)) - { - case FCIDM_SHVIEW_NEWFOLDER: - DoNewFolder(iface, lpSV); - break; - case FCIDM_SHVIEW_INSERT: - DoPaste(iface); - break; - default: - /* if it's a id just pass it to the parent shv */ - SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 ); - break; - } - } - - if (lpSV) - IShellView_Release(lpSV); /* QueryActiveShellView does AddRef*/ - - return NOERROR; -} - -/************************************************************************** - * ISVBgCm_fnGetCommandString() - * - */ -static HRESULT WINAPI ISVBgCm_fnGetCommandString( - IContextMenu2 *iface, - UINT idCommand, - UINT uFlags, - UINT* lpReserved, - LPSTR lpszName, - UINT uMaxNameLen) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); - - /* test the existence of the menu items, the file dialog enables - the buttons according to this */ - if (uFlags == GCS_VALIDATEA) - { - if(HIWORD(idCommand)) - { - if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) || - !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) || - !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA)) - { - return NOERROR; - } - } - } - - FIXME("unknown command string\n"); - return E_FAIL; -} - -/************************************************************************** -* ISVBgCm_fnHandleMenuMsg() -*/ -static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg( - IContextMenu2 *iface, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - FIXME("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam); - - return E_NOTIMPL; -} - -/************************************************************************** -* IContextMenu2 VTable -* -*/ -static struct IContextMenu2Vtbl cmvt = -{ - ISVBgCm_fnQueryInterface, - ISVBgCm_fnAddRef, - ISVBgCm_fnRelease, - ISVBgCm_fnQueryContextMenu, - ISVBgCm_fnInvokeCommand, - ISVBgCm_fnGetCommandString, - ISVBgCm_fnHandleMenuMsg -}; +/* + * IContextMenu + * ShellView Background Context Menu (shv_bg_cm) + * + * Copyright 1999 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "wine/debug.h" + +#include "windef.h" +#include "wingdi.h" +#include "pidl.h" +#include "shlguid.h" +#include "shlobj.h" + +#include "shell32_main.h" +#include "shellfolder.h" +#include "undocshell.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/************************************************************************** +* IContextMenu Implementation +*/ +typedef struct +{ + IContextMenu2Vtbl *lpVtbl; + IShellFolder* pSFParent; + DWORD ref; +} BgCmImpl; + + +static struct IContextMenu2Vtbl cmvt; + +/************************************************************************** +* ISVBgCm_Constructor() +*/ +IContextMenu2 *ISvBgCm_Constructor(IShellFolder* pSFParent) +{ + BgCmImpl* cm; + + cm = (BgCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl)); + cm->lpVtbl = &cmvt; + cm->ref = 1; + cm->pSFParent = pSFParent; + if(pSFParent) IShellFolder_AddRef(pSFParent); + + TRACE("(%p)->()\n",cm); + return (IContextMenu2*)cm; +} + +/************************************************************************** +* ISVBgCm_fnQueryInterface +*/ +static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IContextMenu) || + IsEqualIID(riid, &IID_IContextMenu2)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ + { + FIXME("-- LPSHELLEXTINIT pointer requested\n"); + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** +* ISVBgCm_fnAddRef +*/ +static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu2 *iface) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This, This->ref); + + return ++(This->ref); +} + +/************************************************************************** +* ISVBgCm_fnRelease +*/ +static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu2 *iface) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IContextMenu(%p)\n",This); + + if(This->pSFParent) + IShellFolder_Release(This->pSFParent); + + HeapFree(GetProcessHeap(),0,This); + return 0; + } + + return This->ref; +} + +/************************************************************************** +* ISVBgCm_fnQueryContextMenu() +*/ + +static HRESULT WINAPI ISVBgCm_fnQueryContextMenu( + IContextMenu2 *iface, + HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + HMENU hMyMenu; + UINT idMax; + HRESULT hr; + + BgCmImpl *This = (BgCmImpl *)iface; + + TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", + This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + + + hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002"); + if (uFlags & CMF_DEFAULTONLY) + { + HMENU ourMenu = GetSubMenu(hMyMenu,0); + UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED); + UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED); + if (newDef != oldDef) + SetMenuDefaultItem(hMenu,newDef,TRUE); + if (newDef!=0xFFFFFFFF) + hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1); + else + hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); + } + else + { + idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu, + idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); + hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1); + } + DestroyMenu(hMyMenu); + + TRACE("(%p)->returning 0x%lx\n",This,hr); + return hr; +} + +/************************************************************************** +* DoNewFolder +*/ +static void DoNewFolder( + IContextMenu2 *iface, + IShellView *psv) +{ + BgCmImpl *This = (BgCmImpl *)iface; + ISFHelper * psfhlp; + char szName[MAX_PATH]; + + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp); + if (psfhlp) + { + LPITEMIDLIST pidl; + ISFHelper_GetUniqueName(psfhlp, szName, MAX_PATH); + ISFHelper_AddFolder(psfhlp, 0, szName, &pidl); + + if(psv) + { + /* if we are in a shellview do labeledit */ + IShellView_SelectItem(psv, + pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE + |SVSI_FOCUSED|SVSI_SELECT)); + } + SHFree(pidl); + + ISFHelper_Release(psfhlp); + } +} + +/************************************************************************** +* DoPaste +*/ +static BOOL DoPaste( + IContextMenu2 *iface) +{ + BgCmImpl *This = (BgCmImpl *)iface; + BOOL bSuccess = FALSE; + IDataObject * pda; + + TRACE("\n"); + + if(SUCCEEDED(OleGetClipboard(&pda))) + { + STGMEDIUM medium; + FORMATETC formatetc; + + TRACE("pda=%p\n", pda); + + /* Set the FORMATETC structure*/ + InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); + + /* Get the pidls from IDataObject */ + if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) + { + LPITEMIDLIST * apidl; + LPITEMIDLIST pidl; + IShellFolder *psfFrom = NULL, *psfDesktop; + + LPIDA lpcida = GlobalLock(medium.u.hGlobal); + TRACE("cida=%p\n", lpcida); + + apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + + /* bind to the source shellfolder */ + SHGetDesktopFolder(&psfDesktop); + if(psfDesktop) + { + IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); + IShellFolder_Release(psfDesktop); + } + + if (psfFrom) + { + /* get source and destination shellfolder */ + ISFHelper *psfhlpdst, *psfhlpsrc; + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc); + + /* do the copy/move */ + if (psfhlpdst && psfhlpsrc) + { + ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); + /* FIXME handle move + ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); + */ + } + if(psfhlpdst) ISFHelper_Release(psfhlpdst); + if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); + IShellFolder_Release(psfFrom); + } + + _ILFreeaPidl(apidl, lpcida->cidl); + SHFree(pidl); + + /* release the medium*/ + ReleaseStgMedium(&medium); + } + IDataObject_Release(pda); + } +#if 0 + HGLOBAL hMem; + + OpenClipboard(NULL); + hMem = GetClipboardData(CF_HDROP); + + if(hMem) + { + char * pDropFiles = (char *)GlobalLock(hMem); + if(pDropFiles) + { + int len, offset = sizeof(DROPFILESTRUCT); + + while( pDropFiles[offset] != 0) + { + len = strlen(pDropFiles + offset); + TRACE("%s\n", pDropFiles + offset); + offset += len+1; + } + } + GlobalUnlock(hMem); + } + CloseClipboard(); +#endif + return bSuccess; +} + +/************************************************************************** +* ISVBgCm_fnInvokeCommand() +*/ +static HRESULT WINAPI ISVBgCm_fnInvokeCommand( + IContextMenu2 *iface, + LPCMINVOKECOMMANDINFO lpcmi) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV = NULL; + HWND hWndSV = 0; + + TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); + + /* get the active IShellView */ + if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) + { + if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) + { + IShellView_GetWindow(lpSV, &hWndSV); + } + } + + if(HIWORD(lpcmi->lpVerb)) + { + TRACE("%s\n",lpcmi->lpVerb); + + if (! strcmp(lpcmi->lpVerb,CMDSTR_NEWFOLDERA)) + { + DoNewFolder(iface, lpSV); + } + else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA)) + { + if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 ); + } + else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA)) + { + if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 ); + } + else + { + FIXME("please report: unknown verb %s\n",lpcmi->lpVerb); + } + } + else + { + switch(LOWORD(lpcmi->lpVerb)) + { + case FCIDM_SHVIEW_NEWFOLDER: + DoNewFolder(iface, lpSV); + break; + case FCIDM_SHVIEW_INSERT: + DoPaste(iface); + break; + default: + /* if it's a id just pass it to the parent shv */ + SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 ); + break; + } + } + + if (lpSV) + IShellView_Release(lpSV); /* QueryActiveShellView does AddRef*/ + + return NOERROR; +} + +/************************************************************************** + * ISVBgCm_fnGetCommandString() + * + */ +static HRESULT WINAPI ISVBgCm_fnGetCommandString( + IContextMenu2 *iface, + UINT idCommand, + UINT uFlags, + UINT* lpReserved, + LPSTR lpszName, + UINT uMaxNameLen) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); + + /* test the existence of the menu items, the file dialog enables + the buttons according to this */ + if (uFlags == GCS_VALIDATEA) + { + if(HIWORD(idCommand)) + { + if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) || + !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) || + !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA)) + { + return NOERROR; + } + } + } + + FIXME("unknown command string\n"); + return E_FAIL; +} + +/************************************************************************** +* ISVBgCm_fnHandleMenuMsg() +*/ +static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg( + IContextMenu2 *iface, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + BgCmImpl *This = (BgCmImpl *)iface; + + FIXME("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam); + + return E_NOTIMPL; +} + +/************************************************************************** +* IContextMenu2 VTable +* +*/ +static struct IContextMenu2Vtbl cmvt = +{ + ISVBgCm_fnQueryInterface, + ISVBgCm_fnAddRef, + ISVBgCm_fnRelease, + ISVBgCm_fnQueryContextMenu, + ISVBgCm_fnInvokeCommand, + ISVBgCm_fnGetCommandString, + ISVBgCm_fnHandleMenuMsg +}; diff --git a/reactos/lib/shell32/shv_item_cmenu.c b/reactos/lib/shell32/shv_item_cmenu.c index 6db0b03e442..96584068191 100644 --- a/reactos/lib/shell32/shv_item_cmenu.c +++ b/reactos/lib/shell32/shv_item_cmenu.c @@ -1,531 +1,531 @@ -/* - * IContextMenu for items in the shellview - * - * Copyright 1998, 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "winerror.h" -#include "wine/debug.h" - -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "shlguid.h" -#include "undocshell.h" -#include "shlobj.h" - -#include "shell32_main.h" -#include "shellfolder.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************************************************************** -* IContextMenu Implementation -*/ -typedef struct -{ IContextMenu2Vtbl *lpVtbl; - DWORD ref; - IShellFolder* pSFParent; - LPITEMIDLIST pidl; /* root pidl */ - LPITEMIDLIST *apidl; /* array of child pidls */ - UINT cidl; - BOOL bAllValues; -} ItemCmImpl; - - -static struct IContextMenu2Vtbl cmvt; - -/************************************************************************** -* ISvItemCm_CanRenameItems() -*/ -static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This) -{ UINT i; - DWORD dwAttributes; - - TRACE("(%p)->()\n",This); - - if(This->apidl) - { - for(i = 0; i < This->cidl; i++){} - if(i > 1) return FALSE; /* can't rename more than one item at a time*/ - dwAttributes = SFGAO_CANRENAME; - IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)This->apidl, &dwAttributes); - return dwAttributes & SFGAO_CANRENAME; - } - return FALSE; -} - -/************************************************************************** -* ISvItemCm_Constructor() -*/ -IContextMenu2 *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *apidl, UINT cidl) -{ ItemCmImpl* cm; - UINT u; - - cm = (ItemCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl)); - cm->lpVtbl = &cmvt; - cm->ref = 1; - cm->pidl = ILClone(pidl); - cm->pSFParent = pSFParent; - - if(pSFParent) IShellFolder_AddRef(pSFParent); - - cm->apidl = _ILCopyaPidl(apidl, cidl); - cm->cidl = cidl; - - cm->bAllValues = 1; - for(u = 0; u < cidl; u++) - { - cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0); - } - - TRACE("(%p)->()\n",cm); - - return (IContextMenu2*)cm; -} - -/************************************************************************** -* ISvItemCm_fnQueryInterface -*/ -static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IContextMenu) || - IsEqualIID(riid, &IID_IContextMenu2)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ - { - FIXME("-- LPSHELLEXTINIT pointer requested\n"); - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* ISvItemCm_fnAddRef -*/ -static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu2 *iface) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->(count=%lu)\n",This, This->ref); - - return ++(This->ref); -} - -/************************************************************************** -* ISvItemCm_fnRelease -*/ -static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu2 *iface) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->()\n",This); - - if (!--(This->ref)) - { - TRACE(" destroying IContextMenu(%p)\n",This); - - if(This->pSFParent) - IShellFolder_Release(This->pSFParent); - - if(This->pidl) - SHFree(This->pidl); - - /*make sure the pidl is freed*/ - _ILFreeaPidl(This->apidl, This->cidl); - - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -/************************************************************************** -* ICM_InsertItem() -*/ -void WINAPI _InsertMenuItem ( - HMENU hmenu, - UINT indexMenu, - BOOL fByPosition, - UINT wID, - UINT fType, - LPSTR dwTypeData, - UINT fState) -{ - MENUITEMINFOA mii; - - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - if (fType == MFT_SEPARATOR) - { - mii.fMask = MIIM_ID | MIIM_TYPE; - } - else - { - mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; - mii.dwTypeData = dwTypeData; - mii.fState = fState; - } - mii.wID = wID; - mii.fType = fType; - InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii); -} - -/************************************************************************** -* ISvItemCm_fnQueryContextMenu() -* FIXME: load menu MENU_SHV_FILE out of resources instead if creating -* each menu item by calling _InsertMenuItem() -*/ -static HRESULT WINAPI ISvItemCm_fnQueryContextMenu( - IContextMenu2 *iface, - HMENU hmenu, - UINT indexMenu, - UINT idCmdFirst, - UINT idCmdLast, - UINT uFlags) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - - if (idCmdFirst != 0) - FIXME("We should use idCmdFirst=%d and idCmdLast=%d for command ids\n", idCmdFirst, idCmdLast); - - if(!(CMF_DEFAULTONLY & uFlags) && This->cidl>0) - { - if(!(uFlags & CMF_EXPLORE)) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED); - - if(This->bAllValues) - { - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED); - } - else - { - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED); - } - - SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); - - _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, "&Copy", MFS_ENABLED); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, "&Cut", MFS_ENABLED); - - _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, "&Delete", MFS_ENABLED); - - if(uFlags & CMF_CANRENAME) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, "&Rename", ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED); - - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (FCIDM_SHVIEWLAST)); - } - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); -} - -/************************************************************************** -* DoOpenExplore -* -* for folders only -*/ - -static void DoOpenExplore( - IContextMenu2 *iface, - HWND hwnd, - LPCSTR verb) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - UINT i, bFolderFound = FALSE; - LPITEMIDLIST pidlFQ; - SHELLEXECUTEINFOA sei; - - /* Find the first item in the list that is not a value. These commands - should never be invoked if there isn't at least one folder item in the list.*/ - - for(i = 0; icidl; i++) - { - if(!_ILIsValue(This->apidl[i])) - { - bFolderFound = TRUE; - break; - } - } - - if (!bFolderFound) return; - - pidlFQ = ILCombine(This->pidl, This->apidl[i]); - - ZeroMemory(&sei, sizeof(sei)); - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; - sei.lpIDList = pidlFQ; - sei.lpClass = "Folder"; - sei.hwnd = hwnd; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = verb; - ShellExecuteExA(&sei); - SHFree(pidlFQ); -} - -/************************************************************************** -* DoRename -*/ -static void DoRename( - IContextMenu2 *iface, - HWND hwnd) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV; - - TRACE("(%p)->(wnd=%p)\n",This, hwnd); - - /* get the active IShellView */ - if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - TRACE("(sv=%p)\n",lpSV); - IShellView_SelectItem(lpSV, This->apidl[0], - SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT); - IShellView_Release(lpSV); - } - } -} - -/************************************************************************** - * DoDelete - * - * deletes the currently selected items - */ -static void DoDelete(IContextMenu2 *iface) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - ISFHelper * psfhlp; - - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp); - if (psfhlp) - { - ISFHelper_DeleteItems(psfhlp, This->cidl, (LPCITEMIDLIST *)This->apidl); - ISFHelper_Release(psfhlp); - } -} - -/************************************************************************** - * DoCopyOrCut - * - * copies the currently selected items into the clipboard - */ -static BOOL DoCopyOrCut( - IContextMenu2 *iface, - HWND hwnd, - BOOL bCut) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV; - LPDATAOBJECT lpDo; - - TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut); - - /* get the active IShellView */ - if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo))) - { - OleSetClipboard(lpDo); - IDataObject_Release(lpDo); - } - IShellView_Release(lpSV); - } - } - return TRUE; -} -/************************************************************************** -* ISvItemCm_fnInvokeCommand() -*/ -static HRESULT WINAPI ISvItemCm_fnInvokeCommand( - IContextMenu2 *iface, - LPCMINVOKECOMMANDINFO lpcmi) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO)) - FIXME("Is an EX structure\n"); - - TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); - - if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST) - { - TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb)); - return E_INVALIDARG; - } - - if (HIWORD(lpcmi->lpVerb) == 0) - { - switch(LOWORD(lpcmi->lpVerb)) - { - case FCIDM_SHVIEW_EXPLORE: - TRACE("Verb FCIDM_SHVIEW_EXPLORE\n"); - DoOpenExplore(iface, lpcmi->hwnd, "explore"); - break; - case FCIDM_SHVIEW_OPEN: - TRACE("Verb FCIDM_SHVIEW_OPEN\n"); - DoOpenExplore(iface, lpcmi->hwnd, "open"); - break; - case FCIDM_SHVIEW_RENAME: - TRACE("Verb FCIDM_SHVIEW_RENAME\n"); - DoRename(iface, lpcmi->hwnd); - break; - case FCIDM_SHVIEW_DELETE: - TRACE("Verb FCIDM_SHVIEW_DELETE\n"); - DoDelete(iface); - break; - case FCIDM_SHVIEW_COPY: - TRACE("Verb FCIDM_SHVIEW_COPY\n"); - DoCopyOrCut(iface, lpcmi->hwnd, FALSE); - break; - case FCIDM_SHVIEW_CUT: - TRACE("Verb FCIDM_SHVIEW_CUT\n"); - DoCopyOrCut(iface, lpcmi->hwnd, TRUE); - break; - default: - FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb)); - } - } - else - { - TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb)); - if (strcmp(lpcmi->lpVerb,"delete")==0) - DoDelete(iface); - else - FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb)); - } - return NOERROR; -} - -/************************************************************************** -* ISvItemCm_fnGetCommandString() -*/ -static HRESULT WINAPI ISvItemCm_fnGetCommandString( - IContextMenu2 *iface, - UINT idCommand, - UINT uFlags, - UINT* lpReserved, - LPSTR lpszName, - UINT uMaxNameLen) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - HRESULT hr = E_INVALIDARG; - - TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); - - switch(uFlags) - { - case GCS_HELPTEXTA: - case GCS_HELPTEXTW: - hr = E_NOTIMPL; - break; - - case GCS_VERBA: - switch(idCommand) - { - case FCIDM_SHVIEW_RENAME: - strcpy((LPSTR)lpszName, "rename"); - hr = NOERROR; - break; - } - break; - - /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This - case, you need to do the lstrcpyW to the pointer passed.*/ - case GCS_VERBW: - switch(idCommand) - { case FCIDM_SHVIEW_RENAME: - MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen ); - hr = NOERROR; - break; - } - break; - - case GCS_VALIDATEA: - case GCS_VALIDATEW: - hr = NOERROR; - break; - } - TRACE("-- (%p)->(name=%s)\n",This, lpszName); - return hr; -} - -/************************************************************************** -* ISvItemCm_fnHandleMenuMsg() -* NOTES -* should be only in IContextMenu2 and IContextMenu3 -* is nevertheless called from word95 -*/ -static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg( - IContextMenu2 *iface, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam); - - return E_NOTIMPL; -} - -static struct IContextMenu2Vtbl cmvt = -{ - ISvItemCm_fnQueryInterface, - ISvItemCm_fnAddRef, - ISvItemCm_fnRelease, - ISvItemCm_fnQueryContextMenu, - ISvItemCm_fnInvokeCommand, - ISvItemCm_fnGetCommandString, - ISvItemCm_fnHandleMenuMsg -}; +/* + * IContextMenu for items in the shellview + * + * Copyright 1998, 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "wine/debug.h" + +#include "windef.h" +#include "wingdi.h" +#include "pidl.h" +#include "shlguid.h" +#include "undocshell.h" +#include "shlobj.h" + +#include "shell32_main.h" +#include "shellfolder.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +/************************************************************************** +* IContextMenu Implementation +*/ +typedef struct +{ IContextMenu2Vtbl *lpVtbl; + DWORD ref; + IShellFolder* pSFParent; + LPITEMIDLIST pidl; /* root pidl */ + LPITEMIDLIST *apidl; /* array of child pidls */ + UINT cidl; + BOOL bAllValues; +} ItemCmImpl; + + +static struct IContextMenu2Vtbl cmvt; + +/************************************************************************** +* ISvItemCm_CanRenameItems() +*/ +static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This) +{ UINT i; + DWORD dwAttributes; + + TRACE("(%p)->()\n",This); + + if(This->apidl) + { + for(i = 0; i < This->cidl; i++){} + if(i > 1) return FALSE; /* can't rename more than one item at a time*/ + dwAttributes = SFGAO_CANRENAME; + IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)This->apidl, &dwAttributes); + return dwAttributes & SFGAO_CANRENAME; + } + return FALSE; +} + +/************************************************************************** +* ISvItemCm_Constructor() +*/ +IContextMenu2 *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *apidl, UINT cidl) +{ ItemCmImpl* cm; + UINT u; + + cm = (ItemCmImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl)); + cm->lpVtbl = &cmvt; + cm->ref = 1; + cm->pidl = ILClone(pidl); + cm->pSFParent = pSFParent; + + if(pSFParent) IShellFolder_AddRef(pSFParent); + + cm->apidl = _ILCopyaPidl(apidl, cidl); + cm->cidl = cidl; + + cm->bAllValues = 1; + for(u = 0; u < cidl; u++) + { + cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0); + } + + TRACE("(%p)->()\n",cm); + + return (IContextMenu2*)cm; +} + +/************************************************************************** +* ISvItemCm_fnQueryInterface +*/ +static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IContextMenu) || + IsEqualIID(riid, &IID_IContextMenu2)) + { + *ppvObj = This; + } + else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ + { + FIXME("-- LPSHELLEXTINIT pointer requested\n"); + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** +* ISvItemCm_fnAddRef +*/ +static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu2 *iface) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + TRACE("(%p)->(count=%lu)\n",This, This->ref); + + return ++(This->ref); +} + +/************************************************************************** +* ISvItemCm_fnRelease +*/ +static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu2 *iface) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + TRACE("(%p)->()\n",This); + + if (!--(This->ref)) + { + TRACE(" destroying IContextMenu(%p)\n",This); + + if(This->pSFParent) + IShellFolder_Release(This->pSFParent); + + if(This->pidl) + SHFree(This->pidl); + + /*make sure the pidl is freed*/ + _ILFreeaPidl(This->apidl, This->cidl); + + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->ref; +} + +/************************************************************************** +* ICM_InsertItem() +*/ +void WINAPI _InsertMenuItem ( + HMENU hmenu, + UINT indexMenu, + BOOL fByPosition, + UINT wID, + UINT fType, + LPSTR dwTypeData, + UINT fState) +{ + MENUITEMINFOA mii; + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + if (fType == MFT_SEPARATOR) + { + mii.fMask = MIIM_ID | MIIM_TYPE; + } + else + { + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.dwTypeData = dwTypeData; + mii.fState = fState; + } + mii.wID = wID; + mii.fType = fType; + InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii); +} + +/************************************************************************** +* ISvItemCm_fnQueryContextMenu() +* FIXME: load menu MENU_SHV_FILE out of resources instead if creating +* each menu item by calling _InsertMenuItem() +*/ +static HRESULT WINAPI ISvItemCm_fnQueryContextMenu( + IContextMenu2 *iface, + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + + if (idCmdFirst != 0) + FIXME("We should use idCmdFirst=%d and idCmdLast=%d for command ids\n", idCmdFirst, idCmdLast); + + if(!(CMF_DEFAULTONLY & uFlags) && This->cidl>0) + { + if(!(uFlags & CMF_EXPLORE)) + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED); + + if(This->bAllValues) + { + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED); + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED); + } + else + { + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED); + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Open", MFS_ENABLED); + } + + SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); + + _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, "&Copy", MFS_ENABLED); + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, "&Cut", MFS_ENABLED); + + _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, "&Delete", MFS_ENABLED); + + if(uFlags & CMF_CANRENAME) + _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, "&Rename", ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED); + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (FCIDM_SHVIEWLAST)); + } + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); +} + +/************************************************************************** +* DoOpenExplore +* +* for folders only +*/ + +static void DoOpenExplore( + IContextMenu2 *iface, + HWND hwnd, + LPCSTR verb) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + UINT i, bFolderFound = FALSE; + LPITEMIDLIST pidlFQ; + SHELLEXECUTEINFOA sei; + + /* Find the first item in the list that is not a value. These commands + should never be invoked if there isn't at least one folder item in the list.*/ + + for(i = 0; icidl; i++) + { + if(!_ILIsValue(This->apidl[i])) + { + bFolderFound = TRUE; + break; + } + } + + if (!bFolderFound) return; + + pidlFQ = ILCombine(This->pidl, This->apidl[i]); + + ZeroMemory(&sei, sizeof(sei)); + sei.cbSize = sizeof(sei); + sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME; + sei.lpIDList = pidlFQ; + sei.lpClass = "Folder"; + sei.hwnd = hwnd; + sei.nShow = SW_SHOWNORMAL; + sei.lpVerb = verb; + ShellExecuteExA(&sei); + SHFree(pidlFQ); +} + +/************************************************************************** +* DoRename +*/ +static void DoRename( + IContextMenu2 *iface, + HWND hwnd) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV; + + TRACE("(%p)->(wnd=%p)\n",This, hwnd); + + /* get the active IShellView */ + if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) + { + if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) + { + TRACE("(sv=%p)\n",lpSV); + IShellView_SelectItem(lpSV, This->apidl[0], + SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT); + IShellView_Release(lpSV); + } + } +} + +/************************************************************************** + * DoDelete + * + * deletes the currently selected items + */ +static void DoDelete(IContextMenu2 *iface) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + ISFHelper * psfhlp; + + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp); + if (psfhlp) + { + ISFHelper_DeleteItems(psfhlp, This->cidl, (LPCITEMIDLIST *)This->apidl); + ISFHelper_Release(psfhlp); + } +} + +/************************************************************************** + * DoCopyOrCut + * + * copies the currently selected items into the clipboard + */ +static BOOL DoCopyOrCut( + IContextMenu2 *iface, + HWND hwnd, + BOOL bCut) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV; + LPDATAOBJECT lpDo; + + TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut); + + /* get the active IShellView */ + if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) + { + if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) + { + if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo))) + { + OleSetClipboard(lpDo); + IDataObject_Release(lpDo); + } + IShellView_Release(lpSV); + } + } + return TRUE; +} +/************************************************************************** +* ISvItemCm_fnInvokeCommand() +*/ +static HRESULT WINAPI ISvItemCm_fnInvokeCommand( + IContextMenu2 *iface, + LPCMINVOKECOMMANDINFO lpcmi) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO)) + FIXME("Is an EX structure\n"); + + TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); + + if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST) + { + TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb)); + return E_INVALIDARG; + } + + if (HIWORD(lpcmi->lpVerb) == 0) + { + switch(LOWORD(lpcmi->lpVerb)) + { + case FCIDM_SHVIEW_EXPLORE: + TRACE("Verb FCIDM_SHVIEW_EXPLORE\n"); + DoOpenExplore(iface, lpcmi->hwnd, "explore"); + break; + case FCIDM_SHVIEW_OPEN: + TRACE("Verb FCIDM_SHVIEW_OPEN\n"); + DoOpenExplore(iface, lpcmi->hwnd, "open"); + break; + case FCIDM_SHVIEW_RENAME: + TRACE("Verb FCIDM_SHVIEW_RENAME\n"); + DoRename(iface, lpcmi->hwnd); + break; + case FCIDM_SHVIEW_DELETE: + TRACE("Verb FCIDM_SHVIEW_DELETE\n"); + DoDelete(iface); + break; + case FCIDM_SHVIEW_COPY: + TRACE("Verb FCIDM_SHVIEW_COPY\n"); + DoCopyOrCut(iface, lpcmi->hwnd, FALSE); + break; + case FCIDM_SHVIEW_CUT: + TRACE("Verb FCIDM_SHVIEW_CUT\n"); + DoCopyOrCut(iface, lpcmi->hwnd, TRUE); + break; + default: + FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb)); + } + } + else + { + TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb)); + if (strcmp(lpcmi->lpVerb,"delete")==0) + DoDelete(iface); + else + FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb)); + } + return NOERROR; +} + +/************************************************************************** +* ISvItemCm_fnGetCommandString() +*/ +static HRESULT WINAPI ISvItemCm_fnGetCommandString( + IContextMenu2 *iface, + UINT idCommand, + UINT uFlags, + UINT* lpReserved, + LPSTR lpszName, + UINT uMaxNameLen) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + HRESULT hr = E_INVALIDARG; + + TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); + + switch(uFlags) + { + case GCS_HELPTEXTA: + case GCS_HELPTEXTW: + hr = E_NOTIMPL; + break; + + case GCS_VERBA: + switch(idCommand) + { + case FCIDM_SHVIEW_RENAME: + strcpy((LPSTR)lpszName, "rename"); + hr = NOERROR; + break; + } + break; + + /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This + case, you need to do the lstrcpyW to the pointer passed.*/ + case GCS_VERBW: + switch(idCommand) + { case FCIDM_SHVIEW_RENAME: + MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen ); + hr = NOERROR; + break; + } + break; + + case GCS_VALIDATEA: + case GCS_VALIDATEW: + hr = NOERROR; + break; + } + TRACE("-- (%p)->(name=%s)\n",This, lpszName); + return hr; +} + +/************************************************************************** +* ISvItemCm_fnHandleMenuMsg() +* NOTES +* should be only in IContextMenu2 and IContextMenu3 +* is nevertheless called from word95 +*/ +static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg( + IContextMenu2 *iface, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + ItemCmImpl *This = (ItemCmImpl *)iface; + + TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam); + + return E_NOTIMPL; +} + +static struct IContextMenu2Vtbl cmvt = +{ + ISvItemCm_fnQueryInterface, + ISvItemCm_fnAddRef, + ISvItemCm_fnRelease, + ISvItemCm_fnQueryContextMenu, + ISvItemCm_fnInvokeCommand, + ISvItemCm_fnGetCommandString, + ISvItemCm_fnHandleMenuMsg +}; diff --git a/reactos/lib/shell32/systray.c b/reactos/lib/shell32/systray.c index b371cd87782..1568289a4ad 100644 --- a/reactos/lib/shell32/systray.c +++ b/reactos/lib/shell32/systray.c @@ -1,397 +1,397 @@ -/* - * Systray - * - * Copyright 1999 Kai Morich - * - * Manage the systray window. That it actually appears in the docking - * area of KDE is handled in dlls/x11drv/window.c, - * X11DRV_set_wm_hints using KWM_DOCKWINDOW. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "wingdi.h" -#include "winuser.h" -#include "shlobj.h" -#include "shellapi.h" -#include "shell32_main.h" -#include "commctrl.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -typedef struct SystrayItem { - HWND hWnd; - HWND hWndToolTip; - NOTIFYICONDATAA notifyIcon; - struct SystrayItem *nextTrayItem; -} SystrayItem; - -static SystrayItem *systray=NULL; -static int firstSystray=TRUE; /* defer creation of window class until first systray item is created */ - -static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid); - - -#define ICON_SIZE GetSystemMetrics(SM_CXSMICON) -/* space around icon (forces icon to center of KDE systray area) */ -#define ICON_BORDER 4 - - - -static BOOL SYSTRAY_ItemIsEqual(PNOTIFYICONDATAA pnid1, PNOTIFYICONDATAA pnid2) -{ - if (pnid1->hWnd != pnid2->hWnd) return FALSE; - if (pnid1->uID != pnid2->uID) return FALSE; - return TRUE; -} - -static LRESULT CALLBACK SYSTRAY_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - switch (message) { - case WM_PAINT: - { - RECT rc; - SystrayItem *ptrayItem = systray; - - while (ptrayItem) { - if (ptrayItem->hWnd==hWnd) { - if (ptrayItem->notifyIcon.hIcon) { - hdc = BeginPaint(hWnd, &ps); - GetClientRect(hWnd, &rc); - if (!DrawIconEx(hdc, rc.left+ICON_BORDER, rc.top+ICON_BORDER, ptrayItem->notifyIcon.hIcon, - ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL)) { - ERR("Paint(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem); - SYSTRAY_Delete(&ptrayItem->notifyIcon); - } - } - break; - } - ptrayItem = ptrayItem->nextTrayItem; - } - EndPaint(hWnd, &ps); - } - break; - - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - { - MSG msg; - SystrayItem *ptrayItem = systray; - - while ( ptrayItem ) { - if (ptrayItem->hWnd == hWnd) { - msg.hwnd=hWnd; - msg.message=message; - msg.wParam=wParam; - msg.lParam=lParam; - msg.time = GetMessageTime (); - msg.pt.x = LOWORD(GetMessagePos ()); - msg.pt.y = HIWORD(GetMessagePos ()); - - SendMessageA(ptrayItem->hWndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); - } - ptrayItem = ptrayItem->nextTrayItem; - } - } - /* fall through */ - - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - { - SystrayItem *ptrayItem = systray; - - while (ptrayItem) { - if (ptrayItem->hWnd == hWnd) { - if (ptrayItem->notifyIcon.hWnd && ptrayItem->notifyIcon.uCallbackMessage) { - if (!PostMessageA(ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.uCallbackMessage, - (WPARAM)ptrayItem->notifyIcon.uID, (LPARAM)message)) { - ERR("PostMessage(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem); - SYSTRAY_Delete(&ptrayItem->notifyIcon); - } - } - break; - } - ptrayItem = ptrayItem->nextTrayItem; - } - } - break; - - default: - return (DefWindowProcA(hWnd, message, wParam, lParam)); - } - return (0); - -} - - -BOOL SYSTRAY_RegisterClass(void) -{ - WNDCLASSA wc; - - wc.style = CS_SAVEBITS|CS_DBLCLKS; - wc.lpfnWndProc = (WNDPROC)SYSTRAY_WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = 0; - wc.hIcon = 0; - wc.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = "WineSystray"; - - if (!RegisterClassA(&wc)) { - ERR("RegisterClass(WineSystray) failed\n"); - return FALSE; - } - return TRUE; -} - - -BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem) -{ - RECT rect; - - /* Register the class if this is our first tray item. */ - if ( firstSystray ) { - firstSystray = FALSE; - if ( !SYSTRAY_RegisterClass() ) { - ERR( "RegisterClass(WineSystray) failed\n" ); - return FALSE; - } - } - - /* Initialize the window size. */ - rect.left = 0; - rect.top = 0; - rect.right = ICON_SIZE+2*ICON_BORDER; - rect.bottom = ICON_SIZE+2*ICON_BORDER; - - ZeroMemory( ptrayItem, sizeof(SystrayItem) ); - /* Create tray window for icon. */ - ptrayItem->hWnd = CreateWindowExA( WS_EX_TRAYWINDOW, - "WineSystray", "Wine-Systray", - WS_VISIBLE, - CW_USEDEFAULT, CW_USEDEFAULT, - rect.right-rect.left, rect.bottom-rect.top, - 0, 0, 0, 0 ); - if ( !ptrayItem->hWnd ) { - ERR( "CreateWindow(WineSystray) failed\n" ); - return FALSE; - } - - /* Create tooltip for icon. */ - ptrayItem->hWndToolTip = CreateWindowA( TOOLTIPS_CLASSA,NULL,TTS_ALWAYSTIP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - ptrayItem->hWnd, 0, 0, 0 ); - if ( !ptrayItem->hWndToolTip ) { - ERR( "CreateWindow(TOOLTIP) failed\n" ); - return FALSE; - } - return TRUE; -} - - -static void SYSTRAY_ItemTerm(SystrayItem *ptrayItem) -{ - if(ptrayItem->notifyIcon.hIcon) - DestroyIcon(ptrayItem->notifyIcon.hIcon); - if(ptrayItem->hWndToolTip) - DestroyWindow(ptrayItem->hWndToolTip); - if(ptrayItem->hWnd) - DestroyWindow(ptrayItem->hWnd); - return; -} - - -void SYSTRAY_ItemSetMessage(SystrayItem *ptrayItem, UINT uCallbackMessage) -{ - ptrayItem->notifyIcon.uCallbackMessage = uCallbackMessage; -} - - -void SYSTRAY_ItemSetIcon(SystrayItem *ptrayItem, HICON hIcon) -{ - if(ptrayItem->notifyIcon.hIcon) - DestroyIcon(ptrayItem->notifyIcon.hIcon); - ptrayItem->notifyIcon.hIcon = CopyIcon(hIcon); - InvalidateRect(ptrayItem->hWnd, NULL, TRUE); -} - - -void SYSTRAY_ItemSetTip(SystrayItem *ptrayItem, CHAR* szTip, int modify) -{ - TTTOOLINFOA ti; - - strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip)); - ptrayItem->notifyIcon.szTip[sizeof(ptrayItem->notifyIcon.szTip)-1]=0; - - ti.cbSize = sizeof(TTTOOLINFOA); - ti.uFlags = 0; - ti.hwnd = ptrayItem->hWnd; - ti.hinst = 0; - ti.uId = 0; - ti.lpszText = ptrayItem->notifyIcon.szTip; - ti.rect.left = 0; - ti.rect.top = 0; - ti.rect.right = ICON_SIZE+2*ICON_BORDER; - ti.rect.bottom = ICON_SIZE+2*ICON_BORDER; - - if(modify) - SendMessageA(ptrayItem->hWndToolTip, TTM_UPDATETIPTEXTA, 0, (LPARAM)&ti); - else - SendMessageA(ptrayItem->hWndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti); -} - - -static BOOL SYSTRAY_Add(PNOTIFYICONDATAA pnid) -{ - SystrayItem **ptrayItem = &systray; - - /* Find last element. */ - while( *ptrayItem ) { - if ( SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon) ) - return FALSE; - ptrayItem = &((*ptrayItem)->nextTrayItem); - } - /* Allocate SystrayItem for element and add to end of list. */ - (*ptrayItem) = HeapAlloc(GetProcessHeap(),0,sizeof(SystrayItem)); - - /* Initialize and set data for the tray element. */ - SYSTRAY_ItemInit( (*ptrayItem) ); - (*ptrayItem)->notifyIcon.uID = pnid->uID; /* only needed for callback message */ - (*ptrayItem)->notifyIcon.hWnd = pnid->hWnd; /* only needed for callback message */ - SYSTRAY_ItemSetIcon (*ptrayItem, (pnid->uFlags&NIF_ICON) ?pnid->hIcon :0); - SYSTRAY_ItemSetMessage(*ptrayItem, (pnid->uFlags&NIF_MESSAGE)?pnid->uCallbackMessage:0); - SYSTRAY_ItemSetTip (*ptrayItem, (pnid->uFlags&NIF_TIP) ?pnid->szTip :"", FALSE); - - TRACE("%p: %p %s\n", (*ptrayItem), (*ptrayItem)->notifyIcon.hWnd, - (*ptrayItem)->notifyIcon.szTip); - return TRUE; -} - - -static BOOL SYSTRAY_Modify(PNOTIFYICONDATAA pnid) -{ - SystrayItem *ptrayItem = systray; - - while ( ptrayItem ) { - if ( SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon) ) { - if (pnid->uFlags & NIF_ICON) - SYSTRAY_ItemSetIcon(ptrayItem, pnid->hIcon); - if (pnid->uFlags & NIF_MESSAGE) - SYSTRAY_ItemSetMessage(ptrayItem, pnid->uCallbackMessage); - if (pnid->uFlags & NIF_TIP) - SYSTRAY_ItemSetTip(ptrayItem, pnid->szTip, TRUE); - - TRACE("%p: %p %s\n", ptrayItem, ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.szTip); - return TRUE; - } - ptrayItem = ptrayItem->nextTrayItem; - } - return FALSE; /* not found */ -} - - -static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid) -{ - SystrayItem **ptrayItem = &systray; - - while (*ptrayItem) { - if (SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon)) { - SystrayItem *next = (*ptrayItem)->nextTrayItem; - TRACE("%p: %p %s\n", *ptrayItem, (*ptrayItem)->notifyIcon.hWnd, (*ptrayItem)->notifyIcon.szTip); - SYSTRAY_ItemTerm(*ptrayItem); - - HeapFree(GetProcessHeap(),0,*ptrayItem); - *ptrayItem = next; - - return TRUE; - } - ptrayItem = &((*ptrayItem)->nextTrayItem); - } - - return FALSE; /* not found */ -} - -/************************************************************************* - * - */ -BOOL SYSTRAY_Init(void) -{ - return TRUE; -} - -/************************************************************************* - * Shell_NotifyIcon [SHELL32.296] - * Shell_NotifyIconA [SHELL32.297] - */ -BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid ) -{ - BOOL flag=FALSE; - TRACE("enter %p %d %ld\n", pnid->hWnd, pnid->uID, dwMessage); - switch(dwMessage) { - case NIM_ADD: - flag = SYSTRAY_Add(pnid); - break; - case NIM_MODIFY: - flag = SYSTRAY_Modify(pnid); - break; - case NIM_DELETE: - flag = SYSTRAY_Delete(pnid); - break; - } - TRACE("leave %p %d %ld=%d\n", pnid->hWnd, pnid->uID, dwMessage, flag); - return flag; -} - -/************************************************************************* - * Shell_NotifyIconW [SHELL32.298] - */ -BOOL WINAPI Shell_NotifyIconW (DWORD dwMessage, PNOTIFYICONDATAW pnid ) -{ - BOOL ret; - - PNOTIFYICONDATAA p = HeapAlloc(GetProcessHeap(),0,sizeof(NOTIFYICONDATAA)); - memcpy(p, pnid, sizeof(NOTIFYICONDATAA)); - WideCharToMultiByte( CP_ACP, 0, pnid->szTip, -1, p->szTip, sizeof(p->szTip), NULL, NULL ); - p->szTip[sizeof(p->szTip)-1] = 0; - - ret = Shell_NotifyIconA(dwMessage, p ); - - HeapFree(GetProcessHeap(),0,p); - return ret; -} +/* + * Systray + * + * Copyright 1999 Kai Morich + * + * Manage the systray window. That it actually appears in the docking + * area of KDE is handled in dlls/x11drv/window.c, + * X11DRV_set_wm_hints using KWM_DOCKWINDOW. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "wingdi.h" +#include "winuser.h" +#include "shlobj.h" +#include "shellapi.h" +#include "shell32_main.h" +#include "commctrl.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +typedef struct SystrayItem { + HWND hWnd; + HWND hWndToolTip; + NOTIFYICONDATAA notifyIcon; + struct SystrayItem *nextTrayItem; +} SystrayItem; + +static SystrayItem *systray=NULL; +static int firstSystray=TRUE; /* defer creation of window class until first systray item is created */ + +static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid); + + +#define ICON_SIZE GetSystemMetrics(SM_CXSMICON) +/* space around icon (forces icon to center of KDE systray area) */ +#define ICON_BORDER 4 + + + +static BOOL SYSTRAY_ItemIsEqual(PNOTIFYICONDATAA pnid1, PNOTIFYICONDATAA pnid2) +{ + if (pnid1->hWnd != pnid2->hWnd) return FALSE; + if (pnid1->uID != pnid2->uID) return FALSE; + return TRUE; +} + +static LRESULT CALLBACK SYSTRAY_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + + switch (message) { + case WM_PAINT: + { + RECT rc; + SystrayItem *ptrayItem = systray; + + while (ptrayItem) { + if (ptrayItem->hWnd==hWnd) { + if (ptrayItem->notifyIcon.hIcon) { + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &rc); + if (!DrawIconEx(hdc, rc.left+ICON_BORDER, rc.top+ICON_BORDER, ptrayItem->notifyIcon.hIcon, + ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL)) { + ERR("Paint(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem); + SYSTRAY_Delete(&ptrayItem->notifyIcon); + } + } + break; + } + ptrayItem = ptrayItem->nextTrayItem; + } + EndPaint(hWnd, &ps); + } + break; + + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + { + MSG msg; + SystrayItem *ptrayItem = systray; + + while ( ptrayItem ) { + if (ptrayItem->hWnd == hWnd) { + msg.hwnd=hWnd; + msg.message=message; + msg.wParam=wParam; + msg.lParam=lParam; + msg.time = GetMessageTime (); + msg.pt.x = LOWORD(GetMessagePos ()); + msg.pt.y = HIWORD(GetMessagePos ()); + + SendMessageA(ptrayItem->hWndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); + } + ptrayItem = ptrayItem->nextTrayItem; + } + } + /* fall through */ + + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + { + SystrayItem *ptrayItem = systray; + + while (ptrayItem) { + if (ptrayItem->hWnd == hWnd) { + if (ptrayItem->notifyIcon.hWnd && ptrayItem->notifyIcon.uCallbackMessage) { + if (!PostMessageA(ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.uCallbackMessage, + (WPARAM)ptrayItem->notifyIcon.uID, (LPARAM)message)) { + ERR("PostMessage(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem); + SYSTRAY_Delete(&ptrayItem->notifyIcon); + } + } + break; + } + ptrayItem = ptrayItem->nextTrayItem; + } + } + break; + + default: + return (DefWindowProcA(hWnd, message, wParam, lParam)); + } + return (0); + +} + + +BOOL SYSTRAY_RegisterClass(void) +{ + WNDCLASSA wc; + + wc.style = CS_SAVEBITS|CS_DBLCLKS; + wc.lpfnWndProc = SYSTRAY_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = 0; + wc.hIcon = 0; + wc.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = "WineSystray"; + + if (!RegisterClassA(&wc)) { + ERR("RegisterClass(WineSystray) failed\n"); + return FALSE; + } + return TRUE; +} + + +BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem) +{ + RECT rect; + + /* Register the class if this is our first tray item. */ + if ( firstSystray ) { + firstSystray = FALSE; + if ( !SYSTRAY_RegisterClass() ) { + ERR( "RegisterClass(WineSystray) failed\n" ); + return FALSE; + } + } + + /* Initialize the window size. */ + rect.left = 0; + rect.top = 0; + rect.right = ICON_SIZE+2*ICON_BORDER; + rect.bottom = ICON_SIZE+2*ICON_BORDER; + + ZeroMemory( ptrayItem, sizeof(SystrayItem) ); + /* Create tray window for icon. */ + ptrayItem->hWnd = CreateWindowExA( WS_EX_TRAYWINDOW, + "WineSystray", "Wine-Systray", + WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + rect.right-rect.left, rect.bottom-rect.top, + 0, 0, 0, 0 ); + if ( !ptrayItem->hWnd ) { + ERR( "CreateWindow(WineSystray) failed\n" ); + return FALSE; + } + + /* Create tooltip for icon. */ + ptrayItem->hWndToolTip = CreateWindowA( TOOLTIPS_CLASSA,NULL,TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + ptrayItem->hWnd, 0, 0, 0 ); + if ( !ptrayItem->hWndToolTip ) { + ERR( "CreateWindow(TOOLTIP) failed\n" ); + return FALSE; + } + return TRUE; +} + + +static void SYSTRAY_ItemTerm(SystrayItem *ptrayItem) +{ + if(ptrayItem->notifyIcon.hIcon) + DestroyIcon(ptrayItem->notifyIcon.hIcon); + if(ptrayItem->hWndToolTip) + DestroyWindow(ptrayItem->hWndToolTip); + if(ptrayItem->hWnd) + DestroyWindow(ptrayItem->hWnd); + return; +} + + +void SYSTRAY_ItemSetMessage(SystrayItem *ptrayItem, UINT uCallbackMessage) +{ + ptrayItem->notifyIcon.uCallbackMessage = uCallbackMessage; +} + + +void SYSTRAY_ItemSetIcon(SystrayItem *ptrayItem, HICON hIcon) +{ + if(ptrayItem->notifyIcon.hIcon) + DestroyIcon(ptrayItem->notifyIcon.hIcon); + ptrayItem->notifyIcon.hIcon = CopyIcon(hIcon); + InvalidateRect(ptrayItem->hWnd, NULL, TRUE); +} + + +void SYSTRAY_ItemSetTip(SystrayItem *ptrayItem, CHAR* szTip, int modify) +{ + TTTOOLINFOA ti; + + strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip)); + ptrayItem->notifyIcon.szTip[sizeof(ptrayItem->notifyIcon.szTip)-1]=0; + + ti.cbSize = sizeof(TTTOOLINFOA); + ti.uFlags = 0; + ti.hwnd = ptrayItem->hWnd; + ti.hinst = 0; + ti.uId = 0; + ti.lpszText = ptrayItem->notifyIcon.szTip; + ti.rect.left = 0; + ti.rect.top = 0; + ti.rect.right = ICON_SIZE+2*ICON_BORDER; + ti.rect.bottom = ICON_SIZE+2*ICON_BORDER; + + if(modify) + SendMessageA(ptrayItem->hWndToolTip, TTM_UPDATETIPTEXTA, 0, (LPARAM)&ti); + else + SendMessageA(ptrayItem->hWndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti); +} + + +static BOOL SYSTRAY_Add(PNOTIFYICONDATAA pnid) +{ + SystrayItem **ptrayItem = &systray; + + /* Find last element. */ + while( *ptrayItem ) { + if ( SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon) ) + return FALSE; + ptrayItem = &((*ptrayItem)->nextTrayItem); + } + /* Allocate SystrayItem for element and add to end of list. */ + (*ptrayItem) = HeapAlloc(GetProcessHeap(),0,sizeof(SystrayItem)); + + /* Initialize and set data for the tray element. */ + SYSTRAY_ItemInit( (*ptrayItem) ); + (*ptrayItem)->notifyIcon.uID = pnid->uID; /* only needed for callback message */ + (*ptrayItem)->notifyIcon.hWnd = pnid->hWnd; /* only needed for callback message */ + SYSTRAY_ItemSetIcon (*ptrayItem, (pnid->uFlags&NIF_ICON) ?pnid->hIcon :0); + SYSTRAY_ItemSetMessage(*ptrayItem, (pnid->uFlags&NIF_MESSAGE)?pnid->uCallbackMessage:0); + SYSTRAY_ItemSetTip (*ptrayItem, (pnid->uFlags&NIF_TIP) ?pnid->szTip :"", FALSE); + + TRACE("%p: %p %s\n", (*ptrayItem), (*ptrayItem)->notifyIcon.hWnd, + (*ptrayItem)->notifyIcon.szTip); + return TRUE; +} + + +static BOOL SYSTRAY_Modify(PNOTIFYICONDATAA pnid) +{ + SystrayItem *ptrayItem = systray; + + while ( ptrayItem ) { + if ( SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon) ) { + if (pnid->uFlags & NIF_ICON) + SYSTRAY_ItemSetIcon(ptrayItem, pnid->hIcon); + if (pnid->uFlags & NIF_MESSAGE) + SYSTRAY_ItemSetMessage(ptrayItem, pnid->uCallbackMessage); + if (pnid->uFlags & NIF_TIP) + SYSTRAY_ItemSetTip(ptrayItem, pnid->szTip, TRUE); + + TRACE("%p: %p %s\n", ptrayItem, ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.szTip); + return TRUE; + } + ptrayItem = ptrayItem->nextTrayItem; + } + return FALSE; /* not found */ +} + + +static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid) +{ + SystrayItem **ptrayItem = &systray; + + while (*ptrayItem) { + if (SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon)) { + SystrayItem *next = (*ptrayItem)->nextTrayItem; + TRACE("%p: %p %s\n", *ptrayItem, (*ptrayItem)->notifyIcon.hWnd, (*ptrayItem)->notifyIcon.szTip); + SYSTRAY_ItemTerm(*ptrayItem); + + HeapFree(GetProcessHeap(),0,*ptrayItem); + *ptrayItem = next; + + return TRUE; + } + ptrayItem = &((*ptrayItem)->nextTrayItem); + } + + return FALSE; /* not found */ +} + +/************************************************************************* + * + */ +BOOL SYSTRAY_Init(void) +{ + return TRUE; +} + +/************************************************************************* + * Shell_NotifyIcon [SHELL32.296] + * Shell_NotifyIconA [SHELL32.297] + */ +BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid ) +{ + BOOL flag=FALSE; + TRACE("enter %p %d %ld\n", pnid->hWnd, pnid->uID, dwMessage); + switch(dwMessage) { + case NIM_ADD: + flag = SYSTRAY_Add(pnid); + break; + case NIM_MODIFY: + flag = SYSTRAY_Modify(pnid); + break; + case NIM_DELETE: + flag = SYSTRAY_Delete(pnid); + break; + } + TRACE("leave %p %d %ld=%d\n", pnid->hWnd, pnid->uID, dwMessage, flag); + return flag; +} + +/************************************************************************* + * Shell_NotifyIconW [SHELL32.298] + */ +BOOL WINAPI Shell_NotifyIconW (DWORD dwMessage, PNOTIFYICONDATAW pnid ) +{ + BOOL ret; + + PNOTIFYICONDATAA p = HeapAlloc(GetProcessHeap(),0,sizeof(NOTIFYICONDATAA)); + memcpy(p, pnid, sizeof(NOTIFYICONDATAA)); + WideCharToMultiByte( CP_ACP, 0, pnid->szTip, -1, p->szTip, sizeof(p->szTip), NULL, NULL ); + p->szTip[sizeof(p->szTip)-1] = 0; + + ret = Shell_NotifyIconA(dwMessage, p ); + + HeapFree(GetProcessHeap(),0,p); + return ret; +} diff --git a/reactos/lib/shell32/undocshell.h b/reactos/lib/shell32/undocshell.h index 42edd1427f5..2ae56a8b3d8 100644 --- a/reactos/lib/shell32/undocshell.h +++ b/reactos/lib/shell32/undocshell.h @@ -1,585 +1,585 @@ -/* - * Copyright 1999, 2000 Juergen Schmied - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_UNDOCSHELL_H -#define __WINE_UNDOCSHELL_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "commctrl.h" -#include "shlobj.h" - -#ifdef __cplusplus -extern "C" { -#endif /* defined(__cplusplus) */ - -/**************************************************************************** - * IDList Functions - */ -BOOL WINAPI ILGetDisplayName( - LPCITEMIDLIST pidl, - LPVOID path); - -/* type parameter for ILGetDisplayNameEx() */ -#define ILGDN_FORPARSING 0 -#define ILGDN_NORMAL 1 -#define ILGDN_INFOLDER 2 - -BOOL WINAPI ILGetDisplayNameEx( - LPSHELLFOLDER psf, - LPCITEMIDLIST pidl, - LPVOID path, - DWORD type); - -LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl); -void WINAPI ILGlobalFree(LPITEMIDLIST pidl); - -LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath); -LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath); - -HRESULT WINAPI SHILCreateFromPathA ( - LPCSTR path, - LPITEMIDLIST * ppidl, - DWORD *attributes); - -HRESULT WINAPI SHILCreateFromPathW ( - LPCWSTR path, - LPITEMIDLIST * ppidl, - DWORD *attributes); - -LPITEMIDLIST WINAPI ILCreateFromPathA(LPCSTR path); -LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path); - -/* - string functions -*/ -BOOL WINAPI StrRetToStrNA(LPSTR,DWORD,LPSTRRET,const ITEMIDLIST*); -BOOL WINAPI StrRetToStrNW(LPWSTR,DWORD,LPSTRRET,const ITEMIDLIST*); - - -/**************************************************************************** -* SHChangeNotifyRegister API -*/ -#define SHCNRF_InterruptLevel 0x0001 -#define SHCNRF_ShellLevel 0x0002 -#define SHCNRF_RecursiveInterrupt 0x1000 /* Must be combined with SHCNRF_InterruptLevel */ -#define SHCNRF_NewDelivery 0x8000 /* Messages use shared memory */ - -/**************************************************************************** - * Shell Common Dialogs - */ - -BOOL WINAPI PickIconDlg( - HWND hwndOwner, - LPSTR lpstrFile, - DWORD nMaxFile, - LPDWORD lpdwIconIndex); - -/* RunFileDlg flags */ -#define RFF_NOBROWSE 0x01 -#define RFF_NODEFAULT 0x02 -#define RFF_CALCDIRECTORY 0x04 -#define RFF_NOLABEL 0x08 -#define RFF_NOSEPARATEMEM 0x20 /* NT only */ - -/* RunFileFlg notification structure */ -typedef struct -{ - NMHDR hdr; - LPCSTR lpFile; - LPCSTR lpDirectory; - int nShow; -} NM_RUNFILEDLG, * LPNM_RUNFILEDLG; - -/* RunFileDlg notification return values */ -#define RF_OK 0x00 -#define RF_CANCEL 0x01 -#define RF_RETRY 0x02 - -void WINAPI RunFileDlg( - HWND hwndOwner, - HICON hIcon, - LPCSTR lpstrDirectory, - LPCSTR lpstrTitle, - LPCSTR lpstrDescription, - UINT uFlags); - -void WINAPI ExitWindowsDialog(HWND hwndOwner); - -BOOL WINAPI GetFileNameFromBrowse( - HWND hwndOwner, - LPSTR lpstrFile, - DWORD nMaxFile, - LPCSTR lpstrInitialDir, - LPCSTR lpstrDefExt, - LPCSTR lpstrFilter, - LPCSTR lpstrTitle); - -BOOL WINAPI SHFindComputer( - LPCITEMIDLIST pidlRoot, - LPCITEMIDLIST pidlSavedSearch); - -void WINAPI SHHandleDiskFull(HWND hwndOwner, - UINT uDrive); - -int WINAPI SHOutOfMemoryMessageBox( - HWND hwndOwner, - LPCSTR lpCaption, - UINT uType); - -DWORD WINAPI SHNetConnectionDialog( - HWND hwndOwner, - LPCSTR lpstrRemoteName, - DWORD dwType); - -/**************************************************************************** - * Memory Routines - */ - -/* The Platform SDK's shlobj.h header defines similar functions with a - * leading underscore. However those are unusable because of the leading - * underscore, because they have an incorrect calling convention, and - * because these functions are not exported by name anyway. - */ -HANDLE WINAPI SHAllocShared( - LPVOID pv, - ULONG cb, - DWORD pid); - -BOOL WINAPI SHFreeShared( - HANDLE hMem, - DWORD pid); - -LPVOID WINAPI SHLockShared( - HANDLE hMem, - DWORD pid); - -BOOL WINAPI SHUnlockShared(LPVOID pv); - -/**************************************************************************** - * Cabinet Window Messages - */ - -#define CWM_SETPATH (WM_USER + 2) -#define CWM_WANTIDLE (WM_USER + 3) -#define CWM_GETSETCURRENTINFO (WM_USER + 4) -#define CWM_SELECTITEM (WM_USER + 5) -#define CWM_SELECTITEMSTR (WM_USER + 6) -#define CWM_GETISHELLBROWSER (WM_USER + 7) -#define CWM_TESTPATH (WM_USER + 9) -#define CWM_STATECHANGE (WM_USER + 10) -#define CWM_GETPATH (WM_USER + 12) - -/* CWM_TESTPATH types */ -#define CWTP_ISEQUAL 0 -#define CWTP_ISCHILD 1 - -/* CWM_TESTPATH structure */ -typedef struct -{ - DWORD dwType; - ITEMIDLIST idl; -} CWTESTPATHSTRUCT,* LPCWTESTPATHSTRUCT; - -/**************************************************************************** - * System Imagelist Routines - */ - -int WINAPI Shell_GetCachedImageIndex( - LPCSTR lpszFileName, - UINT nIconIndex, - BOOL bSimulateDoc); - -BOOL WINAPI Shell_GetImageLists( - HIMAGELIST *lphimlLarge, - HIMAGELIST *lphimlSmall); - -HICON WINAPI SHGetFileIcon( - DWORD dwReserved, - LPCSTR lpszPath, - DWORD dwFileAttributes, - UINT uFlags); - -BOOL WINAPI FileIconInit(BOOL bFullInit); - -/**************************************************************************** - * File Menu Routines - */ -/* FileMenu_Create nSelHeight constants */ -#define FM_DEFAULT_SELHEIGHT -1 -#define FM_FULL_SELHEIGHT 0 - -/* FileMenu_Create flags */ -#define FMF_SMALL_ICONS 0x00 -#define FMF_LARGE_ICONS 0x08 -#define FMF_NO_COLUMN_BREAK 0x10 - -HMENU WINAPI FileMenu_Create( - COLORREF crBorderColor, - int nBorderWidth, - HBITMAP hBorderBmp, - int nSelHeight, - UINT uFlags); - -void WINAPI FileMenu_Destroy(HMENU hMenu); - -/* FileMenu_AppendItem constants */ -#define FM_SEPARATOR (LPCSTR)1 -#define FM_BLANK_ICON -1 -#define FM_DEFAULT_HEIGHT 0 - -BOOL WINAPI FileMenu_AppendItem( - HMENU hMenu, - LPCSTR lpszText, - UINT uID, - int iIcon, - HMENU hMenuPopup, - int nItemHeight); - -/* FileMenu_InsertUsingPidl flags */ -#define FMF_NO_EMPTY_ITEM 0x01 -#define FMF_NO_PROGRAM_GROUPS 0x04 - -/* FileMenu_InsertUsingPidl callback function */ -typedef void (CALLBACK *LPFNFMCALLBACK)(LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlFile); - -int WINAPI FileMenu_InsertUsingPidl( - HMENU hMenu, - UINT uID, - LPCITEMIDLIST pidl, - UINT uFlags, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback); - -int WINAPI FileMenu_ReplaceUsingPidl( - HMENU hMenu, - UINT uID, - LPCITEMIDLIST pidl, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback); - -void WINAPI FileMenu_Invalidate(HMENU hMenu); - -HMENU WINAPI FileMenu_FindSubMenuByPidl( - HMENU hMenu, - LPCITEMIDLIST pidl); - -BOOL WINAPI FileMenu_TrackPopupMenuEx( - HMENU hMenu, - UINT uFlags, - int x, - int y, - HWND hWnd, - LPTPMPARAMS lptpm); - -BOOL WINAPI FileMenu_GetLastSelectedItemPidls( - UINT uReserved, - LPCITEMIDLIST *ppidlFolder, - LPCITEMIDLIST *ppidlItem); - -LRESULT WINAPI FileMenu_MeasureItem( - HWND hWnd, - LPMEASUREITEMSTRUCT lpmis); - -LRESULT WINAPI FileMenu_DrawItem( - HWND hWnd, - LPDRAWITEMSTRUCT lpdis); - -BOOL WINAPI FileMenu_InitMenuPopup(HMENU hMenu); - -void WINAPI FileMenu_AbortInitMenu(void); - -LRESULT WINAPI FileMenu_HandleMenuChar( - HMENU hMenu, - WPARAM wParam); - -BOOL WINAPI FileMenu_DeleteAllItems(HMENU hMenu); - -BOOL WINAPI FileMenu_DeleteItemByCmd( - HMENU hMenu, - UINT uID); - -BOOL WINAPI FileMenu_DeleteItemByIndex( - HMENU hMenu, - UINT uPos); - -BOOL WINAPI FileMenu_DeleteMenuItemByFirstID( - HMENU hMenu, - UINT uID); - -BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu); - -BOOL WINAPI FileMenu_EnableItemByCmd( - HMENU hMenu, - UINT uID, - BOOL bEnable); - -DWORD WINAPI FileMenu_GetItemExtent( - HMENU hMenu, - UINT uPos); - -int WINAPI FileMenu_AppendFilesForPidl( - HMENU hMenu, - LPCITEMIDLIST pidl, - BOOL bAddSeparator); - -int WINAPI FileMenu_AddFilesForPidl( - HMENU hMenu, - UINT uReserved, - UINT uID, - LPCITEMIDLIST pidl, - UINT uFlags, - UINT uEnumFlags, - LPFNFMCALLBACK lpfnCallback); - -/**************************************************************************** - * Drag And Drop Routines - */ - -HRESULT WINAPI SHRegisterDragDrop( - HWND hWnd, - LPDROPTARGET lpDropTarget); - -HRESULT WINAPI SHRevokeDragDrop(HWND hWnd); - -BOOL WINAPI DAD_DragEnter(HWND hWnd); - -BOOL WINAPI DAD_SetDragImageFromListView( - HWND hWnd, - POINT pt); - -BOOL WINAPI DAD_ShowDragImage(BOOL bShow); - -HRESULT WINAPI CIDLData_CreateFromIDArray( - LPCITEMIDLIST pidlFolder, - DWORD cpidlFiles, - LPCITEMIDLIST *lppidlFiles, - LPDATAOBJECT *ppdataObject); - -/**************************************************************************** - * Path Manipulation Routines - */ - -BOOL WINAPI PathAppendAW(LPVOID lpszPath1, LPCVOID lpszPath2); - -LPVOID WINAPI PathCombineAW(LPVOID szDest, LPCVOID lpszDir, LPCVOID lpszFile); - -LPVOID WINAPI PathAddBackslashAW(LPVOID path); - -LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive); - -LPVOID WINAPI PathFindExtensionAW(LPCVOID path); - -LPVOID WINAPI PathFindFileNameAW(LPCVOID path); - -LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath, DWORD void1, DWORD void2); - -LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath); - -BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath); - -void WINAPI PathRemoveBlanksAW(LPVOID lpszPath); - -VOID WINAPI PathQuoteSpacesAW(LPVOID path); - -void WINAPI PathUnquoteSpacesAW(LPVOID lpszPath); - -BOOL WINAPI PathIsUNCAW(LPCVOID lpszPath); - -BOOL WINAPI PathIsRelativeAW(LPCVOID lpszPath); - -BOOL WINAPI PathIsRootAW(LPCVOID x); - -BOOL WINAPI PathIsExeAW(LPCVOID lpszPath); - -BOOL WINAPI PathIsDirectoryAW(LPCVOID lpszPath); - -BOOL WINAPI PathFileExistsAW(LPCVOID lpszPath); - -BOOL WINAPI PathMatchSpecAW(LPVOID lpszPath, LPVOID lpszSpec); - -BOOL WINAPI PathMakeUniqueNameAW( - LPVOID lpszBuffer, - DWORD dwBuffSize, - LPCVOID lpszShortName, - LPCVOID lpszLongName, - LPCVOID lpszPathName); - -BOOL WINAPI PathYetAnotherMakeUniqueName( - LPWSTR lpszBuffer, - LPCWSTR lpszPathName, - LPCWSTR lpszShortName, - LPCWSTR lpszLongName); - -BOOL WINAPI PathQualifyA(LPCSTR path); -BOOL WINAPI PathQualifyW(LPCWSTR path); -#define PathQualify WINELIB_NAME_AW(PathQualify) -BOOL WINAPI PathQualifyAW(LPCVOID path); - - -/* PathResolve flags */ -#define PRF_CHECKEXISTANCE 0x01 -#define PRF_EXECUTABLE 0x02 -#define PRF_QUALIFYONPATH 0x04 -#define PRF_WINDOWS31 0x08 - -BOOL WINAPI PathResolveAW(LPVOID lpszPath, LPCVOID *alpszPaths, DWORD dwFlags); - -VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int nIDDlgItem, LPCVOID lpszPath); - -/* PathProcessCommand flags */ -#define PPCF_QUOTEPATH 0x01 /* implies PPCF_INCLUDEARGS */ -#define PPCF_INCLUDEARGS 0x02 -#define PPCF_NODIRECTORIES 0x10 -#define PPCF_DONTRESOLVE 0x20 -#define PPCF_PATHISRELATIVE 0x40 - -HRESULT WINAPI PathProcessCommandAW(LPCVOID lpszPath, LPVOID lpszBuff, - DWORD dwBuffSize, DWORD dwFlags); - -void WINAPI PathStripPathAW(LPVOID lpszPath); - -BOOL WINAPI PathStripToRootAW(LPVOID lpszPath); - -void WINAPI PathRemoveArgsAW(LPVOID lpszPath); - -void WINAPI PathRemoveExtensionAW(LPVOID lpszPath); - -int WINAPI PathParseIconLocationAW(LPVOID lpszPath); - -BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2); - -BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs); - -/**************************************************************************** - * Shell Namespace Routines - */ - -/* Generic structure used by several messages */ -typedef struct -{ - DWORD dwReserved; - DWORD dwReserved2; - LPCITEMIDLIST pidl; - LPDWORD lpdwUser; -} SFVCBINFO, * LPSFVCBINFO; -typedef const SFVCBINFO * LPCSFVCBINFO; - -/* SFVCB_SELECTIONCHANGED structure */ -typedef struct -{ - UINT uOldState; - UINT uNewState; - LPCITEMIDLIST pidl; - LPDWORD lpdwUser; -} SFVSELECTSTATE, * LPSFVSELECTSTATE; -typedef const SFVSELECTSTATE * LPCSFVSELECTSTATE; - -/* SFVCB_COPYHOOKCALLBACK structure */ -typedef struct -{ - HWND hwnd; - UINT wFunc; - UINT wFlags; - LPCSTR pszSrcFile; - DWORD dwSrcAttribs; - LPCSTR pszDestFile; - DWORD dwDestAttribs; -} SFVCOPYHOOKINFO, * LPSFVCOPYHOOKINFO; -typedef const SFVCOPYHOOKINFO * LPCSFVCOPYHOOKINFO; - -/* SFVCB_GETDETAILSOF structure */ -typedef struct -{ - LPCITEMIDLIST pidl; - int fmt; - int cx; - STRRET lpText; -} SFVCOLUMNINFO, * LPSFVCOLUMNINFO; - -/**************************************************************************** - * Misc Stuff - */ - -/* SHWaitForFileToOpen flags */ -#define SHWFF_ADD 0x01 -#define SHWFF_REMOVE 0x02 -#define SHWFF_WAIT 0x04 - -BOOL WINAPI SHWaitForFileToOpen( - LPCITEMIDLIST pidl, - DWORD dwFlags, - DWORD dwTimeout); - -WORD WINAPI ArrangeWindows( - HWND hwndParent, - DWORD dwReserved, - LPCRECT lpRect, - WORD cKids, - CONST HWND * lpKids); - -/* RegisterShellHook types */ -#define RSH_DEREGISTER 0 -#define RSH_REGISTER 1 -#define RSH_REGISTER_PROGMAN 2 -#define RSH_REGISTER_TASKMAN 3 - -BOOL WINAPI RegisterShellHook( - HWND hWnd, - DWORD dwType); - -/* SHCreateDefClassObject callback function */ -typedef HRESULT (CALLBACK *LPFNCDCOCALLBACK)( - LPUNKNOWN pUnkOuter, - REFIID riidObject, - LPVOID *ppvObject); - -HRESULT WINAPI SHCreateDefClassObject( - REFIID riidFactory, - LPVOID *ppvFactory, - LPFNCDCOCALLBACK lpfnCallback, - LPDWORD lpdwUsage, - REFIID riidObject); - -void WINAPI SHFreeUnusedLibraries(); - -/* SHCreateLinks flags */ -#define SHCLF_PREFIXNAME 0x01 -#define SHCLF_CREATEONDESKTOP 0x02 - -HRESULT WINAPI SHCreateLinks( - HWND hWnd, - LPCSTR lpszDir, - LPDATAOBJECT lpDataObject, - UINT uFlags, - LPITEMIDLIST *lppidlLinks); - -DWORD WINAPI CheckEscapesA(LPSTR string, DWORD len); -DWORD WINAPI CheckEscapesW(LPWSTR string, DWORD len); - -/* policy functions */ -BOOL WINAPI SHInitRestricted(LPCVOID unused, LPCVOID inpRegKey); - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* defined(__cplusplus) */ - -#endif /* __WINE_UNDOCSHELL_H */ +/* + * Copyright 1999, 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_UNDOCSHELL_H +#define __WINE_UNDOCSHELL_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" +#include "shlobj.h" + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/**************************************************************************** + * IDList Functions + */ +BOOL WINAPI ILGetDisplayName( + LPCITEMIDLIST pidl, + LPVOID path); + +/* type parameter for ILGetDisplayNameEx() */ +#define ILGDN_FORPARSING 0 +#define ILGDN_NORMAL 1 +#define ILGDN_INFOLDER 2 + +BOOL WINAPI ILGetDisplayNameEx( + LPSHELLFOLDER psf, + LPCITEMIDLIST pidl, + LPVOID path, + DWORD type); + +LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl); +void WINAPI ILGlobalFree(LPITEMIDLIST pidl); + +LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath); +LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath); + +HRESULT WINAPI SHILCreateFromPathA ( + LPCSTR path, + LPITEMIDLIST * ppidl, + DWORD *attributes); + +HRESULT WINAPI SHILCreateFromPathW ( + LPCWSTR path, + LPITEMIDLIST * ppidl, + DWORD *attributes); + +LPITEMIDLIST WINAPI ILCreateFromPathA(LPCSTR path); +LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path); + +/* + string functions +*/ +BOOL WINAPI StrRetToStrNA(LPSTR,DWORD,LPSTRRET,const ITEMIDLIST*); +BOOL WINAPI StrRetToStrNW(LPWSTR,DWORD,LPSTRRET,const ITEMIDLIST*); + + +/**************************************************************************** +* SHChangeNotifyRegister API +*/ +#define SHCNRF_InterruptLevel 0x0001 +#define SHCNRF_ShellLevel 0x0002 +#define SHCNRF_RecursiveInterrupt 0x1000 /* Must be combined with SHCNRF_InterruptLevel */ +#define SHCNRF_NewDelivery 0x8000 /* Messages use shared memory */ + +/**************************************************************************** + * Shell Common Dialogs + */ + +BOOL WINAPI PickIconDlg( + HWND hwndOwner, + LPSTR lpstrFile, + DWORD nMaxFile, + LPDWORD lpdwIconIndex); + +/* RunFileDlg flags */ +#define RFF_NOBROWSE 0x01 +#define RFF_NODEFAULT 0x02 +#define RFF_CALCDIRECTORY 0x04 +#define RFF_NOLABEL 0x08 +#define RFF_NOSEPARATEMEM 0x20 /* NT only */ + +/* RunFileFlg notification structure */ +typedef struct +{ + NMHDR hdr; + LPCSTR lpFile; + LPCSTR lpDirectory; + int nShow; +} NM_RUNFILEDLG, * LPNM_RUNFILEDLG; + +/* RunFileDlg notification return values */ +#define RF_OK 0x00 +#define RF_CANCEL 0x01 +#define RF_RETRY 0x02 + +void WINAPI RunFileDlg( + HWND hwndOwner, + HICON hIcon, + LPCSTR lpstrDirectory, + LPCSTR lpstrTitle, + LPCSTR lpstrDescription, + UINT uFlags); + +void WINAPI ExitWindowsDialog(HWND hwndOwner); + +BOOL WINAPI GetFileNameFromBrowse( + HWND hwndOwner, + LPSTR lpstrFile, + DWORD nMaxFile, + LPCSTR lpstrInitialDir, + LPCSTR lpstrDefExt, + LPCSTR lpstrFilter, + LPCSTR lpstrTitle); + +BOOL WINAPI SHFindComputer( + LPCITEMIDLIST pidlRoot, + LPCITEMIDLIST pidlSavedSearch); + +void WINAPI SHHandleDiskFull(HWND hwndOwner, + UINT uDrive); + +int WINAPI SHOutOfMemoryMessageBox( + HWND hwndOwner, + LPCSTR lpCaption, + UINT uType); + +DWORD WINAPI SHNetConnectionDialog( + HWND hwndOwner, + LPCSTR lpstrRemoteName, + DWORD dwType); + +/**************************************************************************** + * Memory Routines + */ + +/* The Platform SDK's shlobj.h header defines similar functions with a + * leading underscore. However those are unusable because of the leading + * underscore, because they have an incorrect calling convention, and + * because these functions are not exported by name anyway. + */ +HANDLE WINAPI SHAllocShared( + LPVOID pv, + ULONG cb, + DWORD pid); + +BOOL WINAPI SHFreeShared( + HANDLE hMem, + DWORD pid); + +LPVOID WINAPI SHLockShared( + HANDLE hMem, + DWORD pid); + +BOOL WINAPI SHUnlockShared(LPVOID pv); + +/**************************************************************************** + * Cabinet Window Messages + */ + +#define CWM_SETPATH (WM_USER + 2) +#define CWM_WANTIDLE (WM_USER + 3) +#define CWM_GETSETCURRENTINFO (WM_USER + 4) +#define CWM_SELECTITEM (WM_USER + 5) +#define CWM_SELECTITEMSTR (WM_USER + 6) +#define CWM_GETISHELLBROWSER (WM_USER + 7) +#define CWM_TESTPATH (WM_USER + 9) +#define CWM_STATECHANGE (WM_USER + 10) +#define CWM_GETPATH (WM_USER + 12) + +/* CWM_TESTPATH types */ +#define CWTP_ISEQUAL 0 +#define CWTP_ISCHILD 1 + +/* CWM_TESTPATH structure */ +typedef struct +{ + DWORD dwType; + ITEMIDLIST idl; +} CWTESTPATHSTRUCT,* LPCWTESTPATHSTRUCT; + +/**************************************************************************** + * System Imagelist Routines + */ + +int WINAPI Shell_GetCachedImageIndex( + LPCSTR lpszFileName, + UINT nIconIndex, + BOOL bSimulateDoc); + +BOOL WINAPI Shell_GetImageLists( + HIMAGELIST *lphimlLarge, + HIMAGELIST *lphimlSmall); + +HICON WINAPI SHGetFileIcon( + DWORD dwReserved, + LPCSTR lpszPath, + DWORD dwFileAttributes, + UINT uFlags); + +BOOL WINAPI FileIconInit(BOOL bFullInit); + +/**************************************************************************** + * File Menu Routines + */ +/* FileMenu_Create nSelHeight constants */ +#define FM_DEFAULT_SELHEIGHT -1 +#define FM_FULL_SELHEIGHT 0 + +/* FileMenu_Create flags */ +#define FMF_SMALL_ICONS 0x00 +#define FMF_LARGE_ICONS 0x08 +#define FMF_NO_COLUMN_BREAK 0x10 + +HMENU WINAPI FileMenu_Create( + COLORREF crBorderColor, + int nBorderWidth, + HBITMAP hBorderBmp, + int nSelHeight, + UINT uFlags); + +void WINAPI FileMenu_Destroy(HMENU hMenu); + +/* FileMenu_AppendItem constants */ +#define FM_SEPARATOR (LPCSTR)1 +#define FM_BLANK_ICON -1 +#define FM_DEFAULT_HEIGHT 0 + +BOOL WINAPI FileMenu_AppendItem( + HMENU hMenu, + LPCSTR lpszText, + UINT uID, + int iIcon, + HMENU hMenuPopup, + int nItemHeight); + +/* FileMenu_InsertUsingPidl flags */ +#define FMF_NO_EMPTY_ITEM 0x01 +#define FMF_NO_PROGRAM_GROUPS 0x04 + +/* FileMenu_InsertUsingPidl callback function */ +typedef void (CALLBACK *LPFNFMCALLBACK)(LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlFile); + +int WINAPI FileMenu_InsertUsingPidl( + HMENU hMenu, + UINT uID, + LPCITEMIDLIST pidl, + UINT uFlags, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback); + +int WINAPI FileMenu_ReplaceUsingPidl( + HMENU hMenu, + UINT uID, + LPCITEMIDLIST pidl, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback); + +void WINAPI FileMenu_Invalidate(HMENU hMenu); + +HMENU WINAPI FileMenu_FindSubMenuByPidl( + HMENU hMenu, + LPCITEMIDLIST pidl); + +BOOL WINAPI FileMenu_TrackPopupMenuEx( + HMENU hMenu, + UINT uFlags, + int x, + int y, + HWND hWnd, + LPTPMPARAMS lptpm); + +BOOL WINAPI FileMenu_GetLastSelectedItemPidls( + UINT uReserved, + LPCITEMIDLIST *ppidlFolder, + LPCITEMIDLIST *ppidlItem); + +LRESULT WINAPI FileMenu_MeasureItem( + HWND hWnd, + LPMEASUREITEMSTRUCT lpmis); + +LRESULT WINAPI FileMenu_DrawItem( + HWND hWnd, + LPDRAWITEMSTRUCT lpdis); + +BOOL WINAPI FileMenu_InitMenuPopup(HMENU hMenu); + +void WINAPI FileMenu_AbortInitMenu(void); + +LRESULT WINAPI FileMenu_HandleMenuChar( + HMENU hMenu, + WPARAM wParam); + +BOOL WINAPI FileMenu_DeleteAllItems(HMENU hMenu); + +BOOL WINAPI FileMenu_DeleteItemByCmd( + HMENU hMenu, + UINT uID); + +BOOL WINAPI FileMenu_DeleteItemByIndex( + HMENU hMenu, + UINT uPos); + +BOOL WINAPI FileMenu_DeleteMenuItemByFirstID( + HMENU hMenu, + UINT uID); + +BOOL WINAPI FileMenu_DeleteSeparator(HMENU hMenu); + +BOOL WINAPI FileMenu_EnableItemByCmd( + HMENU hMenu, + UINT uID, + BOOL bEnable); + +DWORD WINAPI FileMenu_GetItemExtent( + HMENU hMenu, + UINT uPos); + +int WINAPI FileMenu_AppendFilesForPidl( + HMENU hMenu, + LPCITEMIDLIST pidl, + BOOL bAddSeparator); + +int WINAPI FileMenu_AddFilesForPidl( + HMENU hMenu, + UINT uReserved, + UINT uID, + LPCITEMIDLIST pidl, + UINT uFlags, + UINT uEnumFlags, + LPFNFMCALLBACK lpfnCallback); + +/**************************************************************************** + * Drag And Drop Routines + */ + +HRESULT WINAPI SHRegisterDragDrop( + HWND hWnd, + LPDROPTARGET lpDropTarget); + +HRESULT WINAPI SHRevokeDragDrop(HWND hWnd); + +BOOL WINAPI DAD_DragEnter(HWND hWnd); + +BOOL WINAPI DAD_SetDragImageFromListView( + HWND hWnd, + POINT pt); + +BOOL WINAPI DAD_ShowDragImage(BOOL bShow); + +HRESULT WINAPI CIDLData_CreateFromIDArray( + LPCITEMIDLIST pidlFolder, + DWORD cpidlFiles, + LPCITEMIDLIST *lppidlFiles, + LPDATAOBJECT *ppdataObject); + +/**************************************************************************** + * Path Manipulation Routines + */ + +BOOL WINAPI PathAppendAW(LPVOID lpszPath1, LPCVOID lpszPath2); + +LPVOID WINAPI PathCombineAW(LPVOID szDest, LPCVOID lpszDir, LPCVOID lpszFile); + +LPVOID WINAPI PathAddBackslashAW(LPVOID path); + +LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive); + +LPVOID WINAPI PathFindExtensionAW(LPCVOID path); + +LPVOID WINAPI PathFindFileNameAW(LPCVOID path); + +LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath, DWORD void1, DWORD void2); + +LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath); + +BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath); + +void WINAPI PathRemoveBlanksAW(LPVOID lpszPath); + +VOID WINAPI PathQuoteSpacesAW(LPVOID path); + +void WINAPI PathUnquoteSpacesAW(LPVOID lpszPath); + +BOOL WINAPI PathIsUNCAW(LPCVOID lpszPath); + +BOOL WINAPI PathIsRelativeAW(LPCVOID lpszPath); + +BOOL WINAPI PathIsRootAW(LPCVOID x); + +BOOL WINAPI PathIsExeAW(LPCVOID lpszPath); + +BOOL WINAPI PathIsDirectoryAW(LPCVOID lpszPath); + +BOOL WINAPI PathFileExistsAW(LPCVOID lpszPath); + +BOOL WINAPI PathMatchSpecAW(LPVOID lpszPath, LPVOID lpszSpec); + +BOOL WINAPI PathMakeUniqueNameAW( + LPVOID lpszBuffer, + DWORD dwBuffSize, + LPCVOID lpszShortName, + LPCVOID lpszLongName, + LPCVOID lpszPathName); + +BOOL WINAPI PathYetAnotherMakeUniqueName( + LPWSTR lpszBuffer, + LPCWSTR lpszPathName, + LPCWSTR lpszShortName, + LPCWSTR lpszLongName); + +BOOL WINAPI PathQualifyA(LPCSTR path); +BOOL WINAPI PathQualifyW(LPCWSTR path); +#define PathQualify WINELIB_NAME_AW(PathQualify) +BOOL WINAPI PathQualifyAW(LPCVOID path); + + +/* PathResolve flags */ +#define PRF_CHECKEXISTANCE 0x01 +#define PRF_EXECUTABLE 0x02 +#define PRF_QUALIFYONPATH 0x04 +#define PRF_WINDOWS31 0x08 + +BOOL WINAPI PathResolveAW(LPVOID lpszPath, LPCVOID *alpszPaths, DWORD dwFlags); + +VOID WINAPI PathSetDlgItemPathAW(HWND hDlg, int nIDDlgItem, LPCVOID lpszPath); + +/* PathProcessCommand flags */ +#define PPCF_QUOTEPATH 0x01 /* implies PPCF_INCLUDEARGS */ +#define PPCF_INCLUDEARGS 0x02 +#define PPCF_NODIRECTORIES 0x10 +#define PPCF_DONTRESOLVE 0x20 +#define PPCF_PATHISRELATIVE 0x40 + +HRESULT WINAPI PathProcessCommandAW(LPCVOID lpszPath, LPVOID lpszBuff, + DWORD dwBuffSize, DWORD dwFlags); + +void WINAPI PathStripPathAW(LPVOID lpszPath); + +BOOL WINAPI PathStripToRootAW(LPVOID lpszPath); + +void WINAPI PathRemoveArgsAW(LPVOID lpszPath); + +void WINAPI PathRemoveExtensionAW(LPVOID lpszPath); + +int WINAPI PathParseIconLocationAW(LPVOID lpszPath); + +BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2); + +BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs); + +/**************************************************************************** + * Shell Namespace Routines + */ + +/* Generic structure used by several messages */ +typedef struct +{ + DWORD dwReserved; + DWORD dwReserved2; + LPCITEMIDLIST pidl; + LPDWORD lpdwUser; +} SFVCBINFO, * LPSFVCBINFO; +typedef const SFVCBINFO * LPCSFVCBINFO; + +/* SFVCB_SELECTIONCHANGED structure */ +typedef struct +{ + UINT uOldState; + UINT uNewState; + LPCITEMIDLIST pidl; + LPDWORD lpdwUser; +} SFVSELECTSTATE, * LPSFVSELECTSTATE; +typedef const SFVSELECTSTATE * LPCSFVSELECTSTATE; + +/* SFVCB_COPYHOOKCALLBACK structure */ +typedef struct +{ + HWND hwnd; + UINT wFunc; + UINT wFlags; + LPCSTR pszSrcFile; + DWORD dwSrcAttribs; + LPCSTR pszDestFile; + DWORD dwDestAttribs; +} SFVCOPYHOOKINFO, * LPSFVCOPYHOOKINFO; +typedef const SFVCOPYHOOKINFO * LPCSFVCOPYHOOKINFO; + +/* SFVCB_GETDETAILSOF structure */ +typedef struct +{ + LPCITEMIDLIST pidl; + int fmt; + int cx; + STRRET lpText; +} SFVCOLUMNINFO, * LPSFVCOLUMNINFO; + +/**************************************************************************** + * Misc Stuff + */ + +/* SHWaitForFileToOpen flags */ +#define SHWFF_ADD 0x01 +#define SHWFF_REMOVE 0x02 +#define SHWFF_WAIT 0x04 + +BOOL WINAPI SHWaitForFileToOpen( + LPCITEMIDLIST pidl, + DWORD dwFlags, + DWORD dwTimeout); + +WORD WINAPI ArrangeWindows( + HWND hwndParent, + DWORD dwReserved, + LPCRECT lpRect, + WORD cKids, + CONST HWND * lpKids); + +/* RegisterShellHook types */ +#define RSH_DEREGISTER 0 +#define RSH_REGISTER 1 +#define RSH_REGISTER_PROGMAN 2 +#define RSH_REGISTER_TASKMAN 3 + +BOOL WINAPI RegisterShellHook( + HWND hWnd, + DWORD dwType); + +/* SHCreateDefClassObject callback function */ +typedef HRESULT (CALLBACK *LPFNCDCOCALLBACK)( + LPUNKNOWN pUnkOuter, + REFIID riidObject, + LPVOID *ppvObject); + +HRESULT WINAPI SHCreateDefClassObject( + REFIID riidFactory, + LPVOID *ppvFactory, + LPFNCDCOCALLBACK lpfnCallback, + LPDWORD lpdwUsage, + REFIID riidObject); + +void WINAPI SHFreeUnusedLibraries(void); + +/* SHCreateLinks flags */ +#define SHCLF_PREFIXNAME 0x01 +#define SHCLF_CREATEONDESKTOP 0x02 + +HRESULT WINAPI SHCreateLinks( + HWND hWnd, + LPCSTR lpszDir, + LPDATAOBJECT lpDataObject, + UINT uFlags, + LPITEMIDLIST *lppidlLinks); + +DWORD WINAPI CheckEscapesA(LPSTR string, DWORD len); +DWORD WINAPI CheckEscapesW(LPWSTR string, DWORD len); + +/* policy functions */ +BOOL WINAPI SHInitRestricted(LPCVOID unused, LPCVOID inpRegKey); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_UNDOCSHELL_H */ diff --git a/reactos/lib/shell32/version.h b/reactos/lib/shell32/version.h index 7ac3ee70761..70ae98d7d46 100644 --- a/reactos/lib/shell32/version.h +++ b/reactos/lib/shell32/version.h @@ -1,28 +1,28 @@ -/* - * Shared Resource/DllGetVersion version information - * - * Copyright (C) 2004 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define WINE_FILEVERSION_MAJOR 6 -#define WINE_FILEVERSION_MINOR 0 -#define WINE_FILEVERSION_BUILD 2600 -#define WINE_FILEVERSION_PLATFORMID 1 - -/* FIXME: when libs/wpp gets fixed to support concatenation we can remove - * this and define it in version.rc */ -#define WINE_FILEVERSION "6.0.2600.1" +/* + * Shared Resource/DllGetVersion version information + * + * Copyright (C) 2004 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINE_FILEVERSION_MAJOR 5 +#define WINE_FILEVERSION_MINOR 0 +#define WINE_FILEVERSION_BUILD 3900 +#define WINE_FILEVERSION_PLATFORMID 6975 + +/* FIXME: when libs/wpp gets fixed to support concatenation we can remove + * this and define it in version.rc */ +#define WINE_FILEVERSION "5.0.3900.6975" diff --git a/reactos/lib/shell32/version.rc b/reactos/lib/shell32/version.rc index 32a8d626adc..255ae21d034 100644 --- a/reactos/lib/shell32/version.rc +++ b/reactos/lib/shell32/version.rc @@ -1,27 +1,27 @@ -/* - * version information for shell32.dll - * - * Copyright (C) 2003 John K. Hohm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "version.h" - -#define WINE_OLESELFREGISTER -#define WINE_FILEVERSION WINE_FILEVERSION_MAJOR,WINE_FILEVERSION_MINOR,WINE_FILEVERSION_BUILD,WINE_FILEVERSION_PLATFORMID -#define WINE_FILENAME_STR "shell32.dll" - -#include +/* + * version information for shell32.dll + * + * Copyright (C) 2003 John K. Hohm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "version.h" + +#define WINE_OLESELFREGISTER +#define WINE_FILEVERSION WINE_FILEVERSION_MAJOR,WINE_FILEVERSION_MINOR,WINE_FILEVERSION_BUILD,WINE_FILEVERSION_PLATFORMID +#define WINE_FILENAME_STR "shell32.dll" + +#include diff --git a/reactos/lib/shell32/version16.rc b/reactos/lib/shell32/version16.rc index 27dd1ee6dfd..3620824dae3 100644 --- a/reactos/lib/shell32/version16.rc +++ b/reactos/lib/shell32/version16.rc @@ -1,24 +1,24 @@ -/* - * Copyright 2001 Dmitry Timoshkov - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define WINE_FILEDESCRIPTION_STR "Wine core dll" -#define WINE_FILENAME_STR "shell.dll" -#define WINE_FILEVERSION 4,0,0,0 -#define WINE_FILEVERSION_STR "4.0" - -#include "wine/wine_common_ver.rc" +/* + * Copyright 2001 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINE_FILEDESCRIPTION_STR "Wine core dll" +#define WINE_FILENAME_STR "shell.dll" +#define WINE_FILEVERSION 4,0,0,0 +#define WINE_FILEVERSION_STR "4.0" + +#include "wine/wine_common_ver.rc" diff --git a/reactos/lib/shellext/slayer/slayer.c b/reactos/lib/shellext/slayer/slayer.c index 9fe32077552..08b5d6ca0bb 100644 --- a/reactos/lib/shellext/slayer/slayer.c +++ b/reactos/lib/shellext/slayer/slayer.c @@ -860,7 +860,7 @@ RegisterPropSheetHandler(LPTSTR szType, LPWSTR szGuid) HRESULT STDCALL DllRegisterServer(VOID) { - LONG e; + LONG e = E_ACCESSDENIED; HKEY hk; WCHAR szGuid[40]; WCHAR szDescription[255]; diff --git a/reactos/lib/shlwapi/msgbox.c b/reactos/lib/shlwapi/msgbox.c index 03e921b1f25..7b2785d20b1 100644 --- a/reactos/lib/shlwapi/msgbox.c +++ b/reactos/lib/shlwapi/msgbox.c @@ -273,8 +273,7 @@ INT_PTR WINAPI SHMessageBoxCheckA(HWND hWnd, LPCSTR lpszText, LPCSTR lpszTitle, iRetVal = SHMessageBoxCheckW(hWnd, szTextBuff, lpszTitle ? szTitleBuff : NULL, dwType, iRet, szIdBuff); - if (szTextBuff) - HeapFree(GetProcessHeap(), 0, szTextBuff); + HeapFree(GetProcessHeap(), 0, szTextBuff); return iRetVal; } diff --git a/reactos/lib/shlwapi/ordinal.c b/reactos/lib/shlwapi/ordinal.c index 3bf0f4bf26b..86dedb543db 100644 --- a/reactos/lib/shlwapi/ordinal.c +++ b/reactos/lib/shlwapi/ordinal.c @@ -42,15 +42,12 @@ #include "shlguid.h" #include "wingdi.h" #include "shlobj.h" -#include "olectl.h" #include "shellapi.h" #include "commdlg.h" #include "wine/unicode.h" -#include "servprov.h" #include "winreg.h" #include "wine/debug.h" #include "shlwapi.h" -#include "winnt.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -611,7 +608,7 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen) *buflen, NULL, NULL); *buflen = buflenW ? convlen : 0; - if(langbufW) HeapFree(GetProcessHeap(), 0, langbufW); + HeapFree(GetProcessHeap(), 0, langbufW); return retval; } @@ -621,9 +618,9 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen) * Convert a GUID to a string. * * PARAMS - * guid [I] GUID to convert - * str [O] Destination for string - * cmax [I] Length of output buffer + * guid [I] GUID to convert + * lpszDest [O] Destination for string + * cchMax [I] Length of output buffer * * RETURNS * The length of the string created. @@ -651,15 +648,35 @@ INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax) /************************************************************************* * @ [SHLWAPI.24] * - * Unicode version of SHStringFromGUIDA. + * Convert a GUID to a string. + * + * PARAMS + * guid [I] GUID to convert + * str [O] Destination for string + * cmax [I] Length of output buffer + * + * RETURNS + * The length of the string created. */ INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax) { - char xguid[40]; - INT iLen = SHStringFromGUIDA(guid, xguid, cchMax); + WCHAR xguid[40]; + INT iLen; + static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-', + '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2', + 'X','%','0','2','X','%','0','2','X','}',0}; - if (iLen) - MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax); + TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax); + + sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); + + iLen = strlenW(xguid) + 1; + + if (iLen > cchMax) + return 0; + memcpy(lpszDest, xguid, iLen*sizeof(WCHAR)); return iLen; } @@ -1940,7 +1957,7 @@ HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID) mi.fMask = MIIM_SUBMENU; if (!GetMenuItemInfoA(hMenu, uID, 0, &mi)) - return (HMENU)NULL; + return NULL; return mi.hSubMenu; } @@ -2422,8 +2439,8 @@ HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle wc.cbClsExtra = 0; wc.cbWndExtra = 4; wc.hInstance = shlwapi_hInstance; - wc.hIcon = (HICON)0; - wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW); + wc.hIcon = NULL; + wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW; wc.lpszMenuName = NULL; wc.lpszClassName = szClass; @@ -2709,8 +2726,8 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle wc.cbClsExtra = 0; wc.cbWndExtra = 4; wc.hInstance = shlwapi_hInstance; - wc.hIcon = (HICON)0; - wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW); + wc.hIcon = NULL; + wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW; wc.lpszMenuName = NULL; wc.lpszClassName = szClass; @@ -2723,10 +2740,10 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle hWndParent, hMenu, shlwapi_hInstance, 0); if (hWnd) { - SetWindowLongA(hWnd, DWL_MSGRESULT, z); + SetWindowLongW(hWnd, DWL_MSGRESULT, z); if (wndProc) - SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc); + SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc); } return hWnd; } diff --git a/reactos/lib/shlwapi/regstream.c b/reactos/lib/shlwapi/regstream.c index 7910efbdbea..14c48d21c05 100644 --- a/reactos/lib/shlwapi/regstream.c +++ b/reactos/lib/shlwapi/regstream.c @@ -94,8 +94,7 @@ static ULONG WINAPI IStream_fnRelease(IStream *iface) { TRACE(" destroying SHReg IStream (%p)\n",This); - if (This->pbBuffer) - HeapFree(GetProcessHeap(),0,This->pbBuffer); + HeapFree(GetProcessHeap(),0,This->pbBuffer); if (This->hKey) RegCloseKey(This->hKey); @@ -388,8 +387,7 @@ IStream * WINAPI SHOpenRegStream2A(HKEY hKey, LPCSTR pszSubkey, dwType == REG_BINARY) return IStream_Create(hStrKey, lpBuff, dwLength); - if (lpBuff) - HeapFree (GetProcessHeap(), 0, lpBuff); + HeapFree (GetProcessHeap(), 0, lpBuff); if (hStrKey) RegCloseKey(hStrKey); return NULL; @@ -418,8 +416,7 @@ IStream * WINAPI SHOpenRegStream2W(HKEY hKey, LPCWSTR pszSubkey, dwType == REG_BINARY) return IStream_Create(hStrKey, lpBuff, dwLength); - if (lpBuff) - HeapFree (GetProcessHeap(), 0, lpBuff); + HeapFree (GetProcessHeap(), 0, lpBuff); if (hStrKey) RegCloseKey(hStrKey); return NULL; diff --git a/reactos/lib/shlwapi/stopwatch.c b/reactos/lib/shlwapi/stopwatch.c index 9c10beab97f..406c0821ed8 100644 --- a/reactos/lib/shlwapi/stopwatch.c +++ b/reactos/lib/shlwapi/stopwatch.c @@ -32,15 +32,10 @@ #define NONAMELESSUNION #define NONAMELESSSTRUCT -#include "wine/unicode.h" #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" #include "winreg.h" #include "winternl.h" -#define NO_SHLWAPI_STREAM -#include "shlwapi.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); diff --git a/reactos/lib/shlwapi/string.c b/reactos/lib/shlwapi/string.c index 15b66debc7b..fc6b6f7ccd3 100644 --- a/reactos/lib/shlwapi/string.c +++ b/reactos/lib/shlwapi/string.c @@ -599,7 +599,7 @@ LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch) while (lpszStr <= lpszEnd && *lpszStr) { - if (!ChrCmpIA(*lpszSearch, *lpszStr)) + if (!ChrCmpIW(*lpszSearch, *lpszStr)) { if (!StrCmpNIW(lpszStr, lpszSearch, iLen)) lpszRet = (LPWSTR)lpszStr; @@ -2186,7 +2186,7 @@ INT WINAPI StrCmpLogicalW(LPCWSTR lpszStr, LPCWSTR lpszComp) return 1; else { - iDiff = SHLWAPI_ChrCmpHelperA(*lpszStr,*lpszComp,NORM_IGNORECASE); + iDiff = SHLWAPI_ChrCmpHelperW(*lpszStr,*lpszComp,NORM_IGNORECASE); if (iDiff > 0) return 1; else if (iDiff < 0) @@ -2208,12 +2208,12 @@ typedef struct tagSHLWAPI_BYTEFORMATS LONGLONG dLimit; double dDivisor; double dNormaliser; - LPCSTR lpszFormat; - CHAR wPrefix; + LPCWSTR lpwszFormat; + WCHAR wPrefix; } SHLWAPI_BYTEFORMATS; /************************************************************************* - * StrFormatByteSize64A [SHLWAPI.@] + * StrFormatByteSizeW [SHLWAPI.@] * * Create a string containing an abbreviated byte count of up to 2^63-1. * @@ -2228,12 +2228,12 @@ typedef struct tagSHLWAPI_BYTEFORMATS * NOTES * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW(). */ -LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax) +LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax) { - static const char szBytes[] = "%ld bytes"; - static const char sz3_0[] = "%3.0f"; - static const char sz3_1[] = "%3.1f"; - static const char sz3_2[] = "%3.2f"; + static const WCHAR wszBytes[] = {'%','l','d',' ','b','y','t','e','s',0}; + static const WCHAR wsz3_0[] = {'%','3','.','0','f',0}; + static const WCHAR wsz3_1[] = {'%','3','.','1','f',0}; + static const WCHAR wsz3_2[] = {'%','3','.','2','f',0}; #define KB ((ULONGLONG)1024) #define MB (KB*KB) @@ -2243,25 +2243,25 @@ LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax) static const SHLWAPI_BYTEFORMATS bfFormats[] = { - { 10*KB, 10.24, 100.0, sz3_2, 'K' }, /* 10 KB */ - { 100*KB, 102.4, 10.0, sz3_1, 'K' }, /* 100 KB */ - { 1000*KB, 1024.0, 1.0, sz3_0, 'K' }, /* 1000 KB */ - { 10*MB, 10485.76, 100.0, sz3_2, 'M' }, /* 10 MB */ - { 100*MB, 104857.6, 10.0, sz3_1, 'M' }, /* 100 MB */ - { 1000*MB, 1048576.0, 1.0, sz3_0, 'M' }, /* 1000 MB */ - { 10*GB, 10737418.24, 100.0, sz3_2, 'G' }, /* 10 GB */ - { 100*GB, 107374182.4, 10.0, sz3_1, 'G' }, /* 100 GB */ - { 1000*GB, 1073741824.0, 1.0, sz3_0, 'G' }, /* 1000 GB */ - { 10*TB, 10485.76, 100.0, sz3_2, 'T' }, /* 10 TB */ - { 100*TB, 104857.6, 10.0, sz3_1, 'T' }, /* 100 TB */ - { 1000*TB, 1048576.0, 1.0, sz3_0, 'T' }, /* 1000 TB */ - { 10*PB, 10737418.24, 100.00, sz3_2, 'P' }, /* 10 PB */ - { 100*PB, 107374182.4, 10.00, sz3_1, 'P' }, /* 100 PB */ - { 1000*PB, 1073741824.0, 1.00, sz3_0, 'P' }, /* 1000 PB */ - { 0, 10995116277.76, 100.00, sz3_2, 'E' } /* EB's, catch all */ + { 10*KB, 10.24, 100.0, wsz3_2, 'K' }, /* 10 KB */ + { 100*KB, 102.4, 10.0, wsz3_1, 'K' }, /* 100 KB */ + { 1000*KB, 1024.0, 1.0, wsz3_0, 'K' }, /* 1000 KB */ + { 10*MB, 10485.76, 100.0, wsz3_2, 'M' }, /* 10 MB */ + { 100*MB, 104857.6, 10.0, wsz3_1, 'M' }, /* 100 MB */ + { 1000*MB, 1048576.0, 1.0, wsz3_0, 'M' }, /* 1000 MB */ + { 10*GB, 10737418.24, 100.0, wsz3_2, 'G' }, /* 10 GB */ + { 100*GB, 107374182.4, 10.0, wsz3_1, 'G' }, /* 100 GB */ + { 1000*GB, 1073741824.0, 1.0, wsz3_0, 'G' }, /* 1000 GB */ + { 10*TB, 10485.76, 100.0, wsz3_2, 'T' }, /* 10 TB */ + { 100*TB, 104857.6, 10.0, wsz3_1, 'T' }, /* 100 TB */ + { 1000*TB, 1048576.0, 1.0, wsz3_0, 'T' }, /* 1000 TB */ + { 10*PB, 10737418.24, 100.00, wsz3_2, 'P' }, /* 10 PB */ + { 100*PB, 107374182.4, 10.00, wsz3_1, 'P' }, /* 100 PB */ + { 1000*PB, 1073741824.0, 1.00, wsz3_0, 'P' }, /* 1000 PB */ + { 0, 10995116277.76, 100.00, wsz3_2, 'E' } /* EB's, catch all */ }; - char szBuff[32]; - char szAdd[4]; + WCHAR wszBuff[32]; + WCHAR wszAdd[] = {' ','?','B',0}; double dBytes; UINT i = 0; @@ -2272,7 +2272,7 @@ LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax) if (llBytes < 1024) /* 1K */ { - snprintf (lpszDest, cchMax, szBytes, (long)llBytes); + snprintfW(lpszDest, cchMax, wszBytes, (long)llBytes); return lpszDest; } @@ -2298,30 +2298,26 @@ LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax) dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser; - sprintf(szBuff, bfFormats[i].lpszFormat, dBytes); - szAdd[0] = ' '; - szAdd[1] = bfFormats[i].wPrefix; - szAdd[2] = 'B'; - szAdd[3] = '\0'; - strcat(szBuff, szAdd); - strncpy(lpszDest, szBuff, cchMax); + sprintfW(wszBuff, bfFormats[i].lpwszFormat, dBytes); + wszAdd[1] = bfFormats[i].wPrefix; + strcatW(wszBuff, wszAdd); + strncpyW(lpszDest, wszBuff, cchMax); return lpszDest; } /************************************************************************* - * StrFormatByteSizeW [SHLWAPI.@] + * StrFormatByteSize64A [SHLWAPI.@] * - * See StrFormatByteSize64A. + * See StrFormatByteSizeW. */ -LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest, - UINT cchMax) +LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax) { - char szBuff[32]; + WCHAR wszBuff[32]; - StrFormatByteSize64A(llBytes, szBuff, sizeof(szBuff)); + StrFormatByteSizeW(llBytes, wszBuff, sizeof(wszBuff)/sizeof(WCHAR)); if (lpszDest) - MultiByteToWideChar(CP_ACP, 0, szBuff, -1, lpszDest, cchMax); + WideCharToMultiByte(CP_ACP, 0, wszBuff, -1, lpszDest, cchMax, 0, 0); return lpszDest; } @@ -2560,6 +2556,7 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, { SHTruncateString(mem, *lpiLen); lstrcpynA(lpDstStr, mem, *lpiLen + 1); + HeapFree(GetProcessHeap(), 0, mem); return *lpiLen + 1; } HeapFree(GetProcessHeap(), 0, mem); @@ -2568,7 +2565,6 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, lpDstStr[*lpiLen] = '\0'; return *lpiLen; } - break; default: break; } diff --git a/reactos/lib/shlwapi/thread.c b/reactos/lib/shlwapi/thread.c index 4ed75a096d6..8edbd9da02c 100644 --- a/reactos/lib/shlwapi/thread.c +++ b/reactos/lib/shlwapi/thread.c @@ -288,7 +288,7 @@ BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData, ti.pfnCallback = pfnCallback; ti.pData = pData; ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE; - ti.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL); + ti.hEvent = CreateEventW(NULL,FALSE,FALSE,NULL); /* Hold references to the current thread and IE process, if desired */ if(dwFlags & CTF_THREAD_REF) diff --git a/reactos/lib/shlwapi/url.c b/reactos/lib/shlwapi/url.c index 5230a0dad09..db67c348b36 100644 --- a/reactos/lib/shlwapi/url.c +++ b/reactos/lib/shlwapi/url.c @@ -444,6 +444,7 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, break; default: FIXME("how did we get here - state=%d\n", state); + HeapFree(GetProcessHeap(), 0, lpszUrlCpy); return E_INVALIDARG; } } @@ -1416,7 +1417,7 @@ HRESULT WINAPI UrlHashW(LPCWSTR pszUrl, unsigned char *lpDest, DWORD nDestLen) * return the same digests for the same URL. */ WideCharToMultiByte(0, 0, pszUrl, -1, szUrl, MAX_PATH, 0, 0); - HashData((PBYTE)szUrl, (int)strlen(szUrl), lpDest, nDestLen); + HashData((const BYTE*)szUrl, (int)strlen(szUrl), lpDest, nDestLen); return S_OK; } @@ -1631,6 +1632,8 @@ BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis) DWORD res1; LPCSTR last; + TRACE("(%s %d)\n", debugstr_a(pszUrl), Urlis); + switch (Urlis) { case URLIS_OPAQUE: @@ -1650,6 +1653,8 @@ BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis) return (last >= pszUrl && (*last == '/' || *last == '\\' )); case URLIS_URL: + return PathIsURLA(pszUrl); + case URLIS_NOHISTORY: case URLIS_APPLIABLE: case URLIS_HASQUERY: @@ -1671,6 +1676,8 @@ BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis) DWORD res1; LPCWSTR last; + TRACE("(%s %d)\n", debugstr_w(pszUrl), Urlis); + switch (Urlis) { case URLIS_OPAQUE: @@ -1690,6 +1697,8 @@ BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis) return (last >= pszUrl && (*last == '/' || *last == '\\')); case URLIS_URL: + return PathIsURLW(pszUrl); + case URLIS_NOHISTORY: case URLIS_APPLIABLE: case URLIS_HASQUERY: diff --git a/reactos/lib/shlwapi/wsprintf.c b/reactos/lib/shlwapi/wsprintf.c index 24970a25a38..61fb5effc39 100644 --- a/reactos/lib/shlwapi/wsprintf.c +++ b/reactos/lib/shlwapi/wsprintf.c @@ -28,8 +28,8 @@ #include "windef.h" #include "winbase.h" -#include "wingdi.h" -#include "winuser.h" +#define NO_SHLWAPI_REG +#include "shlwapi.h" #include "wine/debug.h" @@ -284,7 +284,7 @@ static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg, * Success: The number of characters written. * Failure: -1. */ -INT WINAPI wvnsprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args ) +INT WINAPI wvnsprintfA( LPSTR buffer, INT maxlen, LPCSTR spec, va_list args ) { WPRINTF_FORMAT format; LPSTR p = buffer; @@ -389,7 +389,7 @@ INT WINAPI wvnsprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args ) * * See wvnsprintfA. */ -INT WINAPI wvnsprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args ) +INT WINAPI wvnsprintfW( LPWSTR buffer, INT maxlen, LPCWSTR spec, va_list args ) { WPRINTF_FORMAT format; LPWSTR p = buffer; diff --git a/reactos/lib/smdll/compses.c b/reactos/lib/smdll/compses.c new file mode 100644 index 00000000000..cc29d4e3507 --- /dev/null +++ b/reactos/lib/smdll/compses.c @@ -0,0 +1,39 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/smlib/compses.c + * PURPOSE: Call SM API SM_API_COMPLETE_SESSION + */ +#define NTOS_MODE_USER +#include +#include +#include + +NTSTATUS STDCALL +SmCompleteSession (HANDLE hSmApiPort, HANDLE hSbApiPort, HANDLE hApiPort) +{ + NTSTATUS Status; + SM_PORT_MESSAGE SmReqMsg; + + /* Marshal Ses in the LPC message */ + SmReqMsg.CompSes.hApiPort = hApiPort; + SmReqMsg.CompSes.hSbApiPort = hSbApiPort; + + /* SM API to invoke */ + SmReqMsg.ApiIndex = SM_API_COMPLETE_SESSION; + + /* Port message */ + SmReqMsg.Header.MessageType = LPC_NEW_MESSAGE; + SmReqMsg.Header.DataSize = SM_PORT_DATA_SIZE(SmReqMsg.CompSes); + SmReqMsg.Header.MessageSize = SM_PORT_MESSAGE_SIZE; + Status = NtRequestWaitReplyPort (hSmApiPort, (PLPC_MESSAGE) & SmReqMsg, (PLPC_MESSAGE) & SmReqMsg); + if (NT_SUCCESS(Status)) + { + return SmReqMsg.Status; + } + DbgPrint ("%s failed (Status=0x%08lx)\n", __FUNCTION__, Status); + return Status; +} + +/* EOF */ diff --git a/reactos/lib/smdll/connect.c b/reactos/lib/smdll/connect.c new file mode 100644 index 00000000000..24fbca2d138 --- /dev/null +++ b/reactos/lib/smdll/connect.c @@ -0,0 +1,83 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/smdll/connect.c + * PURPOSE: Connect to the API LPC port exposed by the SM + */ +#define NTOS_MODE_USER +#include +#include +#include +#include + +/********************************************************************** + * NAME EXPORTED + * SmConnectApiPort/4 + * + * DESCRIPTION + * Connect to SM API port and register a session "begin" port (Sb) + * or to issue API requests to SmApiPort. + * + * ARGUMENTS + * pSbApiPortName: name of the Sb port the calling subsystem + * server already created in the system name space; + * hSbApiPort: LPC port handle (checked, but not used); + * dwSubsystem: a valid IMAGE_SUBSYSTEM_xxx value; + * phSmApiPort: a pointer to a HANDLE, which will be + * filled with a valid client-side LPC comm port. + * + * RETURN VALUE + * If all three optional values are omitted, an LPC status. + * STATUS_INVALID_PARAMETER_MIX if PortName is defined and + * both hSbApiPort and dwSubsystem are 0. + */ +NTSTATUS STDCALL +SmConnectApiPort (IN PUNICODE_STRING pSbApiPortName OPTIONAL, + IN HANDLE hSbApiPort OPTIONAL, + IN DWORD dwSubsystem OPTIONAL, + IN OUT PHANDLE phSmApiPort) +{ + UNICODE_STRING SmApiPortName; + SECURITY_QUALITY_OF_SERVICE SecurityQos; + NTSTATUS Status = STATUS_SUCCESS; + SM_CONNECT_DATA ConnectData = {0,{0}}; + ULONG ConnectDataLength = 0; + + if (pSbApiPortName) + { + if (NULL == hSbApiPort || IMAGE_SUBSYSTEM_UNKNOWN == dwSubsystem) + { + return STATUS_INVALID_PARAMETER_MIX; + } + ConnectData.Subsystem = dwSubsystem; + memmove (& ConnectData.SbName, pSbApiPortName->Buffer, pSbApiPortName->Length); + } + ConnectDataLength = sizeof (ConnectData); + + SecurityQos.Length = sizeof (SecurityQos); + SecurityQos.ImpersonationLevel = SecurityIdentification; + SecurityQos.ContextTrackingMode = TRUE; + SecurityQos.EffectiveOnly = TRUE; + + RtlInitUnicodeString (& SmApiPortName, SM_API_PORT_NAME); + + Status = NtConnectPort ( + phSmApiPort, + & SmApiPortName, + & SecurityQos, + NULL, + NULL, + NULL, + & ConnectData, + & ConnectDataLength + ); + if (NT_SUCCESS(Status)) + { + return STATUS_SUCCESS; + } + DbgPrint ("%s failed (Status=0x%08lx)\n", __FUNCTION__, Status); + return Status; +} + +/* EOF */ diff --git a/reactos/lib/smdll/dllmain.c b/reactos/lib/smdll/dllmain.c new file mode 100644 index 00000000000..10beccdaedc --- /dev/null +++ b/reactos/lib/smdll/dllmain.c @@ -0,0 +1,17 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS + * FILE: lib/smdll/dllmain.c + * PURPOSE: SM Helper Library + */ + +#define NTOS_MODE_USER +#include + +BOOL STDCALL DllMain(HANDLE hinstDll, DWORD fdwReason, LPVOID fImpLoad) +{ + return TRUE; +} + +/* EOF */ diff --git a/reactos/lib/smdll/execpgm.c b/reactos/lib/smdll/execpgm.c new file mode 100644 index 00000000000..c0d67e52bb4 --- /dev/null +++ b/reactos/lib/smdll/execpgm.c @@ -0,0 +1,49 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/smdll/execpgm.c + * PURPOSE: Call SM API SM_API_EXECPGM + */ +#define NTOS_MODE_USER +#include +#include +#include +#include + +NTSTATUS STDCALL +SmExecuteProgram (HANDLE hSmApiPort, PUNICODE_STRING Pgm) +{ + NTSTATUS Status; + SM_PORT_MESSAGE SmReqMsg; + + + /* Check Pgm's length */ + if (Pgm->Length > (sizeof (Pgm->Buffer[0]) * SM_EXEXPGM_MAX_LENGTH)) + { + return STATUS_INVALID_PARAMETER; + } + /* Marshal Pgm in the LPC message */ + RtlZeroMemory (& SmReqMsg, sizeof SmReqMsg); + SmReqMsg.ExecPgm.NameLength = Pgm->Length; + RtlCopyMemory (SmReqMsg.ExecPgm.Name, Pgm->Buffer, Pgm->Length); + + /* SM API to invoke */ + SmReqMsg.ApiIndex = SM_API_EXECUTE_PROGRAMME; + + /* LPC message */ + SmReqMsg.Header.MessageType = LPC_NEW_MESSAGE; + SmReqMsg.Header.DataSize = SM_PORT_DATA_SIZE(SmReqMsg.ExecPgm); + SmReqMsg.Header.MessageSize = SM_PORT_MESSAGE_SIZE; + + /* Call SM and wait for a reply */ + Status = NtRequestWaitReplyPort (hSmApiPort, (PLPC_MESSAGE) & SmReqMsg, (PLPC_MESSAGE) & SmReqMsg); + if (NT_SUCCESS(Status)) + { + return SmReqMsg.Status; + } + DbgPrint ("%s failed (Status=0x%08lx)\n", __FUNCTION__, Status); + return Status; +} + +/* EOF */ diff --git a/reactos/lib/smdll/makefile b/reactos/lib/smdll/makefile new file mode 100644 index 00000000000..3275d1b26ee --- /dev/null +++ b/reactos/lib/smdll/makefile @@ -0,0 +1,34 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = smdll + +TARGET_SDKLIBS = ntdll.a + +TARGET_CFLAGS = -I./include -Wall -Werror + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS + +TARGET_LFLAGS = -nostartfiles -nostdlib + +#TARGET_BASE = + +TARGET_OBJECTS = \ + dllmain.o \ + connect.o \ + execpgm.o \ + compses.o + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/depend.mk + +# EOF diff --git a/reactos/lib/smdll/readme.txt b/reactos/lib/smdll/readme.txt new file mode 100644 index 00000000000..af75bd866d4 --- /dev/null +++ b/reactos/lib/smdll/readme.txt @@ -0,0 +1,18 @@ +$Id$ + +This is SMDLL: a helper library to talk to the ReactOS session manager (SM). + +It should be linked in the following components: + +a) the SM itself, because it registers for managing native processes + IMAGE_SUBSYSTEM_NATIVE; + +b) environment subsystem servers, because each one should register in + the SM its own subsystem (willing to manage those processes); + +c) terminal emulators for optional subsystems, like posixw32 and os2w32, + to ask the SM to start the optional subsystem server they need connect to; + +d) system and development utilites to debug/query the SM. + +2004-02-15 ea \ No newline at end of file diff --git a/reactos/lib/smdll/smdll.def b/reactos/lib/smdll/smdll.def new file mode 100644 index 00000000000..0c2e91eb482 --- /dev/null +++ b/reactos/lib/smdll/smdll.def @@ -0,0 +1,5 @@ +LIBRARY SMDLL.DLL +EXPORTS +SmCompleteSession@12 +SmConnectApiPort@16 +SmExecuteProgram@8 diff --git a/reactos/lib/smdll/smdll.rc b/reactos/lib/smdll/smdll.rc new file mode 100644 index 00000000000..4195671e0b1 --- /dev/null +++ b/reactos/lib/smdll/smdll.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS SM Helper\0" +#define REACTOS_STR_INTERNAL_NAME "smdll.dll\0" +#define REACTOS_STR_ORIGINAL_FILENAME "smdll.dll\0" +#include diff --git a/reactos/lib/smdll/smdll.xml b/reactos/lib/smdll/smdll.xml new file mode 100644 index 00000000000..93512330b29 --- /dev/null +++ b/reactos/lib/smdll/smdll.xml @@ -0,0 +1,11 @@ + + + . + + ntdll + dllmain.c + connect.c + execpgm.c + compses.c + smdll.rc + diff --git a/reactos/lib/smdll/testapi.c b/reactos/lib/smdll/testapi.c new file mode 100644 index 00000000000..cfb8b453dfd --- /dev/null +++ b/reactos/lib/smdll/testapi.c @@ -0,0 +1,20 @@ +/* $Id$ */ +#define NTOS_MODE_USER +#include +#include + +VOID STDCALL SmPrintPortMessage (PSM_PORT_MESSAGE SmMessage) +{ + DbgPrint ("SM_PORT_MESSAGE %08lx:\n", (ULONG) SmMessage); + DbgPrint (" Header:\n"); + DbgPrint (" MessageType = %u\n", SmMessage->Header.MessageType); + DbgPrint (" DataSize = %d\n", SmMessage->Header.DataSize); + DbgPrint (" MessageSize = %d\n", SmMessage->Header.MessageSize); + DbgPrint (" ApiIndex = %ld\n", SmMessage->ApiIndex); + DbgPrint (" Status = %08lx\n", SmMessage->Status); + DbgPrint (" ExecPgm:\n"); + DbgPrint (" NameLength = %ld\n", SmMessage->ExecPgm.NameLength); + DbgPrint (" Name = %ls\n", (LPWSTR) & SmMessage->ExecPgm.Name); +} +/* EOF */ + diff --git a/reactos/lib/syssetup/install.c b/reactos/lib/syssetup/install.c index 547ff8793a4..39509a461a7 100644 --- a/reactos/lib/syssetup/install.c +++ b/reactos/lib/syssetup/install.c @@ -99,11 +99,13 @@ RunVMWInstall(VOID) #endif -HRESULT CreateShellLink(LPCSTR linkPath, LPCSTR cmd, LPCSTR arg, LPCSTR dir, LPCSTR iconPath, int icon_nr, LPCSTR comment) +HRESULT CreateShellLink(LPCTSTR linkPath, LPCTSTR cmd, LPCTSTR arg, LPCTSTR dir, LPCTSTR iconPath, int icon_nr, LPCTSTR comment) { - IShellLinkA* psl; + IShellLink* psl; IPersistFile* ppf; +#ifndef _UNICODE WCHAR buffer[MAX_PATH]; +#endif /* _UNICODE */ HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl); @@ -135,9 +137,13 @@ HRESULT CreateShellLink(LPCSTR linkPath, LPCSTR cmd, LPCSTR arg, LPCSTR dir, LPC if (SUCCEEDED(hr)) { +#ifdef _UNICODE + hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE); +#else /* _UNICODE */ MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH); hr = ppf->lpVtbl->Save(ppf, buffer, TRUE); +#endif /* _UNICODE */ ppf->lpVtbl->Release(ppf); } @@ -152,16 +158,16 @@ HRESULT CreateShellLink(LPCSTR linkPath, LPCSTR cmd, LPCSTR arg, LPCSTR dir, LPC static VOID CreateCmdLink(VOID) { - char path[MAX_PATH]; - LPSTR p; + TCHAR path[MAX_PATH]; + LPTSTR p; CoInitialize(NULL); - SHGetSpecialFolderPathA(0, path, CSIDL_DESKTOP, TRUE); - p = PathAddBackslashA(path); + SHGetSpecialFolderPath(0, path, CSIDL_DESKTOP, TRUE); + p = PathAddBackslash(path); - strcpy(p, "Command Prompt.lnk"); - CreateShellLink(path, "cmd.exe", "", NULL, NULL, 0, "Open command prompt"); + _tcscpy(p, _T("Command Prompt.lnk")); + CreateShellLink(path, _T("cmd.exe"), _T(""), NULL, NULL, 0, _T("Open command prompt")); CoUninitialize(); } diff --git a/reactos/lib/syssetup/syssetup_De.rc b/reactos/lib/syssetup/syssetup_De.rc index 3b071ba1de6..56a0c93657b 100644 --- a/reactos/lib/syssetup/syssetup_De.rc +++ b/reactos/lib/syssetup/syssetup_De.rc @@ -38,16 +38,16 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "ReactOS Setup" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "The ReactOS developers would like to acknowledge the following Open Source projects, "\ - "(parts of) which were used to create ReactOS:", + LTEXT "Die ReactOS Programmierer wollen folgende Open Source Projekte anerkennen, "\ + "die (teils) verwendet wurden, um ReactOS zu erstellen:", IDC_STATIC,15,7,286,19 LISTBOX IDC_PROJECTS,15,30,286,75,LBS_NOSEL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL - LTEXT "ReactOS is licensed under the GPL, so if you want to reuse or redistribute "\ - "(parts of) it you must respect the GPL", + LTEXT "ReactOS ist unter der GPL veröffentlicht, wenn Sie also (Teile von) ReactOS wiederverwenden "\ + "oder wiederveröffentlichen wollen, müssen Sie die GPL respektieren.", IDC_STATIC,15,110,227,19 - PUSHBUTTON "&View GPL...",IDC_VIEWGPL,251,110,50,19 - LTEXT "Click Next to continue with Setup.",IDC_STATIC,15,136, + PUSHBUTTON "&GPL &ansehen...",IDC_VIEWGPL,251,110,50,19 + LTEXT "Klicken Sie auf Weiter, um mit dem Setup fortzufahren.",IDC_STATIC,15,136, 195,17 END @@ -57,11 +57,11 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "ReactOS Setup" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "Geben Sie ihren Namen und ihre Firma oder Organization ein.", + LTEXT "Geben Sie ihren Namen und ihre Firma oder Organisation ein.", IDC_STATIC, 54, 7, 242, 21 LTEXT "Na&me:", IDC_STATIC, 54, 37, 44, 8 EDITTEXT IDC_OWNERNAME, 132, 35, 163, 14, WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL - LTEXT "&Organization:", IDC_STATIC, 54, 57, 44, 8 + LTEXT "&Organisation:", IDC_STATIC, 54, 57, 44, 8 EDITTEXT IDC_OWNERORGANIZATION, 132, 55, 163, 14, WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL END @@ -93,17 +93,17 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "ReactOS Setup" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "The system locale should match the language of the applications "\ - "you want to use. The user locale controls how numbers, "\ - "currencies, and dates appear.", IDC_STATIC, 53, 7, 253, 20 + LTEXT "Die lokalen Systemeinstellungen sollten mit der Sprache der Anwendungen, "\ + "die Sie nutzen wollen übereinstimmen. Die lokalen Nutzereinstellungen geben vor, "\ + "wie Nummern, Währungen und Datumsangaben dargestellt werden.", IDC_STATIC, 53, 7, 253, 20 LTEXT "", IDC_LOCALETEXT, 53, 29, 250, 16 - LTEXT "To change system or user locale settings, click Customize.", + LTEXT "Um die lokalen Nutzer- oder Systemeinstellungen zu ändern, klicken Sie auf Einstellen", IDC_STATIC, 53, 60, 184, 8 - PUSHBUTTON "&Customize...", IDC_CUSTOMLOCALE, 245, 57, 50, 14 - LTEXT "The keyboard layout controls the characters that appear when you type.", + PUSHBUTTON "&Einstellen...", IDC_CUSTOMLOCALE, 245, 57, 50, 14 + LTEXT "Das Tastaturlayout gibt vor, welche Zeichen erscheinen, wenn Sie eine Taste drücken.", IDC_STATIC, 53, 86, 253, 8 LTEXT "", IDC_LAYOUTTEXT, 53, 100, 250, 16 - LTEXT "To change the keyboard layout, click Customize.", + LTEXT "Um das Tastaturlayout zu ändern, klicken Sie auf Einstellen.", IDC_STATIC, 53, 126, 184, 8 PUSHBUTTON "C&ustomize...", IDC_CUSTOMLAYOUT, 245, 122, 50, 14 END @@ -157,7 +157,7 @@ CAPTION "ReactOS Installation" FONT 8, "MS Shell Dlg" BEGIN LTEXT "Die Installation von ReactOS wurde erfolgreich fertiggestellt.", IDC_STATIC, 13, 12, 212, 16 - LTEXT "Um fortzufahren muss Ihr Computer neu gesratet werden. "\ + LTEXT "Um fortzufahren muss Ihr Computer neu gestartet werden. "\ "Der Computer wird in 15 Minuten automatisch neu gestartet oder wenn Sie auf "\ "Neustart klicken.", IDC_STATIC, 13, 33, 212, 32 /* GROUPBOX "", -1, 7, 3, 231, 106 */ @@ -179,16 +179,16 @@ END STRINGTABLE BEGIN - IDS_ACKTITLE "Acknowledgements" - IDS_ACKSUBTITLE "The shoulders ReactOS stands on and license information" - IDS_OWNERTITLE "Personalize your Software" - IDS_OWNERSUBTITLE "Setup uses this information about yourself to personalize ReactOS." - IDS_COMPUTERTITLE "Computer Name and Administrator Password" - IDS_COMPUTERSUBTITLE "You must provide a name and an Administrator Password for your computer." - IDS_LOCALETITLE "Regional settings" - IDS_LOCALESUBTITLE "You can customize ReactOS for different regions and languages." - IDS_DATETIMETITLE "Date and Time" - IDS_DATETIMESUBTITLE "Set the correct date and time for your computer." + IDS_ACKTITLE "Anerkennungen" + IDS_ACKSUBTITLE "Das Fundament, auf dem ReactOS gebaut ist und Lizenzinformationen" + IDS_OWNERTITLE "Personalisieren Sie ihre Software" + IDS_OWNERSUBTITLE "Das Setup nutzt diese Informationen über Sie, um ReactOS zu personalisieren." + IDS_COMPUTERTITLE "Computername und Administratorpasswort" + IDS_COMPUTERSUBTITLE "Sie müssen einen Namen und ein Adminstratorpasswort für ihren Computer festsetzen." + IDS_LOCALETITLE "Regionale Einstellungen" + IDS_LOCALESUBTITLE "Sie können ReactOS auf unterschiedliche Regionen und Sprachen einstellen." + IDS_DATETIMETITLE "Datum und Uhrzeit" + IDS_DATETIMESUBTITLE "SSetzen Sie das korrekte Datum und Uhrzeit für ihren Computer." IDS_PROCESSTITLE "Process page title" IDS_PROCESSSUBTITLE "Process page subtitle" END diff --git a/reactos/lib/syssetup/wizard.c b/reactos/lib/syssetup/wizard.c index 6ab8f1df3b3..4ddca5662b1 100644 --- a/reactos/lib/syssetup/wizard.c +++ b/reactos/lib/syssetup/wizard.c @@ -1121,6 +1121,62 @@ SetAutoDaylightInfo(HWND hwnd) } +static BOOL +SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData) +{ + HANDLE hToken; + TOKEN_PRIVILEGES priv, previouspriv; + BOOL Ret = FALSE; + + /* + * enable the SeSystemtimePrivilege privilege + */ + + if(OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES, + &hToken)) + { + priv.PrivilegeCount = 1; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if(LookupPrivilegeValue(NULL, + SE_SYSTEMTIME_NAME, + &priv.Privileges[0].Luid)) + { + if(AdjustTokenPrivileges(hToken, + FALSE, + &priv, + sizeof(previouspriv), + &previouspriv, + 0) && + GetLastError() == ERROR_SUCCESS) + { + /* + * we successfully enabled it, we're permitted to change the system time + */ + Ret = SetLocalTime(&SetupData->SystemTime); + + /* + * for the sake of security, restore the previous status again + */ + if(previouspriv.PrivilegeCount > 0) + { + AdjustTokenPrivileges(hToken, + FALSE, + &previouspriv, + 0, + NULL, + 0); + } + } + } + CloseHandle(hToken); + } + + return Ret; +} + + INT_PTR CALLBACK DateTimePageDlgProc(HWND hwndDlg, UINT uMsg, @@ -1167,7 +1223,13 @@ DateTimePageDlgProc(HWND hwndDlg, SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST), SetupData); SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT)); - SetLocalTime(&SetupData->SystemTime); + if(!SetSystemLocalTime(hwndDlg, SetupData)) + { + MessageBox(hwndDlg, + _T("Setup was unable to set the local time."), + _T("ReactOS Setup"), + MB_ICONWARNING | MB_OK); + } } break; diff --git a/reactos/lib/unicode/utf8.c b/reactos/lib/unicode/utf8.c index b6f777b70e8..39bd54bf3b2 100644 --- a/reactos/lib/unicode/utf8.c +++ b/reactos/lib/unicode/utf8.c @@ -145,7 +145,7 @@ int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int unsigned int res; const char *srcend = src + srclen; - if (!dstlen) return get_length_mbs_utf8( src, srclen ); + if (!dstlen) return get_length_mbs_utf8( (const unsigned char*)src, srclen ); for (count = dstlen; count && (src < srcend); count--, dst++) { diff --git a/reactos/lib/urlmon/umon.c b/reactos/lib/urlmon/umon.c index 98b227bb3c8..adac1efccdd 100644 --- a/reactos/lib/urlmon/umon.c +++ b/reactos/lib/urlmon/umon.c @@ -123,9 +123,7 @@ static ULONG WINAPI URLMonikerImpl_Release(IMoniker* iface) /* destroy the object if there's no more reference on it */ if (ref == 0) { - if (This->URLName!=NULL) - HeapFree(GetProcessHeap(),0,This->URLName); - + HeapFree(GetProcessHeap(),0,This->URLName); HeapFree(GetProcessHeap(),0,This); } @@ -186,8 +184,7 @@ static HRESULT WINAPI URLMonikerImpl_Load(IMoniker* iface,IStream* pStm) res = IStream_Read(pStm, &len, sizeof(ULONG), &got); if(SUCCEEDED(res)) { if(got == sizeof(ULONG)) { - if(This->URLName) - HeapFree(GetProcessHeap(), 0, This->URLName); + HeapFree(GetProcessHeap(), 0, This->URLName); This->URLName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(len+1)); if(!This->URLName) res = E_OUTOFMEMORY; @@ -324,6 +321,7 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, IBindStatusCallback *pbscb; BINDINFO bi; DWORD bindf; + IStream *pstr; FIXME("(%p)->(%p,%p,%s,%p): stub\n",This,pbc,pmkToLeft,debugstr_guid(riid),ppvObject); if(pmkToLeft) { @@ -339,32 +337,31 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, We also need to implement IStream ourselves so that IStream_Read can return E_PENDING */ - hres = CreateStreamOnHGlobal(0, TRUE, (IStream**)ppvObject); - + hres = CreateStreamOnHGlobal(0, TRUE, &pstr); if(SUCCEEDED(hres)) { - TRACE("Created dummy stream...\n"); + TRACE("Created dummy stream...\n"); - hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&pbscb); - if(SUCCEEDED(hres)) { - TRACE("Got IBindStatusCallback...\n"); + hres = IBindCtx_GetObjectParam(pbc, (LPOLESTR)BSCBHolder, (IUnknown**)&pbscb); + if(SUCCEEDED(hres)) { + TRACE("Got IBindStatusCallback...\n"); - memset(&bi, 0, sizeof(bi)); - bi.cbSize = sizeof(bi); - bindf = 0; - hres = IBindStatusCallback_GetBindInfo(pbscb, &bindf, &bi); - if(SUCCEEDED(hres)) { - URL_COMPONENTSW url; - WCHAR *host, *path; - DWORD len, lensz = sizeof(len), total_read = 0; - LARGE_INTEGER last_read_pos; - FORMATETC fmt; - STGMEDIUM stg; + memset(&bi, 0, sizeof(bi)); + bi.cbSize = sizeof(bi); + bindf = 0; + hres = IBindStatusCallback_GetBindInfo(pbscb, &bindf, &bi); + if(SUCCEEDED(hres)) { + URL_COMPONENTSW url; + WCHAR *host, *path; + DWORD len, lensz = sizeof(len), total_read = 0; + LARGE_INTEGER last_read_pos; + FORMATETC fmt; + STGMEDIUM stg; - TRACE("got bindinfo. bindf = %08lx extrainfo = %s bindinfof = %08lx bindverb = %08lx iid %s\n", - bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid)); - hres = IBindStatusCallback_OnStartBinding(pbscb, 0, (IBinding*)&This->lpvtbl2); - TRACE("OnStartBinding rets %08lx\n", hres); + TRACE("got bindinfo. bindf = %08lx extrainfo = %s bindinfof = %08lx bindverb = %08lx iid %s\n", + bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid)); + hres = IBindStatusCallback_OnStartBinding(pbscb, 0, (IBinding*)&This->lpvtbl2); + TRACE("OnStartBinding rets %08lx\n", hres); #if 0 if(!registered_wndclass) { @@ -377,80 +374,81 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, URLMON_hInstance, NULL); #endif - memset(&url, 0, sizeof(url)); - url.dwStructSize = sizeof(url); - url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = 1; - InternetCrackUrlW(This->URLName, 0, 0, &url); - host = HeapAlloc(GetProcessHeap(), 0, (url.dwHostNameLength + 1) * sizeof(WCHAR)); - memcpy(host, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR)); - host[url.dwHostNameLength] = '\0'; - path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR)); - memcpy(path, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR)); - path[url.dwUrlPathLength] = '\0'; + memset(&url, 0, sizeof(url)); + url.dwStructSize = sizeof(url); + url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = 1; + InternetCrackUrlW(This->URLName, 0, 0, &url); + host = HeapAlloc(GetProcessHeap(), 0, (url.dwHostNameLength + 1) * sizeof(WCHAR)); + memcpy(host, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR)); + host[url.dwHostNameLength] = '\0'; + path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR)); + memcpy(path, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR)); + path[url.dwUrlPathLength] = '\0'; - This->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/); -/* InternetSetStatusCallback(This->hinternet, URLMON_InternetCallback);*/ + This->hinternet = InternetOpenA("User Agent", 0, NULL, NULL, 0 /*INTERNET_FLAG_ASYNC*/); +/* InternetSetStatusCallback(This->hinternet, URLMON_InternetCallback);*/ - This->hconnect = InternetConnectW(This->hinternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, - INTERNET_SERVICE_HTTP, 0, (DWORD)This); - This->hrequest = HttpOpenRequestW(This->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)This); + This->hconnect = InternetConnectW(This->hinternet, host, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, + INTERNET_SERVICE_HTTP, 0, (DWORD)This); + This->hrequest = HttpOpenRequestW(This->hconnect, NULL, path, NULL, NULL, NULL, 0, (DWORD)This); - hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, 0x22, NULL); - hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL); - hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL); - hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL); - hres = E_OUTOFMEMORY; /* FIXME */ - if(HttpSendRequestW(This->hrequest, NULL, 0, NULL, 0)) { + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, 0x22, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL); + hres = E_OUTOFMEMORY; /* FIXME */ + if(HttpSendRequestW(This->hrequest, NULL, 0, NULL, 0)) { + len = 0; + HttpQueryInfoW(This->hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL); - len = 0; - HttpQueryInfoW(This->hrequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &len, &lensz, NULL); + TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len); - TRACE("res = %ld gle = %08lx url len = %ld\n", hres, GetLastError(), len); + last_read_pos.u.LowPart = last_read_pos.u.HighPart = 0; + fmt.cfFormat = 0; + fmt.ptd = NULL; + fmt.dwAspect = 0; + fmt.lindex = -1; + fmt.tymed = TYMED_ISTREAM; + stg.tymed = TYMED_ISTREAM; + stg.u.pstm = pstr; + stg.pUnkForRelease = NULL; - last_read_pos.u.LowPart = last_read_pos.u.HighPart = 0; - fmt.cfFormat = 0; - fmt.ptd = NULL; - fmt.dwAspect = 0; - fmt.lindex = -1; - fmt.tymed = TYMED_ISTREAM; - stg.tymed = TYMED_ISTREAM; - stg.u.pstm = *(IStream**)ppvObject; - stg.pUnkForRelease = NULL; - - while(1) { - char buf[4096]; - DWORD bufread; - DWORD written; - if(InternetReadFile(This->hrequest, buf, sizeof(buf), &bufread)) { - TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10)); - if(bufread == 0) break; - IStream_Write(*(IStream**)ppvObject, buf, bufread, &written); - total_read += bufread; - IStream_Seek(*(IStream**)ppvObject, last_read_pos, STREAM_SEEK_SET, NULL); - hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, (total_read == bufread) ? - BINDSTATUS_BEGINDOWNLOADDATA : - BINDSTATUS_DOWNLOADINGDATA, NULL); - hres = IBindStatusCallback_OnDataAvailable(pbscb, - (total_read == bufread) ? BSCF_FIRSTDATANOTIFICATION : - BSCF_INTERMEDIATEDATANOTIFICATION, - total_read, &fmt, &stg); - last_read_pos.u.LowPart += bufread; /* FIXME */ - } else - break; + while(1) { + char buf[4096]; + DWORD bufread; + DWORD written; + if(InternetReadFile(This->hrequest, buf, sizeof(buf), &bufread)) { + TRACE("read %ld bytes %s...\n", bufread, debugstr_an(buf, 10)); + if(bufread == 0) break; + IStream_Write(pstr, buf, bufread, &written); + total_read += bufread; + IStream_Seek(pstr, last_read_pos, STREAM_SEEK_SET, NULL); + hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, (total_read == bufread) ? + BINDSTATUS_BEGINDOWNLOADDATA : + BINDSTATUS_DOWNLOADINGDATA, NULL); + hres = IBindStatusCallback_OnDataAvailable(pbscb, + (total_read == bufread) ? BSCF_FIRSTDATANOTIFICATION : + BSCF_INTERMEDIATEDATANOTIFICATION, + total_read, &fmt, &stg); + last_read_pos.u.LowPart += bufread; /* FIXME */ + } else + break; } - hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, BINDSTATUS_ENDDOWNLOADDATA, NULL); - hres = IBindStatusCallback_OnDataAvailable(pbscb, BSCF_LASTDATANOTIFICATION, total_read, &fmt, &stg); - TRACE("OnDataAvail rets %08lx\n", hres); - hres = IBindStatusCallback_OnStopBinding(pbscb, S_OK, NULL); - TRACE("OnStop rets %08lx\n", hres); - hres = S_OK; - } - InternetCloseHandle(This->hrequest); - InternetCloseHandle(This->hconnect); - InternetCloseHandle(This->hinternet); - } - } + hres = IBindStatusCallback_OnProgress(pbscb, total_read, len, BINDSTATUS_ENDDOWNLOADDATA, NULL); + hres = IBindStatusCallback_OnDataAvailable(pbscb, BSCF_LASTDATANOTIFICATION, total_read, &fmt, &stg); + TRACE("OnDataAvail rets %08lx\n", hres); + hres = IBindStatusCallback_OnStopBinding(pbscb, S_OK, NULL); + TRACE("OnStop rets %08lx\n", hres); + hres = S_OK; + } + InternetCloseHandle(This->hrequest); + InternetCloseHandle(This->hconnect); + InternetCloseHandle(This->hinternet); + IBindStatusCallback_Release(pbscb); + } + } } + *ppvObject = (VOID*)pstr; return hres; } @@ -752,7 +750,7 @@ static HRESULT WINAPI URLMonikerImpl_IBinding_Abort(IBinding* iface) static HRESULT WINAPI URLMonikerImpl_IBinding_GetBindResult(IBinding* iface, CLSID* pclsidProtocol, DWORD* pdwResult, LPOLESTR* pszResult, DWORD* pdwReserved) { ICOM_THIS_MULTI(URLMonikerImpl, lpvtbl2, iface); - FIXME("(%p)->(%s, %p, %p, %p): stub\n", This, debugstr_guid(pclsidProtocol), pdwResult, pszResult, pdwReserved); + FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved); return E_NOTIMPL; } @@ -882,8 +880,36 @@ static HRESULT URLMonikerImpl_Construct(URLMonikerImpl* This, LPCOLESTR lpszLeft HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx **pbind) { - FIXME("stub.\n"); - return E_INVALIDARG; + HRESULT hres; + BIND_OPTS bindopts; + IBindCtx *bctx; + + TRACE("(%08lx %p %p %p)\n", reserved, callback, format, pbind); + + if(!callback) + return E_INVALIDARG; + if(format) + FIXME("format is not supported yet\n"); + + hres = CreateBindCtx(0, &bctx); + if(FAILED(hres)) + return hres; + + bindopts.cbStruct = sizeof(BIND_OPTS); + bindopts.grfFlags = BIND_MAYBOTHERUSER; + bindopts.grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE; + bindopts.dwTickCountDeadline = 0; + IBindCtx_SetBindOptions(bctx, &bindopts); + + hres = IBindCtx_RegisterObjectParam(bctx, (LPOLESTR)BSCBHolder, (IUnknown*)callback); + if(FAILED(hres)) { + IBindCtx_Release(bctx); + return hres; + } + + *pbind = bctx; + + return S_OK; } /*********************************************************************** * CreateAsyncBindCtxEx (URLMON.@) @@ -892,7 +918,7 @@ HRESULT WINAPI CreateAsyncBindCtx(DWORD reserved, IBindStatusCallback *callback, * * FIXME * Not implemented. - */ + */ HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options, IBindStatusCallback *callback, IEnumFORMATETC *format, IBindCtx** pbind, DWORD reserved) diff --git a/reactos/lib/user32/controls/static.c b/reactos/lib/user32/controls/static.c index 450557aa206..3e9d44df508 100644 --- a/reactos/lib/user32/controls/static.c +++ b/reactos/lib/user32/controls/static.c @@ -34,7 +34,7 @@ static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style ); static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); -static COLORREF color_windowframe, color_background, color_window; +static COLORREF color_3dshadow, color_3ddkshadow, color_3dhighlight; /* offsets for GetWindowLong for static private information */ #define HFONT_GWL_OFFSET 0 @@ -104,7 +104,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) if ((style & SS_TYPEMASK) != SS_ICON) return 0; prevIcon = (HICON)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hicon ); - if (hicon) + if (hicon && !(style & SS_CENTERIMAGE)) { ICONINFO info; BITMAP bm; @@ -118,7 +118,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) return 0; } SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); } return prevIcon; #else @@ -131,7 +131,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) return 0; } prevIcon = (HICON)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hicon ); - if (hicon) + if (hicon && !(style & SS_CENTERIMAGE)) { SetWindowPos( hwnd, 0, 0, 0, info->nWidth, info->nHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER ); @@ -153,14 +153,14 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) if ((style & SS_TYPEMASK) != SS_BITMAP) return 0; if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) { #ifdef __REACTOS__ - OutputDebugStringA("huh? hBitmap!=0, but not bitmap\n"); + OutputDebugStringA("huh? hBitmap!=0, but not bitmap\n"); #else ERR("huh? hBitmap!=0, but not bitmap\n"); #endif return 0; } hOldBitmap = (HBITMAP)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hBitmap ); - if (hBitmap) + if (hBitmap && !(style & SS_CENTERIMAGE)) { BITMAP bm; GetObjectW(hBitmap, sizeof(bm), &bm); @@ -244,6 +244,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style) } } +static VOID STATIC_InitColours() +{ + color_3ddkshadow = GetSysColor(COLOR_3DDKSHADOW); + color_3dshadow = GetSysColor(COLOR_3DSHADOW); + color_3dhighlight = GetSysColor(COLOR_3DHIGHLIGHT); +} + /*********************************************************************** * StaticWndProc_common */ @@ -266,10 +273,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, #endif return -1; } - /* initialise colours */ - color_windowframe = GetSysColor(COLOR_WINDOWFRAME); - color_background = GetSysColor(COLOR_BACKGROUND); - color_window = GetSysColor(COLOR_WINDOW); + STATIC_InitColours(); break; case WM_NCDESTROY: @@ -302,9 +306,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, break; case WM_SYSCOLORCHANGE: - color_windowframe = GetSysColor(COLOR_WINDOWFRAME); - color_background = GetSysColor(COLOR_BACKGROUND); - color_window = GetSysColor(COLOR_WINDOW); + STATIC_InitColours(); InvalidateRect(hwnd, NULL, TRUE); break; @@ -328,7 +330,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, else hIcon = STATIC_LoadIconA(hwnd, (LPCSTR)lParam); /* FIXME : should we also return the previous hIcon here ??? */ - STATIC_SetIcon(hwnd, hIcon, style); + STATIC_SetIcon(hwnd, hIcon, full_style); break; } case SS_BITMAP: @@ -338,7 +340,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, hBitmap = STATIC_LoadBitmapW(hwnd, (LPCWSTR)lParam); else hBitmap = STATIC_LoadBitmapA(hwnd, (LPCSTR)lParam); - STATIC_SetBitmap(hwnd, hBitmap, style); + STATIC_SetBitmap(hwnd, hBitmap, full_style); break; } case SS_LEFT: @@ -414,10 +416,10 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, case STM_SETIMAGE: switch(wParam) { case IMAGE_BITMAP: - lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, style ); + lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style ); break; case IMAGE_ICON: - lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, style ); + lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style ); break; default: #ifndef __REACTOS__ @@ -432,7 +434,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, case STM_SETICON16: #endif case STM_SETICON: - lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, style ); + lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style ); InvalidateRect( hwnd, NULL, TRUE ); break; @@ -519,6 +521,8 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) if (style & SS_NOPREFIX) wFormat |= DT_NOPREFIX; + if (style & SS_CENTERIMAGE) + wFormat |= DT_VCENTER; if ((hFont = (HFONT)GetWindowLongA( hwnd, HFONT_GWL_OFFSET ))) SelectObject( hdc, hFont ); @@ -550,27 +554,27 @@ static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style ) switch (style & SS_TYPEMASK) { case SS_BLACKRECT: - hBrush = CreateSolidBrush(color_windowframe); + hBrush = CreateSolidBrush(color_3ddkshadow); FillRect( hdc, &rc, hBrush ); break; case SS_GRAYRECT: - hBrush = CreateSolidBrush(color_background); + hBrush = CreateSolidBrush(color_3dshadow); FillRect( hdc, &rc, hBrush ); break; case SS_WHITERECT: - hBrush = CreateSolidBrush(color_window); + hBrush = CreateSolidBrush(color_3dhighlight); FillRect( hdc, &rc, hBrush ); break; case SS_BLACKFRAME: - hBrush = CreateSolidBrush(color_windowframe); + hBrush = CreateSolidBrush(color_3ddkshadow); FrameRect( hdc, &rc, hBrush ); break; case SS_GRAYFRAME: - hBrush = CreateSolidBrush(color_background); + hBrush = CreateSolidBrush(color_3dshadow); FrameRect( hdc, &rc, hBrush ); break; case SS_WHITEFRAME: - hBrush = CreateSolidBrush(color_window); + hBrush = CreateSolidBrush(color_3dhighlight); FrameRect( hdc, &rc, hBrush ); break; default: @@ -585,13 +589,38 @@ static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style ) RECT rc; HBRUSH hbrush; HICON hIcon; + INT x, y; GetClientRect( hwnd, &rc ); hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd ); FillRect( hdc, &rc, hbrush ); - if ((hIcon = (HICON)GetWindowLongA( hwnd, HICON_GWL_OFFSET ))) - DrawIcon( hdc, rc.left, rc.top, hIcon ); + hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); + if (style & SS_CENTERIMAGE) + { +#ifndef __REACTOS__ + CURSORICONINFO *info = hIcon ? (CURSORICONINFO *)GlobalLock16(HICON_16(hIcon)) : NULL; + x = (rc.right - rc.left)/2 - (info ? info->nWidth/2 : 0); + y = (rc.bottom - rc.top)/2 - (info ? info->nHeight/2 : 0); +#else + ICONINFO info; + BITMAP bm; + + if (!GetIconInfo(hIcon, &info)) + return; + if (!GetObjectW(info.hbmColor, sizeof(BITMAP), &bm)) + return; + x = (rc.right - rc.left)/2 - bm.bmWidth/2; + y = (rc.bottom - rc.top)/2 - bm.bmHeight/2; +#endif + } + else + { + x = rc.left; + y = rc.top; + } + if (hIcon) + DrawIcon( hdc, x, y, hIcon ); } static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style ) @@ -606,12 +635,25 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style ) if ((hBitmap = (HBITMAP)GetWindowLongA( hwnd, HICON_GWL_OFFSET ))) { BITMAP bm; + INT x, y; if(GetObjectType(hBitmap) != OBJ_BITMAP) return; if (!(hMemDC = CreateCompatibleDC( hdc ))) return; GetObjectW(hBitmap, sizeof(bm), &bm); oldbitmap = SelectObject(hMemDC, hBitmap); - BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, + if (style & SS_CENTERIMAGE) + { + RECT rcClient; + GetClientRect(hwnd, &rcClient); + x = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2; + y = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2; + } + else + { + x = 0; + y = 0; + } + BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, oldbitmap); DeleteDC(hMemDC); diff --git a/reactos/lib/user32/misc/desktop.c b/reactos/lib/user32/misc/desktop.c index 52e6a8a18a5..f6aaffc6ad5 100644 --- a/reactos/lib/user32/misc/desktop.c +++ b/reactos/lib/user32/misc/desktop.c @@ -177,7 +177,7 @@ SystemParametersInfoA(UINT uiAction, } } - RedrawWindow(GetDesktopWindow(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + RedrawWindow(GetShellWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE); return Ret; } @@ -280,7 +280,7 @@ SystemParametersInfoW(UINT uiAction, } } - RedrawWindow(GetDesktopWindow(), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + RedrawWindow(GetShellWindow(), NULL, NULL, RDW_INVALIDATE | RDW_ERASE); return Ret; } diff --git a/reactos/lib/user32/misc/exit.c b/reactos/lib/user32/misc/exit.c index 595804a2ef8..083fa4936f0 100644 --- a/reactos/lib/user32/misc/exit.c +++ b/reactos/lib/user32/misc/exit.c @@ -104,7 +104,7 @@ RegisterServicesProcess(DWORD ServicesProcessId) NTSTATUS Status; Request.Type = CSRSS_REGISTER_SERVICES_PROCESS; - Request.Data.RegisterServicesProcessRequest.ProcessId = ServicesProcessId; + Request.Data.RegisterServicesProcessRequest.ProcessId = (HANDLE)ServicesProcessId; Status = CsrClientCallServer(&Request, &Reply, diff --git a/reactos/lib/user32/resources/oic_reactos.ico b/reactos/lib/user32/resources/oic_reactos.ico index 928c09211dc..492e388a939 100644 Binary files a/reactos/lib/user32/resources/oic_reactos.ico and b/reactos/lib/user32/resources/oic_reactos.ico differ diff --git a/reactos/lib/user32/user32.xml b/reactos/lib/user32/user32.xml index 80f88e814a3..50fe1c1a350 100644 --- a/reactos/lib/user32/user32.xml +++ b/reactos/lib/user32/user32.xml @@ -1,5 +1,4 @@ - addsys . include @@ -40,7 +39,7 @@ strpool.c stubs.c timer.c - win32k.c + win32k.S winhelp.c winsta.c wsprintf.c diff --git a/reactos/lib/user32/windows/bitmap.c b/reactos/lib/user32/windows/bitmap.c index 16599d9d8b2..26fae34e3ea 100644 --- a/reactos/lib/user32/windows/bitmap.c +++ b/reactos/lib/user32/windows/bitmap.c @@ -149,7 +149,7 @@ LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad) hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE)ResIcon, SizeofResource(hinst, h2Resource), FALSE, 0x00030000, 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); - if (hIcon) + if (hIcon && 0 != (fuLoad & LR_SHARED)) { NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, (HRSRC)NULL); @@ -157,100 +157,98 @@ LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad) return hIcon; } - else + + if (fuLoad & LR_SHARED) { - if (fuLoad & LR_SHARED) - { - DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n"); - } + DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n"); + } - hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (hFile == NULL) - { - return NULL; - } - - hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - if (hSection == NULL) - { - return NULL; - } - - IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hSection); - if (IconDIR == NULL || 0 != IconDIR->idReserved - || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType)) - { - return NULL; - } - - /* - * Get a handle to the screen dc, the icon we create is going to be - * compatable with it. - */ - hScreenDc = CreateCompatibleDC(0); - if (hScreenDc == NULL) - { - UnmapViewOfFile(IconDIR); - return NULL; - } - - if (fuLoad & LR_MONOCHROME) - { - ColorBits = 1; - } - else - { - ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL); - /* - * FIXME: - * Remove this after proper support for alpha icons will be finished. - */ - if (ColorBits > 8) - ColorBits = 8; - } - - /* Pick the best size. */ - dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits); - if (!dirEntry) - { - UnmapViewOfFile(IconDIR); - return(NULL); - } - - SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes); - memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes); + hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (hFile == NULL) + { + return NULL; } - //at this point we have a copy of the icon image to play with + hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(hFile); + if (hSection == NULL) + { + return NULL; + } - SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; + IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hSection); + if (IconDIR == NULL || 0 != IconDIR->idReserved + || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType)) + { + return NULL; + } - if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) - { + /* + * Get a handle to the screen dc, the icon we create is going to be + * compatable with it. + */ + hScreenDc = CreateCompatibleDC(0); + if (hScreenDc == NULL) + { + UnmapViewOfFile(IconDIR); + return NULL; + } + + if (fuLoad & LR_MONOCHROME) + { + ColorBits = 1; + } + else + { + ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL); + /* + * FIXME: + * Remove this after proper support for alpha icons will be finished. + */ + if (ColorBits > 8) + ColorBits = 8; + } + + /* Pick the best size. */ + dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits); + if (!dirEntry) + { + UnmapViewOfFile(IconDIR); + return(NULL); + } + + SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes); + memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes); + + /* at this point we have a copy of the icon image to play with */ + + SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; + + if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) + { BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage; ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE); - } - else - { + } + else + { ColorCount = SafeIconImage->icHeader.biClrUsed; if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8) { ColorCount = 1 << SafeIconImage->icHeader.biBitCount; } HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD); - } + } - //make data point to the start of the XOR image data - Data = (PBYTE)SafeIconImage + HeaderSize; + /* make data point to the start of the XOR image data */ + Data = (PBYTE)SafeIconImage + HeaderSize; - hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot); - DeleteDC(hScreenDc); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return hIcon; + hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot); + DeleteDC(hScreenDc); + RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); + return hIcon; } @@ -326,7 +324,7 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE) ResIcon, SizeofResource(hinst, h2Resource), TRUE, 0x00030000, width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); - if(hIcon) + if (hIcon && 0 != (fuLoad & LR_SHARED)) { NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, (HRSRC)NULL); diff --git a/reactos/lib/user32/windows/menu.c b/reactos/lib/user32/windows/menu.c index 0b2bfdb43a9..037fef35a5b 100644 --- a/reactos/lib/user32/windows/menu.c +++ b/reactos/lib/user32/windows/menu.c @@ -1884,46 +1884,56 @@ MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) { INT i; ROSMENUITEMINFO ItemInfo; + INT OrigPos; DPRINT("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset); + /* Prevent looping */ + if (0 == MenuInfo->MenuItemCount || 0 == Offset) + return; + else if (Offset < -1) + Offset = -1; + else if (Offset > 1) + Offset = 1; + MenuInitRosMenuItemInfo(&ItemInfo); - if (NO_SELECTED_ITEM != MenuInfo->FocusedItem) + + OrigPos = MenuInfo->FocusedItem; + if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */ { - if (1 == MenuInfo->MenuItemCount) - { - MenuCleanupRosMenuItemInfo(&ItemInfo); - return; - } - else - { - for (i = MenuInfo->FocusedItem + Offset; - 0 <= i && i < MenuInfo->MenuItemCount; - i += Offset) - { - if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) && - 0 == (ItemInfo.fType & MF_SEPARATOR)) - { - MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL); - MenuCleanupRosMenuItemInfo(&ItemInfo); - return; - } - } - } + OrigPos = 0; + i = -1; + } + else + { + i = MenuInfo->FocusedItem; } - for (i = (0 < Offset) ? 0 : MenuInfo->MenuItemCount - 1; - 0 <= i && i < MenuInfo->MenuItemCount; i += Offset) + do { + /* Step */ + i += Offset; + /* Clip and wrap around */ + if (i < 0) + { + i = MenuInfo->MenuItemCount - 1; + } + else if (i >= MenuInfo->MenuItemCount) + { + i = 0; + } + /* If this is a good candidate; */ if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) && - 0 == (ItemInfo.fType & MF_SEPARATOR)) + 0 == (ItemInfo.fType & MF_SEPARATOR) && + 0 == (ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) ) { MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL); MenuCleanupRosMenuItemInfo(&ItemInfo); return; } - } + } while (i != OrigPos); + /* Not found */ MenuCleanupRosMenuItemInfo(&ItemInfo); } @@ -2276,15 +2286,19 @@ MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) return FALSE; } - if (MenuInfo.FocusedItem != Index) - { - MenuSwitchTracking(Mt, &MenuInfo, Index); - } + if (!(Item.fType & MF_SEPARATOR) && + !(Item.fState & (MFS_DISABLED | MFS_GRAYED)) ) + { + if (MenuInfo.FocusedItem != Index) + { + MenuSwitchTracking(Mt, &MenuInfo, Index); + } - /* If the popup menu is not already "popped" */ - if (0 == (Item.fState & MF_MOUSESELECT)) - { - Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + /* If the popup menu is not already "popped" */ + if (0 == (Item.fState & MF_MOUSESELECT)) + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + } } MenuCleanupRosMenuItemInfo(&Item); @@ -2422,6 +2436,7 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) { UINT Index; ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; if (NULL != PtMenu) { @@ -2454,8 +2469,15 @@ MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) } else if (MenuInfo.FocusedItem != Index) { - MenuSwitchTracking(Mt, &MenuInfo, Index); - Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + MenuInitRosMenuItemInfo(&ItemInfo); + if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) && + !(ItemInfo.fType & MF_SEPARATOR) && + !(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED)) ) + { + MenuSwitchTracking(Mt, &MenuInfo, Index); + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + } + MenuCleanupRosMenuItemInfo(&ItemInfo); } return TRUE; @@ -4026,9 +4048,9 @@ InsertMenuItemW( BOOL res = FALSE; mi.hbmpItem = (HBITMAP)0; - // while we could just pass 'lpmii' to win32k, we make a copy so that - // if a bad user passes bad data, we crash his process instead of the - // entire kernel + /* while we could just pass 'lpmii' to win32k, we make a copy so that + if a bad user passes bad data, we crash his process instead of the + entire kernel */ if((lpmii->cbSize == sizeof(MENUITEMINFOW)) || (lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP))) diff --git a/reactos/lib/user32/windows/message.c b/reactos/lib/user32/windows/message.c index eb1e4630337..0c7f79837cd 100644 --- a/reactos/lib/user32/windows/message.c +++ b/reactos/lib/user32/windows/message.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/message.c @@ -2038,7 +2037,7 @@ RealMsgWaitForMultipleObjectsEx( LPHANDLE RealHandles; HANDLE MessageQueueHandle; DWORD Result; - + if (dwFlags & ~(MWMO_WAITALL | MWMO_ALERTABLE | MWMO_INPUTAVAILABLE)) { SetLastError(ERROR_INVALID_PARAMETER); @@ -2067,7 +2066,7 @@ RealMsgWaitForMultipleObjectsEx( return WAIT_FAILED; } - RtlCopyMemory(RealHandles, pHandles, nCount); + RtlCopyMemory(RealHandles, pHandles, nCount * sizeof(HANDLE)); RealHandles[nCount] = MessageQueueHandle; Result = WaitForMultipleObjectsEx(nCount + 1, RealHandles, diff --git a/reactos/lib/version/winetests/Makefile b/reactos/lib/version/winetests/Makefile new file mode 100644 index 00000000000..f0eb749613a --- /dev/null +++ b/reactos/lib/version/winetests/Makefile @@ -0,0 +1,27 @@ +# $Id: Makefile 12745 2005-01-03 02:37:10Z sedwards $ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS -D__USE_W32API -D_WIN32_IE=0x0600 \ + -D_WIN32_WINNT=0x0501 -D__REACTOS__ + +TARGET_NAME = version_test + +TARGET_SDKLIBS = version.a ntdll.a wine.a + +TARGET_OBJECTS = \ + testlist.o \ + info.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/reactos/lib/version/winetests/info.c b/reactos/lib/version/winetests/info.c new file mode 100644 index 00000000000..4e421851730 --- /dev/null +++ b/reactos/lib/version/winetests/info.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2004 Stefan Leichter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winver.h" + +#define MY_LAST_ERROR -1L +#define EXPECT_BAD_PATH__NOT_FOUND \ + ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \ + (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \ + (ERROR_FILE_NOT_FOUND == GetLastError()) || \ + (ERROR_BAD_PATHNAME == GetLastError()), \ + "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \ + "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \ + "expected, got 0x%08lx\n", GetLastError()); +#define EXPECT_INVALID__NOT_FOUND \ + ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \ + (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \ + (ERROR_FILE_NOT_FOUND == GetLastError()) || \ + (ERROR_INVALID_PARAMETER == GetLastError()), \ + "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \ + "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \ + "expected, got 0x%08lx\n", GetLastError()); + +static void test_info_size(void) +{ DWORD hdl, retval; + + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( NULL, NULL); + ok( !retval, + "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n", + retval); + EXPECT_INVALID__NOT_FOUND; + + hdl = 0x55555555; + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( NULL, &hdl); + ok( !retval, + "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n", + retval); + EXPECT_INVALID__NOT_FOUND; + ok( hdl == 0L, + "Handle wrong! 0L expected, got 0x%08lx\n", hdl); + + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "", NULL); + ok( !retval, + "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n", + retval); + EXPECT_BAD_PATH__NOT_FOUND; + + hdl = 0x55555555; + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "", &hdl); + ok( !retval, + "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n", + retval); + EXPECT_BAD_PATH__NOT_FOUND; + ok( hdl == 0L, + "Handle wrong! 0L expected, got 0x%08lx\n", hdl); + + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "kernel32.dll", NULL); + ok( retval, + "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n", + retval); + ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()), + "Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n", + MY_LAST_ERROR, GetLastError()); + + hdl = 0x55555555; + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl); + ok( retval, + "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n", + retval); + ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()), + "Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n", + MY_LAST_ERROR, GetLastError()); + ok( hdl == 0L, + "Handle wrong! 0L expected, got 0x%08lx\n", hdl); + + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "notexist.dll", NULL); + ok( !retval, + "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n", + retval); + ok( (ERROR_FILE_NOT_FOUND == GetLastError()) || + (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || + (MY_LAST_ERROR == GetLastError()), + "Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND " + "(XP)/0x%08lx (NT4) expected, got 0x%08lx\n", MY_LAST_ERROR, GetLastError()); +} + +static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString) +{ + WORD a, b, c, d; + + a = (WORD)(Version >> 48); + b = (WORD)((Version >> 32) & 0xffff); + c = (WORD)((Version >> 16) & 0xffff); + d = (WORD)(Version & 0xffff); + + sprintf(lpszVerString, "%d.%d.%d.%d", a, b, c, d); + + return; +} + +static void test_info(void) +{ + DWORD hdl, retval; + PVOID pVersionInfo = NULL; + BOOL boolret; + VS_FIXEDFILEINFO *pFixedVersionInfo; + UINT uiLength; + char VersionString[MAX_PATH]; + DWORDLONG dwlVersion; + + hdl = 0x55555555; + SetLastError(MY_LAST_ERROR); + retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl); + ok( retval, + "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n", + retval); + ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()), + "Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n", + MY_LAST_ERROR, GetLastError()); + ok( hdl == 0L, + "Handle wrong! 0L expected, got 0x%08lx\n", hdl); + + if ( retval == 0 || hdl != 0) + return; + + pVersionInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retval ); + ok(pVersionInfo != 0, "HeapAlloc failed\n" ); + if (pVersionInfo == 0) + return; + + boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, 0); + ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = 0x%08lx\n", GetLastError()); + ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME), + "Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME) expected, got 0x%08lx\n", + GetLastError()); + + boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, pVersionInfo ); + ok (boolret, "GetFileVersionInfoA failed: GetLastError = 0x%08lx\n", GetLastError()); + if (!boolret) + return; + + boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, &uiLength ); + ok (boolret, "VerQueryValueA failed: GetLastError = 0x%08lx\n", GetLastError()); + if (!boolret) + return; + + dwlVersion = (((DWORDLONG)pFixedVersionInfo->dwFileVersionMS) << 32) + + pFixedVersionInfo->dwFileVersionLS; + + VersionDwordLong2String(dwlVersion, VersionString); + + trace("kernel32.dll version: %s\n", VersionString); + + boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, 0); + ok (boolret, "VerQueryValue failed: GetLastError = 0x%08lx\n", GetLastError()); +} + +START_TEST(info) +{ + test_info_size(); + test_info(); +} diff --git a/reactos/lib/version/winetests/testlist.c b/reactos/lib/version/winetests/testlist.c new file mode 100644 index 00000000000..55b47ea6557 --- /dev/null +++ b/reactos/lib/version/winetests/testlist.c @@ -0,0 +1,25 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +/* stdarg.h is needed for Winelib */ +#include +#include +#include +#include "windef.h" +#include "winbase.h" + +extern void func_info(void); + +struct test +{ + const char *name; + void (*func)(void); +}; + +static const struct test winetest_testlist[] = +{ + { "info", func_info }, + { 0, 0 } +}; + +#define WINETEST_WANT_MAIN +#include "wine/test.h" diff --git a/reactos/lib/wdmguid/makefile b/reactos/lib/wdmguid/makefile new file mode 100644 index 00000000000..bc62179643b --- /dev/null +++ b/reactos/lib/wdmguid/makefile @@ -0,0 +1,24 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = library + +TARGET_NAME = wdmguid + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API -I$(PATH_TO_TOP)/include/wine + +# require os code to explicitly request A/W version of structs/functions +TARGET_CFLAGS += -D_DISABLE_TIDENTS + +TARGET_OBJECTS = wdmguid.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +DEP_OBJECTS := $(TARGET_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) + +include $(PATH_TO_TOP)/tools/depend.mk diff --git a/reactos/lib/wdmguid/wdmguid.c b/reactos/lib/wdmguid/wdmguid.c new file mode 100644 index 00000000000..3070d905925 --- /dev/null +++ b/reactos/lib/wdmguid/wdmguid.c @@ -0,0 +1,11 @@ + +#include + +#define COM_NO_WINDOWS_H +#include "initguid.h" + +#include +#define __GUIDS_ONLY__ +#include + +/* EOF */ diff --git a/reactos/lib/winmm/driver.c b/reactos/lib/winmm/driver.c index 7c254549751..dfc0f0791ce 100644 --- a/reactos/lib/winmm/driver.c +++ b/reactos/lib/winmm/driver.c @@ -368,8 +368,8 @@ HDRVR WINAPI OpenDriverW(LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lPa ret = OpenDriverA(dn, sn, lParam); - if (dn) HeapFree(GetProcessHeap(), 0, dn); - if (sn) HeapFree(GetProcessHeap(), 0, sn); + HeapFree(GetProcessHeap(), 0, dn); + HeapFree(GetProcessHeap(), 0, sn); return ret; } diff --git a/reactos/lib/winmm/joystick.c b/reactos/lib/winmm/joystick.c index d1957082f4a..293a0e79ca4 100644 --- a/reactos/lib/winmm/joystick.c +++ b/reactos/lib/winmm/joystick.c @@ -138,9 +138,9 @@ UINT WINAPI joyGetNumDevs(void) } /************************************************************************** - * joyGetDevCapsA [WINMM.@] + * joyGetDevCapsW [WINMM.@] */ -MMRESULT WINAPI joyGetDevCapsA(UINT_PTR wID, LPJOYCAPSA lpCaps, UINT wSize) +MMRESULT WINAPI joyGetDevCapsW(UINT_PTR wID, LPJOYCAPSW lpCaps, UINT wSize) { if (wID >= MAXJOYSTICK) return JOYERR_PARMS; if (!JOY_LoadDriver(wID)) return MMSYSERR_NODRIVER; @@ -152,43 +152,49 @@ MMRESULT WINAPI joyGetDevCapsA(UINT_PTR wID, LPJOYCAPSA lpCaps, UINT wSize) } /************************************************************************** - * joyGetDevCapsW [WINMM.@] + * joyGetDevCapsA [WINMM.@] */ -MMRESULT WINAPI joyGetDevCapsW(UINT_PTR wID, LPJOYCAPSW lpCaps, UINT wSize) +MMRESULT WINAPI joyGetDevCapsA(UINT_PTR wID, LPJOYCAPSA lpCaps, UINT wSize) { - JOYCAPSA jca; - MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca)); + JOYCAPSW jcw; + MMRESULT ret; - if (ret != JOYERR_NOERROR) return ret; - lpCaps->wMid = jca.wMid; - lpCaps->wPid = jca.wPid; - MultiByteToWideChar( CP_ACP, 0, jca.szPname, -1, lpCaps->szPname, - sizeof(lpCaps->szPname)/sizeof(WCHAR) ); - lpCaps->wXmin = jca.wXmin; - lpCaps->wXmax = jca.wXmax; - lpCaps->wYmin = jca.wYmin; - lpCaps->wYmax = jca.wYmax; - lpCaps->wZmin = jca.wZmin; - lpCaps->wZmax = jca.wZmax; - lpCaps->wNumButtons = jca.wNumButtons; - lpCaps->wPeriodMin = jca.wPeriodMin; - lpCaps->wPeriodMax = jca.wPeriodMax; + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - if (wSize >= sizeof(JOYCAPSW)) { /* Win95 extensions ? */ - lpCaps->wRmin = jca.wRmin; - lpCaps->wRmax = jca.wRmax; - lpCaps->wUmin = jca.wUmin; - lpCaps->wUmax = jca.wUmax; - lpCaps->wVmin = jca.wVmin; - lpCaps->wVmax = jca.wVmax; - lpCaps->wCaps = jca.wCaps; - lpCaps->wMaxAxes = jca.wMaxAxes; - lpCaps->wNumAxes = jca.wNumAxes; - lpCaps->wMaxButtons = jca.wMaxButtons; - MultiByteToWideChar( CP_ACP, 0, jca.szRegKey, -1, lpCaps->szRegKey, - sizeof(lpCaps->szRegKey)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, jca.szOEMVxD, -1, lpCaps->szOEMVxD, - sizeof(lpCaps->szOEMVxD)/sizeof(WCHAR) ); + ret = joyGetDevCapsW(wID, &jcw, sizeof(jcw)); + + if (ret == JOYERR_NOERROR) + { + lpCaps->wMid = jcw.wMid; + lpCaps->wPid = jcw.wPid; + WideCharToMultiByte( CP_ACP, 0, jcw.szPname, -1, lpCaps->szPname, + sizeof(lpCaps->szPname), NULL, NULL ); + lpCaps->wXmin = jcw.wXmin; + lpCaps->wXmax = jcw.wXmax; + lpCaps->wYmin = jcw.wYmin; + lpCaps->wYmax = jcw.wYmax; + lpCaps->wZmin = jcw.wZmin; + lpCaps->wZmax = jcw.wZmax; + lpCaps->wNumButtons = jcw.wNumButtons; + lpCaps->wPeriodMin = jcw.wPeriodMin; + lpCaps->wPeriodMax = jcw.wPeriodMax; + + if (wSize >= sizeof(JOYCAPSA)) { /* Win95 extensions ? */ + lpCaps->wRmin = jcw.wRmin; + lpCaps->wRmax = jcw.wRmax; + lpCaps->wUmin = jcw.wUmin; + lpCaps->wUmax = jcw.wUmax; + lpCaps->wVmin = jcw.wVmin; + lpCaps->wVmax = jcw.wVmax; + lpCaps->wCaps = jcw.wCaps; + lpCaps->wMaxAxes = jcw.wMaxAxes; + lpCaps->wNumAxes = jcw.wNumAxes; + lpCaps->wMaxButtons = jcw.wMaxButtons; + WideCharToMultiByte( CP_ACP, 0, jcw.szRegKey, -1, lpCaps->szRegKey, + sizeof(lpCaps->szRegKey), NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, jcw.szOEMVxD, -1, lpCaps->szOEMVxD, + sizeof(lpCaps->szOEMVxD), NULL, NULL ); + } } return ret; diff --git a/reactos/lib/winmm/lolvldrv.c b/reactos/lib/winmm/lolvldrv.c index 20f9bb36d38..50c029b6103 100644 --- a/reactos/lib/winmm/lolvldrv.c +++ b/reactos/lib/winmm/lolvldrv.c @@ -504,6 +504,7 @@ UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1, case DRVM_MAPPER_PREFERRED_GET: /* FIXME: get from registry someday */ *((LPDWORD)dwParam1) = -1; /* No preferred device */ + *((LPDWORD)dwParam2) = 0; break; case DRV_QUERYDEVICEINTERFACE: diff --git a/reactos/lib/winmm/mci.c b/reactos/lib/winmm/mci.c index 8d1961c263a..ddf0a59770a 100644 --- a/reactos/lib/winmm/mci.c +++ b/reactos/lib/winmm/mci.c @@ -415,10 +415,8 @@ static BOOL MCI_DeleteCommandTable(UINT uTbl) return FALSE; S_MciCmdTable[uTbl].lpTable = NULL; - if (S_MciCmdTable[uTbl].aVerbs) { - HeapFree(GetProcessHeap(), 0, S_MciCmdTable[uTbl].aVerbs); - S_MciCmdTable[uTbl].aVerbs = 0; - } + HeapFree(GetProcessHeap(), 0, S_MciCmdTable[uTbl].aVerbs); + S_MciCmdTable[uTbl].aVerbs = 0; return TRUE; } @@ -1090,7 +1088,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpwstrCommand, LPWSTR lpwstrRet, if (lpwstrRet) MultiByteToWideChar( CP_ACP, 0, lpstrRet, -1, lpwstrRet, uRetLen ); HeapFree(GetProcessHeap(), 0, lpstrCommand); - if (lpstrRet) HeapFree(GetProcessHeap(), 0, lpstrRet); + HeapFree(GetProcessHeap(), 0, lpstrRet); return ret; } diff --git a/reactos/lib/winmm/message16.c b/reactos/lib/winmm/message16.c index deb55af37e4..03a8fb6335f 100644 --- a/reactos/lib/winmm/message16.c +++ b/reactos/lib/winmm/message16.c @@ -1,7 +1,7 @@ /* -*- tab-width: 8; c-basic-offset: 4 -*- */ /* - * MMSYTEM MCI and low level mapping functions + * MMSYSTEM MCI and low level mapping functions * * Copyright 1999 Eric Pouech * @@ -297,14 +297,14 @@ static WINMM_MapType MMDRV_MidiOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LP case MODM_GETDEVCAPS: { - LPMIDIOUTCAPSA moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSA)); + LPMIDIOUTCAPSW moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW)); LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1); if (moc32) { *(LPMIDIOUTCAPS16*)moc32 = moc16; - moc32 = (LPMIDIOUTCAPSA)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16)); + moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16)); *lpParam1 = (DWORD)moc32; - *lpParam2 = sizeof(MIDIOUTCAPSA); + *lpParam2 = sizeof(MIDIOUTCAPSW); ret = WINMM_MAP_OKMEM; } else { @@ -390,13 +390,14 @@ static WINMM_MapType MMDRV_MidiOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LP case MODM_GETDEVCAPS: { - LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)(*lpParam1); + LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)(*lpParam1); LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16)); moc16->wMid = moc32->wMid; moc16->wPid = moc32->wPid; moc16->vDriverVersion = moc32->vDriverVersion; - strcpy(moc16->szPname, moc32->szPname); + WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname, + sizeof(moc16->szPname), NULL, NULL ); moc16->wTechnology = moc32->wTechnology; moc16->wVoices = moc32->wVoices; moc16->wNotes = moc32->wNotes; @@ -455,16 +456,16 @@ static WINMM_MapType MMDRV_MidiOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LP break; case MODM_GETDEVCAPS: { - LPMIDIOUTCAPSA moc32 = (LPMIDIOUTCAPSA)*lpParam1; - LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSA)+sizeof(MIDIOUTCAPS16)); + LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)*lpParam1; + LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPSW)+sizeof(MIDIOUTCAPS16)); if (ptr) { - *(LPMIDIOUTCAPSA*)ptr = moc32; + *(LPMIDIOUTCAPSW*)ptr = moc32; ret = WINMM_MAP_OKMEM; } else { ret = WINMM_MAP_NOMEM; } - *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSA); + *lpParam1 = (DWORD)MapLS(ptr) + sizeof(LPMIDIOUTCAPSW); *lpParam2 = sizeof(MIDIOUTCAPS16); } break; @@ -596,13 +597,14 @@ static WINMM_MapType MMDRV_MidiOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LP case MODM_GETDEVCAPS: { LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1); - LPSTR ptr = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSA); - LPMIDIOUTCAPSA moc32 = *(LPMIDIOUTCAPSA*)ptr; + LPSTR ptr = (LPSTR)moc16 - sizeof(LPMIDIOUTCAPSW); + LPMIDIOUTCAPSW moc32 = *(LPMIDIOUTCAPSW*)ptr; moc32->wMid = moc16->wMid; moc32->wPid = moc16->wPid; moc32->vDriverVersion = moc16->vDriverVersion; - strcpy(moc32->szPname, moc16->szPname); + WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname, + sizeof(moc16->szPname), NULL, NULL ); moc32->wTechnology = moc16->wTechnology; moc32->wVoices = moc16->wVoices; moc32->wNotes = moc16->wNotes; @@ -723,14 +725,14 @@ static WINMM_MapType MMDRV_WaveIn_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LPD break; case WIDM_GETDEVCAPS: { - LPWAVEINCAPSA wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSA)); + LPWAVEINCAPSW wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW)); LPWAVEINCAPS16 wic16 = MapSL(*lpParam1); if (wic32) { *(LPWAVEINCAPS16*)wic32 = wic16; - wic32 = (LPWAVEINCAPSA)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16)); + wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16)); *lpParam1 = (DWORD)wic32; - *lpParam2 = sizeof(WAVEINCAPSA); + *lpParam2 = sizeof(WAVEINCAPSW); ret = WINMM_MAP_OKMEM; } else { @@ -833,13 +835,14 @@ static WINMM_MapType MMDRV_WaveIn_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LPD break; case WIDM_GETDEVCAPS: { - LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)(*lpParam1); + LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)(*lpParam1); LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16)); wic16->wMid = wic32->wMid; wic16->wPid = wic32->wPid; wic16->vDriverVersion = wic32->vDriverVersion; - strcpy(wic16->szPname, wic32->szPname); + WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname, + sizeof(wic16->szPname), NULL, NULL ); wic16->dwFormats = wic32->dwFormats; wic16->wChannels = wic32->wChannels; HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16)); @@ -1010,16 +1013,16 @@ static WINMM_MapType MMDRV_WaveIn_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LPD break; case WIDM_GETDEVCAPS: { - LPWAVEINCAPSA wic32 = (LPWAVEINCAPSA)*lpParam1; - LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSA) + sizeof(WAVEINCAPS16)); + LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)*lpParam1; + LPSTR ptr = HeapAlloc( GetProcessHeap(), 0 ,sizeof(LPWAVEINCAPSW) + sizeof(WAVEINCAPS16)); if (ptr) { - *(LPWAVEINCAPSA*)ptr = wic32; + *(LPWAVEINCAPSW*)ptr = wic32; ret = WINMM_MAP_OKMEM; } else { ret = WINMM_MAP_NOMEM; } - *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSA); + *lpParam1 = MapLS(ptr) + sizeof(LPWAVEINCAPSW); *lpParam2 = sizeof(WAVEINCAPS16); } break; @@ -1109,13 +1112,14 @@ static WINMM_MapType MMDRV_WaveIn_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LPD case WIDM_GETDEVCAPS: { LPWAVEINCAPS16 wic16 = MapSL(*lpParam1); - LPSTR ptr = (LPSTR)wic16 - sizeof(LPWAVEINCAPSA); - LPWAVEINCAPSA wic32 = *(LPWAVEINCAPSA*)ptr; + LPSTR ptr = (LPSTR)wic16 - sizeof(LPWAVEINCAPSW); + LPWAVEINCAPSW wic32 = *(LPWAVEINCAPSW*)ptr; wic32->wMid = wic16->wMid; wic32->wPid = wic16->wPid; wic32->vDriverVersion = wic16->vDriverVersion; - strcpy(wic32->szPname, wic16->szPname); + WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname, + sizeof(wic16->szPname), NULL, NULL ); wic32->dwFormats = wic16->dwFormats; wic32->wChannels = wic16->wChannels; UnMapLS( *lpParam1 ); @@ -1222,14 +1226,14 @@ static WINMM_MapType MMDRV_WaveOut_Map16To32A (UINT wMsg, LPDWORD lpdwUser, LP case WODM_GETDEVCAPS: { - LPWAVEOUTCAPSA woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSA)); + LPWAVEOUTCAPSW woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW)); LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1); if (woc32) { *(LPWAVEOUTCAPS16*)woc32 = woc16; - woc32 = (LPWAVEOUTCAPSA)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16)); + woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16)); *lpParam1 = (DWORD)woc32; - *lpParam2 = sizeof(WAVEOUTCAPSA); + *lpParam2 = sizeof(WAVEOUTCAPSW); ret = WINMM_MAP_OKMEM; } else { @@ -1341,13 +1345,14 @@ static WINMM_MapType MMDRV_WaveOut_UnMap16To32A(UINT wMsg, LPDWORD lpdwUser, LP case WODM_GETDEVCAPS: { - LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)(*lpParam1); + LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)(*lpParam1); LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16)); woc16->wMid = woc32->wMid; woc16->wPid = woc32->wPid; woc16->vDriverVersion = woc32->vDriverVersion; - strcpy(woc16->szPname, woc32->szPname); + WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname, + sizeof(woc16->szPname), NULL, NULL ); woc16->dwFormats = woc32->dwFormats; woc16->wChannels = woc32->wChannels; woc16->dwSupport = woc32->dwSupport; @@ -1416,17 +1421,17 @@ static WINMM_MapType MMDRV_WaveOut_Map32ATo16 (UINT wMsg, LPDWORD lpdwUser, LP case WODM_GETDEVCAPS: { - LPWAVEOUTCAPSA woc32 = (LPWAVEOUTCAPSA)*lpParam1; + LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)*lpParam1; LPSTR ptr = HeapAlloc( GetProcessHeap(), 0, - sizeof(LPWAVEOUTCAPSA) + sizeof(WAVEOUTCAPS16)); + sizeof(LPWAVEOUTCAPSW) + sizeof(WAVEOUTCAPS16)); if (ptr) { - *(LPWAVEOUTCAPSA*)ptr = woc32; + *(LPWAVEOUTCAPSW*)ptr = woc32; ret = WINMM_MAP_OKMEM; } else { ret = WINMM_MAP_NOMEM; } - *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSA); + *lpParam1 = MapLS(ptr) + sizeof(LPWAVEOUTCAPSW); *lpParam2 = sizeof(WAVEOUTCAPS16); } break; @@ -1606,13 +1611,14 @@ static WINMM_MapType MMDRV_WaveOut_UnMap32ATo16(UINT wMsg, LPDWORD lpdwUser, LP case WODM_GETDEVCAPS: { LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1); - LPSTR ptr = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSA); - LPWAVEOUTCAPSA woc32 = *(LPWAVEOUTCAPSA*)ptr; + LPSTR ptr = (LPSTR)woc16 - sizeof(LPWAVEOUTCAPSW); + LPWAVEOUTCAPSW woc32 = *(LPWAVEOUTCAPSW*)ptr; woc32->wMid = woc16->wMid; woc32->wPid = woc16->wPid; woc32->vDriverVersion = woc16->vDriverVersion; - strcpy(woc32->szPname, woc16->szPname); + WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname, + sizeof(woc16->szPname), NULL, NULL ); woc32->dwFormats = woc16->dwFormats; woc32->wChannels = woc16->wChannels; woc32->dwSupport = woc16->dwSupport; diff --git a/reactos/lib/winmm/midimap/.cvsignore b/reactos/lib/winmm/midimap/.cvsignore deleted file mode 100644 index 38400f6e478..00000000000 --- a/reactos/lib/winmm/midimap/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -midimap.drv.dbg.c diff --git a/reactos/lib/winmm/midimap/midimap.c b/reactos/lib/winmm/midimap/midimap.c index 014307f8a5d..227d01febf2 100644 --- a/reactos/lib/winmm/midimap/midimap.c +++ b/reactos/lib/winmm/midimap/midimap.c @@ -32,6 +32,7 @@ #include "winuser.h" #include "mmddk.h" #include "winreg.h" +#include "wine/unicode.h" #include "wine/debug.h" /* @@ -80,7 +81,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msacm); typedef struct tagMIDIOUTPORT { - char name[MAXPNAMELEN]; + WCHAR name[MAXPNAMELEN]; int loaded; HMIDIOUT hMidi; unsigned short uDevID; @@ -105,31 +106,36 @@ static BOOL MIDIMAP_IsBadData(MIDIMAPDATA* mm) return TRUE; } -static BOOL MIDIMAP_FindPort(const char* name, unsigned* dev) +static BOOL MIDIMAP_FindPort(const WCHAR* name, unsigned* dev) { for (*dev = 0; *dev < numMidiOutPorts; (*dev)++) { - TRACE("%s\n", midiOutPorts[*dev].name); - if (strcmp(midiOutPorts[*dev].name, name) == 0) + TRACE("%s\n", wine_dbgstr_w(midiOutPorts[*dev].name)); + if (strcmpW(midiOutPorts[*dev].name, name) == 0) return TRUE; } /* try the form #nnn */ if (*name == '#' && isdigit(name[1])) { - *dev = atoi(name + 1); + const WCHAR* ptr = name + 1; + *dev = 0; + do + { + *dev = *dev * 10 + *ptr - '0'; + } while (isdigit(*++ptr)); if (*dev < numMidiOutPorts) return TRUE; } return FALSE; } -static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const char* port) +static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const WCHAR* port) { unsigned i, dev = 0; if (port != NULL && !MIDIMAP_FindPort(port, &dev)) { - ERR("Registry glitch: couldn't find midi out (%s)\n", port); + ERR("Registry glitch: couldn't find midi out (%s)\n", wine_dbgstr_w(port)); dev = 0; } @@ -142,11 +148,11 @@ static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const char* port) return TRUE; } -static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const char* scheme) +static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const WCHAR* scheme) { HKEY hSchemesKey, hKey, hPortKey; unsigned i, idx, dev; - char buffer[256], port[256]; + WCHAR buffer[256], port[256]; DWORD type, size, mask; for (i = 0; i < 16; i++) mom->ChannelMap[i] = NULL; @@ -157,18 +163,18 @@ static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const char* scheme) { return FALSE; } - if (RegOpenKeyA(hSchemesKey, scheme, &hKey)) + if (RegOpenKeyW(hSchemesKey, scheme, &hKey)) { RegCloseKey(hSchemesKey); return FALSE; } - for (idx = 0; !RegEnumKeyA(hKey, idx, buffer, sizeof(buffer)); idx++) + for (idx = 0; !RegEnumKeyW(hKey, idx, buffer, sizeof(buffer)); idx++) { - if (RegOpenKeyA(hKey, buffer, &hPortKey)) continue; + if (RegOpenKeyW(hKey, buffer, &hPortKey)) continue; size = sizeof(port); - if (RegQueryValueExA(hPortKey, NULL, 0, &type, port, &size)) continue; + if (RegQueryValueExW(hPortKey, NULL, 0, &type, (void*)port, &size)) continue; if (!MIDIMAP_FindPort(port, &dev)) continue; @@ -206,14 +212,15 @@ static BOOL MIDIMAP_LoadSettings(MIDIMAPDATA* mom) else { DWORD type, size, out; - char buffer[256]; + WCHAR buffer[256]; ret = 2; size = sizeof(out); if (!RegQueryValueExA(hKey, "UseScheme", 0, &type, (void*)&out, &size) && out) { + static const WCHAR cs[] = {'C','u','r','r','e','n','t','S','c','h','e','m','e',0}; size = sizeof(buffer); - if (!RegQueryValueExA(hKey, "CurrentScheme", 0, &type, buffer, &size)) + if (!RegQueryValueExW(hKey, cs, 0, &type, (void*)buffer, &size)) { if (!(ret = MIDIMAP_LoadSettingsScheme(mom, buffer))) ret = MIDIMAP_LoadSettingsDefault(mom, NULL); @@ -225,8 +232,9 @@ static BOOL MIDIMAP_LoadSettings(MIDIMAPDATA* mom) } if (ret == 2) { + static const WCHAR ci[] = {'C','u','r','r','e','n','t','I','n','s','t','r','u','m','e','n','t',0}; size = sizeof(buffer); - if (!RegQueryValueExA(hKey, "CurrentInstrument", 0, &type, buffer, &size) && *buffer) + if (!RegQueryValueExW(hKey, ci, 0, &type, (void*)buffer, &size) && *buffer) { ret = MIDIMAP_LoadSettingsDefault(mom, buffer); } @@ -404,12 +412,13 @@ static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) return MMSYSERR_NOERROR; } -static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD size) +static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSW lpMidiCaps, DWORD size) { + static const WCHAR name[] = {'W','i','n','e',' ','m','i','d','i',' ','m','a','p','p','e','r',0}; lpMidiCaps->wMid = 0x00FF; lpMidiCaps->wPid = 0x0001; lpMidiCaps->vDriverVersion = 0x0100; - strcpy(lpMidiCaps->szPname, "Wine midi out mapper"); + lstrcpyW(lpMidiCaps->szPname, name); lpMidiCaps->wTechnology = MOD_MAPPER; lpMidiCaps->wVoices = 0; lpMidiCaps->wNotes = 0; @@ -465,7 +474,7 @@ DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, case MODM_UNPREPARE: return modUnprepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MODM_RESET: return modReset ((MIDIMAPDATA*)dwUser); - case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2); + case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSW)dwParam1,dwParam2); case MODM_GETNUMDEVS: return 1; case MODM_GETVOLUME: return MMSYSERR_NOTSUPPORTED; case MODM_SETVOLUME: return MMSYSERR_NOTSUPPORTED; @@ -484,7 +493,7 @@ DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, */ static DWORD MIDIMAP_drvOpen(LPSTR str) { - MIDIOUTCAPSA moc; + MIDIOUTCAPSW moc; unsigned dev, i; if (midiOutPorts) @@ -495,9 +504,9 @@ static DWORD MIDIMAP_drvOpen(LPSTR str) numMidiOutPorts * sizeof(MIDIOUTPORT)); for (dev = 0; dev < numMidiOutPorts; dev++) { - if (midiOutGetDevCapsA(dev, &moc, sizeof(moc)) == 0L) + if (midiOutGetDevCapsW(dev, &moc, sizeof(moc)) == 0L) { - strcpy(midiOutPorts[dev].name, moc.szPname); + strcpyW(midiOutPorts[dev].name, moc.szPname); midiOutPorts[dev].loaded = 0; midiOutPorts[dev].hMidi = 0; midiOutPorts[dev].uDevID = dev; diff --git a/reactos/lib/winmm/mmio.c b/reactos/lib/winmm/mmio.c index e44af2608bc..4b1ed8573fb 100644 --- a/reactos/lib/winmm/mmio.c +++ b/reactos/lib/winmm/mmio.c @@ -703,7 +703,7 @@ HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO* lpmmioinfo, { INT len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL ); szFn = HeapAlloc( GetProcessHeap(), 0, len ); - if (!szFn) return (HMMIO)NULL; + if (!szFn) return NULL; WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL ); } diff --git a/reactos/lib/winmm/mmsystem.c b/reactos/lib/winmm/mmsystem.c index 4ba03720ef0..1221878ffa9 100644 --- a/reactos/lib/winmm/mmsystem.c +++ b/reactos/lib/winmm/mmsystem.c @@ -1940,7 +1940,7 @@ LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD lpMMThd->hTask = 0; if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) { - lpMMThd->hEvent = CreateEventA(0, 0, 1, 0); + lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL); TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd); if (lpMMThd->dwFlags & 2) { @@ -2712,7 +2712,6 @@ static LRESULT MMIO_Callback16(SEGPTR cb16, LPMMIOINFO lpmmioinfo, UINT uMessage mmioInfo16.adwInfo[0] = lpmmioinfo->adwInfo[0]; mmioInfo16.adwInfo[1] = lpmmioinfo->adwInfo[1]; mmioInfo16.adwInfo[2] = lpmmioinfo->adwInfo[2]; - mmioInfo16.adwInfo[3] = lpmmioinfo->adwInfo[3]; /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */ if ((result = MMIO_Map32To16(uMessage, &lp1, &lp2)) != MMSYSERR_NOERROR) return result; @@ -2733,7 +2732,6 @@ static LRESULT MMIO_Callback16(SEGPTR cb16, LPMMIOINFO lpmmioinfo, UINT uMessage lpmmioinfo->adwInfo[0] = mmioInfo16.adwInfo[0]; lpmmioinfo->adwInfo[1] = mmioInfo16.adwInfo[1]; lpmmioinfo->adwInfo[2] = mmioInfo16.adwInfo[2]; - lpmmioinfo->adwInfo[3] = mmioInfo16.adwInfo[3]; return result; } @@ -2777,7 +2775,6 @@ HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16* lpmmioinfo16, mmioinfo.adwInfo[0] = (DWORD)DosFileHandleToWin32Handle(mmioinfo.adwInfo[0]); mmioinfo.adwInfo[1] = lpmmioinfo16->adwInfo[1]; mmioinfo.adwInfo[2] = lpmmioinfo16->adwInfo[2]; - mmioinfo.adwInfo[3] = lpmmioinfo16->adwInfo[3]; ret = MMIO_Open(szFileName, &mmioinfo, dwOpenFlags, MMIO_PROC_16); MMIO_SetSegmentedBuffer(mmioinfo.hmmio, (SEGPTR)lpmmioinfo16->pchBuffer, FALSE); @@ -2856,7 +2853,6 @@ MMRESULT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uF lpmmioinfo->adwInfo[0] = mmioinfo.adwInfo[0]; lpmmioinfo->adwInfo[1] = mmioinfo.adwInfo[1]; lpmmioinfo->adwInfo[2] = mmioinfo.adwInfo[2]; - lpmmioinfo->adwInfo[3] = mmioinfo.adwInfo[3]; lpmmioinfo->dwReserved1 = 0; lpmmioinfo->dwReserved2 = 0; lpmmioinfo->hmmio = HMMIO_16(mmioinfo.hmmio); @@ -3065,7 +3061,11 @@ UINT16 WINAPI joyGetNumDevs16(void) MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize) { JOYCAPSA jca; - MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca)); + MMRESULT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = joyGetDevCapsA(wID, &jca, sizeof(jca)); if (ret != JOYERR_NOERROR) return ret; lpCaps->wMid = jca.wMid; diff --git a/reactos/lib/winmm/playsound.c b/reactos/lib/winmm/playsound.c index f7be898ca83..7b8c2f1082a 100644 --- a/reactos/lib/winmm/playsound.c +++ b/reactos/lib/winmm/playsound.c @@ -352,7 +352,7 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg) TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX\n", (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize); - s.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD)PlaySound_Callback, (DWORD)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) @@ -374,9 +374,9 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg) } s.dwEventCount = 1L; /* for first buffer */ + index = 0; do { - index = 0; left = mmckInfo.cksize; mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET); @@ -410,8 +410,8 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg) errCleanUp: TRACE("Done playing='%s' => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko"); CloseHandle(s.hEvent); - if (waveHdr) HeapFree(GetProcessHeap(), 0, waveHdr); - if (lpWaveFormat) HeapFree(GetProcessHeap(), 0, lpWaveFormat); + HeapFree(GetProcessHeap(), 0, waveHdr); + HeapFree(GetProcessHeap(), 0, lpWaveFormat); if (hWave) while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100); if (hmmio) mmioClose(hmmio, 0); diff --git a/reactos/lib/winmm/wavemap/.cvsignore b/reactos/lib/winmm/wavemap/.cvsignore deleted file mode 100644 index d57696a1f81..00000000000 --- a/reactos/lib/winmm/wavemap/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -msacm.drv.dbg.c diff --git a/reactos/lib/winmm/wavemap/wavemap.c b/reactos/lib/winmm/wavemap/wavemap.c index 6dc55867aec..9fb05d2db70 100644 --- a/reactos/lib/winmm/wavemap/wavemap.c +++ b/reactos/lib/winmm/wavemap/wavemap.c @@ -37,6 +37,7 @@ #include "mmddk.h" #include "mmreg.h" #include "msacm.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(wavemap); @@ -269,8 +270,8 @@ error: WARN("ret = WAVERR_BADFORMAT\n"); return WAVERR_BADFORMAT; } - WARN("ret = MMSYSERR_ERROR\n"); - return MMSYSERR_ERROR; + WARN("ret = 0x%08lx\n", res); + return res; } static DWORD wodClose(WAVEMAPDATA* wom) @@ -422,13 +423,15 @@ static DWORD wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2) return val; } -static DWORD wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveCaps, DWORD dwParam2) +static DWORD wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSW lpWaveCaps, DWORD dwParam2) { + static const WCHAR name[] = {'W','i','n','e',' ','w','a','v','e',' ','o','u','t',' ','m','a','p','p','e','r',0}; + TRACE("(%04x %p %p %08lx)\n",wDevID, wom, lpWaveCaps, dwParam2); /* if opened low driver, forward message */ if (WAVEMAP_IsData(wom)) - return waveOutGetDevCapsA((UINT)wom->u.out.hInnerWave, lpWaveCaps, dwParam2); + return waveOutGetDevCapsW((UINT)wom->u.out.hInnerWave, lpWaveCaps, dwParam2); /* else if no drivers, nothing to map so return bad device */ if (waveOutGetNumDevs() == 0) { WARN("bad device id\n"); @@ -436,11 +439,11 @@ static DWORD wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveC } /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { - WAVEOUTCAPSA woc; + WAVEOUTCAPSW woc; woc.wMid = 0x00FF; woc.wPid = 0x0001; woc.vDriverVersion = 0x0100; - strcpy(woc.szPname, "Wine wave out mapper"); + lstrcpyW(woc.szPname, name); woc.dwFormats = WAVE_FORMAT_96M08 | WAVE_FORMAT_96S08 | WAVE_FORMAT_96M16 | WAVE_FORMAT_96S16 | WAVE_FORMAT_48M08 | WAVE_FORMAT_48S08 | WAVE_FORMAT_48M16 | WAVE_FORMAT_48S16 | @@ -556,7 +559,7 @@ DWORD WINAPI WAVEMAP_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, case WODM_BREAKLOOP: return wodBreakLoop ((WAVEMAPDATA*)dwUser); case WODM_PREPARE: return wodPrepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2); case WODM_UNPREPARE: return wodUnprepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2); - case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEOUTCAPSA)dwParam1,dwParam2); + case WODM_GETDEVCAPS: return wodGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEOUTCAPSW)dwParam1,dwParam2); case WODM_GETNUMDEVS: return 1; case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED; case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED; @@ -778,8 +781,8 @@ error: WARN("ret = WAVERR_BADFORMAT\n"); return WAVERR_BADFORMAT; } - WARN("ret = MMSYSERR_ERROR\n"); - return MMSYSERR_ERROR; + WARN("ret = 0x%08lx\n", res); + return res; } static DWORD widClose(WAVEMAPDATA* wim) @@ -916,13 +919,13 @@ static DWORD widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2) return val; } -static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCaps, DWORD dwParam2) +static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSW lpWaveCaps, DWORD dwParam2) { TRACE("(%04x, %p %p %08lx)\n", wDevID, wim, lpWaveCaps, dwParam2); /* if opened low driver, forward message */ if (WAVEMAP_IsData(wim)) - return waveInGetDevCapsA((UINT)wim->u.in.hInnerWave, lpWaveCaps, dwParam2); + return waveInGetDevCapsW((UINT)wim->u.in.hInnerWave, lpWaveCaps, dwParam2); /* else if no drivers, nothing to map so return bad device */ if (waveInGetNumDevs() == 0) { WARN("bad device id\n"); @@ -930,11 +933,12 @@ static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCa } /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { - WAVEINCAPSA wic; + WAVEINCAPSW wic; + static const WCHAR init[] = {'W','i','n','e',' ','w','a','v','e',' ','i','n',' ','m','a','p','p','e','r',0}; wic.wMid = 0x00FF; wic.wPid = 0x0001; wic.vDriverVersion = 0x0001; - strcpy(wic.szPname, "Wine wave in mapper"); + strcpyW(wic.szPname, init); wic.dwFormats = WAVE_FORMAT_96M08 | WAVE_FORMAT_96S08 | WAVE_FORMAT_96M16 | WAVE_FORMAT_96S16 | WAVE_FORMAT_48M08 | WAVE_FORMAT_48S08 | WAVE_FORMAT_48M16 | WAVE_FORMAT_48S16 | @@ -1023,7 +1027,7 @@ DWORD WINAPI WAVEMAP_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, case WIDM_ADDBUFFER: return widAddBuffer ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2); case WIDM_PREPARE: return widPrepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2); case WIDM_UNPREPARE: return widUnprepare ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1, dwParam2); - case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEINCAPSA)dwParam1, dwParam2); + case WIDM_GETDEVCAPS: return widGetDevCaps (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEINCAPSW)dwParam1, dwParam2); case WIDM_GETNUMDEVS: return 1; case WIDM_GETPOS: return widGetPosition ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1, dwParam2); case WIDM_RESET: return widReset ((WAVEMAPDATA*)dwUser); diff --git a/reactos/lib/winmm/winemm.h b/reactos/lib/winmm/winemm.h index 4ff8736e635..e5661712c9e 100644 --- a/reactos/lib/winmm/winemm.h +++ b/reactos/lib/winmm/winemm.h @@ -268,7 +268,7 @@ MMRESULT MIDI_StreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen, BOOL bFrom32); UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, - const LPWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, + LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags, BOOL bFrom32); HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO* refmminfo, diff --git a/reactos/lib/winmm/winmm.c b/reactos/lib/winmm/winmm.c index 17c0e2e61cd..f589c505146 100644 --- a/reactos/lib/winmm/winmm.c +++ b/reactos/lib/winmm/winmm.c @@ -97,8 +97,8 @@ static BOOL WINMM_CreateIData(HINSTANCE hInstDLL) /* FIXME crashes in ReactOS WINMM_IData->cs.DebugInfo->Spare[1] = (DWORD)"WINMM_IData"; */ - WINMM_IData->psStopEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - WINMM_IData->psLastEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + WINMM_IData->psStopEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + WINMM_IData->psLastEvent = CreateEventW(NULL, TRUE, FALSE, NULL); TRACE("Created IData (%p)\n", WINMM_IData); return TRUE; } @@ -295,14 +295,25 @@ UINT WINAPI mixerGetNumDevs(void) */ UINT WINAPI mixerGetDevCapsA(UINT_PTR uDeviceID, LPMIXERCAPSA lpCaps, UINT uSize) { - LPWINE_MLD wmld; + MIXERCAPSW micW; + UINT ret; - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIXER, TRUE)) == NULL) - return MMSYSERR_BADDEVICEID; + ret = mixerGetDevCapsW(uDeviceID, &micW, sizeof(micW)); - return MMDRV_Message(wmld, MXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); + if (ret == MMSYSERR_NOERROR) { + MIXERCAPSA micA; + micA.wMid = micW.wMid; + micA.wPid = micW.wPid; + micA.vDriverVersion = micW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, micW.szPname, -1, micA.szPname, + sizeof(micA.szPname), NULL, NULL ); + micA.fdwSupport = micW.fdwSupport; + micA.cDestinations = micW.cDestinations; + memcpy(lpCaps, &micA, min(uSize, sizeof(micA))); + } + return ret; } /************************************************************************** @@ -310,24 +321,14 @@ UINT WINAPI mixerGetDevCapsA(UINT_PTR uDeviceID, LPMIXERCAPSA lpCaps, UINT uSize */ UINT WINAPI mixerGetDevCapsW(UINT_PTR uDeviceID, LPMIXERCAPSW lpCaps, UINT uSize) { - MIXERCAPSA micA; - UINT ret; + LPWINE_MLD wmld; - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA)); - if (ret == MMSYSERR_NOERROR) { - MIXERCAPSW micW; - micW.wMid = micA.wMid; - micW.wPid = micA.wPid; - micW.vDriverVersion = micA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, micA.szPname, -1, micW.szPname, - sizeof(micW.szPname)/sizeof(WCHAR) ); - micW.fdwSupport = micA.fdwSupport; - micW.cDestinations = micA.cDestinations; - memcpy(lpCaps, &micW, min(uSize, sizeof(micW))); - } - return ret; + if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIXER, TRUE)) == NULL) + return MMSYSERR_BADDEVICEID; + + return MMDRV_Message(wmld, MXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); } UINT MIXER_Open(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback, @@ -408,75 +409,76 @@ UINT WINAPI mixerGetID(HMIXEROBJ hmix, LPUINT lpid, DWORD fdwID) } /************************************************************************** - * mixerGetControlDetailsA [WINMM.@] + * mixerGetControlDetailsW [WINMM.@] */ -UINT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdA, +UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdW, DWORD fdwDetails) { LPWINE_MIXER lpwm; UINT uRet = MMSYSERR_NOERROR; - TRACE("(%p, %p, %08lx)\n", hmix, lpmcdA, fdwDetails); + TRACE("(%p, %p, %08lx)\n", hmix, lpmcdW, fdwDetails); if ((uRet = MIXER_GetDev(hmix, fdwDetails, &lpwm)) != MMSYSERR_NOERROR) return uRet; - if (lpmcdA == NULL || lpmcdA->cbStruct != sizeof(*lpmcdA)) + if (lpmcdW == NULL || lpmcdW->cbStruct != sizeof(*lpmcdW)) return MMSYSERR_INVALPARAM; - return MMDRV_Message(&lpwm->mld, MXDM_GETCONTROLDETAILS, (DWORD_PTR)lpmcdA, + return MMDRV_Message(&lpwm->mld, MXDM_GETCONTROLDETAILS, (DWORD_PTR)lpmcdW, fdwDetails, TRUE); } /************************************************************************** - * mixerGetControlDetailsW [WINMM.@] + * mixerGetControlDetailsA [WINMM.@] */ -UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails) +UINT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdA, + DWORD fdwDetails) { DWORD ret = MMSYSERR_NOTENABLED; - TRACE("(%p, %p, %08lx)\n", hmix, lpmcd, fdwDetails); + TRACE("(%p, %p, %08lx)\n", hmix, lpmcdA, fdwDetails); - if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd)) + if (lpmcdA == NULL || lpmcdA->cbStruct != sizeof(*lpmcdA)) return MMSYSERR_INVALPARAM; switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) { case MIXER_GETCONTROLDETAILSF_VALUE: - /* can savely use W structure as it is, no string inside */ - ret = mixerGetControlDetailsA(hmix, lpmcd, fdwDetails); + /* can savely use A structure as it is, no string inside */ + ret = mixerGetControlDetailsW(hmix, lpmcdA, fdwDetails); break; case MIXER_GETCONTROLDETAILSF_LISTTEXT: { - MIXERCONTROLDETAILS_LISTTEXTW *pDetailsW = (MIXERCONTROLDETAILS_LISTTEXTW *)lpmcd->paDetails; - MIXERCONTROLDETAILS_LISTTEXTA *pDetailsA; - int size = max(1, lpmcd->cChannels) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA); + MIXERCONTROLDETAILS_LISTTEXTA *pDetailsA = (MIXERCONTROLDETAILS_LISTTEXTA *)lpmcdA->paDetails; + MIXERCONTROLDETAILS_LISTTEXTW *pDetailsW; + int size = max(1, lpmcdA->cChannels) * sizeof(MIXERCONTROLDETAILS_LISTTEXTW); unsigned int i; - if (lpmcd->u.cMultipleItems != 0) { - size *= lpmcd->u.cMultipleItems; + if (lpmcdA->u.cMultipleItems != 0) { + size *= lpmcdA->u.cMultipleItems; } - pDetailsA = (MIXERCONTROLDETAILS_LISTTEXTA *)HeapAlloc(GetProcessHeap(), 0, size); - lpmcd->paDetails = pDetailsA; - lpmcd->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTA); + pDetailsW = (MIXERCONTROLDETAILS_LISTTEXTW *)HeapAlloc(GetProcessHeap(), 0, size); + lpmcdA->paDetails = pDetailsW; + lpmcdA->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTW); /* set up lpmcd->paDetails */ - ret = mixerGetControlDetailsA(hmix, lpmcd, fdwDetails); + ret = mixerGetControlDetailsW(hmix, lpmcdA, fdwDetails); /* copy from lpmcd->paDetails back to paDetailsW; */ - if(ret == MMSYSERR_NOERROR) { - for(i=0;iu.cMultipleItems*lpmcd->cChannels;i++) { - pDetailsW->dwParam1 = pDetailsA->dwParam1; - pDetailsW->dwParam2 = pDetailsA->dwParam2; - MultiByteToWideChar( CP_ACP, 0, pDetailsA->szName, -1, - pDetailsW->szName, - sizeof(pDetailsW->szName)/sizeof(WCHAR) ); + if (ret == MMSYSERR_NOERROR) { + for (i = 0; i < lpmcdA->u.cMultipleItems * lpmcdA->cChannels; i++) { + pDetailsA->dwParam1 = pDetailsW->dwParam1; + pDetailsA->dwParam2 = pDetailsW->dwParam2; + WideCharToMultiByte( CP_ACP, 0, pDetailsW->szName, -1, + pDetailsA->szName, + sizeof(pDetailsA->szName), NULL, NULL ); pDetailsA++; pDetailsW++; } - pDetailsA -= lpmcd->u.cMultipleItems*lpmcd->cChannels; - pDetailsW -= lpmcd->u.cMultipleItems*lpmcd->cChannels; + pDetailsA -= lpmcdA->u.cMultipleItems * lpmcdA->cChannels; + pDetailsW -= lpmcdA->u.cMultipleItems * lpmcdA->cChannels; } - HeapFree(GetProcessHeap(), 0, pDetailsA); - lpmcd->paDetails = pDetailsW; - lpmcd->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTW); + HeapFree(GetProcessHeap(), 0, pDetailsW); + lpmcdA->paDetails = pDetailsA; + lpmcdA->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTA); } break; default: @@ -492,19 +494,59 @@ UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, UINT WINAPI mixerGetLineControlsA(HMIXEROBJ hmix, LPMIXERLINECONTROLSA lpmlcA, DWORD fdwControls) { - LPWINE_MIXER lpwm; - UINT uRet = MMSYSERR_NOERROR; + MIXERLINECONTROLSW mlcW; + DWORD ret; + unsigned int i; TRACE("(%p, %p, %08lx)\n", hmix, lpmlcA, fdwControls); - if ((uRet = MIXER_GetDev(hmix, fdwControls, &lpwm)) != MMSYSERR_NOERROR) - return uRet; - - if (lpmlcA == NULL || lpmlcA->cbStruct != sizeof(*lpmlcA)) + if (lpmlcA == NULL || lpmlcA->cbStruct != sizeof(*lpmlcA) || + lpmlcA->cbmxctrl != sizeof(MIXERCONTROLA)) return MMSYSERR_INVALPARAM; - return MMDRV_Message(&lpwm->mld, MXDM_GETLINECONTROLS, (DWORD_PTR)lpmlcA, - fdwControls, TRUE); + mlcW.cbStruct = sizeof(mlcW); + mlcW.dwLineID = lpmlcA->dwLineID; + mlcW.u.dwControlID = lpmlcA->u.dwControlID; + mlcW.u.dwControlType = lpmlcA->u.dwControlType; + mlcW.cControls = lpmlcA->cControls; + mlcW.cbmxctrl = sizeof(MIXERCONTROLW); + mlcW.pamxctrl = HeapAlloc(GetProcessHeap(), 0, + mlcW.cControls * mlcW.cbmxctrl); + + ret = mixerGetLineControlsW(hmix, &mlcW, fdwControls); + + if (ret == MMSYSERR_NOERROR) { + lpmlcA->dwLineID = mlcW.dwLineID; + lpmlcA->u.dwControlID = mlcW.u.dwControlID; + lpmlcA->u.dwControlType = mlcW.u.dwControlType; + lpmlcA->cControls = mlcW.cControls; + + for (i = 0; i < mlcW.cControls; i++) { + lpmlcA->pamxctrl[i].cbStruct = sizeof(MIXERCONTROLA); + lpmlcA->pamxctrl[i].dwControlID = mlcW.pamxctrl[i].dwControlID; + lpmlcA->pamxctrl[i].dwControlType = mlcW.pamxctrl[i].dwControlType; + lpmlcA->pamxctrl[i].fdwControl = mlcW.pamxctrl[i].fdwControl; + lpmlcA->pamxctrl[i].cMultipleItems = mlcW.pamxctrl[i].cMultipleItems; + WideCharToMultiByte( CP_ACP, 0, mlcW.pamxctrl[i].szShortName, -1, + lpmlcA->pamxctrl[i].szShortName, + sizeof(lpmlcA->pamxctrl[i].szShortName), NULL, NULL ); + WideCharToMultiByte( CP_ACP, 0, mlcW.pamxctrl[i].szName, -1, + lpmlcA->pamxctrl[i].szName, + sizeof(lpmlcA->pamxctrl[i].szName), NULL, NULL ); + /* sizeof(lpmlcA->pamxctrl[i].Bounds) == + * sizeof(mlcW.pamxctrl[i].Bounds) */ + memcpy(&lpmlcA->pamxctrl[i].Bounds, &mlcW.pamxctrl[i].Bounds, + sizeof(mlcW.pamxctrl[i].Bounds)); + /* sizeof(lpmlcA->pamxctrl[i].Metrics) == + * sizeof(mlcW.pamxctrl[i].Metrics) */ + memcpy(&lpmlcA->pamxctrl[i].Metrics, &mlcW.pamxctrl[i].Metrics, + sizeof(mlcW.pamxctrl[i].Metrics)); + } + } + + HeapFree(GetProcessHeap(), 0, mlcW.pamxctrl); + + return ret; } /************************************************************************** @@ -513,65 +555,25 @@ UINT WINAPI mixerGetLineControlsA(HMIXEROBJ hmix, LPMIXERLINECONTROLSA lpmlcA, UINT WINAPI mixerGetLineControlsW(HMIXEROBJ hmix, LPMIXERLINECONTROLSW lpmlcW, DWORD fdwControls) { - MIXERLINECONTROLSA mlcA; - DWORD ret; - unsigned int i; + LPWINE_MIXER lpwm; + UINT uRet = MMSYSERR_NOERROR; TRACE("(%p, %p, %08lx)\n", hmix, lpmlcW, fdwControls); - if (lpmlcW == NULL || lpmlcW->cbStruct != sizeof(*lpmlcW) || - lpmlcW->cbmxctrl != sizeof(MIXERCONTROLW)) + if ((uRet = MIXER_GetDev(hmix, fdwControls, &lpwm)) != MMSYSERR_NOERROR) + return uRet; + + if (lpmlcW == NULL || lpmlcW->cbStruct != sizeof(*lpmlcW)) return MMSYSERR_INVALPARAM; - mlcA.cbStruct = sizeof(mlcA); - mlcA.dwLineID = lpmlcW->dwLineID; - mlcA.u.dwControlID = lpmlcW->u.dwControlID; - mlcA.u.dwControlType = lpmlcW->u.dwControlType; - mlcA.cControls = lpmlcW->cControls; - mlcA.cbmxctrl = sizeof(MIXERCONTROLA); - mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0, - mlcA.cControls * mlcA.cbmxctrl); - - ret = mixerGetLineControlsA(hmix, &mlcA, fdwControls); - - if (ret == MMSYSERR_NOERROR) { - lpmlcW->dwLineID = mlcA.dwLineID; - lpmlcW->u.dwControlID = mlcA.u.dwControlID; - lpmlcW->u.dwControlType = mlcA.u.dwControlType; - lpmlcW->cControls = mlcA.cControls; - - for (i = 0; i < mlcA.cControls; i++) { - lpmlcW->pamxctrl[i].cbStruct = sizeof(MIXERCONTROLW); - lpmlcW->pamxctrl[i].dwControlID = mlcA.pamxctrl[i].dwControlID; - lpmlcW->pamxctrl[i].dwControlType = mlcA.pamxctrl[i].dwControlType; - lpmlcW->pamxctrl[i].fdwControl = mlcA.pamxctrl[i].fdwControl; - lpmlcW->pamxctrl[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems; - MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szShortName, -1, - lpmlcW->pamxctrl[i].szShortName, - sizeof(lpmlcW->pamxctrl[i].szShortName)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, mlcA.pamxctrl[i].szName, -1, - lpmlcW->pamxctrl[i].szName, - sizeof(lpmlcW->pamxctrl[i].szName)/sizeof(WCHAR) ); - /* sizeof(lpmlcW->pamxctrl[i].Bounds) == - * sizeof(mlcA.pamxctrl[i].Bounds) */ - memcpy(&lpmlcW->pamxctrl[i].Bounds, &mlcA.pamxctrl[i].Bounds, - sizeof(mlcA.pamxctrl[i].Bounds)); - /* sizeof(lpmlcW->pamxctrl[i].Metrics) == - * sizeof(mlcA.pamxctrl[i].Metrics) */ - memcpy(&lpmlcW->pamxctrl[i].Metrics, &mlcA.pamxctrl[i].Metrics, - sizeof(mlcA.pamxctrl[i].Metrics)); - } - } - - HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl); - - return ret; + return MMDRV_Message(&lpwm->mld, MXDM_GETLINECONTROLS, (DWORD_PTR)lpmlcW, + fdwControls, TRUE); } /************************************************************************** - * mixerGetLineInfoA [WINMM.@] + * mixerGetLineInfoW [WINMM.@] */ -UINT WINAPI mixerGetLineInfoA(HMIXEROBJ hmix, LPMIXERLINEA lpmliW, DWORD fdwInfo) +UINT WINAPI mixerGetLineInfoW(HMIXEROBJ hmix, LPMIXERLINEW lpmliW, DWORD fdwInfo) { LPWINE_MIXER lpwm; UINT uRet = MMSYSERR_NOERROR; @@ -586,68 +588,68 @@ UINT WINAPI mixerGetLineInfoA(HMIXEROBJ hmix, LPMIXERLINEA lpmliW, DWORD fdwInfo } /************************************************************************** - * mixerGetLineInfoW [WINMM.@] + * mixerGetLineInfoA [WINMM.@] */ -UINT WINAPI mixerGetLineInfoW(HMIXEROBJ hmix, LPMIXERLINEW lpmliW, +UINT WINAPI mixerGetLineInfoA(HMIXEROBJ hmix, LPMIXERLINEA lpmliA, DWORD fdwInfo) { - MIXERLINEA mliA; + MIXERLINEW mliW; UINT ret; - TRACE("(%p, %p, %08lx)\n", hmix, lpmliW, fdwInfo); + TRACE("(%p, %p, %08lx)\n", hmix, lpmliA, fdwInfo); - if (lpmliW == NULL || lpmliW->cbStruct != sizeof(*lpmliW)) + if (lpmliA == NULL || lpmliA->cbStruct != sizeof(*lpmliA)) return MMSYSERR_INVALPARAM; - mliA.cbStruct = sizeof(mliA); + mliW.cbStruct = sizeof(mliW); switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) { case MIXER_GETLINEINFOF_COMPONENTTYPE: - mliA.dwComponentType = lpmliW->dwComponentType; + mliW.dwComponentType = lpmliA->dwComponentType; break; case MIXER_GETLINEINFOF_DESTINATION: - mliA.dwDestination = lpmliW->dwDestination; + mliW.dwDestination = lpmliA->dwDestination; break; case MIXER_GETLINEINFOF_LINEID: - mliA.dwLineID = lpmliW->dwLineID; + mliW.dwLineID = lpmliA->dwLineID; break; case MIXER_GETLINEINFOF_SOURCE: - mliA.dwDestination = lpmliW->dwDestination; - mliA.dwSource = lpmliW->dwSource; + mliW.dwDestination = lpmliA->dwDestination; + mliW.dwSource = lpmliA->dwSource; break; case MIXER_GETLINEINFOF_TARGETTYPE: - mliA.Target.dwType = lpmliW->Target.dwType; - mliA.Target.wMid = lpmliW->Target.wMid; - mliA.Target.wPid = lpmliW->Target.wPid; - mliA.Target.vDriverVersion = lpmliW->Target.vDriverVersion; - WideCharToMultiByte( CP_ACP, 0, lpmliW->Target.szPname, -1, mliA.Target.szPname, sizeof(mliA.Target.szPname), NULL, NULL); + mliW.Target.dwType = lpmliA->Target.dwType; + mliW.Target.wMid = lpmliA->Target.wMid; + mliW.Target.wPid = lpmliA->Target.wPid; + mliW.Target.vDriverVersion = lpmliA->Target.vDriverVersion; + MultiByteToWideChar( CP_ACP, 0, lpmliA->Target.szPname, -1, mliW.Target.szPname, sizeof(mliW.Target.szPname)); break; default: WARN("Unsupported fdwControls=0x%08lx\n", fdwInfo); return MMSYSERR_INVALFLAG; } - ret = mixerGetLineInfoA(hmix, &mliA, fdwInfo); + ret = mixerGetLineInfoW(hmix, &mliW, fdwInfo); - lpmliW->dwDestination = mliA.dwDestination; - lpmliW->dwSource = mliA.dwSource; - lpmliW->dwLineID = mliA.dwLineID; - lpmliW->fdwLine = mliA.fdwLine; - lpmliW->dwUser = mliA.dwUser; - lpmliW->dwComponentType = mliA.dwComponentType; - lpmliW->cChannels = mliA.cChannels; - lpmliW->cConnections = mliA.cConnections; - lpmliW->cControls = mliA.cControls; - MultiByteToWideChar( CP_ACP, 0, mliA.szShortName, -1, lpmliW->szShortName, - sizeof(lpmliW->szShortName)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, mliA.szName, -1, lpmliW->szName, - sizeof(lpmliW->szName)/sizeof(WCHAR) ); - lpmliW->Target.dwType = mliA.Target.dwType; - lpmliW->Target.dwDeviceID = mliA.Target.dwDeviceID; - lpmliW->Target.wMid = mliA.Target.wMid; - lpmliW->Target.wPid = mliA.Target.wPid; - lpmliW->Target.vDriverVersion = mliA.Target.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, mliA.Target.szPname, -1, lpmliW->Target.szPname, - sizeof(lpmliW->Target.szPname)/sizeof(WCHAR) ); + lpmliA->dwDestination = mliW.dwDestination; + lpmliA->dwSource = mliW.dwSource; + lpmliA->dwLineID = mliW.dwLineID; + lpmliA->fdwLine = mliW.fdwLine; + lpmliA->dwUser = mliW.dwUser; + lpmliA->dwComponentType = mliW.dwComponentType; + lpmliA->cChannels = mliW.cChannels; + lpmliA->cConnections = mliW.cConnections; + lpmliA->cControls = mliW.cControls; + WideCharToMultiByte( CP_ACP, 0, mliW.szShortName, -1, lpmliA->szShortName, + sizeof(lpmliA->szShortName), NULL, NULL); + WideCharToMultiByte( CP_ACP, 0, mliW.szName, -1, lpmliA->szName, + sizeof(lpmliA->szName), NULL, NULL ); + lpmliA->Target.dwType = mliW.Target.dwType; + lpmliA->Target.dwDeviceID = mliW.Target.dwDeviceID; + lpmliA->Target.wMid = mliW.Target.wMid; + lpmliA->Target.wPid = mliW.Target.wPid; + lpmliA->Target.vDriverVersion = mliW.Target.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, mliW.Target.szPname, -1, lpmliA->Target.szPname, + sizeof(lpmliA->Target.szPname), NULL, NULL ); return ret; } @@ -655,18 +657,18 @@ UINT WINAPI mixerGetLineInfoW(HMIXEROBJ hmix, LPMIXERLINEW lpmliW, /************************************************************************** * mixerSetControlDetails [WINMM.@] */ -UINT WINAPI mixerSetControlDetails(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdA, +UINT WINAPI mixerSetControlDetails(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails) { LPWINE_MIXER lpwm; UINT uRet = MMSYSERR_NOERROR; - TRACE("(%p, %p, %08lx)\n", hmix, lpmcdA, fdwDetails); + TRACE("(%p, %p, %08lx)\n", hmix, lpmcd, fdwDetails); if ((uRet = MIXER_GetDev(hmix, fdwDetails, &lpwm)) != MMSYSERR_NOERROR) return uRet; - return MMDRV_Message(&lpwm->mld, MXDM_SETCONTROLDETAILS, (DWORD_PTR)lpmcdA, + return MMDRV_Message(&lpwm->mld, MXDM_SETCONTROLDETAILS, (DWORD_PTR)lpmcd, fdwDetails, TRUE); } @@ -698,31 +700,6 @@ UINT WINAPI auxGetNumDevs(void) * auxGetDevCapsW [WINMM.@] */ UINT WINAPI auxGetDevCapsW(UINT_PTR uDeviceID, LPAUXCAPSW lpCaps, UINT uSize) -{ - AUXCAPSA acA; - UINT ret; - - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - - ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA)); - if (ret == MMSYSERR_NOERROR) { - AUXCAPSW acW; - acW.wMid = acA.wMid; - acW.wPid = acA.wPid; - acW.vDriverVersion = acA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, acA.szPname, -1, acW.szPname, - sizeof(acW.szPname)/sizeof(WCHAR) ); - acW.wTechnology = acA.wTechnology; - acW.dwSupport = acA.dwSupport; - memcpy(lpCaps, &acW, min(uSize, sizeof(acW))); - } - return ret; -} - -/************************************************************************** - * auxGetDevCapsA [WINMM.@] - */ -UINT WINAPI auxGetDevCapsA(UINT_PTR uDeviceID, LPAUXCAPSA lpCaps, UINT uSize) { LPWINE_MLD wmld; @@ -735,6 +712,32 @@ UINT WINAPI auxGetDevCapsA(UINT_PTR uDeviceID, LPAUXCAPSA lpCaps, UINT uSize) return MMDRV_Message(wmld, AUXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); } +/************************************************************************** + * auxGetDevCapsA [WINMM.@] + */ +UINT WINAPI auxGetDevCapsA(UINT_PTR uDeviceID, LPAUXCAPSA lpCaps, UINT uSize) +{ + AUXCAPSW acW; + UINT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = auxGetDevCapsW(uDeviceID, &acW, sizeof(acW)); + + if (ret == MMSYSERR_NOERROR) { + AUXCAPSA acA; + acA.wMid = acW.wMid; + acA.wPid = acW.wPid; + acA.vDriverVersion = acW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, acW.szPname, -1, acA.szPname, + sizeof(acA.szPname), NULL, NULL ); + acA.wTechnology = acW.wTechnology; + acA.dwSupport = acW.dwSupport; + memcpy(lpCaps, &acA, min(uSize, sizeof(acA))); + } + return ret; +} + /************************************************************************** * auxGetVolume [WINMM.@] */ @@ -1003,7 +1006,6 @@ static int MCI_MapMsgWtoA(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2) FIXME("Message 0x%04x needs translation\n", msg); return -1; } - return 0; } static DWORD MCI_UnmapMsgWtoA(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2, @@ -1253,35 +1255,6 @@ UINT WINAPI midiOutGetNumDevs(void) */ UINT WINAPI midiOutGetDevCapsW(UINT_PTR uDeviceID, LPMIDIOUTCAPSW lpCaps, UINT uSize) -{ - MIDIOUTCAPSA mocA; - UINT ret; - - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - - ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA)); - if (ret == MMSYSERR_NOERROR) { - MIDIOUTCAPSW mocW; - mocW.wMid = mocA.wMid; - mocW.wPid = mocA.wPid; - mocW.vDriverVersion = mocA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, mocA.szPname, -1, mocW.szPname, - sizeof(mocW.szPname)/sizeof(WCHAR) ); - mocW.wTechnology = mocA.wTechnology; - mocW.wVoices = mocA.wVoices; - mocW.wNotes = mocA.wNotes; - mocW.wChannelMask = mocA.wChannelMask; - mocW.dwSupport = mocA.dwSupport; - memcpy(lpCaps, &mocW, min(uSize, sizeof(mocW))); - } - return ret; -} - -/************************************************************************** - * midiOutGetDevCapsA [WINMM.@] - */ -UINT WINAPI midiOutGetDevCapsA(UINT_PTR uDeviceID, LPMIDIOUTCAPSA lpCaps, - UINT uSize) { LPWINE_MLD wmld; @@ -1295,6 +1268,36 @@ UINT WINAPI midiOutGetDevCapsA(UINT_PTR uDeviceID, LPMIDIOUTCAPSA lpCaps, return MMDRV_Message(wmld, MODM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); } +/************************************************************************** + * midiOutGetDevCapsA [WINMM.@] + */ +UINT WINAPI midiOutGetDevCapsA(UINT_PTR uDeviceID, LPMIDIOUTCAPSA lpCaps, + UINT uSize) +{ + MIDIOUTCAPSW mocW; + UINT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = midiOutGetDevCapsW(uDeviceID, &mocW, sizeof(mocW)); + + if (ret == MMSYSERR_NOERROR) { + MIDIOUTCAPSA mocA; + mocA.wMid = mocW.wMid; + mocA.wPid = mocW.wPid; + mocA.vDriverVersion = mocW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, mocW.szPname, -1, mocA.szPname, + sizeof(mocA.szPname), NULL, NULL ); + mocA.wTechnology = mocW.wTechnology; + mocA.wVoices = mocW.wVoices; + mocA.wNotes = mocW.wNotes; + mocA.wChannelMask = mocW.wChannelMask; + mocA.dwSupport = mocW.dwSupport; + memcpy(lpCaps, &mocA, min(uSize, sizeof(mocA))); + } + return ret; +} + /************************************************************************** * MIDI_GetErrorText [internal] */ @@ -1633,30 +1636,6 @@ UINT WINAPI midiInGetNumDevs(void) * midiInGetDevCapsW [WINMM.@] */ UINT WINAPI midiInGetDevCapsW(UINT_PTR uDeviceID, LPMIDIINCAPSW lpCaps, UINT uSize) -{ - MIDIINCAPSA micA; - UINT ret; - - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - - ret = midiInGetDevCapsA(uDeviceID, &micA, sizeof(micA)); - if (ret == MMSYSERR_NOERROR) { - MIDIINCAPSW micW; - micW.wMid = micA.wMid; - micW.wPid = micA.wPid; - micW.vDriverVersion = micA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, micA.szPname, -1, micW.szPname, - sizeof(micW.szPname)/sizeof(WCHAR) ); - micW.dwSupport = micA.dwSupport; - memcpy(lpCaps, &micW, min(uSize, sizeof(micW))); - } - return ret; -} - -/************************************************************************** - * midiInGetDevCapsA [WINMM.@] - */ -UINT WINAPI midiInGetDevCapsA(UINT_PTR uDeviceID, LPMIDIINCAPSA lpCaps, UINT uSize) { LPWINE_MLD wmld; @@ -1670,6 +1649,31 @@ UINT WINAPI midiInGetDevCapsA(UINT_PTR uDeviceID, LPMIDIINCAPSA lpCaps, UINT uSi return MMDRV_Message(wmld, MIDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); } +/************************************************************************** + * midiInGetDevCapsA [WINMM.@] + */ +UINT WINAPI midiInGetDevCapsA(UINT_PTR uDeviceID, LPMIDIINCAPSA lpCaps, UINT uSize) +{ + MIDIINCAPSW micW; + UINT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = midiInGetDevCapsW(uDeviceID, &micW, sizeof(micW)); + + if (ret == MMSYSERR_NOERROR) { + MIDIINCAPSA micA; + micA.wMid = micW.wMid; + micA.wPid = micW.wPid; + micA.vDriverVersion = micW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, micW.szPname, -1, micA.szPname, + sizeof(micA.szPname), NULL, NULL ); + micA.dwSupport = micW.dwSupport; + memcpy(lpCaps, &micA, min(uSize, sizeof(micA))); + } + return ret; +} + /************************************************************************** * midiInGetErrorTextW [WINMM.@] */ @@ -2273,7 +2277,7 @@ MMRESULT MIDI_StreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, DWORD cMidi lpwm->mld.uDeviceID = *lpuDeviceID; ret = MMDRV_Open(&lpwm->mld, MODM_OPEN, (DWORD)&lpwm->mod, fdwOpen); - lpMidiStrm->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + lpMidiStrm->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); lpMidiStrm->wFlags = HIWORD(fdwOpen); lpMidiStrm->hThread = CreateThread(NULL, 0, MMSYSTEM_MidiStream_Player, @@ -2491,7 +2495,7 @@ MMRESULT WINAPI midiStreamStop(HMIDISTRM hMidiStrm) } UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, - const LPWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, + LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags, BOOL bFrom32) { HANDLE handle; @@ -2528,7 +2532,7 @@ UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType, } wod.hWave = handle; - wod.lpFormat = lpFormat; /* should the struct be copied iso pointer? */ + wod.lpFormat = (LPWAVEFORMATEX)lpFormat; /* should the struct be copied iso pointer? */ wod.dwCallback = dwCallback; wod.dwInstance = dwInstance; wod.dnDevNode = 0L; @@ -2582,6 +2586,34 @@ UINT WINAPI waveOutGetNumDevs(void) */ UINT WINAPI waveOutGetDevCapsA(UINT_PTR uDeviceID, LPWAVEOUTCAPSA lpCaps, UINT uSize) +{ + WAVEOUTCAPSW wocW; + UINT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = waveOutGetDevCapsW(uDeviceID, &wocW, sizeof(wocW)); + + if (ret == MMSYSERR_NOERROR) { + WAVEOUTCAPSA wocA; + wocA.wMid = wocW.wMid; + wocA.wPid = wocW.wPid; + wocA.vDriverVersion = wocW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, wocW.szPname, -1, wocA.szPname, + sizeof(wocA.szPname), NULL, NULL ); + wocA.dwFormats = wocW.dwFormats; + wocA.wChannels = wocW.wChannels; + wocA.dwSupport = wocW.dwSupport; + memcpy(lpCaps, &wocA, min(uSize, sizeof(wocA))); + } + return ret; +} + +/************************************************************************** + * waveOutGetDevCapsW [WINMM.@] + */ +UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps, + UINT uSize) { LPWINE_MLD wmld; @@ -2596,33 +2628,6 @@ UINT WINAPI waveOutGetDevCapsA(UINT_PTR uDeviceID, LPWAVEOUTCAPSA lpCaps, } -/************************************************************************** - * waveOutGetDevCapsW [WINMM.@] - */ -UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps, - UINT uSize) -{ - WAVEOUTCAPSA wocA; - UINT ret; - - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - - ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA)); - if (ret == MMSYSERR_NOERROR) { - WAVEOUTCAPSW wocW; - wocW.wMid = wocA.wMid; - wocW.wPid = wocA.wPid; - wocW.vDriverVersion = wocA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, wocA.szPname, -1, wocW.szPname, - sizeof(wocW.szPname)/sizeof(WCHAR) ); - wocW.dwFormats = wocA.dwFormats; - wocW.wChannels = wocA.wChannels; - wocW.dwSupport = wocA.dwSupport; - memcpy(lpCaps, &wocW, min(uSize, sizeof(wocW))); - } - return ret; -} - /************************************************************************** * WAVE_GetErrorText [internal] */ @@ -2996,31 +3001,6 @@ UINT WINAPI waveInGetNumDevs(void) * waveInGetDevCapsW [WINMM.@] */ UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize) -{ - WAVEINCAPSA wicA; - UINT ret; - - if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - - ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA)); - if (ret == MMSYSERR_NOERROR) { - WAVEINCAPSW wicW; - wicW.wMid = wicA.wMid; - wicW.wPid = wicA.wPid; - wicW.vDriverVersion = wicA.vDriverVersion; - MultiByteToWideChar( CP_ACP, 0, wicA.szPname, -1, wicW.szPname, - sizeof(wicW.szPname)/sizeof(WCHAR) ); - wicW.dwFormats = wicA.dwFormats; - wicW.wChannels = wicA.wChannels; - memcpy(lpCaps, &wicW, min(uSize, sizeof(wicW))); - } - return ret; -} - -/************************************************************************** - * waveInGetDevCapsA [WINMM.@] - */ -UINT WINAPI waveInGetDevCapsA(UINT_PTR uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSize) { LPWINE_MLD wmld; @@ -3034,6 +3014,32 @@ UINT WINAPI waveInGetDevCapsA(UINT_PTR uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSi return MMDRV_Message(wmld, WIDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE); } +/************************************************************************** + * waveInGetDevCapsA [WINMM.@] + */ +UINT WINAPI waveInGetDevCapsA(UINT_PTR uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSize) +{ + WAVEINCAPSW wicW; + UINT ret; + + if (lpCaps == NULL) return MMSYSERR_INVALPARAM; + + ret = waveInGetDevCapsW(uDeviceID, &wicW, sizeof(wicW)); + + if (ret == MMSYSERR_NOERROR) { + WAVEINCAPSA wicA; + wicA.wMid = wicW.wMid; + wicA.wPid = wicW.wPid; + wicA.vDriverVersion = wicW.vDriverVersion; + WideCharToMultiByte( CP_ACP, 0, wicW.szPname, -1, wicA.szPname, + sizeof(wicA.szPname), NULL, NULL ); + wicA.dwFormats = wicW.dwFormats; + wicA.wChannels = wicW.wChannels; + memcpy(lpCaps, &wicA, min(uSize, sizeof(wicA))); + } + return ret; +} + /************************************************************************** * waveInGetErrorTextA [WINMM.@] */ diff --git a/reactos/lib/winmm/winmm.spec b/reactos/lib/winmm/winmm.spec index b7057f46329..ffaad29dd40 100644 --- a/reactos/lib/winmm/winmm.spec +++ b/reactos/lib/winmm/winmm.spec @@ -188,5 +188,3 @@ @ stdcall waveOutSetVolume(long long) @ stdcall waveOutUnprepareHeader(long ptr long) @ stdcall waveOutWrite(long ptr long) -@ stub winmmf_ThunkData32 -@ stub winmmsl_ThunkData32 diff --git a/reactos/lib/winmm/winmm_De.rc b/reactos/lib/winmm/winmm_De.rc index 9f7c8b9051b..24aa8224ae8 100644 --- a/reactos/lib/winmm/winmm_De.rc +++ b/reactos/lib/winmm/winmm_De.rc @@ -57,7 +57,7 @@ MCIERR_OUT_OF_MEMORY, "Nicht gen MCIERR_DEVICE_OPEN, "Der Gerätename wird von dieser Anwendung bereits als Alias benutzt. Benutzen Sie einen eindeutigen Alias" MCIERR_CANNOT_LOAD_DRIVER, "Es gibt ein unbekanntes Problem beim Laden des angegebenen Gerätetreibers." MCIERR_MISSING_COMMAND_STRING, "Kein Befehl wurde angegeben." -MCIERR_PARAM_OVERFLOW, "Die Ausgabezeichenkennte war zu lang für den Rückgabepuffer. Erhöhen Sie die Puffergröße." +MCIERR_PARAM_OVERFLOW, "Die Ausgabezeichenkette war zu lang für den Rückgabepuffer. Erhöhen Sie die Puffergröße." MCIERR_MISSING_STRING_ARGUMENT, "Der Befehl erfordert einen Zeichenkettenparameter. Bitte stellen Sie einen bereit." MCIERR_BAD_INTEGER, "Die Angabe einer ganzen Zahl ist für diesen Befehl ungültig." MCIERR_PARSER_INTERNAL, "Der Gerätetreiber hat einen ungültigen Rückgabewert geliefert. Fragen Sie den Gerätehersteller nach einem neuen Treiber." diff --git a/reactos/lib/ws2_32/misc/catalog.c b/reactos/lib/ws2_32/misc/catalog.c index 849dbba86af..b8d59f9419f 100644 --- a/reactos/lib/ws2_32/misc/catalog.c +++ b/reactos/lib/ws2_32/misc/catalog.c @@ -282,11 +282,11 @@ VOID CreateCatalog(VOID) Provider->Mapping = HeapAlloc(GlobalHeap, 0, - 5 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); + 6 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); if (!Provider->Mapping) return; - Provider->Mapping->Rows = 5; + Provider->Mapping->Rows = 6; Provider->Mapping->Columns = 3; Provider->Mapping->Mapping[0].AddressFamily = AF_INET; @@ -307,7 +307,11 @@ VOID CreateCatalog(VOID) Provider->Mapping->Mapping[4].AddressFamily = AF_INET; Provider->Mapping->Mapping[4].SocketType = SOCK_RAW; - Provider->Mapping->Mapping[4].Protocol = 0; + Provider->Mapping->Mapping[4].Protocol = IPPROTO_ICMP; + + Provider->Mapping->Mapping[5].AddressFamily = AF_INET; + Provider->Mapping->Mapping[5].SocketType = SOCK_RAW; + Provider->Mapping->Mapping[5].Protocol = 0; #endif } diff --git a/reactos/lib/ws2_32/misc/dllmain.c b/reactos/lib/ws2_32/misc/dllmain.c index 3813a05b811..e8fced768ee 100644 --- a/reactos/lib/ws2_32/misc/dllmain.c +++ b/reactos/lib/ws2_32/misc/dllmain.c @@ -552,6 +552,17 @@ WSAAccept( WSASetLastError(Errno); } + if( addr ) { +#ifdef DBG + LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr; + WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n", + sa->sin_family, + inet_ntoa(sa->sin_addr), + ntohs(sa->sin_port), + *addrlen)); +#endif + } + return Socket; } diff --git a/reactos/lib/ws2_32/misc/ns.c b/reactos/lib/ws2_32/misc/ns.c index c8a0d63ef64..977f953ba7f 100644 --- a/reactos/lib/ws2_32/misc/ns.c +++ b/reactos/lib/ws2_32/misc/ns.c @@ -7,6 +7,7 @@ * REVISIONS: * CSH 01/09-2000 Created */ +#define __NO_CTYPE_INLINES #include #include #include diff --git a/reactos/makefile.dos b/reactos/makefile.dos deleted file mode 100644 index 2c9e3e13196..00000000000 --- a/reactos/makefile.dos +++ /dev/null @@ -1,142 +0,0 @@ -# -# Global makefile -# - -# -# Select your host -# -#HOST = mingw32-linux -#HOST = djgpp-msdos -HOST = mingw32-windows - -include rules.mak - -# -# Required to run the system -# -COMPONENTS = iface_native ntoskrnl -#DLLS = ntdll kernel32 crtdll user32 fmifs gdi32 -DLLS = ntdll kernel32 crtdll fmifs gdi32 -#DLLS = crtdll mingw32 -SUBSYS = win32k - -# -# Select the server(s) you want to build -# -SERVERS = win32 -# SERVERS = posix linux os2 - -# -# Select the loader(s) you want to build -# -LOADERS = dos -# LOADERS = boot - -# -# Select the device drivers and filesystems you want -# -DEVICE_DRIVERS = blue ide keyboard mouse null parallel serial vidport -# DEVICE_DRIVERS = beep event floppy ide_test sound test test1 -FS_DRIVERS = vfat -# FS_DRIVERS = minix ext2 template -KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) - -APPS = args hello shell test cat bench -# APPS = cmd - -all: $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS) -.PHONY: all - -clean: $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \ - $(KERNEL_SERVICES:%=%_clean) $(APPS:%=%_clean) -.PHONY: clean - -# -# Applications -# -$(APPS): %: - make -C apps/$* - -$(APPS:%=%_clean): %_clean: - make -C apps/$* clean - -.PHONY: $(APPS) $(APPS:%=%_clean) - -# -# Interfaces -# -iface_native: - make -C iface/native - -iface_native_clean: - make -C iface/native clean - -.PHONY: iface_native iface_native_clean - -# -# Device driver rules -# -$(DEVICE_DRIVERS): %: - make -C services/dd/$* - -$(DEVICE_DRIVERS:%=%_clean): %_clean: - make -C services/dd/$* clean - -.PHONY: $(DEVICE_DRIVERS) $(DEVICE_DRIVERS:%=%_clean) - -$(FS_DRIVERS): %: - make -C services/fs/$* - -$(FS_DRIVERS:%=%_clean): %_clean: - make -C services/fs/$* clean - -.PHONY: $(FS_DRIVERS) $(FS_DRIVERS:%=%_clean) - -# -# Kernel loaders -# - -$(LOADERS): %: - make -C loaders/$* - -$(LOADERS:%=%_clean): %_clean: - make -C loaders/$* clean - -.PHONY: $(LOADERS) $(LOADERS:%=%_clean) - -# -# Required system components -# - -ntoskrnl: - make -C ntoskrnl - -ntoskrnl_clean: - make -C ntoskrnl clean - -.PHONY: ntoskrnl ntoskrnl_clean - -# -# Required DLLs -# - -$(DLLS): %: - make -C lib/$* - -$(DLLS:%=%_clean): %_clean: - make -C lib/$* clean - -.PHONY: $(DLLS) $(DLLS:%=%_clean) - -# -# Kernel Subsystems -# -$(SUBSYS): %: - make -C subsys/$* - -$(SUBSYS:%=%_clean): %_clean: - make -C lib/$* clean - -.PHONY: $(SUBSYS) $(SUBSYS:%=%_clean) - - diff --git a/reactos/media/drivers/etc/services b/reactos/media/drivers/etc/services index 3fc6e36df6f..2e2b549148a 100644 --- a/reactos/media/drivers/etc/services +++ b/reactos/media/drivers/etc/services @@ -2,7 +2,7 @@ # # This file contains port numbers for well-known services defined by IANA # -# The Well Known Ports are thuse from 0 through 1023 +# The Well Known Ports are those from 0 through 1023 # The Registered Ports are those from 1024 through 49151 # The Dynamic and/or Private Ports are those from 49152 through 65535 # diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 0e9393f6a0f..63d323aacf8 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -10,8 +10,6 @@ TARGET_TYPE = kernel TARGET_NAME = ntoskrnl -TARGET_BASE = 0xc0000000 - TARGET_BOOTSTRAP = yes CONFIG := @@ -26,15 +24,9 @@ endif LINKER_SCRIPT := ntoskrnl.lnk STRIP_FLAGS := -Wl,-s -ifeq ($(OPTIMIZED), 1) -CFLAGS_OPT := -O2 -Wno-strict-aliasing -else -CFLAGS_OPT := -endif - ifeq ($(KDBG), 1) OBJECTS_KDBG := dbg/kdb.o dbg/kdb_serial.o dbg/kdb_keyboard.o dbg/rdebug.o \ - dbg/i386/kdb_help.o dbg/profile.o \ + dbg/i386/kdb_help.o \ ../dk/w32/lib/libkjs.a dbg/i386/i386-dis.o CFLAGS_KDBG := -I../lib/kjs/include preall: all @@ -45,7 +37,7 @@ else OBJECTS_KDBG := endif ifeq ($(DBG_OR_KDBG), 1) -OBJECTS_KDBG := $(OBJECTS_KDBG) dbg/kdb_stabs.o dbg/kdb_symbols.o +OBJECTS_KDBG := $(OBJECTS_KDBG) dbg/kdb_symbols.o dbg/profile.o endif TARGET_ASFLAGS = -I./include @@ -77,22 +69,6 @@ OBJECTS_PATH = objects # include Makefile.$(ARCH) -# System API (Nt/Zw) -OBJECTS_NT = \ - nt/channel.o \ - nt/efi.o \ - nt/evtpair.o \ - nt/mutant.o \ - nt/misc.o \ - nt/nt.o \ - nt/ntevent.o \ - nt/ntsem.o \ - nt/nttimer.o \ - nt/plugplay.o \ - nt/profile.o \ - nt/vdm.o \ - nt/zw.o - # Run-Time Library (Rtl) OBJECTS_RTL = \ rtl/atom.o \ @@ -100,6 +76,7 @@ OBJECTS_RTL = \ rtl/ctype.o \ rtl/handle.o \ rtl/message.o \ + rtl/misc.o \ rtl/purecall.o \ rtl/regio.o \ rtl/sprintf.o \ @@ -135,7 +112,8 @@ OBJECTS_KE = \ ke/sem.o \ ke/spinlock.o \ ke/timer.o \ - ke/wait.o + ke/wait.o \ + ke/alert.o # Memory Manager (Mm) OBJECTS_MM = \ @@ -168,7 +146,6 @@ OBJECTS_MM = \ mm/region.o \ mm/rmap.o \ mm/section.o \ - mm/slab.o \ mm/verifier.o \ mm/virtual.o \ mm/wset.o @@ -187,6 +164,7 @@ OBJECTS_IO = \ io/deviface.o \ io/dir.o \ io/driver.o \ + io/efi.o \ io/errlog.o \ io/error.o \ io/event.o \ @@ -205,10 +183,11 @@ OBJECTS_IO = \ io/npipe.o \ io/page.o \ io/parttab.o \ + io/plugplay.o \ io/process.o \ - io/pnpnotify.o \ io/pnpdma.o \ io/pnpmgr.o \ + io/pnpnotify.o \ io/pnpreport.o \ io/pnproot.o \ io/queue.o \ @@ -258,25 +237,32 @@ OBJECTS_PS = \ OBJECTS_EX = \ ex/btree.o \ ex/callback.o \ + ex/event.o \ + ex/evtpair.o \ ex/fmutex.o \ ex/hashtab.o \ ex/init.o \ ex/interlck.o \ ex/list.o \ ex/lookas.o \ + ex/mutant.o \ ex/napi.o \ ex/power.o \ + ex/profile.o \ ex/resource.o \ ex/rundown.o \ ex/stree.o \ + ex/sem.o \ ex/synch.o \ ex/sysinfo.o \ ex/time.o \ + ex/timer.o \ ex/util.o \ ex/uuid.o \ ex/win32k.o \ ex/work.o \ - ex/zone.o + ex/zone.o \ + ex/zw.o # Installable File System Run-Time Library (FsRtl) OBJECTS_FS = \ @@ -312,7 +298,6 @@ OBJECTS_CM = \ cm/regfile.o \ cm/registry.o \ cm/regobj.o \ - cm/rtlfunc.o # Debugger Support (Dbg) OBJECTS_DBG = \ @@ -370,7 +355,7 @@ OBJECTS_KD = \ OBJECTS_INBV = \ inbv/inbv.o -DEP_OBJECTS := $(OBJECTS_NT) $(OBJECTS_MM) $(OBJECTS_ARCH) \ +DEP_OBJECTS := $(OBJECTS_MM) $(OBJECTS_ARCH) \ $(OBJECTS_IO) $(OBJECTS_KE) $(OBJECTS_OB) \ $(OBJECTS_PS) $(OBJECTS_EX) $(OBJECTS_CC) $(OBJECTS_FS) $(OBJECTS_SE) \ $(OBJECTS_DBG) $(OBJECTS_CM) $(OBJECTS_LDR) $(OBJECTS_LPC) \ @@ -474,12 +459,6 @@ $(OBJECTS_PATH)/lpc.o: $(OBJECTS_LPC) -o $(OBJECTS_PATH)/lpc.o \ $(OBJECTS_LPC) -$(OBJECTS_PATH)/nt.o: $(OBJECTS_NT) - $(LD) \ - -r \ - -o $(OBJECTS_PATH)/nt.o \ - $(OBJECTS_NT) - $(OBJECTS_PATH)/po.o: $(OBJECTS_PO) $(LD) \ -r \ @@ -518,7 +497,6 @@ OBJECTS := \ $(OBJECTS_PATH)/kd.o \ $(OBJECTS_PATH)/ldr.o \ $(OBJECTS_PATH)/mm.o \ - $(OBJECTS_PATH)/nt.o \ $(OBJECTS_PATH)/ob.o \ $(OBJECTS_PATH)/po.o \ $(OBJECTS_PATH)/ps.o \ @@ -534,9 +512,11 @@ TARGET_OBJECTS = $(EXTRA_OBJECTS) $(OBJECTS) TARGET_LIBS = \ $(DDK_PATH_LIB)/libhal.a \ $(SDK_PATH_LIB)/librtl.a \ + $(SDK_PATH_LIB)/librossym.a \ $(SDK_PATH_LIB)/libstring.a \ $(SDK_PATH_LIB)/librosrtl.a \ $(SDK_PATH_LIB)/libpseh.a \ + $(SDK_PATH_LIB)/libwdmguid.a \ $(PATH_TO_TOP)/drivers/lib/csq/csq.o TARGET_LFLAGS = \ @@ -545,7 +525,10 @@ TARGET_LFLAGS = \ -Wl,--image-base,$(TARGET_BASE) \ -Wl,--file-alignment,0x1000 \ -Wl,--section-alignment,0x1000 \ - -Wl,--entry,_NtProcessStartup + -Wl,--entry,_NtProcessStartup \ + -nostdlib + +TARGET_GCCLIBS = gcc TAGS: $(TAG_OBJECTS) etags $(addprefix -i , $(TAG_OBJECTS)) @@ -560,9 +543,9 @@ $(PATH_TO_TOP)/include/reactos/bugcodes.h bugcodes.rc: ntoskrnl.mc TARGET_CLEAN = \ $(PATH_TO_TOP)/include/reactos/bugcodes.h \ - $(DEP_OBJECTS) $(DEP_FILES) MSG00409.bin bugcodes.rc + $(DEP_OBJECTS) $(DEP_FILES) MSG00409.bin bugcodes.rc -ex/napi.o: ex/napi.c $(PATH_TO_TOP)/include/ntdll/napi.h +ex/napi.o: ex/zw.S $(PATH_TO_TOP)/include/ntdll/napi.h ke/main.o: ke/main.c $(PATH_TO_TOP)/include/reactos/buildno.h diff --git a/reactos/ntoskrnl/Makefile.i386 b/reactos/ntoskrnl/Makefile.i386 index 61454fd5c74..46b7c9bd006 100644 --- a/reactos/ntoskrnl/Makefile.i386 +++ b/reactos/ntoskrnl/Makefile.i386 @@ -5,7 +5,7 @@ # Defines $(OBJECTS_HAL) # include hal/x86/sources -OBJECTS_BOOT := ke/i386/multiboot.o +OBJECTS_BOOT := ke/i386/main.o OBJECTS_EX_I386 := \ ex/i386/interlck.o @@ -22,6 +22,7 @@ OBJECTS_KE_I386 := \ ke/i386/tskswitch.o \ ke/i386/v86m.o \ ke/i386/v86m_sup.o \ + ke/i386/vdm.o \ ke/i386/bios.o \ ke/i386/i386-mcount.o \ ke/i386/gdt.o \ diff --git a/reactos/ntoskrnl/cc/cacheman.c b/reactos/ntoskrnl/cc/cacheman.c index f174859aa73..8dff78a607d 100644 --- a/reactos/ntoskrnl/cc/cacheman.c +++ b/reactos/ntoskrnl/cc/cacheman.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/cacheman.c * PURPOSE: Cache manager - * PROGRAMMER: David Welch (welch@cwcom.net) - * PORTABILITY: Checked - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/cc/copy.c b/reactos/ntoskrnl/cc/copy.c index 0d34be9d140..60c4893e1cb 100644 --- a/reactos/ntoskrnl/cc/copy.c +++ b/reactos/ntoskrnl/cc/copy.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/copy.c * PURPOSE: Implements cache managers copy interface - * PROGRAMMER: Hartmut Birr - * UPDATE HISTORY: - * Created 05.10.2001 + * + * PROGRAMMERS: Hartmut Birr */ /* INCLUDES ******************************************************************/ @@ -25,7 +24,7 @@ static PFN_TYPE CcZeroPage = 0; #define MAX_RW_LENGTH (256 * 1024) #if defined(__GNUC__) -void * alloca(size_t size); +/* void * alloca(size_t size); */ #elif defined(_MSC_VER) void* _alloca(size_t size); #else diff --git a/reactos/ntoskrnl/cc/fs.c b/reactos/ntoskrnl/cc/fs.c index 09b490b9d6e..7d3d3d8419f 100644 --- a/reactos/ntoskrnl/cc/fs.c +++ b/reactos/ntoskrnl/cc/fs.c @@ -1,10 +1,11 @@ -/* COPYRIGHT: See COPYING in the top level directory +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/fs.c * PURPOSE: Implements cache managers functions useful for File Systems - * PROGRAMMER: Alex Ionescu - * UPDATE HISTORY: - * Created 20/06/04 + * + * PROGRAMMERS: Alex Ionescu */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/cc/mdl.c b/reactos/ntoskrnl/cc/mdl.c index 367d232ff27..1a1873fecc1 100644 --- a/reactos/ntoskrnl/cc/mdl.c +++ b/reactos/ntoskrnl/cc/mdl.c @@ -1,10 +1,11 @@ -/* COPYRIGHT: See COPYING in the top level directory +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/fs.c * PURPOSE: Implements MDL Cache Manager Functions - * PROGRAMMER: Alex Ionescu - * UPDATE HISTORY: - * Created 20/06/04 + * + * PROGRAMMERS: Alex Ionescu */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/cc/pin.c b/reactos/ntoskrnl/cc/pin.c index de20a1ae947..1b51b243e6a 100644 --- a/reactos/ntoskrnl/cc/pin.c +++ b/reactos/ntoskrnl/cc/pin.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/pin.c * PURPOSE: Implements cache managers pinning interface - * PROGRAMMER: Hartmut Birr - * UPDATE HISTORY: - * Created 05.10.2001 + * + * PROGRAMMERS: Hartmut Birr */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/cc/view.c b/reactos/ntoskrnl/cc/view.c index 86fb01b2532..9162b84766b 100644 --- a/reactos/ntoskrnl/cc/view.c +++ b/reactos/ntoskrnl/cc/view.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/view.c * PURPOSE: Cache manager - * PROGRAMMER: David Welch (welch@mcmail.com) - * PORTABILITY: Checked - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* NOTES ********************************************************************** @@ -100,7 +81,7 @@ static CLIENT_ID LazyCloseThreadId; static volatile BOOLEAN LazyCloseThreadShouldTerminate; #if defined(__GNUC__) -void * alloca(size_t size); +/* void * alloca(size_t size); */ #elif defined(_MSC_VER) void* _alloca(size_t size); #else diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c index 21b9d65f6e4..f0be6f834e3 100644 --- a/reactos/ntoskrnl/cm/import.c +++ b/reactos/ntoskrnl/cm/import.c @@ -4,6 +4,7 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/cm/import.c * PURPOSE: Registry-Hive import functions + * * PROGRAMMERS: Eric Kohl */ @@ -195,12 +196,12 @@ CmImportSystemHive(PCHAR ChunkBase, } /* Set the hive filename */ - RtlCreateUnicodeString (&RegistryHive->HiveFileName, - SYSTEM_REG_FILE); + RtlpCreateUnicodeString (&RegistryHive->HiveFileName, + SYSTEM_REG_FILE, NonPagedPool); /* Set the log filename */ - RtlCreateUnicodeString (&RegistryHive->LogFileName, - SYSTEM_LOG_FILE); + RtlpCreateUnicodeString (&RegistryHive->LogFileName, + SYSTEM_LOG_FILE, NonPagedPool); return TRUE; } @@ -233,7 +234,7 @@ CmImportHardwareHive(PCHAR ChunkBase, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtCreateKey (&HardwareKey, + Status = ZwCreateKey (&HardwareKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -242,9 +243,10 @@ CmImportHardwareHive(PCHAR ChunkBase, &Disposition); if (!NT_SUCCESS(Status)) { - return FALSE; + DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status); + return FALSE; } - NtClose (HardwareKey); + ZwClose (HardwareKey); /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */ RtlInitUnicodeString(&KeyName, @@ -254,7 +256,7 @@ CmImportHardwareHive(PCHAR ChunkBase, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtCreateKey (&HardwareKey, + Status = ZwCreateKey (&HardwareKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -263,9 +265,10 @@ CmImportHardwareHive(PCHAR ChunkBase, &Disposition); if (!NT_SUCCESS(Status)) { - return FALSE; + DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status); + return FALSE; } - NtClose (HardwareKey); + ZwClose (HardwareKey); /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */ RtlInitUnicodeString (&KeyName, @@ -275,7 +278,7 @@ CmImportHardwareHive(PCHAR ChunkBase, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtCreateKey (&HardwareKey, + Status = ZwCreateKey (&HardwareKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -284,9 +287,10 @@ CmImportHardwareHive(PCHAR ChunkBase, &Disposition); if (!NT_SUCCESS(Status)) { - return FALSE; + DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status); + return FALSE; } - NtClose (HardwareKey); + ZwClose (HardwareKey); /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */ RtlInitUnicodeString(&KeyName, @@ -296,7 +300,7 @@ CmImportHardwareHive(PCHAR ChunkBase, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtCreateKey (&HardwareKey, + Status = ZwCreateKey (&HardwareKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -305,9 +309,10 @@ CmImportHardwareHive(PCHAR ChunkBase, &Disposition); if (!NT_SUCCESS(Status)) { - return FALSE; + DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status); + return FALSE; } - NtClose (HardwareKey); + ZwClose (HardwareKey); return TRUE; } diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index 31c335c566d..141c0728e7b 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -1,10 +1,12 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/cm/ntfunc.c - * PURPOSE: Ntxxx function for registry access - * UPDATE HISTORY: -*/ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/ntfunc.c + * PURPOSE: Ntxxx function for registry access + * + * PROGRAMMERS: No programmer listed. + */ /* INCLUDES *****************************************************************/ @@ -30,23 +32,22 @@ static BOOLEAN CmiRegistryInitialized = FALSE; */ NTSTATUS STDCALL CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function, - IN PVOID Context, - IN OUT PLARGE_INTEGER Cookie - ) + IN PVOID Context, + IN OUT PLARGE_INTEGER Cookie) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } + /* * @unimplemented */ - NTSTATUS STDCALL -CmUnRegisterCallback(IN LARGE_INTEGER Cookie) +CmUnRegisterCallback(IN LARGE_INTEGER Cookie) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } @@ -63,8 +64,8 @@ NtCreateKey(OUT PHANDLE KeyHandle, PKEY_OBJECT KeyObject; NTSTATUS Status; PVOID Object; - PWSTR End; PWSTR Start; + unsigned i; DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n", ObjectAttributes->ObjectName, @@ -77,18 +78,20 @@ NtCreateKey(OUT PHANDLE KeyHandle, CmiKeyType); if (!NT_SUCCESS(Status)) { + DPRINT("ObFindObject failed, Status: 0x%x\n", Status); return(Status); } DPRINT("RemainingPath %wZ\n", &RemainingPath); - if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0)) + if (RemainingPath.Length == 0) { /* Fail if the key has been deleted */ if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE) { ObDereferenceObject(Object); RtlFreeUnicodeString(&RemainingPath); + DPRINT("Object marked for delete!\n"); return(STATUS_UNSUCCESSFUL); } @@ -101,24 +104,27 @@ NtCreateKey(OUT PHANDLE KeyHandle, TRUE, KeyHandle); - DPRINT("Status %x\n", Status); + DPRINT("ObCreateHandle failed Status 0x%x\n", Status); ObDereferenceObject(Object); RtlFreeUnicodeString(&RemainingPath); return Status; } /* If RemainingPath contains \ we must return error - because NtCreateKey don't create trees */ + because NtCreateKey doesn't create trees */ Start = RemainingPath.Buffer; if (*Start == L'\\') Start++; - End = wcschr(Start, L'\\'); - if (End != NULL) + for (i = 1; i < RemainingPath.Length / sizeof(WCHAR); i++) { - ObDereferenceObject(Object); - RtlFreeUnicodeString(&RemainingPath); - return STATUS_OBJECT_NAME_NOT_FOUND; + if (L'\\' == RemainingPath.Buffer[i]) + { + ObDereferenceObject(Object); + DPRINT1("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath); + RtlFreeUnicodeString(&RemainingPath); + return STATUS_OBJECT_NAME_NOT_FOUND; + } } DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object); @@ -134,6 +140,7 @@ NtCreateKey(OUT PHANDLE KeyHandle, (PVOID*)&KeyObject); if (!NT_SUCCESS(Status)) { + DPRINT1("ObCreateObject() failed!\n"); return(Status); } @@ -147,6 +154,7 @@ NtCreateKey(OUT PHANDLE KeyHandle, { ObDereferenceObject(KeyObject); RtlFreeUnicodeString(&RemainingPath); + DPRINT1("ObInsertObject() failed!\n"); return(Status); } @@ -192,8 +200,7 @@ NtCreateKey(OUT PHANDLE KeyHandle, } else { - RtlCreateUnicodeString(&KeyObject->Name, - Start); + RtlpCreateUnicodeString(&KeyObject->Name, Start, NonPagedPool); RtlFreeUnicodeString(&RemainingPath); } @@ -237,16 +244,19 @@ NtCreateKey(OUT PHANDLE KeyHandle, NTSTATUS STDCALL NtDeleteKey(IN HANDLE KeyHandle) { + KPROCESSOR_MODE PreviousMode; PKEY_OBJECT KeyObject; NTSTATUS Status; DPRINT1("NtDeleteKey(KeyHandle %x) called\n", KeyHandle); + + PreviousMode = ExGetPreviousMode(); /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, DELETE, CmiKeyType, - UserMode, + PreviousMode, (PVOID *)&KeyObject, NULL); if (!NT_SUCCESS(Status)) @@ -899,14 +909,17 @@ NtFlushKey(IN HANDLE KeyHandle) NTSTATUS Status; PKEY_OBJECT KeyObject; PREGISTRY_HIVE RegistryHive; + KPROCESSOR_MODE PreviousMode; DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle); + + PreviousMode = ExGetPreviousMode(); /* Verify that the handle is valid and is a registry key */ Status = ObReferenceObjectByHandle(KeyHandle, KEY_QUERY_VALUE, CmiKeyType, - UserMode, + PreviousMode, (PVOID *)&KeyObject, NULL); if (!NT_SUCCESS(Status)) @@ -947,8 +960,10 @@ NtOpenKey(OUT PHANDLE KeyHandle, IN POBJECT_ATTRIBUTES ObjectAttributes) { UNICODE_STRING RemainingPath; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; PVOID Object; + HANDLE hKey; + NTSTATUS Status = STATUS_SUCCESS; DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n", KeyHandle, @@ -956,6 +971,28 @@ NtOpenKey(OUT PHANDLE KeyHandle, ObjectAttributes, ObjectAttributes ? ObjectAttributes->ObjectName : NULL); + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(KeyHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + RemainingPath.Buffer = NULL; Status = ObFindObject(ObjectAttributes, &Object, @@ -990,7 +1027,7 @@ NtOpenKey(OUT PHANDLE KeyHandle, Object, DesiredAccess, TRUE, - KeyHandle); + &hKey); ObDereferenceObject(Object); if (!NT_SUCCESS(Status)) @@ -998,7 +1035,17 @@ NtOpenKey(OUT PHANDLE KeyHandle, return(Status); } - return(STATUS_SUCCESS); + _SEH_TRY + { + *KeyHandle = hKey; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } @@ -1593,7 +1640,7 @@ NtSetValueKey(IN HANDLE KeyHandle, KeyCell->Flags |= REG_KEY_LINK_CELL; } - NtQuerySystemTime (&KeyCell->LastWriteTime); + KeQuerySystemTime (&KeyCell->LastWriteTime); CmiMarkBlockDirty (RegistryHive, KeyObject->KeyCellOffset); ExReleaseResourceLite(&CmiRegistryLock); @@ -1638,7 +1685,7 @@ NtDeleteValueKey (IN HANDLE KeyHandle, KeyObject->KeyCellOffset, ValueName); - NtQuerySystemTime (&KeyObject->KeyCell->LastWriteTime); + KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime); CmiMarkBlockDirty (KeyObject->RegistryHive, KeyObject->KeyCellOffset); /* Release hive lock */ @@ -1702,7 +1749,7 @@ NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes, if (Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; - Status = NtQueryObject (FileObjectAttributes->RootDirectory, + Status = ZwQueryObject (FileObjectAttributes->RootDirectory, ObjectNameInformation, Buffer, BufferSize, @@ -1796,10 +1843,10 @@ NtNotifyChangeKey (IN HANDLE KeyHandle, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, - IN BOOLEAN Asynchroneous, - OUT PVOID ChangeBuffer, + IN BOOLEAN WatchSubtree, + OUT PVOID Buffer, IN ULONG Length, - IN BOOLEAN WatchSubtree) + IN BOOLEAN Asynchronous) { UNIMPLEMENTED; return(STATUS_NOT_IMPLEMENTED); diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index 800961a9c76..eb340933fdb 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -1,10 +1,12 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/cm/regfile.c - * PURPOSE: Registry file manipulation routines - * UPDATE HISTORY: -*/ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/regfile.c + * PURPOSE: Registry file manipulation routines + * + * PROGRAMMERS: No programmer listed. + */ #include #define NDEBUG @@ -71,7 +73,7 @@ CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell) RootKeyCell->CellSize = -sizeof(KEY_CELL); RootKeyCell->Id = REG_KEY_CELL_ID; RootKeyCell->Flags = REG_KEY_ROOT_CELL | REG_KEY_NAME_PACKED; - NtQuerySystemTime(&RootKeyCell->LastWriteTime); + KeQuerySystemTime(&RootKeyCell->LastWriteTime); RootKeyCell->ParentKeyOffset = 0; RootKeyCell->NumberOfSubKeys = 0; RootKeyCell->HashTableOffset = -1; @@ -384,7 +386,7 @@ CmiCreateNewRegFile(HANDLE FileHandle) /* The rest of the block is free */ FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -403,7 +405,7 @@ CmiCreateNewRegFile(HANDLE FileHandle) return(Status); } - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); return(Status); @@ -483,7 +485,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) else if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateFile() failed (Status %lx)\n", Status); - NtClose(HiveHandle); + ZwClose(HiveHandle); return(Status); } @@ -499,7 +501,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) /* Read hive base block */ FileOffset.QuadPart = 0ULL; - Status = NtReadFile(HiveHandle, + Status = ZwReadFile(HiveHandle, 0, 0, 0, @@ -510,7 +512,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) 0); if (!NT_SUCCESS(Status)) { - DPRINT("NtReadFile() failed (Status %lx)\n", Status); + DPRINT("ZwReadFile() failed (Status %lx)\n", Status); goto ByeBye; } @@ -541,7 +543,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) /* Read log file header */ FileOffset.QuadPart = 0ULL; - Status = NtReadFile(LogHandle, + Status = ZwReadFile(LogHandle, 0, 0, 0, @@ -552,7 +554,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) 0); if (!NT_SUCCESS(Status)) { - DPRINT("NtReadFile() failed (Status %lx)\n", Status); + DPRINT("ZwReadFile() failed (Status %lx)\n", Status); goto ByeBye; } @@ -585,14 +587,14 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) */ /* Get file size */ - Status = NtQueryInformationFile(LogHandle, + Status = ZwQueryInformationFile(LogHandle, &IoStatusBlock, &fsi, sizeof(fsi), FileStandardInformation); if (!NT_SUCCESS(Status)) { - DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); + DPRINT("ZwQueryInformationFile() failed (Status %lx)\n", Status); goto ByeBye; } FileSize = fsi.EndOfFile.u.LowPart; @@ -617,7 +619,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) /* Read log file header */ FileOffset.QuadPart = 0ULL; - Status = NtReadFile(LogHandle, + Status = ZwReadFile(LogHandle, 0, 0, 0, @@ -628,7 +630,7 @@ CmiCheckAndFixHive(PREGISTRY_HIVE RegistryHive) 0); if (!NT_SUCCESS(Status)) { - DPRINT("NtReadFile() failed (Status %lx)\n", Status); + DPRINT("ZwReadFile() failed (Status %lx)\n", Status); goto ByeBye; } @@ -656,9 +658,9 @@ ByeBye: ExFreePool(LogHeader); if (LogHandle != INVALID_HANDLE_VALUE) - NtClose(LogHandle); + ZwClose(LogHandle); - NtClose(HiveHandle); + ZwClose(HiveHandle); return(Status); } @@ -861,11 +863,11 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, RegistryHive, Filename); /* Duplicate Filename */ - Status = RtlCreateUnicodeString(&RegistryHive->HiveFileName, - Filename); + Status = RtlpCreateUnicodeString(&RegistryHive->HiveFileName, + Filename, NonPagedPool); if (!NT_SUCCESS(Status)) { - DPRINT("RtlCreateUnicodeString() failed (Status %lx)\n", Status); + DPRINT("RtlpCreateUnicodeString() failed (Status %lx)\n", Status); return(Status); } @@ -929,7 +931,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, if (!NT_SUCCESS(Status)) { DPRINT("CmiCreateNewRegFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + ZwClose(FileHandle); RtlFreeUnicodeString(&RegistryHive->HiveFileName); RtlFreeUnicodeString(&RegistryHive->LogFileName); return(Status); @@ -972,7 +974,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, ObDereferenceObject(SectionObject); RtlFreeUnicodeString(&RegistryHive->HiveFileName); RtlFreeUnicodeString(&RegistryHive->LogFileName); - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } DPRINT("ViewBase %p ViewSize %lx\n", ViewBase, ViewSize); @@ -996,7 +998,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, ObDereferenceObject(SectionObject); RtlFreeUnicodeString(&RegistryHive->HiveFileName); RtlFreeUnicodeString(&RegistryHive->LogFileName); - NtClose(FileHandle); + ZwClose(FileHandle); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory (RegistryHive->BlockList, @@ -1013,7 +1015,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, ObDereferenceObject(SectionObject); RtlFreeUnicodeString(&RegistryHive->HiveFileName); RtlFreeUnicodeString(&RegistryHive->LogFileName); - NtClose(FileHandle); + ZwClose(FileHandle); return Status; } @@ -1023,7 +1025,7 @@ CmiInitNonVolatileRegistryHive (PREGISTRY_HIVE RegistryHive, ObDereferenceObject(SectionObject); /* Close the hive file */ - NtClose(FileHandle); + ZwClose(FileHandle); /* Initialize the free cell list */ Status = CmiCreateHiveFreeCellList (RegistryHive); @@ -1438,7 +1440,7 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) /* Write hive block and block bitmap */ FileOffset.QuadPart = (ULONGLONG)0; - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1449,8 +1451,8 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); ExFreePool(Buffer); return(Status); } @@ -1479,7 +1481,7 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) DPRINT("File offset %I64x\n", FileOffset.QuadPart); /* Write hive block */ - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1490,8 +1492,8 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } @@ -1501,40 +1503,40 @@ CmiStartLogUpdate(PREGISTRY_HIVE RegistryHive) /* Truncate log file */ EndOfFileInfo.EndOfFile.QuadPart = FileOffset.QuadPart; - Status = NtSetInformationFile(FileHandle, + Status = ZwSetInformationFile(FileHandle, &IoStatusBlock, &EndOfFileInfo, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) { - DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } FileAllocationInfo.AllocationSize.QuadPart = FileOffset.QuadPart; - Status = NtSetInformationFile(FileHandle, + Status = ZwSetInformationFile(FileHandle, &IoStatusBlock, &FileAllocationInfo, sizeof(FILE_ALLOCATION_INFORMATION), FileAllocationInformation); if (!NT_SUCCESS(Status)) { - DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } /* Flush the log file */ - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -1616,7 +1618,7 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive) /* Write hive block and block bitmap */ FileOffset.QuadPart = (ULONGLONG)0; - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1627,8 +1629,8 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); ExFreePool(Buffer); return(Status); } @@ -1636,14 +1638,14 @@ CmiFinishLogUpdate(PREGISTRY_HIVE RegistryHive) ExFreePool(Buffer); /* Flush the log file */ - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -1697,20 +1699,20 @@ CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive) /* Truncate log file */ EndOfFileInfo.EndOfFile.QuadPart = (ULONGLONG)BufferSize; - Status = NtSetInformationFile(FileHandle, + Status = ZwSetInformationFile(FileHandle, &IoStatusBlock, &EndOfFileInfo, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) { - DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwSetInformationFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } FileAllocationInfo.AllocationSize.QuadPart = (ULONGLONG)BufferSize; - Status = NtSetInformationFile(FileHandle, + Status = ZwSetInformationFile(FileHandle, &IoStatusBlock, &FileAllocationInfo, sizeof(FILE_ALLOCATION_INFORMATION), @@ -1718,19 +1720,19 @@ CmiCleanupLogUpdate(PREGISTRY_HIVE RegistryHive) if (!NT_SUCCESS(Status)) { DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } /* Flush the log file */ - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -1780,7 +1782,7 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) /* Write hive block */ FileOffset.QuadPart = (ULONGLONG)0; - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1791,8 +1793,8 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } @@ -1819,7 +1821,7 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) DPRINT(" File offset %I64x\n", FileOffset.QuadPart); /* Write hive block */ - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1830,22 +1832,22 @@ CmiStartHiveUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } BlockIndex++; } - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -1892,7 +1894,7 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive) /* Write hive block */ FileOffset.QuadPart = (ULONGLONG)0; - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -1903,19 +1905,19 @@ CmiFinishHiveUpdate(PREGISTRY_HIVE RegistryHive) NULL); if (!NT_SUCCESS(Status)) { - DPRINT("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return(Status); } - Status = NtFlushBuffersFile(FileHandle, + Status = ZwFlushBuffersFile(FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -1939,7 +1941,7 @@ CmiFlushRegistryHive(PREGISTRY_HIVE RegistryHive) &RegistryHive->LogFileName); /* Update hive header modification time */ - NtQuerySystemTime(&RegistryHive->HiveHeader->DateModified); + KeQuerySystemTime(&RegistryHive->HiveHeader->DateModified); /* Start log update */ Status = CmiStartLogUpdate(RegistryHive); @@ -2436,7 +2438,7 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, { NewKeyCell->Id = REG_KEY_CELL_ID; NewKeyCell->Flags = 0; - NtQuerySystemTime(&NewKeyCell->LastWriteTime); + KeQuerySystemTime(&NewKeyCell->LastWriteTime); NewKeyCell->ParentKeyOffset = -1; NewKeyCell->NumberOfSubKeys = 0; NewKeyCell->HashTableOffset = -1; @@ -2552,7 +2554,7 @@ CmiAddSubKey(PREGISTRY_HIVE RegistryHive, ParentKeyCell->NumberOfSubKeys++; } - NtQuerySystemTime (&ParentKeyCell->LastWriteTime); + KeQuerySystemTime (&ParentKeyCell->LastWriteTime); CmiMarkBlockDirty (RegistryHive, ParentKey->KeyCellOffset); return(Status); @@ -2710,7 +2712,7 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive, } } - NtQuerySystemTime(&ParentKey->KeyCell->LastWriteTime); + KeQuerySystemTime(&ParentKey->KeyCell->LastWriteTime); CmiMarkBlockDirty(ParentKey->RegistryHive, ParentKey->KeyCellOffset); } @@ -3210,7 +3212,7 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, /* Update time of heap */ if (!IsNoFileHive(RegistryHive)) - NtQuerySystemTime(&Bin->DateModified); + KeQuerySystemTime(&Bin->DateModified); } /* Destroy the value cell */ @@ -3219,7 +3221,7 @@ CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, /* Update time of heap */ if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, ValueCellOffset, &Bin)) { - NtQuerySystemTime(&Bin->DateModified); + KeQuerySystemTime(&Bin->DateModified); } return Status; @@ -3254,7 +3256,7 @@ CmiAddBin(PREGISTRY_HIVE RegistryHive, RegistryHive->FileSize += BinSize; tmpBin->BinSize = BinSize; tmpBin->Unused1 = 0; - NtQuerySystemTime(&tmpBin->DateModified); + KeQuerySystemTime(&tmpBin->DateModified); tmpBin->Unused2 = 0; DPRINT (" BinOffset %lx BinSize %lx\n", tmpBin->BinOffset,tmpBin->BinSize); @@ -3382,7 +3384,7 @@ CmiAllocateCell (PREGISTRY_HIVE RegistryHive, return STATUS_UNSUCCESSFUL; } - NtQuerySystemTime(&Bin->DateModified); + KeQuerySystemTime(&Bin->DateModified); CmiMarkBlockDirty(RegistryHive, RegistryHive->FreeListOffset[i]); if ((i + 1) < RegistryHive->FreeListSize) @@ -3471,7 +3473,7 @@ CmiDestroyCell (PREGISTRY_HIVE RegistryHive, /* Update time of heap */ if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, CellOffset,&pBin)) - NtQuerySystemTime(&pBin->DateModified); + KeQuerySystemTime(&pBin->DateModified); CmiMarkBlockDirty(RegistryHive, CellOffset); } @@ -4247,7 +4249,7 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive, /* Write hive block */ FileOffset.QuadPart = (ULONGLONG)0; - Status = NtWriteFile (FileHandle, + Status = ZwWriteFile (FileHandle, NULL, NULL, NULL, @@ -4258,7 +4260,7 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtWriteFile() failed (Status %lx)\n", Status); + DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status); return Status; } @@ -4272,7 +4274,7 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive, DPRINT ("File offset %I64x\n", FileOffset.QuadPart); /* Write hive block */ - Status = NtWriteFile (FileHandle, + Status = ZwWriteFile (FileHandle, NULL, NULL, NULL, @@ -4283,16 +4285,16 @@ CmiSaveTempHive (PREGISTRY_HIVE Hive, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtWriteFile() failed (Status %lx)\n", Status); + DPRINT1 ("ZwWriteFile() failed (Status %lx)\n", Status); return Status; } } - Status = NtFlushBuffersFile (FileHandle, + Status = ZwFlushBuffersFile (FileHandle, &IoStatusBlock); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtFlushBuffersFile() failed (Status %lx)\n", Status); + DPRINT1 ("ZwFlushBuffersFile() failed (Status %lx)\n", Status); } DPRINT ("CmiSaveTempHive() done\n"); diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c index e69702d9086..87dad05bc73 100644 --- a/reactos/ntoskrnl/cm/registry.c +++ b/reactos/ntoskrnl/cm/registry.c @@ -4,11 +4,10 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/cm/registry.c * PURPOSE: Registry functions + * * PROGRAMMERS: Rex Jolliff * Matt Pyne * Jean Michault - * UPDATE HISTORY: - * Created 22/05/98 */ #include @@ -73,7 +72,7 @@ CmiCheckSubKeys(BOOLEAN Verbose, BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; KeyInfo = ExAllocatePool(PagedPool, BufferSize); - Status = NtEnumerateKey(Key, + Status = ZwEnumerateKey(Key, Index, KeyNodeInformation, KeyInfo, @@ -111,7 +110,7 @@ CmiCheckSubKeys(BOOLEAN Verbose, NULL, NULL); - Status = NtOpenKey(&SubKey, + Status = ZwOpenKey(&SubKey, KEY_ALL_ACCESS, &ObjectAttributes); @@ -119,7 +118,7 @@ CmiCheckSubKeys(BOOLEAN Verbose, CmiCheckKey(Verbose, SubKey); - NtClose(SubKey); + ZwClose(SubKey); Index++; } @@ -145,7 +144,7 @@ CmiCheckValues(BOOLEAN Verbose, BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; ValueInfo = ExAllocatePool(PagedPool, BufferSize); - Status = NtEnumerateValueKey(Key, + Status = ZwEnumerateValueKey(Key, Index, KeyNodeInformation, ValueInfo, @@ -209,7 +208,7 @@ CmiCheckByName(BOOLEAN Verbose, NULL, NULL); - Status = NtOpenKey(&Key, + Status = ZwOpenKey(&Key, KEY_ALL_ACCESS, &ObjectAttributes); @@ -225,7 +224,7 @@ CmiCheckByName(BOOLEAN Verbose, CmiCheckKey(Verbose, Key); - NtClose(Key); + ZwClose(Key); } @@ -259,8 +258,8 @@ CmInitializeRegistry(VOID) CmiKeyType->Tag = TAG('R', 'e', 'g', 'K'); CmiKeyType->TotalObjects = 0; CmiKeyType->TotalHandles = 0; - CmiKeyType->MaxObjects = LONG_MAX; - CmiKeyType->MaxHandles = LONG_MAX; + CmiKeyType->PeakObjects = 0; + CmiKeyType->PeakHandles = 0; CmiKeyType->PagedPoolCharge = 0; CmiKeyType->NonpagedPoolCharge = sizeof(KEY_OBJECT); CmiKeyType->Mapping = &CmiKeyMapping; @@ -316,7 +315,7 @@ CmInitializeRegistry(VOID) RootKey->NumberOfSubKeys = 0; RootKey->SubKeys = NULL; RootKey->SizeOfSubKeys = 0; - Status = RtlCreateUnicodeString(&RootKey->Name, L"Registry"); + Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool); ASSERT(NT_SUCCESS(Status)); #if 0 @@ -341,7 +340,7 @@ CmInitializeRegistry(VOID) 0, RootKeyHandle, NULL); - Status = NtCreateKey(&KeyHandle, + Status = ZwCreateKey(&KeyHandle, STANDARD_RIGHTS_REQUIRED, &ObjectAttributes, 0, @@ -358,7 +357,7 @@ CmInitializeRegistry(VOID) 0, RootKeyHandle, NULL); - Status = NtCreateKey(&KeyHandle, + Status = ZwCreateKey(&KeyHandle, STANDARD_RIGHTS_REQUIRED, &ObjectAttributes, 0, @@ -541,7 +540,7 @@ CmiCreateCurrentControlSetLink(VOID) OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK, NULL, NULL); - Status = NtCreateKey(&KeyHandle, + Status = ZwCreateKey(&KeyHandle, KEY_ALL_ACCESS | KEY_CREATE_LINK, &ObjectAttributes, 0, @@ -550,13 +549,13 @@ CmiCreateCurrentControlSetLink(VOID) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); + DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status); return(Status); } RtlRosInitUnicodeStringFromLiteral(&LinkValue, L"SymbolicLinkValue"); - Status = NtSetValueKey(KeyHandle, + Status = ZwSetValueKey(KeyHandle, &LinkValue, 0, REG_LINK, @@ -564,10 +563,10 @@ CmiCreateCurrentControlSetLink(VOID) TargetNameLength); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); } - NtClose(KeyHandle); + ZwClose(KeyHandle); return Status; } @@ -663,12 +662,12 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes, DPRINT ("SubName %S\n", SubName); - Status = RtlCreateUnicodeString(&NewKey->Name, - SubName); + Status = RtlpCreateUnicodeString(&NewKey->Name, + SubName, NonPagedPool); RtlFreeUnicodeString(&RemainingPath); if (!NT_SUCCESS(Status)) { - DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status); + DPRINT1("RtlpCreateUnicodeString() failed (Status %lx)\n", Status); if (NewKey->SubKeys != NULL) { ExFreePool (NewKey->SubKeys); @@ -721,7 +720,7 @@ CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes, KernelMode, (PVOID*)&KeyObject, NULL); - NtClose (KeyHandle); + ZwClose (KeyHandle); if (!NT_SUCCESS(Status)) { DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status); @@ -776,7 +775,7 @@ CmiInitControlSetLink (VOID) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtCreateKey (&KeyHandle, + Status = ZwCreateKey (&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -785,10 +784,10 @@ CmiInitControlSetLink (VOID) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status); + DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status); return Status; } - NtClose (KeyHandle); + ZwClose (KeyHandle); /* Link 'CurrentControlSet' to 'ControlSet001' key */ RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName, @@ -798,7 +797,7 @@ CmiInitControlSetLink (VOID) OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK, NULL, NULL); - Status = NtCreateKey (&KeyHandle, + Status = ZwCreateKey (&KeyHandle, KEY_ALL_ACCESS | KEY_CREATE_LINK, &ObjectAttributes, 0, @@ -807,13 +806,13 @@ CmiInitControlSetLink (VOID) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status); + DPRINT1 ("ZwCreateKey() failed (Status %lx)\n", Status); return Status; } RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName, L"SymbolicLinkValue"); - Status = NtSetValueKey (KeyHandle, + Status = ZwSetValueKey (KeyHandle, &ControlSetValueName, 0, REG_LINK, @@ -821,9 +820,9 @@ CmiInitControlSetLink (VOID) ControlSetKeyName.Length); if (!NT_SUCCESS(Status)) { - DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1 ("ZwSetValueKey() failed (Status %lx)\n", Status); } - NtClose (KeyHandle); + ZwClose (KeyHandle); return STATUS_SUCCESS; } @@ -859,12 +858,12 @@ CmiInitHives(BOOLEAN SetupBoot) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); + DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status); return(Status); } @@ -876,17 +875,17 @@ CmiInitHives(BOOLEAN SetupBoot) BufferSize); if (ValueInfo == NULL) { - NtClose(KeyHandle); + ZwClose(KeyHandle); return(STATUS_INSUFFICIENT_RESOURCES); } - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueInfo, BufferSize, &ResultSize); - NtClose(KeyHandle); + ZwClose(KeyHandle); if (!NT_SUCCESS(Status)) { ExFreePool(ValueInfo); diff --git a/reactos/ntoskrnl/cm/regobj.c b/reactos/ntoskrnl/cm/regobj.c index f4de497cd6a..0bb1984e724 100644 --- a/reactos/ntoskrnl/cm/regobj.c +++ b/reactos/ntoskrnl/cm/regobj.c @@ -1,9 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/cm/regobj.c - * PURPOSE: Registry object manipulation routines. - * UPDATE HISTORY: +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/regobj.c + * PURPOSE: Registry object manipulation routines. + * + * PROGRAMMERS: No programmer listed. */ #include @@ -158,8 +160,8 @@ CmiObjectParse(PVOID ParsedObject, FoundObject->KeyCell = SubKeyCell; FoundObject->KeyCellOffset = BlockOffset; FoundObject->RegistryHive = ParsedKey->RegistryHive; - RtlCreateUnicodeString(&FoundObject->Name, - KeyName.Buffer); + RtlpCreateUnicodeString(&FoundObject->Name, + KeyName.Buffer, NonPagedPool); CmiAddKeyToList(ParsedKey, FoundObject); DPRINT("Created object 0x%x\n", FoundObject); } @@ -246,8 +248,8 @@ CmiObjectCreate(PVOID ObjectBody, Start = RemainingPath; if(*Start == L'\\') Start++; - RtlCreateUnicodeString(&KeyObject->Name, - Start); + RtlpCreateUnicodeString(&KeyObject->Name, + Start, NonPagedPool); } else { @@ -287,7 +289,7 @@ CmiObjectDelete(PVOID DeletedObject) ParentKeyObject, KeyObject); - NtQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime); + KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime); CmiMarkBlockDirty (ParentKeyObject->RegistryHive, ParentKeyObject->KeyCellOffset); diff --git a/reactos/ntoskrnl/cm/rtlfunc.c b/reactos/ntoskrnl/cm/rtlfunc.c deleted file mode 100644 index 7d2bd14ace0..00000000000 --- a/reactos/ntoskrnl/cm/rtlfunc.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/cm/rtlfunc.c - * PURPOSE: Rtlxxx function for registry access - * UPDATE HISTORY: -*/ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -#include "cm.h" - -/* FUNCTIONS ****************************************************************/ - - -static NTSTATUS -RtlpGetRegistryHandle(ULONG RelativeTo, - PWSTR Path, - BOOLEAN Create, - PHANDLE KeyHandle) -{ - UNICODE_STRING KeyPath; - UNICODE_STRING KeyName; - WCHAR KeyBuffer[MAX_PATH]; - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - - if (RelativeTo & RTL_REGISTRY_HANDLE) - { - Status = NtDuplicateObject(NtCurrentProcess(), - (HANDLE)Path, - NtCurrentProcess(), - KeyHandle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS); - return(Status); - } - - if (RelativeTo & RTL_REGISTRY_OPTIONAL) - RelativeTo &= ~RTL_REGISTRY_OPTIONAL; - - if (RelativeTo >= RTL_REGISTRY_MAXIMUM) - return STATUS_INVALID_PARAMETER; - - KeyName.Length = 0; - KeyName.MaximumLength = MAX_PATH; - KeyName.Buffer = KeyBuffer; - KeyBuffer[0] = 0; - - switch (RelativeTo) - { - case RTL_REGISTRY_SERVICES: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - break; - - case RTL_REGISTRY_CONTROL: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\"); - break; - - case RTL_REGISTRY_WINDOWS_NT: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"); - break; - - case RTL_REGISTRY_DEVICEMAP: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\Hardware\\DeviceMap\\"); - break; - - case RTL_REGISTRY_USER: - Status = RtlFormatCurrentUserKeyPath (&KeyPath); - if (!NT_SUCCESS(Status)) - return(Status); - RtlAppendUnicodeStringToString (&KeyName, - &KeyPath); - RtlFreeUnicodeString (&KeyPath); - RtlAppendUnicodeToString (&KeyName, - L"\\"); - break; - - /* ReactOS specific */ - case RTL_REGISTRY_ENUM: - RtlAppendUnicodeToString(&KeyName, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - break; - } - - if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) - { - Path++; - } - RtlAppendUnicodeToString(&KeyName, - Path); - - DPRINT("KeyName '%wZ'\n", &KeyName); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - NULL, - NULL); - - if (Create == TRUE) - { - Status = NtCreateKey(KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes, - 0, - NULL, - 0, - NULL); - } - else - { - Status = NtOpenKey(KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes); - } - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlCheckRegistryKey(IN ULONG RelativeTo, - IN PWSTR Path) -{ - HANDLE KeyHandle; - NTSTATUS Status; - - Status = RtlpGetRegistryHandle(RelativeTo, - Path, - FALSE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - NtClose(KeyHandle); - - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlCreateRegistryKey(IN ULONG RelativeTo, - IN PWSTR Path) -{ - HANDLE KeyHandle; - NTSTATUS Status; - - Status = RtlpGetRegistryHandle(RelativeTo, - Path, - TRUE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - NtClose(KeyHandle); - - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlDeleteRegistryValue(IN ULONG RelativeTo, - IN PCWSTR Path, - IN PCWSTR ValueName) -{ - HANDLE KeyHandle; - NTSTATUS Status; - UNICODE_STRING Name; - - Status = RtlpGetRegistryHandle(RelativeTo, - (PWSTR) Path, - TRUE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - RtlInitUnicodeString(&Name, - ValueName); - - NtDeleteValueKey(KeyHandle, - &Name); - - NtClose(KeyHandle); - - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) -{ - HANDLE TokenHandle; - UCHAR Buffer[256]; - PSID_AND_ATTRIBUTES SidBuffer; - ULONG Length; - UNICODE_STRING SidString; - NTSTATUS Status; - - DPRINT ("RtlFormatCurrentUserKeyPath() called\n"); - - Status = ZwOpenThreadToken (NtCurrentThread (), - TOKEN_READ, - TRUE, - &TokenHandle); - if (!NT_SUCCESS (Status)) - { - if (Status != STATUS_NO_TOKEN) - { - DPRINT1 ("ZwOpenThreadToken() failed (Status %lx)\n", Status); - return Status; - } - - Status = ZwOpenProcessToken (NtCurrentProcess (), - TOKEN_READ, - &TokenHandle); - if (!NT_SUCCESS (Status)) - { - DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status); - return Status; - } - } - - SidBuffer = (PSID_AND_ATTRIBUTES)Buffer; - Status = ZwQueryInformationToken (TokenHandle, - TokenUser, - (PVOID)SidBuffer, - 256, - &Length); - NtClose (TokenHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT ("ZwQueryInformationToken() failed (Status %lx)\n", Status); - return Status; - } - - Status = RtlConvertSidToUnicodeString (&SidString, - SidBuffer[0].Sid, - TRUE); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("RtlConvertSidToUnicodeString() failed (Status %lx)\n", Status); - return Status; - } - - DPRINT ("SidString: '%wZ'\n", &SidString); - - Length = SidString.Length + sizeof(L"\\Registry\\User\\"); - DPRINT ("Length: %lu\n", Length); - - KeyPath->Length = 0; - KeyPath->MaximumLength = Length; - KeyPath->Buffer = ExAllocatePool (NonPagedPool, - KeyPath->MaximumLength); - if (KeyPath->Buffer == NULL) - { - DPRINT1 ("RtlAllocateHeap() failed\n"); - RtlFreeUnicodeString (&SidString); - return STATUS_NO_TOKEN; - } - - RtlAppendUnicodeToString (KeyPath, - L"\\Registry\\User\\"); - RtlAppendUnicodeStringToString (KeyPath, - &SidString); - RtlFreeUnicodeString (&SidString); - - return STATUS_SUCCESS; -} - - -NTSTATUS STDCALL -RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, - OUT PHANDLE KeyHandle) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyPath; - NTSTATUS Status; - - Status = RtlFormatCurrentUserKeyPath(&KeyPath); - if (NT_SUCCESS(Status)) - { - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = NtOpenKey(KeyHandle, - DesiredAccess, - &ObjectAttributes); - RtlFreeUnicodeString(&KeyPath); - if (NT_SUCCESS(Status)) - return(STATUS_SUCCESS); - } - - RtlInitUnicodeString (&KeyPath, - L"\\Registry\\User\\.Default"); - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = NtOpenKey(KeyHandle, - DesiredAccess, - &ObjectAttributes); - return(Status); -} - - -/* - * @unimplemented - */ -NTSTATUS STDCALL -RtlQueryRegistryValues(IN ULONG RelativeTo, - IN PCWSTR Path, - IN PRTL_QUERY_REGISTRY_TABLE QueryTable, - IN PVOID Context, - IN PVOID Environment) -{ - NTSTATUS Status; - HANDLE BaseKeyHandle; - HANDLE CurrentKeyHandle; - PRTL_QUERY_REGISTRY_TABLE QueryEntry; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyName; - PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; - PKEY_VALUE_FULL_INFORMATION FullValueInfo; - ULONG BufferSize; - ULONG ResultSize; - ULONG ValueNameSize; - ULONG Index; - ULONG StringLen; - PWSTR StringPtr; - PWSTR ValueName; - - DPRINT("RtlQueryRegistryValues() called\n"); - - Status = RtlpGetRegistryHandle(RelativeTo, - (PWSTR) Path, - FALSE, - &BaseKeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status); - return(Status); - } - - CurrentKeyHandle = BaseKeyHandle; - QueryEntry = QueryTable; - while ((QueryEntry->QueryRoutine != NULL) || - (QueryEntry->Name != NULL)) - { - if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) && - (BaseKeyHandle != CurrentKeyHandle)) - { - NtClose(CurrentKeyHandle); - CurrentKeyHandle = BaseKeyHandle; - } - - if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) - { - DPRINT("Open new subkey: %S\n", QueryEntry->Name); - - RtlInitUnicodeString(&KeyName, - QueryEntry->Name); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - BaseKeyHandle, - NULL); - Status = NtOpenKey(&CurrentKeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - break; - } - else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT) - { - DPRINT("Query value directly: %S\n", QueryEntry->Name); - - RtlInitUnicodeString(&KeyName, - QueryEntry->Name); - - BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; - ValueInfo = ExAllocatePool(PagedPool, BufferSize); - if (ValueInfo == NULL) - { - Status = STATUS_NO_MEMORY; - break; - } - - Status = ZwQueryValueKey(CurrentKeyHandle, - &KeyName, - KeyValuePartialInformation, - ValueInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED) - { - ExFreePool(ValueInfo); - Status = STATUS_OBJECT_NAME_NOT_FOUND; - goto ByeBye; - } - - if (QueryEntry->DefaultType == REG_SZ) - { - PUNICODE_STRING ValueString; - PUNICODE_STRING SourceString; - - SourceString = (PUNICODE_STRING)QueryEntry->DefaultData; - ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; - if (ValueString->Buffer == 0) - { - ValueString->Length = SourceString->Length; - ValueString->MaximumLength = SourceString->MaximumLength; - ValueString->Buffer = ExAllocatePool(PagedPool, - ValueString->MaximumLength); - if (!ValueString->Buffer) - break; - ValueString->Buffer[0] = 0; - memcpy(ValueString->Buffer, - SourceString->Buffer, - SourceString->MaximumLength); - } - else - { - ValueString->Length = RtlRosMin(SourceString->Length, - ValueString->MaximumLength - sizeof(WCHAR)); - memcpy(ValueString->Buffer, - SourceString->Buffer, - ValueString->Length); - ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; - } - } - else - { - memcpy(QueryEntry->EntryContext, - QueryEntry->DefaultData, - QueryEntry->DefaultLength); - } - Status = STATUS_SUCCESS; - } - else - { - if (ValueInfo->Type == REG_SZ || - ValueInfo->Type == REG_MULTI_SZ || - ValueInfo->Type == REG_EXPAND_SZ) - { - PUNICODE_STRING ValueString; - - ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; - if (ValueString->Buffer == 0) - { - RtlInitUnicodeString(ValueString, - NULL); - ValueString->MaximumLength = ValueInfo->DataLength; - ValueString->Buffer = ExAllocatePool(PagedPool, - ValueString->MaximumLength); - if (!ValueString->Buffer) - break; - ValueString->Buffer[0] = 0; - } - ValueString->Length = RtlRosMin(ValueInfo->DataLength, - ValueString->MaximumLength) - sizeof(WCHAR); - memcpy(ValueString->Buffer, - ValueInfo->Data, - ValueString->Length); - ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; - } - else - { - memcpy(QueryEntry->EntryContext, - ValueInfo->Data, - ValueInfo->DataLength); - } - } - - if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) - { - DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name); - - } - - ExFreePool(ValueInfo); - } - else - { - DPRINT("Query value via query routine: %S\n", QueryEntry->Name); - - if (QueryEntry->Name != NULL) - { - DPRINT("Callback\n"); - - RtlInitUnicodeString(&KeyName, - QueryEntry->Name); - - BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; - ValueInfo = ExAllocatePool(PagedPool, - BufferSize); - if (ValueInfo == NULL) - { - Status = STATUS_NO_MEMORY; - break; - } - - Status = NtQueryValueKey(CurrentKeyHandle, - &KeyName, - KeyValuePartialInformation, - ValueInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - if (! (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)) - { - Status = QueryEntry->QueryRoutine(QueryEntry->Name, - QueryEntry->DefaultType, - QueryEntry->DefaultData, - QueryEntry->DefaultLength, - Context, - QueryEntry->EntryContext); - } - } - else if ((ValueInfo->Type == REG_MULTI_SZ) && - !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) - { - DPRINT("Expand REG_MULTI_SZ type\n"); - StringPtr = (PWSTR)ValueInfo->Data; - while (*StringPtr != 0) - { - StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); - Status = QueryEntry->QueryRoutine(QueryEntry->Name, - REG_SZ, - (PVOID)StringPtr, - StringLen, - Context, - QueryEntry->EntryContext); - if(!NT_SUCCESS(Status)) - break; - StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); - } - } - else - { - Status = QueryEntry->QueryRoutine(QueryEntry->Name, - ValueInfo->Type, - ValueInfo->Data, - ValueInfo->DataLength, - Context, - QueryEntry->EntryContext); - } - - if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) - { - DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name); - - } - - ExFreePool(ValueInfo); - - if (!NT_SUCCESS(Status)) - break; - } - else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE) - { - DPRINT("Simple callback\n"); - Status = QueryEntry->QueryRoutine(NULL, - REG_NONE, - NULL, - 0, - Context, - QueryEntry->EntryContext); - if (!NT_SUCCESS(Status)) - break; - } - else - { - DPRINT("Enumerate values\n"); - - BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096; - FullValueInfo = ExAllocatePool(PagedPool, - BufferSize); - if (FullValueInfo == NULL) - { - Status = STATUS_NO_MEMORY; - break; - } - ValueNameSize = 256 * sizeof(WCHAR); - ValueName = ExAllocatePool(PagedPool, - ValueNameSize); - if (ValueName == NULL) - { - Status = STATUS_NO_MEMORY; - break; - } - Index = 0; - while (TRUE) - { - Status = NtEnumerateValueKey(CurrentKeyHandle, - Index, - KeyValueFullInformation, - FullValueInfo, - BufferSize, - &ResultSize); - if (!NT_SUCCESS(Status)) - { - if ((Status == STATUS_NO_MORE_ENTRIES) && - (Index == 0) && - (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)) - { - Status = STATUS_OBJECT_NAME_NOT_FOUND; - } - else if (Status == STATUS_NO_MORE_ENTRIES) - { - Status = STATUS_SUCCESS; - } - break; - } - - if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR)) - { - /* Should not happen, because the name length is limited to 255 characters */ - ExFreePool(ValueName); - ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR); - ValueName = ExAllocatePool(PagedPool, ValueNameSize); - if (ValueName == NULL) - { - Status = STATUS_NO_MEMORY; - break; - } - } - - RtlCopyMemory(ValueName, - FullValueInfo->Name, - FullValueInfo->NameLength); - ValueName[FullValueInfo->NameLength / sizeof(WCHAR)] = 0; - - if ((FullValueInfo->Type == REG_MULTI_SZ) && - !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) - { - DPRINT("Expand REG_MULTI_SZ type\n"); - - StringPtr = (PWSTR)((char*)FullValueInfo + FullValueInfo->DataOffset); - while (*StringPtr != 0) - { - StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); - Status = QueryEntry->QueryRoutine(ValueName, - REG_SZ, - (PVOID)StringPtr, - StringLen, - Context, - QueryEntry->EntryContext); - if(!NT_SUCCESS(Status)) - break; - StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); - } - } - else - { - Status = QueryEntry->QueryRoutine(ValueName, - FullValueInfo->Type, - (char*)FullValueInfo + FullValueInfo->DataOffset, - FullValueInfo->DataLength, - Context, - QueryEntry->EntryContext); - } - - if (!NT_SUCCESS(Status)) - break; - - /* FIXME: How will these be deleted? */ - - Index++; - } - - ExFreePool(FullValueInfo); - ExFreePool(ValueName); - - if (!NT_SUCCESS(Status)) - break; - } - } - - QueryEntry++; - } - -ByeBye: - - if (CurrentKeyHandle != BaseKeyHandle) - NtClose(CurrentKeyHandle); - - NtClose(BaseKeyHandle); - - return Status; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlWriteRegistryValue(IN ULONG RelativeTo, - IN PCWSTR Path, - IN PCWSTR ValueName, - IN ULONG ValueType, - IN PVOID ValueData, - IN ULONG ValueLength) -{ - HANDLE KeyHandle; - NTSTATUS Status; - UNICODE_STRING Name; - - Status = RtlpGetRegistryHandle(RelativeTo, - (PWSTR) Path, - TRUE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - RtlInitUnicodeString(&Name, - ValueName); - - NtSetValueKey(KeyHandle, - &Name, - 0, - ValueType, - ValueData, - ValueLength); - - NtClose(KeyHandle); - - return(STATUS_SUCCESS); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/dbg/dbgctrl.c b/reactos/ntoskrnl/dbg/dbgctrl.c index ac5fdb63afd..705fa3378a4 100644 --- a/reactos/ntoskrnl/dbg/dbgctrl.c +++ b/reactos/ntoskrnl/dbg/dbgctrl.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/dbgctrl.c * PURPOSE: System debug control - * PORTABILITY: Checked + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/dbg/errinfo.c b/reactos/ntoskrnl/dbg/errinfo.c index 5ca0e9b5e78..765e5d8b762 100644 --- a/reactos/ntoskrnl/dbg/errinfo.c +++ b/reactos/ntoskrnl/dbg/errinfo.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/errinfo.c * PURPOSE: Print information descriptions of error messages - * PORTABILITY: Checked - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/dbg/i386/i386-dis.c b/reactos/ntoskrnl/dbg/i386/i386-dis.c index 558b120e5dc..486406610c3 100644 --- a/reactos/ntoskrnl/dbg/i386/i386-dis.c +++ b/reactos/ntoskrnl/dbg/i386/i386-dis.c @@ -1,3 +1,13 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/i386/i386-dis.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #include /* ReactOS compatibility stuff. */ diff --git a/reactos/ntoskrnl/dbg/kdb.c b/reactos/ntoskrnl/dbg/kdb.c index 9ead1ff917e..98954ed9058 100644 --- a/reactos/ntoskrnl/dbg/kdb.c +++ b/reactos/ntoskrnl/dbg/kdb.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2001-2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/kdb.c * PURPOSE: Kernel debugger - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 01/03/01 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ******************************************************************/ @@ -60,8 +42,9 @@ static KDB_ACTIVE_BREAKPOINT static BOOLEAN KdbHandleUmode = FALSE; static BOOLEAN KdbHandleHandled = FALSE; -static BOOLEAN KdbIgnoreNextSingleStep = FALSE; +static BOOLEAN KdbBreakOnModuleLoad = FALSE; +static BOOLEAN KdbIgnoreNextSingleStep = FALSE; static ULONG KdbLastSingleStepFrom = 0xFFFFFFFF; static BOOLEAN KdbEnteredOnSingleStep = FALSE; @@ -75,6 +58,8 @@ DbgContCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); ULONG DbgStopCondition(ULONG Aargc, PCH Argv[], PKTRAP_FRAME Tf); ULONG +DbgModuleLoadedAction(ULONG Aargc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG DbgEchoToggle(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); ULONG DbgRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); @@ -129,7 +114,8 @@ struct {"cont", "cont", "Exit the debugger", DbgContCommand}, {"echo", "echo", "Toggle serial echo", DbgEchoToggle}, {"condition", "condition [all|umode|kmode]", "Kdbg enter condition", DbgStopCondition}, - + {"module-loaded", "module-loaded [break|continue]", "Module-loaded action", DbgModuleLoadedAction}, + {"regs", "regs", "Display general purpose registers", DbgRegsCommand}, {"dregs", "dregs", "Display debug registers", DbgDRegsCommand}, {"cregs", "cregs", "Display control registers", DbgCRegsCommand}, @@ -909,9 +895,8 @@ DbgPrintBackTrace(PULONG Frame, ULONG_PTR StackBase, ULONG_PTR StackLimit) { PVOID Address; - DbgPrint("Frames: "); - while (Frame != NULL && (ULONG_PTR)Frame >= StackLimit && - (ULONG_PTR)Frame < StackBase) /* FIXME: why limit this to StackBase/StackLimit? */ + DbgPrint("Frames:\n"); + while (Frame != NULL) { if (!NT_SUCCESS(KdbpSafeReadMemory(&Address, Frame + 1, sizeof (Address)))) { @@ -1202,8 +1187,8 @@ DbgBackTraceCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) } else { - StackBase = (ULONG_PTR)&init_stack_top; - StackLimit = (ULONG_PTR)&init_stack; + StackBase = (ULONG_PTR)init_stack_top; + StackLimit = (ULONG_PTR)init_stack; } DbgPrintBackTrace((PULONG)&Tf->DebugEbp, StackBase, StackLimit); } @@ -1352,6 +1337,32 @@ DbgStopCondition(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) return(TRUE); } +ULONG +DbgModuleLoadedAction(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + if (Argc == 1) + { + if (KdbBreakOnModuleLoad) + DbgPrint("Current setting: break\n"); + else + DbgPrint("Current setting: continue\n"); + } + else if (!strcmp(Argv[1], "break")) + { + KdbBreakOnModuleLoad = TRUE; + } + else if (!strcmp(Argv[1], "continue")) + { + KdbBreakOnModuleLoad = FALSE; + } + else + { + DbgPrint("Unknown setting: %s\n", Argv[1]); + } + + return(TRUE); +} + ULONG DbgEchoToggle(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) { @@ -1656,23 +1667,24 @@ KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, LONG BreakPointNr; ULONG ExpNr = (ULONG)TrapFrame->DebugArgMark; + /* Always handle beakpoints */ if (ExpNr != 1 && ExpNr != 3) { DbgPrint(":KDBG:Entered:%s:%s\n", PreviousMode==KernelMode ? "kmode" : "umode", AlwaysHandle ? "always" : "if-unhandled"); - } - - /* If we aren't handling umode exceptions then return */ - if (PreviousMode == UserMode && !KdbHandleUmode && !AlwaysHandle) - { - return kdContinue; - } - /* If the exception would be unhandled (and we care) then handle it */ - if (PreviousMode == KernelMode && !KdbHandleHandled && !AlwaysHandle) - { - return kdContinue; + /* If we aren't handling umode exceptions then return */ + if (PreviousMode == UserMode && !KdbHandleUmode && !AlwaysHandle) + { + return kdHandleException; + } + + /* If the exception would be unhandled (and we care) then handle it */ + if (PreviousMode == KernelMode && !KdbHandleHandled && !AlwaysHandle) + { + return kdHandleException; + } } /* Exception inside the debugger? Game over. */ @@ -1772,3 +1784,14 @@ KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, return(kdContinue); } } + +VOID +KdbModuleLoaded(IN PUNICODE_STRING Name) +{ + if (!KdbBreakOnModuleLoad) + return; + + DbgPrint("Module %wZ loaded.\n", Name); + DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); +} + diff --git a/reactos/ntoskrnl/dbg/kdb.h b/reactos/ntoskrnl/dbg/kdb.h index a3380251c43..46c08762505 100644 --- a/reactos/ntoskrnl/dbg/kdb.h +++ b/reactos/ntoskrnl/dbg/kdb.h @@ -3,10 +3,10 @@ typedef struct _KDB_MODULE_INFO { - WCHAR Name[256]; - ULONG_PTR Base; - ULONG Size; - PIMAGE_SYMBOL_INFO SymbolInfo; + WCHAR Name[256]; + ULONG_PTR Base; + ULONG Size; + PROSSYM_INFO RosSymInfo; } KDB_MODULE_INFO, *PKDB_MODULE_INFO; /* from kdb_symbols.c */ @@ -27,24 +27,13 @@ BOOLEAN KdbSymPrintAddress(IN PVOID Address); NTSTATUS -KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo, +KdbSymGetAddressInformation(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress, OUT PULONG LineNumber OPTIONAL, OUT PCH FileName OPTIONAL, OUT PCH FunctionName OPTIONAL); -BOOLEAN -KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo, - IN PCHAR FileName, - IN ULONG LineNumber OPTIONAL, - IN PCHAR FuncName OPTIONAL, - OUT PVOID *Address); - /* other functions */ -/*NTSTATUS -KdbSafeReadMemory(PVOID dst, PVOID src, INT size); -NTSTATUS -KdbSafeWriteMemory(PVOID dst, PVOID src, INT size);*/ #define KdbpSafeReadMemory(dst, src, size) MmSafeCopyFromUser(dst, src, size) #define KdbpSafeWriteMemory(dst, src, size) MmSafeCopyToUser(dst, src, size) CHAR @@ -72,6 +61,10 @@ KdbEnableProfiling(); VOID KdbProfileInterrupt(ULONG_PTR Eip); +VOID +KdbModuleLoaded(IN PUNICODE_STRING Name); + + struct KDB_BPINFO { DWORD Addr; DWORD Type; diff --git a/reactos/ntoskrnl/dbg/kdb_keyboard.c b/reactos/ntoskrnl/dbg/kdb_keyboard.c index 11cddefd09e..bc0c6b357d9 100644 --- a/reactos/ntoskrnl/dbg/kdb_keyboard.c +++ b/reactos/ntoskrnl/dbg/kdb_keyboard.c @@ -1,27 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/kdb_keyboard.c - * PURPOSE: Keyboard driver - * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/kdb_keyboard.c + * PURPOSE: Keyboard driver + * + * PROGRAMMERS: Victor Kirhenshtein (sauros@iname.com) + * Jason Filby (jasonfilby@yahoo.com) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/dbg/kdb_serial.c b/reactos/ntoskrnl/dbg/kdb_serial.c index 0c27f1796d0..bd2d8f2f854 100644 --- a/reactos/ntoskrnl/dbg/kdb_serial.c +++ b/reactos/ntoskrnl/dbg/kdb_serial.c @@ -1,30 +1,13 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/kdb_serial.c - * PURPOSE: Serial driver - * PROGRAMMER: Original: - * Victor Kirhenshtein (sauros@iname.com) - * Jason Filby (jasonfilby@yahoo.com) - * Modified: - * arty +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/kdb_serial.c + * PURPOSE: Serial driver + * + * PROGRAMMERS: Victor Kirhenshtein (sauros@iname.com) + * Jason Filby (jasonfilby@yahoo.com) + * arty */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/dbg/kdb_stabs.c b/reactos/ntoskrnl/dbg/kdb_stabs.c deleted file mode 100644 index ca3952386db..00000000000 --- a/reactos/ntoskrnl/dbg/kdb_stabs.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/kdb_stabs.c - * PURPOSE: Stabs functions... - * PROGRAMMER: Gregor Anich (blight@blight.eu.org) - * REVISION HISTORY: - * 2004/06/27: Created - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -#include "kdb.h" -#include "kdb_stabs.h" - - -/*! \brief Find a stab entry... - * - * Looks through the stab for an entry which matches the specified criteria. - * - * \param SymbolInfo Pointer to the symbol info. - * \param Type Type of stab entry to look for. - * \param RelativeAddress Relative address of stab to look for. - * \param StartEntry Starting stab entry. - * - * \returns Pointer to a STAB_ENTRY - * \retval NULL No entry found. - */ -PSTAB_ENTRY -KdbpStabFindEntry(IN PIMAGE_SYMBOL_INFO SymbolInfo, - IN CHAR Type, - IN PVOID RelativeAddress OPTIONAL, - IN PSTAB_ENTRY StartEntry OPTIONAL) -{ - PSTAB_ENTRY StabEntry, BestStabEntry = NULL; - PVOID StabsEnd; - ULONG_PTR AddrFound = 0; - - StabEntry = SymbolInfo->SymbolsBase; - StabsEnd = (PVOID)((ULONG_PTR)SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength); - if (StartEntry != NULL) - { - ASSERT((ULONG_PTR)StartEntry >= (ULONG_PTR)StabEntry); - if ((ULONG_PTR)StartEntry >= (ULONG_PTR)StabsEnd) - return NULL; - StabEntry = StartEntry; - } - - if ( RelativeAddress != NULL ) - { - for (; (ULONG_PTR)StabEntry < (ULONG_PTR)StabsEnd; StabEntry++) - { - ULONG_PTR SymbolRelativeAddress; - - if (StabEntry->n_type != Type) - continue; - - if (RelativeAddress != NULL) - { - if (StabEntry->n_value >= SymbolInfo->ImageSize) - continue; - - SymbolRelativeAddress = StabEntry->n_value; - if ((SymbolRelativeAddress <= (ULONG_PTR)RelativeAddress) && - (SymbolRelativeAddress > AddrFound)) - { - AddrFound = SymbolRelativeAddress; - BestStabEntry = StabEntry; - } - } - } - } - else - BestStabEntry = StabEntry; - - if (BestStabEntry == NULL) - { - DPRINT("StabEntry not found!\n"); - } - else - { - DPRINT("StabEntry found!\n"); - } - - return BestStabEntry; -} diff --git a/reactos/ntoskrnl/dbg/kdb_stabs.h b/reactos/ntoskrnl/dbg/kdb_stabs.h deleted file mode 100644 index 00e4c087335..00000000000 --- a/reactos/ntoskrnl/dbg/kdb_stabs.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef __KDB_STABS_H__ -#define __KDB_STABS_H__ - -typedef struct _STAB_ENTRY { - unsigned long n_strx; /* index into string table of name */ - unsigned char n_type; /* type of symbol */ - unsigned char n_other; /* misc info (usually empty) */ - unsigned short n_desc; /* description field */ - unsigned long n_value; /* value of symbol */ -} STAB_ENTRY, *PSTAB_ENTRY; - -/* - * String - Function name with type information - * Desc - Line number - * Value - Absolute virtual address - */ -#define N_FUN 0x24 - -/* - * Desc - Line number - * Value - Relative virtual address - */ -#define N_SLINE 0x44 - -/* - * String - First ending with a '/' is the compillation directory (CD) - * Not ending with a '/' is a source file relative to CD - */ -#define N_SO 0x64 - -/* - * String - Variable name with type information - * Value - Register - */ -#define N_RSYM 0x40 - -/* - * String - Variable name with type information - * Value - Offset of variable within local variables (from %ebp) - */ -#define N_LSYM 0x80 - -#define N_SOL 0x84 - - -#define N_PSYM 0xa0 - -/* - * Value - Start address of code block - */ -#define N_LBRAC 0xc0 - -/* - * Value - End address of code block - */ -#define N_RBRAC 0xe0 - - -/* - * Functions - */ - -PSTAB_ENTRY -KdbpStabFindEntry(IN PIMAGE_SYMBOL_INFO SymbolInfo, - IN CHAR Type, - IN PVOID RelativeAddress OPTIONAL, - IN PSTAB_ENTRY StartEntry OPTIONAL); - -#endif /* __KDB_STABS_H__ */ diff --git a/reactos/ntoskrnl/dbg/kdb_symbols.c b/reactos/ntoskrnl/dbg/kdb_symbols.c index 5da9cbe3b6e..618711e6be0 100644 --- a/reactos/ntoskrnl/dbg/kdb_symbols.c +++ b/reactos/ntoskrnl/dbg/kdb_symbols.c @@ -1,28 +1,10 @@ -/* - * ReactOS kernel - * Copyright (C) 1998-2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/kdb_symbols.c - * PURPOSE: Getting symbol information... - * PROGRAMMER: David Welch (welch@cwcom.net), ... - * REVISION HISTORY: - * ??/??/??: Created +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/kdb_symbols.c + * PURPOSE: Getting symbol information... + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -41,34 +23,24 @@ #include #include #include +#include #define NDEBUG #include #include "kdb.h" -#include "kdb_stabs.h" /* GLOBALS ******************************************************************/ -typedef struct _SYMBOLFILE_HEADER { - ULONG StabsOffset; - ULONG StabsLength; - ULONG StabstrOffset; - ULONG StabstrLength; -} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; +#define TAG_KDBS TAG('K', 'D', 'B', 'S') typedef struct _IMAGE_SYMBOL_INFO_CACHE { LIST_ENTRY ListEntry; ULONG RefCount; UNICODE_STRING FileName; - PVOID FileBuffer; - PVOID SymbolsBase; - ULONG SymbolsLength; - PVOID SymbolStringsBase; - ULONG SymbolStringsLength; + PROSSYM_INFO RosSymInfo; } IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE; - static LIST_ENTRY SymbolFileListHead; static KSPIN_LOCK SymbolFileListLock; @@ -120,7 +92,7 @@ KdbpSymFindUserModule(IN PVOID Address OPTIONAL, current = CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList); if ((Address != NULL && (Address >= (PVOID)current->BaseAddress && - Address < (PVOID)((char *)current->BaseAddress + current->SizeOfImage))) || + Address < (PVOID)((char *)current->BaseAddress + current->ResidentSize))) || (Name != NULL && _wcsicmp(current->BaseDllName.Buffer, Name) == 0) || (Index >= 0 && Count++ == Index)) { @@ -130,8 +102,8 @@ KdbpSymFindUserModule(IN PVOID Address OPTIONAL, wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length); pInfo->Name[Length] = L'\0'; pInfo->Base = (ULONG_PTR)current->BaseAddress; - pInfo->Size = current->SizeOfImage; - pInfo->SymbolInfo = ¤t->SymbolInfo; + pInfo->Size = current->ResidentSize; + pInfo->RosSymInfo = current->RosSymInfo; return TRUE; } current_entry = current_entry->Flink; @@ -173,7 +145,7 @@ KdbpSymFindModule(IN PVOID Address OPTIONAL, pInfo->Name[255] = L'\0'; pInfo->Base = (ULONG_PTR)current->Base; pInfo->Size = current->Length; - pInfo->SymbolInfo = ¤t->SymbolInfo; + pInfo->RosSymInfo = current->RosSymInfo; return TRUE; } current_entry = current_entry->Flink; @@ -264,7 +236,7 @@ KdbSymPrintAddress(IN PVOID Address) return FALSE; RelativeAddress = (ULONG_PTR) Address - Info.Base; - Status = KdbSymGetAddressInformation(Info.SymbolInfo, + Status = KdbSymGetAddressInformation(Info.RosSymInfo, RelativeAddress, &LineNumber, FileName, @@ -286,7 +258,7 @@ KdbSymPrintAddress(IN PVOID Address) /*! \brief Get information for an address (source file, line number, * function name) * - * \param SymbolInfo Pointer to IMAGE_SYMBOL_INFO. + * \param SymbolInfo Pointer to ROSSYM_INFO. * \param RelativeAddress Relative address to look up. * \param LineNumber Pointer to an ULONG which is filled with the line * number (can be NULL) @@ -300,223 +272,26 @@ KdbSymPrintAddress(IN PVOID Address) * \retval STATUS_UNSUCCESSFUL None of the requested information was found. */ NTSTATUS -KdbSymGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo, +KdbSymGetAddressInformation(IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress, OUT PULONG LineNumber OPTIONAL, OUT PCH FileName OPTIONAL, OUT PCH FunctionName OPTIONAL) { - PSTAB_ENTRY FunctionEntry = NULL, FileEntry = NULL, LineEntry = NULL; - - DPRINT("RelativeAddress = 0x%08x\n", RelativeAddress); - - if (SymbolInfo->SymbolsBase == NULL || SymbolInfo->SymbolsLength == 0 || - SymbolInfo->SymbolStringsBase == NULL || SymbolInfo->SymbolStringsLength == 0) + if (NULL == RosSymInfo) { return STATUS_UNSUCCESSFUL; } -#ifdef PEDANTIC_STABS - if (RelativeAddress >= SymbolInfo->ImageSize) + if (! RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber, + FileName, FunctionName)) { - DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n", - RelativeAddress, SymbolInfo->ImageSize); return STATUS_UNSUCCESSFUL; } -#endif - - ASSERT(LineNumber || FileName || FunctionName); - - if (LineNumber != NULL || FunctionName != NULL) - { - /* find stab entry for function */ - FunctionEntry = KdbpStabFindEntry(SymbolInfo, N_FUN, (PVOID)RelativeAddress, NULL); - if (FunctionEntry == NULL) - { - DPRINT("No function stab entry found. RelativeAddress %p\n", RelativeAddress); - } - - if (LineNumber != NULL && FunctionEntry != NULL) - { - /* find stab entry for line number */ - ULONG_PTR FunctionRelativeAddress = RelativeAddress - FunctionEntry->n_value; - ULONG_PTR AddrFound = 0; - PSTAB_ENTRY NextLineEntry; - - LineEntry = NextLineEntry = FunctionEntry; - while (NextLineEntry != NULL) - { - NextLineEntry++; - if ((ULONG_PTR)NextLineEntry >= ((ULONG_PTR)SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength)) - break; - if (NextLineEntry->n_type == N_FUN) - break; - if (NextLineEntry->n_type != N_SLINE) - continue; - - if ( NextLineEntry->n_value <= FunctionRelativeAddress - && NextLineEntry->n_value >= AddrFound ) - { - AddrFound = NextLineEntry->n_value; - LineEntry = NextLineEntry; - } - } - } - } - - if (FileName != NULL) - { - /* find stab entry for file name */ - PCHAR p; - INT Length; - - FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, NULL); - if (FileEntry != NULL) - { - p = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx; - Length = strlen(p); - if (p[Length - 1] == '/' || p[Length - 1] == '\\') /* source dir */ - FileEntry = KdbpStabFindEntry(SymbolInfo, N_SO, (PVOID)RelativeAddress, FileEntry + 1); - } - if (FileEntry == NULL) - { - DPRINT("No filename stab entry found. RelativeAddress %p\n", RelativeAddress); - } - } - - if (((LineNumber != NULL && LineEntry == NULL) || LineNumber == NULL) && - ((FileName != NULL && FileEntry == NULL) || FileName == NULL) && - ((FunctionName != NULL && FunctionEntry == NULL) || FunctionName == NULL)) - { - DPRINT("None of the requested information was found!\n"); - return STATUS_UNSUCCESSFUL; - } - - if (LineNumber != NULL) - { - *LineNumber = 0; - if (LineEntry != NULL) - *LineNumber = LineEntry->n_desc; - } - if (FileName != NULL) - { - PCHAR Name = ""; - if (FileEntry != NULL) - { - Name = (PCHAR)SymbolInfo->SymbolStringsBase + FileEntry->n_strx; - } - strcpy(FileName, Name); - } - if (FunctionName != NULL) - { - PCHAR Name = "", p; - if (FunctionEntry != NULL) - Name = (PCHAR)SymbolInfo->SymbolStringsBase + FunctionEntry->n_strx; - strcpy(FunctionName, Name); - if ((p = strchr(FunctionName, ':')) != NULL) /* remove extra info from function name */ - *p = '\0'; - } return STATUS_SUCCESS; } - -/*! \brief Get absolute source-line number or function address - * - * \param SymbolInfo IMAGE_SYMBOL_INFO of the module containing source file/line number. - * \param FileName Source filename. - * \param LineNumber Line number in source file. - * \param FuncName Function name. - * \param Address Filled with the address on success. - * - * \retval TRUE Success. - * \retval FALSE Failure. - */ -BOOLEAN -KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo, - IN PCHAR FileName, - IN ULONG LineNumber OPTIONAL, - IN PCHAR FuncName OPTIONAL, - OUT PVOID *Address) -{ - PSTAB_ENTRY Entry, FunctionEntry = NULL; - PCHAR SymbolName, p; - CHAR Buffer[512] = ""; - INT Length, FileNameLength, FuncNameLength = 0; - - if (FuncName == NULL && LineNumber < 1) - return FALSE; - - FileNameLength = strlen(FileName); - FuncNameLength = strlen(FuncName); - for (Entry = SymbolInfo->SymbolsBase; - (ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength); - Entry++) - { - if (Entry->n_type != N_SO) - continue; - - SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx; - Length = strlen(SymbolName); - if (SymbolName[Length - 1] == '/' || - SymbolName[Length - 1] == '\\') - { - strncpy(Buffer, SymbolName, sizeof (Buffer) - 1); - Buffer[sizeof (Buffer) - 1] = '\0'; - continue; - } - strncat(Buffer, SymbolName, sizeof (Buffer) - 1); - Buffer[sizeof (Buffer) - 1] = '\0'; - - Length = strlen(Buffer); - if (strcmp(Buffer + Length - FileNameLength, FileName) != 0) - continue; - - Entry++; - for (;(ULONG_PTR)Entry < (ULONG_PTR)(SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength); - Entry++) - { - if (Entry->n_type == N_FUN) - FunctionEntry = Entry; - else if (Entry->n_type == N_SO) - break; - else if (Entry->n_type != N_SLINE || LineNumber < 1) - continue; - - if (LineNumber > 0 && Entry->n_desc != LineNumber) - continue; - else /* if (FunctionName != NULL) */ - { - SymbolName = (PCHAR)SymbolInfo->SymbolStringsBase + Entry->n_strx; - p = strchr(SymbolName, ':'); - if (p == NULL) - return FALSE; - Length = p - SymbolName; - if (Length != FuncNameLength) - continue; - if (strncmp(FuncName, SymbolName, Length) != 0) - continue; - } - - /* found */ - if (Entry->n_type == N_FUN) - { - *Address = (PVOID)Entry->n_value; /* FIXME: relocate address */ - return TRUE; - } - - if (FunctionEntry == NULL) - return FALSE; - - *Address = (PVOID)((ULONG_PTR)Entry->n_value + FunctionEntry->n_value); /* FIXME: relocate address */ - return TRUE; - } - break; - } - - return FALSE; -} - /*! \brief Find cached symbol file. * * Looks through the list of cached symbol files and tries to find an already @@ -529,7 +304,7 @@ KdbpSymGetSourceAddress(IN PIMAGE_SYMBOL_INFO SymbolInfo, * * \sa KdbpSymAddCachedFile */ -STATIC PIMAGE_SYMBOL_INFO_CACHE +STATIC PROSSYM_INFO KdbpSymFindCachedFile(IN PUNICODE_STRING FileName) { PIMAGE_SYMBOL_INFO_CACHE Current; @@ -548,9 +323,10 @@ KdbpSymFindCachedFile(IN PUNICODE_STRING FileName) DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName); if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE)) { + Current->RefCount++; KeReleaseSpinLock(&SymbolFileListLock, Irql); DPRINT("Found cached file!\n"); - return Current; + return Current->RosSymInfo; } CurrentEntry = CurrentEntry->Flink; @@ -565,33 +341,28 @@ KdbpSymFindCachedFile(IN PUNICODE_STRING FileName) /*! \brief Add a symbol file to the cache. * * \param FileName Filename of the symbol file. - * \param SymbolInfo Pointer to the symbol info. + * \param RosSymInfo Pointer to the symbol info. * * \sa KdbpSymRemoveCachedFile */ STATIC VOID KdbpSymAddCachedFile(IN PUNICODE_STRING FileName, - IN PIMAGE_SYMBOL_INFO SymbolInfo) + IN PROSSYM_INFO RosSymInfo) { PIMAGE_SYMBOL_INFO_CACHE CacheEntry; - DPRINT("Adding symbol file: FileBuffer = %p, ImageBase = %p\n", - SymbolInfo->FileBuffer, SymbolInfo->ImageBase); + DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo); /* allocate entry */ - CacheEntry = ExAllocatePool(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE)); + CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS); ASSERT(CacheEntry); RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE)); /* fill entry */ - RtlCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer); + RtlpCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer, PagedPool); ASSERT(CacheEntry->FileName.Buffer); CacheEntry->RefCount = 1; - CacheEntry->FileBuffer = SymbolInfo->FileBuffer; - CacheEntry->SymbolsBase = SymbolInfo->SymbolsBase; - CacheEntry->SymbolsLength = SymbolInfo->SymbolsLength; - CacheEntry->SymbolStringsBase = SymbolInfo->SymbolStringsBase; - CacheEntry->SymbolStringsLength = SymbolInfo->SymbolStringsLength; + CacheEntry->RosSymInfo = RosSymInfo; InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */ } @@ -601,12 +372,12 @@ KdbpSymAddCachedFile(IN PUNICODE_STRING FileName, * it's reference count. If the refcount is 0 after decreasing it the cache * entry will be removed from the list and freed. * - * \param SymbolInfo Pointer to the symbol info. + * \param RosSymInfo Pointer to the symbol info. * * \sa KdbpSymAddCachedFile */ STATIC VOID -KdbpSymRemoveCachedFile(IN PIMAGE_SYMBOL_INFO SymbolInfo) +KdbpSymRemoveCachedFile(IN PROSSYM_INFO RosSymInfo) { PIMAGE_SYMBOL_INFO_CACHE Current; PLIST_ENTRY CurrentEntry; @@ -619,14 +390,14 @@ KdbpSymRemoveCachedFile(IN PIMAGE_SYMBOL_INFO SymbolInfo) { Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); - if (Current->FileBuffer == SymbolInfo->FileBuffer) /* found */ + if (Current->RosSymInfo == RosSymInfo) /* found */ { ASSERT(Current->RefCount > 0); Current->RefCount--; if (Current->RefCount < 1) { RemoveEntryList(&Current->ListEntry); - ExFreePool(Current->FileBuffer); + RosSymDelete(Current->RosSymInfo); ExFreePool(Current); } KeReleaseSpinLock(&SymbolFileListLock, Irql); @@ -637,129 +408,64 @@ KdbpSymRemoveCachedFile(IN PIMAGE_SYMBOL_INFO SymbolInfo) } KeReleaseSpinLock(&SymbolFileListLock, Irql); - DPRINT1("Warning: Removing unknown symbol file: FileBuffer = %p, ImageBase = %p\n", - SymbolInfo->FileBuffer, SymbolInfo->ImageBase); + DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo); } /*! \brief Loads a symbol file. * * \param FileName Filename of the symbol file to load. - * \param SymbolInfo Pointer to a SymbolInfo which gets filled. + * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled. * * \sa KdbpSymUnloadModuleSymbols */ STATIC VOID KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName, - OUT PIMAGE_SYMBOL_INFO SymbolInfo) + OUT PROSSYM_INFO *RosSymInfo) { - FILE_STANDARD_INFORMATION FileStdInfo; OBJECT_ATTRIBUTES ObjectAttributes; - WCHAR TmpFileName[MAX_PATH]; - UNICODE_STRING SymFileName; - LPWSTR Start, Ext; HANDLE FileHandle; - PVOID FileBuffer; NTSTATUS Status; - ULONG Length; IO_STATUS_BLOCK IoStatusBlock; - PSYMBOLFILE_HEADER SymbolFileHeader; - PIMAGE_SYMBOL_INFO_CACHE CachedSymbolFile; - /* Get the path to the symbol store */ - wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\"); - - /* Get the symbol filename from the module name */ - Start = wcsrchr(FileName->Buffer, L'\\'); - if (Start == NULL) - Start = FileName->Buffer; - else - Start++; - - Ext = wcsrchr(FileName->Buffer, L'.'); - if (Ext != NULL) - Length = Ext - Start; - else - Length = wcslen(Start); - - wcsncat(TmpFileName, Start, Length); - wcscat(TmpFileName, L".sym"); - RtlInitUnicodeString(&SymFileName, TmpFileName); +#ifdef KDBG + /* Allow KDB to break on module load */ + KdbModuleLoaded(FileName); +#endif /* Try to find cached (already loaded) symbol file */ - CachedSymbolFile = KdbpSymFindCachedFile(&SymFileName); - if (CachedSymbolFile != NULL) + *RosSymInfo = KdbpSymFindCachedFile(FileName); + if (*RosSymInfo != NULL) { - DPRINT("Found cached symbol file %wZ\n", &SymFileName); - CachedSymbolFile->RefCount++; - SymbolInfo->FileBuffer = CachedSymbolFile->FileBuffer; - SymbolInfo->SymbolsBase = CachedSymbolFile->SymbolsBase; - SymbolInfo->SymbolsLength = CachedSymbolFile->SymbolsLength; - SymbolInfo->SymbolStringsBase = CachedSymbolFile->SymbolStringsBase; - SymbolInfo->SymbolStringsLength = CachedSymbolFile->SymbolStringsLength; + DPRINT("Found cached symbol file %wZ\n", FileName); return; } /* Open the file */ InitializeObjectAttributes(&ObjectAttributes, - &SymFileName, + FileName, 0, NULL, NULL); - DPRINT("Attempting to open symbols: %wZ\n", &SymFileName); + DPRINT("Attempting to open image: %wZ\n", FileName); Status = ZwOpenFile(&FileHandle, - FILE_ALL_ACCESS, + FILE_READ_ACCESS, &ObjectAttributes, &IoStatusBlock, - 0, + FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING); if (!NT_SUCCESS(Status)) { - DPRINT("Could not open symbol file: %wZ\n", &SymFileName); + DPRINT("Could not open image file: %wZ\n", &FileName); return; } - DPRINT("Loading symbols from %wZ...\n", &SymFileName); + DPRINT("Loading symbols from %wZ...\n", FileName); - /* Get the size of the file */ - Status = ZwQueryInformationFile(FileHandle, - &IoStatusBlock, - &FileStdInfo, - sizeof(FileStdInfo), - FileStandardInformation); - if (!NT_SUCCESS(Status)) + if (! RosSymCreateFromFile(&FileHandle, RosSymInfo)) { - DPRINT("Could not get file size\n"); - ZwClose(FileHandle); - return; - } - - DPRINT("Symbol file is %08x bytes\n", FileStdInfo.EndOfFile.u.LowPart); - - /* Allocate nonpageable memory for symbol file */ - FileBuffer = ExAllocatePool(NonPagedPool, - FileStdInfo.AllocationSize.u.LowPart); - - if (FileBuffer == NULL) - { - DPRINT("Could not allocate memory for symbol file\n"); - ZwClose(FileHandle); - return; - } - - /* Load file into memory chunk */ - Status = ZwReadFile(FileHandle, - 0, 0, 0, - &IoStatusBlock, - FileBuffer, - FileStdInfo.EndOfFile.u.LowPart, - 0, 0); - if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) - { - DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status); - ExFreePool(FileBuffer); - ZwClose(FileHandle); + DPRINT("Failed to load symbols from %wZ\n", FileName); return; } @@ -767,41 +473,26 @@ KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName, DPRINT("Symbols loaded.\n"); - SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer; - SymbolInfo->FileBuffer = FileBuffer; - SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset; - SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength; - SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset; - SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength; - /* add file to cache */ - KdbpSymAddCachedFile(&SymFileName, SymbolInfo); + KdbpSymAddCachedFile(FileName, *RosSymInfo); - DPRINT("Installed stabs: %wZ (%08x-%08x,%08x)\n", - FileName, - SymbolInfo->SymbolsBase, - SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase, - SymbolInfo->SymbolStringsBase); + DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo); } /*! \brief Unloads symbol info. * - * \param SymbolInfo Pointer to the symbol info to unload. + * \param RosSymInfo Pointer to the symbol info to unload. * * \sa KdbpSymLoadModuleSymbols */ STATIC VOID -KdbpSymUnloadModuleSymbols(IN PIMAGE_SYMBOL_INFO SymbolInfo) +KdbpSymUnloadModuleSymbols(IN PROSSYM_INFO RosSymInfo) { DPRINT("Unloading symbols\n"); - if (SymbolInfo != NULL && SymbolInfo->FileBuffer != NULL && - (PVOID)SymbolInfo->ImageBase != NULL) + if (RosSymInfo != NULL) { - KdbpSymRemoveCachedFile(SymbolInfo); - SymbolInfo->FileBuffer = NULL; - SymbolInfo->SymbolsBase = NULL; - SymbolInfo->SymbolsLength = 0; + KdbpSymRemoveCachedFile(RosSymInfo); } } @@ -812,13 +503,27 @@ KdbpSymUnloadModuleSymbols(IN PIMAGE_SYMBOL_INFO SymbolInfo) VOID KdbSymLoadUserModuleSymbols(IN PLDR_MODULE LdrModule) { + static WCHAR Prefix[] = L"\\??\\"; + UNICODE_STRING KernelName; DPRINT("LdrModule %p\n", LdrModule); - RtlZeroMemory(&LdrModule->SymbolInfo, sizeof (LdrModule->SymbolInfo)); - LdrModule->SymbolInfo.ImageBase = (ULONG_PTR)LdrModule->BaseAddress; - LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage; + KernelName.MaximumLength = sizeof(Prefix) + LdrModule->FullDllName.Length; + KernelName.Length = KernelName.MaximumLength - sizeof(WCHAR); + KernelName.Buffer = ExAllocatePoolWithTag(PagedPool, KernelName.MaximumLength, TAG_KDBS); + if (NULL == KernelName.Buffer) + { + return; + } + memcpy(KernelName.Buffer, Prefix, sizeof(Prefix) - sizeof(WCHAR)); + memcpy(KernelName.Buffer + sizeof(Prefix) / sizeof(WCHAR) - 1, LdrModule->FullDllName.Buffer, + LdrModule->FullDllName.Length); + KernelName.Buffer[KernelName.Length / sizeof(WCHAR)] = L'\0'; - KdbpSymLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo); + LdrModule->RosSymInfo = NULL; + + KdbpSymLoadModuleSymbols(&KernelName, &LdrModule->RosSymInfo); + + ExFreePool(KernelName.Buffer); } /*! \brief Frees all symbols loaded for a process. @@ -830,7 +535,6 @@ KdbSymFreeProcessSymbols(IN PEPROCESS Process) { PLIST_ENTRY CurrentEntry; PLDR_MODULE Current; - PIMAGE_SYMBOL_INFO SymbolInfo; PEPROCESS CurrentProcess; PPEB Peb; @@ -849,8 +553,7 @@ KdbSymFreeProcessSymbols(IN PEPROCESS Process) { Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE, InLoadOrderModuleList); - SymbolInfo = &Current->SymbolInfo; - KdbpSymUnloadModuleSymbols(SymbolInfo); + KdbpSymUnloadModuleSymbols(Current->RosSymInfo); CurrentEntry = CurrentEntry->Flink; } @@ -872,11 +575,9 @@ KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename, /* Load symbols for the image if available */ DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->Base); - RtlZeroMemory(&Module->TextSection->SymbolInfo, sizeof (Module->TextSection->SymbolInfo)); - Module->TextSection->SymbolInfo.ImageBase = Module->TextSection->Base; - Module->TextSection->SymbolInfo.ImageSize = Module->TextSection->Length; + Module->TextSection->RosSymInfo = NULL; - KdbpSymLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo); + KdbpSymLoadModuleSymbols(Filename, &Module->TextSection->RosSymInfo); } /*! \brief Unloads symbol info for a driver. @@ -887,7 +588,8 @@ VOID KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject) { /* Unload symbols for module if available */ - KdbpSymUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo); + KdbpSymUnloadModuleSymbols(ModuleObject->TextSection->RosSymInfo); + ModuleObject->TextSection->RosSymInfo = NULL; } /*! \brief Called when a symbol file is loaded by the loader? @@ -897,76 +599,83 @@ KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject) * module. * Used to load ntoskrnl and hal symbols before the SystemRoot is available to us. * - * \param ModuleLoadBase Base address of the loaded symbol file. - * \param FileName Filename of the symbol file. - * \param Length Length of the loaded symbol file/module. + * \param FileName Filename for which the symbols are loaded. */ VOID -KdbSymProcessSymbolFile(IN PVOID ModuleLoadBase, - IN PCHAR FileName, - IN ULONG Length) +KdbSymProcessBootSymbols(IN PCHAR FileName) { PMODULE_OBJECT ModuleObject; - UNICODE_STRING ModuleName; - CHAR TmpBaseName[MAX_PATH]; - CHAR TmpFileName[MAX_PATH]; - PSYMBOLFILE_HEADER SymbolFileHeader; - PIMAGE_SYMBOL_INFO SymbolInfo; + UNICODE_STRING UnicodeString; + PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr; ANSI_STRING AnsiString; - PCHAR Extension; ULONG i; - const char *KnownExtension[] = {".exe", ".sys", ".dll"}; + BOOLEAN IsRaw; - DPRINT("Module %s is a symbol file\n", FileName); + DPRINT("KdbSymProcessBootSymbols(%s)\n", FileName); - strncpy(TmpBaseName, FileName, MAX_PATH-1); - TmpBaseName[MAX_PATH-1] = '\0'; - /* remove the extension '.sym' */ - Extension = strrchr(TmpBaseName, '.'); - if (Extension && 0 == _stricmp(Extension, ".sym")) + if (0 == _stricmp(FileName, "ntoskrnl.sym")) { - *Extension = 0; + RtlInitAnsiString(&AnsiString, "ntoskrnl.exe"); + IsRaw = TRUE; } - - DPRINT("base: %s (Length %d)\n", TmpBaseName, Length); - - for (i = 0; i < sizeof(KnownExtension) / sizeof(*KnownExtension); i++) + else { - strcpy(TmpFileName, TmpBaseName); - strcat(TmpFileName, KnownExtension[i]); - RtlInitAnsiString(&AnsiString, TmpFileName); - - RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE); - ModuleObject = LdrGetModuleObject(&ModuleName); - RtlFreeUnicodeString(&ModuleName); - if (ModuleObject) - { - break; - } + RtlInitAnsiString(&AnsiString, FileName); + IsRaw = FALSE; } - + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + ModuleObject = LdrGetModuleObject(&UnicodeString); + RtlFreeUnicodeString(&UnicodeString); + if (ModuleObject != NULL) - { - SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo; - if (SymbolInfo->FileBuffer != NULL) + { + for (i = 0; i < KeLoaderBlock.ModsCount; i++) + { + if (0 == _stricmp(FileName, (PCHAR)KeLoaderModules[i].String)) + { + break; + } + } + if (i < KeLoaderBlock.ModsCount) + { + KeLoaderModules[i].Reserved = 1; + if (ModuleObject->TextSection->RosSymInfo != NULL) { - KdbpSymRemoveCachedFile(SymbolInfo); + KdbpSymRemoveCachedFile(ModuleObject->TextSection->RosSymInfo); } - SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase; - SymbolInfo->FileBuffer = ModuleLoadBase; - SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset; - SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength; - SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset; - SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength; - DPRINT("Installed stabs: %s@%08x-%08x (%08x-%08x,%08x)\n", + if (IsRaw) + { + if (! RosSymCreateFromRaw((PVOID) KeLoaderModules[i].ModStart, + KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart, + &ModuleObject->TextSection->RosSymInfo)) + { + return; + } + } + else + { + if (! RosSymCreateFromMem((PVOID) KeLoaderModules[i].ModStart, + KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart, + &ModuleObject->TextSection->RosSymInfo)) + { + return; + } + } + + /* add file to cache */ + RtlInitAnsiString(&AnsiString, FileName); + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + KdbpSymAddCachedFile(&UnicodeString, ModuleObject->TextSection->RosSymInfo); + RtlFreeUnicodeString(&UnicodeString); + + DPRINT("Installed symbols: %s@%08x-%08x %p\n", FileName, ModuleObject->Base, ModuleObject->Length + ModuleObject->Base, - SymbolInfo->SymbolsBase, - SymbolInfo->SymbolsLength + SymbolInfo->SymbolsBase, - SymbolInfo->SymbolStringsBase); - } + ModuleObject->TextSection->RosSymInfo); + } + } } /*! \brief Initializes the KDB symbols implementation. @@ -978,16 +687,13 @@ VOID KdbSymInit(IN PMODULE_TEXT_SECTION NtoskrnlTextSection, IN PMODULE_TEXT_SECTION LdrHalTextSection) { - RtlZeroMemory(&NtoskrnlTextSection->SymbolInfo, sizeof(NtoskrnlTextSection->SymbolInfo)); - NtoskrnlTextSection->SymbolInfo.ImageBase = NtoskrnlTextSection->OptionalHeader->ImageBase; - NtoskrnlTextSection->SymbolInfo.ImageSize = NtoskrnlTextSection->Length; - - RtlZeroMemory(&LdrHalTextSection->SymbolInfo, sizeof(LdrHalTextSection->SymbolInfo)); - LdrHalTextSection->SymbolInfo.ImageBase = LdrHalTextSection->OptionalHeader->ImageBase; - LdrHalTextSection->SymbolInfo.ImageSize = LdrHalTextSection->Length; + NtoskrnlTextSection->RosSymInfo = NULL; + LdrHalTextSection->RosSymInfo = NULL; InitializeListHead(&SymbolFileListHead); KeInitializeSpinLock(&SymbolFileListLock); + + RosSymInitKernelMode(); } /* EOF */ diff --git a/reactos/ntoskrnl/dbg/print.c b/reactos/ntoskrnl/dbg/print.c index f2ad9b82c77..cc0649d12fe 100644 --- a/reactos/ntoskrnl/dbg/print.c +++ b/reactos/ntoskrnl/dbg/print.c @@ -1,31 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/print.c - * PURPOSE: Debug output - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * PORTABILITY: Unchecked - * UPDATE HISTORY: - * 14/10/99: Created + * PURPOSE: Debug output + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/dbg/profile.c b/reactos/ntoskrnl/dbg/profile.c index df943fe65ce..3b2350541b5 100755 --- a/reactos/ntoskrnl/dbg/profile.c +++ b/reactos/ntoskrnl/dbg/profile.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998-2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ - * + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/profile.c * PURPOSE: Kernel profiling - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * Created 12/01/2003 + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ @@ -154,7 +136,6 @@ KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer) extern LIST_ENTRY ModuleTextListHead; ULONG_PTR RelativeAddress; NTSTATUS Status; - ULONG LineNumber; CHAR FileName[256]; CHAR FunctionName[256]; @@ -170,14 +151,14 @@ KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer) address < (PVOID)(current->Base + current->Length)) { RelativeAddress = (ULONG_PTR) address - current->Base; - Status = KdbSymGetAddressInformation(¤t->SymbolInfo, + Status = KdbSymGetAddressInformation(current->RosSymInfo, RelativeAddress, - &LineNumber, + NULL, FileName, FunctionName); if (NT_SUCCESS(Status)) { - sprintf(NameBuffer, "%s (%s)", FileName, FunctionName); + sprintf(NameBuffer, "%s (%s)", FunctionName, FileName); return(TRUE); } return(TRUE); @@ -249,7 +230,7 @@ KdbProfilerWriteSampleGroups(PLIST_ENTRY SamplesListHead) PLIST_ENTRY Largest; KdbProfilerWriteString("\r\n\r\n"); - KdbProfilerWriteString("Count Symbol\n"); + KdbProfilerWriteString("Count Symbol\r\n"); KdbProfilerWriteString("--------------------------------------------------\r\n"); current = SamplesListHead->Flink; @@ -304,7 +285,7 @@ KdbProfilerAnalyzeSamples() ULONG Index; ULONG_PTR Address; - if (!ExInitializeHashTable(&Hashtable, 17, KdbProfilerKeyCompare, TRUE)) + if (!ExInitializeHashTable(&Hashtable, 12, KdbProfilerKeyCompare, TRUE)) { DPRINT1("ExInitializeHashTable() failed."); KEBUGCHECK(0); @@ -371,14 +352,14 @@ KdbProfilerThreadMain(PVOID Context) KeWaitForSingleObject(&KdbProfilerLock, Executive, KernelMode, FALSE, NULL); - KdbSuspendProfiling(); + KdbSuspendProfiling(); KdbProfilerAnalyzeSamples(); - KdbResumeProfiling(); + KdbResumeProfiling(); - KeReleaseMutex(&KdbProfilerLock, FALSE); - } + KeReleaseMutex(&KdbProfilerLock, FALSE); + } } VOID @@ -447,6 +428,16 @@ KdbEnableProfiling() DPRINT1("Failed to create profiler log file\n"); return; } + KeInitializeMutex(&KdbProfilerLock, 0); + + KdbProfileDatabase = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE)); + ASSERT(KdbProfileDatabase); + InitializeListHead(&KdbProfileDatabase->ListHead); + KeInitializeDpc(&KdbProfilerCollectorDpc, KdbProfilerCollectorDpcRoutine, NULL); + + /* Initialize our periodic timer and its associated DPC object. When the timer + expires, the KdbProfilerSessionEndDpc deferred procedure call (DPC) is queued */ + KeInitializeTimerEx(&KdbProfilerTimer, SynchronizationTimer); Status = PsCreateSystemThread(&KdbProfilerThreadHandle, THREAD_ALL_ACCESS, @@ -461,17 +452,6 @@ KdbEnableProfiling() return; } - KeInitializeMutex(&KdbProfilerLock, 0); - - KdbProfileDatabase = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE)); - ASSERT(KdbProfileDatabase); - InitializeListHead(&KdbProfileDatabase->ListHead); - KeInitializeDpc(&KdbProfilerCollectorDpc, KdbProfilerCollectorDpcRoutine, NULL); - - /* Initialize our periodic timer and its associated DPC object. When the timer - expires, the KdbProfilerSessionEndDpc deferred procedure call (DPC) is queued */ - KeInitializeTimerEx(&KdbProfilerTimer, SynchronizationTimer); - /* Start the periodic timer with an initial and periodic relative expiration time of PROFILE_SESSION_LENGTH seconds */ DueTime.QuadPart = -(LONGLONG) PROFILE_SESSION_LENGTH * 1000 * 10000; diff --git a/reactos/ntoskrnl/dbg/rdebug.c b/reactos/ntoskrnl/dbg/rdebug.c index b26a882f509..f9aefe69717 100644 --- a/reactos/ntoskrnl/dbg/rdebug.c +++ b/reactos/ntoskrnl/dbg/rdebug.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/rdebug.c * PURPOSE: Runtime debugging support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 01-05-2001 CSH Created + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/dbg/user.c b/reactos/ntoskrnl/dbg/user.c index 0c03ae27fc1..c4882b12fab 100644 --- a/reactos/ntoskrnl/dbg/user.c +++ b/reactos/ntoskrnl/dbg/user.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/dbg/user.c * PURPOSE: User mode debugging - * PROGRAMMER: David Welch (welch@cwcom.net) - * PORTABILITY: Unchecked + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/ex/btree.c b/reactos/ntoskrnl/ex/btree.c index d626809470e..abefbee15f5 100644 --- a/reactos/ntoskrnl/ex/btree.c +++ b/reactos/ntoskrnl/ex/btree.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998-2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: btree.c + * FILE: ntoskrnl/ex/btree.c * PURPOSE: Binary tree support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 15-03-2002 CSH Created + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ #include diff --git a/reactos/ntoskrnl/ex/callback.c b/reactos/ntoskrnl/ex/callback.c index be6af0d81f7..d6cf2cbe629 100644 --- a/reactos/ntoskrnl/ex/callback.c +++ b/reactos/ntoskrnl/ex/callback.c @@ -1,34 +1,17 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/callback.c * PURPOSE: Executive callbacks - * PROGRAMMER: David Welch (welch@mcmail.com) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) * Alex Ionescu (alex@relsoft.net) - * PORTABILITY: Checked. - * UPDATE HISTORY: - * Added all functions 30/05/04 - * Created 22/05/98 - * NOTE: - * These funtions are not implemented in NT4, but + */ + + +/* + * NOTE: These funtions are not implemented in NT4, but * they are implemented in Win2k. */ @@ -72,8 +55,8 @@ ExpInitializeCallbacks(VOID) ExCallbackObjectType->Tag = CALLBACK_TAG; ExCallbackObjectType->TotalObjects = 0; ExCallbackObjectType->TotalHandles = 0; - ExCallbackObjectType->MaxObjects = 0xFFFFFFFF; - ExCallbackObjectType->MaxHandles = 0xFFFFFFFF; + ExCallbackObjectType->PeakObjects = 0; + ExCallbackObjectType->PeakHandles = 0; ExCallbackObjectType->PagedPoolCharge = 0; ExCallbackObjectType->Dump = NULL; ExCallbackObjectType->Open = NULL; diff --git a/reactos/ntoskrnl/ex/event.c b/reactos/ntoskrnl/ex/event.c new file mode 100644 index 00000000000..352d1af5238 --- /dev/null +++ b/reactos/ntoskrnl/ex/event.c @@ -0,0 +1,535 @@ +/* $Id:$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/event.c + * PURPOSE: Named event support + * + * PROGRAMMERS: Philip Susi and David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED ExEventObjectType = NULL; + +static GENERIC_MAPPING ExpEventMapping = { + STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE, + EVENT_ALL_ACCESS}; + +static const INFORMATION_CLASS_INFO ExEventInfoClass[] = +{ + ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */ +}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtpCreateEvent(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID INIT_FUNCTION +ExpInitializeEventImplementation(VOID) +{ + ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool); + + ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T'); + ExEventObjectType->PeakObjects = 0; + ExEventObjectType->PeakHandles = 0; + ExEventObjectType->TotalObjects = 0; + ExEventObjectType->TotalHandles = 0; + ExEventObjectType->PagedPoolCharge = 0; + ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT); + ExEventObjectType->Mapping = &ExpEventMapping; + ExEventObjectType->Dump = NULL; + ExEventObjectType->Open = NULL; + ExEventObjectType->Close = NULL; + ExEventObjectType->Delete = NULL; + ExEventObjectType->Parse = NULL; + ExEventObjectType->Security = NULL; + ExEventObjectType->QueryName = NULL; + ExEventObjectType->OkayToClose = NULL; + ExEventObjectType->Create = NtpCreateEvent; + ExEventObjectType->DuplicationNotify = NULL; + + ObpCreateTypeObject(ExEventObjectType); +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtClearEvent(IN HANDLE EventHandle) +{ + PKEVENT Event; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + ExGetPreviousMode(), + (PVOID*)&Event, + NULL); + if(NT_SUCCESS(Status)) + { + KeClearEvent(Event); + ObDereferenceObject(Event); + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtCreateEvent(OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN EVENT_TYPE EventType, + IN BOOLEAN InitialState) +{ + KPROCESSOR_MODE PreviousMode; + PKEVENT Event; + HANDLE hEvent; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(EventHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, + ExEventObjectType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(KEVENT), + 0, + 0, + (PVOID*)&Event); + if(NT_SUCCESS(Status)) + { + KeInitializeEvent(Event, + EventType, + InitialState); + + + Status = ObInsertObject((PVOID)Event, + NULL, + DesiredAccess, + 0, + NULL, + &hEvent); + ObDereferenceObject(Event); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *EventHandle = hEvent; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtOpenEvent(OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hEvent; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(EventHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObOpenObjectByName(ObjectAttributes, + ExEventObjectType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hEvent); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *EventHandle = hEvent; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtPulseEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n", + EventHandle, PreviousState); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousState != NULL && PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(PreviousState, + sizeof(LONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + PreviousMode, + (PVOID*)&Event, + NULL); + if(NT_SUCCESS(Status)) + { + LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE); + ObDereferenceObject(Event); + + if(PreviousState != NULL) + { + _SEH_TRY + { + *PreviousState = Prev; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtQueryEvent(IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID EventInformation, + IN ULONG EventInformationLength, + OUT PULONG ReturnLength OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(EventInformationClass, + ExEventInfoClass, + EventInformation, + EventInformationLength, + ReturnLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status); + return Status; + } + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_QUERY_STATE, + ExEventObjectType, + PreviousMode, + (PVOID*)&Event, + NULL); + if(NT_SUCCESS(Status)) + { + switch(EventInformationClass) + { + case EventBasicInformation: + { + PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation; + + _SEH_TRY + { + if (Event->Header.Type == InternalNotificationEvent) + BasicInfo->EventType = NotificationEvent; + else + BasicInfo->EventType = SynchronizationEvent; + BasicInfo->EventState = KeReadStateEvent(Event); + + if(ReturnLength != NULL) + { + *ReturnLength = sizeof(EVENT_BASIC_INFORMATION); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + ObDereferenceObject(Event); + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtResetEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n", + EventHandle, PreviousState); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousState != NULL && PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(PreviousState, + sizeof(LONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + PreviousMode, + (PVOID*)&Event, + NULL); + if(NT_SUCCESS(Status)) + { + LONG Prev = KeResetEvent(Event); + ObDereferenceObject(Event); + + if(PreviousState != NULL) + { + _SEH_TRY + { + *PreviousState = Prev; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtSetEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n", + EventHandle, PreviousState); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousState != NULL && PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(PreviousState, + sizeof(LONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + PreviousMode, + (PVOID*)&Event, + NULL); + if(NT_SUCCESS(Status)) + { + LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE); + ObDereferenceObject(Event); + + if(PreviousState != NULL) + { + _SEH_TRY + { + *PreviousState = Prev; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @unimplemented + */ +NTSTATUS +STDCALL +NtTraceEvent( + IN ULONG TraceHandle, + IN ULONG Flags, + IN ULONG TraceHeaderLength, + IN struct _EVENT_TRACE_HEADER* TraceHeader + ) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + + +/* EOF */ diff --git a/reactos/ntoskrnl/nt/evtpair.c b/reactos/ntoskrnl/ex/evtpair.c similarity index 63% rename from reactos/ntoskrnl/nt/evtpair.c rename to reactos/ntoskrnl/ex/evtpair.c index 131a8191e33..4e3794194c6 100644 --- a/reactos/ntoskrnl/nt/evtpair.c +++ b/reactos/ntoskrnl/ex/evtpair.c @@ -1,16 +1,12 @@ -/* $Id$ +/* $Id: evtpair.c 12779 2005-01-04 04:45:00Z gdalsnes $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/evtpair.c + * FILE: ntoskrnl/ex/evtpair.c * PURPOSE: Support for event pairs - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com) - * to correctly maintain ownership of the dispatcher lock - * between KeSetEvent and KeWaitForSingleObject calls. - * Additionally, implemented the thread-eventpair routines. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Skywing (skywing@valhallalegends.com) */ /* INCLUDES *****************************************************************/ @@ -43,12 +39,12 @@ static KSPIN_LOCK ExThreadEventPairSpinLock; /* FUNCTIONS *****************************************************************/ NTSTATUS STDCALL -NtpCreateEventPair(PVOID ObjectBody, +ExpCreateEventPair(PVOID ObjectBody, PVOID Parent, PWSTR RemainingPath, POBJECT_ATTRIBUTES ObjectAttributes) { - DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n", + DPRINT("ExpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n", ObjectBody, Parent, RemainingPath); if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) @@ -60,14 +56,14 @@ NtpCreateEventPair(PVOID ObjectBody, } VOID INIT_FUNCTION -NtInitializeEventPairImplementation(VOID) +ExpInitializeEventPairImplementation(VOID) { ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - RtlCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair"); + RtlpCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair", NonPagedPool); ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a'); - ExEventPairObjectType->MaxObjects = ULONG_MAX; - ExEventPairObjectType->MaxHandles = ULONG_MAX; + ExEventPairObjectType->PeakObjects = 0; + ExEventPairObjectType->PeakHandles = 0; ExEventPairObjectType->TotalObjects = 0; ExEventPairObjectType->TotalHandles = 0; ExEventPairObjectType->PagedPoolCharge = 0; @@ -81,7 +77,7 @@ NtInitializeEventPairImplementation(VOID) ExEventPairObjectType->Security = NULL; ExEventPairObjectType->QueryName = NULL; ExEventPairObjectType->OkayToClose = NULL; - ExEventPairObjectType->Create = NtpCreateEventPair; + ExEventPairObjectType->Create = ExpCreateEventPair; ExEventPairObjectType->DuplicationNotify = NULL; KeInitializeSpinLock(&ExThreadEventPairSpinLock); @@ -95,39 +91,71 @@ NtCreateEventPair(OUT PHANDLE EventPairHandle, IN POBJECT_ATTRIBUTES ObjectAttributes) { PKEVENT_PAIR EventPair; - NTSTATUS Status; + HANDLE hEventPair; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); - DPRINT("NtCreateEventPair()\n"); - Status = ObCreateObject(ExGetPreviousMode(), + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(EventPairHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, ExEventPairObjectType, ObjectAttributes, - ExGetPreviousMode(), + PreviousMode, NULL, sizeof(KEVENT_PAIR), 0, 0, (PVOID*)&EventPair); - if (!NT_SUCCESS(Status)) + if(NT_SUCCESS(Status)) + { + KeInitializeEvent(&EventPair->LowEvent, + SynchronizationEvent, + FALSE); + KeInitializeEvent(&EventPair->HighEvent, + SynchronizationEvent, + FALSE); + + Status = ObInsertObject ((PVOID)EventPair, + NULL, + DesiredAccess, + 0, + NULL, + &hEventPair); + ObDereferenceObject(EventPair); + + if(NT_SUCCESS(Status)) { - return(Status); + _SEH_TRY + { + *EventPairHandle = hEventPair; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - - KeInitializeEvent(&EventPair->LowEvent, - SynchronizationEvent, - FALSE); - KeInitializeEvent(&EventPair->HighEvent, - SynchronizationEvent, - FALSE); - - Status = ObInsertObject ((PVOID)EventPair, - NULL, - DesiredAccess, - 0, - NULL, - EventPairHandle); - - ObDereferenceObject(EventPair); - + } return Status; } @@ -137,18 +165,52 @@ NtOpenEventPair(OUT PHANDLE EventPairHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes) { - NTSTATUS Status; + HANDLE hEventPair; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; - DPRINT("NtOpenEventPair()\n"); + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(EventPairHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } Status = ObOpenObjectByName(ObjectAttributes, ExEventPairObjectType, NULL, - UserMode, + PreviousMode, DesiredAccess, NULL, - EventPairHandle); - + &hEventPair); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *EventPairHandle = hEventPair; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + return Status; } @@ -157,26 +219,30 @@ NTSTATUS STDCALL NtSetHighEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeSetEvent(&EventPair->HighEvent, + EVENT_INCREMENT, + FALSE); - KeSetEvent(&EventPair->HighEvent, - EVENT_INCREMENT, - FALSE); - - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + ObDereferenceObject(EventPair); + } + + return Status; } @@ -184,32 +250,36 @@ NTSTATUS STDCALL NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeSetEvent(&EventPair->HighEvent, + EVENT_INCREMENT, + TRUE); - KeSetEvent(&EventPair->HighEvent, - EVENT_INCREMENT, - TRUE); + KeWaitForSingleObject(&EventPair->LowEvent, + WrEventPair, + PreviousMode, + FALSE, + NULL); - KeWaitForSingleObject(&EventPair->LowEvent, - WrEventPair, - UserMode, - FALSE, - NULL); - - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + ObDereferenceObject(EventPair); + } + + return Status; } @@ -217,26 +287,30 @@ NTSTATUS STDCALL NtSetLowEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtSetLowEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeSetEvent(&EventPair->LowEvent, + EVENT_INCREMENT, + FALSE); - KeSetEvent(&EventPair->LowEvent, - EVENT_INCREMENT, - FALSE); - - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + ObDereferenceObject(EventPair); + } + + return Status; } @@ -244,32 +318,36 @@ NTSTATUS STDCALL NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeSetEvent(&EventPair->LowEvent, + EVENT_INCREMENT, + TRUE); - KeSetEvent(&EventPair->LowEvent, - EVENT_INCREMENT, - TRUE); + KeWaitForSingleObject(&EventPair->HighEvent, + WrEventPair, + PreviousMode, + FALSE, + NULL); - KeWaitForSingleObject(&EventPair->HighEvent, - WrEventPair, - UserMode, - FALSE, - NULL); - - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + ObDereferenceObject(EventPair); + } + + return Status; } @@ -277,28 +355,32 @@ NTSTATUS STDCALL NtWaitLowEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeWaitForSingleObject(&EventPair->LowEvent, + WrEventPair, + PreviousMode, + FALSE, + NULL); - KeWaitForSingleObject(&EventPair->LowEvent, - WrEventPair, - UserMode, - FALSE, - NULL); - - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + ObDereferenceObject(EventPair); + } + + return Status; } @@ -306,28 +388,32 @@ NTSTATUS STDCALL NtWaitHighEventPair(IN HANDLE EventPairHandle) { PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n", EventPairHandle); + PreviousMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(EventPairHandle, - EVENT_PAIR_ALL_ACCESS, + SYNCHRONIZE, ExEventPairObjectType, - UserMode, + PreviousMode, (PVOID*)&EventPair, NULL); - if (!NT_SUCCESS(Status)) - return(Status); + if(NT_SUCCESS(Status)) + { + KeWaitForSingleObject(&EventPair->HighEvent, + WrEventPair, + PreviousMode, + FALSE, + NULL); - KeWaitForSingleObject(&EventPair->HighEvent, - WrEventPair, - UserMode, - FALSE, - NULL); + ObDereferenceObject(EventPair); + } - ObDereferenceObject(EventPair); - return(STATUS_SUCCESS); + return Status; } #ifdef _ENABLE_THRDEVTPAIR @@ -349,8 +435,8 @@ NtSetLowWaitHighThread( PKEVENT_PAIR EventPair; NTSTATUS Status; KIRQL Irql; - - Thread = PsGetCurrentThread(); + + PreviousMode = ExGetPreviousMode(); if(!Thread->EventPair) return STATUS_NO_EVENT_PAIR; diff --git a/reactos/ntoskrnl/ex/fmutex.c b/reactos/ntoskrnl/ex/fmutex.c index d6f7a362be3..8bb01b4015d 100644 --- a/reactos/ntoskrnl/ex/fmutex.c +++ b/reactos/ntoskrnl/ex/fmutex.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/fmutex.c * PURPOSE: Implements fast mutexes - * PROGRAMMER: David Welch (welch@cwcom.net) - * PORTABILITY: Checked. - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/hashtab.c b/reactos/ntoskrnl/ex/hashtab.c index 8d5c77921f3..82954c1767c 100644 --- a/reactos/ntoskrnl/ex/hashtab.c +++ b/reactos/ntoskrnl/ex/hashtab.c @@ -1,32 +1,19 @@ -/* - * ReactOS kernel - * Copyright (C) 1998-2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: hashtab.c + * FILE: ntoskrnl/ex/hashtab.c * PURPOSE: Hash table support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* * NOTES: The hash function is from: * Bob Jenkins * http://burtleburtle.net/bob/hash/doobs.html - * UPDATE HISTORY: - * 15-03-2002 CSH Created */ + #include #define NDEBUG diff --git a/reactos/ntoskrnl/ex/i386/interlck.c b/reactos/ntoskrnl/ex/i386/interlck.c index c7d98af1d85..12a3c2d9887 100644 --- a/reactos/ntoskrnl/ex/i386/interlck.c +++ b/reactos/ntoskrnl/ex/i386/interlck.c @@ -1,8 +1,13 @@ /* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/i386/interlck.c + * PURPOSE: No purpose listed. * - * reactos/ntoskrnl/ex/i386/interlck.c - * + * PROGRAMMERS: No programmer listed. */ + #include #ifdef LOCK @@ -11,7 +16,7 @@ #if defined(__GNUC__) -#ifdef MP +#ifdef CONFIG_SMP #define LOCK "lock ; " #else #define LOCK "" @@ -19,7 +24,7 @@ #elif defined(_MSC_VER) -#ifdef MP +#ifdef CONFIG_SMP #define LOCK lock #else #define LOCK diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index 96587e8e4e5..03951a885d7 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: kernel/ex/init.c - * PURPOSE: executive initalization - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * PORTABILITY: Checked. - * UPDATE HISTORY: - * Created 11/09/99 + * FILE: ntoskrnl/ex/init.c + * PURPOSE: Executive initalization + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ #include @@ -44,6 +26,13 @@ VOID INIT_FUNCTION ExInit3 (VOID) { ExInitializeWorkerThreads(); + ExpInitializeEventImplementation(); + ExpInitializeEventPairImplementation(); + ExpInitializeMutantImplementation(); + ExpInitializeSemaphoreImplementation(); + ExpInitializeTimerImplementation(); + LpcpInitSystem(); + ExpInitializeProfileImplementation(); ExpWin32kInit(); ExpInitUuids(); } diff --git a/reactos/ntoskrnl/ex/interlck.c b/reactos/ntoskrnl/ex/interlck.c index 2fe585641ff..e7863fd1ef5 100644 --- a/reactos/ntoskrnl/ex/interlck.c +++ b/reactos/ntoskrnl/ex/interlck.c @@ -3,10 +3,9 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/interlck.c - * PURPOSE: Implements interlocked functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * PURPOSE: Implements interlocked functions + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/list.c b/reactos/ntoskrnl/ex/list.c index 398cb10794d..25fbbea0eae 100644 --- a/reactos/ntoskrnl/ex/list.c +++ b/reactos/ntoskrnl/ex/list.c @@ -5,10 +5,9 @@ * FILE: ntoskrnl/ex/list.c * PURPOSE: Manages double linked lists, single linked lists and * sequenced lists + * * PROGRAMMERS: David Welch (welch@mcmail.com) * Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 02-07-2001 CSH Implemented sequenced lists */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/lookas.c b/reactos/ntoskrnl/ex/lookas.c index 1f1fe9dde76..1bd2a64050e 100644 --- a/reactos/ntoskrnl/ex/lookas.c +++ b/reactos/ntoskrnl/ex/lookas.c @@ -4,12 +4,14 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/lookas.c * PURPOSE: Lookaside lists + * * PROGRAMMERS: David Welch (welch@mcmail.com) * Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + + +/* * TODO: Use InterlockedXxxEntrySList for binary compatibility - * UPDATE HISTORY: - * 22-05-1998 DW Created - * 02-07-2001 CSH Implemented lookaside lists */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/mutant.c b/reactos/ntoskrnl/ex/mutant.c new file mode 100644 index 00000000000..0852e0075ab --- /dev/null +++ b/reactos/ntoskrnl/ex/mutant.c @@ -0,0 +1,368 @@ +/* $Id:$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/mutant.c + * PURPOSE: Synchronization primitives + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +POBJECT_TYPE ExMutantObjectType = NULL; + +static GENERIC_MAPPING ExpMutantMapping = { + STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SYNCHRONIZE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE, + MUTANT_ALL_ACCESS}; + +static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = +{ + ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */ +}; + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS STDCALL +ExpCreateMutant(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +ExpDeleteMutant(PVOID ObjectBody) +{ + DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody); + + KeReleaseMutant((PKMUTANT)ObjectBody, + MUTANT_INCREMENT, + TRUE, + FALSE); +} + + +VOID INIT_FUNCTION +ExpInitializeMutantImplementation(VOID) +{ + ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool); + + ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T'); + ExMutantObjectType->PeakObjects = 0; + ExMutantObjectType->PeakHandles = 0; + ExMutantObjectType->TotalObjects = 0; + ExMutantObjectType->TotalHandles = 0; + ExMutantObjectType->PagedPoolCharge = 0; + ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT); + ExMutantObjectType->Mapping = &ExpMutantMapping; + ExMutantObjectType->Dump = NULL; + ExMutantObjectType->Open = NULL; + ExMutantObjectType->Close = NULL; + ExMutantObjectType->Delete = ExpDeleteMutant; + ExMutantObjectType->Parse = NULL; + ExMutantObjectType->Security = NULL; + ExMutantObjectType->QueryName = NULL; + ExMutantObjectType->OkayToClose = NULL; + ExMutantObjectType->Create = ExpCreateMutant; + ExMutantObjectType->DuplicationNotify = NULL; + + ObpCreateTypeObject(ExMutantObjectType); +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtCreateMutant(OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN BOOLEAN InitialOwner) +{ + KPROCESSOR_MODE PreviousMode; + HANDLE hMutant; + PKMUTEX Mutant; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(MutantHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, + ExMutantObjectType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(KMUTANT), + 0, + 0, + (PVOID*)&Mutant); + if(NT_SUCCESS(Status)) + { + KeInitializeMutant(Mutant, + InitialOwner); + + Status = ObInsertObject((PVOID)Mutant, + NULL, + DesiredAccess, + 0, + NULL, + &hMutant); + ObDereferenceObject(Mutant); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *MutantHandle = hMutant; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtOpenMutant(OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hMutant; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(MutantHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObOpenObjectByName(ObjectAttributes, + ExMutantObjectType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hMutant); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *MutantHandle = hMutant; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtQueryMutant(IN HANDLE MutantHandle, + IN MUTANT_INFORMATION_CLASS MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG MutantInformationLength, + OUT PULONG ResultLength OPTIONAL) +{ + PKMUTANT Mutant; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(MutantInformationClass, + ExMutantInfoClass, + MutantInformation, + MutantInformationLength, + ResultLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status); + return Status; + } + + Status = ObReferenceObjectByHandle(MutantHandle, + MUTANT_QUERY_STATE, + ExMutantObjectType, + PreviousMode, + (PVOID*)&Mutant, + NULL); + if(NT_SUCCESS(Status)) + { + switch(MutantInformationClass) + { + case MutantBasicInformation: + { + PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation; + + _SEH_TRY + { + BasicInfo->Count = KeReadStateMutant(Mutant); + BasicInfo->Owned = (Mutant->OwnerThread != NULL); + BasicInfo->Abandoned = Mutant->Abandoned; + + if(ResultLength != NULL) + { + *ResultLength = sizeof(MUTANT_BASIC_INFORMATION); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + ObDereferenceObject(Mutant); + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtReleaseMutant(IN HANDLE MutantHandle, + IN PLONG PreviousCount OPTIONAL) +{ + PKMUTANT Mutant; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n", + MutantHandle, PreviousCount); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousCount != NULL && PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(PreviousCount, + sizeof(LONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(MutantHandle, + MUTANT_QUERY_STATE, + ExMutantObjectType, + PreviousMode, + (PVOID*)&Mutant, + NULL); + if(NT_SUCCESS(Status)) + { + LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE); + ObDereferenceObject(Mutant); + + if(PreviousCount != NULL) + { + _SEH_TRY + { + *PreviousCount = Prev; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ex/napi.c b/reactos/ntoskrnl/ex/napi.c index b250a4e75d5..76a82a41a88 100644 --- a/reactos/ntoskrnl/ex/napi.c +++ b/reactos/ntoskrnl/ex/napi.c @@ -1,9 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/napi.c * PURPOSE: Native API support routines - * PROGRAMMER: David Welch (welch@cwcom.net) + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/power.c b/reactos/ntoskrnl/ex/power.c index 5663df81160..0f8ca653781 100644 --- a/reactos/ntoskrnl/ex/power.c +++ b/reactos/ntoskrnl/ex/power.c @@ -1,12 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/power.c * PURPOSE: Power managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - * Added reboot support 30/01/99 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -16,6 +15,96 @@ /* FUNCTIONS *****************************************************************/ +VOID STDCALL +KeSetTargetProcessorDpc (IN PKDPC Dpc, + IN CCHAR Number); + +VOID STDCALL +KiHaltProcessorDpcRoutine(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + if (DeferredContext) + { + ExFreePool(DeferredContext); + } + while (TRUE) + { + KfRaiseIrql(SYNCH_LEVEL); + Ke386HaltProcessor(); + } +} + +VOID STDCALL +ShutdownThreadMain(PVOID Context) +{ + SHUTDOWN_ACTION Action = (SHUTDOWN_ACTION)Context; + LARGE_INTEGER Waittime; + + /* Run the thread on the boot processor */ + KeSetSystemAffinityThread(1); + + CmShutdownRegistry(); + IoShutdownRegisteredFileSystems(); + IoShutdownRegisteredDevices(); + + PiShutdownProcessManager(); + MiShutdownMemoryManager(); + + Waittime.QuadPart = (LONGLONG)-10000000; /* 1sec */ + KeDelayExecutionThread(KernelMode, FALSE, &Waittime); + + if (Action == ShutdownNoReboot) + { + +#if 0 + /* Switch off */ + HalReturnToFirmware (FIRMWARE_OFF); +#else +#ifdef CONFIG_SMP + ULONG i; + KIRQL OldIrql; + + OldIrql = KeRaiseIrqlToDpcLevel(); + /* Halt all other processors */ + for (i = 0; i < KeNumberProcessors; i++) + { + if (i != KeGetCurrentProcessorNumber()) + { + PKDPC Dpc = ExAllocatePool(NonPagedPool, sizeof(KDPC)); + if (Dpc == NULL) + { + KEBUGCHECK(0); + } + KeInitializeDpc(Dpc, KiHaltProcessorDpcRoutine, (PVOID)Dpc); + KeSetTargetProcessorDpc(Dpc, i); + KeInsertQueueDpc(Dpc, NULL, NULL); + KiIpiSendRequest(1 << i, IPI_REQUEST_DPC); + } + } + KeLowerIrql(OldIrql); +#endif /* CONFIG_SMP */ + PopSetSystemPowerState(PowerSystemShutdown); + + CHECKPOINT1; + + KiHaltProcessorDpcRoutine(NULL, NULL, NULL, NULL); + /* KiHaltProcessor does never return */ + +#endif + } + else if (Action == ShutdownReboot) + { + HalReturnToFirmware (FIRMWARE_REBOOT); + } + else + { + HalReturnToFirmware (FIRMWARE_HALT); + } +} + + NTSTATUS STDCALL NtSetSystemPowerState(IN POWER_ACTION SystemAction, IN SYSTEM_POWER_STATE MinSystemState, @@ -31,6 +120,10 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction, NTSTATUS STDCALL NtShutdownSystem(IN SHUTDOWN_ACTION Action) { + NTSTATUS Status; + HANDLE ThreadHandle; + PETHREAD ShutdownThread; + static PCH FamousLastWords[] = { "So long, and thanks for all the fish\n", @@ -61,8 +154,8 @@ NtShutdownSystem(IN SHUTDOWN_ACTION Action) "tell me..., in the future... will I be artificial intelligent enough to actually feel\n" "sad serving you this screen?\n", "Thank you for some well deserved rest.\n", - "It’s been great, maybe we can boot me up again some time soon.\n", - "For what’s it worth, I’ve enjoyed every single CPU cycle.\n", + "It's been great, maybe we can boot me up again some time soon.\n", + "For what's it worth, I've enjoyed every single CPU cycle.\n", "There are many questions when the end is near.\n" "What to expect, what will it be like...what should I look for?\n", "I've seen things you people wouldn't believe. Attack ships on fire\n" @@ -84,42 +177,39 @@ NtShutdownSystem(IN SHUTDOWN_ACTION Action) ZwQuerySystemTime(&Now); Now.u.LowPart = Now.u.LowPart >> 8; /* Seems to give a somewhat better "random" number */ - IoShutdownRegisteredDevices(); - CmShutdownRegistry(); - IoShutdownRegisteredFileSystems(); - - PiShutdownProcessManager(); - MiShutdownMemoryManager(); - if (Action == ShutdownNoReboot) { HalReleaseDisplayOwnership(); HalDisplayString("\nYou can switch off your computer now\n\n"); HalDisplayString(FamousLastWords[Now.u.LowPart % (sizeof(FamousLastWords) / sizeof(PCH))]); -#if 0 - /* Switch off */ - HalReturnToFirmware (FIRMWARE_OFF); -#else - PopSetSystemPowerState(PowerSystemShutdown); + } + Status = PsCreateSystemThread(&ThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + ShutdownThreadMain, + (PVOID)Action); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + } + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + (PVOID*)&ShutdownThread, + NULL); + NtClose(ThreadHandle); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + } + + KeSetPriorityThread(&ShutdownThread->Tcb, LOW_REALTIME_PRIORITY + 1); + ObDereferenceObject(ShutdownThread); - while (TRUE) - { - Ke386DisableInterrupts(); - Ke386HaltProcessor(); - } -#endif - } - else if (Action == ShutdownReboot) - { - HalReturnToFirmware (FIRMWARE_REBOOT); - } - else - { - HalReturnToFirmware (FIRMWARE_HALT); - } - return STATUS_SUCCESS; } /* EOF */ - diff --git a/reactos/ntoskrnl/ex/profile.c b/reactos/ntoskrnl/ex/profile.c new file mode 100644 index 00000000000..645dfcb8ccd --- /dev/null +++ b/reactos/ntoskrnl/ex/profile.c @@ -0,0 +1,373 @@ +/* $Id:$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/profile.c + * PURPOSE: Support for profiling + * + * PROGRAMMERS: No programmer listed. + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* TYPES ********************************************************************/ + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED ExProfileObjectType = NULL; + +static GENERIC_MAPPING ExpProfileMapping = { + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE, + STANDARD_RIGHTS_EXECUTE, + STANDARD_RIGHTS_ALL}; + +/* + * Size of the profile hash table. + */ +#define PROFILE_HASH_TABLE_SIZE (32) + +/* + * Table of lists of per-process profiling data structures hashed by PID. + */ +LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; + +/* + * Head of the list of profile data structures for the kernel. + */ +LIST_ENTRY SystemProfileList; + +/* + * Lock that protects the profiling data structures. + */ +KSPIN_LOCK ProfileListLock; + +/* + * Timer interrupts happen before we have initialized the profiling + * data structures so just ignore them before that. + */ +BOOLEAN ProfileInitDone = FALSE; + +VOID INIT_FUNCTION +ExpInitializeProfileImplementation(VOID) +{ + ULONG i; + + InitializeListHead(&SystemProfileList); + + for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++) + { + InitializeListHead(&ProcessProfileListHashTable[i]); + } + + KeInitializeSpinLock(&ProfileListLock); + ProfileInitDone = TRUE; + + ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlpCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile", NonPagedPool); + + ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F'); + ExProfileObjectType->PeakObjects = 0; + ExProfileObjectType->PeakHandles = 0; + ExProfileObjectType->TotalObjects = 0; + ExProfileObjectType->TotalHandles = 0; + ExProfileObjectType->PagedPoolCharge = 0; + ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE); + ExProfileObjectType->Mapping = &ExpProfileMapping; + ExProfileObjectType->Dump = NULL; + ExProfileObjectType->Open = NULL; + ExProfileObjectType->Close = NULL; + ExProfileObjectType->Delete = KiDeleteProfile; + ExProfileObjectType->Parse = NULL; + ExProfileObjectType->Security = NULL; + ExProfileObjectType->QueryName = NULL; + ExProfileObjectType->OkayToClose = NULL; + ExProfileObjectType->Create = NULL; + + ObpCreateTypeObject(ExProfileObjectType); +} + +NTSTATUS STDCALL +NtCreateProfile(OUT PHANDLE ProfileHandle, + IN HANDLE Process OPTIONAL, + IN PVOID ImageBase, + IN ULONG ImageSize, + IN ULONG BucketSize, + IN PVOID Buffer, + IN ULONG BufferSize, + IN KPROFILE_SOURCE ProfileSource, + IN KAFFINITY Affinity) +{ + HANDLE hProfile; + PKPROFILE Profile; + PEPROCESS pProcess; + KPROCESSOR_MODE PreviousMode; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(BufferSize == 0) + { + return STATUS_INVALID_PARAMETER_7; + } + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(ProfileHandle, + sizeof(HANDLE), + sizeof(ULONG)); + ProbeForWrite(Buffer, + BufferSize, + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + /* + * Reference the associated process + */ + if (Process != NULL) + { + Status = ObReferenceObjectByHandle(Process, + PROCESS_QUERY_INFORMATION, + PsProcessType, + PreviousMode, + (PVOID*)&pProcess, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + else + { + pProcess = NULL; + if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, + PreviousMode)) + { + DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; + } + } + + /* + * Check the parameters + */ + if ((pProcess == NULL && ImageBase < (PVOID)KERNEL_BASE) || + (pProcess != NULL && ImageBase >= (PVOID)KERNEL_BASE)) + { + return(STATUS_INVALID_PARAMETER_3); + } + if (((ImageSize >> BucketSize) * 4) >= BufferSize) + { + return(STATUS_BUFFER_TOO_SMALL); + } + if (ProfileSource != ProfileTime) + { + return(STATUS_INVALID_PARAMETER_9); + } + if (Affinity != 0) + { + return(STATUS_INVALID_PARAMETER_10); + } + + /* + * Create the object + */ + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + + Status = ObCreateObject(KernelMode, + ExProfileObjectType, + &ObjectAttributes, + PreviousMode, + NULL, + sizeof(KPROFILE), + 0, + 0, + (PVOID*)&Profile); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize it + */ + Profile->Base = ImageBase; + Profile->Size = ImageSize; + Profile->BucketShift = BucketSize; + Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize); + if(Profile->BufferMdl == NULL) { + DPRINT("MmCreateMdl: Out of memory!"); + ObDereferenceObject (Profile); + return(STATUS_NO_MEMORY); + } + MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess); + Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl); + Profile->BufferSize = BufferSize; + Profile->ProcessorMask = Affinity; + Profile->Started = FALSE; + Profile->Process = pProcess; + + /* + * Insert the profile into the profile list data structures + */ + KiInsertProfile(Profile); + + Status = ObInsertObject ((PVOID)Profile, + NULL, + STANDARD_RIGHTS_ALL, + 0, + NULL, + &hProfile); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject (Profile); + return Status; + } + + /* + * Copy the created handle back to the caller + */ + _SEH_TRY + { + *ProfileHandle = hProfile; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + ObDereferenceObject(Profile); + + return Status; +} + +NTSTATUS STDCALL +NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource, + OUT PULONG Interval) +{ + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(Interval, + sizeof(ULONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + if (ProfileSource == ProfileTime) + { + ULONG ReturnInterval; + + /* FIXME: What units does this use, for now nanoseconds */ + ReturnInterval = 100; + + _SEH_TRY + { + *Interval = ReturnInterval; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; + } + return STATUS_INVALID_PARAMETER_2; +} + +NTSTATUS STDCALL +NtSetIntervalProfile(IN ULONG Interval, + IN KPROFILE_SOURCE Source) +{ + return(STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS STDCALL +NtStartProfile(IN HANDLE ProfileHandle) +{ + PKPROFILE Profile; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + + PreviousMode = ExGetPreviousMode(); + + Status = ObReferenceObjectByHandle(ProfileHandle, + STANDARD_RIGHTS_ALL, + ExProfileObjectType, + PreviousMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Profile->Started = TRUE; + ObDereferenceObject(Profile); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtStopProfile(IN HANDLE ProfileHandle) +{ + PKPROFILE Profile; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + + PreviousMode = ExGetPreviousMode(); + + Status = ObReferenceObjectByHandle(ProfileHandle, + STANDARD_RIGHTS_ALL, + ExProfileObjectType, + PreviousMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Profile->Started = FALSE; + ObDereferenceObject(Profile); + return(STATUS_SUCCESS); +} + + diff --git a/reactos/ntoskrnl/ex/resource.c b/reactos/ntoskrnl/ex/resource.c index 673034753a2..2da0c9752b0 100644 --- a/reactos/ntoskrnl/ex/resource.c +++ b/reactos/ntoskrnl/ex/resource.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/resource.c * PURPOSE: Resource synchronization construct - * PROGRAMMER: Unknown - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: No programmer listed. */ diff --git a/reactos/ntoskrnl/ex/rundown.c b/reactos/ntoskrnl/ex/rundown.c index 39dfa89770e..1ccf65d952d 100644 --- a/reactos/ntoskrnl/ex/rundown.c +++ b/reactos/ntoskrnl/ex/rundown.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998 - 2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/rundown.c * PURPOSE: Rundown Protection Functions - * PORTABILITY: Checked + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/sem.c b/reactos/ntoskrnl/ex/sem.c new file mode 100644 index 00000000000..64c8f7d23d5 --- /dev/null +++ b/reactos/ntoskrnl/ex/sem.c @@ -0,0 +1,355 @@ +/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/sem.c + * PURPOSE: Synchronization primitives + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE ExSemaphoreObjectType; + +static GENERIC_MAPPING ExSemaphoreMapping = { + STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE, + SEMAPHORE_ALL_ACCESS}; + +static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = +{ + ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */ +}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +ExpCreateSemaphore(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + +VOID INIT_FUNCTION +ExpInitializeSemaphoreImplementation(VOID) +{ + ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool); + + ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T'); + ExSemaphoreObjectType->PeakObjects = 0; + ExSemaphoreObjectType->PeakHandles = 0; + ExSemaphoreObjectType->TotalObjects = 0; + ExSemaphoreObjectType->TotalHandles = 0; + ExSemaphoreObjectType->PagedPoolCharge = 0; + ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE); + ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping; + ExSemaphoreObjectType->Dump = NULL; + ExSemaphoreObjectType->Open = NULL; + ExSemaphoreObjectType->Close = NULL; + ExSemaphoreObjectType->Delete = NULL; + ExSemaphoreObjectType->Parse = NULL; + ExSemaphoreObjectType->Security = NULL; + ExSemaphoreObjectType->QueryName = NULL; + ExSemaphoreObjectType->OkayToClose = NULL; + ExSemaphoreObjectType->Create = ExpCreateSemaphore; + ExSemaphoreObjectType->DuplicationNotify = NULL; + + ObpCreateTypeObject(ExSemaphoreObjectType); +} + +/* + * @implemented + */ +NTSTATUS STDCALL +NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN LONG InitialCount, + IN LONG MaximumCount) +{ + PKSEMAPHORE Semaphore; + HANDLE hSemaphore; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(SemaphoreHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, + ExSemaphoreObjectType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(KSEMAPHORE), + 0, + 0, + (PVOID*)&Semaphore); + if (NT_SUCCESS(Status)) + { + KeInitializeSemaphore(Semaphore, + InitialCount, + MaximumCount); + + Status = ObInsertObject ((PVOID)Semaphore, + NULL, + DesiredAccess, + 0, + NULL, + &hSemaphore); + + ObDereferenceObject(Semaphore); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *SemaphoreHandle = hSemaphore; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hSemaphore; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(SemaphoreHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObOpenObjectByName(ObjectAttributes, + ExSemaphoreObjectType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hSemaphore); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *SemaphoreHandle = hSemaphore; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtQuerySemaphore(IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG SemaphoreInformationLength, + OUT PULONG ReturnLength OPTIONAL) +{ + PKSEMAPHORE Semaphore; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(SemaphoreInformationClass, + ExSemaphoreInfoClass, + SemaphoreInformation, + SemaphoreInformationLength, + ReturnLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status); + return Status; + } + + Status = ObReferenceObjectByHandle(SemaphoreHandle, + SEMAPHORE_QUERY_STATE, + ExSemaphoreObjectType, + PreviousMode, + (PVOID*)&Semaphore, + NULL); + if(NT_SUCCESS(Status)) + { + switch(SemaphoreInformationClass) + { + case SemaphoreBasicInformation: + { + PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation; + + _SEH_TRY + { + BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore); + BasicInfo->MaximumCount = Semaphore->Limit; + + if(ReturnLength != NULL) + { + *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + ObDereferenceObject(Semaphore); + } + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtReleaseSemaphore(IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT PLONG PreviousCount OPTIONAL) +{ + KPROCESSOR_MODE PreviousMode; + PKSEMAPHORE Semaphore; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousCount != NULL && PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(PreviousCount, + sizeof(LONG), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(SemaphoreHandle, + SEMAPHORE_MODIFY_STATE, + ExSemaphoreObjectType, + PreviousMode, + (PVOID*)&Semaphore, + NULL); + if (NT_SUCCESS(Status)) + { + LONG PrevCount = KeReleaseSemaphore(Semaphore, + IO_NO_INCREMENT, + ReleaseCount, + FALSE); + ObDereferenceObject(Semaphore); + + if(PreviousCount != NULL) + { + _SEH_TRY + { + *PreviousCount = PrevCount; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ex/stree.c b/reactos/ntoskrnl/ex/stree.c index 8a33bb97fd2..f889d379507 100644 --- a/reactos/ntoskrnl/ex/stree.c +++ b/reactos/ntoskrnl/ex/stree.c @@ -1,31 +1,15 @@ -/* - * ReactOS kernel - * Copyright (C) 1998-2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: stree.c + * FILE: ntoskrnl/ex/stree.c * PURPOSE: Splay tree support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * * NOTES: Based on a splay tree implementation by * Daniel Stenberg * http://www.contactor.se/~dast/stuff/dsplay-1.2.tar.gz - * UPDATE HISTORY: - * 15-03-2002 CSH Created */ #include diff --git a/reactos/ntoskrnl/ex/synch.c b/reactos/ntoskrnl/ex/synch.c index 08984df02f0..70860f9e1f3 100644 --- a/reactos/ntoskrnl/ex/synch.c +++ b/reactos/ntoskrnl/ex/synch.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/synch.c * PURPOSE: Synchronization Functions (Pushlocks) - * PORTABILITY: Checked + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index b11629e2fea..de9efb57168 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -4,12 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/sysinfo.c * PURPOSE: System information functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * 20/03/2003: implemented querying SystemProcessInformation, - * no more copying to-from the caller (Aleksey - * Bragin ) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Aleksey Bragin (aleksey@studiocerebral.com) */ /* INCLUDES *****************************************************************/ @@ -90,237 +87,227 @@ ExGetCurrentProcessorCounts ( } NTSTATUS STDCALL -NtQuerySystemEnvironmentValue (IN PUNICODE_STRING UnsafeName, - OUT PVOID UnsafeValue, - IN ULONG Length, - IN OUT PULONG UnsafeReturnLength) +NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName, + OUT PWCHAR ValueBuffer, + IN ULONG ValueBufferLength, + IN OUT PULONG ReturnLength OPTIONAL) { - NTSTATUS Status; ANSI_STRING AName; UNICODE_STRING WName; BOOLEAN Result; PCH Value; ANSI_STRING AValue; UNICODE_STRING WValue; - ULONG ReturnLength; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(VariableName, + sizeof(UNICODE_STRING), + sizeof(ULONG)); + ProbeForWrite(ValueBuffer, + ValueBufferLength, + sizeof(WCHAR)); + if(ReturnLength != NULL) + { + ProbeForWrite(ReturnLength, + sizeof(ULONG), + sizeof(ULONG)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } /* * Copy the name to kernel space if necessary and convert it to ANSI. */ - if (ExGetPreviousMode() != KernelMode) + Status = RtlCaptureUnicodeString(&WName, + PreviousMode, + NonPagedPool, + FALSE, + VariableName); + if(NT_SUCCESS(Status)) + { + /* + * according to ntinternals the SeSystemEnvironmentName privilege is required! + */ + if(!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, + PreviousMode)) { - Status = RtlCaptureUnicodeString(&WName, UnsafeName); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + RtlReleaseCapturedUnicodeString(&WName, + PreviousMode, + FALSE); + DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; } - else + + /* + * convert the value name to ansi + */ + Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE); + RtlReleaseCapturedUnicodeString(&WName, + PreviousMode, + FALSE); + if(!NT_SUCCESS(Status)) { - Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + return Status; } - + /* * Create a temporary buffer for the value */ - Value = ExAllocatePool(NonPagedPool, Length); - if (Value == NULL) + Value = ExAllocatePool(NonPagedPool, ValueBufferLength); + if (Value == NULL) { RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - } - return(STATUS_NO_MEMORY); + return STATUS_INSUFFICIENT_RESOURCES; } - - /* - * Get the environment variable - */ - Result = HalGetEnvironmentVariable(AName.Buffer, Value, Length); - if (!Result) + + /* + * Get the environment variable + */ + Result = HalGetEnvironmentVariable(AName.Buffer, Value, ValueBufferLength); + if(!Result) { RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - } ExFreePool(Value); - return(STATUS_UNSUCCESSFUL); + return STATUS_UNSUCCESSFUL; } - - /* - * Convert the result to UNICODE. - */ - RtlInitAnsiString(&AValue, Value); - Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE); - if (!NT_SUCCESS(Status)) + + /* + * Convert the result to UNICODE, protect with SEH in case the value buffer + * isn't NULL-terminated! + */ + _SEH_TRY { - RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - } - ExFreePool(Value); - return(Status); + RtlInitAnsiString(&AValue, Value); + Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE); } - ReturnLength = WValue.Length; - - /* - * Copy the result back to the caller. - */ - if (ExGetPreviousMode() != KernelMode) + _SEH_HANDLE { - Status = MmCopyToCaller(UnsafeValue, WValue.Buffer, ReturnLength); - if (!NT_SUCCESS(Status)) - { - RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - } - ExFreePool(Value); - RtlFreeUnicodeString(&WValue); - return(Status); - } - - Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength, - sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - } - ExFreePool(Value); - RtlFreeUnicodeString(&WValue); - return(Status); - } + Status = _SEH_GetExceptionCode(); } - else + _SEH_END; + + if(NT_SUCCESS(Status)) { - memcpy(UnsafeValue, WValue.Buffer, ReturnLength); - memcpy(UnsafeReturnLength, &ReturnLength, sizeof(ULONG)); - } + /* + * Copy the result back to the caller. + */ + _SEH_TRY + { + RtlCopyMemory(ValueBuffer, WValue.Buffer, WValue.Length); + ValueBuffer[WValue.Length / sizeof(WCHAR)] = L'\0'; + if(ReturnLength != NULL) + { + *ReturnLength = WValue.Length + sizeof(WCHAR); + } - /* - * Free temporary buffers. - */ - RtlFreeAnsiString(&AName); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - ExFreePool(Value); - RtlFreeUnicodeString(&WValue); + + /* + * Cleanup allocated resources. + */ + RtlFreeAnsiString(&AName); + ExFreePool(Value); + } - return(STATUS_SUCCESS); + return Status; } NTSTATUS STDCALL -NtSetSystemEnvironmentValue (IN PUNICODE_STRING UnsafeName, - IN PUNICODE_STRING UnsafeValue) +NtSetSystemEnvironmentValue (IN PUNICODE_STRING VariableName, + IN PUNICODE_STRING Value) { - UNICODE_STRING WName; - ANSI_STRING AName; - UNICODE_STRING WValue; - ANSI_STRING AValue; - BOOLEAN Result; + UNICODE_STRING CapturedName, CapturedValue; + ANSI_STRING AName, AValue; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; + PreviousMode = ExGetPreviousMode(); + /* - * Check for required privilege. + * Copy the strings to kernel space if necessary */ - /* FIXME: Not implemented. */ + Status = RtlCaptureUnicodeString(&CapturedName, + PreviousMode, + NonPagedPool, + FALSE, + VariableName); + if(NT_SUCCESS(Status)) + { + Status = RtlCaptureUnicodeString(&CapturedValue, + PreviousMode, + NonPagedPool, + FALSE, + Value); + if(NT_SUCCESS(Status)) + { + /* + * according to ntinternals the SeSystemEnvironmentName privilege is required! + */ + if(SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, + PreviousMode)) + { + /* + * convert the strings to ANSI + */ + Status = RtlUnicodeStringToAnsiString(&AName, + &CapturedName, + TRUE); + if(NT_SUCCESS(Status)) + { + Status = RtlUnicodeStringToAnsiString(&AValue, + &CapturedValue, + TRUE); + if(NT_SUCCESS(Status)) + { + BOOLEAN Result = HalSetEnvironmentVariable(AName.Buffer, + AValue.Buffer); - /* - * Copy the name to kernel space if necessary and convert it to ANSI. - */ - if (ExGetPreviousMode() != KernelMode) - { - Status = RtlCaptureUnicodeString(&WName, UnsafeName); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } - else - { - Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); + } + } + } + else + { + DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n"); + Status = STATUS_PRIVILEGE_NOT_HELD; + } + + RtlReleaseCapturedUnicodeString(&CapturedValue, + PreviousMode, + FALSE); } - /* - * Copy the value to kernel space and convert to ANSI. - */ - if (ExGetPreviousMode() != KernelMode) - { - Status = RtlCaptureUnicodeString(&WValue, UnsafeValue); - if (!NT_SUCCESS(Status)) - { - RtlFreeUnicodeString(&WName); - RtlFreeAnsiString(&AName); - return(Status); - } - Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE); - if (!NT_SUCCESS(Status)) - { - RtlFreeUnicodeString(&WName); - RtlFreeAnsiString(&AName); - RtlFreeUnicodeString(&WValue); - return(Status); - } - } - else - { - Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE); - if (!NT_SUCCESS(Status)) - { - RtlFreeAnsiString(&AName); - return(Status); - } - } - - /* - * Set the environment variable - */ - Result = HalSetEnvironmentVariable(AName.Buffer, AValue.Buffer); - - /* - * Free everything and return status. - */ - RtlFreeAnsiString(&AName); - RtlFreeAnsiString(&AValue); - if (ExGetPreviousMode() != KernelMode) - { - RtlFreeUnicodeString(&WName); - RtlFreeUnicodeString(&WValue); - } - - if (!Result) - { - return(STATUS_UNSUCCESSFUL); - } - return(STATUS_SUCCESS); + RtlReleaseCapturedUnicodeString(&CapturedName, + PreviousMode, + FALSE); + } + + return Status; } @@ -411,7 +398,7 @@ QSI_DEF(SystemPerformanceInformation) return (STATUS_INFO_LENGTH_MISMATCH); } - PsLookupProcessByProcessId((PVOID) 1, &TheIdleProcess); + TheIdleProcess = PsInitialSystemProcess; /* FIXME */ Spi->IdleTime.QuadPart = TheIdleProcess->Pcb.KernelTime * 100000LL; @@ -515,8 +502,6 @@ QSI_DEF(SystemPerformanceInformation) Spi->SecondLevelTbFills = 0; /* FIXME */ Spi->SystemCalls = 0; /* FIXME */ - ObDereferenceObject(TheIdleProcess); - return (STATUS_SUCCESS); } @@ -619,7 +604,7 @@ QSI_DEF(SystemProcessInformation) SpiCur->BasePriority = pr->Pcb.BasePriority; SpiCur->ProcessId = pr->UniqueProcessId; - SpiCur->InheritedFromProcessId = (DWORD)(pr->InheritedFromUniqueProcessId); + SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId; SpiCur->HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable); SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize; SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart; @@ -959,7 +944,7 @@ QSI_DEF(SystemFullMemoryInformation) } DPRINT("SystemFullMemoryInformation\n"); - PsLookupProcessByProcessId((PVOID) 1, &TheIdleProcess); + TheIdleProcess = PsInitialSystemProcess; /* FIXME */ DPRINT("PID: %d, KernelTime: %u PFFree: %d PFUsed: %d\n", TheIdleProcess->UniqueProcessId, @@ -973,8 +958,6 @@ QSI_DEF(SystemFullMemoryInformation) *Spi = MiMemoryConsumers[MC_USER].PagesUsed; - ObDereferenceObject(TheIdleProcess); - return (STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ex/time.c b/reactos/ntoskrnl/ex/time.c index 3ba5c01032c..9e5965893a4 100644 --- a/reactos/ntoskrnl/ex/time.c +++ b/reactos/ntoskrnl/ex/time.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/time.c * PURPOSE: Time - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -142,28 +141,61 @@ ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) * RETURNS: Status */ NTSTATUS STDCALL -NtSetSystemTime(IN PLARGE_INTEGER UnsafeNewSystemTime, - OUT PLARGE_INTEGER UnsafeOldSystemTime OPTIONAL) +NtSetSystemTime(IN PLARGE_INTEGER SystemTime, + OUT PLARGE_INTEGER PreviousTime OPTIONAL) { LARGE_INTEGER OldSystemTime; LARGE_INTEGER NewSystemTime; LARGE_INTEGER LocalTime; TIME_FIELDS TimeFields; - NTSTATUS Status; - - /* FIXME: Check for SeSystemTimePrivilege */ - - Status = MmCopyFromCaller(&NewSystemTime, UnsafeNewSystemTime, - sizeof(NewSystemTime)); - if (!NT_SUCCESS(Status)) + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(SystemTime, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + NewSystemTime = *SystemTime; + if(PreviousTime != NULL) + { + ProbeForWrite(PreviousTime, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) { return Status; } + } + else + { + NewSystemTime = *SystemTime; + } + + if(!SeSinglePrivilegeCheck(SeSystemtimePrivilege, + PreviousMode)) + { + DPRINT1("NtSetSystemTime: Caller requires the SeSystemtimePrivilege privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; + } + + if(PreviousTime != NULL) + { + KeQuerySystemTime(&OldSystemTime); + } - if (UnsafeOldSystemTime != NULL) - { - KeQuerySystemTime(&OldSystemTime); - } ExSystemTimeToLocalTime(&NewSystemTime, &LocalTime); RtlTimeToTimeFields(&LocalTime, @@ -173,15 +205,18 @@ NtSetSystemTime(IN PLARGE_INTEGER UnsafeNewSystemTime, /* Set system time */ KiSetSystemTime(&NewSystemTime); - if (UnsafeOldSystemTime != NULL) + if(PreviousTime != NULL) + { + _SEH_TRY { - Status = MmCopyToCaller(UnsafeOldSystemTime, &OldSystemTime, - sizeof(OldSystemTime)); - if (!NT_SUCCESS(Status)) - { - return Status; - } + *PreviousTime = OldSystemTime; } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } return STATUS_SUCCESS; } @@ -194,19 +229,38 @@ NtSetSystemTime(IN PLARGE_INTEGER UnsafeNewSystemTime, * time of day in the standard time format. */ NTSTATUS STDCALL -NtQuerySystemTime(OUT PLARGE_INTEGER UnsafeCurrentTime) +NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime) { - LARGE_INTEGER CurrentTime; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; - KeQuerySystemTime(&CurrentTime); - Status = MmCopyToCaller(UnsafeCurrentTime, &CurrentTime, - sizeof(CurrentTime)); - if (!NT_SUCCESS(Status)) + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY { - return(Status); + ProbeForRead(SystemTime, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + + /* it's safe to pass the pointer directly to KeQuerySystemTime as it's just + a basic copy to these pointer, if it raises an exception nothing dangerous + can happen! */ + KeQuerySystemTime(SystemTime); } - return STATUS_SUCCESS; + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + else + { + KeQuerySystemTime(SystemTime); + } + + return Status; } diff --git a/reactos/ntoskrnl/ex/timer.c b/reactos/ntoskrnl/ex/timer.c new file mode 100644 index 00000000000..3deeff2518c --- /dev/null +++ b/reactos/ntoskrnl/ex/timer.c @@ -0,0 +1,540 @@ +/* $Id: nttimer.c 12779 2005-01-04 04:45:00Z gdalsnes $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/timer.c + * PURPOSE: User-mode timers + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + + +/* TYPES ********************************************************************/ + +typedef struct _NTTIMER +{ + KTIMER Timer; + KDPC Dpc; + KAPC Apc; + BOOLEAN Running; +} NTTIMER, *PNTTIMER; + + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE ExTimerType = NULL; + +static GENERIC_MAPPING ExpTimerMapping = { + STANDARD_RIGHTS_READ | TIMER_QUERY_STATE, + STANDARD_RIGHTS_WRITE | TIMER_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, + TIMER_ALL_ACCESS}; + +static const INFORMATION_CLASS_INFO ExTimerInfoClass[] = +{ + ICI_SQ_SAME( sizeof(TIMER_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* TimerBasicInformation */ +}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +ExpCreateTimer(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("ExpCreateTimer(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +ExpDeleteTimer(PVOID ObjectBody) +{ + KIRQL OldIrql; + PNTTIMER Timer = ObjectBody; + + DPRINT("ExpDeleteTimer()\n"); + + OldIrql = KeRaiseIrqlToDpcLevel(); + + KeCancelTimer(&Timer->Timer); + KeRemoveQueueDpc(&Timer->Dpc); + KeRemoveQueueApc(&Timer->Apc); + Timer->Running = FALSE; + + KeLowerIrql(OldIrql); +} + + +VOID STDCALL +ExpTimerDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PNTTIMER Timer; + + DPRINT("ExpTimerDpcRoutine()\n"); + + Timer = (PNTTIMER)DeferredContext; + + if ( Timer->Running ) + { + KeInsertQueueApc(&Timer->Apc, + SystemArgument1, + SystemArgument2, + IO_NO_INCREMENT); + } +} + + +VOID STDCALL +ExpTimerApcKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2) +{ + DPRINT("ExpTimerApcKernelRoutine()\n"); + +} + + +VOID INIT_FUNCTION +ExpInitializeTimerImplementation(VOID) +{ + ASSERT(!ExTimerType) + ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + RtlpCreateUnicodeString(&ExTimerType->TypeName, L"Timer", NonPagedPool); + + ExTimerType->Tag = TAG('T', 'I', 'M', 'T'); + ExTimerType->PeakObjects = 0; + ExTimerType->PeakHandles = 0; + ExTimerType->TotalObjects = 0; + ExTimerType->TotalHandles = 0; + ExTimerType->PagedPoolCharge = 0; + ExTimerType->NonpagedPoolCharge = sizeof(NTTIMER); + ExTimerType->Mapping = &ExpTimerMapping; + ExTimerType->Dump = NULL; + ExTimerType->Open = NULL; + ExTimerType->Close = NULL; + ExTimerType->Delete = ExpDeleteTimer; + ExTimerType->Parse = NULL; + ExTimerType->Security = NULL; + ExTimerType->QueryName = NULL; + ExTimerType->OkayToClose = NULL; + ExTimerType->Create = ExpCreateTimer; + ExTimerType->DuplicationNotify = NULL; + + ObpCreateTypeObject(ExTimerType); +} + + +NTSTATUS STDCALL +NtCancelTimer(IN HANDLE TimerHandle, + OUT PBOOLEAN CurrentState OPTIONAL) +{ + PNTTIMER Timer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState); + + if(CurrentState != NULL && PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(CurrentState, + sizeof(BOOLEAN), + sizeof(BOOLEAN)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_ALL_ACCESS, + ExTimerType, + PreviousMode, + (PVOID*)&Timer, + NULL); + if(NT_SUCCESS(Status)) + { + BOOLEAN State; + KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); + + State = KeCancelTimer(&Timer->Timer); + KeRemoveQueueDpc(&Timer->Dpc); + KeRemoveQueueApc(&Timer->Apc); + Timer->Running = FALSE; + + KeLowerIrql(OldIrql); + ObDereferenceObject(Timer); + + if(CurrentState != NULL) + { + _SEH_TRY + { + *CurrentState = State; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +NTSTATUS STDCALL +NtCreateTimer(OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN TIMER_TYPE TimerType) +{ + PNTTIMER Timer; + HANDLE hTimer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtCreateTimer()\n"); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(TimerHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, + ExTimerType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(NTTIMER), + 0, + 0, + (PVOID*)&Timer); + if(NT_SUCCESS(Status)) + { + KeInitializeTimerEx(&Timer->Timer, + TimerType); + + KeInitializeDpc(&Timer->Dpc, + &ExpTimerDpcRoutine, + Timer); + + Timer->Running = FALSE; + + Status = ObInsertObject ((PVOID)Timer, + NULL, + DesiredAccess, + 0, + NULL, + &hTimer); + ObDereferenceObject(Timer); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *TimerHandle = hTimer; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; +} + + +NTSTATUS STDCALL +NtOpenTimer(OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hTimer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtOpenTimer()\n"); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(TimerHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObOpenObjectByName(ObjectAttributes, + ExTimerType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hTimer); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *TimerHandle = hTimer; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; +} + + +NTSTATUS STDCALL +NtQueryTimer(IN HANDLE TimerHandle, + IN TIMER_INFORMATION_CLASS TimerInformationClass, + OUT PVOID TimerInformation, + IN ULONG TimerInformationLength, + OUT PULONG ReturnLength OPTIONAL) +{ + PNTTIMER Timer; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(TimerInformationClass, + ExTimerInfoClass, + TimerInformation, + TimerInformationLength, + ReturnLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryTimer() failed, Status: 0x%x\n", Status); + return Status; + } + + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_QUERY_STATE, + ExTimerType, + PreviousMode, + (PVOID*)&Timer, + NULL); + if(NT_SUCCESS(Status)) + { + switch(TimerInformationClass) + { + case TimerBasicInformation: + { + PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation; + + _SEH_TRY + { + /* FIXME - interrupt correction */ + BasicInfo->TimeRemaining.QuadPart = Timer->Timer.DueTime.QuadPart; + BasicInfo->SignalState = (BOOLEAN)Timer->Timer.Header.SignalState; + + if(ReturnLength != NULL) + { + *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + ObDereferenceObject(Timer); + } + + return Status; +} + + +NTSTATUS STDCALL +NtSetTimer(IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN PTIMER_APC_ROUTINE TimerApcRoutine OPTIONAL, + IN PVOID TimerContext OPTIONAL, + IN BOOLEAN ResumeTimer, + IN LONG Period OPTIONAL, + OUT PBOOLEAN PreviousState OPTIONAL) +{ + PNTTIMER Timer; + BOOLEAN Result; + BOOLEAN State; + LARGE_INTEGER TimerDueTime; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtSetTimer()\n"); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(DueTime, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + TimerDueTime = *DueTime; + + if(PreviousState != NULL) + { + ProbeForWrite(PreviousState, + sizeof(BOOLEAN), + sizeof(BOOLEAN)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_ALL_ACCESS, + ExTimerType, + PreviousMode, + (PVOID*)&Timer, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + State = KeReadStateTimer(&Timer->Timer); + + if (Timer->Running == TRUE) + { + /* cancel running timer */ + const KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); + KeCancelTimer(&Timer->Timer); + KeRemoveQueueDpc(&Timer->Dpc); + KeRemoveQueueApc(&Timer->Apc); + Timer->Running = FALSE; + KeLowerIrql(OldIrql); + } + + if (TimerApcRoutine) + { + KeInitializeApc(&Timer->Apc, + KeGetCurrentThread(), + OriginalApcEnvironment, + &ExpTimerApcKernelRoutine, + (PKRUNDOWN_ROUTINE)NULL, + (PKNORMAL_ROUTINE)TimerApcRoutine, + PreviousMode, + TimerContext); + } + + Result = KeSetTimerEx(&Timer->Timer, + TimerDueTime, + Period, + TimerApcRoutine ? &Timer->Dpc : 0 ); + if (Result) + { + ObDereferenceObject(Timer); + DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" ); + return STATUS_UNSUCCESSFUL; + } + + Timer->Running = TRUE; + + ObDereferenceObject(Timer); + + if (PreviousState != NULL) + { + _SEH_TRY + { + *PreviousState = State; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ex/util.c b/reactos/ntoskrnl/ex/util.c index 25c4bee59a4..6970575a29c 100644 --- a/reactos/ntoskrnl/ex/util.c +++ b/reactos/ntoskrnl/ex/util.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/misc.c * PURPOSE: Executive Utility Functions - * PORTABILITY: Checked + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/uuid.c b/reactos/ntoskrnl/ex/uuid.c index 9971a2ddb46..8cdac4f657f 100644 --- a/reactos/ntoskrnl/ex/uuid.c +++ b/reactos/ntoskrnl/ex/uuid.c @@ -1,9 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: UUID generator - * FILE: kernel/ex/uuid.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/uuid.c + * PURPOSE: UUID generator + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ @@ -72,12 +74,12 @@ ExpLoadUuidSequence(PULONG Sequence) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - DPRINT("NtOpenKey() failed (Status %lx)\n", Status); + DPRINT("ZwOpenKey() failed (Status %lx)\n", Status); return Status; } @@ -85,16 +87,16 @@ ExpLoadUuidSequence(PULONG Sequence) L"UuidSequenceNumber"); ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &Name, KeyValuePartialInformation, ValueBuffer, VALUE_BUFFER_SIZE, &ValueLength); - NtClose(KeyHandle); + ZwClose(KeyHandle); if (!NT_SUCCESS(Status)) { - DPRINT("NtQueryValueKey() failed (Status %lx)\n", Status); + DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status); return Status; } @@ -122,27 +124,27 @@ ExpSaveUuidSequence(PULONG Sequence) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - DPRINT("NtOpenKey() failed (Status %lx)\n", Status); + DPRINT("ZwOpenKey() failed (Status %lx)\n", Status); return Status; } RtlInitUnicodeString(&Name, L"UuidSequenceNumber"); - Status = NtSetValueKey(KeyHandle, + Status = ZwSetValueKey(KeyHandle, &Name, 0, REG_DWORD, Sequence, sizeof(ULONG)); - NtClose(KeyHandle); + ZwClose(KeyHandle); if (!NT_SUCCESS(Status)) { - DPRINT("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT("ZwSetValueKey() failed (Status %lx)\n", Status); } return Status; diff --git a/reactos/ntoskrnl/ex/win32k.c b/reactos/ntoskrnl/ex/win32k.c index 00e972017a4..4cdc21622d8 100644 --- a/reactos/ntoskrnl/ex/win32k.c +++ b/reactos/ntoskrnl/ex/win32k.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: kernel/ex/win32k.c + * FILE: ntoskrnl/ex/win32k.c * PURPOSE: Executive Win32 subsystem support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 04-06-2001 CSH Created + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ #include @@ -101,7 +84,7 @@ ExpWinStaObjectCreate(PVOID ObjectBody, DPRINT("Creating window station (0x%X) Name (%wZ)\n", WinSta, &UnicodeString); - Status = RtlCreateUnicodeString(&WinSta->Name, UnicodeString.Buffer); + Status = RtlpCreateUnicodeString(&WinSta->Name, UnicodeString.Buffer, NonPagedPool); if (!NT_SUCCESS(Status)) { return Status; @@ -264,7 +247,7 @@ ExpDesktopObjectCreate(PVOID ObjectBody, &Desktop->ListEntry, &Desktop->WindowStation->Lock); - return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer); + return RtlpCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer, NonPagedPool); } VOID STDCALL @@ -297,8 +280,8 @@ ExpWin32kInit(VOID) ExWindowStationObjectType->Tag = TAG('W', 'I', 'N', 'S'); ExWindowStationObjectType->TotalObjects = 0; ExWindowStationObjectType->TotalHandles = 0; - ExWindowStationObjectType->MaxObjects = ULONG_MAX; - ExWindowStationObjectType->MaxHandles = ULONG_MAX; + ExWindowStationObjectType->PeakObjects = 0; + ExWindowStationObjectType->PeakHandles = 0; ExWindowStationObjectType->PagedPoolCharge = 0; ExWindowStationObjectType->NonpagedPoolCharge = sizeof(WINSTATION_OBJECT); ExWindowStationObjectType->Mapping = &ExpWindowStationMapping; @@ -327,8 +310,8 @@ ExpWin32kInit(VOID) ExDesktopObjectType->Tag = TAG('D', 'E', 'S', 'K'); ExDesktopObjectType->TotalObjects = 0; ExDesktopObjectType->TotalHandles = 0; - ExDesktopObjectType->MaxObjects = ULONG_MAX; - ExDesktopObjectType->MaxHandles = ULONG_MAX; + ExDesktopObjectType->PeakObjects = 0; + ExDesktopObjectType->PeakHandles = 0; ExDesktopObjectType->PagedPoolCharge = 0; ExDesktopObjectType->NonpagedPoolCharge = sizeof(DESKTOP_OBJECT); ExDesktopObjectType->Mapping = &ExpDesktopMapping; diff --git a/reactos/ntoskrnl/ex/work.c b/reactos/ntoskrnl/ex/work.c index 94fbba3c0ce..8d7bac152fa 100644 --- a/reactos/ntoskrnl/ex/work.c +++ b/reactos/ntoskrnl/ex/work.c @@ -2,11 +2,10 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: mkernel/kernel/work.c + * FILE: ntoskrnl/ex/work.c * PURPOSE: Manage system work queues - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 29/06/98: Created + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/ex/zone.c b/reactos/ntoskrnl/ex/zone.c index 3d17459a02d..c606d6afe75 100644 --- a/reactos/ntoskrnl/ex/zone.c +++ b/reactos/ntoskrnl/ex/zone.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/zone.c - * PURPOSE: Implements zone buffers - * PROGRAMMER: David Welch (welch@mcmail.com) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/zone.c + * PURPOSE: Implements zone buffers + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/fs/dbcsname.c b/reactos/ntoskrnl/fs/dbcsname.c index c008218e168..d1af7e2b3ec 100644 --- a/reactos/ntoskrnl/fs/dbcsname.c +++ b/reactos/ntoskrnl/fs/dbcsname.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/dbcsname.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/dbcsname.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include @@ -10,134 +14,134 @@ static UCHAR LegalAnsiCharacterArray[] = { - 0, /* CTRL+@, 0x00 */ - 0, /* CTRL+A, 0x01 */ - 0, /* CTRL+B, 0x02 */ - 0, /* CTRL+C, 0x03 */ - 0, /* CTRL+D, 0x04 */ - 0, /* CTRL+E, 0x05 */ - 0, /* CTRL+F, 0x06 */ - 0, /* CTRL+G, 0x07 */ - 0, /* CTRL+H, 0x08 */ - 0, /* CTRL+I, 0x09 */ - 0, /* CTRL+J, 0x0a */ - 0, /* CTRL+K, 0x0b */ - 0, /* CTRL+L, 0x0c */ - 0, /* CTRL+M, 0x0d */ - 0, /* CTRL+N, 0x0e */ - 0, /* CTRL+O, 0x0f */ - 0, /* CTRL+P, 0x10 */ - 0, /* CTRL+Q, 0x11 */ - 0, /* CTRL+R, 0x12 */ - 0, /* CTRL+S, 0x13 */ - 0, /* CTRL+T, 0x14 */ - 0, /* CTRL+U, 0x15 */ - 0, /* CTRL+V, 0x16 */ - 0, /* CTRL+W, 0x17 */ - 0, /* CTRL+X, 0x18 */ - 0, /* CTRL+Y, 0x19 */ - 0, /* CTRL+Z, 0x1a */ - 0, /* CTRL+[, 0x1b */ - 0, /* CTRL+\, 0x1c */ - 0, /* CTRL+], 0x1d */ - 0, /* CTRL+^, 0x1e */ - 0, /* CTRL+_, 0x1f */ - 0, /* ` ', 0x20 */ - 0, /* `!', 0x21 */ - FSRTL_WILD_CHARACTER, /* `"', 0x22 */ - 0, /* `#', 0x23 */ - 0, /* `$', 0x24 */ - 0, /* `%', 0x25 */ - 0, /* `&', 0x26 */ - 0, /* `'', 0x27 */ - 0, /* `(', 0x28 */ - 0, /* `)', 0x29 */ - FSRTL_WILD_CHARACTER, /* `*', 0x2a */ - 0, /* `+', 0x2b */ - 0, /* `,', 0x2c */ - 0, /* `-', 0x2d */ - 0, /* `.', 0x2e */ - 0, /* `/', 0x2f */ - 0, /* `0', 0x30 */ - 0, /* `1', 0x31 */ - 0, /* `2', 0x32 */ - 0, /* `3', 0x33 */ - 0, /* `4', 0x34 */ - 0, /* `5', 0x35 */ - 0, /* `6', 0x36 */ - 0, /* `7', 0x37 */ - 0, /* `8', 0x38 */ - 0, /* `9', 0x39 */ - 0, /* `:', 0x3a */ - 0, /* `;', 0x3b */ - FSRTL_WILD_CHARACTER, /* `<', 0x3c */ - 0, /* `=', 0x3d */ - FSRTL_WILD_CHARACTER, /* `>', 0x3e */ - FSRTL_WILD_CHARACTER, /* `?', 0x3f */ - FSRTL_WILD_CHARACTER, /* `@', 0x40 */ - 0, /* `A', 0x41 */ - 0, /* `B', 0x42 */ - 0, /* `C', 0x43 */ - 0, /* `D', 0x44 */ - 0, /* `E', 0x45 */ - 0, /* `F', 0x46 */ - 0, /* `G', 0x47 */ - 0, /* `H', 0x48 */ - 0, /* `I', 0x49 */ - 0, /* `J', 0x4a */ - 0, /* `K', 0x4b */ - 0, /* `L', 0x4c */ - 0, /* `M', 0x4d */ - 0, /* `N', 0x4e */ - 0, /* `O', 0x4f */ - 0, /* `P', 0x50 */ - 0, /* `Q', 0x51 */ - 0, /* `R', 0x52 */ - 0, /* `S', 0x53 */ - 0, /* `T', 0x54 */ - 0, /* `U', 0x55 */ - 0, /* `V', 0x56 */ - 0, /* `W', 0x57 */ - 0, /* `X', 0x58 */ - 0, /* `Y', 0x59 */ - 0, /* `Z', 0x5a */ - 0, /* `[', 0x5b */ - 0, /* `\', 0x5c */ - 0, /* `]', 0x5d */ - 0, /* `^', 0x5e */ - 0, /* `_', 0x5f */ - 0, /* ``', 0x60 */ - 0, /* `a', 0x61 */ - 0, /* `b', 0x62 */ - 0, /* `c', 0x63 */ - 0, /* `d', 0x64 */ - 0, /* `e', 0x65 */ - 0, /* `f', 0x66 */ - 0, /* `g', 0x67 */ - 0, /* `h', 0x68 */ - 0, /* `i', 0x69 */ - 0, /* `j', 0x6a */ - 0, /* `k', 0x6b */ - 0, /* `l', 0x6c */ - 0, /* `m', 0x6d */ - 0, /* `n', 0x6e */ - 0, /* `o', 0x6f */ - 0, /* `p', 0x70 */ - 0, /* `q', 0x71 */ - 0, /* `r', 0x72 */ - 0, /* `s', 0x73 */ - 0, /* `t', 0x74 */ - 0, /* `u', 0x75 */ - 0, /* `v', 0x76 */ - 0, /* `w', 0x77 */ - 0, /* `x', 0x78 */ - 0, /* `y', 0x79 */ - 0, /* `z', 0x7a */ - 0, /* `{', 0x7b */ - 0, /* `|', 0x7c */ - 0, /* `}', 0x7d */ - 0, /* `~', 0x7e */ - 0 /* 0x7f */ + 0, /* CTRL+@, 0x00 */ + 0, /* CTRL+A, 0x01 */ + 0, /* CTRL+B, 0x02 */ + 0, /* CTRL+C, 0x03 */ + 0, /* CTRL+D, 0x04 */ + 0, /* CTRL+E, 0x05 */ + 0, /* CTRL+F, 0x06 */ + 0, /* CTRL+G, 0x07 */ + 0, /* CTRL+H, 0x08 */ + 0, /* CTRL+I, 0x09 */ + 0, /* CTRL+J, 0x0a */ + 0, /* CTRL+K, 0x0b */ + 0, /* CTRL+L, 0x0c */ + 0, /* CTRL+M, 0x0d */ + 0, /* CTRL+N, 0x0e */ + 0, /* CTRL+O, 0x0f */ + 0, /* CTRL+P, 0x10 */ + 0, /* CTRL+Q, 0x11 */ + 0, /* CTRL+R, 0x12 */ + 0, /* CTRL+S, 0x13 */ + 0, /* CTRL+T, 0x14 */ + 0, /* CTRL+U, 0x15 */ + 0, /* CTRL+V, 0x16 */ + 0, /* CTRL+W, 0x17 */ + 0, /* CTRL+X, 0x18 */ + 0, /* CTRL+Y, 0x19 */ + 0, /* CTRL+Z, 0x1a */ + 0, /* CTRL+[, 0x1b */ + 0, /* CTRL+\, 0x1c */ + 0, /* CTRL+], 0x1d */ + 0, /* CTRL+^, 0x1e */ + 0, /* CTRL+_, 0x1f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* ` ', 0x20 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `!', 0x21 */ + FSRTL_WILD_CHARACTER, /* `"', 0x22 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `#', 0x23 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `$', 0x24 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `%', 0x25 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `&', 0x26 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `'', 0x27 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `(', 0x28 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `)', 0x29 */ + FSRTL_WILD_CHARACTER, /* `*', 0x2a */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `+', 0x2b */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `,', 0x2c */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `-', 0x2d */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `.', 0x2e */ + 0, /* `/', 0x2f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `0', 0x30 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `1', 0x31 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `2', 0x32 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `3', 0x33 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `4', 0x34 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `5', 0x35 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `6', 0x36 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `7', 0x37 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `8', 0x38 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `9', 0x39 */ + FSRTL_NTFS_LEGAL, /* `:', 0x3a */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `;', 0x3b */ + FSRTL_WILD_CHARACTER, /* `<', 0x3c */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `=', 0x3d */ + FSRTL_WILD_CHARACTER, /* `>', 0x3e */ + FSRTL_WILD_CHARACTER, /* `?', 0x3f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `@', 0x40 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `A', 0x41 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `B', 0x42 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `C', 0x43 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `D', 0x44 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `E', 0x45 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `F', 0x46 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `G', 0x47 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `H', 0x48 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `I', 0x49 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `J', 0x4a */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `K', 0x4b */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `L', 0x4c */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `M', 0x4d */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `N', 0x4e */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `O', 0x4f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `P', 0x50 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Q', 0x51 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `R', 0x52 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `S', 0x53 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `T', 0x54 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `U', 0x55 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `V', 0x56 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `W', 0x57 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `X', 0x58 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Y', 0x59 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `Z', 0x5a */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `[', 0x5b */ + 0, /* `\', 0x5c */ + FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `]', 0x5d */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `^', 0x5e */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `_', 0x5f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* ``', 0x60 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `a', 0x61 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `b', 0x62 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `c', 0x63 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `d', 0x64 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `e', 0x65 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `f', 0x66 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `g', 0x67 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `h', 0x68 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `i', 0x69 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `j', 0x6a */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `k', 0x6b */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `l', 0x6c */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `m', 0x6d */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `n', 0x6e */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `o', 0x6f */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `p', 0x70 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `q', 0x71 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `r', 0x72 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `s', 0x73 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `t', 0x74 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `u', 0x75 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `v', 0x76 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `w', 0x77 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `x', 0x78 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `y', 0x79 */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `z', 0x7a */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `{', 0x7b */ + 0, /* `|', 0x7c */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `}', 0x7d */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL, /* `~', 0x7e */ + FSRTL_FAT_LEGAL | FSRTL_HPFS_LEGAL | FSRTL_NTFS_LEGAL /* 0x7f */ }; PUCHAR EXPORTED FsRtlLegalAnsiCharacterArray = LegalAnsiCharacterArray; @@ -247,9 +251,10 @@ FsRtlDoesDbcsContainWildCards(IN PANSI_STRING Name) } /* We didn't return above...so none found */ - return FALSE; + return FALSE; } + /********************************************************************** * NAME EXPORTED * FsRtlIsDbcsInExpression@8 @@ -262,14 +267,11 @@ FsRtlDoesDbcsContainWildCards(IN PANSI_STRING Name) * * @unimplemented */ -BOOLEAN -STDCALL -FsRtlIsDbcsInExpression ( - DWORD Unknown0, - DWORD Unknown1 - ) +BOOLEAN STDCALL +FsRtlIsDbcsInExpression(IN PANSI_STRING Expression, + IN PANSI_STRING Name) { - return FALSE; + return FALSE; } @@ -287,15 +289,12 @@ FsRtlIsDbcsInExpression ( */ BOOLEAN STDCALL -FsRtlIsFatDbcsLegal ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4 - ) +FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible) { - return FALSE; + return FALSE; } @@ -311,17 +310,13 @@ FsRtlIsFatDbcsLegal ( * * @unimplemented */ -BOOLEAN -STDCALL -FsRtlIsHpfsDbcsLegal ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3, - DWORD Unknown4 - ) +BOOLEAN STDCALL +FsRtlIsHpfsDbcsLegal(IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible) { - return FALSE; + return FALSE; } /* EOF */ diff --git a/reactos/ntoskrnl/fs/filelock.c b/reactos/ntoskrnl/fs/filelock.c index 61e1bcf0cd3..be9e2108fbf 100644 --- a/reactos/ntoskrnl/fs/filelock.c +++ b/reactos/ntoskrnl/fs/filelock.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/filelock.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/filelock.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/mcb.c b/reactos/ntoskrnl/fs/mcb.c index 11eb8ad9b0c..430d747447f 100644 --- a/reactos/ntoskrnl/fs/mcb.c +++ b/reactos/ntoskrnl/fs/mcb.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/mcb.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/mcb.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/mdl.c b/reactos/ntoskrnl/fs/mdl.c index 6bbcc631ac0..1cedcba0f8a 100644 --- a/reactos/ntoskrnl/fs/mdl.c +++ b/reactos/ntoskrnl/fs/mdl.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/mdl.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/mdl.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/name.c b/reactos/ntoskrnl/fs/name.c index 80dee2c0b19..e6dd25779b8 100644 --- a/reactos/ntoskrnl/fs/name.c +++ b/reactos/ntoskrnl/fs/name.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/name.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/name.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/notify.c b/reactos/ntoskrnl/fs/notify.c index 493c60a16be..401dce9252d 100644 --- a/reactos/ntoskrnl/fs/notify.c +++ b/reactos/ntoskrnl/fs/notify.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/notify.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/notify.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include @@ -313,10 +317,8 @@ FsRtlNotifyVolumeEvent ( */ NTSTATUS STDCALL -FsRtlRegisterFileSystemFilterCallbacks ( - IN PVOID Unknown1, - IN PVOID Unknown2 - ) +FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject, + IN PFS_FILTER_CALLBACKS Callbacks) { UNIMPLEMENTED; return STATUS_NOT_IMPLEMENTED; diff --git a/reactos/ntoskrnl/fs/oplock.c b/reactos/ntoskrnl/fs/oplock.c index 4f7f810c69f..c43e144f0d3 100644 --- a/reactos/ntoskrnl/fs/oplock.c +++ b/reactos/ntoskrnl/fs/oplock.c @@ -1,9 +1,13 @@ /* $Id$ * - * reactos/ntoskrnl/fs/oplock.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/oplock.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ - + #include diff --git a/reactos/ntoskrnl/fs/pool.c b/reactos/ntoskrnl/fs/pool.c index 4cee65915a7..54513102a62 100644 --- a/reactos/ntoskrnl/fs/pool.c +++ b/reactos/ntoskrnl/fs/pool.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/pool.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/pool.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/tunnel.c b/reactos/ntoskrnl/fs/tunnel.c index 980b608dea3..908acf5b2a6 100644 --- a/reactos/ntoskrnl/fs/tunnel.c +++ b/reactos/ntoskrnl/fs/tunnel.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/tunnel.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/tunnel.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/unc.c b/reactos/ntoskrnl/fs/unc.c index 2dd07986f61..11da3c74e4d 100644 --- a/reactos/ntoskrnl/fs/unc.c +++ b/reactos/ntoskrnl/fs/unc.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/unc.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/unc.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/fs/util.c b/reactos/ntoskrnl/fs/util.c index ab7e33a7a92..d034f4bfa89 100644 --- a/reactos/ntoskrnl/fs/util.c +++ b/reactos/ntoskrnl/fs/util.c @@ -1,7 +1,11 @@ /* $Id$ * - * reactos/ntoskrnl/fs/util.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/fs/util.c + * PURPOSE: No purpose listed. * + * PROGRAMMERS: No programmer listed. */ #include @@ -157,7 +161,8 @@ DWORD STDCALL FsRtlAllocateResource (VOID) { - return 0; + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } @@ -174,13 +179,12 @@ FsRtlAllocateResource (VOID) * * @unimplemented */ -DWORD +NTSTATUS STDCALL -FsRtlBalanceReads ( - DWORD Unknown0 - ) +FsRtlBalanceReads (PDEVICE_OBJECT TargetDevice) { - return 0; + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } @@ -212,6 +216,7 @@ FsRtlCopyRead ( IN PDEVICE_OBJECT DeviceObject ) { + UNIMPLEMENTED; return FALSE; } @@ -244,6 +249,7 @@ FsRtlCopyWrite ( IN PDEVICE_OBJECT DeviceObject ) { + UNIMPLEMENTED; return FALSE; } @@ -341,12 +347,11 @@ FsRtlInsertPerFileObjectContext ( */ VOID STDCALL -FsRtlPostPagingFileStackOverflow ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2 - ) +FsRtlPostPagingFileStackOverflow(IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine) { + UNIMPLEMENTED; } @@ -364,12 +369,11 @@ FsRtlPostPagingFileStackOverflow ( */ VOID STDCALL -FsRtlPostStackOverflow ( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2 - ) +FsRtlPostStackOverflow (IN PVOID Context, + IN PKEVENT Event, + IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine) { + UNIMPLEMENTED; } diff --git a/reactos/ntoskrnl/inbv/inbv.c b/reactos/ntoskrnl/inbv/inbv.c index 6d9f1ce06c4..c16db544afb 100755 --- a/reactos/ntoskrnl/inbv/inbv.c +++ b/reactos/ntoskrnl/inbv/inbv.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/inbv/inbv.c * PURPOSE: Boot video support - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 12-07-2003 CSH Created + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES ******************************************************************/ @@ -60,6 +59,7 @@ InbvCheckBootVid(VOID) return(STATUS_SUCCESS); } + VOID STDCALL InbvAcquireDisplayOwnership(VOID) @@ -82,6 +82,7 @@ InbvDisplayString(IN PCHAR String) return FALSE; } + BOOLEAN STDCALL InbvResetDisplayParameters(ULONG SizeX, ULONG SizeY) @@ -89,6 +90,7 @@ InbvResetDisplayParameters(ULONG SizeX, ULONG SizeY) return(InbvResetDisplay()); } + VOID STDCALL INIT_FUNCTION InbvEnableBootDriver(IN BOOLEAN Enable) @@ -149,6 +151,7 @@ InbvEnableBootDriver(IN BOOLEAN Enable) } } + BOOLEAN STDCALL InbvEnableDisplayString(IN BOOLEAN Enable) @@ -217,3 +220,16 @@ InbvSolidColorFill(IN ULONG Left, IN ULONG Color) { } + +NTSTATUS +STDCALL +NtDisplayString(IN PUNICODE_STRING DisplayString) +{ + OEM_STRING OemString; + + RtlUnicodeStringToOemString(&OemString, DisplayString, TRUE); + HalDisplayString(OemString.Buffer); + RtlFreeOemString(&OemString); + + return STATUS_SUCCESS; +} diff --git a/reactos/ntoskrnl/include/internal/debug.h b/reactos/ntoskrnl/include/internal/debug.h index 4e0df358ee1..ce8c2f5d18e 100644 --- a/reactos/ntoskrnl/include/internal/debug.h +++ b/reactos/ntoskrnl/include/internal/debug.h @@ -20,7 +20,7 @@ #include #include -#include + #if defined(_MSC_VER) && (_MSC_VER < 1300) /* TODO: Verify which version the MS compiler learned the __FUNCTION__ macro */ @@ -37,8 +37,13 @@ /* Assert only on "checked" version */ #ifndef NASSERT +#ifdef CONFIG_SMP +#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); } +#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d for CPU%d\n", __FILE__,__LINE__, KeGetCurrentKPCR()->ProcessorNumber), KeBugCheck(0); } +#else #define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); } #define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); } +#endif #define assertmsg(_c_, _m_) \ if (!(_c_)) { \ diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 4a6db727346..06612b5c5a0 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -75,10 +75,13 @@ #define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ +#define X86_CR0_PE 0x00000001 /* enable Protected Mode */ #define X86_CR0_NE 0x00000020 /* enable native FPU error reporting */ #define X86_CR0_TS 0x00000008 /* enable exception on FPU instruction for task switch */ #define X86_CR0_EM 0x00000004 /* enable FPU emulation (disable FPU) */ #define X86_CR0_MP 0x00000002 /* enable FPU monitoring */ +#define X86_CR0_WP 0x00010000 /* enable Write Protect (copy on write) */ +#define X86_CR0_PG 0x80000000 /* enable Paging */ #define X86_CR4_PAE 0x00000020 /* enable physical address extensions */ #define X86_CR4_PGE 0x00000080 /* enable global pages */ @@ -88,6 +91,7 @@ #define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */ #define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */ #define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */ +#define X86_FEATURE_SYSCALL 0x00000800 /* SYSCALL/SYSRET support present */ #define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */ #define X86_FEATURE_MMX 0x00800000 /* MMX extension present */ #define X86_FEATURE_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions present */ @@ -192,7 +196,7 @@ VOID KeFreeGdtSelector(ULONG Entry); VOID NtEarlyInitVdm(VOID); -#ifdef MP +#ifdef CONFIG_SMP #define LOCK "lock ; " #else #define LOCK "" @@ -207,8 +211,20 @@ NtEarlyInitVdm(VOID); __asm__("movl %%cr3,%0\n\t" : "=d" (X)); #define Ke386SetPageTableDirectory(X) \ __asm__("movl %0,%%cr3\n\t" \ - : /* no outputs */ \ - : "r" (X)); + : /* no outputs */ \ + : "r" (X)); +#define Ke386SetFileSelector(X) \ + __asm__("movl %0,%%cr3\n\t" \ + : /* no outputs */ \ + : "r" (X)); +#define Ke386SetLocalDescriptorTable(X) \ + __asm__("lldt %0\n\t" \ + : /* no outputs */ \ + : "m" (X)); +#define Ke386SetGlobalDescriptorTable(X) \ + __asm__("lgdt %0\n\t" \ + : /* no outputs */ \ + : "m" (X)); #define Ke386SaveFlags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) #define Ke386RestoreFlags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") diff --git a/reactos/ntoskrnl/include/internal/i386/mm.h b/reactos/ntoskrnl/include/internal/i386/mm.h index d045379fe6e..06a06a10b48 100644 --- a/reactos/ntoskrnl/include/internal/i386/mm.h +++ b/reactos/ntoskrnl/include/internal/i386/mm.h @@ -23,14 +23,10 @@ #endif -#ifdef __3GB__ -#define KERNEL_BASE (0xC0000000) -#else -#define KERNEL_BASE (0x80000000) -#endif - #ifndef __ASM__ +#define KERNEL_BASE (ULONG)MmSystemRangeStart + #if defined(__GNUC__) #define FLUSH_TLB { \ @@ -58,7 +54,6 @@ struct _EPROCESS; PULONG MmGetPageDirectory(VOID); -VOID MiEnablePAE(PVOID* LastKernelAddress); diff --git a/reactos/ntoskrnl/include/internal/i386/ps.h b/reactos/ntoskrnl/include/internal/i386/ps.h index 6fb73b77d7f..f6cf2dc6bc7 100644 --- a/reactos/ntoskrnl/include/internal/i386/ps.h +++ b/reactos/ntoskrnl/include/internal/i386/ps.h @@ -27,6 +27,7 @@ #define KTHREAD_TEB 0x20 #define KTHREAD_KERNEL_STACK 0x28 #define KTHREAD_NPX_STATE 0x31 +#define KTHREAD_PENDING_USER_APC 0x34 + 0x16 #define KTHREAD_APCSTATE_PROCESS 0x44 #define KTHREAD_SERVICE_TABLE 0xDC #define KTHREAD_PREVIOUS_MODE 0x137 @@ -248,7 +249,7 @@ typedef struct _KPCR { #ifndef __USE_W32API -#ifdef MP +#ifdef CONFIG_SMP static inline PKPCR KeGetCurrentKPCR(VOID) { diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index c624f673638..823c153c197 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -500,6 +500,17 @@ IopMarkLastReinitializeDriver(VOID); VOID FASTCALL IopReinitializeDrivers(VOID); + +/* plugplay.c */ + +NTSTATUS INIT_FUNCTION +IopInitPlugPlayEvents(VOID); + +NTSTATUS +IopQueueTargetDeviceEvent(const GUID *Guid, + PUNICODE_STRING DeviceIds); + + /* pnpmgr.c */ NTSTATUS diff --git a/reactos/ntoskrnl/include/internal/kd.h b/reactos/ntoskrnl/include/internal/kd.h index d05f2b939ef..4594dd47ee4 100644 --- a/reactos/ntoskrnl/include/internal/kd.h +++ b/reactos/ntoskrnl/include/internal/kd.h @@ -109,21 +109,20 @@ VOID KdInitializeMda(VOID); VOID KdPrintMda(PCH pch); #if !defined(KDBG) && !defined(DBG) -# define KDB_LOADUSERMODULE_HOOK(LDRMOD) do { } while (0) -# define KDB_DELETEPROCESS_HOOK(PROCESS) do { } while (0) -# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) do { } while (0) -# define KDB_UNLOADDRIVER_HOOK(MODULE) do { } while (0) -# define KDB_LOADERINIT_HOOK(NTOS, HAL) do { } while (0) -# define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) do { } while (0) -# define KDB_CREATE_THREAD_HOOK(CONTEXT) do { } while (0) +# define KDB_LOADUSERMODULE_HOOK(LDRMOD) do { } while (0) +# define KDB_DELETEPROCESS_HOOK(PROCESS) do { } while (0) +# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) do { } while (0) +# define KDB_UNLOADDRIVER_HOOK(MODULE) do { } while (0) +# define KDB_LOADERINIT_HOOK(NTOS, HAL) do { } while (0) +# define KDB_SYMBOLFILE_HOOK(FILENAME) do { } while (0) +# define KDB_CREATE_THREAD_HOOK(CONTEXT) do { } while (0) #else -# define KDB_LOADUSERMODULE_HOOK(LDRMOD) KdbSymLoadUserModuleSymbols(LDRMOD) -# define KDB_DELETEPROCESS_HOOK(PROCESS) KdbSymFreeProcessSymbols(PROCESS) -# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) KdbSymLoadDriverSymbols(FILENAME, MODULE) -# define KDB_UNLOADDRIVER_HOOK(MODULE) KdbSymUnloadDriverSymbols(MODULE) -# define KDB_LOADERINIT_HOOK(NTOS, HAL) KdbSymInit(NTOS, HAL) -# define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) \ - KdbSymProcessSymbolFile(LOADBASE, FILENAME, LENGTH) +# define KDB_LOADUSERMODULE_HOOK(LDRMOD) KdbSymLoadUserModuleSymbols(LDRMOD) +# define KDB_DELETEPROCESS_HOOK(PROCESS) KdbSymFreeProcessSymbols(PROCESS) +# define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) KdbSymLoadDriverSymbols(FILENAME, MODULE) +# define KDB_UNLOADDRIVER_HOOK(MODULE) KdbSymUnloadDriverSymbols(MODULE) +# define KDB_LOADERINIT_HOOK(NTOS, HAL) KdbSymInit(NTOS, HAL) +# define KDB_SYMBOLFILE_HOOK(FILENAME) KdbSymProcessBootSymbols(FILENAME) /*#define KDB_CREATE_THREAD_HOOK(CONTEXT) \ KdbCreateThreadHook(CONTEXT) */ @@ -141,9 +140,7 @@ VOID KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject); VOID -KdbSymProcessSymbolFile(IN PVOID ModuleLoadBase, - IN PCHAR FileName, - IN ULONG Length); +KdbSymProcessBootSymbols(IN PCHAR FileName); VOID KdbSymInit(IN PMODULE_TEXT_SECTION NtoskrnlTextSection, diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 940db4e136b..14ba678b188 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -58,12 +58,62 @@ KiIpiSendRequest(ULONG TargetSet, ULONG IpiRequest); VOID -KeIpiGenericCall(VOID STDCALL (*WorkerRoutine)(PVOID), +KeIpiGenericCall(VOID (STDCALL *WorkerRoutine)(PVOID), PVOID Argument); /* next file ***************************************************************/ +typedef struct _KPROCESS_PROFILE +/* + * List of the profile data structures associated with a process. + */ +{ + LIST_ENTRY ProfileListHead; + LIST_ENTRY ListEntry; + HANDLE Pid; +} KPROCESS_PROFILE, *PKPROCESS_PROFILE; +typedef struct _KPROFILE +/* + * Describes a contiguous region of process memory that is being profiled. + */ +{ + CSHORT Type; + CSHORT Name; + + /* Entry in the list of profile data structures for this process. */ + LIST_ENTRY ListEntry; + + /* Base of the region being profiled. */ + PVOID Base; + + /* Size of the region being profiled. */ + ULONG Size; + + /* Shift of offsets from the region to buckets in the profiling buffer. */ + ULONG BucketShift; + + /* MDL which described the buffer that receives profiling data. */ + struct _MDL *BufferMdl; + + /* System alias for the profiling buffer. */ + PULONG Buffer; + + /* Size of the buffer for profiling data. */ + ULONG BufferSize; + + /* + * Mask of processors for which profiling data should be collected. + * Currently unused. + */ + ULONG ProcessorMask; + + /* TRUE if profiling has been started for this region. */ + BOOLEAN Started; + + /* Pointer (and reference) to the process which is being profiled. */ + struct _EPROCESS *Process; +} KPROFILE, *PKPROFILE; VOID STDCALL DbgBreakPointNoBugCheck(VOID); @@ -81,6 +131,14 @@ KeProfileInterruptWithSource( IN KPROFILE_SOURCE Source ); +VOID KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip); +VOID KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip); +VOID KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile); +VOID KiInsertProfile(PKPROFILE Profile); +VOID KiRemoveProfile(PKPROFILE Profile); +VOID STDCALL KiDeleteProfile(PVOID ObjectBody); + + VOID STDCALL KeUpdateSystemTime(PKTRAP_FRAME TrapFrame, KIRQL Irql); VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql); @@ -89,7 +147,7 @@ VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID); VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql); VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID); -BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr); +BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment); VOID STDCALL KeExpireTimers(PKDPC Apc, PVOID Arg1, PVOID Arg2, diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index cfb3faeb7d0..cf40567a127 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -158,15 +158,18 @@ typedef struct _SECTION_OBJECT typedef struct _SECTION_OBJECT *PSECTION_OBJECT; +typedef struct _EPROCESS_QUOTA_ENTRY { + ULONG Usage; + ULONG Limit; + ULONG Peak; + ULONG Return; +} EPROCESS_QUOTA_ENTRY, *PEPROCESS_QUOTA_ENTRY; + typedef struct _EPROCESS_QUOTA_BLOCK { -KSPIN_LOCK QuotaLock; -ULONG ReferenceCount; -ULONG QuotaPeakPoolUsage[2]; -ULONG QuotaPoolUsage[2]; -ULONG QuotaPoolLimit[2]; -ULONG PeakPagefileUsage; -ULONG PagefileUsage; -ULONG PagefileLimit; + EPROCESS_QUOTA_ENTRY QuotaEntry[3]; + LIST_ENTRY QuotaList; + ULONG ReferenceCount; + ULONG ProcessCount; } EPROCESS_QUOTA_BLOCK, *PEPROCESS_QUOTA_BLOCK; /* @@ -293,7 +296,7 @@ typedef struct _MM_PAGEOP * These fields are used to identify the operation if it is against a * virtual memory area. */ - ULONG Pid; + HANDLE Pid; PVOID Address; /* * These fields are used to identify the operation if it is against a @@ -450,9 +453,9 @@ VOID MmBuildMdlFromPages(PMDL Mdl, PULONG Pages); VOID MiShutdownMemoryManager(VOID); -VOID MmInit1(ULONG FirstKernelPhysAddress, - ULONG LastKernelPhysAddress, - ULONG LastKernelAddress, +VOID MmInit1(ULONG_PTR FirstKernelPhysAddress, + ULONG_PTR LastKernelPhysAddress, + ULONG_PTR LastKernelAddress, PADDRESS_RANGE BIOSMemoryMap, ULONG AddressRangeCount, ULONG MaxMemInMeg); @@ -504,11 +507,11 @@ NTSTATUS MmPageFault(ULONG Cs, /* mm.c **********************************************************************/ NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode, - ULONG Address, + ULONG_PTR Address, BOOLEAN FromMdl); NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode, - ULONG Address, + ULONG_PTR Address, BOOLEAN FromMdl); /* anonmem.c *****************************************************************/ @@ -548,8 +551,6 @@ PVOID ExAllocatePage(VOID); VOID ExUnmapPage(PVOID Addr); -VOID MiInitKernelMap(VOID); - PVOID ExAllocatePageWithPhysPage(PFN_TYPE Page); NTSTATUS MiCopyFromUserPage(PFN_TYPE Page, PVOID SourceAddress); @@ -568,10 +569,10 @@ VOID MmReleasePageOp(PMM_PAGEOP PageOp); PMM_PAGEOP -MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, +MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address, PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First); PMM_PAGEOP -MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, +MmCheckForPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address, PMM_SECTION_SEGMENT Segment, ULONG Offset); VOID MmInitializePageOp(VOID); @@ -630,10 +631,10 @@ VOID MmUnlockPage(PFN_TYPE Page); ULONG MmGetLockCountPage(PFN_TYPE Page); -PVOID MmInitializePageList(PVOID FirstPhysKernelAddress, - PVOID LastPhysKernelAddress, +PVOID MmInitializePageList(ULONG_PTR FirstPhysKernelAddress, + ULONG_PTR LastPhysKernelAddress, ULONG MemorySizeInPages, - ULONG LastKernelBase, + ULONG_PTR LastKernelBase, PADDRESS_RANGE BIOSMemoryMap, ULONG AddressRangeCount); @@ -646,6 +647,12 @@ NTSTATUS MmInitZeroPageThread(VOID); /* i386/page.c *********************************************************/ +PVOID MmCreateHyperspaceMapping(PFN_TYPE Page); + +PFN_TYPE MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE Page); + +PFN_TYPE MmDeleteHyperspaceMapping(PVOID Address); + NTSTATUS MmCreateVirtualMappingForKernel(PVOID Address, ULONG flProtect, PPFN_TYPE Pages, @@ -694,6 +701,12 @@ VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address); PFN_TYPE MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry); +LONG MmAllocPagesSpecifyRange(ULONG Consumer, + PHYSICAL_ADDRESS LowestAddress, + PHYSICAL_ADDRESS HighestAddress, + ULONG NumberOfPages, + PPFN_TYPE Pages); + VOID MmDereferencePage(PFN_TYPE Page); VOID MmReferencePage(PFN_TYPE Page); diff --git a/reactos/ntoskrnl/include/internal/module.h b/reactos/ntoskrnl/include/internal/module.h index 9c60eba1ca5..57ee469f0ab 100644 --- a/reactos/ntoskrnl/include/internal/module.h +++ b/reactos/ntoskrnl/include/internal/module.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include typedef struct _MODULE_TEXT_SECTION { @@ -15,7 +15,7 @@ typedef struct _MODULE_TEXT_SECTION PWCH Name; PIMAGE_OPTIONAL_HEADER OptionalHeader; #if defined(DBG) || defined(KDBG) - IMAGE_SYMBOL_INFO SymbolInfo; + PROSSYM_INFO RosSymInfo; #endif /* KDBG */ } MODULE_TEXT_SECTION, *PMODULE_TEXT_SECTION; diff --git a/reactos/ntoskrnl/include/internal/ntoskrnl.h b/reactos/ntoskrnl/include/internal/ntoskrnl.h index 1bceac403cc..a98537fe3c0 100644 --- a/reactos/ntoskrnl/include/internal/ntoskrnl.h +++ b/reactos/ntoskrnl/include/internal/ntoskrnl.h @@ -37,9 +37,13 @@ extern IDT_DESCRIPTOR KiIdt[256]; //extern GDT_DESCRIPTOR KiGdt[256]; -VOID NtInitializeEventImplementation(VOID); -VOID NtInit(VOID); - +VOID ExpInitializeEventImplementation(VOID); +VOID ExpInitializeEventImplementation(VOID); +VOID ExpInitializeEventPairImplementation(VOID); +VOID ExpInitializeSemaphoreImplementation(VOID); +VOID ExpInitializeMutantImplementation(VOID); +VOID ExpInitializeTimerImplementation(VOID); +VOID ExpInitializeProfileImplementation(VOID); /* * Initalization functions (called once by main()) */ diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 7c0548d0e0a..59255bac675 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -24,6 +24,162 @@ typedef struct typedef PVOID POBJECT; + +typedef struct _OBJECT_TYPE +{ + /* + * PURPOSE: Tag to be used when allocating objects of this type + */ + ULONG Tag; + + /* + * PURPOSE: Name of the type + */ + UNICODE_STRING TypeName; + + /* + * PURPOSE: Total number of objects of this type + */ + ULONG TotalObjects; + + /* + * PURPOSE: Total number of handles of this type + */ + ULONG TotalHandles; + + /* + * PURPOSE: Peak objects of this type + */ + ULONG PeakObjects; + + /* + * PURPOSE: Peak handles of this type + */ + ULONG PeakHandles; + + /* + * PURPOSE: Paged pool charge + */ + ULONG PagedPoolCharge; + + /* + * PURPOSE: Nonpaged pool charge + */ + ULONG NonpagedPoolCharge; + + /* + * PURPOSE: Mapping of generic access rights + */ + PGENERIC_MAPPING Mapping; + + /* + * PURPOSE: Dumps the object + * NOTE: To be defined + */ + VOID STDCALL_FUNC (*Dump)(VOID); + + /* + * PURPOSE: Opens the object + * NOTE: To be defined + */ + VOID STDCALL_FUNC (*Open)(VOID); + + /* + * PURPOSE: Called to close an object if OkayToClose returns true + */ + VOID STDCALL_FUNC (*Close)(PVOID ObjectBody, + ULONG HandleCount); + + /* + * PURPOSE: Called to delete an object when the last reference is removed + */ + VOID STDCALL_FUNC (*Delete)(PVOID ObjectBody); + + /* + * PURPOSE: Called when an open attempts to open a file apparently + * residing within the object + * RETURNS + * STATUS_SUCCESS NextObject was found + * STATUS_UNSUCCESSFUL NextObject not found + * STATUS_REPARSE Path changed, restart parsing the path + */ + NTSTATUS STDCALL_FUNC (*Parse)(PVOID ParsedObject, + PVOID *NextObject, + PUNICODE_STRING FullPath, + PWSTR *Path, + ULONG Attributes); + + /* + * PURPOSE: Called to set, query, delete or assign a security-descriptor + * to the object + * RETURNS + * STATUS_SUCCESS NextObject was found + */ + NTSTATUS STDCALL_FUNC (*Security)(PVOID ObjectBody, + SECURITY_OPERATION_CODE OperationCode, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR SecurityDescriptor, + PULONG BufferLength); + + /* + * PURPOSE: Called to query the name of the object + * RETURNS + * STATUS_SUCCESS NextObject was found + */ + NTSTATUS STDCALL_FUNC (*QueryName)(PVOID ObjectBody, + POBJECT_NAME_INFORMATION ObjectNameInfo, + ULONG Length, + PULONG ReturnLength); + + /* + * PURPOSE: Called when a process asks to close the object + */ + VOID STDCALL_FUNC (*OkayToClose)(VOID); + + NTSTATUS STDCALL_FUNC (*Create)(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes); + + VOID STDCALL_FUNC (*DuplicationNotify)(PEPROCESS DuplicateTo, + PEPROCESS DuplicateFrom, + PVOID Object); +} OBJECT_TYPE; + + + +typedef struct _OBJECT_HEADER +/* + * PURPOSE: Header for every object managed by the object manager + */ +{ + UNICODE_STRING Name; + LIST_ENTRY Entry; + LONG RefCount; + LONG HandleCount; + BOOLEAN CloseInProcess; + BOOLEAN Permanent; + BOOLEAN Inherit; + struct _DIRECTORY_OBJECT* Parent; + POBJECT_TYPE ObjectType; + PSECURITY_DESCRIPTOR SecurityDescriptor; + + /* + * PURPOSE: Object type + * NOTE: This overlaps the first member of the object body + */ + CSHORT Type; + + /* + * PURPOSE: Object size + * NOTE: This overlaps the second member of the object body + */ + CSHORT Size; + + +} OBJECT_HEADER, *POBJECT_HEADER; + + typedef struct _DIRECTORY_OBJECT { CSHORT Type; @@ -141,6 +297,10 @@ VOID STDCALL ObQueryDeviceMapInformation(PEPROCESS Process, PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo); +VOID FASTCALL +ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent); + + /* Security descriptor cache functions */ NTSTATUS @@ -159,5 +319,195 @@ ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) VOID ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor); +/* Secure object information functions */ + +typedef struct _CAPTURED_OBJECT_ATTRIBUTES +{ + HANDLE RootDirectory; + ULONG Attributes; + PSECURITY_DESCRIPTOR SecurityDescriptor; + /* PVOID SecurityQualityOfService; */ +} CAPTURED_OBJECT_ATTRIBUTES, *PCAPTURED_OBJECT_ATTRIBUTES; + +NTSTATUS +ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL, + OUT PUNICODE_STRING ObjectName OPTIONAL); + +VOID +ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL, + IN PUNICODE_STRING ObjectName OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN BOOLEAN CaptureIfKernel); + +/* object information classes */ + +#define ICIF_QUERY 0x1 +#define ICIF_SET 0x2 +#define ICIF_QUERY_SIZE_VARIABLE 0x4 +#define ICIF_SET_SIZE_VARIABLE 0x8 +#define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE) + +typedef struct _INFORMATION_CLASS_INFO +{ + ULONG RequiredSizeQUERY; + ULONG RequiredSizeSET; + ULONG AlignmentSET; + ULONG AlignmentQUERY; + ULONG Flags; +} INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO; + +#define ICI_SQ_SAME(Size, Alignment, Flags) \ + { Size, Size, Alignment, Alignment, Flags } + +#define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \ + { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags } + +#define CheckInfoClass(Class, BufferLen, ClassList, StatusVar, Mode) \ + do { \ + if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \ + { \ + if(!(ClassList[Class].Flags & ICIF_##Mode)) \ + { \ + *(StatusVar) = STATUS_INVALID_INFO_CLASS; \ + } \ + else if(ClassList[Class].RequiredSize##Mode > 0 && \ + (BufferLen) != ClassList[Class].RequiredSize##Mode) \ + { \ + if((!(ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \ + (BufferLen) != ClassList[Class].RequiredSize##Mode) || \ + ((ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \ + (BufferLen) < ClassList[Class].RequiredSize##Mode)) \ + { \ + *(StatusVar) = STATUS_INFO_LENGTH_MISMATCH; \ + } \ + } \ + } \ + else \ + { \ + *(StatusVar) = STATUS_INVALID_INFO_CLASS; \ + } \ + } while(0) + + +#define GetInfoClassAlignment(Class, ClassList, AlignmentVar, Mode) \ + do { \ + if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \ + { \ + *(AlignmentVar) = ClassList[Class].Alignment##Mode; \ + } \ + else \ + { \ + *(AlignmentVar) = sizeof(ULONG); \ + } \ + } while(0) + +#define ProbeQueryInfoBuffer(Buffer, BufferLen, Alignment, RetLen, PrevMode, StatusVar) \ + do { \ + if(PrevMode == UserMode) \ + { \ + _SEH_TRY \ + { \ + ProbeForWrite(Buffer, \ + BufferLen, \ + Alignment); \ + if(RetLen != NULL) \ + { \ + ProbeForWrite(RetLen, \ + sizeof(ULONG), \ + 1); \ + } \ + } \ + _SEH_HANDLE \ + { \ + *(StatusVar) = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(*(StatusVar))) \ + { \ + DPRINT1("ProbeQueryInfoBuffer failed: 0x%x\n", *(StatusVar)); \ + return *(StatusVar); \ + } \ + } \ + } while(0) + +#define ProbeSetInfoBuffer(Buffer, BufferLen, Alignment, PrevMode, StatusVar) \ + do { \ + if(PrevMode == UserMode) \ + { \ + _SEH_TRY \ + { \ + ProbeForRead(Buffer, \ + BufferLen, \ + Alignment); \ + } \ + _SEH_HANDLE \ + { \ + *(StatusVar) = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(*(StatusVar))) \ + { \ + DPRINT1("ProbeAllInfoBuffer failed: 0x%x\n", *(StatusVar)); \ + return *(StatusVar); \ + } \ + } \ + } while(0) + +#define DefaultSetInfoBufferCheck(Class, ClassList, Buffer, BufferLen, PrevMode, StatusVar) \ + do { \ + ULONG _Alignment; \ + /* get the preferred alignment for the information class or return */ \ + /* default alignment in case the class doesn't exist */ \ + GetInfoClassAlignment(Class, \ + ClassList, \ + &_Alignment, \ + SET); \ + \ + /* probe the ENTIRE buffers and return on failure */ \ + ProbeSetInfoBuffer(Buffer, \ + BufferLen, \ + _Alignment, \ + PrevMode, \ + StatusVar); \ + \ + /* validate information class index and check buffer size */ \ + CheckInfoClass(Class, \ + BufferLen, \ + ClassList, \ + StatusVar, \ + SET); \ + } while(0) + +#define DefaultQueryInfoBufferCheck(Class, ClassList, Buffer, BufferLen, RetLen, PrevMode, StatusVar) \ + do { \ + ULONG _Alignment; \ + /* get the preferred alignment for the information class or return */ \ + /* alignment in case the class doesn't exist */ \ + GetInfoClassAlignment(Class, \ + ClassList, \ + &_Alignment, \ + QUERY); \ + \ + /* probe the ENTIRE buffers and return on failure */ \ + ProbeQueryInfoBuffer(Buffer, \ + BufferLen, \ + _Alignment, \ + RetLen, \ + PrevMode, \ + StatusVar); \ + \ + /* validate information class index and check buffer size */ \ + CheckInfoClass(Class, \ + BufferLen, \ + ClassList, \ + StatusVar, \ + QUERY); \ + } while(0) #endif /* __INCLUDE_INTERNAL_OBJMGR_H */ diff --git a/reactos/ntoskrnl/include/internal/pool.h b/reactos/ntoskrnl/include/internal/pool.h index b1f62671cdc..888d590cea2 100644 --- a/reactos/ntoskrnl/include/internal/pool.h +++ b/reactos/ntoskrnl/include/internal/pool.h @@ -45,7 +45,7 @@ extern ULONG MmPagedPoolSize; */ #define MM_CACHE_LINE_SIZE 32 -#define MM_ROUND_UP(x,s) ((PVOID)(((ULONG)(x)+(s)-1) & ~((s)-1))) -#define MM_ROUND_DOWN(x,s) ((PVOID)(((ULONG)(x)) & ~((s)-1))) +#define MM_ROUND_UP(x,s) ((PVOID)(((ULONG_PTR)(x)+(s)-1) & ~((ULONG_PTR)(s)-1))) +#define MM_ROUND_DOWN(x,s) ((PVOID)(((ULONG_PTR)(x)) & ~((ULONG_PTR)(s)-1))) #endif /* __INTERNAL_POOL_H */ diff --git a/reactos/ntoskrnl/include/internal/port.h b/reactos/ntoskrnl/include/internal/port.h index fada5b8365b..c987f67c811 100644 --- a/reactos/ntoskrnl/include/internal/port.h +++ b/reactos/ntoskrnl/include/internal/port.h @@ -65,7 +65,7 @@ LpcRequestPort (PEPORT Port, NTSTATUS STDCALL LpcSendTerminationPort (PEPORT Port, - TIME CreationTime); + LARGE_INTEGER CreationTime); /* EPORT.Type */ @@ -134,13 +134,13 @@ NiCreatePort (PVOID ObjectBody, /* Code in ntoskrnl/lpc/port.c */ NTSTATUS STDCALL -NiInitializePort (IN OUT PEPORT Port, +LpcpInitializePort (IN OUT PEPORT Port, IN USHORT Type, IN PEPORT Parent OPTIONAL); NTSTATUS -NiInitPort (VOID); +LpcpInitSystem (VOID); -extern OBJECT_TYPE LpcPortObjectType; +extern POBJECT_TYPE LpcPortObjectType; extern ULONG LpcpNextMessageId; extern FAST_MUTEX LpcpLock; diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index fdf1893f599..28f47535dcf 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -147,10 +147,10 @@ typedef struct _KTHREAD #ifndef __USE_W32API typedef struct { - PACCESS_TOKEN Token; - BOOLEAN CopyOnOpen; - BOOLEAN EffectiveOnly; - SECURITY_IMPERSONATION_LEVEL Level; + PACCESS_TOKEN Token; + BOOLEAN CopyOnOpen; + BOOLEAN EffectiveOnly; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; } PS_IMPERSONATION_INFORMATION, *PPS_IMPERSONATION_INFORMATION; #endif @@ -160,11 +160,11 @@ typedef struct _ETHREAD { KTHREAD Tcb; union { - TIME CreateTime; + LARGE_INTEGER CreateTime; UCHAR NestedFaultCount:2; UCHAR ApcNeeded:1; }; - TIME ExitTime; + LARGE_INTEGER ExitTime; LIST_ENTRY LpcReplyChain; NTSTATUS ExitStatus; PVOID OfsChain; @@ -316,18 +316,14 @@ struct _EPROCESS ULONG LockCount; /* 07C */ /* Time of process creation. */ -#ifdef __USE_W32API - LARGE_INTEGER CreateTime; /* 080 */ -#else - TIME CreateTime; /* 080 */ -#endif + LARGE_INTEGER CreateTime; /* 080 */ /* Time of process exit. */ - TIME ExitTime; /* 088 */ + LARGE_INTEGER ExitTime; /* 088 */ /* Unknown. */ PKTHREAD LockOwner; /* 090 */ /* Process id. */ - ULONG UniqueProcessId; /* 094 */ + HANDLE UniqueProcessId; /* 094 */ /* Unknown. */ LIST_ENTRY ActiveProcessLinks; /* 098 */ /* Unknown. */ @@ -532,7 +528,7 @@ VOID PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason); VOID -PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus); +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment); VOID PsApplicationProcessorInit(VOID); VOID diff --git a/reactos/ntoskrnl/include/internal/safe.h b/reactos/ntoskrnl/include/internal/safe.h index 340811c306e..692b4282bdb 100644 --- a/reactos/ntoskrnl/include/internal/safe.h +++ b/reactos/ntoskrnl/include/internal/safe.h @@ -10,7 +10,15 @@ NTSTATUS STDCALL MmCopyToCaller(PVOID Dest, const VOID *Src, ULONG NumberOfBytes); NTSTATUS -RtlCaptureUnicodeString(PUNICODE_STRING Dest, - PUNICODE_STRING UnsafeSrc); +RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest, + IN KPROCESSOR_MODE CurrentMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN PUNICODE_STRING UnsafeSrc); + +VOID +RtlReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, + IN KPROCESSOR_MODE CurrentMode, + IN BOOLEAN CaptureIfKernel); #endif /* __NTOSKRNL_INCLUDE_INTERNAL_SAFE_Hb */ diff --git a/reactos/ntoskrnl/include/internal/se.h b/reactos/ntoskrnl/include/internal/se.h index a4c82c4893b..8d3e269906a 100644 --- a/reactos/ntoskrnl/include/internal/se.h +++ b/reactos/ntoskrnl/include/internal/se.h @@ -111,8 +111,8 @@ BOOLEAN SepInitDACLs(VOID); BOOLEAN SepInitSDs(VOID); NTSTATUS STDCALL -SepCreateImpersonationTokenDacl(PACCESS_TOKEN Token, - PACCESS_TOKEN PrimaryToken, +SepCreateImpersonationTokenDacl(PTOKEN Token, + PTOKEN PrimaryToken, PACL *Dacl); VOID SepInitializeTokenImplementation(VOID); @@ -142,7 +142,7 @@ SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, ULONG a); BOOLEAN -SepPrivilegeCheck(PACCESS_TOKEN Token, +SepPrivilegeCheck(PTOKEN Token, PLUID_AND_ATTRIBUTES Privileges, ULONG PrivilegeCount, ULONG PrivilegeControl, diff --git a/reactos/ntoskrnl/include/ntoskrnl.h b/reactos/ntoskrnl/include/ntoskrnl.h index e49245a77e8..9f86d423f2e 100755 --- a/reactos/ntoskrnl/include/ntoskrnl.h +++ b/reactos/ntoskrnl/include/ntoskrnl.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ #include #include #include -#include #include "internal/xhal.h" #include #include @@ -63,4 +63,6 @@ #include #include +#include + #endif /* INCLUDE_NTOSKRNL_H */ diff --git a/reactos/ntoskrnl/io/adapter.c b/reactos/ntoskrnl/io/adapter.c index bfcf9279c1f..59907aaf947 100644 --- a/reactos/ntoskrnl/io/adapter.c +++ b/reactos/ntoskrnl/io/adapter.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/adapter.c * PURPOSE: DMA handling - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/arcname.c b/reactos/ntoskrnl/io/arcname.c index 87ad99f19f1..d47003e6780 100644 --- a/reactos/ntoskrnl/io/arcname.c +++ b/reactos/ntoskrnl/io/arcname.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/arcname.c - * PURPOSE: creates ARC names for boot devices - * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * PURPOSE: Creates ARC names for boot devices + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ @@ -224,32 +207,32 @@ IopCheckCdromDevices(PULONG DeviceNumber) NULL, NULL); - Status = NtOpenFile(&Handle, + Status = ZwOpenFile(&Handle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, 0, 0); - DPRINT("NtOpenFile() DeviceNumber %lu Status %lx\n", i, Status); + DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status); if (NT_SUCCESS(Status)) { - Status = NtQueryVolumeInformationFile(Handle, + Status = ZwQueryVolumeInformationFile(Handle, &IoStatusBlock, FileFsVolume, FS_VOLUME_BUFFER_SIZE, FileFsVolumeInformation); - DPRINT("NtQueryVolumeInformationFile() Status %lx\n", Status); + DPRINT("ZwQueryVolumeInformationFile() Status %lx\n", Status); if (NT_SUCCESS(Status)) { DPRINT("VolumeLabel: '%S'\n", FileFsVolume->VolumeLabel); if (_wcsicmp(FileFsVolume->VolumeLabel, L"REACTOS") == 0) { - NtClose(Handle); + ZwClose(Handle); *DeviceNumber = i; return(STATUS_SUCCESS); } } - NtClose(Handle); + ZwClose(Handle); } #endif @@ -269,17 +252,17 @@ IopCheckCdromDevices(PULONG DeviceNumber) NULL, NULL); - Status = NtOpenFile(&Handle, + Status = ZwOpenFile(&Handle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, 0, 0); - DPRINT("NtOpenFile() DeviceNumber %lu Status %lx\n", i, Status); + DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status); if (NT_SUCCESS(Status)) { DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i); - NtClose(Handle); + ZwClose(Handle); *DeviceNumber = i; return(STATUS_SUCCESS); } @@ -300,17 +283,17 @@ IopCheckCdromDevices(PULONG DeviceNumber) NULL, NULL); - Status = NtOpenFile(&Handle, + Status = ZwOpenFile(&Handle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, 0, 0); - DPRINT("NtOpenFile() DeviceNumber %lu Status %lx\n", i, Status); + DPRINT("ZwOpenFile() DeviceNumber %lu Status %lx\n", i, Status); if (NT_SUCCESS(Status)) { DPRINT("Found ntoskrnl.exe on Cdrom%lu\n", i); - NtClose(Handle); + ZwClose(Handle); *DeviceNumber = i; return(STATUS_SUCCESS); } @@ -424,14 +407,14 @@ IoCreateSystemRootLink(PCHAR ParameterLine) NULL, NULL); - Status = NtOpenSymbolicLinkObject(&Handle, + Status = ZwOpenSymbolicLinkObject(&Handle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&BootPath); RtlFreeUnicodeString(&DeviceName); - CPRINT("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n", + CPRINT("ZwOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n", &ArcName, Status); RtlFreeUnicodeString(&ArcName); @@ -440,15 +423,15 @@ IoCreateSystemRootLink(PCHAR ParameterLine) } RtlFreeUnicodeString(&ArcName); - Status = NtQuerySymbolicLinkObject(Handle, + Status = ZwQuerySymbolicLinkObject(Handle, &DeviceName, &Length); - NtClose (Handle); + ZwClose (Handle); if (!NT_SUCCESS(Status)) { RtlFreeUnicodeString(&BootPath); RtlFreeUnicodeString(&DeviceName); - CPRINT("NtQuerySymbolicObject() failed (Status %x)\n", + CPRINT("ZwQuerySymbolicObject() failed (Status %x)\n", Status); return(Status); @@ -483,7 +466,7 @@ IoCreateSystemRootLink(PCHAR ParameterLine) NULL, NULL); - Status = NtOpenFile(&Handle, + Status = ZwOpenFile(&Handle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, @@ -491,12 +474,12 @@ IoCreateSystemRootLink(PCHAR ParameterLine) 0); if (!NT_SUCCESS(Status)) { - CPRINT("NtOpenFile() failed to open '\\SystemRoot' (Status %x)\n", + CPRINT("ZwOpenFile() failed to open '\\SystemRoot' (Status %x)\n", Status); return(Status); } - NtClose(Handle); + ZwClose(Handle); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/io/bootlog.c b/reactos/ntoskrnl/io/bootlog.c index 9753dad9ca6..71dc17b194a 100644 --- a/reactos/ntoskrnl/io/bootlog.c +++ b/reactos/ntoskrnl/io/bootlog.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/bootlog.c - * PURPOSE: Boot log file support - * PROGRAMMER: Eric Kohl + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/bootlog.c + * PURPOSE: Boot log file support + * + * PROGRAMMERS: Eric Kohl */ /* INCLUDES *****************************************************************/ @@ -85,12 +86,12 @@ IopBootLog(PUNICODE_STRING DriverName, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&ControlSetKey, + Status = ZwOpenKey(&ControlSetKey, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); + DPRINT1("ZwOpenKey() failed (Status %lx)\n", Status); ExReleaseResourceLite(&IopBootLogResource); return; } @@ -101,7 +102,7 @@ IopBootLog(PUNICODE_STRING DriverName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ControlSetKey, NULL); - Status = NtCreateKey(&BootLogKey, + Status = ZwCreateKey(&BootLogKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -110,21 +111,21 @@ IopBootLog(PUNICODE_STRING DriverName, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); - NtClose(ControlSetKey); + DPRINT1("ZwCreateKey() failed (Status %lx)\n", Status); + ZwClose(ControlSetKey); ExReleaseResourceLite(&IopBootLogResource); return; } RtlInitUnicodeString(&ValueName, ValueNameBuffer); - Status = NtSetValueKey(BootLogKey, + Status = ZwSetValueKey(BootLogKey, &ValueName, 0, REG_SZ, (PVOID)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR)); - NtClose(BootLogKey); - NtClose(ControlSetKey); + ZwClose(BootLogKey); + ZwClose(ControlSetKey); if (!NT_SUCCESS(Status)) { @@ -159,7 +160,7 @@ IopWriteLogFile(PWSTR LogText) NULL, NULL); - Status = NtCreateFile(&FileHandle, + Status = ZwCreateFile(&FileHandle, FILE_APPEND_DATA, &ObjectAttributes, &IoStatusBlock, @@ -172,13 +173,13 @@ IopWriteLogFile(PWSTR LogText) 0); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateFile() failed (Status %lx)\n", Status); + DPRINT1("ZwCreateFile() failed (Status %lx)\n", Status); return Status; } if (LogText != NULL) { - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -189,14 +190,14 @@ IopWriteLogFile(PWSTR LogText) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); - NtClose(FileHandle); + DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status); + ZwClose(FileHandle); return Status; } } /* L"\r\n" */ - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -206,11 +207,11 @@ IopWriteLogFile(PWSTR LogText) NULL, NULL); - NtClose(FileHandle); + ZwClose(FileHandle); if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); + DPRINT1("ZwWriteFile() failed (Status %lx)\n", Status); } return Status; @@ -240,7 +241,7 @@ IopCreateLogFile(VOID) NULL, NULL); - Status = NtCreateFile(&FileHandle, + Status = ZwCreateFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, @@ -253,14 +254,14 @@ IopCreateLogFile(VOID) 0); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateFile() failed (Status %lx)\n", Status); + DPRINT1("ZwCreateFile() failed (Status %lx)\n", Status); return Status; } ByteOffset.QuadPart = (LONGLONG)0; Signature = 0xFEFF; - Status = NtWriteFile(FileHandle, + Status = ZwWriteFile(FileHandle, NULL, NULL, NULL, @@ -271,10 +272,10 @@ IopCreateLogFile(VOID) NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtWriteKey() failed (Status %lx)\n", Status); + DPRINT1("ZwWriteKey() failed (Status %lx)\n", Status); } - NtClose(FileHandle); + ZwClose(FileHandle); return Status; } @@ -343,7 +344,7 @@ IopSaveBootLogToFile(VOID) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -362,7 +363,7 @@ IopSaveBootLogToFile(VOID) RtlInitUnicodeString(&ValueName, ValueNameBuffer); - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, KeyInfo, @@ -376,7 +377,7 @@ IopSaveBootLogToFile(VOID) if (!NT_SUCCESS(Status)) { CHECKPOINT1; - NtClose(KeyHandle); + ZwClose(KeyHandle); ExFreePool(KeyInfo); ExReleaseResourceLite(&IopBootLogResource); return; @@ -386,18 +387,18 @@ IopSaveBootLogToFile(VOID) if (!NT_SUCCESS(Status)) { CHECKPOINT1; - NtClose(KeyHandle); + ZwClose(KeyHandle); ExFreePool(KeyInfo); ExReleaseResourceLite(&IopBootLogResource); return; } /* Delete keys */ - NtDeleteValueKey(KeyHandle, + ZwDeleteValueKey(KeyHandle, &ValueName); } - NtClose(KeyHandle); + ZwClose(KeyHandle); ExFreePool(KeyInfo); diff --git a/reactos/ntoskrnl/io/buildirp.c b/reactos/ntoskrnl/io/buildirp.c index c7848e4c870..99fdc41cbbe 100644 --- a/reactos/ntoskrnl/io/buildirp.c +++ b/reactos/ntoskrnl/io/buildirp.c @@ -4,10 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/buildirp.c * PURPOSE: Building various types of irp - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * Fixed IO method handling 04/03/99 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/cancel.c b/reactos/ntoskrnl/io/cancel.c index dbb1f0d5e30..f5c4312eeb9 100644 --- a/reactos/ntoskrnl/io/cancel.c +++ b/reactos/ntoskrnl/io/cancel.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/cancel.c * PURPOSE: Cancel routine - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/cleanup.c b/reactos/ntoskrnl/io/cleanup.c index 19bb86ab11b..c085eb1bb2f 100644 --- a/reactos/ntoskrnl/io/cleanup.c +++ b/reactos/ntoskrnl/io/cleanup.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/cleanup.c - * PURPOSE: IRP cleanup - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 30/05/98: Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/cleanup.c + * PURPOSE: IRP cleanup + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/io/cntrller.c b/reactos/ntoskrnl/io/cntrller.c index a9218db4f71..70a6dba75c8 100644 --- a/reactos/ntoskrnl/io/cntrller.c +++ b/reactos/ntoskrnl/io/cntrller.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/cntrller.c * PURPOSE: Implements the controller object - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/create.c b/reactos/ntoskrnl/io/create.c index 848fed6236f..2595918670f 100644 --- a/reactos/ntoskrnl/io/create.c +++ b/reactos/ntoskrnl/io/create.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/create.c * PURPOSE: Handling file create/open apis - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 24/05/98: Created + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ***************************************************************/ @@ -86,8 +85,10 @@ IopCreateFile(PVOID ObjectBody, if (ParentObjectType != IoDeviceObjectType && ParentObjectType != IoFileObjectType) { - CPRINT("Parent is a %S which is neither a file type nor a device type\n", - BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer); + DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n", + &BODY_TO_HEADER(Parent)->Name, + BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer, + RemainingPath); return(STATUS_UNSUCCESSFUL); } @@ -146,8 +147,8 @@ IopCreateFile(PVOID ObjectBody, DeviceObject = DeviceObject->Vpb->DeviceObject; DPRINT("FsDeviceObject %lx\n", DeviceObject); } - RtlCreateUnicodeString(&(FileObject->FileName), - RemainingPath); + RtlpCreateUnicodeString(&(FileObject->FileName), + RemainingPath, NonPagedPool); } } else @@ -164,8 +165,8 @@ IopCreateFile(PVOID ObjectBody, FileObject->RelatedFileObject = (PFILE_OBJECT)Parent; - RtlCreateUnicodeString(&(FileObject->FileName), - RemainingPath); + RtlpCreateUnicodeString(&(FileObject->FileName), + RemainingPath, NonPagedPool); } DPRINT("FileObject->FileName %wZ\n", @@ -319,7 +320,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject, * @implemented */ NTSTATUS STDCALL -IoCreateFile(OUT PHANDLE FileHandle, +IoCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, @@ -335,11 +336,15 @@ IoCreateFile(OUT PHANDLE FileHandle, IN ULONG Options) { PFILE_OBJECT FileObject; - NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION StackLoc; IO_SECURITY_CONTEXT SecurityContext; - KPROCESSOR_MODE PreviousMode; + KPROCESSOR_MODE AccessMode; + HANDLE LocalFileHandle; + IO_STATUS_BLOCK LocalIoStatusBlock; + LARGE_INTEGER SafeAllocationSize; + PVOID SystemEaBuffer = NULL; + NTSTATUS Status = STATUS_SUCCESS; DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, " "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", @@ -348,17 +353,89 @@ IoCreateFile(OUT PHANDLE FileHandle, ASSERT_IRQL(PASSIVE_LEVEL); - if (IoStatusBlock == NULL) - return STATUS_ACCESS_VIOLATION; + if (IoStatusBlock == NULL || FileHandle == NULL) + return STATUS_ACCESS_VIOLATION; - *FileHandle = 0; + LocalFileHandle = 0; - PreviousMode = ExGetPreviousMode(); + if(Options & IO_NO_PARAMETER_CHECKING) + AccessMode = KernelMode; + else + AccessMode = ExGetPreviousMode(); + + if(AccessMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(FileHandle, + sizeof(HANDLE), + sizeof(ULONG)); + ProbeForWrite(IoStatusBlock, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + if(AllocationSize != NULL) + { + ProbeForRead(AllocationSize, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + SafeAllocationSize = *AllocationSize; + } + else + SafeAllocationSize.QuadPart = 0; - Status = ObCreateObject(PreviousMode, + if(EaBuffer != NULL && EaLength > 0) + { + ProbeForRead(EaBuffer, + EaLength, + sizeof(ULONG)); + + /* marshal EaBuffer */ + SystemEaBuffer = ExAllocatePool(NonPagedPool, + EaLength); + if(SystemEaBuffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH_LEAVE; + } + + RtlCopyMemory(SystemEaBuffer, + EaBuffer, + EaLength); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + if(AllocationSize != NULL) + SafeAllocationSize = *AllocationSize; + else + SafeAllocationSize.QuadPart = 0; + + if(EaBuffer != NULL && EaLength > 0) + { + SystemEaBuffer = EaBuffer; + } + } + + if(Options & IO_CHECK_CREATE_PARAMETERS) + { + DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n"); + } + + Status = ObCreateObject(AccessMode, IoFileObjectType, ObjectAttributes, - PreviousMode, + AccessMode, NULL, sizeof(FILE_OBJECT), 0, @@ -378,7 +455,7 @@ IoCreateFile(OUT PHANDLE FileHandle, DesiredAccess, 0, NULL, - FileHandle); + &LocalFileHandle); if (!NT_SUCCESS(Status)) { DPRINT("ObInsertObject() failed! (Status %lx)\n", Status); @@ -416,22 +493,19 @@ IoCreateFile(OUT PHANDLE FileHandle, Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE); if (Irp == NULL) { - ZwClose(*FileHandle); + ZwClose(LocalFileHandle); return STATUS_UNSUCCESSFUL; } //trigger FileObject/Event dereferencing Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->RequestorMode = PreviousMode; - Irp->UserIosb = IoStatusBlock; - Irp->AssociatedIrp.SystemBuffer = EaBuffer; + Irp->RequestorMode = AccessMode; + Irp->UserIosb = &LocalIoStatusBlock; + Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer; Irp->Tail.Overlay.AuxiliaryBuffer = NULL; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->UserEvent = &FileObject->Event; - if (AllocationSize) - { - Irp->Overlay.AllocationSize = *AllocationSize; - } + Irp->Overlay.AllocationSize = SafeAllocationSize; /* * Get the stack location for the new @@ -454,7 +528,7 @@ IoCreateFile(OUT PHANDLE FileHandle, StackLoc->Parameters.Create.Options |= (CreateDisposition << 24); StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes; StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess; - StackLoc->Parameters.Create.EaLength = EaLength; + StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0; break; case CreateFileTypeNamedPipe: @@ -488,10 +562,10 @@ IoCreateFile(OUT PHANDLE FileHandle, { KeWaitForSingleObject(&FileObject->Event, Executive, - PreviousMode, + AccessMode, FALSE, NULL); - Status = IoStatusBlock->Status; + Status = LocalIoStatusBlock.Status; } if (!NT_SUCCESS(Status)) { @@ -499,8 +573,27 @@ IoCreateFile(OUT PHANDLE FileHandle, FileObject->DeviceObject = NULL; FileObject->Vpb = NULL; - ZwClose(*FileHandle); + ZwClose(LocalFileHandle); } + else + { + _SEH_TRY + { + *FileHandle = LocalFileHandle; + *IoStatusBlock = LocalIoStatusBlock; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + /* cleanup EABuffer if captured */ + if(AccessMode != KernelMode && SystemEaBuffer != NULL) + { + ExFreePool(SystemEaBuffer); + } ASSERT_IRQL(PASSIVE_LEVEL); diff --git a/reactos/ntoskrnl/io/device.c b/reactos/ntoskrnl/io/device.c index 44e6ec892ac..d68f4d89a4a 100644 --- a/reactos/ntoskrnl/io/device.c +++ b/reactos/ntoskrnl/io/device.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/device.c - * PURPOSE: Manage devices - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 15/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/device.c + * PURPOSE: Manage devices + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *******************************************************************/ @@ -340,7 +339,7 @@ IoGetDeviceObjectPointer( NULL, NULL); - Status = NtOpenFile( + Status = ZwOpenFile( &FileHandle, DesiredAccess, &ObjectAttributes, @@ -365,7 +364,7 @@ IoGetDeviceObjectPointer( *FileObject = LocalFileObject; } - NtClose(FileHandle); + ZwClose(FileHandle); return Status; } diff --git a/reactos/ntoskrnl/io/deviface.c b/reactos/ntoskrnl/io/deviface.c index 4d42858241a..e1542f56834 100644 --- a/reactos/ntoskrnl/io/deviface.c +++ b/reactos/ntoskrnl/io/deviface.c @@ -1,12 +1,12 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/devintrf.c - * PURPOSE: Device interface functions - * PROGRAMMER: Filip Navara (xnavara@volny.cz) - * Matthew Brace (ismarc@austin.rr.com) - * UPDATE HISTORY: - * 22/09/2003 FiN Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/deviface.c + * PURPOSE: Device interface functions + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) + * Matthew Brace (ismarc@austin.rr.com) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/dir.c b/reactos/ntoskrnl/io/dir.c index f25ef751278..90b91800927 100644 --- a/reactos/ntoskrnl/io/dir.c +++ b/reactos/ntoskrnl/io/dir.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/dir.c * PURPOSE: Directory functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -236,11 +235,4 @@ NtQueryDirectoryFile( return(Status); } -NTSTATUS STDCALL NtQueryOleDirectoryFile(VOID) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); -} - - /* EOF */ diff --git a/reactos/ntoskrnl/io/driver.c b/reactos/ntoskrnl/io/driver.c index a41da67ecdb..c43ead25976 100644 --- a/reactos/ntoskrnl/io/driver.c +++ b/reactos/ntoskrnl/io/driver.c @@ -1,13 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/driver.c - * PURPOSE: Loading and unloading of drivers - * PROGRAMMER: David Welch (welch@cwcom.net) - * Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 15/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/driver.c + * PURPOSE: Loading and unloading of drivers + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Filip Navara (xnavara@volny.cz) */ /* INCLUDES *******************************************************************/ @@ -97,8 +96,8 @@ IopInitDriverImplementation(VOID) IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R'); IoDriverObjectType->TotalObjects = 0; IoDriverObjectType->TotalHandles = 0; - IoDriverObjectType->MaxObjects = ULONG_MAX; - IoDriverObjectType->MaxHandles = ULONG_MAX; + IoDriverObjectType->PeakObjects = 0; + IoDriverObjectType->PeakHandles = 0; IoDriverObjectType->PagedPoolCharge = 0; IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT); IoDriverObjectType->Dump = NULL; @@ -181,6 +180,7 @@ IopDeleteDriver(PVOID ObjectBody) DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody); ExFreePool(Object->DriverExtension); + RtlFreeUnicodeString(&Object->DriverName); OldIrql = KeRaiseIrqlToDpcLevel(); @@ -208,6 +208,7 @@ IopCreateDriverObject( UNICODE_STRING DriverName; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; + PWSTR Buffer = NULL; DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n", DriverObject, ServiceName, FileSystem, DriverImageStart, DriverImageSize); @@ -225,6 +226,10 @@ IopCreateDriverObject( RtlInitUnicodeString(&DriverName, NameBuffer); DPRINT("Driver name: '%wZ'\n", &DriverName); + + Buffer = (PWSTR)ExAllocatePool(NonPagedPool, DriverName.Length); + /* If we don't success, it is not a problem. Our driver + * object will not have associated driver name... */ } else { @@ -258,6 +263,12 @@ IopCreateDriverObject( Object->DriverStart = DriverImageStart; Object->DriverSize = DriverImageSize; + if (Buffer) + { + Object->DriverName.Buffer = Buffer; + Object->DriverName.Length = Object->DriverName.MaximumLength = DriverName.Length; + RtlCopyMemory(Object->DriverName.Buffer, DriverName.Buffer, DriverName.Length); + } *DriverObject = Object; @@ -448,6 +459,8 @@ IopLoadServiceModule( &ServiceImagePath, ModuleObject); + KDB_SYMBOLFILE_HOOK(SearchName); + break; } } @@ -781,8 +794,7 @@ IopCreateGroupListEntry(PWSTR ValueName, RtlZeroMemory(Group, sizeof(SERVICE_GROUP)); - if (!RtlCreateUnicodeString(&Group->GroupName, - (PWSTR)ValueData)) + if (!RtlpCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData, NonPagedPool)) { ExFreePool(Group); return(STATUS_INSUFFICIENT_RESOURCES); @@ -947,7 +959,7 @@ IoCreateDriverList(VOID) NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, 0x10001, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -959,14 +971,14 @@ IoCreateDriverList(VOID) KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength); if (KeyInfo == NULL) { - NtClose(KeyHandle); + ZwClose(KeyHandle); return(STATUS_INSUFFICIENT_RESOURCES); } Index = 0; while (TRUE) { - Status = NtEnumerateKey(KeyHandle, + Status = ZwEnumerateKey(KeyHandle, Index, KeyBasicInformation, KeyInfo, @@ -994,7 +1006,7 @@ IoCreateDriverList(VOID) } ExFreePool(KeyInfo); - NtClose(KeyHandle); + ZwClose(KeyHandle); DPRINT("IoCreateDriverList() done\n"); @@ -1135,6 +1147,9 @@ IopInitializeBuiltinDriver( return Status; } + /* Load symbols */ + KDB_SYMBOLFILE_HOOK(FileName); + /* * Strip the file extension from ServiceName */ @@ -1205,13 +1220,11 @@ IopInitializeBootDrivers(VOID) if (Extension == NULL) Extension = ""; - if (!_stricmp(Extension, ".sym")) - { - /* Pass symbol files to kernel debugger */ - KDB_SYMBOLFILE_HOOK((PVOID)ModuleStart, ModuleName, ModuleSize); - } - else if (!_stricmp(Extension, ".exe") || !_stricmp(Extension, ".dll")) + if (!_stricmp(Extension, ".sym") || !_stricmp(Extension, ".dll")) { + /* Process symbols for *.exe and *.dll */ + KDB_SYMBOLFILE_HOOK(ModuleName); + /* Log *.exe and *.dll files */ RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName); IopBootLog(&DriverName, TRUE); @@ -1232,20 +1245,16 @@ IopInitializeBootDrivers(VOID) } BootDriverCount++; } + } - /* - * Free memory for all boot files, except ntoskrnl.exe - * and symbol files, if the kernel debugger is active - */ - if (i != 0 /* ntoskrnl.exe is always the first module */ -#if defined(DBG) || defined(KDBG) - && _stricmp(Extension, ".sym") -#endif - ) - { - MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart, - KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart); - } + /* + * Free memory for all boot files, except ntoskrnl.exe. + */ + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { + + MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart, + KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart); } if (BootDriverCount == 0) @@ -1261,7 +1270,7 @@ IopLoadDriver(PSERVICE Service) NTSTATUS Status = STATUS_UNSUCCESSFUL; IopDisplayLoadingMessage(Service->ServiceName.Buffer); - Status = NtLoadDriver(&Service->RegistryPath); + Status = ZwLoadDriver(&Service->RegistryPath); IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE); if (!NT_SUCCESS(Status)) { @@ -1854,7 +1863,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) Start = DriverServiceName->Buffer; else Start++; - RtlCreateUnicodeString(&DeviceNode->ServiceName, Start); + RtlpCreateUnicodeString(&DeviceNode->ServiceName, Start, NonPagedPool); /* * Initialize the driver module diff --git a/reactos/ntoskrnl/nt/efi.c b/reactos/ntoskrnl/io/efi.c similarity index 91% rename from reactos/ntoskrnl/nt/efi.c rename to reactos/ntoskrnl/io/efi.c index c84d91ce287..f93fea0d784 100644 --- a/reactos/ntoskrnl/nt/efi.c +++ b/reactos/ntoskrnl/io/efi.c @@ -1,11 +1,11 @@ -/* +/* $Id:$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/efi.c + * FILE: ntoskrnl/io/efi.c * PURPOSE: EFI Unimplemented Function Calls - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 16/07/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/errlog.c b/reactos/ntoskrnl/io/errlog.c index a31986c93b9..43e13d76fa8 100644 --- a/reactos/ntoskrnl/io/errlog.c +++ b/reactos/ntoskrnl/io/errlog.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/errlog.c * PURPOSE: Error logging - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -136,7 +135,7 @@ IopConnectLogPort (VOID) RtlInitUnicodeString (&PortName, L"\\ErrorLogPort"); - Status = NtConnectPort (&IopLogPort, + Status = ZwConnectPort (&IopLogPort, &PortName, NULL, NULL, @@ -146,7 +145,7 @@ IopConnectLogPort (VOID) NULL); if (!NT_SUCCESS(Status)) { - DPRINT ("NtConnectPort() failed (Status %lx)\n", Status); + DPRINT ("ZwConnectPort() failed (Status %lx)\n", Status); return FALSE; } @@ -291,7 +290,7 @@ IopLogWorker (PVOID Parameter) Request->Header.DataSize + sizeof(LPC_MESSAGE); /* Send the error message to the log port */ - Status = NtRequestPort (IopLogPort, + Status = ZwRequestPort (IopLogPort, &Request->Header); /* Release request buffer */ @@ -299,7 +298,7 @@ IopLogWorker (PVOID Parameter) if (!NT_SUCCESS(Status)) { - DPRINT ("NtRequestPort() failed (Status %lx)\n", Status); + DPRINT ("ZwRequestPort() failed (Status %lx)\n", Status); /* Requeue log message and restart the worker */ ExInterlockedInsertTailList (&IopLogListHead, diff --git a/reactos/ntoskrnl/io/error.c b/reactos/ntoskrnl/io/error.c index 98e85f48027..5b85dd926ff 100644 --- a/reactos/ntoskrnl/io/error.c +++ b/reactos/ntoskrnl/io/error.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/error.c * PURPOSE: Handle media errors - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/event.c b/reactos/ntoskrnl/io/event.c index 2afe8dba027..785df0330b1 100644 --- a/reactos/ntoskrnl/io/event.c +++ b/reactos/ntoskrnl/io/event.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/event.c * PURPOSE: Implements named events - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -34,7 +33,7 @@ IoCreateNotificationEvent(PUNICODE_STRING EventName, NULL, NULL); - Status = NtCreateEvent(&Handle, + Status = ZwCreateEvent(&Handle, EVENT_ALL_ACCESS, &ObjectAttributes, NotificationEvent, @@ -65,9 +64,12 @@ IoCreateSynchronizationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle) { OBJECT_ATTRIBUTES ObjectAttributes; + KPROCESSOR_MODE PreviousMode; PKEVENT Event; HANDLE Handle; NTSTATUS Status; + + PreviousMode = ExGetPreviousMode(); InitializeObjectAttributes(&ObjectAttributes, EventName, @@ -75,11 +77,12 @@ IoCreateSynchronizationEvent(PUNICODE_STRING EventName, NULL, NULL); - Status = NtCreateEvent(&Handle, + Status = ZwCreateEvent(&Handle, EVENT_ALL_ACCESS, &ObjectAttributes, SynchronizationEvent, TRUE); + if (!NT_SUCCESS(Status)) { return NULL; diff --git a/reactos/ntoskrnl/io/file.c b/reactos/ntoskrnl/io/file.c index 79f410598c2..21d4a116962 100644 --- a/reactos/ntoskrnl/io/file.c +++ b/reactos/ntoskrnl/io/file.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/file.c * PURPOSE: Graceful system shutdown if a bug is detected - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -538,7 +537,7 @@ NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, NTSTATUS Status; /* Open the file */ - Status = NtOpenFile (&FileHandle, + Status = ZwOpenFile (&FileHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES, ObjectAttributes, &IoStatusBlock, @@ -546,20 +545,20 @@ NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS (Status)) { - DPRINT ("NtOpenFile() failed (Status %lx)\n", Status); + DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status); return Status; } /* Get file attributes */ - Status = NtQueryInformationFile (FileHandle, + Status = ZwQueryInformationFile (FileHandle, &IoStatusBlock, FileInformation, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); - NtClose (FileHandle); + ZwClose (FileHandle); if (!NT_SUCCESS (Status)) { - DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status); + DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status); } return Status; @@ -575,7 +574,7 @@ NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, NTSTATUS Status; /* Open the file */ - Status = NtOpenFile (&FileHandle, + Status = ZwOpenFile (&FileHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES, ObjectAttributes, &IoStatusBlock, @@ -583,20 +582,20 @@ NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS (Status)) { - DPRINT ("NtOpenFile() failed (Status %lx)\n", Status); + DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status); return Status; } /* Get file attributes */ - Status = NtQueryInformationFile (FileHandle, + Status = ZwQueryInformationFile (FileHandle, &IoStatusBlock, FileInformation, sizeof(FILE_NETWORK_OPEN_INFORMATION), FileNetworkOpenInformation); - NtClose (FileHandle); + ZwClose (FileHandle); if (!NT_SUCCESS (Status)) { - DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status); + DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status); } return Status; diff --git a/reactos/ntoskrnl/io/flush.c b/reactos/ntoskrnl/io/flush.c index 7443dfa5eee..d944745b3f4 100644 --- a/reactos/ntoskrnl/io/flush.c +++ b/reactos/ntoskrnl/io/flush.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/flush.c * PURPOSE: Flushing file buffer - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/fs.c b/reactos/ntoskrnl/io/fs.c index 686ba951f54..d3f661ce924 100644 --- a/reactos/ntoskrnl/io/fs.c +++ b/reactos/ntoskrnl/io/fs.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/fs.c * PURPOSE: Filesystem functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -35,7 +35,7 @@ typedef struct _FS_CHANGE_NOTIFY_ENTRY static ERESOURCE FileSystemListLock; static LIST_ENTRY FileSystemListHead; -static KSPIN_LOCK FsChangeNotifyListLock; +static FAST_MUTEX FsChangeNotifyListLock; static LIST_ENTRY FsChangeNotifyListHead; #define TAG_FILE_SYSTEM TAG('F', 'S', 'Y', 'S') @@ -178,7 +178,7 @@ IoInitFileSystemImplementation(VOID) ExInitializeResourceLite(&FileSystemListLock); InitializeListHead(&FsChangeNotifyListHead); - KeInitializeSpinLock(&FsChangeNotifyListLock); + ExInitializeFastMutex(&FsChangeNotifyListLock); } @@ -709,9 +709,8 @@ IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject, { PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; PLIST_ENTRY Entry; - KIRQL oldlvl; - KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl); + ExAcquireFastMutex(&FsChangeNotifyListLock); Entry = FsChangeNotifyListHead.Flink; while (Entry != &FsChangeNotifyListHead) { @@ -721,7 +720,7 @@ IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject, Entry = Entry->Flink; } - KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl); + ExReleaseFastMutex(&FsChangeNotifyListLock); } @@ -743,9 +742,10 @@ IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, Entry->DriverObject = DriverObject; Entry->FSDNotificationProc = FSDNotificationProc; - ExInterlockedInsertHeadList(&FsChangeNotifyListHead, - &Entry->FsChangeNotifyList, - &FsChangeNotifyListLock); + ExAcquireFastMutex(&FsChangeNotifyListLock); + InsertHeadList(&FsChangeNotifyListHead, + &Entry->FsChangeNotifyList); + ExReleaseFastMutex(&FsChangeNotifyListLock); return(STATUS_SUCCESS); } @@ -760,7 +760,6 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, { PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; PLIST_ENTRY Entry; - KIRQL oldlvl; Entry = FsChangeNotifyListHead.Flink; while (Entry != &FsChangeNotifyListHead) @@ -769,9 +768,9 @@ IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, if (ChangeEntry->DriverObject == DriverObject && ChangeEntry->FSDNotificationProc == FSDNotificationProc) { - KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl); + ExAcquireFastMutex(&FsChangeNotifyListLock); RemoveEntryList(Entry); - KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl); + ExReleaseFastMutex(&FsChangeNotifyListLock); ExFreePool(Entry); return; diff --git a/reactos/ntoskrnl/io/iocomp.c b/reactos/ntoskrnl/io/iocomp.c index deb9b3453ff..de412e59036 100644 --- a/reactos/ntoskrnl/io/iocomp.c +++ b/reactos/ntoskrnl/io/iocomp.c @@ -1,12 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/iocomp.c - * PURPOSE: - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - Changed NtQueryIoCompletion + * FILE: ntoskrnl/io/iocomp.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -33,14 +32,14 @@ static GENERIC_MAPPING ExIoCompletionMapping = NTSTATUS STDCALL -NtpCreateIoCompletion( +IopCreateIoCompletion( PVOID ObjectBody, PVOID Parent, PWSTR RemainingPath, POBJECT_ATTRIBUTES ObjectAttributes ) { - DPRINT("NtpCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n", + DPRINT("IopCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n", ObjectBody, Parent, RemainingPath); if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) @@ -52,11 +51,11 @@ NtpCreateIoCompletion( } VOID STDCALL -NtpDeleteIoCompletion(PVOID ObjectBody) +IopDeleteIoCompletion(PVOID ObjectBody) { PKQUEUE Queue = ObjectBody; - DPRINT("NtpDeleteIoCompletion()\n"); + DPRINT("IopDeleteIoCompletion()\n"); KeRundownQueue(Queue); } @@ -120,11 +119,11 @@ IopInitIoCompletionImplementation(VOID) { ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - RtlCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion"); + RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool); ExIoCompletionType->Tag = IOC_TAG; - ExIoCompletionType->MaxObjects = ULONG_MAX; - ExIoCompletionType->MaxHandles = ULONG_MAX; + ExIoCompletionType->PeakObjects = 0; + ExIoCompletionType->PeakHandles = 0; ExIoCompletionType->TotalObjects = 0; ExIoCompletionType->TotalHandles = 0; ExIoCompletionType->PagedPoolCharge = 0; @@ -133,12 +132,12 @@ IopInitIoCompletionImplementation(VOID) ExIoCompletionType->Dump = NULL; ExIoCompletionType->Open = NULL; ExIoCompletionType->Close = NULL; - ExIoCompletionType->Delete = NtpDeleteIoCompletion; + ExIoCompletionType->Delete = IopDeleteIoCompletion; ExIoCompletionType->Parse = NULL; ExIoCompletionType->Security = NULL; ExIoCompletionType->QueryName = NULL; ExIoCompletionType->OkayToClose = NULL; - ExIoCompletionType->Create = NtpCreateIoCompletion; + ExIoCompletionType->Create = IopCreateIoCompletion; ExIoCompletionType->DuplicationNotify = NULL; ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside, diff --git a/reactos/ntoskrnl/io/ioctrl.c b/reactos/ntoskrnl/io/ioctrl.c index b9a038c38f6..f404ae16296 100644 --- a/reactos/ntoskrnl/io/ioctrl.c +++ b/reactos/ntoskrnl/io/ioctrl.c @@ -4,13 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/ioctrl.c * PURPOSE: Device IO control - * PROGRAMMER: David Welch (welch@mcmail.com) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) * Eric Kohl (ekohl@rz-online.de) - * UPDATE HISTORY: - * Created 22/05/98 - * Filled in ZwDeviceIoControlFile 22/02/99 - * Fixed IO method handling 08/03/99 - * Added APC support 05/11/99 */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 0a3e6ce69b2..b8a2dcf1ebb 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/iomgr.c - * PURPOSE: Initializes the io manager - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 29/07/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/iomgr.c + * PURPOSE: Initializes the io manager + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ @@ -395,8 +394,8 @@ IoInit (VOID) IoDeviceObjectType->Tag = TAG_DEVICE_TYPE; IoDeviceObjectType->TotalObjects = 0; IoDeviceObjectType->TotalHandles = 0; - IoDeviceObjectType->MaxObjects = ULONG_MAX; - IoDeviceObjectType->MaxHandles = ULONG_MAX; + IoDeviceObjectType->PeakObjects = 0; + IoDeviceObjectType->PeakHandles = 0; IoDeviceObjectType->PagedPoolCharge = 0; IoDeviceObjectType->NonpagedPoolCharge = sizeof (DEVICE_OBJECT); IoDeviceObjectType->Mapping = &IopFileMapping; @@ -424,8 +423,8 @@ IoInit (VOID) IoFileObjectType->Tag = TAG_FILE_TYPE; IoFileObjectType->TotalObjects = 0; IoFileObjectType->TotalHandles = 0; - IoFileObjectType->MaxObjects = ULONG_MAX; - IoFileObjectType->MaxHandles = ULONG_MAX; + IoFileObjectType->PeakObjects = 0; + IoFileObjectType->PeakHandles = 0; IoFileObjectType->PagedPoolCharge = 0; IoFileObjectType->NonpagedPoolCharge = sizeof(FILE_OBJECT); IoFileObjectType->Mapping = &IopFileMapping; @@ -451,8 +450,8 @@ IoInit (VOID) sizeof (OBJECT_TYPE)); RtlZeroMemory(IoAdapterObjectType, sizeof(OBJECT_TYPE)); IoAdapterObjectType->Tag = TAG_ADAPTER_TYPE; - IoAdapterObjectType->MaxObjects = ULONG_MAX; - IoAdapterObjectType->MaxHandles = ULONG_MAX; + IoAdapterObjectType->PeakObjects = 0; + IoAdapterObjectType->PeakHandles = 0; IoDeviceObjectType->Mapping = &IopFileMapping; RtlRosInitUnicodeStringFromLiteral(&IoAdapterObjectType->TypeName, L"Adapter"); ObpCreateTypeObject(IoAdapterObjectType); @@ -466,7 +465,7 @@ IoInit (VOID) 0, NULL, NULL); - NtCreateDirectoryObject(&Handle, + ZwCreateDirectoryObject(&Handle, 0, &ObjectAttributes); @@ -480,7 +479,7 @@ IoInit (VOID) 0, NULL, NULL); - NtCreateDirectoryObject(&Handle, + ZwCreateDirectoryObject(&Handle, 0, &ObjectAttributes); diff --git a/reactos/ntoskrnl/io/iowork.c b/reactos/ntoskrnl/io/iowork.c index a7bb0392938..62ce6683eda 100644 --- a/reactos/ntoskrnl/io/iowork.c +++ b/reactos/ntoskrnl/io/iowork.c @@ -1,13 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: reactos/ntoskrnl/io/iowork.c - * PURPOSE: Manage IO system work queues - * PROGRAMMER: David Welch (welch@mcmail.com) - * Robert Dickenson (odin@pnc.com.au) - * REVISION HISTORY: - * 28/09/2002: (RDD) Created from copy of ex/work.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/iowork.c + * PURPOSE: Manage IO system work queues + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Robert Dickenson (odin@pnc.com.au) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/irp.c b/reactos/ntoskrnl/io/irp.c index e846a2ef79a..d898dc4f1c8 100644 --- a/reactos/ntoskrnl/io/irp.c +++ b/reactos/ntoskrnl/io/irp.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/irp.c * PURPOSE: Handle IRPs - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 24/05/98: Created + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* NOTES ******************************************************************* diff --git a/reactos/ntoskrnl/io/irq.c b/reactos/ntoskrnl/io/irq.c index 66dee26c58b..0bb060bd0ff 100644 --- a/reactos/ntoskrnl/io/irq.c +++ b/reactos/ntoskrnl/io/irq.c @@ -1,9 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/irq.c * PURPOSE: IRQ handling - * PROGRAMMER: David Welch (welch@mcmail.com) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/lock.c b/reactos/ntoskrnl/io/lock.c index 5a181ae4978..26bad31c09b 100644 --- a/reactos/ntoskrnl/io/lock.c +++ b/reactos/ntoskrnl/io/lock.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/bug.c - * PURPOSE: Graceful system shutdown if a bug is detected - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * FILE: ntoskrnl/io/lock.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/mailslot.c b/reactos/ntoskrnl/io/mailslot.c index aa328408515..5d62b6b6643 100644 --- a/reactos/ntoskrnl/io/mailslot.c +++ b/reactos/ntoskrnl/io/mailslot.c @@ -1,12 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/bug.c - * PURPOSE: Graceful system shutdown if a bug is detected - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - Changed NtCreateMailslotFile + * FILE: ntoskrnl/io/mailslot.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/mdl.c b/reactos/ntoskrnl/io/mdl.c index 85d470f1b67..da6a4dbc7e0 100644 --- a/reactos/ntoskrnl/io/mdl.c +++ b/reactos/ntoskrnl/io/mdl.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/mdl.c * PURPOSE: Io manager mdl functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/npipe.c b/reactos/ntoskrnl/io/npipe.c index fe1e1879b90..cd3bd499b79 100644 --- a/reactos/ntoskrnl/io/npipe.c +++ b/reactos/ntoskrnl/io/npipe.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/npipe.c * PURPOSE: Named pipe helper function - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/page.c b/reactos/ntoskrnl/io/page.c index fa6178df73d..49734f0f4fc 100644 --- a/reactos/ntoskrnl/io/page.c +++ b/reactos/ntoskrnl/io/page.c @@ -3,10 +3,9 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/page.c - * PURPOSE: - * PROGRAMMER: - * UPDATE HISTORY: - * + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/parttab.c b/reactos/ntoskrnl/io/parttab.c index bff11177ac1..3bab16d9c7a 100644 --- a/reactos/ntoskrnl/io/parttab.c +++ b/reactos/ntoskrnl/io/parttab.c @@ -4,11 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/parttab.c * PURPOSE: Handling fixed disks (partition table functions) - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * 2000-03-25 (ea) - * Moved here from ntoskrnl/io/fdisk.c + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/plugplay.c b/reactos/ntoskrnl/io/plugplay.c new file mode 100644 index 00000000000..4160efd6d2a --- /dev/null +++ b/reactos/ntoskrnl/io/plugplay.c @@ -0,0 +1,192 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/plugplay.c + * PURPOSE: Plug-and-play interface routines + * + * PROGRAMMERS: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +typedef struct _PNP_EVENT_ENTRY +{ + LIST_ENTRY ListEntry; + PLUGPLAY_EVENT_BLOCK Event; +} PNP_EVENT_ENTRY, *PPNP_EVENT_ENTRY; + + +/* GLOBALS *******************************************************************/ + +static LIST_ENTRY IopPnpEventQueueHead; +static KEVENT IopPnpNotifyEvent; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS INIT_FUNCTION +IopInitPlugPlayEvents(VOID) +{ + + InitializeListHead(&IopPnpEventQueueHead); + + KeInitializeEvent(&IopPnpNotifyEvent, + SynchronizationEvent, + FALSE); + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopQueueTargetDeviceEvent(const GUID *Guid, + PUNICODE_STRING DeviceIds) +{ + PPNP_EVENT_ENTRY EventEntry; + DWORD TotalSize; + + TotalSize = + FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) + + DeviceIds->MaximumLength; + + EventEntry = ExAllocatePool(NonPagedPool, + TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); + if (EventEntry == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + memcpy(&EventEntry->Event.EventGuid, + Guid, + sizeof(GUID)); + EventEntry->Event.EventCategory = TargetDeviceChangeEvent; + EventEntry->Event.TotalSize = TotalSize; + + memcpy(&EventEntry->Event.TargetDevice.DeviceIds, + DeviceIds->Buffer, + DeviceIds->MaximumLength); + + InsertHeadList(&IopPnpEventQueueHead, + &EventEntry->ListEntry); + KeSetEvent(&IopPnpNotifyEvent, + 0, + FALSE); + + return STATUS_SUCCESS; +} + + +/* + * Remove the current PnP event from the tail of the event queue + * and signal IopPnpNotifyEvent if there is yet another event in the queue. + */ +static VOID +IopRemovePlugPlayEvent(VOID) +{ + /* Remove a pnp event entry from the tail of the queue */ + if (!IsListEmpty(&IopPnpEventQueueHead)) + { + ExFreePool(RemoveTailList(&IopPnpEventQueueHead)); + } + + /* Signal the next pnp event in the queue */ + if (!IsListEmpty(&IopPnpEventQueueHead)) + { + KeSetEvent(&IopPnpNotifyEvent, + 0, + FALSE); + } +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtGetPlugPlayEvent(IN ULONG Reserved1, + IN ULONG Reserved2, + OUT PPLUGPLAY_EVENT_BLOCK Buffer, + IN ULONG BufferLength) +{ + PPNP_EVENT_ENTRY Entry; + NTSTATUS Status; + + DPRINT("NtGetPlugPlayEvent() called\n"); + + /* Function can only be called from user-mode */ + if (KeGetPreviousMode() != UserMode) + { + DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n"); + return STATUS_ACCESS_DENIED; + } + + /* Check for Tcb privilege */ + if (!SeSinglePrivilegeCheck(SeTcbPrivilege, + UserMode)) + { + DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; + } + + /* Wait for a PnP event */ + DPRINT("Waiting for pnp notification event\n"); + Status = KeWaitForSingleObject(&IopPnpNotifyEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status); + return Status; + } + + /* Get entry from the tail of the queue */ + Entry = CONTAINING_RECORD(IopPnpEventQueueHead.Blink, + PNP_EVENT_ENTRY, + ListEntry); + + /* Check the buffer size */ + if (BufferLength < Entry->Event.TotalSize) + { + DPRINT1("Buffer is too small for the pnp-event\n"); + return STATUS_BUFFER_TOO_SMALL; + } + + /* Copy event data to the user buffer */ + memcpy(Buffer, + &Entry->Event, + Entry->Event.TotalSize); + + DPRINT("NtGetPlugPlayEvent() done\n"); + + return STATUS_SUCCESS; +} + + +/* + * @unimplemented + */ +NTSTATUS STDCALL +NtPlugPlayControl(IN ULONG ControlCode, + IN OUT PVOID Buffer, + IN ULONG BufferLength) +{ + DPRINT("NtPlugPlayControl(%lu %p %lu) called\n", + ControlCode, Buffer, BufferLength); + + switch (ControlCode) + { + case PLUGPLAY_USER_RESPONSE: + IopRemovePlugPlayEvent(); + return STATUS_SUCCESS; + } + + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/io/pnpdma.c b/reactos/ntoskrnl/io/pnpdma.c index 854b7fbf328..60398aa1aa9 100644 --- a/reactos/ntoskrnl/io/pnpdma.c +++ b/reactos/ntoskrnl/io/pnpdma.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr.c - * PURPOSE: PnP manager DMA routines - * PROGRAMMER: Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 22/09/2003 FiN Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnpdma.c + * PURPOSE: PnP manager DMA routines + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr.c index a5f20ad0515..9ee95cd5aa5 100644 --- a/reactos/ntoskrnl/io/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr.c @@ -1,17 +1,17 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c - * PURPOSE: Initializes the PnP manager - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 16/04/2001 CSH Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnpmgr.c + * PURPOSE: Initializes the PnP manager + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include @@ -435,7 +435,7 @@ IoRequestDeviceEject( BOOLEAN IopCreateUnicodeString( - PUNICODE_STRING Destination, + PUNICODE_STRING Destination, PWSTR Source, POOL_TYPE PoolType) { @@ -482,7 +482,7 @@ IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) return STATUS_UNSUCCESSFUL; } -/********************************************************************** +/* * DESCRIPTION * Creates a device node * @@ -791,7 +791,7 @@ IopCreateDeviceKeyPath(PWSTR Path, DPRINT("Create '%S'\n", KeyName.Buffer); - Status = NtCreateKey (&KeyHandle, + Status = ZwCreateKey (&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -800,7 +800,7 @@ IopCreateDeviceKeyPath(PWSTR Path, NULL); if (!NT_SUCCESS (Status)) { - DPRINT ("NtCreateKey() failed with status %x\n", Status); + DPRINT ("ZwCreateKey() failed with status %x\n", Status); return Status; } @@ -811,7 +811,7 @@ IopCreateDeviceKeyPath(PWSTR Path, } else { - NtClose (KeyHandle); + ZwClose (KeyHandle); *Next = L'\\'; } @@ -843,7 +843,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, OBJ_CASE_INSENSITIVE, InstanceKey, NULL); - Status = NtCreateKey(&LogConfKey, + Status = ZwCreateKey(&LogConfKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -862,7 +862,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, RtlInitUnicodeString(&KeyName, L"BootConfig"); - Status = NtSetValueKey(LogConfKey, + Status = ZwSetValueKey(LogConfKey, &KeyName, 0, REG_RESOURCE_LIST, @@ -877,7 +877,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, { RtlInitUnicodeString(&KeyName, L"BasicConfigVector"); - Status = NtSetValueKey(LogConfKey, + Status = ZwSetValueKey(LogConfKey, &KeyName, 0, REG_RESOURCE_REQUIREMENTS_LIST, @@ -885,7 +885,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, DeviceNode->ResourceRequirements->ListSize); } - NtClose(LogConfKey); + ZwClose(LogConfKey); } DPRINT("IopSetDeviceInstanceData() done\n"); @@ -1069,7 +1069,7 @@ IopActionInterrogateDeviceStack( /* Set 'Capabilities' value */ RtlInitUnicodeString(&ValueName, L"Capabilities"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_DWORD, @@ -1081,7 +1081,7 @@ IopActionInterrogateDeviceStack( { RtlInitUnicodeString(&ValueName, L"UINumber"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_DWORD, @@ -1120,7 +1120,7 @@ IopActionInterrogateDeviceStack( RtlInitUnicodeString(&ValueName, L"HardwareID"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, @@ -1128,7 +1128,7 @@ IopActionInterrogateDeviceStack( (TotalLength + 1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); } } else @@ -1166,7 +1166,7 @@ IopActionInterrogateDeviceStack( RtlInitUnicodeString(&ValueName, L"CompatibleIDs"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, @@ -1174,7 +1174,7 @@ IopActionInterrogateDeviceStack( (TotalLength + 1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); } } else @@ -1196,7 +1196,7 @@ IopActionInterrogateDeviceStack( { RtlInitUnicodeString(&ValueName, L"DeviceDesc"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, @@ -1204,7 +1204,7 @@ IopActionInterrogateDeviceStack( (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); } } else @@ -1226,7 +1226,7 @@ IopActionInterrogateDeviceStack( DPRINT("LocationInformation: %S\n", (PWSTR)IoStatusBlock.Information); RtlInitUnicodeString(&ValueName, L"LocationInformation"); - Status = NtSetValueKey(InstanceKey, + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, @@ -1234,7 +1234,7 @@ IopActionInterrogateDeviceStack( (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { - DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status); } } else @@ -1315,10 +1315,14 @@ IopActionInterrogateDeviceStack( IopSetDeviceInstanceData(InstanceKey, DeviceNode); } - NtClose(InstanceKey); + ZwClose(InstanceKey); DeviceNode->Flags |= DNF_PROCESSED; + /* Report the device to the user-mode pnp manager */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &DeviceNode->InstancePath); + return STATUS_SUCCESS; } @@ -1378,6 +1382,13 @@ IopActionConfigureChildServices( if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED)) { + WCHAR RegKeyBuffer[MAX_PATH]; + UNICODE_STRING RegKey; + + RegKey.Length = 0; + RegKey.MaximumLength = sizeof(RegKeyBuffer); + RegKey.Buffer = RegKeyBuffer; + /* * Retrieve configuration from Enum key */ @@ -1391,8 +1402,11 @@ IopActionConfigureChildServices( QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[0].EntryContext = Service; - Status = RtlQueryRegistryValues(RTL_REGISTRY_ENUM, - DeviceNode->InstancePath.Buffer, QueryTable, NULL, NULL); + RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath); + + Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, + RegKey.Buffer, QueryTable, NULL, NULL); if (!NT_SUCCESS(Status)) { @@ -1547,7 +1561,6 @@ IopActionInitAllServices( * parent node. This function just calls IopActionInitChildServices with * BootDrivers = TRUE. */ - NTSTATUS IopActionInitBootServices( PDEVICE_NODE DeviceNode, @@ -1572,7 +1585,6 @@ IopActionInitBootServices( * Return Value * Status */ - NTSTATUS IopInitializePnpServices( IN PDEVICE_NODE DeviceNode, @@ -1721,7 +1733,7 @@ IopInvalidateDeviceRelations( NULL, NULL); - Status = NtOpenFile( + Status = ZwOpenFile( &Handle, FILE_ALL_ACCESS, &ObjectAttributes, @@ -1731,7 +1743,7 @@ IopInvalidateDeviceRelations( BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE; - NtClose(Handle); + ZwClose(Handle); /* * Initialize services for discovered children. Only boot drivers will @@ -1759,6 +1771,14 @@ PnpInit(VOID) KeInitializeSpinLock(&IopDeviceTreeLock); + /* Initialize PnP-Event notification support */ + Status = IopInitPlugPlayEvents(); + if (!NT_SUCCESS(Status)) + { + CPRINT("IopInitPlugPlayEvents() failed\n"); + KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); + } + /* * Create root device node */ @@ -1785,6 +1805,18 @@ PnpInit(VOID) KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } + if (!IopCreateUnicodeString(&IopRootDeviceNode->InstancePath, + L"HTREE\\Root\\0", + PagedPool)) + { + CPRINT("Failed to create the instance path!\n"); + KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_UNSUCCESSFUL, 0, 0, 0); + } + + /* Report the device to the user-mode pnp manager */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &IopRootDeviceNode->InstancePath); + IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE; PnpRootDriverEntry(IopRootDriverObject, NULL); IopRootDriverObject->DriverExtension->AddDevice( diff --git a/reactos/ntoskrnl/io/pnpnotify.c b/reactos/ntoskrnl/io/pnpnotify.c index 501f6159951..1cd818d2a5e 100644 --- a/reactos/ntoskrnl/io/pnpnotify.c +++ b/reactos/ntoskrnl/io/pnpnotify.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/remlock.c - * PURPOSE: Plug & Play notification functions - * PROGRAMMER: Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 22/09/2003 FiN Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnpnotify.c + * PURPOSE: Plug & Play notification functions + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/pnpreport.c b/reactos/ntoskrnl/io/pnpreport.c index e8626e70bbd..95b06f00175 100644 --- a/reactos/ntoskrnl/io/pnpreport.c +++ b/reactos/ntoskrnl/io/pnpreport.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/report.c - * PURPOSE: Device Changes Reporting functions - * PROGRAMMER: Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 22/09/2003 FiN Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnpreport.c + * PURPOSE: Device Changes Reporting functions + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/pnproot.c b/reactos/ntoskrnl/io/pnproot.c index a3cb5ba33cc..96191e9dae1 100644 --- a/reactos/ntoskrnl/io/pnproot.c +++ b/reactos/ntoskrnl/io/pnproot.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/pnproot.c - * PURPOSE: PnP manager root device - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 16/04/2001 CSH Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnproot.c + * PURPOSE: PnP manager root device + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES ******************************************************************/ @@ -21,7 +20,8 @@ /* DATA **********************************************************************/ -typedef struct _PNPROOT_DEVICE { +typedef struct _PNPROOT_DEVICE +{ // Entry on device list LIST_ENTRY ListEntry; // Physical Device Object of device @@ -36,7 +36,8 @@ typedef struct _PNPROOT_DEVICE { UNICODE_STRING DeviceDescription; } PNPROOT_DEVICE, *PPNPROOT_DEVICE; -typedef enum { +typedef enum +{ dsStopped, dsStarted, dsPaused, @@ -286,10 +287,6 @@ PdoQueryResourceRequirements( } -NTSTATUS -PnpRootPdoPnpControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) /* * FUNCTION: Handle Plug and Play IRPs for the child device * ARGUMENTS: @@ -298,6 +295,10 @@ PnpRootPdoPnpControl( * RETURNS: * Status */ +NTSTATUS +PnpRootPdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; @@ -354,10 +355,7 @@ PnpRootPdoPnpControl( return Status; } -NTSTATUS -PnpRootPdoPowerControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) + /* * FUNCTION: Handle power management IRPs for the child device * ARGUMENTS: @@ -366,6 +364,10 @@ PnpRootPdoPowerControl( * RETURNS: * Status */ +NTSTATUS +PnpRootPdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; @@ -409,7 +411,8 @@ PnpRootFdoReadDeviceInfo( DeviceDesc = &Device->DeviceDescription; - wcscpy(KeyName, ENUM_NAME_ROOT); + wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + wcscat(KeyName, ENUM_NAME_ROOT); wcscat(KeyName, L"\\"); wcscat(KeyName, Device->ServiceName.Buffer); wcscat(KeyName, L"\\"); @@ -426,7 +429,7 @@ PnpRootFdoReadDeviceInfo( QueryTable[0].EntryContext = DeviceDesc; Status = RtlQueryRegistryValues( - RTL_REGISTRY_ENUM, + RTL_REGISTRY_ABSOLUTE, KeyName, QueryTable, NULL, @@ -484,10 +487,10 @@ PnpRootFdoEnumerateDevices( NULL, NULL); - Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); + Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - DPRINT("NtOpenKey() failed (Status %x)\n", Status); + DPRINT("ZwOpenKey() failed (Status %x)\n", Status); ExFreePool(KeyInfo); return Status; } @@ -570,7 +573,7 @@ PnpRootFdoEnumerateDevices( DPRINT("Entries found: %d\n", Index); - NtClose(KeyHandle); + ZwClose(KeyHandle); ExFreePool(KeyInfo); @@ -668,8 +671,8 @@ PnpRootQueryBusRelations( /* FIXME: */ } - DPRINT("DeviceID: %S PDO %x\n", - PdoDeviceExtension->DeviceID.Buffer, + DPRINT1("DeviceID: %wZ PDO %p\n", + &PdoDeviceExtension->DeviceID, Device->Pdo); if (!IopCreateUnicodeString( @@ -681,6 +684,9 @@ PnpRootQueryBusRelations( /* FIXME: */ } + DPRINT1("InstanceID: %wZ PDO %p\n", + &PdoDeviceExtension->InstanceID, + Device->Pdo); } /* Reference the physical device object. The PnP manager @@ -730,11 +736,6 @@ PnpRootQueryDeviceRelations( } -NTSTATUS -STDCALL -PnpRootFdoPnpControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) /* * FUNCTION: Handle Plug and Play IRPs for the root bus device object * ARGUMENTS: @@ -743,6 +744,11 @@ PnpRootFdoPnpControl( * RETURNS: * Status */ +NTSTATUS +STDCALL +PnpRootFdoPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION IrpSp; @@ -788,11 +794,6 @@ PnpRootFdoPnpControl( } -NTSTATUS -STDCALL -PnpRootFdoPowerControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) /* * FUNCTION: Handle power management IRPs for the root bus device object * ARGUMENTS: @@ -801,6 +802,11 @@ PnpRootFdoPowerControl( * RETURNS: * Status */ +NTSTATUS +STDCALL +PnpRootFdoPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; @@ -827,11 +833,6 @@ PnpRootFdoPowerControl( } -NTSTATUS -STDCALL -PnpRootPnpControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) /* * FUNCTION: Handle Plug and Play IRPs * ARGUMENTS: @@ -840,6 +841,11 @@ PnpRootPnpControl( * RETURNS: * Status */ +NTSTATUS +STDCALL +PnpRootPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; @@ -861,11 +867,6 @@ PnpRootPnpControl( } -NTSTATUS -STDCALL -PnpRootPowerControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) /* * FUNCTION: Handle power management IRPs * ARGUMENTS: @@ -874,6 +875,11 @@ PnpRootPowerControl( * RETURNS: * Status */ +NTSTATUS +STDCALL +PnpRootPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; diff --git a/reactos/ntoskrnl/io/process.c b/reactos/ntoskrnl/io/process.c index 51537867e3b..4d04d24fa0f 100644 --- a/reactos/ntoskrnl/io/process.c +++ b/reactos/ntoskrnl/io/process.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/process.c * PURPOSE: Process functions that, bizarrely, are in the iomgr - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/queue.c b/reactos/ntoskrnl/io/queue.c index f4d55cf30dc..543f433e4bb 100644 --- a/reactos/ntoskrnl/io/queue.c +++ b/reactos/ntoskrnl/io/queue.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/queue.c - * PURPOSE: Implement device queueing - * PROGRAMMER: David Welch (welch@mcmail.com) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/queue.c + * PURPOSE: Implement device queueing + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/rawfs.c b/reactos/ntoskrnl/io/rawfs.c index 7ae9b643b86..c4198e48135 100755 --- a/reactos/ntoskrnl/io/rawfs.c +++ b/reactos/ntoskrnl/io/rawfs.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/rawfs.c * PURPOSE: Raw filesystem driver - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * Created 13/04/2003 + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ @@ -454,7 +453,6 @@ RawFsCreateFile(IN PRAWFS_IRP_CONTEXT IrpContext) return (STATUS_INSUFFICIENT_RESOURCES); } - FileObject->Flags |= FO_FCB_IS_VALID; FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers; FileObject->FsContext = pFcb; FileObject->FsContext2 = pCcb; diff --git a/reactos/ntoskrnl/io/remlock.c b/reactos/ntoskrnl/io/remlock.c index d58c096ef13..e68cbe8061e 100644 --- a/reactos/ntoskrnl/io/remlock.c +++ b/reactos/ntoskrnl/io/remlock.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/pnpmgr/remlock.c - * PURPOSE: Remove Lock functions - * PROGRAMMER: Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 22/09/2003 FiN Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/remlock.c + * PURPOSE: Remove Lock functions + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/io/resource.c b/reactos/ntoskrnl/io/resource.c index fd3fd78abd0..f066e1f63bb 100644 --- a/reactos/ntoskrnl/io/resource.c +++ b/reactos/ntoskrnl/io/resource.c @@ -1,30 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/resource.c * PURPOSE: Hardware resource managment - * PROGRAMMER: David Welch (welch@mcmail.com) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) * Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 22/05/98 */ /* INCLUDES *****************************************************************/ @@ -854,7 +836,7 @@ IoReportHalResourceUsage(PUNICODE_STRING HalDescription, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, NULL); - Status = NtCreateKey(&ResourcemapKey, + Status = ZwCreateKey(&ResourcemapKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, @@ -872,14 +854,14 @@ IoReportHalResourceUsage(PUNICODE_STRING HalDescription, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ResourcemapKey, NULL); - Status = NtCreateKey(&HalKey, + Status = ZwCreateKey(&HalKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, &Disposition); - NtClose(ResourcemapKey); + ZwClose(ResourcemapKey); if (!NT_SUCCESS(Status)) return(Status); @@ -889,21 +871,21 @@ IoReportHalResourceUsage(PUNICODE_STRING HalDescription, OBJ_CASE_INSENSITIVE, HalKey, NULL); - Status = NtCreateKey(&DescriptionKey, + Status = ZwCreateKey(&DescriptionKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, &Disposition); - NtClose(HalKey); + ZwClose(HalKey); if (!NT_SUCCESS(Status)) return(Status); /* Add '.Raw' value. */ RtlRosInitUnicodeStringFromLiteral(&Name, L".Raw"); - Status = NtSetValueKey(DescriptionKey, + Status = ZwSetValueKey(DescriptionKey, &Name, 0, REG_RESOURCE_LIST, @@ -911,20 +893,20 @@ IoReportHalResourceUsage(PUNICODE_STRING HalDescription, ListSize); if (!NT_SUCCESS(Status)) { - NtClose(DescriptionKey); + ZwClose(DescriptionKey); return(Status); } /* Add '.Translated' value. */ RtlRosInitUnicodeStringFromLiteral(&Name, L".Translated"); - Status = NtSetValueKey(DescriptionKey, + Status = ZwSetValueKey(DescriptionKey, &Name, 0, REG_RESOURCE_LIST, TranslatedList, ListSize); - NtClose(DescriptionKey); + ZwClose(DescriptionKey); return(Status); } diff --git a/reactos/ntoskrnl/io/rw.c b/reactos/ntoskrnl/io/rw.c index c0518b6d455..07af4e53701 100644 --- a/reactos/ntoskrnl/io/rw.c +++ b/reactos/ntoskrnl/io/rw.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/rw.c - * PURPOSE: Implements read/write APIs - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 30/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/rw.c + * PURPOSE: Implements read/write APIs + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/io/share.c b/reactos/ntoskrnl/io/share.c index 86c245e6b1a..735ae576d69 100644 --- a/reactos/ntoskrnl/io/share.c +++ b/reactos/ntoskrnl/io/share.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/share.c - * PURPOSE: - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/shutdown.c b/reactos/ntoskrnl/io/shutdown.c index 5fc0f62e46a..6602ceba835 100644 --- a/reactos/ntoskrnl/io/shutdown.c +++ b/reactos/ntoskrnl/io/shutdown.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/shutdown.c * PURPOSE: Implements shutdown notification - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/symlink.c b/reactos/ntoskrnl/io/symlink.c index 842d901a2fc..adccd3733c0 100644 --- a/reactos/ntoskrnl/io/symlink.c +++ b/reactos/ntoskrnl/io/symlink.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/symlink.c * PURPOSE: Implements symbolic links - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -52,17 +51,17 @@ IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, NULL, SePublicDefaultSd); - Status = NtCreateSymbolicLinkObject(&Handle, + Status = ZwCreateSymbolicLinkObject(&Handle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, DeviceName); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateSymbolicLinkObject() failed (Status %lx)\n", Status); + DPRINT1("ZwCreateSymbolicLinkObject() failed (Status %lx)\n", Status); return(Status); } - NtClose(Handle); + ZwClose(Handle); return(STATUS_SUCCESS); } @@ -121,17 +120,17 @@ IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName, NULL, &SecurityDescriptor); - Status = NtCreateSymbolicLinkObject(&Handle, + Status = ZwCreateSymbolicLinkObject(&Handle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes, DeviceName); if (!NT_SUCCESS(Status)) { - DPRINT1("NtCreateSymbolicLinkObject() failed (Status %lx)\n", Status); + DPRINT1("ZwCreateSymbolicLinkObject() failed (Status %lx)\n", Status); return(Status); } - NtClose(Handle); + ZwClose(Handle); return(STATUS_SUCCESS); } @@ -169,14 +168,14 @@ IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) NULL, NULL); - Status = NtOpenSymbolicLinkObject(&Handle, + Status = ZwOpenSymbolicLinkObject(&Handle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) return(Status); - Status = NtMakeTemporaryObject(Handle); - NtClose(Handle); + Status = ZwMakeTemporaryObject(Handle); + ZwClose(Handle); return(Status); } diff --git a/reactos/ntoskrnl/io/timer.c b/reactos/ntoskrnl/io/timer.c index 6fe893b4116..a6ba198fddb 100644 --- a/reactos/ntoskrnl/io/timer.c +++ b/reactos/ntoskrnl/io/timer.c @@ -1,12 +1,12 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/timer.c - * PURPOSE: io timers - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * Reimplemented 05/11/04 - Alex Ionescu (alex@relsoft.net) + * PURPOSE: IO timers + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/vpb.c b/reactos/ntoskrnl/io/vpb.c index 963f9b7aec5..df168e91393 100644 --- a/reactos/ntoskrnl/io/vpb.c +++ b/reactos/ntoskrnl/io/vpb.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/vpb.c * PURPOSE: Volume Parameter Block managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/wdm.c b/reactos/ntoskrnl/io/wdm.c index 4185d46bd72..e62843f6d4d 100644 --- a/reactos/ntoskrnl/io/wdm.c +++ b/reactos/ntoskrnl/io/wdm.c @@ -1,9 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/wdm.c * PURPOSE: Various Windows Driver Model routines - * PROGRAMMER: Filip Navara (xnavara@volny.cz) + * + * PROGRAMMERS: Filip Navara (xnavara@volny.cz) */ #include diff --git a/reactos/ntoskrnl/io/wmi.c b/reactos/ntoskrnl/io/wmi.c index 5d16ba961ed..8b9088270f5 100644 --- a/reactos/ntoskrnl/io/wmi.c +++ b/reactos/ntoskrnl/io/wmi.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/wmi.c * PURPOSE: Windows Management Instrumentation - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 23/06/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/xhaldisp.c b/reactos/ntoskrnl/io/xhaldisp.c index 5a8ef861d31..4c4cea3d5ab 100644 --- a/reactos/ntoskrnl/io/xhaldisp.c +++ b/reactos/ntoskrnl/io/xhaldisp.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/xhaldisp.c * PURPOSE: Hal dispatch tables - * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) - * UPDATE HISTORY: - * Created 19/06/2000 + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/io/xhaldrv.c b/reactos/ntoskrnl/io/xhaldrv.c index 0dbea45e093..5737f7ed3d3 100644 --- a/reactos/ntoskrnl/io/xhaldrv.c +++ b/reactos/ntoskrnl/io/xhaldrv.c @@ -4,10 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/xhaldrv.c * PURPOSE: Hal drive routines - * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) * Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * Created 19/06/2000 */ /* INCLUDES *****************************************************************/ @@ -447,7 +446,7 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, NULL, NULL); - Status = NtOpenFile(&FileHandle, + Status = ZwOpenFile(&FileHandle, 0x10001, &ObjectAttributes, &StatusBlock, @@ -455,7 +454,7 @@ xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(Status)) { - NtClose(FileHandle); + ZwClose(FileHandle); swprintf(Buffer2, L"\\??\\PhysicalDrive%d", diff --git a/reactos/ntoskrnl/kd/dlog.c b/reactos/ntoskrnl/kd/dlog.c index 3d0592f5a9d..2e86dcfee0e 100644 --- a/reactos/ntoskrnl/kd/dlog.c +++ b/reactos/ntoskrnl/kd/dlog.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/kd/kdebug.c * PURPOSE: Kernel debugger - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * UPDATE HISTORY: - * 21/10/99: Created + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/kd/kdebug.c b/reactos/ntoskrnl/kd/kdebug.c index 8cf5d957be0..68004e5d230 100644 --- a/reactos/ntoskrnl/kd/kdebug.c +++ b/reactos/ntoskrnl/kd/kdebug.c @@ -1,12 +1,11 @@ /* $Id$ - * + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/kd/kdebug.c * PURPOSE: Kernel debugger - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * UPDATE HISTORY: - * 21/10/99: Created + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ #include @@ -61,7 +60,8 @@ PrintString(char* fmt,...) va_list ap; va_start(ap, fmt); - vsprintf(buffer, fmt, ap); + _vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap); + buffer[sizeof(buffer) - 1] = 0; va_end(ap); HalDisplayString(buffer); @@ -243,7 +243,7 @@ KdInitSystem(ULONG BootPhase, } } } -#ifdef KDBG +#if defined(KDBG) || defined(DBG) else if (!_strnicmp(p2, "PROFILE", 7) && BootPhase > 0) { KdbInitProfiling(); diff --git a/reactos/ntoskrnl/kd/mda.c b/reactos/ntoskrnl/kd/mda.c index b8cbd392c34..cd6887ac3c3 100644 --- a/reactos/ntoskrnl/kd/mda.c +++ b/reactos/ntoskrnl/kd/mda.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/kd/mda.c * PURPOSE: Support for debugging using an MDA card. - * PROGRAMMER: David Welch + * + * PROGRAMMERS: David Welch */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/kd/service.c b/reactos/ntoskrnl/kd/service.c index 4f7833ba446..f37f9206e56 100644 --- a/reactos/ntoskrnl/kd/service.c +++ b/reactos/ntoskrnl/kd/service.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/kd/service.c * PURPOSE: Debug service dispatcher - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * UPDATE HISTORY: - * 17/01/2000: Created + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ #include diff --git a/reactos/ntoskrnl/ke/alert.c b/reactos/ntoskrnl/ke/alert.c new file mode 100644 index 00000000000..6dcc12cec1e --- /dev/null +++ b/reactos/ntoskrnl/ke/alert.c @@ -0,0 +1,149 @@ +/* $Id:$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/alert.c + * PURPOSE: Alerts + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + + +BOOLEAN +STDCALL +KeTestAlertThread(IN KPROCESSOR_MODE AlertMode) +/* + * FUNCTION: Tests whether there are any pending APCs for the current thread + * and if so the APCs will be delivered on exit from kernel mode + */ +{ + KIRQL OldIrql; + PKTHREAD Thread = KeGetCurrentThread(); + BOOLEAN OldState; + + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + + OldIrql = KeAcquireDispatcherDatabaseLock(); + KiAcquireSpinLock(&Thread->ApcQueueLock); + + /* NOTE: Albert Almeida claims Alerted[1] is never used. Two kind of + * alerts _do_ seem useless. -Gunnar + */ + OldState = Thread->Alerted[0]; + + /* If the Thread is Alerted, Clear it */ + if (OldState) { + Thread->Alerted[0] = FALSE; + } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) { + /* If the mode is User and the Queue isn't empty, set Pending */ + Thread->ApcState.UserApcPending = TRUE; + } + + KiReleaseSpinLock(&Thread->ApcQueueLock); + KeReleaseDispatcherDatabaseLock(OldIrql); + return OldState; +} + + +VOID +KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode) +{ + KIRQL oldIrql; + + + oldIrql = KeAcquireDispatcherDatabaseLock(); + + + /* Return if thread is already alerted. + * NOTE: Albert Almeida claims Alerted[1] is never used. Two kind of + * alerts _do_ seem useless. -Gunnar + */ + if (Thread->Alerted[0] == FALSE) + { + Thread->Alerted[0] = TRUE; + + if (Thread->State == THREAD_STATE_BLOCKED && + Thread->WaitMode == AlertMode && + Thread->Alertable) + { + KiAbortWaitThread(Thread, STATUS_ALERTED); + } + } + + KeReleaseDispatcherDatabaseLock(oldIrql); + +} + + +/* + * + * NOT EXPORTED + */ +NTSTATUS STDCALL +NtAlertResumeThread(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount) +{ + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); + +} + +/* + * @implemented + * + * EXPORTED + */ +NTSTATUS STDCALL +NtAlertThread (IN HANDLE ThreadHandle) +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + ExGetPreviousMode(), + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* FIXME: should we always use UserMode here, even if the ntoskrnl exported + * ZwAlertThread was called? + * -Gunnar + */ + KeAlertThread((PKTHREAD)Thread, UserMode); + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} + + +/* + * NOT EXPORTED + */ +NTSTATUS +STDCALL +NtTestAlert(VOID) +{ + /* Check and Alert Thread if needed */ + if (KeTestAlertThread(KeGetPreviousMode())) { + return STATUS_ALERTED; + } else { + return STATUS_SUCCESS; + } +} + diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index a495ed74c61..ca7b3d45f63 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -1,31 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/apc.c * PURPOSE: NT Implementation of APCs - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * PORTABILITY: Unchecked - * UPDATE HISTORY: - * Created 22/05/98 - * 12/11/99: Phillip Susi: Reworked the APC code - * 11/11/04: Alex Ionescu - Total Rewrite + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * Phillip Susi */ /* INCLUDES *****************************************************************/ @@ -262,37 +243,6 @@ KeRemoveQueueApc (PKAPC Apc) return(TRUE); } -BOOLEAN -STDCALL -KeTestAlertThread(IN KPROCESSOR_MODE AlertMode) -/* - * FUNCTION: Tests whether there are any pending APCs for the current thread - * and if so the APCs will be delivered on exit from kernel mode - */ -{ - KIRQL OldIrql; - PKTHREAD Thread = KeGetCurrentThread(); - BOOLEAN OldState; - - ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); - - OldIrql = KeAcquireDispatcherDatabaseLock(); - KiAcquireSpinLock(&Thread->ApcQueueLock); - - OldState = Thread->Alerted[(int)AlertMode]; - - /* If the Thread is Alerted, Clear it */ - if (OldState) { - Thread->Alerted[(int)AlertMode] = FALSE; - } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) { - /* If the mode is User and the Queue isn't empty, set Pending */ - Thread->ApcState.UserApcPending = TRUE; - } - - KiReleaseSpinLock(&Thread->ApcQueueLock); - KeReleaseDispatcherDatabaseLock(OldIrql); - return OldState; -} /* * @implemented @@ -615,17 +565,6 @@ NtQueueApcThread(HANDLE ThreadHandle, return Status; } -NTSTATUS -STDCALL -NtTestAlert(VOID) -{ - /* Check and Alert Thread if needed */ - if (KeTestAlertThread(KeGetPreviousMode())) { - return STATUS_ALERTED; - } else { - return STATUS_SUCCESS; - } -} static inline VOID RepairList(PLIST_ENTRY Original, PLIST_ENTRY Copy, diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index 2e8df660bb8..2af3e26b721 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -1,31 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/bug.c * PURPOSE: Graceful system shutdown if a bug is detected - * PROGRAMMER: David Welch (welch@cwcom.net) - * PORTABILITY: Unchecked - * UPDATE HISTORY: - * Created 22/05/98 - * Phillip Susi: 12/8/99: Minor fix + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Phillip Susi */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/catch.c b/reactos/ntoskrnl/ke/catch.c index 9d54d4b61be..1d4ca92a486 100644 --- a/reactos/ntoskrnl/ke/catch.c +++ b/reactos/ntoskrnl/ke/catch.c @@ -1,28 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/catch.c - * PURPOSE: Exception handling - * PROGRAMMER: David Welch (welch@mcmail.com) - * Casper S. Hornstrup (chorns@users.sourceforge.net) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/catch.c + * PURPOSE: Exception handling + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ @@ -50,6 +34,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, DPRINT("KiDispatchException() called\n"); + /* PCR->KeExceptionDispatchCount++; */ if (Context == NULL) @@ -95,8 +80,12 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, NTSTATUS StatusOfCopy; #ifdef KDBG - KdbEnterDebuggerException (ExceptionRecord, PreviousMode, - Context, Tf, FALSE); + Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode, + Context, Tf, FALSE); + if (Action == kdContinue) + { + return; + } #endif /* FIXME: Forward exception to user mode debugger */ @@ -141,8 +130,12 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, /* FIXME: Forward the exception to the process exception port */ #ifdef KDBG - KdbEnterDebuggerException (ExceptionRecord, PreviousMode, - Context, Tf, TRUE); + Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode, + Context, Tf, TRUE); + if (Action == kdContinue) + { + return; + } #endif /* Terminate the offending thread */ @@ -153,8 +146,12 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, { /* PreviousMode == KernelMode */ #ifdef KDBG - KdbEnterDebuggerException (ExceptionRecord, PreviousMode, - Context, Tf, FALSE); + Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode, + Context, Tf, FALSE); + if (Action == kdContinue) + { + return; + } #endif Value = RtlpDispatchException (ExceptionRecord, Context); diff --git a/reactos/ntoskrnl/ke/critical.c b/reactos/ntoskrnl/ke/critical.c index 09b39bd04e5..e2428549b45 100644 --- a/reactos/ntoskrnl/ke/critical.c +++ b/reactos/ntoskrnl/ke/critical.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/critical.c * PURPOSE: Implement critical regions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/device.c b/reactos/ntoskrnl/ke/device.c index 56473d18b32..ad1c8bd32dd 100644 --- a/reactos/ntoskrnl/ke/device.c +++ b/reactos/ntoskrnl/ke/device.c @@ -1,10 +1,11 @@ /* $Id$ * - * FILE: ntoskrnl/ke/profile.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/device.c * PURPOSE: Kernel Device/Settings Functions - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 23/06/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ #include diff --git a/reactos/ntoskrnl/ke/dpc.c b/reactos/ntoskrnl/ke/dpc.c index 37d1bed8612..2aee866c39d 100644 --- a/reactos/ntoskrnl/ke/dpc.c +++ b/reactos/ntoskrnl/ke/dpc.c @@ -1,35 +1,14 @@ -/* - * ReactOS kernel - * Copyright (C) 2000, 1999, 1998 David Welch , - * Philip Susi , - * Eric Kohl - * Alex Ionescu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/dpc.c * PURPOSE: Handle DPCs (Delayed Procedure Calls) - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 28/05/98: Created - * 12/3/99: Phillip Susi: Fixed IRQL problem - * 12/11/04: Alex Ionescu - Major rewrite. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Philip Susi (phreak@iag.net) + * Eric Kohl (ekohl@abo.rhein-zeitung.de) + * Alex Ionescu (alex@relsoft.net) */ /* @@ -193,7 +172,7 @@ KeInsertQueueDpc (PKDPC Dpc, // KeLowerIrql(OldIrql); //} -#ifdef MP +#ifdef CONFIG_SMP /* Get the right PCR for this CPU */ if (Dpc->Number >= MAXIMUM_PROCESSORS) { ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors); @@ -211,7 +190,7 @@ KeInsertQueueDpc (PKDPC Dpc, /* Get the DPC Data */ if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) { DPRINT("DPC Already Inserted"); -#ifdef MP +#ifdef CONFIG_SMP KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); #endif KeLowerIrql(OldIrql); @@ -242,7 +221,7 @@ KeInsertQueueDpc (PKDPC Dpc, /* Make sure a DPC isn't executing already and respect rules outlined above. */ if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) { -#ifdef MP +#ifdef CONFIG_SMP /* Check if this is the same CPU */ if (Pcr != KeGetCurrentKPCR()) { /* Send IPI if High Importance */ @@ -280,7 +259,7 @@ KeInsertQueueDpc (PKDPC Dpc, } #endif } -#ifdef MP +#ifdef CONFIG_SMP KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); #endif /* Lower IRQL */ @@ -309,7 +288,7 @@ KeRemoveQueueDpc (PKDPC Dpc) /* Raise IRQL */ DPRINT("Removing DPC: %x\n", Dpc); KeRaiseIrql(HIGH_LEVEL, &OldIrql); -#ifdef MP +#ifdef CONFIG_SMP KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); #endif @@ -322,7 +301,7 @@ KeRemoveQueueDpc (PKDPC Dpc) RemoveEntryList(&Dpc->DpcListEntry); } -#ifdef MP +#ifdef CONFIG_SMP KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); #endif @@ -494,7 +473,7 @@ KiDispatchInterrupt(VOID) if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) { /* Raise IRQL */ KeRaiseIrql(HIGH_LEVEL, &OldIrql); -#ifdef MP +#ifdef CONFIG_SMP KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); #endif Pcr->PrcbData.DpcRoutineActive = TRUE; @@ -511,7 +490,7 @@ KiDispatchInterrupt(VOID) DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink); Dpc->DpcData = NULL; Pcr->PrcbData.DpcData[0].DpcQueueDepth--; -#ifdef MP +#ifdef CONFIG_SMP KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); #endif /* Disable/Enabled Interrupts and Call the DPC */ @@ -523,7 +502,7 @@ KiDispatchInterrupt(VOID) Dpc->SystemArgument2); KeRaiseIrql(HIGH_LEVEL, &OldIrql); -#ifdef MP +#ifdef CONFIG_SMP KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); /* * If the dpc routine drops the irql below DISPATCH_LEVEL, @@ -542,7 +521,7 @@ KiDispatchInterrupt(VOID) /* Clear DPC Flags */ Pcr->PrcbData.DpcRoutineActive = FALSE; Pcr->PrcbData.DpcInterruptRequested = FALSE; -#ifdef MP +#ifdef CONFIG_SMP KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); #endif diff --git a/reactos/ntoskrnl/ke/error.c b/reactos/ntoskrnl/ke/error.c index e6759423edc..da0033e221a 100644 --- a/reactos/ntoskrnl/ke/error.c +++ b/reactos/ntoskrnl/ke/error.c @@ -1,12 +1,11 @@ -/* $Id $ +/* $Id$ * - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel v0.0.2 - * FILE: ntoskrnl/ke/error.c - * PURPOSE: Error reason setting/getting - * PROGRAMMER: David Welch - * UPDATE HISTORY: - * 16/4/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/error.c + * PURPOSE: Error reason setting/getting + * + * PROGRAMMERS: David Welch */ /* INCLUDE *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/event.c b/reactos/ntoskrnl/ke/event.c index b352142f623..5ef0e626bf4 100644 --- a/reactos/ntoskrnl/ke/event.c +++ b/reactos/ntoskrnl/ke/event.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/event.c * PURPOSE: Implements events - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -87,9 +87,9 @@ LONG STDCALL KeSetEvent (PKEVENT Event, OldIrql = KeAcquireDispatcherDatabaseLock(); - ret = InterlockedExchange(&(Event->Header.SignalState),1); + ret = InterlockedExchange(&Event->Header.SignalState,1); - KiDispatcherObjectWake((DISPATCHER_HEADER *)Event); + KiDispatcherObjectWake(&Event->Header, Increment); if (Wait == FALSE) { @@ -108,17 +108,18 @@ LONG STDCALL KeSetEvent (PKEVENT Event, /* * @implemented */ -NTSTATUS STDCALL KePulseEvent (PKEVENT Event, - KPRIORITY Increment, - BOOLEAN Wait) +LONG STDCALL +KePulseEvent (IN PKEVENT Event, + IN KPRIORITY Increment, + IN BOOLEAN Wait) { KIRQL OldIrql; - int ret; + LONG Ret; DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait); OldIrql = KeAcquireDispatcherDatabaseLock(); - ret = InterlockedExchange(&(Event->Header.SignalState),1); - KiDispatcherObjectWake((DISPATCHER_HEADER *)Event); + Ret = InterlockedExchange(&Event->Header.SignalState,1); + KiDispatcherObjectWake(&Event->Header, Increment); InterlockedExchange(&(Event->Header.SignalState),0); if (Wait == FALSE) @@ -132,7 +133,7 @@ NTSTATUS STDCALL KePulseEvent (PKEVENT Event, Thread->WaitIrql = OldIrql; } - return ((NTSTATUS)ret); + return Ret; } /* diff --git a/reactos/ntoskrnl/ke/gmutex.c b/reactos/ntoskrnl/ke/gmutex.c index 0c1db8c1cbf..35d1d436276 100644 --- a/reactos/ntoskrnl/ke/gmutex.c +++ b/reactos/ntoskrnl/ke/gmutex.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/gmutex.c * PURPOSE: Implements guarded mutex (w2k3+/64) - * PROGRAMMER: - * UPDATE HISTORY: - * Created 2004-10-31 based on Steve Dispensa's blog + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/bios.c b/reactos/ntoskrnl/ke/i386/bios.c index e89f7df8e92..facd6a9c6c6 100644 --- a/reactos/ntoskrnl/ke/i386/bios.c +++ b/reactos/ntoskrnl/ke/i386/bios.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/bios.c * PURPOSE: Support for calling the BIOS in v86 mode - * PROGRAMMER: David Welch (welch@cwcom.net) + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/brkpoint.c b/reactos/ntoskrnl/ke/i386/brkpoint.c index f81480e88bf..e2c668a34db 100644 --- a/reactos/ntoskrnl/ke/i386/brkpoint.c +++ b/reactos/ntoskrnl/ke/i386/brkpoint.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/brkpoints.c + * FILE: ntoskrnl/ke/i386/brkpoint.c * PURPOSE: Handles breakpoints + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/bthread.S b/reactos/ntoskrnl/ke/i386/bthread.S index 54b6abc1714..b0139e9e491 100644 --- a/reactos/ntoskrnl/ke/i386/bthread.S +++ b/reactos/ntoskrnl/ke/i386/bthread.S @@ -143,4 +143,4 @@ _PsBeginThreadWithContextInternal: /* Load the rest of the thread's user mode context. */ movl $0, %eax - jmp KeReturnFromSystemCallWithHook + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index e1105f5e3ea..5f8c9a8751c 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -1,36 +1,17 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/exp.c - * PURPOSE: Handling exceptions - * PROGRAMMERS: David Welch (welch@cwcom.net) - * Skywing (skywing@valhallalegends.com) - * REVISION HISTORY: - * ??/??/??: Created - * 09/12/03: KeRaiseUserException added (Skywing). +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/exp.c + * PURPOSE: Handling exceptions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Skywing (skywing@valhallalegends.com) */ /* INCLUDES *****************************************************************/ #include -#include + #define NDEBUG #include @@ -45,7 +26,7 @@ # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0])) #endif -extern void interrupt_handler2e(void); +extern void KiSystemService(void); extern void interrupt_handler2d(void); extern VOID KiTrap0(VOID); @@ -99,7 +80,7 @@ static char *ExceptionTypeStrings[] = "SIMD Fault" }; -static NTSTATUS ExceptionToNtStatus[] = +NTSTATUS ExceptionToNtStatus[] = { STATUS_INTEGER_DIVIDE_BY_ZERO, STATUS_SINGLE_STEP, @@ -108,7 +89,7 @@ static NTSTATUS ExceptionToNtStatus[] = STATUS_INTEGER_OVERFLOW, STATUS_ARRAY_BOUNDS_EXCEEDED, STATUS_ILLEGAL_INSTRUCTION, - STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_FLOAT_INVALID_OPERATION, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, @@ -117,10 +98,10 @@ static NTSTATUS ExceptionToNtStatus[] = STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, STATUS_ACCESS_VIOLATION, /* RESERVED */ - STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */ STATUS_DATATYPE_MISALIGNMENT, STATUS_ACCESS_VIOLATION, - STATUS_ACCESS_VIOLATION /* STATUS_FLT_MULTIPLE_TRAPS? */ + STATUS_FLOAT_MULTIPLE_TRAPS, }; /* FUNCTIONS ****************************************************************/ @@ -190,9 +171,8 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) Er.NumberParameters = 0; } - Er.ExceptionFlags = ((NTSTATUS) STATUS_SINGLE_STEP == (NTSTATUS) Er.ExceptionCode - || (NTSTATUS) STATUS_BREAKPOINT == (NTSTATUS) Er.ExceptionCode) ? - EXCEPTION_NONCONTINUABLE : 0; + /* FIXME: Which exceptions are noncontinuable? */ + Er.ExceptionFlags = 0; KiDispatchException(&Er, 0, Tf, KernelMode, TRUE); @@ -305,8 +285,8 @@ KiDoubleFaultHandler(VOID) } else { - StackLimit = (ULONG)&init_stack_top; - StackBase = (ULONG)&init_stack; + StackLimit = (ULONG)init_stack_top; + StackBase = (ULONG)init_stack; } /* @@ -412,9 +392,7 @@ VOID KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2) { ULONG cr3_; - ULONG i; ULONG StackLimit; - PULONG Frame; ULONG Esp0; ULONG ExceptionNr = (ULONG)Tf->DebugArgMark; ULONG cr2 = (ULONG)Tf->DebugPointer; @@ -475,52 +453,13 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2) } else { - StackLimit = (ULONG)&init_stack_top; + StackLimit = (ULONG)init_stack_top; } /* * Dump the stack frames */ - DbgPrint("Frames: "); - /* Change to an #if 0 if no frames are printed because of fpo. */ -#if 1 - i = 1; - Frame = (PULONG)Tf->Ebp; - while (Frame != NULL) - { - NTSTATUS Status; - PVOID Eip; - Status = MmSafeCopyFromUser(&Eip, Frame + 1, sizeof(Eip)); - if (!NT_SUCCESS(Status)) - { - DbgPrint(""); - break; - } - if (!KeRosPrintAddress(Eip)) - { - DbgPrint("<%X>", Eip); - } - Status = MmSafeCopyFromUser(&Frame, Frame, sizeof(Frame)); - if (!NT_SUCCESS(Status)) - { - break; - } - i++; - DbgPrint(" "); - } -#else - i = 1; - Frame = (PULONG)((ULONG_PTR)Esp0 + KTRAP_FRAME_EFLAGS); - while (Frame < (PULONG)PsGetCurrentThread()->Tcb.StackBase && i < 50) - { - ULONG Address = *Frame; - if (KeRosPrintAddress((PVOID)Address)) - { - i++; - } - Frame++; - } -#endif + KeDumpStackFrames((PULONG)Tf->Ebp); } ULONG @@ -635,7 +574,7 @@ KeDumpStackFrames(PULONG Frame) ULONG ResultLength = sizeof(mbi); NTSTATUS Status; - DbgPrint("Frames: "); + DbgPrint("Frames:\n"); _SEH_TRY { Status = MiQueryVirtualMemory ( @@ -851,51 +790,55 @@ KeInitExceptions(VOID) } set_system_call_gate(0x2d,(int)interrupt_handler2d); - set_system_call_gate(0x2e,(int)interrupt_handler2e); + set_system_call_gate(0x2e,(int)KiSystemService); } /* * @implemented */ - NTSTATUS STDCALL KeRaiseUserException(IN NTSTATUS ExceptionCode) { - /* FIXME: This needs SEH */ ULONG OldEip; PKTHREAD Thread = KeGetCurrentThread(); - ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */ + _SEH_TRY { + Thread->Teb->ExceptionCode = ExceptionCode; + } _SEH_HANDLE { + return(ExceptionCode); + } _SEH_END; + OldEip = Thread->TrapFrame->Eip; Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher(); - Thread->Teb->ExceptionCode = ExceptionCode; return((NTSTATUS)OldEip); } -VOID -FASTCALL -KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame ); - /* * @implemented */ -NTSTATUS STDCALL +NTSTATUS +STDCALL NtRaiseException ( - IN PEXCEPTION_RECORD ExceptionRecord, - IN PCONTEXT Context, - IN BOOLEAN SearchFrames) + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN BOOLEAN SearchFrames) { - PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame; - PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; + PKTHREAD Thread = KeGetCurrentThread(); + PKTRAP_FRAME TrapFrame = Thread->TrapFrame; + PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; - KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList; + KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList; - KiDispatchException(ExceptionRecord, - Context, - PsGetCurrentThread()->Tcb.TrapFrame, - (KPROCESSOR_MODE)ExGetPreviousMode(), - SearchFrames); + KiDispatchException(ExceptionRecord, + Context, + TrapFrame, + KeGetPreviousMode(), + SearchFrames); - KeRosTrapReturn ( TrapFrame, PrevTrapFrame ); - return(STATUS_SUCCESS); + /* Restore the user context */ + Thread->TrapFrame = PrevTrapFrame; + __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame)); + + /* We never get here */ + return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ke/i386/fpu.c b/reactos/ntoskrnl/ke/i386/fpu.c index 7668573ed68..cb94a7078af 100644 --- a/reactos/ntoskrnl/ke/i386/fpu.c +++ b/reactos/ntoskrnl/ke/i386/fpu.c @@ -1,29 +1,11 @@ /* $Id$ * - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/fpu.c * PURPOSE: Handles the FPU - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -35,16 +17,6 @@ /* DEFINES *******************************************************************/ -#define EXCEPTION_FLT_DENORMAL_OPERAND (0xc000008dL) -#define EXCEPTION_FLT_DIVIDE_BY_ZERO (0xc000008eL) -#define EXCEPTION_FLT_INEXACT_RESULT (0xc000008fL) -#define EXCEPTION_FLT_INVALID_OPERATION (0xc0000090L) -#define EXCEPTION_FLT_OVERFLOW (0xc0000091L) -#define EXCEPTION_FLT_STACK_CHECK (0xc0000092L) -#define EXCEPTION_FLT_UNDERFLOW (0xc0000093L) -#define EXCEPTION_FLT_MULTIPLE_FAULTS (0xC00002B4L) -#define EXCEPTION_FLT_MULTIPLE_TRAPS (0xC00002B5L) - /* x87 Status Word exception flags */ #define X87_SW_IE (1<<0) /* Invalid Operation */ #define X87_SW_DE (1<<1) /* Denormalized Operand */ @@ -69,7 +41,7 @@ ULONG HardwareMathSupport = 0; static ULONG MxcsrFeatureMask = 0, XmmSupport = 0; -ULONG FxsrSupport = 0; /* used by Ki386ContextSwitch for MP */ +ULONG FxsrSupport = 0; /* used by Ki386ContextSwitch for SMP */ /* FUNCTIONS *****************************************************************/ @@ -413,7 +385,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) PKTHREAD CurrentThread; PFX_SAVE_AREA FxSaveArea; KIRQL oldIrql; -#ifndef MP +#ifndef CONFIG_SMP PKTHREAD NpxThread; #endif @@ -428,14 +400,14 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) asm volatile("clts"); CurrentThread = KeGetCurrentThread(); -#ifndef MP +#ifndef CONFIG_SMP NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread; #endif ASSERT(CurrentThread != NULL); DPRINT("Device not present exception happened! (Cr0 = 0x%x, NpxState = 0x%x)\n", cr0, CurrentThread->NpxState); -#ifndef MP +#ifndef CONFIG_SMP /* check if the current thread already owns the FPU */ if (NpxThread != CurrentThread) /* FIXME: maybe this could be an assertation */ { @@ -456,7 +428,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) } NpxThread->NpxState = NPX_STATE_VALID; } -#endif /* !MP */ +#endif /* !CONFIG_SMP */ /* restore the state of the current thread */ ASSERT((CurrentThread->NpxState & NPX_STATE_DIRTY) == 0); @@ -492,7 +464,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) } } KeGetCurrentKPCR()->PrcbData.NpxThread = CurrentThread; -#ifndef MP +#ifndef CONFIG_SMP } #endif @@ -566,19 +538,19 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) DPRINT("FpuStatusWord = 0x%04x\n", FpuStatusWord); if (FpuStatusWord & X87_SW_IE) - Er.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION; + Er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; else if (FpuStatusWord & X87_SW_DE) - Er.ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND; + Er.ExceptionCode = STATUS_FLOAT_DENORMAL_OPERAND; else if (FpuStatusWord & X87_SW_ZE) - Er.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO; + Er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; else if (FpuStatusWord & X87_SW_OE) - Er.ExceptionCode = EXCEPTION_FLT_OVERFLOW; + Er.ExceptionCode = STATUS_FLOAT_OVERFLOW; else if (FpuStatusWord & X87_SW_UE) - Er.ExceptionCode = EXCEPTION_FLT_UNDERFLOW; + Er.ExceptionCode = STATUS_FLOAT_UNDERFLOW; else if (FpuStatusWord & X87_SW_PE) - Er.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT; + Er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; else if (FpuStatusWord & X87_SW_SE) - Er.ExceptionCode = EXCEPTION_FLT_STACK_CHECK; + Er.ExceptionCode = STATUS_FLOAT_STACK_CHECK; else ASSERT(0); /* not reached */ /* FIXME: is this the right way to get the correct EIP of the faulting instruction? */ @@ -586,8 +558,8 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) } else /* ExceptionNr == 19 */ { - /* FIXME: When should we use EXCEPTION_FLT_MULTIPLE_FAULTS? */ - Er.ExceptionCode = EXCEPTION_FLT_MULTIPLE_TRAPS; + /* FIXME: When should we use STATUS_FLOAT_MULTIPLE_FAULTS? */ + Er.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS; Er.ExceptionAddress = (PVOID)Tf->Eip; } diff --git a/reactos/ntoskrnl/ke/i386/gdt.c b/reactos/ntoskrnl/ke/i386/gdt.c index ac06f5c1b22..716eb7cddcd 100644 --- a/reactos/ntoskrnl/ke/i386/gdt.c +++ b/reactos/ntoskrnl/ke/i386/gdt.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/gdt.c + * FILE: ntoskrnl/ke/i386/gdt.c * PURPOSE: GDT managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -40,11 +23,11 @@ USHORT KiBootGdt[11 * 4] = 0x0, 0x0, 0x0, 0x0, /* Null */ 0xffff, 0x0, 0x9a00, 0xcf, /* Kernel CS */ 0xffff, 0x0, 0x9200, 0xcf, /* Kernel DS */ - 0x0, 0x0, 0xfa00, 0xcc, /* User CS */ - 0x0, 0x0, 0xf200, 0xcc, /* User DS */ + 0xffff, 0x0, 0xfa00, 0xcf, /* User CS */ + 0xffff, 0x0, 0xf200, 0xcf, /* User DS */ 0x0, 0x0, 0x0, 0x0, /* TSS */ - 0x1000, 0x0000, 0x9200, 0xff00, /* PCR */ - 0x1000, 0x0, 0xf200, 0x0, /* TEB */ + 0x0fff, 0x0000, 0x9200, 0xff00, /* PCR */ + 0x0fff, 0x0, 0xf200, 0x0, /* TEB */ 0x0, 0x0, 0x0, 0x0, /* Reserved */ 0x0, 0x0, 0x0, 0x0, /* LDT */ 0x0, 0x0, 0x0, 0x0 /* Trap TSS */ diff --git a/reactos/ntoskrnl/ke/i386/idt.c b/reactos/ntoskrnl/ke/i386/idt.c index 2e45ae8958d..e4c4486beaa 100644 --- a/reactos/ntoskrnl/ke/i386/idt.c +++ b/reactos/ntoskrnl/ke/i386/idt.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/idt.c + * FILE: ntoskrnl/ke/i386/idt.c * PURPOSE: IDT managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index d35116313e6..cf90d44695f 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -1,30 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998 - 2005 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ - * + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/irq.c * PURPOSE: IRQ handling - * PROGRAMMER: David Welch (welch@mcmail.com) + * + * PROGRAMMERS: David Welch (welch@mcmail.com) * Hartmut Birr - * UPDATE HISTORY: - * 29/05/98: Created */ /* @@ -37,7 +19,7 @@ /* INCLUDES ****************************************************************/ #include -#ifdef KDBG +#if defined(KDBG) || defined(DBG) #include <../dbg/kdb.h> #endif /* KDBG */ @@ -48,7 +30,7 @@ /* GLOBALS *****************************************************************/ -#ifdef MP +#ifdef CONFIG_SMP #define __STR(x) #x #define STR(x) __STR(x) @@ -136,7 +118,7 @@ static ULONG irq_handler[ROUND_UP(NR_IRQS, 16)] = { #undef L #undef L16 -#else /* MP */ +#else /* CONFIG_SMP */ void irq_handler_0(void); void irq_handler_1(void); @@ -175,7 +157,7 @@ static unsigned int irq_handler[NR_IRQS]= (int)&irq_handler_15, }; -#endif /* MP */ +#endif /* CONFIG_SMP */ /* * PURPOSE: Object describing each isr @@ -191,7 +173,7 @@ typedef struct } ISR_TABLE, *PISR_TABLE; -#ifdef MP +#ifdef CONFIG_SMP static ISR_TABLE IsrTable[NR_IRQS][MAXIMUM_PROCESSORS]; #else static ISR_TABLE IsrTable[NR_IRQS][1]; @@ -218,7 +200,7 @@ KeInitInterrupts (VOID) KiIdt[IRQ_BASE+i].a=(irq_handler[i]&0xffff)+(KERNEL_CS<<16); KiIdt[IRQ_BASE+i].b=(irq_handler[i]&0xffff0000)+PRESENT+ I486_INTERRUPT_GATE; -#ifdef MP +#ifdef CONFIG_SMP for (j = 0; j < MAXIMUM_PROCESSORS; j++) #else j = 0; @@ -353,12 +335,12 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe) */ Ke386EnableInterrupts(); -#ifndef MP +#ifndef CONFIG_SMP if (VECTOR2IRQ(vector) == 0) { KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); KeUpdateSystemTime(&KernelTrapFrame, old_level); -#ifdef KDBG +#if defined(KDBG) || defined(DBG) KdbProfileInterrupt(Trapframe->Eip); #endif /* KDBG */ } @@ -462,7 +444,7 @@ KeConnectInterrupt(PKINTERRUPT InterruptObject) Vector = InterruptObject->Vector; - if (Vector < IRQ_BASE && Vector >= IRQ_BASE + NR_IRQS) + if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) return FALSE; Vector -= IRQ_BASE; diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index fc0eba13e61..a1ffb830baf 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/kernel.c * PURPOSE: Initializes the kernel - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -41,8 +24,8 @@ CHAR Ke386CpuidModel[49] = {0,}; ULONG Ke386L1CacheSize; BOOLEAN Ke386NoExecute = FALSE; BOOLEAN Ke386Pae = FALSE; -BOOLEAN Ke386PaeEnabled = FALSE; BOOLEAN Ke386GlobalPagesEnabled = FALSE; +ULONG KiFastSystemCallDisable = 1; /* FUNCTIONS *****************************************************************/ @@ -191,6 +174,18 @@ KeApplicationProcessorInit(VOID) KeInitDpc(Pcr); + if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) + { + extern void KiFastCallEntry(void); + + /* CS Selector of the target segment. */ + Ke386Wrmsr(0x174, KERNEL_CS, 0); + /* Target ESP. */ + Ke386Wrmsr(0x175, 0, 0); + /* Target EIP. */ + Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0); + } + /* * It is now safe to process interrupts */ @@ -290,7 +285,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress) } p1 = p2; } - +#if 0 /* * FIXME: * Make the detection of the noexecute feature more portable. @@ -315,14 +310,28 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress) { NoExecute=FALSE; } +#endif - + Ke386Pae = Ke386GetCr4() & X86_CR4_PAE ? TRUE : FALSE; +#if 0 /* Enable PAE mode */ if ((Pae && (KPCR->PrcbData.FeatureBits & X86_FEATURE_PAE)) || NoExecute) { MiEnablePAE((PVOID*)LastKernelAddress); Ke386PaeEnabled = TRUE; } +#endif + if (KPCR->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) + { + extern void KiFastCallEntry(void); + + /* CS Selector of the target segment. */ + Ke386Wrmsr(0x174, KERNEL_CS, 0); + /* Target ESP. */ + Ke386Wrmsr(0x175, 0, 0); + /* Target EIP. */ + Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0); + } } VOID INIT_FUNCTION @@ -391,23 +400,93 @@ KeInit2(VOID) VOID INIT_FUNCTION Ki386SetProcessorFeatures(VOID) { - PKPCR Pcr = KeGetCurrentKPCR(); + PKPCR Pcr = KeGetCurrentKPCR(); + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + ULONG ResultLength; + KEY_VALUE_PARTIAL_INFORMATION ValueData; + NTSTATUS Status; + ULONG FastSystemCallDisable = 0; - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; - SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8); - SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX); - SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; - SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; - SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE); - SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = - (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW); - SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC); - SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386PaeEnabled; - SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2); + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; + SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8); + SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX); + SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; + SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; + SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE); + SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = + (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW); + SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC); + SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386Pae; + SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2); + + /* Does the CPU Support Fast System Call? */ + if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) { + + /* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */ + + /* Make sure it's not disabled in registry */ + RtlRosInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel"); + RtlRosInitUnicodeStringFromLiteral(&ValueName, + L"FastSystemCallDisable"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); + + if (NT_SUCCESS(Status)) { + + /* Read the Value then Close the Key */ + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + &ValueData, + sizeof(ValueData), + &ResultLength); + RtlMoveMemory(&FastSystemCallDisable, ValueData.Data, sizeof(ULONG)); + + NtClose(KeyHandle); + } + + } else { + + /* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */ + FastSystemCallDisable = 1; + + } + + if (FastSystemCallDisable) { + + /* Use INT2E */ + SharedUserData->SystemCall[0] = 0x8D; + SharedUserData->SystemCall[1] = 0x54; + SharedUserData->SystemCall[2] = 0x24; + SharedUserData->SystemCall[3] = 0x08; + SharedUserData->SystemCall[4] = 0xCD; + SharedUserData->SystemCall[5] = 0x2E; + SharedUserData->SystemCall[6] = 0xC3; + + } else { + + /* Use SYSENTER */ + SharedUserData->SystemCall[0] = 0x8B; + SharedUserData->SystemCall[1] = 0xD4; + SharedUserData->SystemCall[2] = 0x0F; + SharedUserData->SystemCall[3] = 0x34; + SharedUserData->SystemCall[4] = 0xC3; + + /* Enable SYSENTER/SYSEXIT */ + KiFastSystemCallDisable = 0; + } } diff --git a/reactos/ntoskrnl/ke/i386/ldt.c b/reactos/ntoskrnl/ke/i386/ldt.c index aa7d33b9d75..cc9047bdc4c 100644 --- a/reactos/ntoskrnl/ke/i386/ldt.c +++ b/reactos/ntoskrnl/ke/i386/ldt.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/ldt.c * PURPOSE: LDT managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/main.S b/reactos/ntoskrnl/ke/i386/main.S new file mode 100644 index 00000000000..ab0374f7af9 --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/main.S @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include +#include + +.globl _NtProcessStartup + +_NtProcessStartup: + + /* FIXME: Application processors should have their own GDT/IDT */ + lgdt _KiGdtDescriptor + lidt _KiIdtDescriptor + + /* Load the PCR selector */ + movl $PCR_SELECTOR, %eax + movl %eax, %fs + + /* Load the initial kernel stack */ + lea _kernel_stack, %eax + add $0x1000, %eax + and $0xFFFFE000, %eax + add $(0x3000 - SIZEOF_FX_SAVE_AREA), %eax + movl %eax, %esp + + /* Call the main kernel initialization */ + pushl %edx + pushl %ecx + call __main diff --git a/reactos/ntoskrnl/ke/i386/multiboot.S b/reactos/ntoskrnl/ke/i386/multiboot.S index d8b41891124..455cce90607 100644 --- a/reactos/ntoskrnl/ke/i386/multiboot.S +++ b/reactos/ntoskrnl/ke/i386/multiboot.S @@ -12,11 +12,11 @@ #define V2P(x) (x - KERNEL_BASE + 0x200000) -#ifdef MP +#ifdef CONFIG_SMP #define AP_MAGIC (0x12481020) -#endif /* MP */ +#endif /* CONFIG_SMP */ .globl _NtProcessStartup .globl _start @@ -79,7 +79,7 @@ _multiboot_entry: */ cld -#ifdef MP +#ifdef CONFIG_SMP /* * Save the multiboot or application processor magic @@ -89,7 +89,7 @@ _multiboot_entry: cmpl $AP_MAGIC, %edx je .m1 -#endif /* MP */ +#endif /* CONFIG_SMP */ /* * Zero the BSS @@ -114,10 +114,10 @@ _multiboot_entry: movl $(V2P(kernel_pagetable+4096) + 0x3), ((KERNEL_BASE >> 20) + 4)(%esi) movl $(V2P(startup_pagedirectory) + 0x3), 0xF00(%esi) - movl $(V2P(kernelmap_pagetable) + 0x3), 0xF0C(%esi) -#ifdef MP + movl $(V2P(hyperspace_pagetable) + 0x3), 0xF08(%esi) +#ifdef CONFIG_SMP movl $(V2P(apic_pagetable) + 0x3), 0xFEC(%esi) -#endif /* MP */ +#endif /* CONFIG_SMP */ movl $(V2P(kpcr_pagetable) + 0x3), 0xFF0(%esi) /* @@ -146,7 +146,7 @@ _multiboot_entry: cmpl $6144, %edi jl .l4 -#ifdef MP +#ifdef CONFIG_SMP /* * Initialize the page table that maps the APIC register address space @@ -164,7 +164,7 @@ _multiboot_entry: movl $0xFEE0001B, %eax movl %eax, (%esi, %edi) -#endif /* MP */ +#endif /* CONFIG_SMP */ /* * Initialize the page table that maps the initial KPCR (at FF000000) @@ -175,7 +175,7 @@ _multiboot_entry: movl %eax, (%esi, %edi) -#ifdef MP +#ifdef CONFIG_SMP .m1: /* @@ -203,7 +203,7 @@ _multiboot_entry: .m3: -#endif /* MP */ +#endif /* CONFIG_SMP */ /* * Set up the PDBR @@ -211,7 +211,7 @@ _multiboot_entry: movl $(V2P(startup_pagedirectory)), %eax movl %eax, %cr3 -#ifdef MP +#ifdef CONFIG_SMP .m4: #endif @@ -249,7 +249,7 @@ _multiboot_entry: movl $0, %eax movl %eax, %fs -#ifdef MP +#ifdef CONFIG_SMP cmpl $AP_MAGIC, %edx jne .m2 @@ -292,7 +292,7 @@ _multiboot_entry: .m2: -#endif /* MP */ +#endif /* CONFIG_SMP */ /* * Load the PCR selector @@ -351,14 +351,15 @@ lowmem_pagetable: kernel_pagetable: .fill 2*4096, 1, 0 -kernelmap_pagetable: +hyperspace_pagetable: .fill 4096, 1, 0 + _pae_pagedirtable: .fill 4096, 1, 0 -#ifdef MP +#ifdef CONFIG_SMP apic_pagetable: .fill 4096, 1, 0 -#endif /* MP */ +#endif /* CONFIG_SMP */ kpcr_pagetable: .fill 4096, 1, 0 diff --git a/reactos/ntoskrnl/ke/i386/stkswitch.S b/reactos/ntoskrnl/ke/i386/stkswitch.S index 73f22f6e4b4..d37c46abd45 100644 --- a/reactos/ntoskrnl/ke/i386/stkswitch.S +++ b/reactos/ntoskrnl/ke/i386/stkswitch.S @@ -78,5 +78,5 @@ _KePushAndStackSwitchAndSysRet@8: push $0 call _KeLowerIrql@4 - jmp KeReturnFromSystemCall + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/syscall.S b/reactos/ntoskrnl/ke/i386/syscall.S index 29824d078b4..2cc6ca34287 100644 --- a/reactos/ntoskrnl/ke/i386/syscall.S +++ b/reactos/ntoskrnl/ke/i386/syscall.S @@ -1,324 +1,319 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 David Welch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * FILE: ntoskrnl/ke/i386/syscall.S - * PURPOSE: 2E trap handler - * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: System Call Handler + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) * UPDATE HISTORY: - * ??? + * ??-??-??: Original Version - David Welch(?) + * 13-01-05: Complete rewrite, added support for SYSENTER, direct kmode syscalls + * and re-wrote most of handler code. - Alex Ionescu */ +#include #include #include #include #include -#include +#include +#include -#define KernelMode (0) -#define UserMode (1) +#define UserMode (1) -/* - * - */ -.globl KeReturnFromSystemCall .globl KeReturnFromSystemCallWithHook -.globl _interrupt_handler2e -_interrupt_handler2e: +.globl _KiServiceExit +.globl _KiFastCallEntry +.globl _KiSystemService - /* Construct a trap frame on the stack */ +_KiFastCallEntry: + + /* Set FS to PCR */ + movl $PCR_SELECTOR, %ecx + movw %cx, %fs + + /* Set the current stack to Kernel Stack */ + movl %fs:KPCR_TSS, %ecx + movl %ss:KTSS_ESP0(%ecx), %ecx + movl %ecx, %esp + + /* Set up a fake INT Stack. */ + pushl $USER_DS + pushl %edx /* Ring 3 SS:ESP */ + pushfl + orl $X86_EFLAGS_IF, (%esp) /* Re-enable IRQs in EFLAGS, to fake INT */ + pushl $USER_CS + pushl $KUSER_SHARED_SYSCALL_RET + + /* User Parameter List */ + add $8, %edx + +_KiSystemService: - /* Error code */ - pushl $0 - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - pushl %fs - /* Load PCR selector into fs */ - movl $PCR_SELECTOR, %ebx - movl %ebx, %fs + /* + * Construct a trap frame on the stack. + * The following are already on the stack. + */ + // SS + 0x0 + // ESP + 0x4 + // EFLAGS + 0x8 + // CS + 0xC + // EIP + 0x10 + pushl $0 // + 0x14 + pushl %ebp // + 0x18 + pushl %ebx // + 0x1C + pushl %esi // + 0x20 + pushl %edi // + 0x24 + pushl %fs // + 0x28 + + /* Load PCR Selector into fs */ + movw $PCR_SELECTOR, %bx + movw %bx, %fs + + /* Save the previous exception list */ + pushl %fs:KPCR_EXCEPTION_LIST // + 0x2C - /* Save the old exception list */ - movl %fs:KPCR_EXCEPTION_LIST, %ebx - pushl %ebx - /* Set the exception handler chain terminator */ - movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST - /* Get a pointer to the current thread */ - movl %fs:KPCR_CURRENT_THREAD, %esi - /* Save the old previous mode */ - movl $0, %ebx - movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl - pushl %ebx - /* Set the new previous mode based on the saved CS selector */ - movl 0x24(%esp), %ebx - andl $0x0000FFFF, %ebx - cmpl $KERNEL_CS, %ebx - jne L1 - movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) - jmp L3 -L1: - movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) -L3: + /* Set the exception handler chain terminator */ + movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST - /* Save other registers */ - pushl %eax - pushl %ecx - pushl %edx - pushl %ds - pushl %es - pushl %gs - pushl $0 /* DR7 */ - pushl $0 /* DR6 */ - pushl $0 /* DR3 */ - pushl $0 /* DR2 */ - pushl $0 /* DR1 */ - pushl $0 /* DR0 */ - pushl $0 /* XXX: TempESP */ - pushl $0 /* XXX: TempCS */ - pushl $0 /* XXX: DebugPointer */ - pushl $0 /* XXX: DebugArgMark */ + /* Get a pointer to the current thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi + + /* Save the old previous mode */ + pushl %ss:KTHREAD_PREVIOUS_MODE(%esi) // + 0x30 + + /* Set the new previous mode based on the saved CS selector */ + movl 0x24(%esp), %ebx + andl $1, %ebx + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + + /* Save other registers */ + pushl %eax // + 0x34 + pushl %ecx // + 0x38 + pushl %edx // + 0x3C + pushl %ds // + 0x40 + pushl %es // + 0x44 + pushl %gs // + 0x48 + sub $0x28, %esp // + 0x70 #ifdef DBG - /* Trick gdb 6 into backtracing over the system call */ - movl 4(%ebp), %ebx - pushl %ebx /* DebugEIP */ - movl (%ebp), %ebx - pushl %ebx /* DebugEBP */ + /* Trick gdb 6 into backtracing over the system call */ + mov 0x6c(%esp), %ebx + pushl 4(%ebx) /* DebugEIP */ // + 0x74 #else - movl 0x60(%esp), %ebx - pushl %ebx /* DebugEIP */ - pushl %ebp /* DebugEBP */ + pushl 0x60(%esp) /* DebugEIP */ // + 0x74 #endif + pushl %ebp /* DebugEBP */ // + 0x78 - /* Load the segment registers */ - movl $KERNEL_DS, %ebx - movl %ebx, %ds - movl %ebx, %es - movl %ebx, %gs + /* Load the segment registers */ + sti + movw $KERNEL_DS, %bx + movw %bx, %ds + movw %bx, %es - /* - * Save the old trap frame pointer over where we would save the EDX - * register. - */ - movl KTHREAD_TRAP_FRAME(%esi), %ebx - movl %ebx, KTRAP_FRAME_EDX(%esp) + /* Save the old trap frame pointer where EDX would be saved */ + movl KTHREAD_TRAP_FRAME(%esi), %ebx + movl %ebx, KTRAP_FRAME_EDX(%esp) - /* Allocate new Kernel stack frame */ - movl %esp,%ebp + /* Allocate new Kernel stack frame */ + movl %esp,%ebp - /* Save a pointer to the trap frame in the TCB */ - movl %ebp, KTHREAD_TRAP_FRAME(%esi) - - /* Set ES to kernel segment */ - movw $KERNEL_DS,%bx - movw %bx,%es - - /* Users's current stack frame pointer is source */ - movl %edx,%esi - - /* Determine system service table to use */ - cmpl $0x0fff, %eax - ja new_useShadowTable - - /* Check to see if EAX is valid/inrange */ - cmpl %es:_KeServiceDescriptorTable + 8, %eax - jbe new_serviceInRange - movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - jmp KeReturnFromSystemCall - -new_serviceInRange: + /* Save a pointer to the trap frame in the TCB */ + movl %ebp, KTHREAD_TRAP_FRAME(%esi) +CheckValidCall: + #ifdef DBG - /* GDB thinks the function starts here and - wants a standard prolog, so let's give it */ - pushl %ebp - movl %esp,%ebp - popl %ebp + /* + * GDB thinks the function starts here and + * wants a standard prolog, so let's give it + */ + pushl %ebp + movl %esp,%ebp + popl %ebp #endif - /* Allocate room for argument list from kernel stack */ - movl %es:_KeServiceDescriptorTable + 12, %ecx - movb %es:(%ecx, %eax), %cl - movzx %cl, %ecx - subl %ecx, %esp + /* + * Find out which table offset to use. Converts 0x1124 into 0x10. + * The offset is related to the Table Index as such: Offset = TableIndex x 10 + */ + movl %eax, %edi + shrl $8, %edi + andl $0x10, %edi + movl %edi, %ecx + + /* Now add the thread's base system table to the offset */ + addl KTHREAD_SERVICE_TABLE(%esi), %edi + + /* Get the true syscall ID and check it */ + movl %eax, %ebx + andl $0x0FFF, %eax + cmpl 8(%edi), %eax + + /* Invalid ID, try to load Win32K Table */ + jnb KiBBTUnexpectedRange - /* Copy the arguments from the user stack to the kernel stack */ - movl %esp,%edi - cld - rep movsb + /* Users's current stack frame pointer is source */ + movl %edx, %esi + + /* Allocate room for argument list from kernel stack */ + movl 12(%edi), %ecx + movb (%ecx, %eax), %cl + movzx %cl, %ecx + + /* Allocate space on our stack */ + subl %ecx, %esp + + /* Get pointer to function */ + movl (%edi), %edi + movl (%edi, %eax, 4), %eax - /* DS is now also kernel segment */ - movw %bx, %ds + /* Copy the arguments from the user stack to our stack */ + shr $2, %ecx + movl %esp, %edi + cld + rep movsd - /* Call system call hook */ - pushl %eax - call _KiSystemCallHook - popl %eax + /* Do the System Call */ + call *%eax + movl %eax, KTRAP_FRAME_EAX(%ebp) - /* Make the system service call */ - movl %es:_KeServiceDescriptorTable, %ecx - movl %es:(%ecx, %eax, 4), %eax - call *%eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - -#if CHECKED - /* Bump Service Counter */ -#endif - - jmp KeDeallocateStackAndReturnFromSystemCallWithHook - -new_useShadowTable: - - subl $0x1000, %eax - - /* Check to see if EAX is valid/inrange */ - cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax - jbe new_shadowServiceInRange - movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - jmp KeReturnFromSystemCall - -new_shadowServiceInRange: - -#ifdef DBG - /* - * GDB thinks the function starts here and - * wants a standard prolog, so let's give it - */ - pushl %ebp - movl %esp,%ebp - popl %ebp -#endif - - /* Allocate room for argument list from kernel stack */ - movl %es:_KeServiceDescriptorTableShadow + 28, %ecx - movb %es:(%ecx, %eax), %cl - movzx %cl, %ecx - subl %ecx, %esp - - /* Copy the arguments from the user stack to the kernel stack */ - movl %esp,%edi - cld - rep movsb - - /* DS is now also kernel segment */ - movw %bx,%ds - - /* Call system call hook */ -// pushl %eax -// call _KiSystemCallHook -// popl %eax - - /* Call service check routine */ - pushl %eax - call _KiServiceCheck - popl %eax - - /* Make the system service call */ - movl %es:_KeServiceDescriptorTableShadow + 16, %ecx - movl %es:(%ecx, %eax, 4), %eax - call *%eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - -#if CHECKED - /* Bump Service Counter */ -#endif - -KeDeallocateStackAndReturnFromSystemCallWithHook: - /* Deallocate the kernel stack frame */ - movl %ebp,%esp - -KeReturnFromSystemCallWithHook: - /* Call the post system call hook and deliver any pending APCs */ - pushl %esp - call _KiAfterSystemCallHook - addl $4,%esp + /* Deallocate the kernel stack frame */ + movl %ebp, %esp KeReturnFromSystemCall: - /* Restore the user context */ - /* Get a pointer to the current thread */ - movl %fs:0x124, %esi + /* Get the Current Thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi - /* Restore the old trap frame pointer */ - movl KTRAP_FRAME_EDX(%esp), %ebx - movl %ebx, KTHREAD_TRAP_FRAME(%esi) + /* Restore the old trap frame pointer */ + movl KTRAP_FRAME_EDX(%esp), %ebx + movl %ebx, KTHREAD_TRAP_FRAME(%esi) +_KiServiceExit: + + /* Get the Current Thread */ + cli + movl %fs:KPCR_CURRENT_THREAD, %esi + + /* Deliver APCs only if we were called from user mode */ + testb $1, KTRAP_FRAME_CS(%esp) + je KiRosTrapReturn + + /* And only if any are actually pending */ + cmpb $0, KTHREAD_PENDING_USER_APC(%esi) + je KiRosTrapReturn + + /* Save pointer to Trap Frame */ + movl %esp, %ebx + + /* Raise IRQL to APC_LEVEL */ + movl $1, %ecx + call @KfRaiseIrql@4 + + /* Save old IRQL */ + pushl %eax + + /* Deliver APCs */ + sti + pushl %ebx + pushl $0 + pushl $UserMode + call _KiDeliverApc@12 + cli + + /* Return to old IRQL */ + popl %ecx + call @KfLowerIrql@4 + KiRosTrapReturn: + + /* Skip debug information and unsaved registers */ + addl $0x30, %esp // + 0x48 + popl %gs // + 0x44 + popl %es // + 0x40 + popl %ds // + 0x3C + popl %edx // + 0x38 + popl %ecx // + 0x34 + popl %eax // + 0x30 -#if 0 - mov KTRAP_FRAME_RESERVED1(%ebp), %ax - cmp %ax, SSIDX_NTCONTINUE - jnz KeNoEpilogPrint - movl KTRAP_FRAME_ESP(%ebp), %ecx - movl KTRAP_FRAME_EBP(%ebp), %edx - call @KeRosPrintEspEbp@8 -KeNoEpilogPrint: -#endif + /* Restore the old previous mode */ + popl %ebx // + 0x2C + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) - /* Skip debug information and unsaved registers */ - addl $0x30, %esp - popl %gs - popl %es - popl %ds - popl %edx - popl %ecx - popl %eax + /* Restore the old exception handler list */ + popl %fs:KPCR_EXCEPTION_LIST // + 0x28 - /* Restore the old previous mode */ - popl %ebx - movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + /* Restore final registers from trap frame */ + popl %fs // + 0x24 + popl %edi // + 0x20 + popl %esi // + 0x1C + popl %ebx // + 0x18 + popl %ebp // + 0x14 + add $4, %esp // + 0x10 - /* Restore the old exception handler list */ - popl %ebx - movl %ebx, %fs:KPCR_EXCEPTION_LIST + /* Check if previous CS is from user-mode */ + testl $1, 4(%esp) + + /* It is, so use Fast Exit */ + jnz FastRet + + /* + * Restore what the stub pushed, and return back to it. + * Note that we were CALLed, so the first thing on our stack is the ret EIP! + */ + pop %edx // + 0x0C + pop %ecx // + 0x08 + popf // + 0x04 + jmp *%edx + +IntRet: + + iret - popl %fs - popl %edi - popl %esi - popl %ebx - popl %ebp - addl $0x4, %esp /* Ignore error code */ +FastRet: - iret + /* Is SYSEXIT Supported/Wanted? */ + cmpl $0, %ss:_KiFastSystemCallDisable + jnz IntRet -/* R3: NOTE: This is part of my in-progress attempt at correcting NtContinue - * It is not being called, yet... - */ -.globl @KeRosTrapReturn@8 -@KeRosTrapReturn@8: + /* Restore FS to TIB */ + mov $TEB_SELECTOR, %ecx + mov %ecx, %fs + + /* We will be cleaning up the stack ourselves */ + popl %edx /* New Ring 3 EIP */ + add $0x4, %esp /* Skip Ring 3 DS */ + andl $~X86_EFLAGS_IF, (%esp) /* Remove IRQ hack from EFLAGS */ + popfl /* Restore old EFLAGS */ + popl %ecx /* Old Ring 3 SS:ESP */ + + /* + * At this point: + * ECX points to the old User Stack. + * EDX points to the instruction to execute in usermode after the sysenter + */ + sti + sysexit - /* point %esp to the trap frame to restore */ - movl %ecx, %esp - movl %esp, %ebp +KiBBTUnexpectedRange: - /* Call the post system call hook and deliver any pending APCs */ - pushl %esp - call _KiAfterSystemCallHook - addl $4,%esp + /* If this isn't a Win32K call, fail */ + cmp $0x10, %ecx + jne InvalidCall - /* Restore the user context */ - /* Get a pointer to the current thread */ - movl %fs:0x124, %esi - /* Restore the old trap frame pointer */ - movl %edx, KTHREAD_TRAP_FRAME(%esi) + /* Set up Win32K Table */ + pushl %edx + pushl %ebx + call _KiServiceCheck + popl %eax + popl %edx + + /* Try the Call again */ + jmp CheckValidCall + +InvalidCall: - jmp KiRosTrapReturn; + /* Invalid System Call */ + movl $STATUS_INVALID_SYSTEM_SERVICE, %eax + movl %eax, KTRAP_FRAME_EAX(%ebp) + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/thread.c b/reactos/ntoskrnl/ke/i386/thread.c index 7e4c34b35cd..6eb7c67b1b1 100644 --- a/reactos/ntoskrnl/ke/i386/thread.c +++ b/reactos/ntoskrnl/ke/i386/thread.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/thread.c - * PURPOSE: Architecture multitasking functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * REVISION HISTORY: - * 27/06/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/thread.c + * PURPOSE: Architecture multitasking functions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/ke/i386/tskswitch.S b/reactos/ntoskrnl/ke/i386/tskswitch.S index badd8855f1e..a97577fa5ee 100644 --- a/reactos/ntoskrnl/ke/i386/tskswitch.S +++ b/reactos/ntoskrnl/ke/i386/tskswitch.S @@ -60,7 +60,7 @@ _Ki386ContextSwitch: */ cli -#ifdef MP +#ifdef CONFIG_SMP /* * Get the pointer to the old thread. */ @@ -81,7 +81,7 @@ _Ki386ContextSwitch: 2: movb $NPX_STATE_VALID, KTHREAD_NPX_STATE(%ebx) 3: -#endif /* MP */ +#endif /* CONFIG_SMP */ /* @@ -182,10 +182,10 @@ _Ki386ContextSwitch: * Set TS in cr0 to catch FPU code and load the FPU state when needed * For uni-processor we do this only if NewThread != KPCR->NpxThread */ -#ifndef MP +#ifndef CONFIG_SMP cmpl %ebx, %fs:KPCR_NPX_THREAD je 4f -#endif /* !MP */ +#endif /* !CONFIG_SMP */ movl %cr0, %eax orl $X86_CR0_TS, %eax movl %eax, %cr0 diff --git a/reactos/ntoskrnl/ke/i386/tss.c b/reactos/ntoskrnl/ke/i386/tss.c index 835a75010ea..03c63f8135e 100644 --- a/reactos/ntoskrnl/ke/i386/tss.c +++ b/reactos/ntoskrnl/ke/i386/tss.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/tss.c * PURPOSE: TSS managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -42,7 +25,8 @@ KTSS KiBootTss; static KTSSNOIOPM KiBootTrapTss; extern USHORT KiBootGdt[]; - +extern ULONG init_stack; +extern ULONG init_stack_top; extern VOID KiTrap8(VOID); /* FUNCTIONS *****************************************************************/ @@ -199,7 +183,6 @@ VOID INIT_FUNCTION Ki386BootInitializeTSS(VOID) { ULONG cr3_; - extern unsigned int init_stack, init_stack_top; extern unsigned int trap_stack, trap_stack_top; unsigned int base, length; @@ -207,11 +190,11 @@ Ki386BootInitializeTSS(VOID) Ki386TssArray[0] = &KiBootTss; Ki386TrapTssArray[0] = &KiBootTrapTss; - Ki386TrapStackArray[0] = (PVOID)&trap_stack; - Ki386InitialStackArray[0] = (PVOID)&init_stack; + Ki386TrapStackArray[0] = (PVOID)trap_stack; + Ki386InitialStackArray[0] = (PVOID)init_stack; /* Initialize the boot TSS. */ - KiBootTss.Esp0 = (ULONG)&init_stack_top - sizeof(FX_SAVE_AREA); + KiBootTss.Esp0 = (ULONG)init_stack_top - sizeof(FX_SAVE_AREA); KiBootTss.Ss0 = KERNEL_DS; // KiBootTss.IoMapBase = FIELD_OFFSET(KTSS, IoBitmap); KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ @@ -232,9 +215,9 @@ Ki386BootInitializeTSS(VOID) /* Initialize the TSS used for handling double faults. */ KiBootTrapTss.Eflags = 0; - KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */ + KiBootTrapTss.Esp0 = (ULONG)trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */ KiBootTrapTss.Ss0 = KERNEL_DS; - KiBootTrapTss.Esp = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */ + KiBootTrapTss.Esp = (ULONG)trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */ KiBootTrapTss.Cs = KERNEL_CS; KiBootTrapTss.Eip = (ULONG)KiTrap8; KiBootTrapTss.Ss = KERNEL_DS; diff --git a/reactos/ntoskrnl/ke/i386/usercall.c b/reactos/ntoskrnl/ke/i386/usercall.c index 2f6e4ea5699..46aa853ef50 100644 --- a/reactos/ntoskrnl/ke/i386/usercall.c +++ b/reactos/ntoskrnl/ke/i386/usercall.c @@ -2,11 +2,10 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/hal/x86/usercall.c + * FILE: ntoskrnl/ke/i386/usercall.c * PURPOSE: 2E interrupt handler - * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) - * UPDATE HISTORY: - * ??? + * + * PROGRAMMERS: David Welch (david.welch@seh.ox.ac.uk) */ /* INCLUDES ******************************************************************/ @@ -17,127 +16,6 @@ /* FUNCTIONS *****************************************************************/ -VOID -KiSystemCallHook(ULONG Nr, ...) -{ -#if 0 - va_list ap; - ULONG i; - - va_start(ap, Nr); - - DbgPrint("%x/%d ", KeServiceDescriptorTable[0].SSDT[Nr].SysCallPtr, Nr); - DbgPrint("%x (", KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes); - for (i = 0; i < KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes / 4; i++) - { - DbgPrint("%x, ", va_arg(ap, ULONG)); - } - DbgPrint(")\n"); - ASSERT_IRQL(PASSIVE_LEVEL); - va_end(ap); -#endif -} - -VOID -KiAfterSystemCallHook(PKTRAP_FRAME TrapFrame) -{ - KIRQL oldIrql; - - /* If we are returning to umode, deliver one pending umode apc. - * Note that kmode apcs are also delivered, even if deliverymode is UserMode. - * This is because we can't return to umode with pending kmode apcs! - * FIXME: Should we deliver pending kmode apcs when returning from a - * kmode-to-kmode syscall (ZwXxx calls)????? - * -Gunnar - */ - if (TrapFrame->Cs != KERNEL_CS) - { - KeRaiseIrql(APC_LEVEL, &oldIrql); - KiDeliverApc(UserMode, NULL, TrapFrame); - KeLowerIrql(oldIrql); - } - -} - - -VOID -KiServiceCheck (ULONG Nr) -{ - PETHREAD Thread; - - Thread = PsGetCurrentThread(); - -#if 0 - DbgPrint ("KiServiceCheck(%p) called\n", Thread); - DbgPrint ("Service %d (%p)\n", Nr, KeServiceDescriptorTableShadow[1].SSDT[Nr].SysCallPtr); -#endif - - if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow) - { -#if 0 - DbgPrint ("Initialize Win32 thread\n"); -#endif - - PsInitWin32Thread (Thread); - - Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; - } -} - -// This function should be used by win32k.sys to add its own user32/gdi32 services -// TableIndex is 0 based -// ServiceCountTable its not used at the moment -/* - * @implemented - */ -BOOLEAN STDCALL -KeAddSystemServiceTable ( - PSSDT SSDT, - PULONG ServiceCounterTable, - ULONG NumberOfServices, - PSSPT SSPT, - ULONG TableIndex - ) -{ - if (TableIndex > SSDT_MAX_ENTRIES - 1) - return FALSE; - - /* check if descriptor table entry is free */ - if ((KeServiceDescriptorTable[TableIndex].SSDT != NULL) || - (KeServiceDescriptorTableShadow[TableIndex].SSDT != NULL)) - return FALSE; - - /* initialize the shadow service descriptor table */ - KeServiceDescriptorTableShadow[TableIndex].SSDT = SSDT; - KeServiceDescriptorTableShadow[TableIndex].SSPT = SSPT; - KeServiceDescriptorTableShadow[TableIndex].NumberOfServices = NumberOfServices; - KeServiceDescriptorTableShadow[TableIndex].ServiceCounterTable = ServiceCounterTable; - - /* initialize the service descriptor table (not for win32k services) */ - if (TableIndex != 1) - { - KeServiceDescriptorTable[TableIndex].SSDT = SSDT; - KeServiceDescriptorTable[TableIndex].SSPT = SSPT; - KeServiceDescriptorTable[TableIndex].NumberOfServices = NumberOfServices; - KeServiceDescriptorTable[TableIndex].ServiceCounterTable = ServiceCounterTable; - } - - return TRUE; -} - -/* - * @unimplemented - */ -BOOLEAN -STDCALL -KeRemoveSystemServiceTable( - IN PUCHAR Number -) -{ - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ diff --git a/reactos/ntoskrnl/ke/i386/usertrap.c b/reactos/ntoskrnl/ke/i386/usertrap.c index b87b4fa79c7..2307fe9099c 100644 --- a/reactos/ntoskrnl/ke/i386/usertrap.c +++ b/reactos/ntoskrnl/ke/i386/usertrap.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/usertrap.c - * PURPOSE: Handling usermode exceptions. - * PROGRAMMER: David Welch (welch@cwcom.net) - * REVISION HISTORY: - * 18/11/01: Split from ntoskrnl/ke/i386/exp.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/usertrap.c + * PURPOSE: Handling usermode exceptions. + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -71,7 +54,7 @@ print_user_address(PVOID address) CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList); if (address >= (PVOID)current->BaseAddress && - address < (PVOID)((char*)current->BaseAddress + current->SizeOfImage)) + address < (PVOID)((char*)current->BaseAddress + current->ResidentSize)) { RelativeAddress = (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress; @@ -131,10 +114,8 @@ KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) Er.NumberParameters = 0; } - - Er.ExceptionFlags = ((NTSTATUS) STATUS_SINGLE_STEP == (NTSTATUS) Er.ExceptionCode || - (NTSTATUS) STATUS_BREAKPOINT == (NTSTATUS) Er.ExceptionCode) ? - EXCEPTION_NONCONTINUABLE : 0; + /* FIXME: Which exceptions are noncontinuable? */ + Er.ExceptionFlags = 0; KiDispatchException(&Er, 0, Tf, UserMode, TRUE); return(0); diff --git a/reactos/ntoskrnl/ke/i386/v86m.c b/reactos/ntoskrnl/ke/i386/v86m.c index dadacc76384..615777a9321 100644 --- a/reactos/ntoskrnl/ke/i386/v86m.c +++ b/reactos/ntoskrnl/ke/i386/v86m.c @@ -1,26 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000, 2001 ReactOS Team +/* $Id$ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/v86m.c * PURPOSE: Support for v86 mode - * PROGRAMMER: David Welch (welch@cwcom.net) + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/nt/vdm.c b/reactos/ntoskrnl/ke/i386/vdm.c similarity index 92% rename from reactos/ntoskrnl/nt/vdm.c rename to reactos/ntoskrnl/ke/i386/vdm.c index 09f21b798d6..75cd7497bac 100644 --- a/reactos/ntoskrnl/nt/vdm.c +++ b/reactos/ntoskrnl/ke/i386/vdm.c @@ -1,11 +1,11 @@ -/* +/* $Id:$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/vdm.c + * FILE: ntoskrnl/ke/i386/vdm.c * PURPOSE: Virtual DOS machine support - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ke/ipi.c b/reactos/ntoskrnl/ke/ipi.c index cb87e121483..3798d44acdf 100644 --- a/reactos/ntoskrnl/ke/ipi.c +++ b/reactos/ntoskrnl/ke/ipi.c @@ -4,10 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/ipi.c * PURPOSE: IPI Routines (Inter-Processor Interrupts). NT5+ - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) * Hartmut Birr - * UPDATE HISTORY: - * Created 11/08/2004 */ /* INCLUDES *****************************************************************/ @@ -157,7 +156,7 @@ KiIpiSendPacket(ULONG TargetSet, VOID STDCALL (*WorkerRoutine)(PVOID), PVOID Arg } VOID -KeIpiGenericCall(VOID STDCALL (*Function)(PVOID), PVOID Argument) +KeIpiGenericCall(VOID (STDCALL *Function)(PVOID), PVOID Argument) { KIRQL oldIrql; ULONG TargetSet; diff --git a/reactos/ntoskrnl/ke/kqueue.c b/reactos/ntoskrnl/ke/kqueue.c index 70ffe09954f..b19a3155890 100644 --- a/reactos/ntoskrnl/ke/kqueue.c +++ b/reactos/ntoskrnl/ke/kqueue.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PURPOSE: ReactOS kernel - * FILE: ntoskrnl/ke/kqueue.c - * PURPOSE: Implement device queues - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 08/07/98: Created +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: ReactOS kernel + * FILE: ntoskrnl/ke/kqueue.c + * PURPOSE: Implement device queues + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 8651c5e5aaf..5a1eaa2b8ab 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/kthread.c * PURPOSE: Microkernel thread support - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -33,6 +16,21 @@ /* FUNCTIONS *****************************************************************/ +VOID +KiServiceCheck (VOID) +{ + PETHREAD Thread; + + Thread = PsGetCurrentThread(); + + if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow) + { + PsInitWin32Thread (Thread); + + Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; + } +} + /* * @unimplemented */ @@ -87,7 +85,7 @@ KeReleaseThread(PKTHREAD Thread) /* FIXME - lock the process */ RemoveEntryList(&Thread->ThreadListEntry); - if (Thread->StackLimit != (ULONG_PTR)&init_stack) + if (Thread->StackLimit != (ULONG_PTR)init_stack) { MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), @@ -195,10 +193,10 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) } else { - Thread->InitialStack = (PCHAR)&init_stack_top; - Thread->StackBase = (PCHAR)&init_stack_top; - Thread->StackLimit = (ULONG_PTR)&init_stack; - Thread->KernelStack = (PCHAR)&init_stack_top; + Thread->InitialStack = (PCHAR)init_stack_top; + Thread->StackBase = (PCHAR)init_stack_top; + Thread->StackLimit = (ULONG_PTR)init_stack; + Thread->KernelStack = (PCHAR)init_stack_top; } /* @@ -309,7 +307,7 @@ VOID STDCALL KeRevertToUserAffinityThread(VOID) { -#ifdef MP +#ifdef CONFIG_SMP PKTHREAD CurrentThread; KIRQL oldIrql; @@ -366,7 +364,7 @@ VOID STDCALL KeSetSystemAffinityThread(IN KAFFINITY Affinity) { -#ifdef MP +#ifdef CONFIG_SMP PKTHREAD CurrentThread; KIRQL oldIrql; diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 022904b09bc..c0ccca43c76 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ - * + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c * PURPOSE: Initalizes the kernel - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 28/05/98: Created + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -77,15 +59,24 @@ static CHAR KeLoaderModuleStrings[64][256]; static CHAR KeLoaderCommandLine[256]; static ADDRESS_RANGE KeMemoryMap[64]; static ULONG KeMemoryMapRangeCount; -static ULONG FirstKrnlPhysAddr; -static ULONG LastKrnlPhysAddr; -static ULONG LastKernelAddress; +static ULONG_PTR FirstKrnlPhysAddr; +static ULONG_PTR LastKrnlPhysAddr; +static ULONG_PTR LastKernelAddress; volatile BOOLEAN Initialized = FALSE; extern ULONG MmCoreDumpType; extern CHAR KiTimerSystemAuditing; extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; +/* We allocate 4 pages, but we only use 3. The 4th is to guarantee page alignment */ +ULONG kernel_stack[4096]; +ULONG double_trap_stack[4096]; + +/* These point to the aligned 3 pages */ +ULONG init_stack; +ULONG init_stack_top; +ULONG trap_stack; +ULONG trap_stack_top; /* FUNCTIONS ****************************************************************/ @@ -519,11 +510,7 @@ ExpInitializeExecutive(VOID) PsPrepareForApplicationProcessorInit(KeNumberProcessors); /* Allocate a stack for use when booting the processor */ - /* FIXME: The nonpaged memory for the stack is not released after use */ - ProcessorStack = - (char*)ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE; - Ki386InitialStackArray[((int)KeNumberProcessors)] = - (PVOID)((char*)ProcessorStack - MM_STACK_SIZE); + ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE; HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA)); KeNumberProcessors++; @@ -539,7 +526,6 @@ ExpInitializeExecutive(VOID) IoInit(); PoInit(); CmInitializeRegistry(); - NtInit(); MmInit3(); CcInit(); KdInit2(); @@ -697,6 +683,7 @@ ExpInitializeExecutive(VOID) /* Create the SystemRoot symbolic link */ CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine); + DPRINT1("MmSystemRangeStart: 0x%x PageDir: 0x%x\n", MmSystemRangeStart, KeLoaderBlock.PageDirectoryStart); Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine); if (!NT_SUCCESS(Status)) { @@ -705,7 +692,7 @@ ExpInitializeExecutive(VOID) KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE); } -#ifdef KDBG +#if defined(KDBG) || defined(DBG) KdbInitProfiling2(); #endif /* KDBG */ @@ -754,7 +741,7 @@ ExpInitializeExecutive(VOID) 0, NULL, NULL); - Status = NtCreateEvent(&InitDoneEventHandle, + Status = ZwCreateEvent(&InitDoneEventHandle, EVENT_ALL_ACCESS, &ObjectAttributes, SynchronizationEvent, @@ -784,7 +771,7 @@ ExpInitializeExecutive(VOID) /* Wait for the system to be initialized */ Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */ - Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)), + Status = ZwWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)), Handles, WaitAny, FALSE, /* Non-alertable */ @@ -810,9 +797,9 @@ ExpInitializeExecutive(VOID) InbvEnableBootDriver(FALSE); } - NtSetEvent(InitDoneEventHandle, NULL); + ZwSetEvent(InitDoneEventHandle, NULL); - NtClose(InitDoneEventHandle); + ZwClose(InitDoneEventHandle); } else { @@ -826,7 +813,7 @@ ExpInitializeExecutive(VOID) * Crash the system if the initial process terminates within 5 seconds. */ Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */ - Status = NtWaitForSingleObject(ProcessHandle, + Status = ZwWaitForSingleObject(ProcessHandle, FALSE, &Timeout); if (Status != STATUS_TIMEOUT) @@ -840,13 +827,14 @@ ExpInitializeExecutive(VOID) KiTimerSystemAuditing = 1; - NtClose(ThreadHandle); - NtClose(ProcessHandle); + ZwClose(ThreadHandle); + ZwClose(ProcessHandle); } VOID __attribute((noinline)) KiSystemStartup(BOOLEAN BootProcessor) { + DPRINT1("KiSystemStartup(%d)\n", BootProcessor); if (BootProcessor) { } @@ -888,11 +876,16 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) { ULONG i; ULONG size; - extern ULONG _bss_end__; ULONG HalBase; ULONG DriverBase; ULONG DriverSize; + /* Set up the Stacks */ + trap_stack = PAGE_ROUND_UP(&double_trap_stack); + trap_stack_top = trap_stack + 3 * PAGE_SIZE; + init_stack = PAGE_ROUND_UP(&kernel_stack); + init_stack_top = init_stack + 3 * PAGE_SIZE; + /* * Copy the parameters to a local buffer because lowmem will go away */ @@ -902,6 +895,9 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) KeLoaderBlock.ModsCount++; KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules; + /* Save the Base Address */ + MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase; + /* * Convert a path specification in the grub format to one understood by the * rest of the kernel. @@ -962,17 +958,10 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe"); KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0]; KeLoaderModules[0].ModStart = KERNEL_BASE; -#ifdef __GNUC__ - KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__); -#else /* Take this value from the PE... */ - { PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart); PIMAGE_OPTIONAL_HEADER OptHead = &NtHeader->OptionalHeader; - KeLoaderModules[0].ModEnd = - KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage); - } -#endif + KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage); for (i = 1; i < KeLoaderBlock.ModsCount; i++) { CHAR* s; @@ -984,7 +973,6 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) { strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String); } - /* TODO: Fix this hardcoded load address stuff... */ KeLoaderModules[i].ModStart -= 0x200000; KeLoaderModules[i].ModStart += KERNEL_BASE; KeLoaderModules[i].ModEnd -= 0x200000; @@ -1047,6 +1035,9 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + DPRINT1("_main (%x, %x)\n", MultiBootMagic, _LoaderBlock); + + KiSystemStartup(1); } diff --git a/reactos/ntoskrnl/ke/mutex.c b/reactos/ntoskrnl/ke/mutex.c index 841b44d3ddf..3532781082c 100644 --- a/reactos/ntoskrnl/ke/mutex.c +++ b/reactos/ntoskrnl/ke/mutex.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/mutex.c * PURPOSE: Implements mutex - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -82,7 +64,7 @@ KeReleaseMutex(IN PKMUTEX Mutex, Mutex->OwnerThread = NULL; if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink) RemoveEntryList(&Mutex->MutantListEntry); - KiDispatcherObjectWake(&Mutex->Header); + KiDispatcherObjectWake(&Mutex->Header, IO_NO_INCREMENT); } if (Wait == FALSE) @@ -191,7 +173,7 @@ KeReleaseMutant(IN PKMUTANT Mutant, Mutant->OwnerThread = NULL; if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink) RemoveEntryList(&Mutant->MutantListEntry); - KiDispatcherObjectWake(&Mutant->Header); + KiDispatcherObjectWake(&Mutant->Header, Increment); } if (Wait == FALSE) diff --git a/reactos/ntoskrnl/ke/process.c b/reactos/ntoskrnl/ke/process.c index 94c44cc08a9..56d2bf00bc9 100644 --- a/reactos/ntoskrnl/ke/process.c +++ b/reactos/ntoskrnl/ke/process.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/process.c * PURPOSE: Microkernel process management - * PROGRAMMER: David Welch (welch@cwcom.net) - * PORTABILITY: No. - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -270,4 +251,46 @@ KeUnstackDetachProcess ( KeReleaseDispatcherDatabaseLock(OldIrql); } +// This function should be used by win32k.sys to add its own user32/gdi32 services +// TableIndex is 0 based +// ServiceCountTable its not used at the moment +/* + * @implemented + */ +BOOLEAN STDCALL +KeAddSystemServiceTable ( + PSSDT SSDT, + PULONG ServiceCounterTable, + ULONG NumberOfServices, + PSSPT SSPT, + ULONG TableIndex + ) +{ + /* check if descriptor table entry is free */ + if ((TableIndex > SSDT_MAX_ENTRIES - 1) || + (KeServiceDescriptorTable[TableIndex].SSDT != NULL) || + (KeServiceDescriptorTableShadow[TableIndex].SSDT != NULL)) + return FALSE; + + /* initialize the shadow service descriptor table */ + KeServiceDescriptorTableShadow[TableIndex].SSDT = SSDT; + KeServiceDescriptorTableShadow[TableIndex].SSPT = SSPT; + KeServiceDescriptorTableShadow[TableIndex].NumberOfServices = NumberOfServices; + KeServiceDescriptorTableShadow[TableIndex].ServiceCounterTable = ServiceCounterTable; + + return TRUE; +} + +/* + * @unimplemented + */ +BOOLEAN +STDCALL +KeRemoveSystemServiceTable( + IN PUCHAR Number +) +{ + UNIMPLEMENTED; + return FALSE; +} /* EOF */ diff --git a/reactos/ntoskrnl/ke/profile.c b/reactos/ntoskrnl/ke/profile.c index 068963bbcc6..08b9bb9d968 100644 --- a/reactos/ntoskrnl/ke/profile.c +++ b/reactos/ntoskrnl/ke/profile.c @@ -1,16 +1,253 @@ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/profile.c * PURPOSE: Kernel Profiling - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 23/06/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ #include #define NDEBUG #include +extern LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; +extern LIST_ENTRY SystemProfileList; +extern KSPIN_LOCK ProfileListLock; +extern BOOLEAN ProfileInitDone; + +/* FUNCTIONS *****************************************************************/ + +VOID +KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip) + /* + * Add a profile event to the profile objects for a particular process + * or the system + */ +{ + PKPROFILE current; + PLIST_ENTRY current_entry; + + current_entry = ListHead->Flink; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); + + if (current->Base > Eip) + { + return; + } + + if (current->Base <= Eip && ((char*)current->Base + current->Size) > (char*)Eip && + current->Started) + { + ULONG Bucket; + + Bucket = ((ULONG)((char*)Eip - (char*)current->Base)) >> current->BucketShift; + + if ((Bucket*4) < current->BufferSize) + { + current->Buffer[Bucket]++; + } + } + + current_entry = current_entry->Flink; + } +} + +VOID +KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip) + /* + * Add a profile event + */ +{ + HANDLE Pid; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + PLIST_ENTRY ListHead; + + if (!ProfileInitDone) + { + return; + } + + Pid = PsGetCurrentProcessId(); + ListHead = + ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink; + + KeAcquireSpinLockAtDpcLevel(&ProfileListLock); + + current_entry = ListHead; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry); + + if (current->Pid == Pid) + { + KiAddProfileEventToProcess(¤t->ProfileListHead, (PVOID)Eip); + break; + } + + current_entry = current_entry->Flink; + } + + KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip); + + KeReleaseSpinLockFromDpcLevel(&ProfileListLock); +} + +VOID +KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile) + /* + * Insert a profile object into the list for a process or the system + */ +{ + PKPROFILE current; + PLIST_ENTRY current_entry; + + current_entry = ListHead; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); + + if (current->Base > Profile->Base) + { + Profile->ListEntry.Flink = current_entry; + Profile->ListEntry.Blink = current_entry->Blink; + current_entry->Blink->Flink = &Profile->ListEntry; + current_entry->Blink = &Profile->ListEntry; + return; + } + + current_entry = current_entry->Flink; + } + InsertTailList(ListHead, &Profile->ListEntry); +} + +VOID +KiInsertProfile(PKPROFILE Profile) + /* + * Insert a profile into the relevant data structures + */ +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&ProfileListLock, &oldIrql); + + if (Profile->Process == NULL) + { + KiInsertProfileIntoProcess(&SystemProfileList, Profile); + } + else + { + HANDLE Pid; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + PLIST_ENTRY ListHead; + + Pid = Profile->Process->UniqueProcessId; + ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE]; + + current_entry = ListHead; + while(current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, + ListEntry); + + if (current->Pid == Pid) + { + KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); + KeReleaseSpinLock(&ProfileListLock, oldIrql); + return; + } + + current_entry = current_entry->Flink; + } + + current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE)); + + current->Pid = Pid; + InitializeListHead(¤t->ProfileListHead); + InsertTailList(ListHead, ¤t->ListEntry); + + KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); + } + + KeReleaseSpinLock(&ProfileListLock, oldIrql); +} + +VOID KiRemoveProfile(PKPROFILE Profile) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&ProfileListLock, &oldIrql); + + if (Profile->Process == NULL) + { + RemoveEntryList(&Profile->ListEntry); + } + else + { + HANDLE Pid; + PLIST_ENTRY ListHead; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + + RemoveEntryList(&Profile->ListEntry); + + Pid = Profile->Process->UniqueProcessId; + ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE]; + + current_entry = ListHead; + while(current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, + ListEntry); + + if (current->Pid == Pid) + { + if (IsListEmpty(¤t->ProfileListHead)) + { + RemoveEntryList(¤t->ListEntry); + ExFreePool(current); + } + KeReleaseSpinLock(&ProfileListLock, oldIrql); + return; + } + + current_entry = current_entry->Flink; + } + KEBUGCHECK(0); + } + + KeReleaseSpinLock(&ProfileListLock, oldIrql); +} + +VOID STDCALL +KiDeleteProfile(PVOID ObjectBody) +{ + PKPROFILE Profile; + + Profile = (PKPROFILE)ObjectBody; + + KiRemoveProfile(Profile); + if (Profile->Process != NULL) + { + ObDereferenceObject(Profile->Process); + Profile->Process = NULL; + } + + if (Profile->BufferMdl->MappedSystemVa != NULL) + { + MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa, + Profile->BufferMdl); + } + MmUnlockPages(Profile->BufferMdl); + ExFreePool(Profile->BufferMdl); + Profile->BufferMdl = NULL; +} + /* * @unimplemented */ diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index 1e45c3c65e7..9c478709de8 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/queue.c * PURPOSE: Implements kernel queues - * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) - * UPDATE HISTORY: - * Created 04/01/2002 + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ /* INCLUDES *****************************************************************/ @@ -100,7 +82,7 @@ KiInsertQueue( !IsListEmpty(&Queue->Header.WaitListHead) && KeGetCurrentThread()->Queue != Queue) { - KiDispatcherObjectWake(&Queue->Header); + KiDispatcherObjectWake(&Queue->Header, IO_NO_INCREMENT); } return InitialState; @@ -179,7 +161,7 @@ KeRemoveQueue(IN PKQUEUE Queue, if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount && !IsListEmpty(&Thread->Queue->EntryListHead)) { - KiDispatcherObjectWake(&Thread->Queue->Header); + KiDispatcherObjectWake(&Thread->Queue->Header, 0); } } diff --git a/reactos/ntoskrnl/ke/sem.c b/reactos/ntoskrnl/ke/sem.c index f3b226b4456..9408e66948c 100644 --- a/reactos/ntoskrnl/ke/sem.c +++ b/reactos/ntoskrnl/ke/sem.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/sem.c * PURPOSE: Implements kernel semaphores - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -105,7 +87,7 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore, Semaphore->Header.SignalState += Adjustment; if (InitialState == 0) { - KiDispatcherObjectWake(&Semaphore->Header); + KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT); } if (Wait == FALSE) diff --git a/reactos/ntoskrnl/ke/spinlock.c b/reactos/ntoskrnl/ke/spinlock.c index 284d19792ad..15c3b13737c 100644 --- a/reactos/ntoskrnl/ke/spinlock.c +++ b/reactos/ntoskrnl/ke/spinlock.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/spinlock.c * PURPOSE: Implements spinlocks - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 3/6/98: Created + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* @@ -187,12 +186,21 @@ KiAcquireSpinLock(PKSPIN_LOCK SpinLock) while ((i = InterlockedExchangeUL(SpinLock, 1)) == 1) { -#ifndef MP +#ifdef CONFIG_SMP + /* Avoid reading the value again too fast */ +#if 1 + __asm__ __volatile__ ("1:\n\t" + "cmpl $0,(%0)\n\t" + "jne 1b\n\t" + : + : "r" (SpinLock)); +#else + while (0 != *(volatile KSPIN_LOCK*)SpinLock); +#endif +#else DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i); KEBUGCHECK(0); -#else /* not MP */ - /* Avoid reading the value again too fast */ -#endif /* MP */ +#endif /* CONFIG_SMP */ } } diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index 28a44c32a1b..46ec4198975 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -1,13 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/timer.c - * PURPOSE: Handle timers - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 28/05/98: Created - * 12/3/99: Phillip Susi: enabled the timers, fixed spin lock + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/timer.c + * PURPOSE: Handle timers + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi */ /* NOTES ******************************************************************/ @@ -72,8 +71,6 @@ static KDPC ExpireTimerDpc; /* must raise IRQL to PROFILE_LEVEL and grab spin lock there, to sync with ISR */ -extern HANDLE PsIdleThreadHandle; - #define MICROSECONDS_PER_TICK (10000) #define TICKS_TO_CALIBRATE (1) #define CALIBRATE_PERIOD (MICROSECONDS_PER_TICK * TICKS_TO_CALIBRATE) @@ -105,58 +102,100 @@ NtSetTimerResolution(IN ULONG DesiredResolution, NTSTATUS STDCALL -NtQueryPerformanceCounter(IN PLARGE_INTEGER Counter, - IN PLARGE_INTEGER Frequency) +NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, + OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) { LARGE_INTEGER PerfCounter; LARGE_INTEGER PerfFrequency; - NTSTATUS Status; - - PerfCounter = KeQueryPerformanceCounter(&PerfFrequency); - - if (Counter != NULL) - { - Status = MmCopyToCaller(&Counter->QuadPart, &PerfCounter.QuadPart, sizeof(PerfCounter.QuadPart)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } - - if (Frequency != NULL) + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) { - Status = MmCopyToCaller(&Frequency->QuadPart, &PerfFrequency.QuadPart, sizeof(PerfFrequency.QuadPart)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + _SEH_TRY + { + ProbeForWrite(PerformanceCounter, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + if(PerformanceFrequency != NULL) + { + ProbeForWrite(PerformanceFrequency, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } } - return(STATUS_SUCCESS); + PerfCounter = KeQueryPerformanceCounter(&PerfFrequency); + + _SEH_TRY + { + *PerformanceCounter = PerfCounter; + if(PerformanceFrequency != NULL) + { + *PerformanceFrequency = PerfFrequency; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + return Status; } NTSTATUS STDCALL -NtDelayExecution(IN ULONG Alertable, - IN LARGE_INTEGER* Interval) +NtDelayExecution(IN BOOLEAN Alertable, + IN PLARGE_INTEGER DelayInterval) { - NTSTATUS Status; - LARGE_INTEGER Timeout; - - Status = MmCopyFromCaller(&Timeout, Interval, sizeof(Timeout)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Timeout = *((PLARGE_INTEGER)Interval); - DPRINT("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n", - Alertable, Internal, Timeout); + KPROCESSOR_MODE PreviousMode; + LARGE_INTEGER SafeInterval; - DPRINT("Execution delay is %d/%d\n", - Timeout.u.HighPart, Timeout.u.LowPart); - Status = KeDelayExecutionThread(UserMode, (BOOLEAN)Alertable, &Timeout); - return(Status); + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + NTSTATUS Status = STATUS_SUCCESS; + + _SEH_TRY + { + ProbeForRead(DelayInterval, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a copy on the kernel stack and let DelayInterval point to it so + we don't need to wrap KeDelayExecutionThread in SEH! */ + SafeInterval = *DelayInterval; + DelayInterval = &SafeInterval; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + return KeDelayExecutionThread(PreviousMode, + Alertable, + DelayInterval); } @@ -529,7 +568,7 @@ HandleExpiredTimer(PKTIMER Timer) KeAcquireDispatcherDatabaseLockAtDpcLevel(); Timer->Header.SignalState = TRUE; - KiDispatcherObjectWake(&Timer->Header); + KiDispatcherObjectWake(&Timer->Header, 0); KeReleaseDispatcherDatabaseLockFromDpcLevel(); if (Timer->Period != 0) diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 89c0c048b6f..3cff12ee706 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -1,13 +1,12 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS project - * FILE: ntoskrnl/ke/wait.c - * PURPOSE: Manages non-busy waiting - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 21/07/98: Created - * 12/1/99: Phillip Susi: Fixed wake code in KeDispatcherObjectWake - * so that things like KeWaitForXXX() return the correct value +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS project + * FILE: ntoskrnl/ke/wait.c + * PURPOSE: Manages non-busy waiting + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi */ /* NOTES ******************************************************************** @@ -25,8 +24,8 @@ static KSPIN_LOCK DispatcherDatabaseLock; -#define KeDispatcherObjectWakeOne(hdr) KeDispatcherObjectWakeOneOrAll(hdr, FALSE) -#define KeDispatcherObjectWakeAll(hdr) KeDispatcherObjectWakeOneOrAll(hdr, TRUE) +#define KeDispatcherObjectWakeOne(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, FALSE) +#define KeDispatcherObjectWakeAll(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, TRUE) extern POBJECT_TYPE EXPORTED ExMutantObjectType; extern POBJECT_TYPE EXPORTED ExSemaphoreObjectType; @@ -227,13 +226,14 @@ BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus) if (WasWaiting) { - PsUnblockThread((PETHREAD)Thread, &WaitStatus); + PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0); } return WasWaiting; } static BOOLEAN KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, + KPRIORITY increment, BOOLEAN WakeAll) { PKWAIT_BLOCK Waiter; @@ -332,7 +332,8 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, WakedAny = TRUE; DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status); - PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), &Status); + PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), + &Status, increment); } } @@ -340,7 +341,7 @@ KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr, } -BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) +BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment) /* * FUNCTION: Wake threads waiting on a dispatcher object * NOTE: The exact semantics of waking are dependant on the type of object @@ -355,19 +356,19 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) switch (hdr->Type) { case InternalNotificationEvent: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalNotificationTimer: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalSynchronizationEvent: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalSynchronizationTimer: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalQueueType: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); case InternalSemaphoreType: DPRINT("hdr->SignalState %d\n", hdr->SignalState); @@ -376,20 +377,20 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr) do { DPRINT("Waking one semaphore waiter\n"); - Ret = KeDispatcherObjectWakeOne(hdr); + Ret = KeDispatcherObjectWakeOne(hdr, increment); } while(hdr->SignalState > 0 && Ret) ; return(Ret); } else return FALSE; case InternalProcessType: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalThreadType: - return(KeDispatcherObjectWakeAll(hdr)); + return(KeDispatcherObjectWakeAll(hdr, increment)); case InternalMutexType: - return(KeDispatcherObjectWakeOne(hdr)); + return(KeDispatcherObjectWakeOne(hdr, increment)); } DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type); KEBUGCHECK(0); @@ -488,6 +489,7 @@ KeWaitForMultipleObjects(ULONG Count, NTSTATUS Status; KIRQL OldIrql; BOOLEAN Abandoned; + NTSTATUS WaitStatus; DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) " "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread()); @@ -539,40 +541,32 @@ KeWaitForMultipleObjects(ULONG Count, OldIrql = KeAcquireDispatcherDatabaseLock (); } - /* Alertability 101 - * ---------------- - * A Wait can either be Alertable, or Non-Alertable. - * An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting - * If an APC is Pending however, we must refuse an Alertable Wait. Such a wait would - * be pointless since an APC is just about to be delivered. - * - * There are many ways to check if it's safe to be alertable, and these are the ones - * that I could think of: - * - The Thread is already Alerted. So someone beat us to the punch and we bail out. - * - The Thread is Waiting in User-Mode, the APC Queue is not-empty. - * It's defintely clear that we have incoming APCs, so we need to bail out and let the system - * know that there are Pending User APCs (so they can be Delivered and maybe we can try again) - * - * Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there - * are Pending User APCs, we should bail out, since APCs will be delivered any second. - */ - if (Alertable) { - if (CurrentThread->Alerted[(int)WaitMode]) { - CurrentThread->Alerted[(int)WaitMode] = FALSE; - DPRINT("Alertability failed\n"); - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_ALERTED); - } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) { - DPRINT1("Alertability failed\n"); - CurrentThread->ApcState.UserApcPending = TRUE; - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_USER_APC); - } - } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) { - DPRINT1("Alertability failed\n"); - KeReleaseDispatcherDatabaseLock(OldIrql); - return (STATUS_USER_APC); - } + /* Get the current Wait Status */ + WaitStatus = CurrentThread->WaitStatus; + + if (Alertable) { + + /* If the Thread is Alerted, set the Wait Status accordingly */ + if (CurrentThread->Alerted[(int)WaitMode]) { + + CurrentThread->Alerted[(int)WaitMode] = FALSE; + DPRINT("Thread was Alerted\n"); + WaitStatus = STATUS_ALERTED; + + /* If there are User APCs Pending, then we can't really be alertable */ + } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && + (WaitMode == UserMode)) { + + DPRINT1("APCs are Pending\n"); + CurrentThread->ApcState.UserApcPending = TRUE; + WaitStatus = STATUS_USER_APC; + } + + /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */ + } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) { + DPRINT1("APCs are Pending\n"); + WaitStatus = STATUS_USER_APC; + } /* * Check if the wait is (already) satisfied @@ -658,7 +652,7 @@ KeWaitForMultipleObjects(ULONG Count, /* * Set up the wait */ - CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; + CurrentThread->WaitStatus = WaitStatus;; for (i = 0; i < Count; i++) { @@ -723,7 +717,7 @@ KeWaitForMultipleObjects(ULONG Count, if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount && !IsListEmpty(&CurrentThread->Queue->EntryListHead)) { - KiDispatcherObjectWake(&CurrentThread->Queue->Header); + KiDispatcherObjectWake(&CurrentThread->Queue->Header, IO_NO_INCREMENT); } } diff --git a/reactos/ntoskrnl/ldr/init.c b/reactos/ntoskrnl/ldr/init.c index 4ba799b189d..7b0d5352fb7 100644 --- a/reactos/ntoskrnl/ldr/init.c +++ b/reactos/ntoskrnl/ldr/init.c @@ -1,38 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ldr/init.c * PURPOSE: Loaders for PE executables + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) - * UPDATE HISTORY: - * DW 22/05/98 Created - * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE - * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF - * RJJ 10/12/98 Rolled in David's code to load COFF drivers - * JM 14/12/98 Built initial PE user module loader - * RJJ 06/03/99 Moved user PE loader into NTDLL - * EA 19990717 LdrGetSystemDirectory() - * EK 20000618 Using SystemRoot link instead of LdrGetSystemDirectory() - * EK 20021119 Create a process parameter block for the initial process. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 9c58c5aaec6..c1f7a8ab78a 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -4,21 +4,11 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ldr/loader.c * PURPOSE: Loaders for PE executables + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) * Jason Filby (jasonfilby@yahoo.com) * Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * DW 22/05/98 Created - * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE - * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF - * RJJ 10/12/98 Rolled in David's code to load COFF drivers - * JM 14/12/98 Built initial PE user module loader - * RJJ 06/03/99 Moved user PE loader into NTDLL - * JF 26/01/2000 Recoded some parts to retrieve export details correctly - * DW 27/06/2000 Removed redundant header files - * CSH 11/04/2001 Added automatic loading of module symbols if they exist - * KJK 02/04/2003 Nebbet-ized a couple of type names */ @@ -307,7 +297,7 @@ LdrLoadModule(PUNICODE_STRING Filename, NULL, NULL); CHECKPOINT; - Status = NtOpenFile(&FileHandle, + Status = ZwOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, @@ -322,7 +312,7 @@ LdrLoadModule(PUNICODE_STRING Filename, CHECKPOINT; /* Get the size of the file */ - Status = NtQueryInformationFile(FileHandle, + Status = ZwQueryInformationFile(FileHandle, &IoStatusBlock, &FileStdInfo, sizeof(FileStdInfo), @@ -348,7 +338,7 @@ LdrLoadModule(PUNICODE_STRING Filename, CHECKPOINT; /* Load driver into memory chunk */ - Status = NtReadFile(FileHandle, + Status = ZwReadFile(FileHandle, 0, 0, 0, &IoStatusBlock, ModuleLoadBase, @@ -363,7 +353,7 @@ LdrLoadModule(PUNICODE_STRING Filename, } CHECKPOINT; - NtClose(FileHandle); + ZwClose(FileHandle); Status = LdrProcessModule(ModuleLoadBase, Filename, @@ -680,7 +670,7 @@ LdrLookupPageProtection(PVOID PageStart, { Execute = TRUE; } - if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_LNK_OTHER)) + if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { Write = TRUE; } @@ -910,7 +900,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase, Protect = PAGE_EXECUTE_READ; } } - else if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_LNK_OTHER)) + else if (Characteristics & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { Protect = PAGE_READWRITE; } @@ -1115,7 +1105,7 @@ LdrSafePEProcessModule(PVOID ModuleLoadBase, PageAddress = (PVOID)((ULONG_PTR)PageAddress + PAGE_SIZE); } if (DriverBase == ModuleLoadBase && - Characteristics & IMAGE_SCN_LNK_OTHER) + Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { /* For ntoskrnl, we must stop after the bss section */ break; @@ -1587,6 +1577,12 @@ LdrPEFixupImports(PMODULE_OBJECT Module) DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); while (ImportModuleDirectory->Name) { + if (Module->Length <= ImportModuleDirectory->Name) + { + DPRINT1("Invalid import directory in %wZ\n", &Module->FullName); + return STATUS_SECTION_NOT_IMAGE; + } + /* Check to make sure that import lib is kernel */ ImportedName = (PCHAR) Module->Base + ImportModuleDirectory->Name; diff --git a/reactos/ntoskrnl/ldr/resource.c b/reactos/ntoskrnl/ldr/resource.c index 28507e71dac..97588714a0e 100644 --- a/reactos/ntoskrnl/ldr/resource.c +++ b/reactos/ntoskrnl/ldr/resource.c @@ -4,6 +4,7 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ldr/resource.c * PURPOSE: Resource loader + * * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ diff --git a/reactos/ntoskrnl/ldr/rtl.c b/reactos/ntoskrnl/ldr/rtl.c index ee9a7aa20cc..dd345fcf803 100644 --- a/reactos/ntoskrnl/ldr/rtl.c +++ b/reactos/ntoskrnl/ldr/rtl.c @@ -2,8 +2,9 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ldr/loader.c + * FILE: ntoskrnl/ldr/rtl.c * PURPOSE: Loader utilities + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) */ @@ -16,132 +17,6 @@ /* FUNCTIONS ****************************************************************/ - -/* - * @implemented - */ -PIMAGE_NT_HEADERS STDCALL -RtlImageNtHeader (IN PVOID BaseAddress) -{ - PIMAGE_DOS_HEADER DosHeader; - PIMAGE_NT_HEADERS NTHeaders; - - DosHeader = (PIMAGE_DOS_HEADER)BaseAddress; - NTHeaders = (PIMAGE_NT_HEADERS)((char*)BaseAddress + DosHeader->e_lfanew); - if ((DosHeader->e_magic != IMAGE_DOS_SIGNATURE) - || (DosHeader->e_lfanew == 0L) - || (*(PULONG) NTHeaders != IMAGE_NT_SIGNATURE)) - { - return(NULL); - } - return(NTHeaders); -} - - -/* - * @implemented - */ -PVOID STDCALL -RtlImageDirectoryEntryToData (IN PVOID BaseAddress, - IN BOOLEAN ImageLoaded, - IN ULONG Directory, - OUT PULONG Size) -{ - PIMAGE_NT_HEADERS NtHeader; - PIMAGE_SECTION_HEADER SectionHeader; - ULONG Va; - ULONG Count; - - NtHeader = RtlImageNtHeader (BaseAddress); - if (NtHeader == NULL) - return NULL; - - if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) - return NULL; - - Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress; - if (Va == 0) - return NULL; - - if (Size) - *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size; - - if (ImageLoaded) - return (PVOID)((char*)BaseAddress + Va); - - /* image mapped as ordinary file, we must find raw pointer */ - SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1); - Count = NtHeader->FileHeader.NumberOfSections; - while (Count--) - { - if (SectionHeader->VirtualAddress == Va) - return (PVOID)((char*)BaseAddress + SectionHeader->PointerToRawData); - SectionHeader++; - } - - return NULL; -} - - -PIMAGE_SECTION_HEADER -STDCALL -RtlImageRvaToSection ( - PIMAGE_NT_HEADERS NtHeader, - PVOID BaseAddress, - ULONG Rva - ) -{ - PIMAGE_SECTION_HEADER Section; - ULONG Va; - ULONG Count; - - Count = NtHeader->FileHeader.NumberOfSections; - Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader + - NtHeader->FileHeader.SizeOfOptionalHeader); - while (Count) - { - Va = Section->VirtualAddress; - if ((Va <= Rva) && - (Rva < Va + Section->SizeOfRawData)) - return Section; - Section++; - } - return NULL; -} - - -ULONG -STDCALL -RtlImageRvaToVa ( - PIMAGE_NT_HEADERS NtHeader, - PVOID BaseAddress, - ULONG Rva, - PIMAGE_SECTION_HEADER *SectionHeader - ) -{ - PIMAGE_SECTION_HEADER Section = NULL; - - if (SectionHeader) - Section = *SectionHeader; - - if (Section == NULL || - Rva < Section->VirtualAddress || - Rva >= Section->VirtualAddress + Section->SizeOfRawData) - { - Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva); - if (Section == NULL) - return 0; - - if (SectionHeader) - *SectionHeader = Section; - } - - return (ULONG)((char*)BaseAddress + - Rva + - Section->PointerToRawData - - Section->VirtualAddress); -} - #define RVA(m, b) ((ULONG)b + m) NTSTATUS STDCALL diff --git a/reactos/ntoskrnl/ldr/sysdll.c b/reactos/ntoskrnl/ldr/sysdll.c index 8a2756b4d78..9af2d009eef 100644 --- a/reactos/ntoskrnl/ldr/sysdll.c +++ b/reactos/ntoskrnl/ldr/sysdll.c @@ -1,13 +1,13 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ldr/sysdll.c * PURPOSE: Loaders for PE executables + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) - * UPDATE HISTORY: - * DW 26/01/00 Created - * Skywing 09/11/2003 Added support for KiRaiseUserExceptionDispatcher + * Skywing */ /* INCLUDES *****************************************************************/ @@ -93,14 +93,14 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, NULL); DPRINT("Opening NTDLL\n"); Status = ZwOpenFile(&FileHandle, - FILE_ALL_ACCESS, + FILE_READ_ACCESS, &FileObjectAttributes, &Iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { - DbgPrint("NTDLL open failed (Status %x)\n", Status); + DPRINT1("NTDLL open failed (Status %x)\n", Status); return Status; } Status = ZwReadFile(FileHandle, @@ -114,7 +114,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, 0); if (!NT_SUCCESS(Status) || Iosb.Information != sizeof(BlockBuffer)) { - DbgPrint("NTDLL header read failed (Status %x)\n", Status); + DPRINT1("NTDLL header read failed (Status %x)\n", Status); ZwClose(FileHandle); return Status; } @@ -129,7 +129,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, || (DosHeader->e_lfanew == 0L) || (*(PULONG) NTHeaders != IMAGE_NT_SIGNATURE)) { - DbgPrint("NTDLL format invalid\n"); + DPRINT1("NTDLL format invalid\n"); ZwClose(FileHandle); return(STATUS_UNSUCCESSFUL); } @@ -149,7 +149,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, FileHandle); if (!NT_SUCCESS(Status)) { - DbgPrint("NTDLL create section failed (Status %x)\n", Status); + DPRINT1("NTDLL create section failed (Status %x)\n", Status); ZwClose(FileHandle); return(Status); } @@ -172,7 +172,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { - DbgPrint("NTDLL map view of secion failed (Status %x)", Status); + DPRINT1("NTDLL map view of secion failed (Status %x)", Status); ZwClose(NTDllSectionHandle); return(Status); } @@ -186,7 +186,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, NULL); if (!NT_SUCCESS(Status)) { - DbgPrint("ObReferenceObjectByProcess() failed (Status %x)\n", Status); + DPRINT1("ObReferenceObjectByProcess() failed (Status %x)\n", Status); return(Status); } @@ -210,7 +210,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, &SystemDllEntryPoint); if (!NT_SUCCESS(Status)) { - DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status); if (Process != CurrentProcess) { KeDetachProcess(); @@ -235,7 +235,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, &SystemDllApcDispatcher); if (!NT_SUCCESS(Status)) { - DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status); if (Process != CurrentProcess) { KeDetachProcess(); @@ -259,7 +259,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, &SystemDllExceptionDispatcher); if (!NT_SUCCESS(Status)) { - DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status); if (Process != CurrentProcess) { KeDetachProcess(); @@ -283,7 +283,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, &SystemDllCallbackDispatcher); if (!NT_SUCCESS(Status)) { - DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status); if (Process != CurrentProcess) { KeDetachProcess(); @@ -307,7 +307,7 @@ NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, &SystemDllRaiseExceptionDispatcher); if (!NT_SUCCESS(Status)) { - DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status); if (Process != CurrentProcess) { KeDetachProcess(); diff --git a/reactos/ntoskrnl/ldr/userldr.c b/reactos/ntoskrnl/ldr/userldr.c index 00e28be6c59..8c48105b6e2 100644 --- a/reactos/ntoskrnl/ldr/userldr.c +++ b/reactos/ntoskrnl/ldr/userldr.c @@ -1,12 +1,12 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ldr/sysdll.c + * FILE: ntoskrnl/ldr/userldr.c * PURPOSE: Loaders for PE executables + * * PROGRAMMERS: Jean Michault * Rex Jolliff (rex@lvcablemodem.com) - * UPDATE HISTORY: - * DW 26/01/00 Created */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/lpc/close.c b/reactos/ntoskrnl/lpc/close.c index 1fd8d76e37d..4f61c713263 100644 --- a/reactos/ntoskrnl/lpc/close.c +++ b/reactos/ntoskrnl/lpc/close.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/close.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/lpc/complete.c b/reactos/ntoskrnl/lpc/complete.c index 3b7f67a020d..343e143d966 100644 --- a/reactos/ntoskrnl/lpc/complete.c +++ b/reactos/ntoskrnl/lpc/complete.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/complete.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ @@ -46,7 +45,7 @@ NtCompleteConnectPort (HANDLE hServerSideCommPort) */ Status = ObReferenceObjectByHandle (hServerSideCommPort, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&ReplyPort, NULL); diff --git a/reactos/ntoskrnl/lpc/connect.c b/reactos/ntoskrnl/lpc/connect.c index 4df287118c4..544788268dd 100644 --- a/reactos/ntoskrnl/lpc/connect.c +++ b/reactos/ntoskrnl/lpc/connect.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/connect.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -66,7 +65,7 @@ EiConnectPort(IN PEPORT* ConnectedPort, * Create a port to represent our side of the connection */ Status = ObCreateObject (KernelMode, - & LpcPortObjectType, + LpcPortObjectType, NULL, KernelMode, NULL, @@ -78,7 +77,7 @@ EiConnectPort(IN PEPORT* ConnectedPort, { return (Status); } - NiInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort); + LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort); /* * Allocate a request message. @@ -333,7 +332,7 @@ NtConnectPort (PHANDLE UnsafeConnectedPortHandle, 0, NULL, PORT_ALL_ACCESS, /* DesiredAccess */ - & LpcPortObjectType, + LpcPortObjectType, UserMode, NULL, (PVOID*)&NamedPort); @@ -547,7 +546,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, Status = ObReferenceObjectByHandle(NamedPortHandle, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&NamedPort, NULL); @@ -563,7 +562,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, if (AcceptIt) { Status = ObCreateObject(ExGetPreviousMode(), - & LpcPortObjectType, + LpcPortObjectType, NULL, ExGetPreviousMode(), NULL, @@ -592,7 +591,7 @@ NtAcceptConnectPort (PHANDLE ServerPortHandle, return(Status); } - NiInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort); + LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort); } /* diff --git a/reactos/ntoskrnl/lpc/create.c b/reactos/ntoskrnl/lpc/create.c index e24ed62e53d..637c54d0166 100644 --- a/reactos/ntoskrnl/lpc/create.c +++ b/reactos/ntoskrnl/lpc/create.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/create.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -134,7 +133,7 @@ NtCreatePort (PHANDLE PortHandle, /* Ask Ob to create the object */ Status = ObCreateObject (ExGetPreviousMode(), - & LpcPortObjectType, + LpcPortObjectType, ObjectAttributes, ExGetPreviousMode(), NULL, @@ -159,7 +158,7 @@ NtCreatePort (PHANDLE PortHandle, return (Status); } - Status = NiInitializePort (Port, EPORT_TYPE_SERVER_RQST_PORT, NULL); + Status = LpcpInitializePort (Port, EPORT_TYPE_SERVER_RQST_PORT, NULL); Port->MaxConnectInfoLength = PORT_MAX_DATA_LENGTH; Port->MaxDataLength = PORT_MAX_MESSAGE_LENGTH; Port->MaxPoolUsage = MaxPoolUsage; diff --git a/reactos/ntoskrnl/lpc/listen.c b/reactos/ntoskrnl/lpc/listen.c index a9931652e92..7b5d3cbc34d 100644 --- a/reactos/ntoskrnl/lpc/listen.c +++ b/reactos/ntoskrnl/lpc/listen.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/listen.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/lpc/port.c b/reactos/ntoskrnl/lpc/port.c index b21e6f994e1..6735cc195d8 100644 --- a/reactos/ntoskrnl/lpc/port.c +++ b/reactos/ntoskrnl/lpc/port.c @@ -4,12 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/port.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - * - * 2000-06-04 (ea) - * ntoskrnl/nt/port.c moved in ntoskrnl/lpc/port.c + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -21,7 +17,7 @@ /* GLOBALS *******************************************************************/ -OBJECT_TYPE LpcPortObjectType = {0, }; +POBJECT_TYPE LpcPortObjectType = 0; ULONG LpcpNextMessageId = 0; /* 0 is not a valid ID */ FAST_MUTEX LpcpLock; /* global internal sync in LPC facility */ @@ -35,32 +31,34 @@ static GENERIC_MAPPING ExpPortMapping = { NTSTATUS INIT_FUNCTION -NiInitPort (VOID) +LpcpInitSystem (VOID) { - RtlZeroMemory (& LpcPortObjectType, sizeof (OBJECT_TYPE)); + /* Allocate Memory for the LPC Object */ + LpcPortObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + RtlZeroMemory (LpcPortObjectType, sizeof (OBJECT_TYPE)); - RtlRosInitUnicodeStringFromLiteral(&LpcPortObjectType.TypeName,L"Port"); + RtlRosInitUnicodeStringFromLiteral(&LpcPortObjectType->TypeName,L"Port"); - LpcPortObjectType.Tag = TAG('L', 'P', 'R', 'T'); - LpcPortObjectType.MaxObjects = ULONG_MAX; - LpcPortObjectType.MaxHandles = ULONG_MAX; - LpcPortObjectType.TotalObjects = 0; - LpcPortObjectType.TotalHandles = 0; - LpcPortObjectType.PagedPoolCharge = 0; - LpcPortObjectType.NonpagedPoolCharge = sizeof(EPORT); - LpcPortObjectType.Mapping = &ExpPortMapping; - LpcPortObjectType.Dump = NULL; - LpcPortObjectType.Open = NULL; - LpcPortObjectType.Close = NiClosePort; - LpcPortObjectType.Delete = NiDeletePort; - LpcPortObjectType.Parse = NULL; - LpcPortObjectType.Security = NULL; - LpcPortObjectType.QueryName = NULL; - LpcPortObjectType.OkayToClose = NULL; - LpcPortObjectType.Create = NiCreatePort; - LpcPortObjectType.DuplicationNotify = NULL; + LpcPortObjectType->Tag = TAG('L', 'P', 'R', 'T'); + LpcPortObjectType->PeakObjects = 0; + LpcPortObjectType->PeakHandles = 0; + LpcPortObjectType->TotalObjects = 0; + LpcPortObjectType->TotalHandles = 0; + LpcPortObjectType->PagedPoolCharge = 0; + LpcPortObjectType->NonpagedPoolCharge = sizeof(EPORT); + LpcPortObjectType->Mapping = &ExpPortMapping; + LpcPortObjectType->Dump = NULL; + LpcPortObjectType->Open = NULL; + LpcPortObjectType->Close = NiClosePort; + LpcPortObjectType->Delete = NiDeletePort; + LpcPortObjectType->Parse = NULL; + LpcPortObjectType->Security = NULL; + LpcPortObjectType->QueryName = NULL; + LpcPortObjectType->OkayToClose = NULL; + LpcPortObjectType->Create = NiCreatePort; + LpcPortObjectType->DuplicationNotify = NULL; - ObpCreateTypeObject(& LpcPortObjectType); + ObpCreateTypeObject(LpcPortObjectType); LpcpNextMessageId = 0; @@ -89,7 +87,7 @@ NiInitPort (VOID) * otherwise. */ NTSTATUS STDCALL -NiInitializePort (IN OUT PEPORT Port, +LpcpInitializePort (IN OUT PEPORT Port, IN USHORT Type, IN PEPORT Parent OPTIONAL) { diff --git a/reactos/ntoskrnl/lpc/query.c b/reactos/ntoskrnl/lpc/query.c index 456acd3300d..faad386e23b 100644 --- a/reactos/ntoskrnl/lpc/query.c +++ b/reactos/ntoskrnl/lpc/query.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/query.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -50,7 +49,7 @@ NtQueryInformationPort (IN HANDLE PortHandle, Status = ObReferenceObjectByHandle (PortHandle, PORT_ALL_ACCESS, /* AccessRequired */ - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID *) & Port, NULL); diff --git a/reactos/ntoskrnl/lpc/queue.c b/reactos/ntoskrnl/lpc/queue.c index c98fbf20bc3..ebb60623bab 100644 --- a/reactos/ntoskrnl/lpc/queue.c +++ b/reactos/ntoskrnl/lpc/queue.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/queue.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/lpc/receive.c b/reactos/ntoskrnl/lpc/receive.c index bf71f12d2c7..6b05130b2ff 100644 --- a/reactos/ntoskrnl/lpc/receive.c +++ b/reactos/ntoskrnl/lpc/receive.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/receive.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/lpc/reply.c b/reactos/ntoskrnl/lpc/reply.c index c66312a478a..73bb67f4090 100644 --- a/reactos/ntoskrnl/lpc/reply.c +++ b/reactos/ntoskrnl/lpc/reply.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/reply.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ @@ -88,7 +87,7 @@ NtReplyPort (IN HANDLE PortHandle, Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS, /* AccessRequired */ - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&Port, NULL); @@ -154,7 +153,7 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle, Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&Port, NULL); diff --git a/reactos/ntoskrnl/lpc/send.c b/reactos/ntoskrnl/lpc/send.c index bb89dbcbc12..1f790c8609e 100644 --- a/reactos/ntoskrnl/lpc/send.c +++ b/reactos/ntoskrnl/lpc/send.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/lpc/send.c * PURPOSE: Communication mechanism - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -30,7 +29,7 @@ */ NTSTATUS STDCALL LpcSendTerminationPort (IN PEPORT Port, - IN TIME CreationTime) + IN LARGE_INTEGER CreationTime) { NTSTATUS Status; LPC_TERMINATION_MESSAGE Msg; @@ -180,7 +179,7 @@ NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle, Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&Port, NULL); @@ -231,7 +230,7 @@ NtRequestWaitReplyPort (IN HANDLE PortHandle, Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, UserMode, (PVOID*)&Port, NULL); diff --git a/reactos/ntoskrnl/mkconfig.c b/reactos/ntoskrnl/mkconfig.c index 56bb885dc08..ad2c6aabc63 100644 --- a/reactos/ntoskrnl/mkconfig.c +++ b/reactos/ntoskrnl/mkconfig.c @@ -1,3 +1,13 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mkconfig.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #include #include #include diff --git a/reactos/ntoskrnl/mm/RPoolMgr.h b/reactos/ntoskrnl/mm/RPoolMgr.h index c94da9b4014..dae429f3574 100644 --- a/reactos/ntoskrnl/mm/RPoolMgr.h +++ b/reactos/ntoskrnl/mm/RPoolMgr.h @@ -13,16 +13,16 @@ typedef unsigned long rulong; -#define R_IS_POOL_PTR(pool,ptr) (void*)(ptr) >= pool->UserBase && (char*)(ptr) < ((char*)pool->UserBase+pool->UserSize) +#define R_IS_POOL_PTR(pool,ptr) (void*)(ptr) >= pool->UserBase && (ULONG_PTR)(ptr) < ((ULONG_PTR)pool->UserBase + pool->UserSize) #define R_ASSERT_PTR(pool,ptr) ASSERT( R_IS_POOL_PTR(pool,ptr) ) #define R_ASSERT_SIZE(pool,sz) ASSERT( sz > (sizeof(R_USED)+2*R_RZ) && sz >= sizeof(R_FREE) && sz < pool->UserSize ) #ifndef R_ROUND_UP -#define R_ROUND_UP(x,s) ((PVOID)(((rulong)(x)+(s)-1) & ~((s)-1))) +#define R_ROUND_UP(x,s) ((PVOID)(((ULONG_PTR)(x)+(s)-1) & ~((ULONG_PTR)(s)-1))) #endif//R_ROUND_UP #ifndef R_ROUND_DOWN -#define R_ROUND_DOWN(x,s) ((PVOID)(((rulong)(x)) & ~((s)-1))) +#define R_ROUND_DOWN(x,s) ((PVOID)(((ULONG_PTR)(x)) & ~((ULONG_PTR)(s)-1))) #endif//R_ROUND_DOWN #ifndef R_QUEMIN @@ -79,7 +79,7 @@ typedef struct _R_FREE rulong Status : 2; rulong Size; #if R_STACK - rulong LastOwnerStack[R_STACK]; + ULONG_PTR LastOwnerStack[R_STACK]; #endif//R_STACK struct _R_FREE* NextFree; struct _R_FREE* PrevFree; @@ -95,7 +95,7 @@ typedef struct _R_USED rulong Status : 2; rulong Size; #if R_STACK - rulong LastOwnerStack[R_STACK]; + ULONG_PTR LastOwnerStack[R_STACK]; #endif//R_STACK struct _R_USED* NextUsed; #if R_RZ @@ -245,7 +245,7 @@ RPoolRemoveFree ( PR_POOL pool, PR_FREE Item ) pool->FirstFree = Item->NextFree; } #if defined(DBG) || defined(KDBG) - Item->NextFree = Item->PrevFree = (PR_FREE)0xDEADBEEF; + Item->NextFree = Item->PrevFree = (PR_FREE)(ULONG_PTR)0xDEADBEEF; #endif//DBG || KDBG } @@ -281,7 +281,7 @@ RFreeInit ( void* memory ) block->Status = 0; RFreeFillStack ( block ); #if defined(DBG) || defined(KDBG) - block->PrevFree = block->NextFree = (PR_FREE)0xDEADBEEF; + block->PrevFree = block->NextFree = (PR_FREE)(ULONG_PTR)0xDEADBEEF; #endif//DBG || KDBG return block; } @@ -369,6 +369,39 @@ RiBadBlock ( PR_USED pUsed, char* Addr, const char* violation, const char* file, RiPrintLastOwner ( pUsed ); R_DEBUG ( "\n" ); + R_DEBUG ( "Contents of Block:\n" ); + for ( i = 0; i < 8*16 && i < pUsed->UserSize; i += 16 ) + { + int j; + R_DEBUG ( "%04X ", i ); + for ( j = 0; j < 16; j++ ) + { + if ( i+j < pUsed->UserSize ) + { + R_DEBUG ( "%02X ", (unsigned)(unsigned char)Addr[i+j] ); + } + else + { + R_DEBUG ( " " ); + } + } + R_DEBUG(" "); + for ( j = 0; j < 16; j++ ) + { + if ( i+j < pUsed->UserSize ) + { + char c = Addr[i+j]; + if ( c < 0x20 || c > 0x7E ) + c = '.'; + R_DEBUG ( "%c", c ); + } + else + { + R_DEBUG ( " " ); + } + } + R_DEBUG("\n"); + } R_PANIC(); } static void @@ -423,11 +456,11 @@ RUsedRedZoneCheck ( PR_POOL pool, PR_USED pUsed, char* Addr, const char* file, i } if ( !bLow || !bHigh ) { - const char* violation = "High and Low-side redzone"; + const char* violation = "High and Low-side redzone overwrite"; if ( bHigh ) // high is okay, so it was just low failed - violation = "Low-side redzone"; + violation = "Low-side redzone overwrite"; else if ( bLow ) // low side is okay, so it was just high failed - violation = "High-side redzone"; + violation = "High-side redzone overwrite"; RiBadBlock ( pUsed, Addr, violation, file, line, 1 ); } } @@ -611,7 +644,7 @@ RiUsedInit ( PR_USED Block, rulong Tag ) // now add the block to the used block list #if defined(DBG) || defined(KDBG) - Block->NextUsed = (PR_USED)0xDEADBEEF; + Block->NextUsed = (PR_USED)(ULONG_PTR)0xDEADBEEF; #endif//R_USED_LIST Block->Tag = Tag; diff --git a/reactos/ntoskrnl/mm/anonmem.c b/reactos/ntoskrnl/mm/anonmem.c index 8310bb68231..33efecd23cb 100644 --- a/reactos/ntoskrnl/mm/anonmem.c +++ b/reactos/ntoskrnl/mm/anonmem.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/anonmem.c - * PURPOSE: Implementing anonymous memory. - * PROGRAMMER: David Welch + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/anonmem.c + * PURPOSE: Implementing anonymous memory. + * + * PROGRAMMERS: David Welch */ /* INCLUDE *****************************************************************/ @@ -272,7 +256,7 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace, /* * Get or create a page operation */ - PageOp = MmGetPageOp(MemoryArea, (ULONG)MemoryArea->Process->UniqueProcessId, + PageOp = MmGetPageOp(MemoryArea, MemoryArea->Process->UniqueProcessId, (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0, MM_PAGEOP_PAGEIN, FALSE); if (PageOp == NULL) diff --git a/reactos/ntoskrnl/mm/aspace.c b/reactos/ntoskrnl/mm/aspace.c index f7ee69a4c42..28f62383ad3 100644 --- a/reactos/ntoskrnl/mm/aspace.c +++ b/reactos/ntoskrnl/mm/aspace.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/aspace.c * PURPOSE: Manages address spaces - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/balance.c b/reactos/ntoskrnl/mm/balance.c index 89739bbb460..c026a991e1c 100644 --- a/reactos/ntoskrnl/mm/balance.c +++ b/reactos/ntoskrnl/mm/balance.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/balance.c - * PURPOSE: kernel memory managment functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 27/12/01 + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/balance.c + * PURPOSE: kernel memory managment functions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/cont.c b/reactos/ntoskrnl/mm/cont.c index 324cca6d44b..4aeec1f9614 100644 --- a/reactos/ntoskrnl/mm/cont.c +++ b/reactos/ntoskrnl/mm/cont.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/cont.c * PURPOSE: Manages continuous memory - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/drvlck.c b/reactos/ntoskrnl/mm/drvlck.c index 550307e213a..ec3e43c44cb 100644 --- a/reactos/ntoskrnl/mm/drvlck.c +++ b/reactos/ntoskrnl/mm/drvlck.c @@ -2,11 +2,10 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/drvlck.c + * FILE: ntoskrnl/mm/drvlck.c * PURPOSE: Managing driver managing - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/elf.c b/reactos/ntoskrnl/mm/elf.inc.h similarity index 98% rename from reactos/ntoskrnl/mm/elf.c rename to reactos/ntoskrnl/mm/elf.inc.h index 431aabb70a7..70e3e9763ce 100644 --- a/reactos/ntoskrnl/mm/elf.c +++ b/reactos/ntoskrnl/mm/elf.inc.h @@ -628,6 +628,12 @@ Elf64FmtCreateSection else pssSegments[j].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA; + /* + FIXME: see the TODO above. This is the safest way to load ELF drivers, for + now, if a bit wasteful of memory + */ + pssSegments[j].Characteristics |= IMAGE_SCN_MEM_NOT_PAGED; + /* Copy-on-write */ pssSegments[j].WriteCopy = TRUE; diff --git a/reactos/ntoskrnl/mm/elf32.c b/reactos/ntoskrnl/mm/elf32.c index 0a4374171f1..7e287452999 100644 --- a/reactos/ntoskrnl/mm/elf32.c +++ b/reactos/ntoskrnl/mm/elf32.c @@ -1,5 +1,15 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/elf32.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #define __ELF_WORD_SIZE 32 -#include "elf.c" +#include "elf.inc.h" extern NTSTATUS NTAPI Elf64FmtCreateSection ( diff --git a/reactos/ntoskrnl/mm/elf64.c b/reactos/ntoskrnl/mm/elf64.c index c96d87fb7aa..a8c46ae1fd2 100644 --- a/reactos/ntoskrnl/mm/elf64.c +++ b/reactos/ntoskrnl/mm/elf64.c @@ -1,2 +1,12 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/elf64.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #define __ELF_WORD_SIZE 64 -#include "elf.c" +#include "elf.inc.h" diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index d40d6d0b280..0e6038467a1 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -1,12 +1,12 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/freelist.c - * PURPOSE: Handle the list of free physical pages - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 27/05/98: Created - * 18/08/98: Added a fix from Robert Bergkvist +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/freelist.c + * PURPOSE: Handle the list of free physical pages + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Robert Bergkvist */ /* INCLUDES ****************************************************************/ @@ -56,9 +56,10 @@ static LIST_ENTRY FreeZeroedPageListHead; static LIST_ENTRY FreeUnzeroedPageListHead; static LIST_ENTRY BiosPageListHead; -static HANDLE ZeroPageThreadHandle; +static PETHREAD ZeroPageThread; static CLIENT_ID ZeroPageThreadId; static KEVENT ZeroPageThreadEvent; +static BOOLEAN ZeroPageThreadShouldTerminate = FALSE; static ULONG UnzeroedPageCount = 0; @@ -284,10 +285,10 @@ MiIsPfnRam(PADDRESS_RANGE BIOSMemoryMap, PVOID INIT_FUNCTION -MmInitializePageList(PVOID FirstPhysKernelAddress, - PVOID LastPhysKernelAddress, +MmInitializePageList(ULONG_PTR FirstPhysKernelAddress, + ULONG_PTR LastPhysKernelAddress, ULONG MemorySizeInPages, - ULONG LastKernelAddress, + ULONG_PTR LastKernelAddress, PADDRESS_RANGE BIOSMemoryMap, ULONG AddressRangeCount) /* @@ -331,9 +332,9 @@ MmInitializePageList(PVOID FirstPhysKernelAddress, DPRINT("Reserved %d\n", Reserved); LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress); - LastKernelAddress = ((ULONG)LastKernelAddress + (Reserved * PAGE_SIZE)); - LastPhysKernelAddress = (PVOID)PAGE_ROUND_UP(LastPhysKernelAddress); - LastPhysKernelAddress = (char*)LastPhysKernelAddress + (Reserved * PAGE_SIZE); + LastKernelAddress = ((ULONG_PTR)LastKernelAddress + (Reserved * PAGE_SIZE)); + LastPhysKernelAddress = (ULONG_PTR)PAGE_ROUND_UP(LastPhysKernelAddress); + LastPhysKernelAddress = (ULONG_PTR)LastPhysKernelAddress + (Reserved * PAGE_SIZE); MmStats.NrTotalPages = 0; MmStats.NrSystemPages = 0; @@ -349,7 +350,7 @@ MmInitializePageList(PVOID FirstPhysKernelAddress, LastPage = MmPageArraySize; for (i = 0; i < Reserved; i++) { - PVOID Address = (char*)(ULONG)MmPageArray + (i * PAGE_SIZE); + PVOID Address = (char*)MmPageArray + (i * PAGE_SIZE); ULONG j, start, end; if (!MmIsPagePresent(NULL, Address)) { @@ -381,6 +382,11 @@ MmInitializePageList(PVOID FirstPhysKernelAddress, KEBUGCHECK(0); } } + else + { + /* Setting the page protection is necessary to set the global bit on IA32 */ + MmSetPageProtect(NULL, Address, PAGE_READWRITE); + } memset(Address, 0, PAGE_SIZE); start = ((ULONG_PTR)Address - (ULONG_PTR)MmPageArray) / sizeof(PHYSICAL_PAGE); @@ -417,6 +423,17 @@ MmInitializePageList(PVOID FirstPhysKernelAddress, &MmPageArray[1].ListEntry); MmStats.NrReservedPages++; } + /* Protect the Page Directory. This will be changed in r3 */ + else if (j >= (KeLoaderBlock.PageDirectoryStart / PAGE_SIZE) && j < (KeLoaderBlock.PageDirectoryEnd / PAGE_SIZE)) + { + MmPageArray[j].Flags.Type = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[j].Flags.Zero = 0; + MmPageArray[j].Flags.Consumer = MC_NPPOOL; + MmPageArray[j].ReferenceCount = 1; + InsertTailList(&BiosPageListHead, + &MmPageArray[j].ListEntry); + MmStats.NrReservedPages++; + } else if (j >= 0xa0000 / PAGE_SIZE && j < 0x100000 / PAGE_SIZE) { MmPageArray[j].Flags.Type = MM_PHYSICAL_PAGE_BIOS; @@ -897,8 +914,156 @@ MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry) return PfnOffset; } +LONG +MmAllocPagesSpecifyRange(ULONG Consumer, + PHYSICAL_ADDRESS LowestAddress, + PHYSICAL_ADDRESS HighestAddress, + ULONG NumberOfPages, + PPFN_TYPE Pages) +{ + PPHYSICAL_PAGE PageDescriptor; + KIRQL oldIrql; + PFN_TYPE LowestPage, HighestPage; + PFN_TYPE pfn; + ULONG NumberOfPagesFound = 0; + ULONG i; -NTSTATUS STDCALL + DPRINT("MmAllocPagesSpecifyRange()\n" + " LowestAddress = 0x%08x%08x\n" + " HighestAddress = 0x%08x%08x\n" + " NumberOfPages = %d\n", + LowestAddress.u.HighPart, LowestAddress.u.LowPart, + HighestAddress.u.HighPart, HighestAddress.u.LowPart, + NumberOfPages); + + if (NumberOfPages == 0) + return 0; + + LowestPage = LowestAddress.QuadPart / PAGE_SIZE; + HighestPage = HighestAddress.QuadPart / PAGE_SIZE; + if ((HighestAddress.u.LowPart % PAGE_SIZE) != 0) + HighestPage++; + + if (LowestPage >= MmPageArraySize) + { + DPRINT1("MmAllocPagesSpecifyRange(): Out of memory\n"); + return -1; + } + if (HighestPage > MmPageArraySize) + HighestPage = MmPageArraySize; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + if (LowestPage == 0 && HighestPage == MmPageArraySize) + { + PLIST_ENTRY ListEntry; + while (NumberOfPagesFound < NumberOfPages) + { + if (!IsListEmpty(&FreeZeroedPageListHead)) + { + ListEntry = RemoveTailList(&FreeZeroedPageListHead); + } + else if (!IsListEmpty(&FreeUnzeroedPageListHead)) + { + ListEntry = RemoveTailList(&FreeUnzeroedPageListHead); + UnzeroedPageCount--; + } + else + { + if (NumberOfPagesFound == 0) + { + KeReleaseSpinLock(&PageListLock, oldIrql); + DPRINT1("MmAllocPagesSpecifyRange(): Out of memory\n"); + return -1; + } + else + { + break; + } + } + PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry); + + ASSERT(PageDescriptor->Flags.Type == MM_PHYSICAL_PAGE_FREE); + ASSERT(PageDescriptor->MapCount == 0); + ASSERT(PageDescriptor->ReferenceCount == 0); + + /* Allocate the page */ + PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; + PageDescriptor->Flags.Consumer = Consumer; + PageDescriptor->ReferenceCount = 1; + PageDescriptor->LockCount = 0; + PageDescriptor->MapCount = 0; + PageDescriptor->SavedSwapEntry = 0; /* FIXME: Do we need swap entries? */ + InsertTailList(&UsedPageListHeads[Consumer], &PageDescriptor->ListEntry); + + MmStats.NrSystemPages++; + MmStats.NrFreePages--; + + /* Remember the page */ + pfn = PageDescriptor - MmPageArray; + Pages[NumberOfPagesFound++] = pfn; + } + } + else + { + INT LookForZeroedPages; + for (LookForZeroedPages = 1; LookForZeroedPages >= 0; LookForZeroedPages--) + { + for (pfn = LowestPage; pfn < HighestPage; pfn++) + { + PageDescriptor = MmPageArray + pfn; + + if (PageDescriptor->Flags.Type != MM_PHYSICAL_PAGE_FREE) + continue; + if (PageDescriptor->Flags.Zero != LookForZeroedPages) + continue; + + ASSERT(PageDescriptor->MapCount == 0); + ASSERT(PageDescriptor->ReferenceCount == 0); + + /* Allocate the page */ + PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; + PageDescriptor->Flags.Consumer = Consumer; + PageDescriptor->ReferenceCount = 1; + PageDescriptor->LockCount = 0; + PageDescriptor->MapCount = 0; + PageDescriptor->SavedSwapEntry = 0; /* FIXME: Do we need swap entries? */ + RemoveEntryList(&PageDescriptor->ListEntry); + InsertTailList(&UsedPageListHeads[Consumer], &PageDescriptor->ListEntry); + + if (!PageDescriptor->Flags.Zero) + UnzeroedPageCount--; + MmStats.NrSystemPages++; + MmStats.NrFreePages--; + + /* Remember the page */ + Pages[NumberOfPagesFound++] = pfn; + if (NumberOfPagesFound == NumberOfPages) + break; + } + if (NumberOfPagesFound == NumberOfPages) + break; + } + } + KeReleaseSpinLock(&PageListLock, oldIrql); + + /* Zero unzero-ed pages */ + for (i = 0; i < NumberOfPagesFound; i++) + { + pfn = Pages[i]; + if (MmPageArray[pfn].Flags.Zero == 0) + { + MiZeroPage(pfn); + } + else + { + MmPageArray[pfn].Flags.Zero = 0; + } + } + + return NumberOfPagesFound; +} + +VOID STDCALL MmZeroPageThreadMain(PVOID Ignored) { NTSTATUS Status; @@ -906,7 +1071,6 @@ MmZeroPageThreadMain(PVOID Ignored) PLIST_ENTRY ListEntry; PPHYSICAL_PAGE PageDescriptor; PFN_TYPE Pfn; - static PVOID Address = NULL; ULONG Count; while(1) @@ -920,9 +1084,14 @@ MmZeroPageThreadMain(PVOID Ignored) { DbgPrint("ZeroPageThread: Wait failed\n"); KEBUGCHECK(0); - return(STATUS_UNSUCCESSFUL); + return; } + if (ZeroPageThreadShouldTerminate) + { + DbgPrint("ZeroPageThread: Terminating\n"); + return; + } Count = 0; KeAcquireSpinLock(&PageListLock, &oldIrql); while (!IsListEmpty(&FreeUnzeroedPageListHead)) @@ -933,27 +1102,9 @@ MmZeroPageThreadMain(PVOID Ignored) /* We set the page to used, because MmCreateVirtualMapping failed with unused pages */ PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; KeReleaseSpinLock(&PageListLock, oldIrql); - Count++; Pfn = PageDescriptor - MmPageArray; - if (Address == NULL) - { - Address = ExAllocatePageWithPhysPage(Pfn); - } - else - { - Status = MmCreateVirtualMapping(NULL, - Address, - PAGE_READWRITE | PAGE_SYSTEM, - &Pfn, - 1); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KEBUGCHECK(0); - } - } - memset(Address, 0, PAGE_SIZE); - MmDeleteVirtualMapping(NULL, (PVOID)Address, FALSE, NULL, NULL); + Status = MiZeroPage(Pfn); + KeAcquireSpinLock(&PageListLock, &oldIrql); if (PageDescriptor->MapCount != 0) { @@ -962,7 +1113,17 @@ MmZeroPageThreadMain(PVOID Ignored) } PageDescriptor->Flags.Zero = 1; PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_FREE; - InsertHeadList(&FreeZeroedPageListHead, ListEntry); + if (NT_SUCCESS(Status)) + { + InsertHeadList(&FreeZeroedPageListHead, ListEntry); + Count++; + } + else + { + InsertHeadList(&FreeUnzeroedPageListHead, ListEntry); + UnzeroedPageCount++; + } + } DPRINT("Zeroed %d pages.\n", Count); KeResetEvent(&ZeroPageThreadEvent); @@ -973,28 +1134,36 @@ MmZeroPageThreadMain(PVOID Ignored) NTSTATUS INIT_FUNCTION MmInitZeroPageThread(VOID) { - KPRIORITY Priority; NTSTATUS Status; - - Status = PsCreateSystemThread(&ZeroPageThreadHandle, + HANDLE ThreadHandle; + + ZeroPageThreadShouldTerminate = FALSE; + Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, NULL, &ZeroPageThreadId, - (PKSTART_ROUTINE) MmZeroPageThreadMain, + MmZeroPageThreadMain, NULL); if (!NT_SUCCESS(Status)) { - return(Status); + KEBUGCHECK(0); } - Priority = 1; - NtSetInformationThread(ZeroPageThreadHandle, - ThreadPriority, - &Priority, - sizeof(Priority)); + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + (PVOID*)&ZeroPageThread, + NULL); + if (!NT_SUCCESS(Status)) + { + KEBUGCHECK(0); + } - return(STATUS_SUCCESS); + KeSetPriorityThread(&ZeroPageThread->Tcb, LOW_PRIORITY); + NtClose(ThreadHandle); + return STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 76a73f009a0..8f21c8b8463 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/i386/page.c - * PURPOSE: low level memory managment manipulation - * PROGRAMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 9/3/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/i386/page.c + * PURPOSE: Low level memory managment manipulation + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ***************************************************************/ @@ -52,11 +34,14 @@ #define PA_ACCESSED (1 << PA_BIT_ACCESSED) #define PA_GLOBAL (1 << PA_BIT_GLOBAL) -#define PAGETABLE_MAP (0xf0000000) -#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024))) +#define PAGETABLE_MAP (0xf0000000) +#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024))) #define PAE_PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (512))) +#define HYPERSPACE (0xf0800000) +#define IS_HYPERSPACE(v) (((ULONG)(v) >= 0xF0800000 && (ULONG)(v) < 0xF0C00000)) + ULONG MmGlobalKernelPageDirectory[1024]; ULONGLONG MmGlobalKernelPageDirectoryForPAE[2048]; @@ -106,7 +91,7 @@ MiFlushTlbIpiRoutine(PVOID Address) VOID MiFlushTlb(PULONG Pt, PVOID Address) { -#ifdef MP +#ifdef CONFIG_SMP if (Pt) { MmUnmapPageTable(Pt); @@ -237,12 +222,12 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) PULONGLONG Pde; ULONG k; - PageDirTable = (PULONGLONG)ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDirTable = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); for (i = 0; i < 4; i++) { + PageDir = (PULONGLONG)MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[i])); if (i < PAE_ADDR_TO_PDTE_OFFSET(KERNEL_BASE)) { - PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(PageDirTable[i] >> PAGE_SHIFT); for (j = 0; j < 512; j++) { if (PageDir[j] != 0LL) @@ -251,7 +236,7 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) Process->UniqueProcessId, (i * 512 + j) * 512 * PAGE_SIZE, (i * 512 + j + 1) * 512 * PAGE_SIZE - 1, Process->AddressSpace.PageTableRefCountTable[i*512 + j]); - Pde = ExAllocatePageWithPhysPage(PageDir[j] >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDir[j])); for (k = 0; k < 512; k++) { if(Pde[k] != 0) @@ -268,21 +253,27 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) } } } - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[j])); } } - ExUnmapPage(PageDir); } - MmReleasePageMemoryConsumer(MC_NPPOOL, PageDirTable[i] >> PAGE_SHIFT); + if (i == PAE_ADDR_TO_PDTE_OFFSET(HYPERSPACE)) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)])); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1])); + } + MmDeleteHyperspaceMapping(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(PageDirTable[i])); } - ExUnmapPage((PVOID)PageDirTable); + MmDeleteHyperspaceMapping((PVOID)PageDirTable); + MmReleasePageMemoryConsumer(MC_NPPOOL, PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); } else { PULONG Pde; PULONG PageDir; - PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart)); for (i = 0; i < ADDR_TO_PDE_OFFSET(KERNEL_BASE); i++) { if (PageDir[i] != 0) @@ -290,7 +281,7 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) DPRINT1("Pde for %08x - %08x is not freed, RefCount %d\n", i * 4 * 1024 * 1024, (i + 1) * 4 * 1024 * 1024 - 1, Process->AddressSpace.PageTableRefCountTable[i]); - Pde = ExAllocatePageWithPhysPage(PageDir[i] >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(PageDir[i])); for (j = 0; j < 1024; j++) { if(Pde[j] != 0) @@ -307,14 +298,15 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) } } } - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[i])); } } - ExUnmapPage(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)])); + MmDeleteHyperspaceMapping(PageDir); + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart)); } - MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); #if defined(__GNUC__) Process->Pcb.DirectoryTableBase.QuadPart = 0LL; @@ -329,87 +321,75 @@ NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest) { - PHYSICAL_ADDRESS PhysPageDirectory; PKPROCESS KProcess = &Dest->Pcb; - + NTSTATUS Status; + ULONG i, j; + PFN_TYPE Pfn[7]; + ULONG Count; + DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest); + Count = Ke386Pae ? 7 : 2; + + for (i = 0; i < Count; i++) + { + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]); + if (!NT_SUCCESS(Status)) + { + for (j = 0; j < i; j++) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); + } + return Status; + } + } + if (Ke386Pae) { PULONGLONG PageDirTable; PULONGLONG PageDir; - PFN_TYPE Pfn[4]; - ULONG i, j; - NTSTATUS Status; - - PageDirTable = ExAllocatePage(); - if (PageDirTable == NULL) - { - return STATUS_UNSUCCESSFUL; - } - PhysPageDirectory = MmGetPhysicalAddress(PageDirTable); + PageDirTable = MmCreateHyperspaceMapping(Pfn[0]); for (i = 0; i < 4; i++) { - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn[i]); - if (!NT_SUCCESS(Status)) - { - for (j = 0; j < i; j++) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); - } - ExUnmapPage(PageDirTable); - MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT); - return Status; - } - PageDirTable[i] = (Pfn[i] << PAGE_SHIFT) | PA_PRESENT; + PageDirTable[i] = PAE_PFN_TO_PTE(Pfn[1+i]) | PA_PRESENT; } - ExUnmapPage(PageDirTable); + MmDeleteHyperspaceMapping(PageDirTable); for (i = PAE_ADDR_TO_PDTE_OFFSET(KERNEL_BASE); i < 4; i++) { - PageDir = (PULONGLONG)ExAllocatePageWithPhysPage(Pfn[i]); - if (PageDir == NULL) - { - for (j = 0; j < 4; j++) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn[j]); - } - ExUnmapPage(PageDirTable); - MmReleasePageMemoryConsumer(MC_NPPOOL, PhysPageDirectory.QuadPart >> PAGE_SHIFT); - return STATUS_UNSUCCESSFUL; - } + PageDir = (PULONGLONG)MmCreateHyperspaceMapping(Pfn[i+1]); memcpy(PageDir, &MmGlobalKernelPageDirectoryForPAE[i * 512], 512 * sizeof(ULONGLONG)); if (PAE_ADDR_TO_PDTE_OFFSET(PAGETABLE_MAP) == i) { for (j = 0; j < 4; j++) { - PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + j] = (Pfn[j] << PAGE_SHIFT) | PA_PRESENT | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + j] = PAE_PFN_TO_PTE(Pfn[1+j]) | PA_PRESENT | PA_READWRITE; } } - ExUnmapPage(PageDir); + if (PAE_ADDR_TO_PDTE_OFFSET(HYPERSPACE) == i) + { + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)] = PAE_PFN_TO_PTE(Pfn[5]) | PA_PRESENT | PA_READWRITE; + PageDir[PAE_ADDR_TO_PDE_PAGE_OFFSET(HYPERSPACE)+1] = PAE_PFN_TO_PTE(Pfn[6]) | PA_PRESENT | PA_READWRITE; + } + MmDeleteHyperspaceMapping(PageDir); } } else { PULONG PageDirectory; - PageDirectory = ExAllocatePage(); - if (PageDirectory == NULL) - { - return(STATUS_UNSUCCESSFUL); - } - PhysPageDirectory = MmGetPhysicalAddress(PageDirectory); + PageDirectory = MmCreateHyperspaceMapping(Pfn[0]); memcpy(PageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(KERNEL_BASE), (1024 - ADDR_TO_PDE_OFFSET(KERNEL_BASE)) * sizeof(ULONG)); - DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024)); - PageDirectory[PAGETABLE_MAP / (4*1024*1024)] = - PhysPageDirectory.u.LowPart | PA_PRESENT | PA_READWRITE; + DPRINT("Addr %x\n",ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)); + PageDirectory[ADDR_TO_PDE_OFFSET(PAGETABLE_MAP)] = PFN_TO_PTE(Pfn[0]) | PA_PRESENT | PA_READWRITE; + PageDirectory[ADDR_TO_PDE_OFFSET(HYPERSPACE)] = PFN_TO_PTE(Pfn[1]) | PA_PRESENT | PA_READWRITE; - ExUnmapPage(PageDirectory); + MmDeleteHyperspaceMapping(PageDirectory); } - KProcess->DirectoryTableBase = PhysPageDirectory; + KProcess->DirectoryTableBase.QuadPart = PFN_TO_PTE(Pfn[0]); DPRINT("Finished MmCopyMmInfo()\n"); return(STATUS_SUCCESS); } @@ -524,13 +504,13 @@ MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create) } if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess()) { - PageDirTable = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); if (PageDirTable == NULL) { KEBUGCHECK(0); } - PageDir = ExAllocatePageWithPhysPage(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address)] >> PAGE_SHIFT); - ExUnmapPage(PageDirTable); + PageDir = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(PageDirTable[PAE_ADDR_TO_PDTE_OFFSET(Address)])); + MmDeleteHyperspaceMapping(PageDirTable); if (PageDir == NULL) { KEBUGCHECK(0); @@ -541,7 +521,7 @@ MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create) { if (Create == FALSE) { - ExUnmapPage(PageDir); + MmDeleteHyperspaceMapping(PageDir); return NULL; } Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); @@ -561,8 +541,8 @@ MmGetPageTableForProcessForPAE(PEPROCESS Process, PVOID Address, BOOLEAN Create) { Pfn = PAE_PTE_TO_PFN(Entry); } - ExUnmapPage(PageDir); - Pt = ExAllocatePageWithPhysPage(Pfn); + MmDeleteHyperspaceMapping(PageDir); + Pt = MmCreateHyperspaceMapping(Pfn); if (Pt == NULL) { KEBUGCHECK(0); @@ -630,16 +610,16 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) if (Address < (PVOID)KERNEL_BASE && Process && Process != PsGetCurrentProcess()) { - PageDir = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.QuadPart >> PAGE_SHIFT); + PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); if (PageDir == NULL) { KEBUGCHECK(0); } - if (PageDir[PdeOffset] == 0) + if (0 == InterlockedCompareExchangeUL(&PageDir[PdeOffset], 0, 0)) { if (Create == FALSE) { - ExUnmapPage(PageDir); + MmDeleteHyperspaceMapping(PageDir); return NULL; } Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Pfn); @@ -658,8 +638,8 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) { Pfn = PTE_TO_PFN(PageDir[PdeOffset]); } - ExUnmapPage(PageDir); - Pt = ExAllocatePageWithPhysPage(Pfn); + MmDeleteHyperspaceMapping(PageDir); + Pt = MmCreateHyperspaceMapping(Pfn); if (Pt == NULL) { KEBUGCHECK(0); @@ -667,11 +647,11 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) return Pt + ADDR_TO_PTE_OFFSET(Address); } PageDir = ADDR_TO_PDE(Address); - if (*PageDir == 0) + if (0 == InterlockedCompareExchangeUL(PageDir, 0, 0)) { if (Address >= (PVOID)KERNEL_BASE) { - if (MmGlobalKernelPageDirectory[PdeOffset] == 0) + if (0 == InterlockedCompareExchangeUL(&MmGlobalKernelPageDirectory[PdeOffset], 0, 0)) { if (Create == FALSE) { @@ -692,7 +672,7 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn); } } - *PageDir =MmGlobalKernelPageDirectory[PdeOffset]; + InterlockedExchangeUL(PageDir, MmGlobalKernelPageDirectory[PdeOffset]); } else { @@ -733,7 +713,7 @@ BOOLEAN MmUnmapPageTable(PULONG Pt) } if (Pt) { - ExUnmapPage((PVOID)PAGE_ROUND_DOWN(Pt)); + MmDeleteHyperspaceMapping((PVOID)PAGE_ROUND_DOWN(Pt)); } return FALSE; } @@ -907,7 +887,7 @@ MmRawDeleteVirtualMapping(PVOID Address) /* * Set the entry to zero */ - *Pt = 0; + InterlockedExchangeUL(Pt, 0); MiFlushTlb(Pt, Address); } } @@ -1596,7 +1576,7 @@ MmCreateVirtualMappingForKernel(PVOID Address, { KEBUGCHECK(0); } - *Pt = PFN_TO_PTE(Pages[i]) | Attributes; + InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes); } } @@ -1665,7 +1645,7 @@ MmCreatePageFileMapping(PEPROCESS Process, { MmMarkPageUnmapped(PTE_TO_PFN((Pte))); } - *Pt = SwapEntry << 1; + InterlockedExchangeUL(Pt, SwapEntry << 1); if (Pte != 0) { MiFlushTlb(Pt, Address); @@ -1866,7 +1846,7 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process, { MmMarkPageUnmapped(PTE_TO_PFN((Pte))); } - *Pt = PFN_TO_PTE(Pages[i]) | Attributes; + InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages[i]) | Attributes); if (Address < (PVOID)KERNEL_BASE && Process->AddressSpace.PageTableRefCountTable != NULL && Attributes & PA_PRESENT) @@ -1907,7 +1887,7 @@ MmCreateVirtualMapping(PEPROCESS Process, { if (!MmIsUsablePage(Pages[i])) { - DPRINT1("Page at address %x not usable\n", Pages[i] << PAGE_SHIFT); + DPRINT1("Page at address %x not usable\n", PFN_TO_PTE(Pages[i])); KEBUGCHECK(0); } } @@ -2027,7 +2007,7 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) { KEBUGCHECK(0); } - *Pt = PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)); + InterlockedExchange(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY))); MiFlushTlb(Pt, Address); } } @@ -2075,6 +2055,176 @@ MmGetPhysicalAddress(PVOID vaddr) return p; } +PVOID +MmCreateHyperspaceMapping(PFN_TYPE Page) +{ + PVOID Address; + LONG i; + + if (Ke386Pae) + { + ULONGLONG Entry; + ULONGLONG ZeroEntry = 0LL; + PULONGLONG Pte; + + Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE; + Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + Page % 1024; + + if (Page & 1024) + { + for (i = Page %1024; i < 1024; i++, Pte++) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i >= 1024) + { + Pte = PAE_ADDR_TO_PTE(HYPERSPACE); + for (i = 0; i < Page % 1024; i++, Pte++) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i >= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + else + { + for (i = Page %1024; i >= 0; i--, Pte--) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i < 0) + { + Pte = PAE_ADDR_TO_PTE(HYPERSPACE) + 1023; + for (i = 1023; i > Page % 1024; i--, Pte--) + { + if (0LL == ExfInterlockedCompareExchange64UL(Pte, &Entry, &ZeroEntry)) + { + break; + } + } + if (i <= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + } + else + { + ULONG Entry; + PULONG Pte; + Entry = PFN_TO_PTE(Page) | PA_PRESENT | PA_READWRITE; + Pte = ADDR_TO_PTE(HYPERSPACE) + Page % 1024; + if (Page & 1024) + { + for (i = Page % 1024; i < 1024; i++, Pte++) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i >= 1024) + { + Pte = ADDR_TO_PTE(HYPERSPACE); + for (i = 0; i < Page % 1024; i++, Pte++) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i >= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + else + { + for (i = Page % 1024; i >= 0; i--, Pte--) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i < 0) + { + Pte = ADDR_TO_PTE(HYPERSPACE) + 1023; + for (i = 1023; i > Page % 1024; i--, Pte--) + { + if (0 == InterlockedCompareExchange((PLONG)Pte, (LONG)Entry, 0)) + { + break; + } + } + if (i <= Page % 1024) + { + KEBUGCHECK(0); + } + } + } + } + Address = (PVOID)HYPERSPACE + i * PAGE_SIZE; + FLUSH_TLB_ONE(Address); + return Address; +} + +PFN_TYPE +MmChangeHyperspaceMapping(PVOID Address, PFN_TYPE NewPage) +{ + PFN_TYPE Pfn; + ASSERT (IS_HYPERSPACE(Address)); + if (Ke386Pae) + { + ULONGLONG Entry = PAE_PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE; + Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry); + Pfn = PAE_PTE_TO_PFN(Entry); + } + else + { + ULONG Entry; + Entry = InterlockedExchange(ADDR_TO_PTE(Address), PFN_TO_PTE(NewPage) | PA_PRESENT | PA_READWRITE); + Pfn = PTE_TO_PFN(Entry); + } + FLUSH_TLB_ONE(Address); + return Pfn; +} + +PFN_TYPE +MmDeleteHyperspaceMapping(PVOID Address) +{ + PFN_TYPE Pfn; + ASSERT (IS_HYPERSPACE(Address)); + if (Ke386Pae) + { + ULONGLONG Entry = 0LL; + Entry = (ULONG)ExfpInterlockedExchange64UL(PAE_ADDR_TO_PTE(Address), &Entry); + Pfn = PAE_PTE_TO_PFN(Entry); + } + else + { + ULONG Entry; + Entry = InterlockedExchange(ADDR_TO_PTE(Address), 0); + Pfn = PTE_TO_PFN(Entry); + } + FLUSH_TLB_ONE(Address); + return Pfn; +} + VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) { ULONG StartOffset, EndOffset, Offset; @@ -2111,9 +2261,9 @@ VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) if (Process != NULL && Process != PsGetCurrentProcess()) { - PageDirTable = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.u.LowPart >> PAGE_SHIFT); - Pde = (PULONGLONG)ExAllocatePageWithPhysPage(PageDirTable[i] >> PAGE_SHIFT); - ExUnmapPage(PageDirTable); + PageDirTable = MmCreateHyperspaceMapping(PAE_PTE_TO_PFN(Process->Pcb.DirectoryTableBase.QuadPart)); + Pde = (PULONGLONG)MmCreateHyperspaceMapping(PTE_TO_PFN(PageDirTable[i])); + MmDeleteHyperspaceMapping(PageDirTable); } else { @@ -2138,7 +2288,7 @@ VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) if (Process != NULL && Process != PsGetCurrentProcess()) { - Pde = ExAllocatePageWithPhysPage(Process->Pcb.DirectoryTableBase.u.LowPart >> PAGE_SHIFT); + Pde = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase.u.LowPart)); } else { @@ -2153,27 +2303,32 @@ VOID MmUpdatePageDir(PEPROCESS Process, PVOID Address, ULONG Size) } if (Pde != (PULONG)PAGEDIRECTORY_MAP) { - ExUnmapPage(Pde); + MmDeleteHyperspaceMapping(Pde); } } } - + VOID INIT_FUNCTION MmInitGlobalKernelPageDirectory(VOID) { ULONG i; + + DPRINT("MmInitGlobalKernelPageDirectory()\n"); + if (Ke386Pae) { PULONGLONG CurrentPageDirectory = (PULONGLONG)PAE_PAGEDIRECTORY_MAP; for (i = PAE_ADDR_TO_PDE_OFFSET(KERNEL_BASE); i < 4 * 512; i++) { - if ((i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) && - 0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i]) + if (!(i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) && + !(i >= PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) && i < PAE_ADDR_TO_PDE_OFFSET(HYPERSPACE) + 2) && + 0LL == MmGlobalKernelPageDirectoryForPAE[i] && 0LL != CurrentPageDirectory[i]) { ExfpInterlockedExchange64UL(&MmGlobalKernelPageDirectoryForPAE[i], &CurrentPageDirectory[i]); if (Ke386GlobalPagesEnabled) { MmGlobalKernelPageDirectoryForPAE[i] |= PA_GLOBAL; + CurrentPageDirectory[i] |= PA_GLOBAL; } } } @@ -2184,103 +2339,20 @@ MmInitGlobalKernelPageDirectory(VOID) for (i = ADDR_TO_PDE_OFFSET(KERNEL_BASE); i < 1024; i++) { if (i != ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) && + i != ADDR_TO_PDE_OFFSET(HYPERSPACE) && 0 == MmGlobalKernelPageDirectory[i] && 0 != CurrentPageDirectory[i]) { MmGlobalKernelPageDirectory[i] = CurrentPageDirectory[i]; if (Ke386GlobalPagesEnabled) { MmGlobalKernelPageDirectory[i] |= PA_GLOBAL; + CurrentPageDirectory[i] |= PA_GLOBAL; } } } } } -extern ULONGLONG pae_pagedirtable; - -VOID INIT_FUNCTION -MiEnablePAE(PVOID* LastKernelAddress) -{ - PULONGLONG PageDirTable; - PULONGLONG PageDir; - - ULONG i, k; - - ULONG Flags; - - PageDirTable = &pae_pagedirtable; - - if (LastKernelAddress) - { - /* This is the boot processor */ - memcpy(PageDirTable, (PVOID)PAGEDIRECTORY_MAP, PAGE_SIZE); - - PageDir = (PULONGLONG)*LastKernelAddress; - (*LastKernelAddress) += 4 * PAGE_SIZE; - PageDirTable[0] = MmGetPhysicalAddress((PVOID)PageDir).QuadPart | PA_PRESENT; - PageDirTable[1] = PageDirTable[0] + PAGE_SIZE; - PageDirTable[2] = PageDirTable[1] + PAGE_SIZE; - PageDirTable[3] = PageDirTable[2] + PAGE_SIZE; - - memset(PageDir, 0, 4 * PAGE_SIZE); - - for (i = 0; i < 4; i++) - { - PageDir[3*512+PAE_ADDR_TO_PDE_PAGE_OFFSET(PAGETABLE_MAP) + i] = PageDirTable[i] | PA_READWRITE; - } - - for (i = 0; i < 2048; i++) - { - if (i < PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) || i >= PAE_ADDR_TO_PDE_OFFSET(PAGETABLE_MAP) + 4) - { - PVOID Address = (PVOID)(i * 512 * PAGE_SIZE); - PULONG Pde = ADDR_TO_PDE(Address); - PULONGLONG PtePAE=NULL; - - if (*Pde != 0) - { - if (PageDir[i] == 0LL) - { - PtePAE = (PULONGLONG)(ULONG_PTR)*LastKernelAddress; - (*LastKernelAddress) += PAGE_SIZE; - PageDir[i] = MmGetPhysicalAddress((PVOID)PtePAE).QuadPart | PA_PRESENT | PA_READWRITE; - memset(PtePAE, 0, PAGE_SIZE); - } - for (k = 0; k < 512; k++) - { - PULONG Pte = ADDR_TO_PTE(Address + k * PAGE_SIZE); - if (*Pte != 0) - { - PtePAE[k] = *Pte; - - } - } - } - } - } - } - else - { - /* this is an application processor in a mp system */ - if (!Ke386Pae) - { - return; - } - } - - Ke386SaveFlags(Flags); - Ke386DisableInterrupts(); - - Ke386SetPageTableDirectory(MmGetPhysicalAddress(PageDirTable).u.LowPart) - - Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE); - if (LastKernelAddress) - { - Ke386Pae = TRUE; - } - Ke386RestoreFlags(Flags); -} - ULONG MiGetUserPageDirectoryCount(VOID) { @@ -2291,9 +2363,12 @@ VOID INIT_FUNCTION MiInitPageDirectoryMap(VOID) { MEMORY_AREA* kernel_map_desc = NULL; + MEMORY_AREA* hyperspace_desc = NULL; PHYSICAL_ADDRESS BoundaryAddressMultiple; PVOID BaseAddress; + DPRINT("MiInitPageDirectoryMap()\n"); + BoundaryAddressMultiple.QuadPart = 0; BaseAddress = (PVOID)PAGETABLE_MAP; MmCreateMemoryArea(NULL, @@ -2306,6 +2381,17 @@ MiInitPageDirectoryMap(VOID) TRUE, FALSE, BoundaryAddressMultiple); + BaseAddress = (PVOID)HYPERSPACE; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + 0x400000, + 0, + &hyperspace_desc, + TRUE, + FALSE, + BoundaryAddressMultiple); } /* EOF */ diff --git a/reactos/ntoskrnl/mm/i386/pfault.c b/reactos/ntoskrnl/mm/i386/pfault.c index 75bcfda024c..11c37958328 100644 --- a/reactos/ntoskrnl/mm/i386/pfault.c +++ b/reactos/ntoskrnl/mm/i386/pfault.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/i386/pfault.c * PURPOSE: Paging file functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/iospace.c b/reactos/ntoskrnl/mm/iospace.c index 3cbd4333d15..0e7031e5db6 100644 --- a/reactos/ntoskrnl/mm/iospace.c +++ b/reactos/ntoskrnl/mm/iospace.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/iospace.c * PURPOSE: Mapping I/O space - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/kmap.c b/reactos/ntoskrnl/mm/kmap.c index 7a6e96ba801..614f69a2df4 100644 --- a/reactos/ntoskrnl/mm/kmap.c +++ b/reactos/ntoskrnl/mm/kmap.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/kmap.c - * PURPOSE: Implements the kernel memory pool - * PROGRAMMER: David Welch (welch@cwcom.net) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/kmap.c + * PURPOSE: Implements the kernel memory pool + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ @@ -15,61 +16,19 @@ /* GLOBALS *****************************************************************/ -#define ALLOC_MAP_SIZE (MM_KERNEL_MAP_SIZE / PAGE_SIZE) - -/* - * One bit for each page in the kmalloc region - * If set then the page is used by a kmalloc block - */ -static UCHAR AllocMapBuffer[ROUND_UP(ALLOC_MAP_SIZE, 32) / 8]; -static RTL_BITMAP AllocMap; -static KSPIN_LOCK AllocMapLock; -static ULONG AllocMapHint = 0; - /* FUNCTIONS ***************************************************************/ - -VOID -ExUnmapPage(PVOID Addr) -{ - KIRQL oldIrql; - ULONG Base = ((char*)Addr - (char*)MM_KERNEL_MAP_BASE) / PAGE_SIZE; - - DPRINT("ExUnmapPage(Addr %x)\n",Addr); - - MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL); - KeAcquireSpinLock(&AllocMapLock, &oldIrql); - RtlClearBits(&AllocMap, Base, 1); - AllocMapHint = min(AllocMapHint, Base); - KeReleaseSpinLock(&AllocMapLock, oldIrql); -} - -PVOID -ExAllocatePage(VOID) -{ - PFN_TYPE Page; - NTSTATUS Status; - - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Page); - if (!NT_SUCCESS(Status)) - { - return(NULL); - } - - return(ExAllocatePageWithPhysPage(Page)); -} - NTSTATUS MiZeroPage(PFN_TYPE Page) { PVOID TempAddress; - TempAddress = ExAllocatePageWithPhysPage(Page); + TempAddress = MmCreateHyperspaceMapping(Page); if (TempAddress == NULL) { return(STATUS_NO_MEMORY); } memset(TempAddress, 0, PAGE_SIZE); - ExUnmapPage(TempAddress); + MmDeleteHyperspaceMapping(TempAddress); return(STATUS_SUCCESS); } @@ -78,99 +37,13 @@ MiCopyFromUserPage(PFN_TYPE DestPage, PVOID SourceAddress) { PVOID TempAddress; - TempAddress = ExAllocatePageWithPhysPage(DestPage); + TempAddress = MmCreateHyperspaceMapping(DestPage); if (TempAddress == NULL) { return(STATUS_NO_MEMORY); } memcpy(TempAddress, SourceAddress, PAGE_SIZE); - ExUnmapPage(TempAddress); + MmDeleteHyperspaceMapping(TempAddress); return(STATUS_SUCCESS); } -PVOID -ExAllocatePageWithPhysPage(PFN_TYPE Page) -{ - KIRQL oldlvl; - PVOID Addr; - ULONG Base; - NTSTATUS Status; - - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - Base = RtlFindClearBitsAndSet(&AllocMap, 1, AllocMapHint); - if (Base != 0xFFFFFFFF) - { - AllocMapHint = Base + 1; - KeReleaseSpinLock(&AllocMapLock, oldlvl); - Addr = (char*)MM_KERNEL_MAP_BASE + Base * PAGE_SIZE; - Status = MmCreateVirtualMapping(NULL, - Addr, - PAGE_READWRITE | PAGE_SYSTEM, - &Page, - 1); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - KEBUGCHECK(0); - } - return Addr; - } - KeReleaseSpinLock(&AllocMapLock, oldlvl); - return NULL; -} - -VOID INIT_FUNCTION -MiInitKernelMap(VOID) -{ - KeInitializeSpinLock(&AllocMapLock); - RtlInitializeBitMap(&AllocMap, (PULONG)AllocMapBuffer, ALLOC_MAP_SIZE); - RtlClearAllBits(&AllocMap); -} - -VOID -MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free) -{ - ULONG i; - ULONG Base = ((char*)Addr - (char*)MM_KERNEL_MAP_BASE) / PAGE_SIZE; - KIRQL oldlvl; - - for (i = 0; i < Count; i++) - { - MmDeleteVirtualMapping(NULL, - (char*)Addr + (i * PAGE_SIZE), - Free, - NULL, - NULL); - } - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - RtlClearBits(&AllocMap, Base, Count); - AllocMapHint = min(AllocMapHint, Base); - KeReleaseSpinLock(&AllocMapLock, oldlvl); -} - -PVOID -MiAllocNonPagedPoolRegion(ULONG nr_pages) -/* - * FUNCTION: Allocates a region of pages within the nonpaged pool area - */ -{ - ULONG Base; - KIRQL oldlvl; - - KeAcquireSpinLock(&AllocMapLock, &oldlvl); - Base = RtlFindClearBitsAndSet(&AllocMap, nr_pages, AllocMapHint); - if (Base == 0xFFFFFFFF) - { - DbgPrint("CRITICAL: Out of non-paged pool space\n"); - KEBUGCHECK(0); - } - if (AllocMapHint == Base) - { - AllocMapHint += nr_pages; - } - KeReleaseSpinLock(&AllocMapLock, oldlvl); - //DPRINT("returning %x\n",NonPagedPoolBase + Base * PAGE_SIZE); - return (char*)MM_KERNEL_MAP_BASE + Base * PAGE_SIZE; -} - - diff --git a/reactos/ntoskrnl/mm/marea.c b/reactos/ntoskrnl/mm/marea.c index c5c85ef6bd4..6830f995a38 100644 --- a/reactos/ntoskrnl/mm/marea.c +++ b/reactos/ntoskrnl/mm/marea.c @@ -1,28 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/marea.c * PURPOSE: Implements memory areas - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -77,13 +60,13 @@ static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node) else { PMEMORY_AREA TempNode = NULL; - + do { /* Check if we're at the end of tree. */ if (Node->Parent == NULL) return NULL; - + TempNode = Node; Node = Node->Parent; } @@ -130,13 +113,13 @@ static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node) else { PMEMORY_AREA TempNode = NULL; - + do { /* Check if we're at the end of tree. */ if (Node->Parent == NULL) return NULL; - + TempNode = Node; Node = Node->Parent; } @@ -151,7 +134,7 @@ static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace) PMEMORY_AREA Node; ASSERT(AddressSpace != NULL); - + /* Special case for empty tree. */ if (AddressSpace->MemoryAreaRoot == NULL) return; @@ -169,7 +152,7 @@ static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace) } } #else -#define MmVerifyMemoryAreas(x) +#define MmVerifyMemoryAreas(x) #endif VOID STDCALL @@ -178,7 +161,7 @@ MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace) PMEMORY_AREA Node; DbgPrint("MmDumpMemoryAreas()\n"); - + /* Special case for empty tree. */ if (AddressSpace->MemoryAreaRoot == NULL) return; @@ -188,7 +171,7 @@ MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace) Node != NULL; Node = MmIterateNextNode(Node)) { - DbgPrint("Start %x End %x Attributes %x\n", + DbgPrint("Start %p End %p Attributes %x\n", Node->StartingAddress, Node->EndingAddress, Node->Attributes); } @@ -203,7 +186,7 @@ MmLocateMemoryAreaByAddress( { PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot; - DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %x, Address %x)\n", + DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n", AddressSpace, Address); if (!(KdDebugState & KD_DEBUG_SCREEN)) @@ -217,13 +200,13 @@ MmLocateMemoryAreaByAddress( Node = Node->RightChild; else { - DPRINT("MmLocateMemoryAreaByAddress(%x): %x [%x - %x]\n", + DPRINT("MmLocateMemoryAreaByAddress(%p): %p [%p - %p]\n", Address, Node, Node->StartingAddress, Node->EndingAddress); return Node; } } - DPRINT("MmLocateMemoryAreaByAddress(%x): 0\n", Address); + DPRINT("MmLocateMemoryAreaByAddress(%p): 0\n", Address); return NULL; } @@ -250,24 +233,24 @@ MmLocateMemoryAreaByRegion( if (Node->StartingAddress >= Address && Node->StartingAddress < Extent) { - DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n", - Address, Address + Length, Node->StartingAddress, + DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n", + Address, (ULONG_PTR)Address + Length, Node->StartingAddress, Node->EndingAddress); return Node; } if (Node->EndingAddress > Address && Node->EndingAddress < Extent) { - DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n", - Address, Address + Length, Node->StartingAddress, + DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n", + Address, (ULONG_PTR)Address + Length, Node->StartingAddress, Node->EndingAddress); return Node; } if (Node->StartingAddress <= Address && Node->EndingAddress >= Extent) { - DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n", - Address, Address + Length, Node->StartingAddress, + DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n", + Address, (ULONG_PTR)Address + Length, Node->StartingAddress, Node->EndingAddress); return Node; } @@ -281,17 +264,17 @@ MmLocateMemoryAreaByRegion( return NULL; } -/* +/** * @name MmCompressHelper * * This is helper of MmRebalanceTree. Performs a compression transformation - * count times, starting at root. + * count times, starting at root. */ static VOID MmCompressHelper( PMADDRESS_SPACE AddressSpace, - ULONG Count) + ULONG Count) { PMEMORY_AREA Root = NULL; PMEMORY_AREA Red = AddressSpace->MemoryAreaRoot; @@ -319,7 +302,7 @@ MmCompressHelper( } } -/* +/** * @name MmRebalanceTree * * Rebalance a memory area tree using the Tree->Vine->Balanced Tree @@ -345,13 +328,13 @@ MmRebalanceTree( CurrentNode = AddressSpace->MemoryAreaRoot; while (CurrentNode != NULL) { - if (CurrentNode->RightChild == NULL) + if (CurrentNode->RightChild == NULL) { PreviousNode = CurrentNode; CurrentNode = CurrentNode->LeftChild; NodeCount++; } - else + else { TempNode = CurrentNode->RightChild; @@ -375,7 +358,7 @@ MmRebalanceTree( /* Transform Vine back into a balanced tree. */ Leaves = NodeCount + 1; - for (;;) + for (;;) { ULONG Next = Leaves & (Leaves - 1); if (Next == 0) @@ -388,7 +371,7 @@ MmRebalanceTree( Vine = NodeCount - Leaves; Height = 1 + (Leaves > 0); - while (Vine > 1) + while (Vine > 1) { MmCompressHelper(AddressSpace, Vine / 2); Vine /= 2; @@ -417,21 +400,21 @@ MmInsertMemoryArea( Node = AddressSpace->MemoryAreaRoot; do { - DPRINT("marea->EndingAddress: %x Node->StartingAddress: %x\n", + DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n", marea->EndingAddress, Node->StartingAddress); - DPRINT("marea->StartingAddress: %x Node->EndingAddress: %x\n", + DPRINT("marea->StartingAddress: %p Node->EndingAddress: %p\n", marea->StartingAddress, Node->EndingAddress); ASSERT(marea->EndingAddress <= Node->StartingAddress || marea->StartingAddress >= Node->EndingAddress); ASSERT(marea->StartingAddress != Node->StartingAddress); - + PreviousNode = Node; - + if (marea->StartingAddress < Node->StartingAddress) Node = Node->LeftChild; else Node = Node->RightChild; - + if (Node) { Depth++; @@ -467,7 +450,7 @@ MmFindGapBottomUp( MmVerifyMemoryAreas(AddressSpace); - DPRINT("LowestAddress: %x HighestAddress: %x\n", + DPRINT("LowestAddress: %p HighestAddress: %p\n", AddressSpace->LowestAddress, HighestAddress); AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); @@ -475,9 +458,9 @@ MmFindGapBottomUp( /* Special case for empty tree. */ if (AddressSpace->MemoryAreaRoot == NULL) { - if (HighestAddress - AlignedAddress >= Length) + if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length) { - DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); return AlignedAddress; } DPRINT("MmFindGapBottomUp: 0\n"); @@ -497,9 +480,9 @@ MmFindGapBottomUp( AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); if (Node->StartingAddress > AlignedAddress && - Node->StartingAddress - AlignedAddress >= Length) + (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) { - DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); return AlignedAddress; } @@ -508,18 +491,18 @@ MmFindGapBottomUp( /* Check if there is enough space after the last memory area. */ AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); - if (HighestAddress - AlignedAddress >= Length) + if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length) { - DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); return AlignedAddress; } /* Check if there is enough space before the first memory area. */ AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); if (FirstNode->StartingAddress > AlignedAddress && - FirstNode->StartingAddress - AlignedAddress >= Length) + (ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) { - DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); return AlignedAddress; } @@ -542,10 +525,10 @@ MmFindGapTopDown( MmVerifyMemoryAreas(AddressSpace); - DPRINT("LowestAddress: %x HighestAddress: %x\n", + DPRINT("LowestAddress: %p HighestAddress: %p\n", AddressSpace->LowestAddress, HighestAddress); - AlignedAddress = MM_ROUND_DOWN(HighestAddress - Length + 1, Granularity); + AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)HighestAddress - Length + 1, Granularity); /* Check for overflow. */ if (AlignedAddress > HighestAddress) @@ -556,7 +539,7 @@ MmFindGapTopDown( { if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress) { - DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); return AlignedAddress; } DPRINT("MmFindGapTopDown: 0\n"); @@ -569,7 +552,7 @@ MmFindGapTopDown( /* Check if there is enough space after the last memory area. */ if (Node->EndingAddress <= AlignedAddress) { - DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); return AlignedAddress; } @@ -581,22 +564,22 @@ MmFindGapTopDown( if (Node == NULL) break; - AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity); + AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity); /* Check for overflow. */ if (AlignedAddress > PreviousNode->StartingAddress) return NULL; - + if (Node->EndingAddress <= AlignedAddress) { - DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); return AlignedAddress; } PreviousNode = Node; } - AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity); + AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity); /* Check for overflow. */ if (AlignedAddress > PreviousNode->StartingAddress) @@ -604,7 +587,7 @@ MmFindGapTopDown( if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress) { - DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); return AlignedAddress; } @@ -675,13 +658,15 @@ MmFindGapAtAddress( if (RightNeighbour) { - DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, RightNeighbour->StartingAddress - Address); - return RightNeighbour->StartingAddress - Address; + DPRINT("MmFindGapAtAddress: %p [%p]\n", Address, + (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address); + return (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address; } else { - DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, HighestAddress - Address); - return HighestAddress - Address; + DPRINT("MmFindGapAtAddress: %p [%p]\n", Address, + (ULONG_PTR)HighestAddress - (ULONG_PTR)Address); + return (ULONG_PTR)HighestAddress - (ULONG_PTR)Address; } } @@ -699,12 +684,12 @@ MmInitMemoryAreas(VOID) } -/* +/** * @name MmFreeMemoryArea * * Free an existing memory area. * - * @param AddressSpace + * @param AddressSpace * Address space to free the area from. * @param MemoryArea * Memory area we're about to free. @@ -726,7 +711,7 @@ MmFreeMemoryArea( PVOID FreePageContext) { PMEMORY_AREA *ParentReplace; - PVOID Address; + ULONG_PTR Address; PVOID EndAddress; PEPROCESS CurrentProcess = PsGetCurrentProcess(); @@ -736,8 +721,10 @@ MmFreeMemoryArea( KeAttachProcess(&AddressSpace->Process->Pcb); } - EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE); - for (Address = MemoryArea->StartingAddress; Address < EndAddress; Address += PAGE_SIZE) + EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE); + for (Address = (ULONG_PTR)MemoryArea->StartingAddress; + Address < (ULONG_PTR)EndAddress; + Address += PAGE_SIZE) { if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING) { @@ -771,7 +758,7 @@ MmFreeMemoryArea( KeDetachProcess(); } - /* Remove the tree item. */ + /* Remove the tree item. */ { if (MemoryArea->Parent != NULL) { @@ -832,12 +819,12 @@ MmFreeMemoryArea( return STATUS_SUCCESS; } -/* +/** * @name MmFreeMemoryAreaByPtr * * Free an existing memory area given a pointer inside it. * - * @param AddressSpace + * @param AddressSpace * Address space to free the area from. * @param BaseAddress * Address in the memory area we're about to free. @@ -866,8 +853,8 @@ MmFreeMemoryAreaByPtr( { PMEMORY_AREA MemoryArea; - DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, " - "FreePageContext %d)\n", AddressSpace, BaseAddress, + DPRINT("MmFreeMemoryArea(AddressSpace %p, BaseAddress %p, " + "FreePageContext %p)\n", AddressSpace, BaseAddress, FreePageContext); MmVerifyMemoryAreas(AddressSpace); @@ -883,12 +870,12 @@ MmFreeMemoryAreaByPtr( return MmFreeMemoryArea(AddressSpace, MemoryArea, FreePage, FreePageContext); } -/* +/** * @name MmCreateMemoryArea * * Create a memory area. * - * @param AddressSpace + * @param AddressSpace * Address space to create the area in. * @param Type * Type of the memory area. @@ -926,9 +913,9 @@ MmCreateMemoryArea(PEPROCESS Process, ULONG tmpLength; PMEMORY_AREA MemoryArea; - DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x, " - "*BaseAddress %x, Length %x, Attributes %x, TopDown: %x, " - "FixedAddress %x, Result %x)\n", + DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %p, " + "*BaseAddress %p, Length %p, Attributes %x, TopDown: %x, " + "FixedAddress %x, Result %p)\n", Type, BaseAddress, *BaseAddress, Length, Attributes, TopDown, FixedAddress, Result); @@ -988,7 +975,7 @@ MmCreateMemoryArea(PEPROCESS Process, RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA)); MemoryArea->Type = Type; MemoryArea->StartingAddress = *BaseAddress; - MemoryArea->EndingAddress = *BaseAddress + tmpLength; + MemoryArea->EndingAddress = (PVOID)((ULONG_PTR)*BaseAddress + tmpLength); MemoryArea->Attributes = Attributes; MemoryArea->LockCount = 0; MemoryArea->Process = Process; @@ -999,7 +986,7 @@ MmCreateMemoryArea(PEPROCESS Process, *Result = MemoryArea; - DPRINT("MmCreateMemoryArea() succeeded (%x)\n", *BaseAddress); + DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress); return STATUS_SUCCESS; } @@ -1013,7 +1000,7 @@ MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process, PLIST_ENTRY Entry; PMM_REGION Region; BOOLEAN Reserved; - + MmVerifyMemoryAreas(AddressSpace); MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); diff --git a/reactos/ntoskrnl/mm/mdl.c b/reactos/ntoskrnl/mm/mdl.c index 9724c8b205f..e3d7c2a44de 100644 --- a/reactos/ntoskrnl/mm/mdl.c +++ b/reactos/ntoskrnl/mm/mdl.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/mdl.c - * PURPOSE: Manipulates MDLs - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 27/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mdl.c + * PURPOSE: Manipulates MDLs + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ @@ -40,6 +39,7 @@ MDL_PARTIAL_HAS_BEEN_MAPPED mdl flagged MDL_PARTIAL has been mapped into kerne /* FUNCTIONS *****************************************************************/ + /* * @unimplemented */ @@ -54,6 +54,7 @@ MmAdvanceMdl ( return STATUS_NOT_IMPLEMENTED; } + VOID INIT_FUNCTION MmInitializeMdlImplementation(VOID) { @@ -92,14 +93,15 @@ MmInitializeMdlImplementation(VOID) KeInitializeSpinLock(&MiMdlMappingRegionLock); } + PVOID MmGetMdlPageAddress(PMDL Mdl, PVOID Offset) { - PULONG MdlPages; + PPFN_NUMBER MdlPages; - MdlPages = (PULONG)(Mdl + 1); + MdlPages = (PPFN_NUMBER)(Mdl + 1); - return((PVOID)MdlPages[((ULONG)Offset) / PAGE_SIZE]); + return((PVOID)MdlPages[((ULONG_PTR)Offset) / PAGE_SIZE]); } @@ -120,8 +122,8 @@ MmUnlockPages(PMDL Mdl) */ { ULONG i; - PULONG MdlPages; - PFN_TYPE Page; + PPFN_NUMBER MdlPages; + PFN_NUMBER Page; /* * MmProbeAndLockPages MUST have been called to lock this mdl! @@ -158,7 +160,7 @@ MmUnlockPages(PMDL Mdl) } - MdlPages = (PULONG)(Mdl + 1); + MdlPages = (PPFN_NUMBER)(Mdl + 1); for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGE_SIZE); i++) { Page = MdlPages[i]; @@ -170,153 +172,6 @@ MmUnlockPages(PMDL Mdl) } - -/* - * @implemented - */ -PVOID STDCALL -MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) -/* - * FUNCTION: Maps the physical pages described by a given MDL - * ARGUMENTS: - * Mdl = Points to an MDL updated by MmProbeAndLockPages, MmBuildMdlForNonPagedPool - * or IoBuildPartialMdl. - * AccessMode = Specifies the portion of the address space to map the - * pages. - * RETURNS: The base virtual address that maps the locked pages for the - * range described by the MDL - * - * If mapping into user space, pages are mapped into current address space. - */ -{ - PVOID Base; - PULONG MdlPages; - KIRQL oldIrql; - ULONG PageCount; - ULONG StartingOffset; - PEPROCESS CurrentProcess; - NTSTATUS Status; - - DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode); - - /* Calculate the number of pages required. */ - PageCount = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; - - if (AccessMode == UserMode) - { - MEMORY_AREA *Result; - LARGE_INTEGER BoundaryAddressMultiple; - NTSTATUS Status; - - /* pretty sure you can't map partial mdl's to user space */ - ASSERT(!(Mdl->MdlFlags & MDL_PARTIAL)); - - BoundaryAddressMultiple.QuadPart = 0; - Base = NULL; - - CurrentProcess = PsGetCurrentProcess(); - - MmLockAddressSpace(&CurrentProcess->AddressSpace); - Status = MmCreateMemoryArea(CurrentProcess, - &CurrentProcess->AddressSpace, - MEMORY_AREA_MDL_MAPPING, - &Base, - PageCount * PAGE_SIZE, - 0, /* PAGE_READWRITE? */ - &Result, - FALSE, - FALSE, - BoundaryAddressMultiple); - MmUnlockAddressSpace(&CurrentProcess->AddressSpace); - if (!NT_SUCCESS(Status)) - { - if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) - { - return NULL; - } - - KEBUGCHECK(0); - /* FIXME: handle this? */ - } - - Mdl->Process = CurrentProcess; - } - else /* if (AccessMode == KernelMode) */ - { - /* can't map mdl twice */ - ASSERT(!(Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA|MDL_PARTIAL_HAS_BEEN_MAPPED))); - /* can't map mdl buildt from non paged pool into kernel space */ - ASSERT(!(Mdl->MdlFlags & (MDL_SOURCE_IS_NONPAGED_POOL))); - - CurrentProcess = NULL; - - /* Allocate that number of pages from the mdl mapping region. */ - KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); - - StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, PageCount, MiMdlMappingRegionHint); - - if (StartingOffset == 0xffffffff) - { - KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); - - DPRINT1("Out of MDL mapping space\n"); - - if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) - { - return NULL; - } - - KEBUGCHECK(0); - } - - Base = (PVOID)((ULONG_PTR)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE); - - if (MiMdlMappingRegionHint == StartingOffset) - { - MiMdlMappingRegionHint += PageCount; - } - - KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); - } - - - - /* Set the virtual mappings for the MDL pages. */ - MdlPages = (PULONG)(Mdl + 1); - - Status = MmCreateVirtualMapping(CurrentProcess, - Base, - PAGE_READWRITE, - MdlPages, - PageCount); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Unable to create virtual mapping\n"); - if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) - { - return NULL; - } - KEBUGCHECK(0); - } - - /* Mark the MDL has having being mapped. */ - if (AccessMode == KernelMode) - { - if (Mdl->MdlFlags & MDL_PARTIAL) - { - Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED; - } - else - { - Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; - } - Mdl->MappedSystemVa = (char*)Base + Mdl->ByteOffset; - } - - return((char*)Base + Mdl->ByteOffset); -} - - /* * @unimplemented */ @@ -333,6 +188,7 @@ MmMapLockedPagesWithReservedMapping ( return 0; } + /* * @implemented */ @@ -423,6 +279,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) } + /* * @unimplemented */ @@ -447,6 +304,7 @@ MmBuildMdlFromPages(PMDL Mdl, PPFN_TYPE Pages) Mdl->MdlFlags |= MDL_IO_PAGE_READ; } + /* * @unimplemented */ @@ -461,6 +319,7 @@ MmPrefetchPages ( return STATUS_NOT_IMPLEMENTED; } + /* * @unimplemented */ @@ -477,7 +336,7 @@ MmProtectMdlSystemAddress ( /* - * @unimplemented + * @implemented */ VOID STDCALL MmProbeAndLockPages (PMDL Mdl, KPROCESSOR_MODE AccessMode, @@ -562,7 +421,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl, if (!MmIsPagePresent(NULL, Address)) { - Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE); + Status = MmNotPresentFault(Mode, (ULONG_PTR)Address, TRUE); if (!NT_SUCCESS(Status)) { for (j = 0; j < i; j++) @@ -582,7 +441,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl, if ((Operation == IoWriteAccess || Operation == IoModifyAccess) && (!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE))) { - Status = MmAccessFault(Mode, (ULONG)Address, TRUE); + Status = MmAccessFault(Mode, (ULONG_PTR)Address, TRUE); if (!NT_SUCCESS(Status)) { for (j = 0; j < i; j++) @@ -603,6 +462,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl, Mdl->MdlFlags |= MDL_PAGES_LOCKED; } + /* * @unimplemented */ @@ -618,6 +478,7 @@ MmProbeAndLockProcessPages ( UNIMPLEMENTED; } + /* * @unimplemented */ @@ -633,6 +494,7 @@ MmProbeAndLockSelectedPages( UNIMPLEMENTED; } + /* * @implemented */ @@ -678,7 +540,7 @@ MmBuildMdlForNonPagedPool (PMDL Mdl) * mdl buffer must (at least) be in kernel space, thou this doesn't * necesarely mean that the buffer in within _nonpaged_ kernel space... */ - ASSERT((ULONG)Mdl->StartVa >= KERNEL_BASE); + ASSERT((ULONG_PTR)Mdl->StartVa >= KERNEL_BASE); PageCount = PAGE_ROUND_UP(Mdl->ByteOffset + Mdl->ByteCount) / PAGE_SIZE; MdlPages = (PPFN_TYPE)(Mdl + 1); @@ -732,6 +594,7 @@ MmCreateMdl (PMDL Mdl, return(Mdl); } + /* * @unimplemented */ @@ -745,8 +608,9 @@ MmMapMemoryDumpMdl (PVOID Unknown0) UNIMPLEMENTED; } + /* - * @unimplemented + * @implemented */ PMDL STDCALL MmAllocatePagesForMdl ( IN PHYSICAL_ADDRESS LowAddress, @@ -772,19 +636,73 @@ MmAllocatePagesForMdl ( IN PHYSICAL_ADDRESS LowAddress, memory. When a driver wants to access physical memory described by a sub-MDL it must map the sub-MDL using MmGetSystemAddressForMdlSafe. - Konstantin Gusev + Konstantin Gusev + */ -*/ + PMDL Mdl; + PPFN_TYPE Pages; + ULONG NumberOfPagesWanted, NumberOfPagesAllocated; + ULONG Ret; + + DPRINT("MmAllocatePagesForMdl - LowAddress = 0x%I64x, HighAddress = 0x%I64x, " + "SkipBytes = 0x%I64x, Totalbytes = 0x%x\n", + LowAddress.QuadPart, HighAddress.QuadPart, + SkipBytes.QuadPart, Totalbytes); /* SkipBytes must be a multiple of the page size */ - ASSERT((SkipBytes.QuadPart % PAGE_SIZE) == 0); - - UNIMPLEMENTED; - return(NULL); + if ((SkipBytes.QuadPart % PAGE_SIZE) != 0) + { + DPRINT1("Warning: SkipBytes is not a multiple of PAGE_SIZE\n"); + return NULL; + } + + /* Allocate memory for the MDL */ + Mdl = MmCreateMdl(NULL, 0, Totalbytes); + if (Mdl == NULL) + { + return NULL; + } + + /* Allocate pages into the MDL */ + NumberOfPagesAllocated = 0; + NumberOfPagesWanted = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + Pages = (PPFN_TYPE)(Mdl + 1); + while (NumberOfPagesWanted > 0) + { + Ret = MmAllocPagesSpecifyRange( + MC_NPPOOL, + LowAddress, + HighAddress, + NumberOfPagesWanted, + Pages + NumberOfPagesAllocated); + if (Ret == -1) + break; + + NumberOfPagesAllocated += Ret; + NumberOfPagesWanted -= Ret; + + if (SkipBytes.QuadPart == 0) + break; + LowAddress.QuadPart += SkipBytes.QuadPart; + HighAddress.QuadPart += SkipBytes.QuadPart; + } + + if (NumberOfPagesAllocated == 0) + { + ExFreePool(Mdl); + Mdl = NULL; + } + else if (NumberOfPagesWanted > 0) + { + Mdl->ByteCount = (ULONG)(NumberOfPagesAllocated * PAGE_SIZE); + /* FIXME: I don't know if Mdl->Size should also be changed -- blight */ + } + return Mdl; } + /* - * @unimplemented + * @implemented */ VOID STDCALL MmFreePagesFromMdl ( IN PMDL Mdl ) @@ -801,12 +719,21 @@ MmFreePagesFromMdl ( IN PMDL Mdl ) Konstantin Gusev */ - - UNIMPLEMENTED; + PPFN_TYPE Pages; + LONG NumberOfPages; + + NumberOfPages = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + Pages = (PPFN_TYPE)(Mdl + 1); + + while (--NumberOfPages >= 0) + { + MmDereferencePage(Pages[NumberOfPages]); + } } + /* - * @unimplemented + * @implemented */ PVOID STDCALL MmMapLockedPagesSpecifyCache ( IN PMDL Mdl, @@ -814,12 +741,188 @@ MmMapLockedPagesSpecifyCache ( IN PMDL Mdl, IN MEMORY_CACHING_TYPE CacheType, IN PVOID BaseAddress, IN ULONG BugCheckOnFailure, - IN MM_PAGE_PRIORITY Priority ) + IN MM_PAGE_PRIORITY Priority) { - UNIMPLEMENTED; - return MmMapLockedPages (Mdl, AccessMode); + PVOID Base; + PULONG MdlPages; + KIRQL oldIrql; + ULONG PageCount; + ULONG StartingOffset; + PEPROCESS CurrentProcess; + NTSTATUS Status; + ULONG Protect; + + DPRINT("MmMapLockedPagesSpecifyCache(Mdl 0x%x, AccessMode 0x%x, CacheType 0x%x, " + "BaseAddress 0x%x, BugCheckOnFailure 0x%x, Priority 0x%x)\n", + Mdl, AccessMode, CacheType, BaseAddress, BugCheckOnFailure, Priority); + + /* FIXME: Implement Priority */ + (void) Priority; + + /* Calculate the number of pages required. */ + PageCount = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + + if (AccessMode == UserMode) + { + MEMORY_AREA *Result; + LARGE_INTEGER BoundaryAddressMultiple; + NTSTATUS Status; + + /* pretty sure you can't map partial mdl's to user space */ + ASSERT(!(Mdl->MdlFlags & MDL_PARTIAL)); + + BoundaryAddressMultiple.QuadPart = 0; + Base = BaseAddress; + + CurrentProcess = PsGetCurrentProcess(); + + MmLockAddressSpace(&CurrentProcess->AddressSpace); + Status = MmCreateMemoryArea(CurrentProcess, + &CurrentProcess->AddressSpace, + MEMORY_AREA_MDL_MAPPING, + &Base, + PageCount * PAGE_SIZE, + 0, /* PAGE_READWRITE? */ + &Result, + (Base != NULL), + FALSE, + BoundaryAddressMultiple); + MmUnlockAddressSpace(&CurrentProcess->AddressSpace); + if (!NT_SUCCESS(Status)) + { + if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) + { + return NULL; + } + + /* Throw exception */ + ExRaiseStatus(STATUS_ACCESS_VIOLATION); + ASSERT(0); + } + + Mdl->Process = CurrentProcess; + } + else /* if (AccessMode == KernelMode) */ + { + /* can't map mdl twice */ + ASSERT(!(Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA|MDL_PARTIAL_HAS_BEEN_MAPPED))); + /* can't map mdl buildt from non paged pool into kernel space */ + ASSERT(!(Mdl->MdlFlags & (MDL_SOURCE_IS_NONPAGED_POOL))); + + CurrentProcess = NULL; + + /* Allocate that number of pages from the mdl mapping region. */ + KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); + + StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, PageCount, MiMdlMappingRegionHint); + + if (StartingOffset == 0xffffffff) + { + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); + + DPRINT1("Out of MDL mapping space\n"); + + if ((Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) || !BugCheckOnFailure) + { + return NULL; + } + + KEBUGCHECK(0); + } + + Base = (PVOID)((ULONG_PTR)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE); + + if (MiMdlMappingRegionHint == StartingOffset) + { + MiMdlMappingRegionHint += PageCount; + } + + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); + } + + /* Set the virtual mappings for the MDL pages. */ + MdlPages = (PULONG)(Mdl + 1); + + Protect = PAGE_READWRITE; + if (CacheType == MmNonCached) + Protect |= PAGE_NOCACHE; + else if (CacheType == MmWriteCombined) + DPRINT("CacheType MmWriteCombined not supported!\n"); + Status = MmCreateVirtualMapping(CurrentProcess, + Base, + Protect, + MdlPages, + PageCount); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + if (Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL) + { + return NULL; + } + if (AccessMode == UserMode) + { + /* Throw exception */ + ExRaiseStatus(STATUS_ACCESS_VIOLATION); + ASSERT(0); + } + else /* AccessMode == KernelMode */ + { + if (!BugCheckOnFailure) + return NULL; + + /* FIXME: Use some bugcheck code instead of 0 */ + KEBUGCHECK(0); + } + } + + /* Mark the MDL has having being mapped. */ + if (AccessMode == KernelMode) + { + if (Mdl->MdlFlags & MDL_PARTIAL) + { + Mdl->MdlFlags |= MDL_PARTIAL_HAS_BEEN_MAPPED; + } + else + { + Mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; + } + Mdl->MappedSystemVa = (char*)Base + Mdl->ByteOffset; + } + else + DPRINT1("UserMode mapping - returning 0x%x\n", (ULONG)Base + Mdl->ByteOffset); + + return((char*)Base + Mdl->ByteOffset); } + +/* + * @implemented + */ +PVOID STDCALL +MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) +/* + * FUNCTION: Maps the physical pages described by a given MDL + * ARGUMENTS: + * Mdl = Points to an MDL updated by MmProbeAndLockPages, MmBuildMdlForNonPagedPool, + * MmAllocatePagesForMdl or IoBuildPartialMdl. + * AccessMode = Specifies the portion of the address space to map the + * pages. + * RETURNS: The base virtual address that maps the locked pages for the + * range described by the MDL + * + * If mapping into user space, pages are mapped into current address space. + */ +{ + return MmMapLockedPagesSpecifyCache(Mdl, + AccessMode, + MmCached, + NULL, + TRUE, + NormalPagePriority); +} + + /* EOF */ diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 13c2011e3b2..033c5c5fd3e 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -1,30 +1,10 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/mm.c - * PURPOSE: kernel memory managment functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 9/4/98 + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mm.c + * PURPOSE: Kernel memory managment functions + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -55,7 +35,7 @@ MmCopyToCaller(PVOID Dest, const VOID *Src, ULONG NumberOfBytes) if (ExGetPreviousMode() == UserMode) { - if ((ULONG)Dest >= KERNEL_BASE) + if ((ULONG_PTR)Dest >= KERNEL_BASE) { return(STATUS_ACCESS_VIOLATION); } @@ -76,7 +56,7 @@ MmCopyFromCaller(PVOID Dest, const VOID *Src, ULONG NumberOfBytes) if (ExGetPreviousMode() == UserMode) { - if ((ULONG)Src >= KERNEL_BASE) + if ((ULONG_PTR)Src >= KERNEL_BASE) { return(STATUS_ACCESS_VIOLATION); } @@ -177,7 +157,7 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress) MEMORY_AREA* MemoryArea; PMADDRESS_SPACE AddressSpace; - if ((ULONG)VirtualAddress >= KERNEL_BASE) + if ((ULONG_PTR)VirtualAddress >= KERNEL_BASE) { AddressSpace = MmGetKernelAddressSpace(); } @@ -200,7 +180,7 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress) } NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode, - ULONG Address, /* FiN TODO: Should be ULONG_PTR! */ + ULONG_PTR Address, BOOLEAN FromMdl) { PMADDRESS_SPACE AddressSpace; @@ -322,7 +302,7 @@ NTSTATUS MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked) } NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode, - ULONG Address, /* FiN TODO: Should be ULONG_PTR! */ + ULONG_PTR Address, BOOLEAN FromMdl) { PMADDRESS_SPACE AddressSpace; diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 6daca270538..7c7973921b0 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/mminit.c - * PURPOSE: kernel memory managment initialization functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 9/4/98 + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mminit.c + * PURPOSE: Kernel memory managment initialization functions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -49,6 +48,8 @@ PVOID MiNonPagedPoolStart; ULONG MiNonPagedPoolLength; //PVOID MiKernelMapStart; +extern ULONG init_stack; +extern ULONG init_stack_top; /* FUNCTIONS ****************************************************************/ @@ -72,7 +73,7 @@ VOID MiShutdownMemoryManager(VOID) {} VOID INIT_FUNCTION -MmInitVirtualMemory(ULONG LastKernelAddress, +MmInitVirtualMemory(ULONG_PTR LastKernelAddress, ULONG KernelLength) /* * FUNCTION: Intialize the memory areas list @@ -133,7 +134,7 @@ MmInitVirtualMemory(ULONG LastKernelAddress, BoundaryAddressMultiple); BaseAddress = (PVOID)KERNEL_BASE; - Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE; + Length = PAGE_ROUND_UP(((ULONG_PTR)&_text_end__)) - KERNEL_BASE; ParamLength = ParamLength - Length; /* @@ -151,10 +152,10 @@ MmInitVirtualMemory(ULONG LastKernelAddress, FALSE, BoundaryAddressMultiple); - BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__)); + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_text_end__)); ASSERT(BaseAddress == (PVOID)&_init_start__); - Length = PAGE_ROUND_UP(((ULONG)&_init_end__)) - - PAGE_ROUND_UP(((ULONG)&_text_end__)); + Length = PAGE_ROUND_UP(((ULONG_PTR)&_init_end__)) - + PAGE_ROUND_UP(((ULONG_PTR)&_text_end__)); ParamLength = ParamLength - Length; MmCreateMemoryArea(NULL, @@ -168,11 +169,11 @@ MmInitVirtualMemory(ULONG LastKernelAddress, FALSE, BoundaryAddressMultiple); - Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) - - PAGE_ROUND_UP(((ULONG)&_init_end__)); + Length = PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__)) - + PAGE_ROUND_UP(((ULONG_PTR)&_init_end__)); ParamLength = ParamLength - Length; DPRINT("Length %x\n",Length); - BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_init_end__)); + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_init_end__)); DPRINT("BaseAddress %x\n",BaseAddress); /* @@ -190,8 +191,8 @@ MmInitVirtualMemory(ULONG LastKernelAddress, FALSE, BoundaryAddressMultiple); - BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__)); - Length = LastKernelAddress - (ULONG)BaseAddress; + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG_PTR)&_bss_end__)); + Length = LastKernelAddress - (ULONG_PTR)BaseAddress; MmCreateMemoryArea(NULL, MmGetKernelAddressSpace(), MEMORY_AREA_SYSTEM, @@ -277,9 +278,9 @@ MmInitVirtualMemory(ULONG LastKernelAddress, } VOID INIT_FUNCTION -MmInit1(ULONG FirstKrnlPhysAddr, - ULONG LastKrnlPhysAddr, - ULONG LastKernelAddress, +MmInit1(ULONG_PTR FirstKrnlPhysAddr, + ULONG_PTR LastKrnlPhysAddr, + ULONG_PTR LastKernelAddress, PADDRESS_RANGE BIOSMemoryMap, ULONG AddressRangeCount, ULONG MaxMem) @@ -289,17 +290,13 @@ MmInit1(ULONG FirstKrnlPhysAddr, { ULONG i; ULONG kernel_len; -#ifndef MP + ULONG_PTR MappingAddress; - extern unsigned int unmap_me, unmap_me2, unmap_me3; -#endif - - DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n", + DPRINT("MmInit1(FirstKrnlPhysAddr, %p, LastKrnlPhysAddr %p, LastKernelAddress %p)\n", FirstKrnlPhysAddr, LastKrnlPhysAddr, LastKernelAddress); - if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0)) { // If we have a bios memory map, recalulate the memory size @@ -323,10 +320,7 @@ MmInit1(ULONG FirstKrnlPhysAddr, KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024; } - /* - * FIXME: Set this based on the system command line - */ - MmSystemRangeStart = (PVOID)KERNEL_BASE; // 0xC0000000 + /* Set memory limits */ MmUserProbeAddress = 0x7fff0000; MmHighestUserAddress = (PVOID)0x7ffeffff; @@ -377,14 +371,12 @@ MmInit1(ULONG FirstKrnlPhysAddr, MmInitGlobalKernelPageDirectory(); - MiInitKernelMap(); - - - DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024); + DPRINT1("Kernel Stack Limits. InitTop = 0x%x, Init = 0x%x\n", init_stack_top, init_stack); - LastKernelAddress = (ULONG)MmInitializePageList((PVOID)FirstKrnlPhysAddr, - (PVOID)LastKrnlPhysAddr, + LastKernelAddress = (ULONG_PTR)MmInitializePageList( + FirstKrnlPhysAddr, + LastKrnlPhysAddr, MmStats.NrTotalPages, PAGE_ROUND_UP(LastKernelAddress), BIOSMemoryMap, @@ -394,35 +386,23 @@ MmInit1(ULONG FirstKrnlPhysAddr, /* * Unmap low memory */ -#ifndef MP +#ifndef CONFIG_SMP /* In SMP mode we unmap the low memory in MmInit3. The APIC needs the mapping of the first pages while the processors are starting up. */ MmDeletePageTable(NULL, 0); #endif - - DPRINT("Invalidating between %x and %x\n", LastKernelAddress, KERNEL_BASE + 0x00600000); - for (i=(LastKernelAddress); iSize >= new_size && (best == NULL || current->Size < best->Size)) @@ -1382,9 +1378,9 @@ static BLOCK_HDR* get_block(unsigned int size, unsigned long alignment) * if size-aligned, break off the preceding bytes into their own block... */ previous = current; - previous_size = (ULONG)blk - (ULONG)previous - BLOCK_HDR_SIZE; + previous_size = (ULONG_PTR)blk - (ULONG_PTR)previous - BLOCK_HDR_SIZE; current = blk; - current_size -= ((ULONG)current - (ULONG)previous); + current_size -= ((ULONG_PTR)current - (ULONG_PTR)previous); } } @@ -1393,7 +1389,7 @@ static BLOCK_HDR* get_block(unsigned int size, unsigned long alignment) if (current_size >= size + BLOCK_HDR_SIZE + MM_POOL_ALIGNMENT) { /* create a new free block after our block, if the memory size is >= 4 byte for this block */ - next = (BLOCK_HDR*)((ULONG)current + size + BLOCK_HDR_SIZE); + next = (BLOCK_HDR*)((ULONG_PTR)current + size + BLOCK_HDR_SIZE); next_size = current_size - size - BLOCK_HDR_SIZE; current_size = size; end = (char*)next + BLOCK_HDR_SIZE; @@ -1828,9 +1824,9 @@ MiInitializeNonPagedPool(VOID) /* the second block is the first free block */ blk = (BLOCK_HDR*)((char*)blk + BLOCK_HDR_SIZE + blk->Size); memset(blk, 0, BLOCK_HDR_SIZE); - memset((char*)blk + BLOCK_HDR_SIZE, 0x0cc, MiNonPagedPoolNrOfPages * PAGE_SIZE - ((ULONG)blk + BLOCK_HDR_SIZE - (ULONG)MiNonPagedPoolStart)); + memset((char*)blk + BLOCK_HDR_SIZE, 0x0cc, MiNonPagedPoolNrOfPages * PAGE_SIZE - ((ULONG_PTR)blk + BLOCK_HDR_SIZE - (ULONG_PTR)MiNonPagedPoolStart)); blk->Magic = BLOCK_HDR_FREE_MAGIC; - blk->Size = MiNonPagedPoolLength - ((ULONG)blk + BLOCK_HDR_SIZE - (ULONG)MiNonPagedPoolStart); + blk->Size = MiNonPagedPoolLength - ((ULONG_PTR)blk + BLOCK_HDR_SIZE - (ULONG_PTR)MiNonPagedPoolStart); blk->previous = (BLOCK_HDR*)MiNonPagedPoolStart; add_to_free_list(blk); #endif diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index acdc9230549..c700d2c5251 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -45,14 +45,14 @@ typedef struct _PAGINGFILE PULONG AllocMap; KSPIN_LOCK AllocMapLock; ULONG AllocMapSize; - PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; } PAGINGFILE, *PPAGINGFILE; typedef struct _RETRIEVEL_DESCRIPTOR_LIST { struct _RETRIEVEL_DESCRIPTOR_LIST* Next; - GET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + RETRIEVAL_POINTERS_BUFFER RetrievalPointers; } RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST; @@ -128,27 +128,27 @@ MmShowOutOfSpaceMessagePagingFile(VOID) } LARGE_INTEGER STATIC -MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers, LARGE_INTEGER Offset) +MmGetOffsetPageFile(PRETRIEVAL_POINTERS_BUFFER RetrievalPointers, LARGE_INTEGER Offset) { /* Simple binary search */ ULONG first, last, mid; first = 0; - last = RetrievalPointers->NumberOfPairs - 1; + last = RetrievalPointers->ExtentCount - 1; while (first <= last) { mid = (last - first) / 2 + first; - if ((ULONGLONG) Offset.QuadPart < RetrievalPointers->Pair[mid].Vcn) + if (Offset.QuadPart < RetrievalPointers->Extents[mid].NextVcn.QuadPart) { if (mid == 0) { - Offset.QuadPart += RetrievalPointers->Pair[0].Lcn - RetrievalPointers->StartVcn; + Offset.QuadPart += RetrievalPointers->Extents[0].Lcn.QuadPart - RetrievalPointers->StartingVcn.QuadPart; return Offset; } else { - if ((ULONGLONG) Offset.QuadPart >= RetrievalPointers->Pair[mid-1].Vcn) + if (Offset.QuadPart >= RetrievalPointers->Extents[mid-1].NextVcn.QuadPart) { - Offset.QuadPart += RetrievalPointers->Pair[mid].Lcn - RetrievalPointers->Pair[mid-1].Vcn; + Offset.QuadPart += RetrievalPointers->Extents[mid].Lcn.QuadPart - RetrievalPointers->Extents[mid-1].NextVcn.QuadPart; return Offset; } last = mid - 1; @@ -156,13 +156,13 @@ MmGetOffsetPageFile(PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers, LARGE_INTEGER O } else { - if (mid == RetrievalPointers->NumberOfPairs - 1) + if (mid == RetrievalPointers->ExtentCount - 1) { break; } - if ((ULONGLONG) Offset.QuadPart < RetrievalPointers->Pair[mid+1].Vcn) + if (Offset.QuadPart < RetrievalPointers->Extents[mid+1].NextVcn.QuadPart) { - Offset.QuadPart += RetrievalPointers->Pair[mid+1].Lcn - RetrievalPointers->Pair[mid].Vcn; + Offset.QuadPart += RetrievalPointers->Extents[mid+1].Lcn.QuadPart - RetrievalPointers->Extents[mid].NextVcn.QuadPart; return Offset; } first = mid + 1; @@ -471,7 +471,7 @@ MmAllocRetrievelDescriptorList(ULONG Pairs) ULONG Size; PRETRIEVEL_DESCRIPTOR_LIST RetDescList; - Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * sizeof(MAPPING_PAIR); + Size = sizeof(RETRIEVEL_DESCRIPTOR_LIST) + Pairs * 2 * sizeof(LARGE_INTEGER); RetDescList = ExAllocatePool(NonPagedPool, Size); if (RetDescList) { @@ -498,7 +498,7 @@ MmDumpToPagingFile(ULONG BugCode, PULONG MdlMap; LONGLONG NextOffset = 0; ULONG i; - PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers; + PRETRIEVAL_POINTERS_BUFFER RetrievalPointers; LARGE_INTEGER DiskOffset; if (MmCoreDumpPageFile == 0xFFFFFFFF) @@ -532,7 +532,7 @@ MmDumpToPagingFile(ULONG BugCode, Headers->BugCheckParameters[3] = BugCodeParameter4; Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit; Headers->FaultingStackSize = - StackSize = (ULONG_PTR)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit); + StackSize = (ULONG_PTR)Thread->Tcb.StackBase - (ULONG_PTR)Thread->Tcb.StackLimit; Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE; /* Initialize the dump device. */ @@ -759,9 +759,12 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ULONG BytesPerAllocationUnit; LARGE_INTEGER Vcn; ULONG ExtentCount; - ULONG MaxVcn; + LARGE_INTEGER MaxVcn; ULONG Count; ULONG Size; + KPROCESSOR_MODE PreviousMode; + UNICODE_STRING CapturedFileName; + LARGE_INTEGER SafeInitialSize, SafeMaximumSize; DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n", FileName, InitialSize->QuadPart); @@ -771,8 +774,48 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, return(STATUS_TOO_MANY_PAGING_FILES); } + PreviousMode = ExGetPreviousMode(); + Status = RtlCaptureUnicodeString(&CapturedFileName, + PreviousMode, + PagedPool, + FALSE, + FileName); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForRead(InitialSize, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + SafeInitialSize = *InitialSize; + ProbeForRead(MaximumSize, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + SafeMaximumSize = *MaximumSize; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + SafeInitialSize = *InitialSize; + SafeMaximumSize = *MaximumSize; + } + InitializeObjectAttributes(&ObjectAttributes, - FileName, + &CapturedFileName, 0, NULL, NULL); @@ -790,50 +833,53 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, 0, CreateFileTypeNone, NULL, - SL_OPEN_PAGING_FILE); + SL_OPEN_PAGING_FILE | IO_NO_PARAMETER_CHECKING); + RtlReleaseCapturedUnicodeString(&CapturedFileName, + PreviousMode, + FALSE); if (!NT_SUCCESS(Status)) { return(Status); } - Status = NtQueryVolumeInformationFile(FileHandle, + Status = ZwQueryVolumeInformationFile(FileHandle, &IoStatus, &FsSizeInformation, sizeof(FILE_FS_SIZE_INFORMATION), FileFsSizeInformation); if (!NT_SUCCESS(Status)) { - NtClose(FileHandle); + ZwClose(FileHandle); return Status; } BytesPerAllocationUnit = FsSizeInformation.SectorsPerAllocationUnit * FsSizeInformation.BytesPerSector; if (BytesPerAllocationUnit % PAGE_SIZE) { - NtClose(FileHandle); + ZwClose(FileHandle); return STATUS_UNSUCCESSFUL; } - Status = NtSetInformationFile(FileHandle, + Status = ZwSetInformationFile(FileHandle, &IoStatus, - InitialSize, + &SafeInitialSize, sizeof(LARGE_INTEGER), FileAllocationInformation); if (!NT_SUCCESS(Status)) { - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } Status = ObReferenceObjectByHandle(FileHandle, FILE_ALL_ACCESS, IoFileObjectType, - UserMode, + PreviousMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } @@ -842,7 +888,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, if (CurrentRetDescList == NULL) { ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_NO_MEMORY); } @@ -854,10 +900,10 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, #endif ExtentCount = 0; - MaxVcn = (ULONG)((InitialSize->QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit); + MaxVcn.QuadPart = (SafeInitialSize.QuadPart + BytesPerAllocationUnit - 1) / BytesPerAllocationUnit; while(1) { - Status = NtFsControlFile(FileHandle, + Status = ZwFsControlFile(FileHandle, 0, NULL, NULL, @@ -866,7 +912,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, &Vcn, sizeof(LARGE_INTEGER), &CurrentRetDescList->RetrievalPointers, - sizeof(GET_RETRIEVAL_DESCRIPTOR) + PAIRS_PER_RUN * sizeof(MAPPING_PAIR)); + sizeof(RETRIEVAL_POINTERS_BUFFER) + PAIRS_PER_RUN * 2 * sizeof(LARGE_INTEGER)); if (!NT_SUCCESS(Status)) { while (RetDescList) @@ -876,11 +922,11 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ExFreePool(CurrentRetDescList); } ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(Status); } - ExtentCount += CurrentRetDescList->RetrievalPointers.NumberOfPairs; - if ((ULONG)CurrentRetDescList->RetrievalPointers.Pair[CurrentRetDescList->RetrievalPointers.NumberOfPairs-1].Vcn < MaxVcn) + ExtentCount += CurrentRetDescList->RetrievalPointers.ExtentCount; + if (CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn.QuadPart < MaxVcn.QuadPart) { CurrentRetDescList->Next = MmAllocRetrievelDescriptorList(PAIRS_PER_RUN); if (CurrentRetDescList->Next == NULL) @@ -892,10 +938,10 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ExFreePool(CurrentRetDescList); } ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_NO_MEMORY); } - Vcn.QuadPart = CurrentRetDescList->RetrievalPointers.Pair[CurrentRetDescList->RetrievalPointers.NumberOfPairs-1].Vcn; + Vcn = CurrentRetDescList->RetrievalPointers.Extents[CurrentRetDescList->RetrievalPointers.ExtentCount-1].NextVcn; CurrentRetDescList = CurrentRetDescList->Next; } else @@ -914,16 +960,16 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ExFreePool(CurrentRetDescList); } ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_NO_MEMORY); } RtlZeroMemory(PagingFile, sizeof(*PagingFile)); PagingFile->FileObject = FileObject; - PagingFile->MaximumSize.QuadPart = MaximumSize->QuadPart; - PagingFile->CurrentSize.QuadPart = InitialSize->QuadPart; - PagingFile->FreePages = (ULONG)(InitialSize->QuadPart / PAGE_SIZE); + PagingFile->MaximumSize.QuadPart = SafeMaximumSize.QuadPart; + PagingFile->CurrentSize.QuadPart = SafeInitialSize.QuadPart; + PagingFile->FreePages = (ULONG)(SafeInitialSize.QuadPart / PAGE_SIZE); PagingFile->UsedPages = 0; KeInitializeSpinLock(&PagingFile->AllocMapLock); @@ -946,7 +992,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, return(STATUS_NO_MEMORY); } DPRINT("ExtentCount: %d\n", ExtentCount); - Size = sizeof(GET_RETRIEVAL_DESCRIPTOR) + ExtentCount * sizeof(MAPPING_PAIR); + Size = sizeof(RETRIEVAL_POINTERS_BUFFER) + ExtentCount * 2 * sizeof(LARGE_INTEGER); PagingFile->RetrievalPointers = ExAllocatePool(NonPagedPool, Size); if (PagingFile->RetrievalPointers == NULL) { @@ -959,7 +1005,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, ExFreePool(PagingFile->AllocMap); ExFreePool(PagingFile); ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_NO_MEMORY); } @@ -967,39 +1013,39 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, RtlZeroMemory(PagingFile->RetrievalPointers, Size); Count = 0; - PagingFile->RetrievalPointers->NumberOfPairs = ExtentCount; - PagingFile->RetrievalPointers->StartVcn = RetDescList->RetrievalPointers.StartVcn; + PagingFile->RetrievalPointers->ExtentCount = ExtentCount; + PagingFile->RetrievalPointers->StartingVcn = RetDescList->RetrievalPointers.StartingVcn; CurrentRetDescList = RetDescList; while (CurrentRetDescList) { - memcpy(&PagingFile->RetrievalPointers->Pair[Count], - CurrentRetDescList->RetrievalPointers.Pair, - CurrentRetDescList->RetrievalPointers.NumberOfPairs * sizeof(MAPPING_PAIR)); - Count += CurrentRetDescList->RetrievalPointers.NumberOfPairs; + memcpy(&PagingFile->RetrievalPointers->Extents[Count], + CurrentRetDescList->RetrievalPointers.Extents, + CurrentRetDescList->RetrievalPointers.ExtentCount * 2 * sizeof(LARGE_INTEGER)); + Count += CurrentRetDescList->RetrievalPointers.ExtentCount; RetDescList = CurrentRetDescList; CurrentRetDescList = CurrentRetDescList->Next; ExFreePool(RetDescList); } - if (PagingFile->RetrievalPointers->NumberOfPairs != ExtentCount || - (ULONG)PagingFile->RetrievalPointers->Pair[ExtentCount - 1].Vcn != MaxVcn) + if (PagingFile->RetrievalPointers->ExtentCount != ExtentCount || + PagingFile->RetrievalPointers->Extents[ExtentCount - 1].NextVcn.QuadPart != MaxVcn.QuadPart) { ExFreePool(PagingFile->RetrievalPointers); ExFreePool(PagingFile->AllocMap); ExFreePool(PagingFile); ObDereferenceObject(FileObject); - NtClose(FileHandle); + ZwClose(FileHandle); return(STATUS_UNSUCCESSFUL); } /* * Change the entries from lcn's to volume offset's. */ - PagingFile->RetrievalPointers->StartVcn *= BytesPerAllocationUnit; + PagingFile->RetrievalPointers->StartingVcn.QuadPart *= BytesPerAllocationUnit; for (i = 0; i < ExtentCount; i++) { - PagingFile->RetrievalPointers->Pair[i].Lcn *= BytesPerAllocationUnit; - PagingFile->RetrievalPointers->Pair[i].Vcn *= BytesPerAllocationUnit; + PagingFile->RetrievalPointers->Extents[i].Lcn.QuadPart *= BytesPerAllocationUnit; + PagingFile->RetrievalPointers->Extents[i].NextVcn.QuadPart *= BytesPerAllocationUnit; } KeAcquireSpinLock(&PagingFileListLock, &oldIrql); @@ -1022,7 +1068,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName, { MmInitializeCrashDump(FileHandle, i); } - NtClose(FileHandle); + ZwClose(FileHandle); MmSwapSpaceMessage = FALSE; diff --git a/reactos/ntoskrnl/mm/pageop.c b/reactos/ntoskrnl/mm/pageop.c index 24694d9f584..e68414dea15 100644 --- a/reactos/ntoskrnl/mm/pageop.c +++ b/reactos/ntoskrnl/mm/pageop.c @@ -1,11 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/pageop.c - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 27/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pageop.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ @@ -67,10 +67,10 @@ MmReleasePageOp(PMM_PAGEOP PageOp) } PMM_PAGEOP -MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, +MmCheckForPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address, PMM_SECTION_SEGMENT Segment, ULONG Offset) { - ULONG Hash; + ULONG_PTR Hash; KIRQL oldIrql; PMM_PAGEOP PageOp; @@ -79,11 +79,11 @@ MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, */ if (MArea->Type == MEMORY_AREA_SECTION_VIEW) { - Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE)); } else { - Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE)); } Hash = Hash % PAGEOP_HASH_TABLE_SIZE; @@ -129,7 +129,7 @@ MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, } PMM_PAGEOP -MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, +MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address, PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First) /* * FUNCTION: Get a page operation descriptor corresponding to @@ -137,7 +137,7 @@ MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, * pid, address pair. */ { - ULONG Hash; + ULONG_PTR Hash; KIRQL oldIrql; PMM_PAGEOP PageOp; @@ -146,11 +146,11 @@ MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, */ if (MArea->Type == MEMORY_AREA_SECTION_VIEW) { - Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE)); } else { - Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE)); } Hash = Hash % PAGEOP_HASH_TABLE_SIZE; diff --git a/reactos/ntoskrnl/mm/pager.c b/reactos/ntoskrnl/mm/pager.c index 50f62c6357d..656da6aba35 100644 --- a/reactos/ntoskrnl/mm/pager.c +++ b/reactos/ntoskrnl/mm/pager.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/pager.c - * PURPOSE: Moves infrequently used data out of memory - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 27/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pager.c + * PURPOSE: Moves infrequently used data out of memory + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/mm/pagfault.c b/reactos/ntoskrnl/mm/pagfault.c index 7ac0e17dfbe..a274cd210a2 100644 --- a/reactos/ntoskrnl/mm/pagfault.c +++ b/reactos/ntoskrnl/mm/pagfault.c @@ -1,4 +1,13 @@ -/* $Id$ */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pagfault.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #include diff --git a/reactos/ntoskrnl/mm/paging.c b/reactos/ntoskrnl/mm/paging.c index 9f4411121a2..6e29cf4467c 100644 --- a/reactos/ntoskrnl/mm/paging.c +++ b/reactos/ntoskrnl/mm/paging.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/paging.c * PURPOSE: Paging file functions - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/pe.c b/reactos/ntoskrnl/mm/pe.c index 316819b217d..fc8e2b97ffd 100644 --- a/reactos/ntoskrnl/mm/pe.c +++ b/reactos/ntoskrnl/mm/pe.c @@ -1,34 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/pe.c * PURPOSE: Loader for PE executables - * PROGRAMMER: KJK::Hyperion - * UPDATE HISTORY: - * 2004-12-06 Created - * 2004-12-09 Compiles - * 2004-12-26 Actually works, several checks relaxed to support - * the majority of existing executables, corrected - * the alignment helper functions, debug messages to - * explain failure. + * + * PROGRAMMERS: KJK::Hyperion */ /* INCLUDES *****************************************************************/ @@ -343,7 +320,7 @@ l_ReadHeaderFromFile: } else { - SIZE_T cbOptHeaderOffsetSize; + ULONG cbOptHeaderOffsetSize; nStatus = STATUS_INVALID_IMAGE_FORMAT; @@ -672,8 +649,11 @@ l_ReadHeaderFromFile: if(pishSectionHeaders[i].SizeOfRawData != 0) { /* validate the alignment */ +#if 0 /* Yes, this should be a multiple of FileAlignment, but there's + stuff out there that isn't. We can cope with that */ if(!IsAligned(pishSectionHeaders[i].SizeOfRawData, nFileAlignment)) DIE(("SizeOfRawData[%u] is not aligned\n", i)); +#endif if(!IsAligned(pishSectionHeaders[i].PointerToRawData, nFileAlignment)) DIE(("PointerToRawData[%u] is not aligned\n", i)); diff --git a/reactos/ntoskrnl/mm/physical.c b/reactos/ntoskrnl/mm/physical.c index 99176a5f1b2..c9bbc649f92 100644 --- a/reactos/ntoskrnl/mm/physical.c +++ b/reactos/ntoskrnl/mm/physical.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/physical.c * PURPOSE: Physical Memory Manipulation functions - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 16/07/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/pool.c b/reactos/ntoskrnl/mm/pool.c index 7164e6a5d18..9370213c88e 100644 --- a/reactos/ntoskrnl/mm/pool.c +++ b/reactos/ntoskrnl/mm/pool.c @@ -1,16 +1,16 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/pool.c - * PURPOSE: Implements the kernel memory pool - * PROGRAMMER: David Welch (welch@mcmail.com) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pool.c + * PURPOSE: Implements the kernel memory pool + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ #include -#include #define NDEBUG #include diff --git a/reactos/ntoskrnl/mm/ppool.c b/reactos/ntoskrnl/mm/ppool.c index 7bcb786ac38..0a141302056 100644 --- a/reactos/ntoskrnl/mm/ppool.c +++ b/reactos/ntoskrnl/mm/ppool.c @@ -4,10 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/ppool.c * PURPOSE: Implements the paged pool - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * Complete Rewrite Dec 2004 by Royce Mitchell III + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Royce Mitchell III */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/region.c b/reactos/ntoskrnl/mm/region.c index c6e745c84b4..e5efd3fe827 100644 --- a/reactos/ntoskrnl/mm/region.c +++ b/reactos/ntoskrnl/mm/region.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/region.c - * PROGRAMMER: David Welch - * PURPOSE: + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/region.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch */ /* INCLUDE *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/rmap.c b/reactos/ntoskrnl/mm/rmap.c index 4302fb376b4..da916f1f1af 100644 --- a/reactos/ntoskrnl/mm/rmap.c +++ b/reactos/ntoskrnl/mm/rmap.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/rmap.c - * PURPOSE: kernel memory managment functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 27/12/01 + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/rmap.c + * PURPOSE: Kernel memory managment functions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -136,7 +117,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page) /* * Get or create a pageop */ - PageOp = MmGetPageOp(MemoryArea, 0, 0, + PageOp = MmGetPageOp(MemoryArea, NULL, 0, MemoryArea->Data.SectionData.Segment, Offset, MM_PAGEOP_PAGEOUT, TRUE); @@ -163,7 +144,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page) } else if (Type == MEMORY_AREA_VIRTUAL_MEMORY) { - PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0, + PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : NULL, Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE); if (PageOp == NULL) @@ -260,7 +241,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page) /* * Get or create a pageop */ - PageOp = MmGetPageOp(MemoryArea, 0, 0, + PageOp = MmGetPageOp(MemoryArea, NULL, 0, MemoryArea->Data.SectionData.Segment, Offset, MM_PAGEOP_PAGEOUT, TRUE); if (PageOp == NULL) @@ -286,7 +267,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page) } else if (Type == MEMORY_AREA_VIRTUAL_MEMORY) { - PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0, + PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : NULL, Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE); if (PageOp == NULL) { diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index 9040d979dc3..ada2a84042c 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/section.c * PURPOSE: Implements section objects - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -547,7 +529,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, return Status; } } - PageAddr = ExAllocatePageWithPhysPage(*Page); + PageAddr = MmCreateHyperspaceMapping(*Page); CacheSegOffset = BaseOffset + CacheSeg->Bcb->CacheSegmentSize - FileOffset; Length = RawLength - SegOffset; if (Length <= CacheSegOffset && Length <= PAGE_SIZE) @@ -570,7 +552,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, &CacheSeg); if (!NT_SUCCESS(Status)) { - ExUnmapPage(PageAddr); + MmDeleteHyperspaceMapping(PageAddr); return(Status); } if (!UptoDate) @@ -583,7 +565,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, if (!NT_SUCCESS(Status)) { CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); - ExUnmapPage(PageAddr); + MmDeleteHyperspaceMapping(PageAddr); return Status; } } @@ -597,7 +579,7 @@ MiReadPage(PMEMORY_AREA MemoryArea, } } CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE); - ExUnmapPage(PageAddr); + MmDeleteHyperspaceMapping(PageAddr); } return(STATUS_SUCCESS); } @@ -665,7 +647,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Get or create a page operation descriptor */ - PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE); + PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE); if (PageOp == NULL) { DPRINT1("MmGetPageOp failed\n"); @@ -1127,7 +1109,6 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, PSECTION_OBJECT Section; PFN_TYPE OldPage; PFN_TYPE NewPage; - PVOID NewAddress; NTSTATUS Status; PVOID PAddress; ULONG Offset; @@ -1188,7 +1169,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Get or create a pageop */ - PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset, + PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_ACCESSFAULT, FALSE); if (PageOp == NULL) { @@ -1242,10 +1223,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Copy the old page */ - - NewAddress = ExAllocatePageWithPhysPage(NewPage); - memcpy(NewAddress, PAddress, PAGE_SIZE); - ExUnmapPage(NewAddress); + MiCopyFromUserPage(NewPage, PAddress); /* * Delete the old entry. @@ -2148,8 +2126,8 @@ MmInitSectionImplementation(VOID) MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T'); MmSectionObjectType->TotalObjects = 0; MmSectionObjectType->TotalHandles = 0; - MmSectionObjectType->MaxObjects = ULONG_MAX; - MmSectionObjectType->MaxHandles = ULONG_MAX; + MmSectionObjectType->PeakObjects = 0; + MmSectionObjectType->PeakHandles = 0; MmSectionObjectType->PagedPoolCharge = 0; MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT); MmSectionObjectType->Mapping = &MmpSectionMapping; @@ -3265,8 +3243,8 @@ MmCreateImageSection(PSECTION_OBJECT *SectionObject, return(Status); } - if (0 != InterlockedCompareExchangeUL(&FileObject->SectionObjectPointer->ImageSectionObject, - ImageSectionObject, 0)) + if (NULL != InterlockedCompareExchangePointer(&FileObject->SectionObjectPointer->ImageSectionObject, + ImageSectionObject, NULL)) { /* * An other thread has initialized the some image in the background @@ -3593,7 +3571,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, Section = MArea->Data.SectionData.Section; Segment = MArea->Data.SectionData.Segment; - PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset); + PageOp = MmCheckForPageOp(MArea, NULL, NULL, Segment, Offset); while (PageOp) { @@ -3610,7 +3588,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, MmLockAddressSpace(&MArea->Process->AddressSpace); MmLockSectionSegment(Segment); MmspCompleteAndReleasePageOp(PageOp); - PageOp = MmCheckForPageOp(MArea, 0, NULL, Segment, Offset); + PageOp = MmCheckForPageOp(MArea, NULL, NULL, Segment, Offset); } Entry = MmGetPageEntrySectionSegment(Segment, Offset); @@ -4089,7 +4067,7 @@ MmAllocateSection (IN ULONG Length, PVOID BaseAddress) KEBUGCHECK(0); } Status = MmCreateVirtualMapping (NULL, - (PVOID)(Result + (i * PAGE_SIZE)), + (PVOID)((ULONG_PTR)Result + (i * PAGE_SIZE)), PAGE_READWRITE, &Page, 1); @@ -4201,9 +4179,9 @@ MmMapViewOfSection(IN PVOID SectionObject, { if (!(SectionSegments[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD)) { - ULONG MaxExtent; - MaxExtent = (ULONG)((char*)SectionSegments[i].VirtualAddress + - SectionSegments[i].Length); + ULONG_PTR MaxExtent; + MaxExtent = (ULONG_PTR)SectionSegments[i].VirtualAddress + + SectionSegments[i].Length; ImageSize = max(ImageSize, MaxExtent); } } diff --git a/reactos/ntoskrnl/mm/slab.c b/reactos/ntoskrnl/mm/slab.c deleted file mode 100644 index 2c6c44980bd..00000000000 --- a/reactos/ntoskrnl/mm/slab.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/slab.c - * PURPOSE: Slab allocator. - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 27/12/01 - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* TYPES ********************************************************************/ - -typedef VOID (*SLAB_CACHE_CONSTRUCTOR)(VOID*, ULONG); -typedef VOID (*SLAB_CACHE_DESTRUCTOR)(VOID*, ULONG); - -struct _SLAB_CACHE_PAGE; - -typedef struct _SLAB_CACHE -{ - SLAB_CACHE_CONSTRUCTOR Constructor; - SLAB_CACHE_DESTRUCTOR Destructor; - ULONG BaseSize; - ULONG ObjectSize; - ULONG ObjectsPerPage; - LIST_ENTRY PageListHead; - struct _SLAB_CACHE_PAGE* FirstFreePage; - KSPIN_LOCK SlabLock; -} -SLAB_CACHE, *PSLAB_CACHE; - -typedef struct _SLAB_CACHE_BUFCTL -{ - struct _SLAB_CACHE_BUFCTL* NextFree; -} -SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL; - -typedef struct _SLAB_CACHE_PAGE -{ - LIST_ENTRY PageListEntry; - PSLAB_CACHE_BUFCTL FirstFreeBuffer; - ULONG ReferenceCount; -} -SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE; - -/* GLOBALS ******************************************************************/ - -/* FUNCTIONS ****************************************************************/ - -PSLAB_CACHE -ExCreateSlabCache(PUNICODE_STRING Name, ULONG Size, ULONG Align, - SLAB_CACHE_CONSTRUCTOR Constructor, - SLAB_CACHE_DESTRUCTOR Destructor) -{ - PSLAB_CACHE Slab; - ULONG ObjectSize; - ULONG AlignSize; - - Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE)); - if (Slab == NULL) - { - return(NULL); - } - - Slab->Constructor = Constructor; - Slab->Destructor = Destructor; - Slab->BaseSize = Size; - ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL); - AlignSize = Align - (ObjectSize % Align); - Slab->ObjectSize = ObjectSize + AlignSize; - Slab->ObjectsPerPage = - (PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize; - Slab->FirstFreePage = NULL; - InitializeListHead(&Slab->PageListHead); - KeInitializeSpinLock(&Slab->SlabLock); - - return(Slab); -} - -PSLAB_CACHE_PAGE -ExGrowSlabCache(PSLAB_CACHE Slab) -{ - PSLAB_CACHE_PAGE SlabPage; - PFN_TYPE Pfn; - PVOID Page; - NTSTATUS Status; - ULONG i; - PSLAB_CACHE_BUFCTL BufCtl; - PVOID Object; - - Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pfn); - if (!NT_SUCCESS(Status)) - { - return(NULL); - } - - Page = ExAllocatePageWithPhysPage(Pfn); - if (Page == NULL) - { - MmReleasePageMemoryConsumer(MC_NPPOOL, Pfn); - return(NULL); - } - - SlabPage = (PSLAB_CACHE_PAGE)((char*)Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)); - SlabPage->ReferenceCount = 0; - SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page; - for (i = 0; i < Slab->ObjectsPerPage; i++) - { - BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Page + (i * Slab->ObjectSize)); - Object = (PVOID)(BufCtl + 1); - if (Slab->Constructor != NULL) - { - Slab->Constructor(Object, Slab->BaseSize); - } - if (i == (Slab->ObjectsPerPage - 1)) - { - BufCtl->NextFree = - (PSLAB_CACHE_BUFCTL)((char*)Page + ((i + 1) * Slab->ObjectSize)); - } - else - { - BufCtl->NextFree = NULL; - } - } - - return(SlabPage); -} - -PVOID -ExAllocateSlabCache(PSLAB_CACHE Slab, BOOLEAN MayWait) -{ - KIRQL oldIrql; - PSLAB_CACHE_PAGE Page; - PVOID Object; - BOOLEAN NewPage; - - KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); - - /* - * Check if there is a page with free objects - * present, if so allocate from it, if - * not grow the slab. - */ - if (Slab->FirstFreePage == NULL) - { - KeReleaseSpinLock(&Slab->SlabLock, oldIrql); - Page = ExGrowSlabCache(Slab); - NewPage = TRUE; - KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); - } - else - { - Page = Slab->FirstFreePage; - NewPage = FALSE; - } - - /* - * We shouldn't have got a page without free buffers. - */ - if (Page->FirstFreeBuffer == NULL) - { - DPRINT1("First free page had no free buffers.\n"); - KEBUGCHECK(0); - } - - /* - * Allocate the first free object from the page. - */ - Object = (PVOID)((char*)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL)); - Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree; - Page->ReferenceCount++; - - /* - * If we just allocated all the objects from this page - * and it was the first free page then adjust the - * first free page pointer and move the page to the head - * of the list. - */ - if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage) - { - if (Page->PageListEntry.Flink == &Slab->PageListHead) - { - Slab->FirstFreePage = NULL; - } - else - { - PSLAB_CACHE_PAGE NextPage; - - NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink, - SLAB_CACHE_PAGE, - PageListEntry); - Slab->FirstFreePage = NextPage; - } - RemoveEntryList(&Page->PageListEntry); - InsertHeadList(&Slab->PageListHead, &Page->PageListEntry); - } - /* - * Otherwise if we created a new page then add it to the end of - * the page list. - */ - else if (NewPage) - { - InsertTailList(&Slab->PageListHead, &Page->PageListEntry); - if (Slab->FirstFreePage == NULL) - { - Slab->FirstFreePage = Page; - } - } - KeReleaseSpinLock(&Slab->SlabLock, oldIrql); - return(Object); -} - -VOID -ExFreeFromPageSlabCache(PSLAB_CACHE Slab, - PSLAB_CACHE_PAGE Page, - PVOID Object) -{ - PSLAB_CACHE_BUFCTL BufCtl; - - BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Object - sizeof(SLAB_CACHE_BUFCTL)); - BufCtl->NextFree = Page->FirstFreeBuffer; - Page->FirstFreeBuffer = BufCtl; - Page->ReferenceCount--; -} - -VOID -ExFreeSlabCache(PSLAB_CACHE Slab, PVOID Object) -{ - KIRQL oldIrql; - PLIST_ENTRY current_entry; - PSLAB_CACHE_PAGE current; - - KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); - current_entry = Slab->PageListHead.Flink; - while (current_entry != &Slab->PageListHead) - { - PVOID Base; - - current = CONTAINING_RECORD(current_entry, - SLAB_CACHE_PAGE, - PageListEntry); - Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE); - if (Base >= Object && - ((char*)Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >= - ((char*)Object + Slab->ObjectSize)) - { - ExFreeFromPageSlabCache(Slab, current, Object); - /* - * If the page just become free then rearrange things. - */ - if (current->ReferenceCount == 0) - { - RemoveEntryList(¤t->PageListEntry); - InsertTailList(&Slab->PageListHead, ¤t->PageListEntry); - if (Slab->FirstFreePage == NULL) - { - Slab->FirstFreePage = current; - } - } - KeReleaseSpinLock(&Slab->SlabLock, oldIrql); - return; - } - } - DPRINT1("Tried to free object not in cache.\n"); - KEBUGCHECK(0); -} - -VOID -ExDestroySlabCache(PSLAB_CACHE Slab) -{ - PLIST_ENTRY current_entry; - PSLAB_CACHE_PAGE current; - ULONG i; - PVOID Object; - - current_entry = Slab->PageListHead.Flink; - while (current_entry != &Slab->PageListHead) - { - PVOID Base; - PFN_TYPE Page; - - current = CONTAINING_RECORD(current_entry, - SLAB_CACHE_PAGE, - PageListEntry); - Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE); - if (Slab->Destructor != NULL) - { - for (i = 0; i < Slab->ObjectsPerPage; i++) - { - Object = (char*)Base + (i * Slab->ObjectSize) + - sizeof(SLAB_CACHE_BUFCTL); - Slab->Destructor(Object, Slab->BaseSize); - } - } - Page = MmGetPfnForProcess(NULL, Base); - ExUnmapPage(Base); - MmReleasePageMemoryConsumer(MC_NPPOOL, Page); - } - ExFreePool(Slab); -} diff --git a/reactos/ntoskrnl/mm/verifier.c b/reactos/ntoskrnl/mm/verifier.c index 7f39eabcc9e..fc7e721e940 100644 --- a/reactos/ntoskrnl/mm/verifier.c +++ b/reactos/ntoskrnl/mm/verifier.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/verifier.c * PURPOSE: Driver Verifier functions - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 16/07/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index b92ed3b0040..aadecb396c9 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -1,33 +1,16 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/virtual.c - * PURPOSE: Implementing operations on virtual memory. - * PROGRAMMER: David Welch + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/virtual.c + * PURPOSE: Implementing operations on virtual memory. + * + * PROGRAMMERS: David Welch */ /* INCLUDE *****************************************************************/ #include -#include #define NDEBUG #include @@ -50,8 +33,9 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle, * RETURNS: Status */ { - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); + /* This should be implemented once we support network filesystems */ + DPRINT("NtFlushVirtualMemory is UNIMPLEMENTED\n"); + return(STATUS_SUCCESS); } @@ -350,6 +334,61 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle, } +NTSTATUS STDCALL +MiProtectVirtualMemory(IN PEPROCESS Process, + IN OUT PVOID *BaseAddress, + IN OUT PULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection OPTIONAL) +{ + PMEMORY_AREA MemoryArea; + PMADDRESS_SPACE AddressSpace; + ULONG OldAccessProtection_; + NTSTATUS Status; + + *NumberOfBytesToProtect = + PAGE_ROUND_UP((*BaseAddress) + (*NumberOfBytesToProtect)) - + PAGE_ROUND_DOWN(*BaseAddress); + *BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress); + + AddressSpace = &Process->AddressSpace; + + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress); + if (MemoryArea == NULL) + { + MmUnlockAddressSpace(AddressSpace); + return STATUS_UNSUCCESSFUL; + } + + if (OldAccessProtection == NULL) + OldAccessProtection = &OldAccessProtection_; + + if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY) + { + Status = MmProtectAnonMem(AddressSpace, MemoryArea, *BaseAddress, + *NumberOfBytesToProtect, NewAccessProtection, + OldAccessProtection); + } + else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) + { + Status = MmProtectSectionView(AddressSpace, MemoryArea, *BaseAddress, + *NumberOfBytesToProtect, + NewAccessProtection, + OldAccessProtection); + } + else + { + /* FIXME: Should we return failure or success in this case? */ + Status = STATUS_SUCCESS; + } + + MmUnlockAddressSpace(AddressSpace); + + return Status; +} + + /* (tMk 2004.II.5) * FUNCTION: * Called from VirtualProtectEx (lib\kernel32\mem\virtual.c) @@ -357,15 +396,13 @@ NtQueryVirtualMemory (IN HANDLE ProcessHandle, */ NTSTATUS STDCALL NtProtectVirtualMemory(IN HANDLE ProcessHandle, - IN PVOID *UnsafeBaseAddress, - IN ULONG *UnsafeNumberOfBytesToProtect, + IN OUT PVOID *UnsafeBaseAddress, + IN OUT ULONG *UnsafeNumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG UnsafeOldAccessProtection) { - PMEMORY_AREA MemoryArea; PEPROCESS Process; NTSTATUS Status; - PMADDRESS_SPACE AddressSpace; ULONG OldAccessProtection; PVOID BaseAddress; ULONG NumberOfBytesToProtect; @@ -377,18 +414,14 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle, if (!NT_SUCCESS(Status)) return Status; - // (tMk 2004.II.5) in Microsoft SDK I read: - // 'if this parameter is NULL or does not point to a valid variable, the function fails' + /* (tMk 2004.II.5) in Microsoft SDK I read: + * 'if this parameter is NULL or does not point to a valid variable, the function fails' + */ if(UnsafeOldAccessProtection == NULL) { return(STATUS_INVALID_PARAMETER); } - NumberOfBytesToProtect = - PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) - - PAGE_ROUND_DOWN(BaseAddress); - BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress); - Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_VM_OPERATION, PsProcessType, @@ -401,32 +434,12 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle, return(Status); } - AddressSpace = &Process->AddressSpace; + Status = MiProtectVirtualMemory(Process, + &BaseAddress, + &NumberOfBytesToProtect, + NewAccessProtection, + &OldAccessProtection); - MmLockAddressSpace(AddressSpace); - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress); - if (MemoryArea == NULL) - { - MmUnlockAddressSpace(AddressSpace); - ObDereferenceObject(Process); - return(STATUS_UNSUCCESSFUL); - } - - if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY) - { - Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress, - NumberOfBytesToProtect, NewAccessProtection, - &OldAccessProtection); - } - else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) - { - Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress, - NumberOfBytesToProtect, - NewAccessProtection, - &OldAccessProtection); - } - - MmUnlockAddressSpace(AddressSpace); ObDereferenceObject(Process); MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection, sizeof(ULONG)); @@ -590,12 +603,15 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN ULONG NumberOfBytesToWrite, - OUT PULONG NumberOfBytesWritten) + OUT PULONG NumberOfBytesWritten OPTIONAL) { NTSTATUS Status; PMDL Mdl; PVOID SystemAddress; PEPROCESS Process; + ULONG OldProtection = 0; + PVOID ProtectBaseAddress; + ULONG ProtectNumberOfBytes; DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, " "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress, @@ -612,23 +628,62 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle, return(Status); } + /* We have to make sure the target memory is writable. + * + * I am not sure if it is correct to do this in any case, but it has to be + * done at least in some cases because you can use WriteProcessMemory to + * write into the .text section of a module where memcpy() would crash. + * -blight (2005/01/09) + */ + ProtectBaseAddress = BaseAddress; + ProtectNumberOfBytes = NumberOfBytesToWrite; + + /* Write memory */ if (Process == PsGetCurrentProcess()) { + Status = MiProtectVirtualMemory(Process, + &ProtectBaseAddress, + &ProtectNumberOfBytes, + PAGE_READWRITE, + &OldProtection); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Process); + return Status; + } memcpy(BaseAddress, Buffer, NumberOfBytesToWrite); } else { + /* Create MDL describing the source buffer. */ Mdl = MmCreateMdl(NULL, Buffer, NumberOfBytesToWrite); - MmProbeAndLockPages(Mdl, - UserMode, - IoReadAccess); if(Mdl == NULL) { ObDereferenceObject(Process); return(STATUS_NO_MEMORY); } + + /* Make the target area writable. */ + Status = MiProtectVirtualMemory(Process, + &ProtectBaseAddress, + &ProtectNumberOfBytes, + PAGE_READWRITE, + &OldProtection); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Process); + ExFreePool(Mdl); + return Status; + } + + /* Map the MDL. */ + MmProbeAndLockPages(Mdl, + UserMode, + IoReadAccess); + + /* Copy memory from the mapped MDL into the target buffer. */ KeAttachProcess(&Process->Pcb); SystemAddress = MmGetSystemAddressForMdl(Mdl); @@ -636,6 +691,7 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle, KeDetachProcess(); + /* Free the MDL. */ if (Mdl->MappedSystemVa != NULL) { MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); @@ -644,9 +700,22 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle, ExFreePool(Mdl); } + /* Reset the protection of the target memory. */ + Status = MiProtectVirtualMemory(Process, + &ProtectBaseAddress, + &ProtectNumberOfBytes, + OldProtection, + &OldProtection); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reset protection of the target memory! (Status 0x%x)\n", Status); + /* FIXME: Should we bugcheck here? */ + } + ObDereferenceObject(Process); - *NumberOfBytesWritten = NumberOfBytesToWrite; + if (NumberOfBytesWritten != NULL) + MmCopyToCaller(NumberOfBytesWritten, &NumberOfBytesToWrite, sizeof(ULONG)); return(STATUS_SUCCESS); } @@ -710,7 +779,7 @@ ProbeForRead (IN CONST VOID *Address, IN ULONG Length, IN ULONG Alignment) { - ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8); + ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8); if (Length == 0) return; @@ -719,8 +788,8 @@ ProbeForRead (IN CONST VOID *Address, { ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT); } - else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address || - (ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress) + else if ((ULONG_PTR)Address + Length - 1 < (ULONG_PTR)Address || + (ULONG_PTR)Address + Length - 1 > (ULONG_PTR)MmUserProbeAddress) { ExRaiseStatus (STATUS_ACCESS_VIOLATION); } @@ -735,11 +804,10 @@ ProbeForWrite (IN CONST VOID *Address, IN ULONG Length, IN ULONG Alignment) { - PULONG Ptr; - ULONG x; - ULONG i; + volatile CHAR *Current; + PCHAR Last; - ASSERT(Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8); + ASSERT(Alignment == 1 || Alignment == 2 || Alignment == 4 || Alignment == 8); if (Length == 0) return; @@ -748,19 +816,21 @@ ProbeForWrite (IN CONST VOID *Address, { ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT); } - else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address || - (ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress) + + Last = (PCHAR)((ULONG_PTR)Address + Length - 1); + if ((ULONG_PTR)Last < (ULONG_PTR)Address || + (ULONG_PTR)Last > (ULONG_PTR)MmUserProbeAddress) { ExRaiseStatus (STATUS_ACCESS_VIOLATION); } /* Check for accessible pages */ - for (i = 0; i < Length; i += PAGE_SIZE) + Current = (CHAR*)Address; + do { - Ptr = (PULONG)(((ULONG_PTR)Address & ~(PAGE_SIZE - 1)) + i); - x = *Ptr; - *Ptr = x; - } + *Current = *Current; + Current = (CHAR*)((ULONG_PTR)Current + PAGE_SIZE); + } while (Current <= Last); } /* EOF */ diff --git a/reactos/ntoskrnl/mm/wset.c b/reactos/ntoskrnl/mm/wset.c index f3962cac114..d6ff15b5a85 100644 --- a/reactos/ntoskrnl/mm/wset.c +++ b/reactos/ntoskrnl/mm/wset.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/wset.c * PURPOSE: Manages working sets - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/nt/channel.c b/reactos/ntoskrnl/nt/channel.c deleted file mode 100644 index 9ec317425fa..00000000000 --- a/reactos/ntoskrnl/nt/channel.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/channel.c - * PURPOSE: Channels (??) - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* - * NOTES: - * - * An article on System Internals (http://www.sysinternals.com) reports - * that these functions are unimplemented on nt version 3-5. - * - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS -STDCALL -NtCreateChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - - -NTSTATUS -STDCALL -NtListenChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -STDCALL -NtOpenChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - - -NTSTATUS -STDCALL -NtReplyWaitSendChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - - -NTSTATUS -STDCALL -NtSendWaitReplyChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - - -NTSTATUS -STDCALL -NtSetContextChannel(VOID) -{ - return STATUS_NOT_IMPLEMENTED; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/misc.c b/reactos/ntoskrnl/nt/misc.c deleted file mode 100644 index 022671075fd..00000000000 --- a/reactos/ntoskrnl/nt/misc.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/misc.c - * PURPOSE: Misc undocumented system calls - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS -STDCALL -NtDisplayString(IN PUNICODE_STRING DisplayString) -{ - ANSI_STRING AnsiString; - - RtlUnicodeStringToAnsiString (&AnsiString, DisplayString, TRUE); - - HalDisplayString (AnsiString.Buffer); - - RtlFreeAnsiString (&AnsiString); - - return(STATUS_SUCCESS); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/mutant.c b/reactos/ntoskrnl/nt/mutant.c deleted file mode 100644 index bd932d19835..00000000000 --- a/reactos/ntoskrnl/nt/mutant.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/mutant.c - * PURPOSE: Synchronization primitives - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -POBJECT_TYPE ExMutantObjectType = NULL; - -static GENERIC_MAPPING ExpMutantMapping = { - STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE, - STANDARD_RIGHTS_WRITE | SYNCHRONIZE, - STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE, - MUTANT_ALL_ACCESS}; - -/* FUNCTIONS *****************************************************************/ - - -NTSTATUS STDCALL -NtpCreateMutant(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - return(STATUS_SUCCESS); -} - - -VOID STDCALL -NtpDeleteMutant(PVOID ObjectBody) -{ - DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody); - - KeReleaseMutant((PKMUTANT)ObjectBody, - MUTANT_INCREMENT, - TRUE, - FALSE); -} - - -VOID INIT_FUNCTION -NtInitializeMutantImplementation(VOID) -{ - ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant"); - - ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T'); - ExMutantObjectType->MaxObjects = ULONG_MAX; - ExMutantObjectType->MaxHandles = ULONG_MAX; - ExMutantObjectType->TotalObjects = 0; - ExMutantObjectType->TotalHandles = 0; - ExMutantObjectType->PagedPoolCharge = 0; - ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT); - ExMutantObjectType->Mapping = &ExpMutantMapping; - ExMutantObjectType->Dump = NULL; - ExMutantObjectType->Open = NULL; - ExMutantObjectType->Close = NULL; - ExMutantObjectType->Delete = NtpDeleteMutant; - ExMutantObjectType->Parse = NULL; - ExMutantObjectType->Security = NULL; - ExMutantObjectType->QueryName = NULL; - ExMutantObjectType->OkayToClose = NULL; - ExMutantObjectType->Create = NtpCreateMutant; - ExMutantObjectType->DuplicationNotify = NULL; - - ObpCreateTypeObject(ExMutantObjectType); -} - - -NTSTATUS STDCALL -NtCreateMutant(OUT PHANDLE MutantHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN BOOLEAN InitialOwner) -{ - PKMUTEX Mutant; - NTSTATUS Status; - - Status = ObCreateObject(ExGetPreviousMode(), - ExMutantObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(KMUTANT), - 0, - 0, - (PVOID*)&Mutant); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - KeInitializeMutant(Mutant, - InitialOwner); - - Status = ObInsertObject ((PVOID)Mutant, - NULL, - DesiredAccess, - 0, - NULL, - MutantHandle); - - ObDereferenceObject(Mutant); - - return Status; -} - - -NTSTATUS STDCALL -NtOpenMutant(OUT PHANDLE MutantHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - return(ObOpenObjectByName(ObjectAttributes, - ExMutantObjectType, - NULL, - ExGetPreviousMode(), - DesiredAccess, - NULL, - MutantHandle)); -} - - -NTSTATUS STDCALL -NtQueryMutant(IN HANDLE MutantHandle, - IN MUTANT_INFORMATION_CLASS MutantInformationClass, - OUT PVOID MutantInformation, - IN ULONG MutantInformationLength, - OUT PULONG ResultLength OPTIONAL) -{ - MUTANT_BASIC_INFORMATION SafeMutantInformation; - PKMUTANT Mutant; - NTSTATUS Status; - - if (MutantInformationClass > MutantBasicInformation) - return(STATUS_INVALID_INFO_CLASS); - - if (MutantInformationLength < sizeof(MUTANT_BASIC_INFORMATION)) - return(STATUS_INFO_LENGTH_MISMATCH); - - Status = ObReferenceObjectByHandle(MutantHandle, - MUTANT_QUERY_STATE, - ExMutantObjectType, - ExGetPreviousMode(), - (PVOID*)&Mutant, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - SafeMutantInformation.Count = KeReadStateMutant(Mutant); - SafeMutantInformation.Owned = (Mutant->OwnerThread != NULL); - SafeMutantInformation.Abandoned = Mutant->Abandoned; - - ObDereferenceObject(Mutant); - - Status = MmCopyToCaller(MutantInformation, &SafeMutantInformation, sizeof(MUTANT_BASIC_INFORMATION)); - if(NT_SUCCESS(Status)) - { - if(ResultLength != NULL) - { - ULONG RetLen = sizeof(MUTANT_BASIC_INFORMATION); - Status = MmCopyToCaller(ResultLength, &RetLen, sizeof(ULONG)); - } - else - { - Status = STATUS_SUCCESS; - } - } - - return Status; -} - - -NTSTATUS STDCALL -NtReleaseMutant(IN HANDLE MutantHandle, - IN PLONG PreviousCount OPTIONAL) -{ - PKMUTANT Mutant; - NTSTATUS Status; - LONG Count; - - Status = ObReferenceObjectByHandle(MutantHandle, - MUTANT_ALL_ACCESS, - ExMutantObjectType, - ExGetPreviousMode(), - (PVOID*)&Mutant, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Count = KeReleaseMutant(Mutant, - MUTANT_INCREMENT, - 0, - FALSE); - ObDereferenceObject(Mutant); - - if (PreviousCount != NULL) - { - Status = MmCopyToCaller(PreviousCount, &Count, sizeof(LONG)); - } - else - { - Status = STATUS_SUCCESS; - } - - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/nt.c b/reactos/ntoskrnl/nt/nt.c deleted file mode 100644 index 194630eb12e..00000000000 --- a/reactos/ntoskrnl/nt/nt.c +++ /dev/null @@ -1,31 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/nt.c - * PURPOSE: Initialization of system call interfaces - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -/* FUNCTIONS *****************************************************************/ - -VOID INIT_FUNCTION -NtInit(VOID) -{ - NtInitializeEventImplementation(); - NtInitializeEventPairImplementation(); - NtInitializeMutantImplementation(); - NtInitializeSemaphoreImplementation(); - NtInitializeTimerImplementation(); - NiInitPort(); - NtInitializeProfileImplementation(); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/ntevent.c b/reactos/ntoskrnl/nt/ntevent.c deleted file mode 100644 index 02e01d17a1a..00000000000 --- a/reactos/ntoskrnl/nt/ntevent.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/event.c - * PURPOSE: Named event support - * PROGRAMMER: Philip Susi and David Welch - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* GLOBALS *******************************************************************/ - -POBJECT_TYPE EXPORTED ExEventObjectType = NULL; - -static GENERIC_MAPPING ExpEventMapping = { - STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE, - STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE, - STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE, - EVENT_ALL_ACCESS}; - - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS STDCALL -NtpCreateEvent(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - return(STATUS_SUCCESS); -} - - -VOID INIT_FUNCTION -NtInitializeEventImplementation(VOID) -{ - ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExEventObjectType->TypeName, L"Event"); - - ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T'); - ExEventObjectType->MaxObjects = ULONG_MAX; - ExEventObjectType->MaxHandles = ULONG_MAX; - ExEventObjectType->TotalObjects = 0; - ExEventObjectType->TotalHandles = 0; - ExEventObjectType->PagedPoolCharge = 0; - ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT); - ExEventObjectType->Mapping = &ExpEventMapping; - ExEventObjectType->Dump = NULL; - ExEventObjectType->Open = NULL; - ExEventObjectType->Close = NULL; - ExEventObjectType->Delete = NULL; - ExEventObjectType->Parse = NULL; - ExEventObjectType->Security = NULL; - ExEventObjectType->QueryName = NULL; - ExEventObjectType->OkayToClose = NULL; - ExEventObjectType->Create = NtpCreateEvent; - ExEventObjectType->DuplicationNotify = NULL; - - ObpCreateTypeObject(ExEventObjectType); -} - - -NTSTATUS STDCALL -NtClearEvent(IN HANDLE EventHandle) -{ - PKEVENT Event; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - UserMode, - (PVOID*)&Event, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - KeClearEvent(Event); - ObDereferenceObject(Event); - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtCreateEvent(OUT PHANDLE EventHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN EVENT_TYPE EventType, - IN BOOLEAN InitialState) -{ - PKEVENT Event; - HANDLE hEvent; - NTSTATUS Status; - OBJECT_ATTRIBUTES SafeObjectAttributes; - - if (ObjectAttributes != NULL) - { - Status = MmCopyFromCaller(&SafeObjectAttributes, ObjectAttributes, - sizeof(OBJECT_ATTRIBUTES)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - ObjectAttributes = &SafeObjectAttributes; - } - - Status = ObCreateObject(ExGetPreviousMode(), - ExEventObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(KEVENT), - 0, - 0, - (PVOID*)&Event); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - KeInitializeEvent(Event, - EventType, - InitialState); - - Status = ObInsertObject ((PVOID)Event, - NULL, - DesiredAccess, - 0, - NULL, - &hEvent); - ObDereferenceObject(Event); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - Status = MmCopyToCaller(EventHandle, &hEvent, sizeof(HANDLE)); - if (!NT_SUCCESS(Status)) - { - ZwClose(hEvent); - return(Status); - } - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -NtOpenEvent(OUT PHANDLE EventHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - NTSTATUS Status; - HANDLE hEvent; - - DPRINT("ObjectName '%wZ'\n", ObjectAttributes->ObjectName); - - Status = ObOpenObjectByName(ObjectAttributes, - ExEventObjectType, - NULL, - UserMode, - DesiredAccess, - NULL, - &hEvent); - - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = MmCopyToCaller(EventHandle, &hEvent, sizeof(HANDLE)); - if (!NT_SUCCESS(Status)) - { - ZwClose(EventHandle); - return(Status); - } - - return(Status); -} - - -NTSTATUS STDCALL -NtPulseEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - NTSTATUS Status; - - DPRINT("NtPulseEvent(EventHandle %x PreviousState %x)\n", - EventHandle, PreviousState); - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - UserMode, - (PVOID*)&Event, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - KePulseEvent(Event, EVENT_INCREMENT, FALSE); - - ObDereferenceObject(Event); - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -NtQueryEvent(IN HANDLE EventHandle, - IN EVENT_INFORMATION_CLASS EventInformationClass, - OUT PVOID EventInformation, - IN ULONG EventInformationLength, - OUT PULONG ReturnLength OPTIONAL) -{ - EVENT_BASIC_INFORMATION Info; - PKEVENT Event; - NTSTATUS Status; - ULONG RetLen; - - if (EventInformationClass > EventBasicInformation) - return STATUS_INVALID_INFO_CLASS; - - if (EventInformationLength < sizeof(EVENT_BASIC_INFORMATION)) - return STATUS_INFO_LENGTH_MISMATCH; - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_QUERY_STATE, - ExEventObjectType, - UserMode, - (PVOID*)&Event, - NULL); - if (!NT_SUCCESS(Status)) - return Status; - - if (Event->Header.Type == InternalNotificationEvent) - Info.EventType = NotificationEvent; - else - Info.EventType = SynchronizationEvent; - Info.EventState = KeReadStateEvent(Event); - - Status = MmCopyToCaller(EventInformation, &Event, - sizeof(EVENT_BASIC_INFORMATION)); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Event); - return(Status); - } - - if (ReturnLength != NULL) - { - RetLen = sizeof(EVENT_BASIC_INFORMATION); - Status = MmCopyToCaller(ReturnLength, &RetLen, sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Event); - return(Status); - } - } - - ObDereferenceObject(Event); - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -NtResetEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - NTSTATUS Status; - - DPRINT("NtResetEvent(EventHandle %x)\n", EventHandle); - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - UserMode, - (PVOID*)&Event, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - KeResetEvent(Event); - ObDereferenceObject(Event); - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtSetEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - NTSTATUS Status; - - DPRINT("NtSetEvent(EventHandle %x)\n", EventHandle); - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - UserMode, - (PVOID*)&Event, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - KeSetEvent(Event,EVENT_INCREMENT,FALSE); - ObDereferenceObject(Event); - return(STATUS_SUCCESS); -} - -/* - * @unimplemented - */ -NTSTATUS -STDCALL -NtTraceEvent( - IN ULONG TraceHandle, - IN ULONG Flags, - IN ULONG TraceHeaderLength, - IN struct _EVENT_TRACE_HEADER* TraceHeader - ) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/ntsem.c b/reactos/ntoskrnl/nt/ntsem.c deleted file mode 100644 index 1c908d085c5..00000000000 --- a/reactos/ntoskrnl/nt/ntsem.c +++ /dev/null @@ -1,201 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/ntsem.c - * PURPOSE: Synchronization primitives - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* GLOBALS ******************************************************************/ - -POBJECT_TYPE ExSemaphoreObjectType; - -static GENERIC_MAPPING ExSemaphoreMapping = { - STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE, - STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE, - STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE, - SEMAPHORE_ALL_ACCESS}; - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS STDCALL -NtpCreateSemaphore(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - return(STATUS_SUCCESS); -} - -VOID INIT_FUNCTION -NtInitializeSemaphoreImplementation(VOID) -{ - ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore"); - - ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T'); - ExSemaphoreObjectType->MaxObjects = ULONG_MAX; - ExSemaphoreObjectType->MaxHandles = ULONG_MAX; - ExSemaphoreObjectType->TotalObjects = 0; - ExSemaphoreObjectType->TotalHandles = 0; - ExSemaphoreObjectType->PagedPoolCharge = 0; - ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE); - ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping; - ExSemaphoreObjectType->Dump = NULL; - ExSemaphoreObjectType->Open = NULL; - ExSemaphoreObjectType->Close = NULL; - ExSemaphoreObjectType->Delete = NULL; - ExSemaphoreObjectType->Parse = NULL; - ExSemaphoreObjectType->Security = NULL; - ExSemaphoreObjectType->QueryName = NULL; - ExSemaphoreObjectType->OkayToClose = NULL; - ExSemaphoreObjectType->Create = NtpCreateSemaphore; - ExSemaphoreObjectType->DuplicationNotify = NULL; - - ObpCreateTypeObject(ExSemaphoreObjectType); -} - -NTSTATUS STDCALL -NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN LONG InitialCount, - IN LONG MaximumCount) -{ - PKSEMAPHORE Semaphore; - NTSTATUS Status; - - Status = ObCreateObject(ExGetPreviousMode(), - ExSemaphoreObjectType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(KSEMAPHORE), - 0, - 0, - (PVOID*)&Semaphore); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - KeInitializeSemaphore(Semaphore, - InitialCount, - MaximumCount); - - Status = ObInsertObject ((PVOID)Semaphore, - NULL, - DesiredAccess, - 0, - NULL, - SemaphoreHandle); - - ObDereferenceObject(Semaphore); - - return Status; -} - - -NTSTATUS STDCALL -NtOpenSemaphore(IN HANDLE SemaphoreHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - NTSTATUS Status; - - Status = ObOpenObjectByName(ObjectAttributes, - ExSemaphoreObjectType, - NULL, - UserMode, - DesiredAccess, - NULL, - SemaphoreHandle); - - return Status; -} - - -NTSTATUS STDCALL -NtQuerySemaphore(IN HANDLE SemaphoreHandle, - IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, - OUT PVOID SemaphoreInformation, - IN ULONG SemaphoreInformationLength, - OUT PULONG ReturnLength OPTIONAL) -{ - PSEMAPHORE_BASIC_INFORMATION Info; - PKSEMAPHORE Semaphore; - NTSTATUS Status; - - Info = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation; - - if (SemaphoreInformationClass > SemaphoreBasicInformation) - return STATUS_INVALID_INFO_CLASS; - - if (SemaphoreInformationLength < sizeof(SEMAPHORE_BASIC_INFORMATION)) - return STATUS_INFO_LENGTH_MISMATCH; - - Status = ObReferenceObjectByHandle(SemaphoreHandle, - SEMAPHORE_QUERY_STATE, - ExSemaphoreObjectType, - UserMode, - (PVOID*)&Semaphore, - NULL); - if (!NT_SUCCESS(Status)) - return Status; - - Info->CurrentCount = KeReadStateSemaphore(Semaphore); - Info->MaximumCount = Semaphore->Limit; - - if (ReturnLength != NULL) - *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION); - - ObDereferenceObject(Semaphore); - - return STATUS_SUCCESS; -} - -NTSTATUS STDCALL -NtReleaseSemaphore(IN HANDLE SemaphoreHandle, - IN LONG ReleaseCount, - OUT PLONG PreviousCount OPTIONAL) -{ - PKSEMAPHORE Semaphore; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(SemaphoreHandle, - SEMAPHORE_MODIFY_STATE, - ExSemaphoreObjectType, - UserMode, - (PVOID*)&Semaphore, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - KeReleaseSemaphore(Semaphore, - IO_NO_INCREMENT, - ReleaseCount, - FALSE); - ObDereferenceObject(Semaphore); - return(STATUS_SUCCESS); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/nttimer.c b/reactos/ntoskrnl/nt/nttimer.c deleted file mode 100644 index 2d35b8f410a..00000000000 --- a/reactos/ntoskrnl/nt/nttimer.c +++ /dev/null @@ -1,381 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/nttimer.c - * PURPOSE: User-mode timers - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - - -/* TYPES ********************************************************************/ - -typedef struct _NTTIMER -{ - KTIMER Timer; - KDPC Dpc; - KAPC Apc; - BOOLEAN Running; -} NTTIMER, *PNTTIMER; - - -/* GLOBALS ******************************************************************/ - -POBJECT_TYPE ExTimerType = NULL; - -static GENERIC_MAPPING ExpTimerMapping = { - STANDARD_RIGHTS_READ | TIMER_QUERY_STATE, - STANDARD_RIGHTS_WRITE | TIMER_MODIFY_STATE, - STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, - TIMER_ALL_ACCESS}; - - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS STDCALL -NtpCreateTimer(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - DPRINT("NtpCreateTimer(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) - { - return(STATUS_UNSUCCESSFUL); - } - - return(STATUS_SUCCESS); -} - - -VOID STDCALL -NtpDeleteTimer(PVOID ObjectBody) -{ - KIRQL OldIrql; - PNTTIMER Timer = ObjectBody; - - DPRINT("NtpDeleteTimer()\n"); - - OldIrql = KeRaiseIrqlToDpcLevel(); - - KeCancelTimer(&Timer->Timer); - KeRemoveQueueDpc(&Timer->Dpc); - KeRemoveQueueApc(&Timer->Apc); - Timer->Running = FALSE; - - KeLowerIrql(OldIrql); -} - - -VOID STDCALL -NtpTimerDpcRoutine(PKDPC Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) -{ - PNTTIMER Timer; - - DPRINT("NtpTimerDpcRoutine()\n"); - - Timer = (PNTTIMER)DeferredContext; - - if ( Timer->Running ) - { - KeInsertQueueApc(&Timer->Apc, - SystemArgument1, - SystemArgument2, - IO_NO_INCREMENT); - } -} - - -VOID STDCALL -NtpTimerApcKernelRoutine(PKAPC Apc, - PKNORMAL_ROUTINE* NormalRoutine, - PVOID* NormalContext, - PVOID* SystemArgument1, - PVOID* SystemArguemnt2) -{ - DPRINT("NtpTimerApcKernelRoutine()\n"); - -} - - -VOID INIT_FUNCTION -NtInitializeTimerImplementation(VOID) -{ - ASSERT(!ExTimerType) - ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExTimerType->TypeName, L"Timer"); - - ExTimerType->Tag = TAG('T', 'I', 'M', 'T'); - ExTimerType->MaxObjects = ULONG_MAX; - ExTimerType->MaxHandles = ULONG_MAX; - ExTimerType->TotalObjects = 0; - ExTimerType->TotalHandles = 0; - ExTimerType->PagedPoolCharge = 0; - ExTimerType->NonpagedPoolCharge = sizeof(NTTIMER); - ExTimerType->Mapping = &ExpTimerMapping; - ExTimerType->Dump = NULL; - ExTimerType->Open = NULL; - ExTimerType->Close = NULL; - ExTimerType->Delete = NtpDeleteTimer; - ExTimerType->Parse = NULL; - ExTimerType->Security = NULL; - ExTimerType->QueryName = NULL; - ExTimerType->OkayToClose = NULL; - ExTimerType->Create = NtpCreateTimer; - ExTimerType->DuplicationNotify = NULL; - - ObpCreateTypeObject(ExTimerType); -} - - -NTSTATUS STDCALL -NtCancelTimer(IN HANDLE TimerHandle, - OUT PBOOLEAN CurrentState OPTIONAL) -{ - PNTTIMER Timer; - NTSTATUS Status; - BOOLEAN State; - KIRQL OldIrql; - - DPRINT("NtCancelTimer()\n"); - Status = ObReferenceObjectByHandle(TimerHandle, - TIMER_ALL_ACCESS, - ExTimerType, - UserMode, - (PVOID*)&Timer, - NULL); - if (!NT_SUCCESS(Status)) - return Status; - - OldIrql = KeRaiseIrqlToDpcLevel(); - - State = KeCancelTimer(&Timer->Timer); - KeRemoveQueueDpc(&Timer->Dpc); - KeRemoveQueueApc(&Timer->Apc); - Timer->Running = FALSE; - - KeLowerIrql(OldIrql); - ObDereferenceObject(Timer); - - if (CurrentState != NULL) - { - *CurrentState = State; - } - - return STATUS_SUCCESS; -} - - -NTSTATUS STDCALL -NtCreateTimer(OUT PHANDLE TimerHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN TIMER_TYPE TimerType) -{ - PNTTIMER Timer; - NTSTATUS Status; - - DPRINT("NtCreateTimer()\n"); - Status = ObCreateObject(ExGetPreviousMode(), - ExTimerType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(NTTIMER), - 0, - 0, - (PVOID*)&Timer); - if (!NT_SUCCESS(Status)) - return Status; - - KeInitializeTimerEx(&Timer->Timer, - TimerType); - - KeInitializeDpc(&Timer->Dpc, - &NtpTimerDpcRoutine, - Timer); - - Timer->Running = FALSE; - - Status = ObInsertObject ((PVOID)Timer, - NULL, - DesiredAccess, - 0, - NULL, - TimerHandle); - - ObDereferenceObject(Timer); - - return Status; -} - - -NTSTATUS STDCALL -NtOpenTimer(OUT PHANDLE TimerHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - NTSTATUS Status; - - Status = ObOpenObjectByName(ObjectAttributes, - ExTimerType, - NULL, - UserMode, - DesiredAccess, - NULL, - TimerHandle); - return Status; -} - - -NTSTATUS STDCALL -NtQueryTimer(IN HANDLE TimerHandle, - IN TIMER_INFORMATION_CLASS TimerInformationClass, - OUT PVOID TimerInformation, - IN ULONG TimerInformationLength, - OUT PULONG ReturnLength OPTIONAL) -{ - PNTTIMER Timer; - TIMER_BASIC_INFORMATION SafeTimerInformation; - ULONG ResultLength; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(TimerHandle, - TIMER_QUERY_STATE, - ExTimerType, - (KPROCESSOR_MODE)KeGetPreviousMode(), - (PVOID*)&Timer, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - if (TimerInformationClass != TimerBasicInformation) - { - ObDereferenceObject(Timer); - return(STATUS_INVALID_INFO_CLASS); - } - if (TimerInformationLength < sizeof(TIMER_BASIC_INFORMATION)) - { - ObDereferenceObject(Timer); - return(STATUS_INFO_LENGTH_MISMATCH); - } - - memcpy(&SafeTimerInformation.TimeRemaining, &Timer->Timer.DueTime, - sizeof(LARGE_INTEGER)); - SafeTimerInformation.SignalState = (BOOLEAN)Timer->Timer.Header.SignalState; - ResultLength = sizeof(TIMER_BASIC_INFORMATION); - - Status = MmCopyToCaller(TimerInformation, &SafeTimerInformation, - sizeof(TIMER_BASIC_INFORMATION)); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Timer); - return(Status); - } - - if (ReturnLength != NULL) - { - Status = MmCopyToCaller(ReturnLength, &ResultLength, - sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Timer); - return(Status); - } - } - ObDereferenceObject(Timer); - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -NtSetTimer(IN HANDLE TimerHandle, - IN PLARGE_INTEGER DueTime, - IN PTIMER_APC_ROUTINE TimerApcRoutine OPTIONAL, - IN PVOID TimerContext OPTIONAL, - IN BOOLEAN ResumeTimer, - IN LONG Period OPTIONAL, - OUT PBOOLEAN PreviousState OPTIONAL) -{ - PNTTIMER Timer; - NTSTATUS Status; - BOOLEAN Result; - BOOLEAN State; - - DPRINT("NtSetTimer()\n"); - - Status = ObReferenceObjectByHandle(TimerHandle, - TIMER_ALL_ACCESS, - ExTimerType, - (KPROCESSOR_MODE)KeGetPreviousMode(), - (PVOID*)&Timer, - NULL); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - State = KeReadStateTimer(&Timer->Timer); - - if (Timer->Running == TRUE) - { - /* cancel running timer */ - const KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); - KeCancelTimer(&Timer->Timer); - KeRemoveQueueDpc(&Timer->Dpc); - KeRemoveQueueApc(&Timer->Apc); - Timer->Running = FALSE; - KeLowerIrql(OldIrql); - } - - if (TimerApcRoutine) - { - KeInitializeApc(&Timer->Apc, - KeGetCurrentThread(), - OriginalApcEnvironment, - &NtpTimerApcKernelRoutine, - (PKRUNDOWN_ROUTINE)NULL, - (PKNORMAL_ROUTINE)TimerApcRoutine, - (KPROCESSOR_MODE)KeGetPreviousMode(), - TimerContext); - } - - Result = KeSetTimerEx(&Timer->Timer, - *DueTime, - Period, - TimerApcRoutine ? &Timer->Dpc : 0 ); - if (Result == TRUE) - { - ObDereferenceObject(Timer); - DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" ); - return STATUS_UNSUCCESSFUL; - } - - Timer->Running = TRUE; - - ObDereferenceObject(Timer); - - if (PreviousState != NULL) - { - *PreviousState = State; - } - - return STATUS_SUCCESS; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/nt/plugplay.c b/reactos/ntoskrnl/nt/plugplay.c deleted file mode 100644 index 7beceace626..00000000000 --- a/reactos/ntoskrnl/nt/plugplay.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/plugplay.c - * PURPOSE: Mysterious nt4 support for plug-and-play - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -/* FUNCTIONS *****************************************************************/ - -NTSTATUS -STDCALL -NtPlugPlayControl (DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); -} - -NTSTATUS -STDCALL -NtGetPlugPlayEvent (ULONG Reserved1, - ULONG Reserved2, - PVOID Buffer, - ULONG BufferLength) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); -} diff --git a/reactos/ntoskrnl/nt/profile.c b/reactos/ntoskrnl/nt/profile.c deleted file mode 100644 index 7b358344948..00000000000 --- a/reactos/ntoskrnl/nt/profile.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/profile.c - * PURPOSE: Support for profiling - * PROGRAMMER: Nobody - * UPDATE HISTORY: - * - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -/* TYPES ********************************************************************/ - -typedef struct _KPROCESS_PROFILE -/* - * List of the profile data structures associated with a process. - */ -{ - LIST_ENTRY ProfileListHead; - LIST_ENTRY ListEntry; - HANDLE Pid; -} KPROCESS_PROFILE, *PKPROCESS_PROFILE; - -typedef struct _KPROFILE -/* - * Describes a contiguous region of process memory that is being profiled. - */ -{ - CSHORT Type; - CSHORT Name; - - /* Entry in the list of profile data structures for this process. */ - LIST_ENTRY ListEntry; - - /* Base of the region being profiled. */ - PVOID Base; - - /* Size of the region being profiled. */ - ULONG Size; - - /* Shift of offsets from the region to buckets in the profiling buffer. */ - ULONG BucketShift; - - /* MDL which described the buffer that receives profiling data. */ - PMDL BufferMdl; - - /* System alias for the profiling buffer. */ - PULONG Buffer; - - /* Size of the buffer for profiling data. */ - ULONG BufferSize; - - /* - * Mask of processors for which profiling data should be collected. - * Currently unused. - */ - ULONG ProcessorMask; - - /* TRUE if profiling has been started for this region. */ - BOOLEAN Started; - - /* Pointer (and reference) to the process which is being profiled. */ - PEPROCESS Process; -} KPROFILE, *PKPROFILE; - -/* GLOBALS *******************************************************************/ - -POBJECT_TYPE EXPORTED ExProfileObjectType = NULL; - -static GENERIC_MAPPING ExpProfileMapping = { - STANDARD_RIGHTS_READ, - STANDARD_RIGHTS_WRITE, - STANDARD_RIGHTS_EXECUTE, - STANDARD_RIGHTS_ALL}; - -/* - * Size of the profile hash table. - */ -#define PROFILE_HASH_TABLE_SIZE (32) - -/* - * Table of lists of per-process profiling data structures hashed by PID. - */ -static LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; - -/* - * Head of the list of profile data structures for the kernel. - */ -static LIST_ENTRY SystemProfileList; - -/* - * Lock that protects the profiling data structures. - */ -static KSPIN_LOCK ProfileListLock; - -/* - * Timer interrupts happen before we have initialized the profiling - * data structures so just ignore them before that. - */ -static BOOLEAN ProfileInitDone = FALSE; - -/* FUNCTIONS *****************************************************************/ - -VOID STATIC -KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip) - /* - * Add a profile event to the profile objects for a particular process - * or the system - */ -{ - PKPROFILE current; - PLIST_ENTRY current_entry; - - current_entry = ListHead->Flink; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); - - if (current->Base > Eip) - { - return; - } - - if (current->Base <= Eip && ((char*)current->Base + current->Size) > (char*)Eip && - current->Started) - { - ULONG Bucket; - - Bucket = ((ULONG)((char*)Eip - (char*)current->Base)) >> current->BucketShift; - - if ((Bucket*4) < current->BufferSize) - { - current->Buffer[Bucket]++; - } - } - - current_entry = current_entry->Flink; - } -} - -VOID -KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip) - /* - * Add a profile event - */ -{ - HANDLE Pid; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - PLIST_ENTRY ListHead; - - if (!ProfileInitDone) - { - return; - } - - Pid = PsGetCurrentProcessId(); - ListHead = - ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink; - - KeAcquireSpinLockAtDpcLevel(&ProfileListLock); - - current_entry = ListHead; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry); - - if (current->Pid == Pid) - { - KiAddProfileEventToProcess(¤t->ProfileListHead, (PVOID)Eip); - break; - } - - current_entry = current_entry->Flink; - } - - KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip); - - KeReleaseSpinLockFromDpcLevel(&ProfileListLock); -} - -VOID -KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile) - /* - * Insert a profile object into the list for a process or the system - */ -{ - PKPROFILE current; - PLIST_ENTRY current_entry; - - current_entry = ListHead; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); - - if (current->Base > Profile->Base) - { - Profile->ListEntry.Flink = current_entry; - Profile->ListEntry.Blink = current_entry->Blink; - current_entry->Blink->Flink = &Profile->ListEntry; - current_entry->Blink = &Profile->ListEntry; - return; - } - - current_entry = current_entry->Flink; - } - InsertTailList(ListHead, &Profile->ListEntry); -} - -VOID -KiInsertProfile(PKPROFILE Profile) - /* - * Insert a profile into the relevant data structures - */ -{ - KIRQL oldIrql; - - KeAcquireSpinLock(&ProfileListLock, &oldIrql); - - if (Profile->Process == NULL) - { - KiInsertProfileIntoProcess(&SystemProfileList, Profile); - } - else - { - ULONG Pid; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - PLIST_ENTRY ListHead; - - Pid = Profile->Process->UniqueProcessId; - ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE]; - - current_entry = ListHead; - while(current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, - ListEntry); - - if (current->Pid == (HANDLE)Pid) - { - KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); - KeReleaseSpinLock(&ProfileListLock, oldIrql); - return; - } - - current_entry = current_entry->Flink; - } - - current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE)); - - current->Pid = (HANDLE)Pid; - InitializeListHead(¤t->ProfileListHead); - InsertTailList(ListHead, ¤t->ListEntry); - - KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); - } - - KeReleaseSpinLock(&ProfileListLock, oldIrql); -} - -VOID KiRemoveProfile(PKPROFILE Profile) -{ - KIRQL oldIrql; - - KeAcquireSpinLock(&ProfileListLock, &oldIrql); - - if (Profile->Process == NULL) - { - RemoveEntryList(&Profile->ListEntry); - } - else - { - ULONG Pid; - PLIST_ENTRY ListHead; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - - RemoveEntryList(&Profile->ListEntry); - - Pid = Profile->Process->UniqueProcessId; - ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE]; - - current_entry = ListHead; - while(current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, - ListEntry); - - if (current->Pid == (HANDLE)Pid) - { - if (IsListEmpty(¤t->ProfileListHead)) - { - RemoveEntryList(¤t->ListEntry); - ExFreePool(current); - } - KeReleaseSpinLock(&ProfileListLock, oldIrql); - return; - } - - current_entry = current_entry->Flink; - } - KEBUGCHECK(0); - } - - KeReleaseSpinLock(&ProfileListLock, oldIrql); -} - -VOID STDCALL -KiDeleteProfile(PVOID ObjectBody) -{ - PKPROFILE Profile; - - Profile = (PKPROFILE)ObjectBody; - - KiRemoveProfile(Profile); - if (Profile->Process != NULL) - { - ObDereferenceObject(Profile->Process); - Profile->Process = NULL; - } - - if (Profile->BufferMdl->MappedSystemVa != NULL) - { - MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa, - Profile->BufferMdl); - } - MmUnlockPages(Profile->BufferMdl); - ExFreePool(Profile->BufferMdl); - Profile->BufferMdl = NULL; -} - -VOID INIT_FUNCTION -NtInitializeProfileImplementation(VOID) -{ - ULONG i; - - InitializeListHead(&SystemProfileList); - - for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++) - { - InitializeListHead(&ProcessProfileListHashTable[i]); - } - - KeInitializeSpinLock(&ProfileListLock); - ProfileInitDone = TRUE; - - ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - RtlCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile"); - - ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F'); - ExProfileObjectType->MaxObjects = ULONG_MAX; - ExProfileObjectType->MaxHandles = ULONG_MAX; - ExProfileObjectType->TotalObjects = 0; - ExProfileObjectType->TotalHandles = 0; - ExProfileObjectType->PagedPoolCharge = 0; - ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE); - ExProfileObjectType->Mapping = &ExpProfileMapping; - ExProfileObjectType->Dump = NULL; - ExProfileObjectType->Open = NULL; - ExProfileObjectType->Close = NULL; - ExProfileObjectType->Delete = KiDeleteProfile; - ExProfileObjectType->Parse = NULL; - ExProfileObjectType->Security = NULL; - ExProfileObjectType->QueryName = NULL; - ExProfileObjectType->OkayToClose = NULL; - ExProfileObjectType->Create = NULL; - - ObpCreateTypeObject(ExProfileObjectType); -} - -NTSTATUS STDCALL -NtCreateProfile(OUT PHANDLE ProfileHandle, - IN HANDLE Process OPTIONAL, - IN PVOID ImageBase, - IN ULONG ImageSize, - IN ULONG BucketSize, - IN PVOID Buffer, - IN ULONG BufferSize, - IN KPROFILE_SOURCE ProfileSource, - IN KAFFINITY Affinity) -{ - HANDLE SafeProfileHandle; - NTSTATUS Status; - PKPROFILE Profile; - PEPROCESS pProcess; - - /* - * Reference the associated process - */ - if (Process != NULL) - { - Status = ObReferenceObjectByHandle(Process, - PROCESS_QUERY_INFORMATION, - PsProcessType, - UserMode, - (PVOID*)&pProcess, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } - else - { - pProcess = NULL; - /* FIXME: Check privilege. */ - } - - /* - * Check the parameters - */ - if ((pProcess == NULL && ImageBase < (PVOID)KERNEL_BASE) || - (pProcess != NULL && ImageBase >= (PVOID)KERNEL_BASE)) - { - return(STATUS_INVALID_PARAMETER_3); - } - if (((ImageSize >> BucketSize) * 4) >= BufferSize) - { - return(STATUS_BUFFER_TOO_SMALL); - } - if (ProfileSource != ProfileTime) - { - return(STATUS_INVALID_PARAMETER_9); - } - if (Affinity != 0) - { - return(STATUS_INVALID_PARAMETER_10); - } - - /* - * Create the object - */ - Status = ObCreateObject(ExGetPreviousMode(), - ExProfileObjectType, - NULL, - ExGetPreviousMode(), - NULL, - sizeof(KPROFILE), - 0, - 0, - (PVOID*)&Profile); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* - * Initialize it - */ - Profile->Base = ImageBase; - Profile->Size = ImageSize; - Profile->BucketShift = BucketSize; - Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize); - if(Profile->BufferMdl == NULL) { - DPRINT("MmCreateMdl: Out of memory!"); - return(STATUS_NO_MEMORY); - } - MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess); - Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl); - Profile->BufferSize = BufferSize; - Profile->ProcessorMask = Affinity; - Profile->Started = FALSE; - Profile->Process = pProcess; - - /* - * Insert the profile into the profile list data structures - */ - KiInsertProfile(Profile); - - Status = ObInsertObject ((PVOID)Profile, - NULL, - STANDARD_RIGHTS_ALL, - 0, - NULL, - &SafeProfileHandle); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Profile); - return Status; - } - - /* - * Copy the created handle back to the caller - */ - Status = MmCopyToCaller(ProfileHandle, &SafeProfileHandle, sizeof(HANDLE)); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Profile); - ZwClose(ProfileHandle); - return(Status); - } - - ObDereferenceObject(Profile); - - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL -NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource, - OUT PULONG Interval) -{ - NTSTATUS Status; - - if (ProfileSource == ProfileTime) - { - ULONG SafeInterval; - - /* FIXME: What units does this use, for now nanoseconds */ - SafeInterval = 100; - Status = MmCopyToCaller(Interval, &SafeInterval, sizeof(ULONG)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - return(STATUS_SUCCESS); - } - return(STATUS_INVALID_PARAMETER_2); -} - -NTSTATUS STDCALL -NtSetIntervalProfile(IN ULONG Interval, - IN KPROFILE_SOURCE Source) -{ - return(STATUS_NOT_IMPLEMENTED); -} - -NTSTATUS STDCALL -NtStartProfile(IN HANDLE ProfileHandle) -{ - NTSTATUS Status; - PKPROFILE Profile; - - Status = ObReferenceObjectByHandle(ProfileHandle, - STANDARD_RIGHTS_ALL, - ExProfileObjectType, - UserMode, - (PVOID*)&Profile, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - Profile->Started = TRUE; - ObDereferenceObject(Profile); - return(STATUS_SUCCESS); -} - -NTSTATUS STDCALL -NtStopProfile(IN HANDLE ProfileHandle) -{ - NTSTATUS Status; - PKPROFILE Profile; - - Status = ObReferenceObjectByHandle(ProfileHandle, - STANDARD_RIGHTS_ALL, - ExProfileObjectType, - UserMode, - (PVOID*)&Profile, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - Profile->Started = FALSE; - ObDereferenceObject(Profile); - return(STATUS_SUCCESS); -} - - diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index 565050d4985..461ebe6aa04 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -815,7 +815,6 @@ NtQueryInformationFile@20 NtQueryInformationProcess@20 NtQueryInformationThread@20 NtQueryInformationToken@20 -;NtQueryOleDirectoryFile@44 <--- ? NtQueryQuotaInformationFile@36 NtQuerySecurityObject@20 NtQuerySystemInformation@16 diff --git a/reactos/ntoskrnl/ntoskrnl.xml b/reactos/ntoskrnl/ntoskrnl.xml index 0ed2474fa5d..9bf4b8f382d 100644 --- a/reactos/ntoskrnl/ntoskrnl.xml +++ b/reactos/ntoskrnl/ntoskrnl.xml @@ -1,6 +1,5 @@ - genntdll @@ -17,7 +16,7 @@ - multiboot.S + main.S bios.c brkpoint.c bthread.S @@ -41,8 +40,10 @@ usertrap.c v86m.c v86m_sup.S + vdm.c + alert.c apc.c bug.c catch.c @@ -79,7 +80,6 @@ regfile.c registry.c regobj.c - rtlfunc.c @@ -116,25 +116,32 @@ btree.c callback.c + event.c + evtpair.c fmutex.c hashtab.c init.c interlck.c list.c lookas.c + mutant.c napi.c power.c + profile.c resource.c rundown.c + sem.c stree.c synch.c sysinfo.c time.c + timer.c util.c uuid.c win32k.c work.c zone.c + zw.S dbcsname.c @@ -165,6 +172,7 @@ deviface.c dir.c driver.c + efi.c errlog.c error.c event.c @@ -183,6 +191,7 @@ npipe.c page.c parttab.c + plugplay.c pnpdma.c pnpmgr.c pnpnotify.c @@ -269,26 +278,10 @@ region.c rmap.c section.c - slab.c verifier.c virtual.c wset.c - - channel.c - efi.c - evtpair.c - misc.c - mutant.c - nt.c - ntevent.c - ntsem.c - nttimer.c - plugplay.c - profile.c - vdm.c - zw.c - dirobj.c handle.c @@ -344,6 +337,7 @@ handle.c libsupp.c message.c + misc.c nls.c purecall.c rangelist.c diff --git a/reactos/ntoskrnl/ob/dirobj.c b/reactos/ntoskrnl/ob/dirobj.c index 57f96715c38..fab1f3d4001 100644 --- a/reactos/ntoskrnl/ob/dirobj.c +++ b/reactos/ntoskrnl/ob/dirobj.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ob/dirobj.c * PURPOSE: Interface functions to directory object - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 22/05/98: Created + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ***************************************************************/ @@ -47,62 +46,54 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes) { - PVOID Object; - NTSTATUS Status; - - *DirectoryHandle = 0; + HANDLE hDirectory; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; - Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, - ObjectAttributes->Attributes, - NULL, - DesiredAccess, - ObDirectoryType, - UserMode, - NULL, - &Object); - if (!NT_SUCCESS(Status)) + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY { - return Status; + ProbeForWrite(DirectoryHandle, + sizeof(HANDLE), + sizeof(ULONG)); } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenDirectoryObject failed, Status: 0x%x\n", Status); + return Status; + } + } - Status = ObCreateHandle(PsGetCurrentProcess(), - Object, - DesiredAccess, - FALSE, - DirectoryHandle); - return STATUS_SUCCESS; -} - -static NTSTATUS -CopyDirectoryString(PUNICODE_STRING UnsafeTarget, PUNICODE_STRING Source, PUCHAR *Buffer) -{ - UNICODE_STRING Target; - NTSTATUS Status; - WCHAR NullWchar; - - Target.Length = Source->Length; - Target.MaximumLength = (Source->Length + sizeof (WCHAR)); - Target.Buffer = (PWCHAR) *Buffer; - Status = MmCopyToCaller(UnsafeTarget, &Target, sizeof(UNICODE_STRING)); - if (! NT_SUCCESS(Status)) - { - return Status; - } - Status = MmCopyToCaller(*Buffer, Source->Buffer, Source->Length); - if (! NT_SUCCESS(Status)) - { - return Status; - } - *Buffer += Source->Length; - NullWchar = L'\0'; - Status = MmCopyToCaller(*Buffer, &NullWchar, sizeof(WCHAR)); - if (! NT_SUCCESS(Status)) - { - return Status; - } - *Buffer += sizeof(WCHAR); - - return STATUS_SUCCESS; + Status = ObOpenObjectByName(ObjectAttributes, + ObDirectoryType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hDirectory); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *DirectoryHandle = hDirectory; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; } @@ -169,202 +160,237 @@ NtQueryDirectoryObject (IN HANDLE DirectoryHandle, IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan, - IN OUT PULONG UnsafeContext, - OUT PULONG UnsafeReturnLength OPTIONAL) + IN OUT PULONG Context, + OUT PULONG ReturnLength OPTIONAL) { - PDIRECTORY_OBJECT dir = NULL; - PLIST_ENTRY current_entry = NULL; - PLIST_ENTRY start_entry; - POBJECT_HEADER current = NULL; - NTSTATUS Status = STATUS_SUCCESS; - ULONG DirectoryCount = 0; - ULONG DirectoryIndex = 0; - PDIRECTORY_BASIC_INFORMATION current_odi = (PDIRECTORY_BASIC_INFORMATION) Buffer; - DIRECTORY_BASIC_INFORMATION ZeroOdi; - PUCHAR FirstFree = (PUCHAR) Buffer; - ULONG Context; - ULONG RequiredSize; - ULONG NewValue; - KIRQL OldLevel; + PDIRECTORY_OBJECT Directory; + KPROCESSOR_MODE PreviousMode; + ULONG SkipEntries = 0; + ULONG NextEntry = 0; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); - DPRINT("NtQueryDirectoryObject(DirectoryHandle %x)\n", DirectoryHandle); - - /* Check Context is not NULL */ - if (NULL == UnsafeContext) + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + /* a test showed that the Buffer pointer just has to be 16 bit aligned, + propably due to the fact that most information that needs to be copied + is unicode strings */ + ProbeForWrite(Buffer, + BufferLength, + sizeof(WCHAR)); + ProbeForWrite(Context, + sizeof(ULONG), + sizeof(ULONG)); + if(!RestartScan) { - return STATUS_INVALID_PARAMETER; + SkipEntries = *Context; } - - /* Reference the DIRECTORY_OBJECT */ - Status = ObReferenceObjectByHandle(DirectoryHandle, - DIRECTORY_QUERY, - ObDirectoryType, - UserMode, - (PVOID*)&dir, - NULL); - if (!NT_SUCCESS(Status)) + if(ReturnLength != NULL) { - return Status; + ProbeForWrite(ReturnLength, + sizeof(ULONG), + sizeof(ULONG)); } - - KeAcquireSpinLock(&dir->Lock, &OldLevel); - - /* - * Optionally, skip over some entries at the start of the directory - * (use *ObjectIndex value) - */ - start_entry = dir->head.Flink; - if (! RestartScan) - { - register ULONG EntriesToSkip; - - Status = MmCopyFromCaller(&Context, UnsafeContext, sizeof(ULONG)); - if (! NT_SUCCESS(Status)) - { - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); - return Status; - } - EntriesToSkip = Context; - - CHECKPOINT; - - for (; 0 != EntriesToSkip-- && start_entry != &dir->head; - start_entry = start_entry->Flink) - { - ; - } - if ((0 != EntriesToSkip) && (start_entry == &dir->head)) - { - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); - return STATUS_NO_MORE_ENTRIES; - } - } - - /* - * Compute number of entries that we will copy into the buffer and - * the total size of all entries (even if larger than the buffer size) - */ - DirectoryCount = 0; - /* For the end sentenil */ - RequiredSize = sizeof(DIRECTORY_BASIC_INFORMATION); - for (current_entry = start_entry; - current_entry != &dir->head; - current_entry = current_entry->Flink) - { - current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry); - - RequiredSize += sizeof(DIRECTORY_BASIC_INFORMATION) + - current->Name.Length + sizeof(WCHAR) + - current->ObjectType->TypeName.Length + sizeof(WCHAR); - if (RequiredSize <= BufferLength && - (! ReturnSingleEntry || DirectoryCount < 1)) - { - DirectoryCount++; - } - } - - /* - * If there's no room to even copy a single entry then return error - * status. - */ - if (0 == DirectoryCount && - !(IsListEmpty(&dir->head) && BufferLength >= RequiredSize)) - { - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); - if (NULL != UnsafeReturnLength) - { - Status = MmCopyToCaller(UnsafeReturnLength, &RequiredSize, sizeof(ULONG)); - } - return NT_SUCCESS(Status) ? STATUS_BUFFER_TOO_SMALL : Status; - } - - /* - * Move FirstFree to point to the Unicode strings area - */ - FirstFree += (DirectoryCount + 1) * sizeof(DIRECTORY_BASIC_INFORMATION); - - /* Scan the directory */ - current_entry = start_entry; - for (DirectoryIndex = 0; DirectoryIndex < DirectoryCount; DirectoryIndex++) - { - current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry); - - /* - * Copy the current directory entry's data into the buffer - * and update the OBJDIR_INFORMATION entry in the array. - */ - /* --- Object's name --- */ - Status = CopyDirectoryString(¤t_odi->ObjectName, ¤t->Name, &FirstFree); - if (! NT_SUCCESS(Status)) - { - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); - return Status; - } - /* --- Object type's name --- */ - Status = CopyDirectoryString(¤t_odi->ObjectTypeName, ¤t->ObjectType->TypeName, &FirstFree); - if (! NT_SUCCESS(Status)) - { - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); - return Status; - } - - /* Next entry in the array */ - current_odi++; - /* Next object in the directory */ - current_entry = current_entry->Flink; } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; - /* - * Don't need dir object anymore - */ - KeReleaseSpinLock(&dir->Lock, OldLevel); - ObDereferenceObject(dir); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryDirectoryObject failed, Status: 0x%x\n", Status); + return Status; + } + } + else if(!RestartScan) + { + SkipEntries = *Context; + } + + Status = ObReferenceObjectByHandle(DirectoryHandle, + DIRECTORY_QUERY, + ObDirectoryType, + PreviousMode, + (PVOID*)&Directory, + NULL); + if(NT_SUCCESS(Status)) + { + PVOID TemporaryBuffer = ExAllocatePool(PagedPool, + BufferLength); + if(TemporaryBuffer != NULL) + { + POBJECT_HEADER EntryHeader; + PLIST_ENTRY ListEntry; + KIRQL OldLevel; + ULONG RequiredSize = 0; + ULONG nDirectories = 0; + POBJECT_DIRECTORY_INFORMATION DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer; + + Status = STATUS_NO_MORE_ENTRIES; - /* Terminate with all zero entry */ - memset(&ZeroOdi, '\0', sizeof(DIRECTORY_BASIC_INFORMATION)); - Status = MmCopyToCaller(current_odi, &ZeroOdi, sizeof(DIRECTORY_BASIC_INFORMATION)); - if (! NT_SUCCESS(Status)) + KeAcquireSpinLock(&Directory->Lock, &OldLevel); + + for(ListEntry = Directory->head.Flink; + ListEntry != &Directory->head; + ListEntry = ListEntry->Flink) { - return Status; + NextEntry++; + if(SkipEntries == 0) + { + PUNICODE_STRING Name, Type; + ULONG EntrySize; + + EntryHeader = CONTAINING_RECORD(ListEntry, OBJECT_HEADER, Entry); + + /* calculate the size of the required buffer space for this entry */ + Name = (EntryHeader->Name.Length != 0 ? &EntryHeader->Name : NULL); + Type = &EntryHeader->ObjectType->TypeName; + EntrySize = sizeof(OBJECT_DIRECTORY_INFORMATION) + + ((Name != NULL) ? ((ULONG)Name->Length + sizeof(WCHAR)) : 0) + + (ULONG)EntryHeader->ObjectType->TypeName.Length + sizeof(WCHAR); + + if(RequiredSize + EntrySize <= BufferLength) + { + /* the buffer is large enough to receive this entry. It would've + been much easier if the strings were directly appended to the + OBJECT_DIRECTORY_INFORMATION structured written into the buffer */ + if(Name != NULL) + DirInfo->ObjectName = *Name; + else + { + DirInfo->ObjectName.Length = DirInfo->ObjectName.MaximumLength = 0; + DirInfo->ObjectName.Buffer = NULL; + } + DirInfo->ObjectTypeName = *Type; + + nDirectories++; + RequiredSize += EntrySize; + + Status = STATUS_SUCCESS; + + if(ReturnSingleEntry) + { + /* we're only supposed to query one entry, so bail and copy the + strings to the buffer */ + break; + } + DirInfo++; + } + else + { + if(ReturnSingleEntry) + { + /* the buffer is too small, so return the number of bytes that + would've been required for this query */ + RequiredSize += EntrySize; + Status = STATUS_BUFFER_TOO_SMALL; + } + + /* we couldn't query this entry, so leave the index that will be stored + in Context to this entry so the caller can query it the next time + he queries (hopefully with a buffer that is large enough then...) */ + NextEntry--; + + /* just copy the entries that fit into the buffer */ + break; + } + } + else + { + /* skip the entry */ + SkipEntries--; + } + } + + if(!ReturnSingleEntry && ListEntry != &Directory->head) + { + /* there are more entries to enumerate but the buffer is already full. + only tell this to the user if he queries multiple entries */ + Status = STATUS_MORE_ENTRIES; } - /* - * Store current index in Context - */ - if (RestartScan) + if(NT_SUCCESS(Status)) { - Context = DirectoryCount; + if(nDirectories > 0) + { + _SEH_TRY + { + POBJECT_DIRECTORY_INFORMATION DestDirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer; + PWSTR strbuf = (PWSTR)((POBJECT_DIRECTORY_INFORMATION)Buffer + nDirectories); + + /* copy all OBJECT_DIRECTORY_INFORMATION structures to the buffer and + just append all strings (whose pointers are stored in the buffer!) + and replace the pointers */ + for(DirInfo = (POBJECT_DIRECTORY_INFORMATION)TemporaryBuffer; + nDirectories > 0; + nDirectories--, DirInfo++, DestDirInfo++) + { + if(DirInfo->ObjectName.Length > 0) + { + DestDirInfo->ObjectName.Length = DirInfo->ObjectName.Length; + DestDirInfo->ObjectName.MaximumLength = DirInfo->ObjectName.MaximumLength; + DestDirInfo->ObjectName.Buffer = strbuf; + RtlCopyMemory(strbuf, + DirInfo->ObjectName.Buffer, + DirInfo->ObjectName.Length); + /* NULL-terminate the string */ + strbuf[DirInfo->ObjectName.Length / sizeof(WCHAR)] = L'\0'; + strbuf += (DirInfo->ObjectName.Length / sizeof(WCHAR)) + 1; + } + + DestDirInfo->ObjectTypeName.Length = DirInfo->ObjectTypeName.Length; + DestDirInfo->ObjectTypeName.MaximumLength = DirInfo->ObjectTypeName.MaximumLength; + DestDirInfo->ObjectTypeName.Buffer = strbuf; + RtlCopyMemory(strbuf, + DirInfo->ObjectTypeName.Buffer, + DirInfo->ObjectTypeName.Length); + /* NULL-terminate the string */ + strbuf[DirInfo->ObjectTypeName.Length / sizeof(WCHAR)] = L'\0'; + strbuf += (DirInfo->ObjectTypeName.Length / sizeof(WCHAR)) + 1; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } } + + KeReleaseSpinLock(&Directory->Lock, OldLevel); + ObDereferenceObject(Directory); + + ExFreePool(TemporaryBuffer); + + if(NT_SUCCESS(Status) || ReturnSingleEntry) + { + _SEH_TRY + { + *Context = NextEntry; + if(ReturnLength != NULL) + { + *ReturnLength = RequiredSize; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } else - { - Context += DirectoryCount; - } - Status = MmCopyToCaller(UnsafeContext, &Context, sizeof(ULONG)); - if (! NT_SUCCESS(Status)) - { - return Status; - } - - /* - * Report to the caller how much bytes - * we wrote in the user buffer. - */ - if (NULL != UnsafeReturnLength) - { - NewValue = FirstFree - (PUCHAR) Buffer; - Status = MmCopyToCaller(UnsafeReturnLength, &NewValue, sizeof(ULONG)); - if (! NT_SUCCESS(Status)) - { - return Status; - } - } - - return Status; + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + return Status; } @@ -396,43 +422,69 @@ NtCreateDirectoryObject (OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes) { - PDIRECTORY_OBJECT DirectoryObject; - NTSTATUS Status; - + PDIRECTORY_OBJECT Directory; + HANDLE hDirectory; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, " - "DesiredAccess %x, ObjectAttributes %x, " - "ObjectAttributes->ObjectName %wZ)\n", - DirectoryHandle, DesiredAccess, ObjectAttributes, - ObjectAttributes->ObjectName); + "DesiredAccess %x, ObjectAttributes %x\n", + DirectoryHandle, DesiredAccess, ObjectAttributes); - Status = NtOpenDirectoryObject (DirectoryHandle, - DesiredAccess, - ObjectAttributes); + PreviousMode = ExGetPreviousMode(); - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + if(PreviousMode != KernelMode) { - Status = ObCreateObject (ExGetPreviousMode(), - ObDirectoryType, - ObjectAttributes, - ExGetPreviousMode(), - NULL, - sizeof(DIRECTORY_OBJECT), - 0, - 0, - (PVOID*)&DirectoryObject); - if (!NT_SUCCESS(Status)) - { - return Status; - } + _SEH_TRY + { + ProbeForWrite(DirectoryHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; - Status = ObInsertObject ((PVOID)DirectoryObject, - NULL, - DesiredAccess, - 0, - NULL, - DirectoryHandle); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateDirectoryObject failed, Status: 0x%x\n", Status); + return Status; + } + } - ObDereferenceObject(DirectoryObject); + Status = ObCreateObject(PreviousMode, + ObDirectoryType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(DIRECTORY_OBJECT), + 0, + 0, + (PVOID*)&Directory); + if(NT_SUCCESS(Status)) + { + Status = ObInsertObject((PVOID)Directory, + NULL, + DesiredAccess, + 0, + NULL, + &hDirectory); + ObDereferenceObject(Directory); + + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *DirectoryHandle = hDirectory; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } } return Status; diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index 3d48c98769f..7e2306a3ddd 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -353,13 +353,7 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, } KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); - if (!((ULONG_PTR)SourceHandleEntry->ObjectBody & OB_HANDLE_FLAG_INHERIT)) - { - ObDereferenceObject(TargetProcess); - ObDereferenceObject(SourceProcess); - ObDereferenceObject(ObjectBody); - return STATUS_INVALID_HANDLE; - } + ObCreateHandle(TargetProcess, ObjectBody, DesiredAccess, diff --git a/reactos/ntoskrnl/ob/namespc.c b/reactos/ntoskrnl/ob/namespc.c index 605596b23fe..fc179d003ac 100644 --- a/reactos/ntoskrnl/ob/namespc.c +++ b/reactos/ntoskrnl/ob/namespc.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ob/namespc.c * PURPOSE: Manages the system namespace - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * 22/05/98: Created + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ***************************************************************/ @@ -196,7 +195,7 @@ ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, { KIRQL oldlvl; - RtlCreateUnicodeString(&Header->Name, Name); + RtlpCreateUnicodeString(&Header->Name, Name, NonPagedPool); Header->Parent = Parent; KeAcquireSpinLock(&Parent->Lock, &oldlvl); @@ -376,8 +375,8 @@ ObInit(VOID) ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T'); ObDirectoryType->TotalObjects = 0; ObDirectoryType->TotalHandles = 0; - ObDirectoryType->MaxObjects = ULONG_MAX; - ObDirectoryType->MaxHandles = ULONG_MAX; + ObDirectoryType->PeakObjects = 0; + ObDirectoryType->PeakHandles = 0; ObDirectoryType->PagedPoolCharge = 0; ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT); ObDirectoryType->Mapping = &ObpDirectoryMapping; @@ -401,8 +400,8 @@ ObInit(VOID) ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T'); ObTypeObjectType->TotalObjects = 0; ObTypeObjectType->TotalHandles = 0; - ObTypeObjectType->MaxObjects = ULONG_MAX; - ObTypeObjectType->MaxHandles = ULONG_MAX; + ObTypeObjectType->PeakObjects = 0; + ObTypeObjectType->PeakHandles = 0; ObTypeObjectType->PagedPoolCharge = 0; ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT); ObTypeObjectType->Mapping = &ObpTypeMapping; diff --git a/reactos/ntoskrnl/ob/ntobj.c b/reactos/ntoskrnl/ob/ntobj.c index 40ff67643c9..91d9b86a872 100644 --- a/reactos/ntoskrnl/ob/ntobj.c +++ b/reactos/ntoskrnl/ob/ntobj.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ob/ntobj.c - * PURPOSE: User mode interface to object manager - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 10/06/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/ntobj.c + * PURPOSE: User mode interface to object manager + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -206,9 +205,26 @@ NtQueryObject (IN HANDLE ObjectHandle, } +/********************************************************************** + * NAME PRIVATE + * ObpSetPermanentObject/2 + * + * DESCRIPTION + * Fast general purpose routine to set an object's permanent + * attribute, given a pointer to the object's body. + */ +VOID FASTCALL +ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent) +{ + POBJECT_HEADER ObjectHeader; + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader->Permanent = Permanent; +} + /********************************************************************** * NAME EXPORTED - * ObMakeTemporaryObject + * ObMakeTemporaryObject/1 * * DESCRIPTION * @@ -223,10 +239,7 @@ NtQueryObject (IN HANDLE ObjectHandle, VOID STDCALL ObMakeTemporaryObject(IN PVOID ObjectBody) { - POBJECT_HEADER ObjectHeader; - - ObjectHeader = BODY_TO_HEADER(ObjectBody); - ObjectHeader->Permanent = FALSE; + ObpSetPermanentObject (ObjectBody, FALSE); } @@ -245,25 +258,23 @@ ObMakeTemporaryObject(IN PVOID ObjectBody) NTSTATUS STDCALL NtMakeTemporaryObject(IN HANDLE ObjectHandle) { - POBJECT_HEADER ObjectHeader; - PVOID Object; + PVOID ObjectBody; NTSTATUS Status; Status = ObReferenceObjectByHandle(ObjectHandle, 0, NULL, (KPROCESSOR_MODE)KeGetPreviousMode(), - &Object, + &ObjectBody, NULL); if (Status != STATUS_SUCCESS) { return Status; } - ObjectHeader = BODY_TO_HEADER(Object); - ObjectHeader->Permanent = FALSE; + ObpSetPermanentObject (ObjectBody, FALSE); - ObDereferenceObject(Object); + ObDereferenceObject(ObjectBody); return STATUS_SUCCESS; } @@ -271,7 +282,7 @@ NtMakeTemporaryObject(IN HANDLE ObjectHandle) /********************************************************************** * NAME EXPORTED - * NtMakePermanentObject + * NtMakePermanentObject/1 * * DESCRIPTION * @@ -286,25 +297,23 @@ NtMakeTemporaryObject(IN HANDLE ObjectHandle) NTSTATUS STDCALL NtMakePermanentObject(IN HANDLE ObjectHandle) { - POBJECT_HEADER ObjectHeader; - PVOID Object; + PVOID ObjectBody; NTSTATUS Status; Status = ObReferenceObjectByHandle(ObjectHandle, 0, NULL, (KPROCESSOR_MODE)KeGetPreviousMode(), - &Object, + &ObjectBody, NULL); if (Status != STATUS_SUCCESS) { return Status; } - ObjectHeader = BODY_TO_HEADER(Object); - ObjectHeader->Permanent = TRUE; + ObpSetPermanentObject (ObjectBody, TRUE); - ObDereferenceObject(Object); + ObDereferenceObject(ObjectBody); return STATUS_SUCCESS; } diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index 48a65b2f340..b065b353377 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -1,14 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ob/object.c - * PURPOSE: Implements generic object managment functions - * PROGRAMMERS David Welch (welch@cwcom.net), Skywing (skywing@valhallalegends.com) - * UPDATE HISTORY: - * 10/06/98: Created - * 09/13/03: Fixed various ObXxx routines to not call retention - * checks directly at a raised IRQL. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/object.c + * PURPOSE: Implements generic object managment functions + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Skywing (skywing@valhallalegends.com) */ /* INCLUDES *****************************************************************/ @@ -39,6 +37,276 @@ POBJECT_HEADER BODY_TO_HEADER(PVOID body) return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); } +NTSTATUS +ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL, + OUT PUNICODE_STRING ObjectName OPTIONAL) +{ + OBJECT_ATTRIBUTES AttributesCopy; + NTSTATUS Status = STATUS_SUCCESS; + + /* at least one output parameter must be != NULL! */ + ASSERT(CapturedObjectAttributes != NULL || ObjectName != NULL); + + if(ObjectAttributes == NULL) + { + /* we're going to return STATUS_SUCCESS! */ + goto failbasiccleanup; + } + + if(AccessMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(ObjectAttributes, + sizeof(ObjectAttributes), + sizeof(ULONG)); + /* make a copy on the stack */ + AttributesCopy = *ObjectAttributes; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n"); + goto failbasiccleanup; + } + } + else if(!CaptureIfKernel) + { + if(ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) + { + if(ObjectName != NULL) + { + /* we don't have to capture any memory, the caller considers the passed data + as valid */ + if(ObjectAttributes->ObjectName != NULL) + { + *ObjectName = *ObjectAttributes->ObjectName; + } + else + { + ObjectName->Length = ObjectName->MaximumLength = 0; + ObjectName->Buffer = NULL; + } + } + if(CapturedObjectAttributes != NULL) + { + CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory; + CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes; + CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor; + } + + return STATUS_SUCCESS; + } + else + { + Status = STATUS_INVALID_PARAMETER; + goto failbasiccleanup; + } + } + else + { + AttributesCopy = *ObjectAttributes; + } + + /* if Length isn't as expected, bail with an invalid parameter status code so + the caller knows he passed garbage... */ + if(AttributesCopy.Length != sizeof(OBJECT_ATTRIBUTES)) + { + Status = STATUS_INVALID_PARAMETER; + goto failbasiccleanup; + } + + if(CapturedObjectAttributes != NULL) + { + CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory; + CapturedObjectAttributes->Attributes = AttributesCopy.Attributes; + + if(AttributesCopy.SecurityDescriptor != NULL) + { + Status = SeCaptureSecurityDescriptor(AttributesCopy.SecurityDescriptor, + AccessMode, + PoolType, + TRUE, + &CapturedObjectAttributes->SecurityDescriptor); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Unable to capture the security descriptor!!!\n"); + goto failbasiccleanup; + } + } + else + { + CapturedObjectAttributes->SecurityDescriptor = NULL; + } + } + + if(ObjectName != NULL) + { + if(AttributesCopy.ObjectName != NULL) + { + UNICODE_STRING OriginalCopy; + + if(AccessMode != KernelMode) + { + _SEH_TRY + { + /* probe the ObjectName structure and make a local stack copy of it */ + ProbeForRead(AttributesCopy.ObjectName, + sizeof(UNICODE_STRING), + sizeof(ULONG)); + OriginalCopy = *AttributesCopy.ObjectName; + if(OriginalCopy.Length > 0) + { + ProbeForRead(OriginalCopy.Buffer, + OriginalCopy.Length, + sizeof(WCHAR)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + if(OriginalCopy.Length > 0) + { + ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR); + ObjectName->Buffer = ExAllocatePool(PoolType, + ObjectName->MaximumLength); + if(ObjectName->Buffer != NULL) + { + _SEH_TRY + { + /* no need to probe OriginalCopy.Buffer again, we already did that + when capturing the UNICODE_STRING structure itself */ + RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length); + ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0'; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + DPRINT1("ObpCaptureObjectAttributes failed to copy the unicode string!\n"); + } + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */) + { + /* if the caller specified a root directory, there must be an object name! */ + Status = STATUS_OBJECT_NAME_INVALID; + } + } + else + { + DPRINT1("ObpCaptureObjectAttributes failed to probe the object name UNICODE_STRING structure!\n"); + } + } + else /* AccessMode == KernelMode */ + { + OriginalCopy = *AttributesCopy.ObjectName; + + if(OriginalCopy.Length > 0) + { + ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR); + ObjectName->Buffer = ExAllocatePool(PoolType, + ObjectName->MaximumLength); + if(ObjectName->Buffer != NULL) + { + RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length); + ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0'; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */) + { + /* if the caller specified a root directory, there must be an object name! */ + Status = STATUS_OBJECT_NAME_INVALID; + } + } + } + else + { + ObjectName->Length = ObjectName->MaximumLength = 0; + ObjectName->Buffer = NULL; + } + } + + if(!NT_SUCCESS(Status)) + { + if(ObjectName->Buffer) + { + ExFreePool(ObjectName->Buffer); + } + if(CapturedObjectAttributes != NULL) + { + /* cleanup allocated resources */ + SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor, + AccessMode, + TRUE); + } + +failbasiccleanup: + if(ObjectName != NULL) + { + ObjectName->Length = ObjectName->MaximumLength = 0; + ObjectName->Buffer = NULL; + } + if(CapturedObjectAttributes != NULL) + { + RtlZeroMemory(CapturedObjectAttributes, sizeof(CAPTURED_OBJECT_ATTRIBUTES)); + } + } + + return Status; +} + + +VOID +ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL, + IN PUNICODE_STRING ObjectName OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN BOOLEAN CaptureIfKernel) +{ + /* WARNING - You need to pass the same parameters to this function as you passed + to ObpCaptureObjectAttributes() to avoid memory leaks */ + if(AccessMode != KernelMode || CaptureIfKernel) + { + if(CapturedObjectAttributes != NULL && + CapturedObjectAttributes->SecurityDescriptor != NULL) + { + ExFreePool(CapturedObjectAttributes->SecurityDescriptor); + CapturedObjectAttributes->SecurityDescriptor = NULL; + } + if(ObjectName != NULL && + ObjectName->Length > 0) + { + ExFreePool(ObjectName->Buffer); + } + } +} + /********************************************************************** * NAME PRIVATE @@ -185,7 +453,7 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, } if (current) - RtlCreateUnicodeString (RemainingPath, current); + RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool); RtlFreeUnicodeString (&PathString); *ReturnedObject = CurrentObject; @@ -344,6 +612,27 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, SECURITY_SUBJECT_CONTEXT SubjectContext; ASSERT_IRQL(APC_LEVEL); + + if(ObjectAttributesAccessMode == UserMode && ObjectAttributes != NULL) + { + Status = STATUS_SUCCESS; + _SEH_TRY + { + ProbeForRead(ObjectAttributes, + sizeof(OBJECT_ATTRIBUTES), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n", Type, ObjectAttributes, Object); diff --git a/reactos/ntoskrnl/ob/sdcache.c b/reactos/ntoskrnl/ob/sdcache.c index dc5f0fc5ec0..f06b3f9d1dc 100644 --- a/reactos/ntoskrnl/ob/sdcache.c +++ b/reactos/ntoskrnl/ob/sdcache.c @@ -2,11 +2,10 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/kill.c - * PURPOSE: Terminating a thread - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * FILE: ntoskrnl/ob/sdcache.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ob/security.c b/reactos/ntoskrnl/ob/security.c index 4d1000a9c18..38de6a66fd4 100644 --- a/reactos/ntoskrnl/ob/security.c +++ b/reactos/ntoskrnl/ob/security.c @@ -1,11 +1,11 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: ntoskrnl/ob/security.c - * PROGRAMER: ? - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/security.c + * PURPOSE: Security manager + * + * PROGRAMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ob/symlink.c b/reactos/ntoskrnl/ob/symlink.c index 091e54d9550..67681c31f44 100644 --- a/reactos/ntoskrnl/ob/symlink.c +++ b/reactos/ntoskrnl/ob/symlink.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ob/symlink.c * PURPOSE: Implements symbolic links - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -165,8 +164,8 @@ ObInitSymbolicLinkImplementation (VOID) ObSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T'); ObSymbolicLinkType->TotalObjects = 0; ObSymbolicLinkType->TotalHandles = 0; - ObSymbolicLinkType->MaxObjects = ULONG_MAX; - ObSymbolicLinkType->MaxHandles = ULONG_MAX; + ObSymbolicLinkType->PeakObjects = 0; + ObSymbolicLinkType->PeakHandles = 0; ObSymbolicLinkType->PagedPoolCharge = 0; ObSymbolicLinkType->NonpagedPoolCharge = sizeof(SYMLINK_OBJECT); ObSymbolicLinkType->Mapping = &ObpSymbolicLinkMapping; @@ -256,7 +255,7 @@ NtCreateSymbolicLinkObject(OUT PHANDLE LinkHandle, DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer); - NtQuerySystemTime (&SymbolicLink->CreateTime); + ZwQuerySystemTime (&SymbolicLink->CreateTime); DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__); ObDereferenceObject(SymbolicLink); diff --git a/reactos/ntoskrnl/po/power.c b/reactos/ntoskrnl/po/power.c index 453ca4448f6..b50bd0912d5 100644 --- a/reactos/ntoskrnl/po/power.c +++ b/reactos/ntoskrnl/po/power.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/po/power.c * PURPOSE: Power Manager - * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) - * UPDATE HISTORY: - * 20/08/1999 EA Created - * 16/04/2001 CSH Stubs added + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ #include @@ -245,8 +227,41 @@ NtPowerInformation( IN ULONG OutputBufferLength ) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + + DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, " + "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n", + PowerInformationLevel, + InputBuffer, InputBufferLength, + OutputBuffer, OutputBufferLength); + switch (PowerInformationLevel) + { + case SystemBatteryState: + { + PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer; + + if (InputBuffer != NULL) + return STATUS_INVALID_PARAMETER; + if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE)) + return STATUS_BUFFER_TOO_SMALL; + + /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */ + RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE)); + BatteryState->EstimatedTime = (ULONG)-1; + + Status = STATUS_SUCCESS; + break; + } + + default: + Status = STATUS_NOT_IMPLEMENTED; + DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n", + PowerInformationLevel); + for (;;); + break; + } + + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/ps/cid.c b/reactos/ntoskrnl/ps/cid.c index 2d6da148b9f..e38842500f5 100644 --- a/reactos/ntoskrnl/ps/cid.c +++ b/reactos/ntoskrnl/ps/cid.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/clientid.c - * PURPOSE: Client ID (CID) management - * PROGRAMMER: Thomas Weidenmueller - * REVISION HISTORY: - * 9/20/2004: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/cid.c + * PURPOSE: Client ID (CID) management + * + * PROGRAMMERS: Thomas Weidenmueller */ /* INCLUDES ******************************************************************/ @@ -70,7 +69,7 @@ PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle) cido->Obj.Object = Object; KeAcquireSpinLock(&CidLock, &oldIrql); - cido->Handle = (HANDLE)(++CidCounter); + cido->Handle = (HANDLE)((ULONG_PTR)(++CidCounter) << 2); InsertTailList(&CidHead, &cido->Entry); KeReleaseSpinLock(&CidLock, oldIrql); diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index c61f52bbd65..d1256576320 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -1,14 +1,13 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/thread.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 23/06/98: Created - * 12/10/99: Phillip Susi: Thread priorities, and APC work - * 09/08/03: Skywing: ThreadEventPair support (delete) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/create.c + * PURPOSE: Thread managment + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi + * Skywing */ /* @@ -58,7 +57,7 @@ PsAssignImpersonationToken(PETHREAD Thread, { return(Status); } - ImpersonationLevel = Token->ImpersonationLevel; + ImpersonationLevel = SeTokenImpersonationLevel(Token); } else { @@ -134,7 +133,7 @@ PsImpersonateClient (IN PETHREAD Thread, sizeof(PS_IMPERSONATION_INFORMATION)); } - Thread->ImpersonationInfo->Level = ImpersonationLevel; + Thread->ImpersonationInfo->ImpersonationLevel = ImpersonationLevel; Thread->ImpersonationInfo->CopyOnOpen = CopyOnOpen; Thread->ImpersonationInfo->EffectiveOnly = EffectiveOnly; Thread->ImpersonationInfo->Token = Token; @@ -167,7 +166,7 @@ PsReferenceEffectiveToken(PETHREAD Thread, Token = Thread->ImpersonationInfo->Token; *TokenType = TokenImpersonation; *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; - *Level = Thread->ImpersonationInfo->Level; + *Level = Thread->ImpersonationInfo->ImpersonationLevel; } return(Token); } @@ -178,56 +177,73 @@ NtImpersonateThread(IN HANDLE ThreadHandle, IN HANDLE ThreadToImpersonateHandle, IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService) { + SECURITY_QUALITY_OF_SERVICE SafeServiceQoS; SECURITY_CLIENT_CONTEXT ClientContext; PETHREAD Thread; PETHREAD ThreadToImpersonate; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(SecurityQualityOfService, + sizeof(SECURITY_QUALITY_OF_SERVICE), + sizeof(ULONG)); + SafeServiceQoS = *SecurityQualityOfService; + SecurityQualityOfService = &SafeServiceQoS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } - Status = ObReferenceObjectByHandle (ThreadHandle, + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_IMPERSONATE, + PsThreadType, + PreviousMode, + (PVOID*)&Thread, + NULL); + if(NT_SUCCESS(Status)) + { + Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle, + THREAD_DIRECT_IMPERSONATION, + PsThreadType, + PreviousMode, + (PVOID*)&ThreadToImpersonate, + NULL); + if(NT_SUCCESS(Status)) + { + Status = SeCreateClientSecurity(ThreadToImpersonate, + SecurityQualityOfService, 0, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (!NT_SUCCESS (Status)) - { - return Status; + &ClientContext); + if(NT_SUCCESS(Status)) + { + SeImpersonateClient(&ClientContext, + Thread); + if(ClientContext.ClientToken != NULL) + { + ObDereferenceObject (ClientContext.ClientToken); + } + } + + ObDereferenceObject(ThreadToImpersonate); } + ObDereferenceObject(Thread); + } - Status = ObReferenceObjectByHandle (ThreadToImpersonateHandle, - 0, - PsThreadType, - UserMode, - (PVOID*)&ThreadToImpersonate, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Thread); - return Status; - } - - Status = SeCreateClientSecurity (ThreadToImpersonate, - SecurityQualityOfService, - 0, - &ClientContext); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (ThreadToImpersonate); - ObDereferenceObject (Thread); - return Status; - } - - SeImpersonateClient (&ClientContext, - Thread); - if (ClientContext.Token != NULL) - { - ObDereferenceObject (ClientContext.Token); - } - - ObDereferenceObject (ThreadToImpersonate); - ObDereferenceObject (Thread); - - return STATUS_SUCCESS; + return Status; } /* @@ -244,7 +260,7 @@ PsReferenceImpersonationToken(IN PETHREAD Thread, return NULL; } - *ImpersonationLevel = Thread->ImpersonationInfo->Level; + *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel; *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen; *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; ObReferenceObjectByPointer (Thread->ImpersonationInfo->Token, @@ -255,8 +271,11 @@ PsReferenceImpersonationToken(IN PETHREAD Thread, return Thread->ImpersonationInfo->Token; } +#ifdef PsDereferencePrimaryToken +#undef PsDereferenceImpersonationToken +#endif /* - * @unimplemented + * @implemented */ VOID STDCALL @@ -264,11 +283,16 @@ PsDereferenceImpersonationToken( IN PACCESS_TOKEN ImpersonationToken ) { - UNIMPLEMENTED; + if (ImpersonationToken) { + ObDereferenceObject(ImpersonationToken); + } } +#ifdef PsDereferencePrimaryToken +#undef PsDereferencePrimaryToken +#endif /* - * @unimplemented + * @implemented */ VOID STDCALL @@ -276,7 +300,7 @@ PsDereferencePrimaryToken( IN PACCESS_TOKEN PrimaryToken ) { - UNIMPLEMENTED; + ObDereferenceObject(PrimaryToken); } /* @@ -305,7 +329,7 @@ PsDisableImpersonation( ImpersonationState->Token = Thread->ImpersonationInfo->Token; ImpersonationState->CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen; ImpersonationState->EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly; - ImpersonationState->Level = Thread->ImpersonationInfo->Level; + ImpersonationState->Level = Thread->ImpersonationInfo->ImpersonationLevel; /* FIXME */ /* ExfReleasePushLock(&Thread->ThreadLock); */ @@ -397,7 +421,7 @@ PsInitializeThread(PEPROCESS Process, Status = ObCreateObject(UserMode, PsThreadType, ThreadAttributes, - UserMode, + KernelMode, NULL, sizeof(ETHREAD), 0, @@ -419,19 +443,6 @@ PsInitializeThread(PEPROCESS Process, } Thread->ThreadsProcess = Process; Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; - - Status = ObInsertObject ((PVOID)Thread, - NULL, - DesiredAccess, - 0, - NULL, - ThreadHandle); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Thread); - ObDereferenceObject (Process); - return Status; - } DPRINT("Thread = %x\n",Thread); @@ -464,8 +475,14 @@ PsInitializeThread(PEPROCESS Process, KeReleaseDispatcherDatabaseLock(oldIrql); *ThreadPtr = Thread; - - return(STATUS_SUCCESS); + + Status = ObInsertObject((PVOID)Thread, + NULL, + DesiredAccess, + 0, + NULL, + ThreadHandle); + return(Status); } @@ -639,17 +656,64 @@ NtCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, - OUT PCLIENT_ID Client, + OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended) { + HANDLE hThread; + CONTEXT SafeContext; + INITIAL_TEB SafeInitialTeb; PEPROCESS Process; PETHREAD Thread; PTEB TebBase; - NTSTATUS Status; PKAPC LdrInitApc; KIRQL oldIrql; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + if(ThreadContext == NULL) + { + return STATUS_INVALID_PARAMETER; + } + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(ThreadHandle, + sizeof(HANDLE), + sizeof(ULONG)); + if(ClientId != NULL) + { + ProbeForWrite(ClientId, + sizeof(CLIENT_ID), + sizeof(ULONG)); + } + ProbeForRead(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + SafeContext = *ThreadContext; + ThreadContext = &SafeContext; + ProbeForRead(InitialTeb, + sizeof(INITIAL_TEB), + sizeof(ULONG)); + SafeInitialTeb = *InitialTeb; + InitialTeb = &SafeInitialTeb; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", ThreadHandle,ThreadContext); @@ -657,7 +721,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_CREATE_THREAD, PsProcessType, - UserMode, + PreviousMode, (PVOID*)&Process, NULL); if(!NT_SUCCESS(Status)) @@ -667,7 +731,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Status = PsInitializeThread(Process, &Thread, - ThreadHandle, + &hThread, DesiredAccess, ObjectAttributes, FALSE); @@ -697,11 +761,6 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Thread->StartAddress = NULL; - if (Client != NULL) - { - *Client = Thread->Cid; - } - /* * Maybe send a message to the process's debugger */ @@ -740,11 +799,24 @@ NtCreateThread(OUT PHANDLE ThreadHandle, Thread->Tcb.Alerted[KernelMode] = TRUE; oldIrql = KeAcquireDispatcherDatabaseLock (); - PsUnblockThread(Thread, NULL); + PsUnblockThread(Thread, NULL, 0); KeReleaseDispatcherDatabaseLock(oldIrql); + _SEH_TRY + { + if(ClientId != NULL) + { + *ClientId = Thread->Cid; + } + *ThreadHandle = hThread; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; - return(STATUS_SUCCESS); + return Status; } @@ -806,9 +878,9 @@ PsCreateSystemThread(PHANDLE ThreadHandle, *ClientId=Thread->Cid; } - oldIrql = KeAcquireDispatcherDatabaseLock (); - PsUnblockThread(Thread, NULL); - KeReleaseDispatcherDatabaseLock(oldIrql); + oldIrql = KeAcquireDispatcherDatabaseLock (); + PsUnblockThread(Thread, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ps/debug.c b/reactos/ntoskrnl/ps/debug.c index 50b36b1adb5..0a74fe8cbc8 100644 --- a/reactos/ntoskrnl/ps/debug.c +++ b/reactos/ntoskrnl/ps/debug.c @@ -1,31 +1,12 @@ -/* - * ReactOS kernel - * Copyright (C) 2000, 1999, 1998 David Welch , - * Philip Susi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/debug.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 23/06/98: Created - * 12/10/99: Phillip Susi: Thread priorities, and APC work + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/debug.c + * PURPOSE: Thread managment + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi */ /* @@ -205,28 +186,43 @@ NtGetContextThread(IN HANDLE ThreadHandle, OUT PCONTEXT ThreadContext) { PETHREAD Thread; - NTSTATUS Status; CONTEXT Context; KAPC Apc; KEVENT Event; - NTSTATUS AStatus; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); - Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); - if (! NT_SUCCESS(Status)) + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) { return Status; } + } + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_GET_CONTEXT, PsThreadType, - UserMode, + PreviousMode, (PVOID*)&Thread, NULL); - if (! NT_SUCCESS(Status)) - { - return Status; - } - if (Thread == PsGetCurrentThread()) + if(NT_SUCCESS(Status)) + { + if(Thread == PsGetCurrentThread()) { /* * I don't know if trying to get your own context makes much @@ -234,15 +230,13 @@ NtGetContextThread(IN HANDLE ThreadHandle, */ KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context); - Status = STATUS_SUCCESS; } - else + else { KeInitializeEvent(&Event, NotificationEvent, - FALSE); - AStatus = STATUS_SUCCESS; - + FALSE); + KeInitializeApc(&Apc, &Thread->Tcb, OriginalApcEnvironment, @@ -253,7 +247,7 @@ NtGetContextThread(IN HANDLE ThreadHandle, (PVOID)&Context); if (!KeInsertQueueApc(&Apc, (PVOID)&Event, - (PVOID)&AStatus, + (PVOID)&Status, IO_NO_INCREMENT)) { Status = STATUS_THREAD_IS_TERMINATING; @@ -262,21 +256,27 @@ NtGetContextThread(IN HANDLE ThreadHandle, { Status = KeWaitForSingleObject(&Event, 0, - UserMode, + KernelMode, FALSE, NULL); - if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus)) - { - Status = AStatus; - } } } - if (NT_SUCCESS(Status)) + ObDereferenceObject(Thread); + + if(NT_SUCCESS(Status)) { - Status = MmCopyToCaller(ThreadContext, &Context, sizeof(Context)); + _SEH_TRY + { + *ThreadContext = Context; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - - ObDereferenceObject(Thread); + } + return Status; } @@ -310,29 +310,45 @@ NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext) { PETHREAD Thread; - NTSTATUS Status; KAPC Apc; KEVENT Event; - NTSTATUS AStatus; CONTEXT Context; - - Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); - if (! NT_SUCCESS(Status)) + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + Context = *ThreadContext; + ThreadContext = &Context; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) { return Status; } + } + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_SET_CONTEXT, PsThreadType, - UserMode, + PreviousMode, (PVOID*)&Thread, NULL); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - if (Thread == PsGetCurrentThread()) + if(NT_SUCCESS(Status)) + { + if (Thread == PsGetCurrentThread()) { /* * I don't know if trying to set your own context makes much @@ -340,14 +356,12 @@ NtSetContextThread(IN HANDLE ThreadHandle, */ KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame); - Status = STATUS_SUCCESS; } - else + else { KeInitializeEvent(&Event, NotificationEvent, FALSE); - AStatus = STATUS_SUCCESS; KeInitializeApc(&Apc, &Thread->Tcb, @@ -359,7 +373,7 @@ NtSetContextThread(IN HANDLE ThreadHandle, (PVOID)&Context); if (!KeInsertQueueApc(&Apc, (PVOID)&Event, - (PVOID)&AStatus, + (PVOID)&Status, IO_NO_INCREMENT)) { Status = STATUS_THREAD_IS_TERMINATING; @@ -368,17 +382,14 @@ NtSetContextThread(IN HANDLE ThreadHandle, { Status = KeWaitForSingleObject(&Event, 0, - UserMode, + KernelMode, FALSE, - NULL); - if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus)) - { - Status = AStatus; - } + NULL); } } - - ObDereferenceObject(Thread); + ObDereferenceObject(Thread); + } + return Status; } diff --git a/reactos/ntoskrnl/ps/i386/continue.c b/reactos/ntoskrnl/ps/i386/continue.c index 5b2cd8a027f..10d2c60650b 100644 --- a/reactos/ntoskrnl/ps/i386/continue.c +++ b/reactos/ntoskrnl/ps/i386/continue.c @@ -1,12 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/i386/continue.c - * PURPOSE: i386 implementation of NtContinue() - * PROGRAMMER: Royce Mitchell III, kjk_hyperion - * REVISION HISTORY: - * 29/06/04: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/i386/continue.c + * PURPOSE: i386 implementation of NtContinue() + * + * PROGRAMMERS: Royce Mitchell III, + * kjk_hyperion */ /* INCLUDES ****************************************************************/ @@ -15,10 +15,6 @@ #define NDEBUG #include -VOID -FASTCALL -KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame ); - VOID STDCALL KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount ); @@ -30,8 +26,9 @@ NtContinue ( IN PCONTEXT Context, IN BOOLEAN TestAlert) { - PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame; - PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; + PKTHREAD Thread = KeGetCurrentThread(); + PKTRAP_FRAME TrapFrame = Thread->TrapFrame; + PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; PFX_SAVE_AREA FxSaveArea; KIRQL oldIrql; @@ -65,12 +62,12 @@ NtContinue ( /* Put the floating point context into the thread's FX_SAVE_AREA * and make sure it is reloaded when needed. */ - FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KeGetCurrentThread()->InitialStack - sizeof(FX_SAVE_AREA)); + FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA)); if (KiContextToFxSaveArea(FxSaveArea, Context)) { - KeGetCurrentThread()->NpxState = NPX_STATE_VALID; + Thread->NpxState = NPX_STATE_VALID; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); - if (KeGetCurrentKPCR()->PrcbData.NpxThread == KeGetCurrentThread()) + if (KeGetCurrentKPCR()->PrcbData.NpxThread == Thread) { KeGetCurrentKPCR()->PrcbData.NpxThread = NULL; Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); @@ -82,7 +79,9 @@ NtContinue ( KeLowerIrql(oldIrql); } - KeRosTrapReturn ( TrapFrame, PrevTrapFrame ); + /* Restore the user context */ + Thread->TrapFrame = PrevTrapFrame; + __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame)); return STATUS_SUCCESS; /* this doesn't actually happen b/c KeRosTrapReturn() won't return */ } diff --git a/reactos/ntoskrnl/ps/idle.c b/reactos/ntoskrnl/ps/idle.c index 6fec7c96b30..c1d0b09e77a 100644 --- a/reactos/ntoskrnl/ps/idle.c +++ b/reactos/ntoskrnl/ps/idle.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/idle.c * PURPOSE: Using idle time - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ps/job.c b/reactos/ntoskrnl/ps/job.c index 6401ce4e2f0..8196f94a86a 100644 --- a/reactos/ntoskrnl/ps/job.c +++ b/reactos/ntoskrnl/ps/job.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/jobs.c + * FILE: ntoskrnl/ps/job.c * PURPOSE: Job Native Functions - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * UPDATE HISTORY: - * Created 16/07/04 + * + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ /* Note: Jobs are only supported on Win2K+ */ @@ -19,7 +19,7 @@ POBJECT_TYPE EXPORTED PsJobType = NULL; LIST_ENTRY PsJobListHead; -static KSPIN_LOCK PsJobListLock; +static FAST_MUTEX PsJobListLock; static GENERIC_MAPPING PiJobMapping = {STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY, STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_SECURITY_ATTRIBUTES, @@ -31,12 +31,23 @@ static GENERIC_MAPPING PiJobMapping = {STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY, VOID STDCALL PiDeleteJob(PVOID ObjectBody) { - KIRQL oldIrql; PEJOB Job = (PEJOB)ObjectBody; - KeAcquireSpinLock(&PsJobListLock, &oldIrql); - RemoveEntryList(&Job->JobLinks); - KeReleaseSpinLock(&PsJobListLock, oldIrql); + /* remove the reference to the completion port if associated */ + if(Job->CompletionPort != NULL) + { + ObDereferenceObject(Job->CompletionPort); + } + + /* unlink the job object */ + if(Job->JobLinks.Flink != NULL) + { + ExAcquireFastMutex(&PsJobListLock); + RemoveEntryList(&Job->JobLinks); + ExReleaseFastMutex(&PsJobListLock); + } + + ExDeleteResource(&Job->JobLock); } VOID INIT_FUNCTION @@ -47,8 +58,8 @@ PsInitJobManagment(VOID) PsJobType->Tag = TAG('E', 'J', 'O', 'B'); PsJobType->TotalObjects = 0; PsJobType->TotalHandles = 0; - PsJobType->MaxObjects = ULONG_MAX; - PsJobType->MaxHandles = ULONG_MAX; + PsJobType->PeakObjects = 0; + PsJobType->PeakHandles = 0; PsJobType->PagedPoolCharge = 0; PsJobType->NonpagedPoolCharge = sizeof(EJOB); PsJobType->Mapping = &PiJobMapping; @@ -68,9 +79,27 @@ PsInitJobManagment(VOID) ObpCreateTypeObject(PsJobType); InitializeListHead(&PsJobListHead); - KeInitializeSpinLock(&PsJobListLock); + ExInitializeFastMutex(&PsJobListLock); } +NTSTATUS +PspAssignProcessToJob(PEPROCESS Process, + PEJOB Job) +{ + DPRINT("PspAssignProcessToJob() is unimplemented!\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +PspTerminateJobObject(PEJOB Job, + KPROCESSOR_MODE AccessMode, + NTSTATUS ExitStatus) +{ + DPRINT("PspTerminateJobObject() is unimplemented!\n"); + return STATUS_NOT_IMPLEMENTED; +} + + /* * @unimplemented */ @@ -79,8 +108,80 @@ STDCALL NtAssignProcessToJobObject(HANDLE JobHandle, HANDLE ProcessHandle) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PEPROCESS Process; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + + PreviousMode = ExGetPreviousMode(); + + /* make sure we're having a handle with enough rights, especially the to + terminate the process. otherwise one could abuse the job objects to + terminate processes without having rights granted to do so! The reason + I open the process handle before the job handle is that a simple test showed + that it first complains about a invalid process handle! The other way around + would be simpler though... */ + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_TERMINATE, + PsProcessType, + PreviousMode, + (PVOID*)&Process, + NULL); + if(NT_SUCCESS(Status)) + { + if(Process->Job == NULL) + { + PEJOB Job; + + Status = ObReferenceObjectByHandle(JobHandle, + JOB_OBJECT_ASSIGN_PROCESS, + PsJobType, + PreviousMode, + (PVOID*)&Job, + NULL); + if(NT_SUCCESS(Status)) + { + /* lock the process so we can safely assign the process. Note that in the + meanwhile another thread could have assigned this process to a job! */ + + Status = PsLockProcess(Process, FALSE); + if(NT_SUCCESS(Status)) + { + if(Process->Job == NULL && Process->SessionId == Job->SessionId) + { + /* Just store the pointer to the job object in the process, we'll + assign it later. The reason we can't do this here is that locking + the job object might require it to wait, which is a bad thing + while holding the process lock! */ + Process->Job = Job; + } + else + { + /* process is already assigned to a job or session id differs! */ + Status = STATUS_ACCESS_DENIED; + } + PsUnlockProcess(Process); + + if(NT_SUCCESS(Status)) + { + /* let's actually assign the process to the job as we're not holding + the process lock anymore! */ + Status = PspAssignProcessToJob(Process, Job); + } + } + + ObDereferenceObject(Job); + } + } + else + { + /* process is already assigned to a job or session id differs! */ + Status = STATUS_ACCESS_DENIED; + } + + ObDereferenceObject(Process); + } + + return Status; } @@ -93,8 +194,99 @@ NtCreateJobObject(PHANDLE JobHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + HANDLE hJob; + PEJOB Job; + KPROCESSOR_MODE PreviousMode; + PEPROCESS CurrentProcess; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + CurrentProcess = PsGetCurrentProcess(); + + /* check for valid buffers */ + if(PreviousMode == UserMode) + { + _SEH_TRY + { + /* probe with 32bit alignment */ + ProbeForWrite(JobHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObCreateObject(PreviousMode, + PsJobType, + ObjectAttributes, + PreviousMode, + NULL, + sizeof(EJOB), + 0, + 0, + (PVOID*)&Job); + + if(NT_SUCCESS(Status)) + { + /* FIXME - Zero all fields as we don't yet implement all of them */ + RtlZeroMemory(Job, sizeof(EJOB)); + + /* make sure that early destruction doesn't attempt to remove the object from + the list before it even gets added! */ + Job->JobLinks.Flink = NULL; + + /* setup the job object */ + InitializeListHead(&Job->ProcessListHead); + Job->SessionId = CurrentProcess->SessionId; /* inherit the session id from the caller */ + + Status = ExInitializeResource(&Job->JobLock); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failed to initialize job lock!!!\n"); + ObDereferenceObject(Job); + return Status; + } + KeInitializeEvent(&Job->Event, NotificationEvent, FALSE); + + /* link the object into the global job list */ + ExAcquireFastMutex(&PsJobListLock); + InsertTailList(&PsJobListHead, &Job->JobLinks); + ExReleaseFastMutex(&PsJobListLock); + + Status = ObInsertObject(Job, + NULL, + DesiredAccess, + 0, + NULL, + &hJob); + if(NT_SUCCESS(Status)) + { + /* pass the handle back to the caller */ + _SEH_TRY + { + /* NOTE: if the caller passed invalid buffers to receive the handle it's his + own fault! the object will still be created and live... It's possible + to find the handle using ObFindHandleForObject()! */ + *JobHandle = hJob; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; } @@ -163,7 +355,7 @@ NtIsProcessInJob(IN HANDLE ProcessHandle, /* - * @unimplemented + * @implemented */ NTSTATUS STDCALL @@ -171,8 +363,58 @@ NtOpenJobObject(PHANDLE JobHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + KPROCESSOR_MODE PreviousMode; + HANDLE hJob; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + /* check for valid buffers */ + if(PreviousMode == UserMode) + { + _SEH_TRY + { + /* probe with 32bit alignment */ + ProbeForWrite(JobHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + if(NT_SUCCESS(Status)) + { + Status = ObOpenObjectByName(ObjectAttributes, + PsJobType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hJob); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *JobHandle = hJob; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + } + + return Status; } @@ -215,8 +457,27 @@ STDCALL NtTerminateJobObject(HANDLE JobHandle, NTSTATUS ExitStatus) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + KPROCESSOR_MODE PreviousMode; + PEJOB Job; + NTSTATUS Status; + + PreviousMode = ExGetPreviousMode(); + + Status = ObReferenceObjectByHandle(JobHandle, + JOB_OBJECT_TERMINATE, + PsJobType, + PreviousMode, + (PVOID*)&Job, + NULL); + if(NT_SUCCESS(Status)) + { + Status = PspTerminateJobObject(Job, + PreviousMode, + ExitStatus); + ObDereferenceObject(Job); + } + + return Status; } diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 253aa789ce5..273f12d5808 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/kill.c * PURPOSE: Terminating a thread - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -191,7 +190,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) oldIrql = KeAcquireDispatcherDatabaseLock(); CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; - KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader); + KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT); KeReleaseDispatcherDatabaseLock (oldIrql); /* The last thread shall close the door on exit */ @@ -239,6 +238,12 @@ PiTerminateThreadNormalRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) { + PETHREAD EThread = PsGetCurrentThread(); + if (EThread->HasTerminated) + { + /* Someone else has already called PsTerminateCurrentThread */ + return; + } PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus); } @@ -319,7 +324,7 @@ PiTerminateProcess(PEPROCESS Process, } OldIrql = KeAcquireDispatcherDatabaseLock (); Process->Pcb.DispatcherHeader.SignalState = TRUE; - KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader); + KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT); KeReleaseDispatcherDatabaseLock (OldIrql); ObDereferenceObject(Process); return(STATUS_SUCCESS); @@ -448,7 +453,7 @@ NtRegisterThreadTerminatePort(HANDLE PortHandle) Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS, - & LpcPortObjectType, + LpcPortObjectType, KeGetCurrentThread()->PreviousMode, (PVOID*)&TerminationPort, NULL); diff --git a/reactos/ntoskrnl/ps/locale.c b/reactos/ntoskrnl/ps/locale.c index cb0fd0d03e6..545cde0f667 100644 --- a/reactos/ntoskrnl/ps/locale.c +++ b/reactos/ntoskrnl/ps/locale.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/locale.c * PURPOSE: Locale support - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -65,7 +64,7 @@ PiInitDefaultLocale(VOID) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (NT_SUCCESS(Status)) @@ -73,7 +72,7 @@ PiInitDefaultLocale(VOID) /* Read system locale */ RtlRosInitUnicodeStringFromLiteral(&ValueName, L"Default"); - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueBuffer, @@ -98,7 +97,7 @@ PiInitDefaultLocale(VOID) /* Read install language id */ RtlRosInitUnicodeStringFromLiteral(&ValueName, L"InstallLanguage"); - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueBuffer, @@ -120,7 +119,7 @@ PiInitDefaultLocale(VOID) } } - NtClose(KeyHandle); + ZwClose(KeyHandle); } } @@ -161,12 +160,12 @@ PiInitThreadLocale(VOID) OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (NT_SUCCESS(Status)) { - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueBuffer, @@ -187,7 +186,7 @@ PiInitThreadLocale(VOID) PsDefaultThreadLocaleId = (LCID)LocaleValue; } } - NtClose(KeyHandle); + ZwClose(KeyHandle); } PsDefaultThreadLocaleInitialized = TRUE; @@ -280,14 +279,14 @@ NtSetDefaultLocale(IN BOOLEAN UserProfile, OBJ_CASE_INSENSITIVE, UserKey, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { if (UserKey != NULL) { - NtClose(UserKey); + ZwClose(UserKey); } return(Status); } @@ -306,17 +305,17 @@ NtSetDefaultLocale(IN BOOLEAN UserProfile, } ValueLength = (ValueLength + 1) * sizeof(WCHAR); - Status = NtSetValueKey(KeyHandle, + Status = ZwSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, ValueBuffer, ValueLength); - NtClose(KeyHandle); + ZwClose(KeyHandle); if (UserKey != NULL) { - NtClose(UserKey); + ZwClose(UserKey); } if (!NT_SUCCESS(Status)) @@ -378,7 +377,7 @@ NtQueryDefaultUILanguage(OUT PLANGID LanguageId) OBJ_CASE_INSENSITIVE, UserKey, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -389,15 +388,15 @@ NtQueryDefaultUILanguage(OUT PLANGID LanguageId) ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; - Status = NtQueryValueKey(KeyHandle, + Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueBuffer, VALUE_BUFFER_SIZE, &ValueLength); - NtClose(KeyHandle); - NtClose(UserKey); + ZwClose(KeyHandle); + ZwClose(UserKey); if (!NT_SUCCESS(Status) || ValueInfo->Type != REG_SZ) { @@ -471,12 +470,12 @@ NtSetDefaultUILanguage(IN LANGID LanguageId) UserHandle, NULL); - Status = NtOpenKey(&KeyHandle, + Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { - NtClose(UserHandle); + ZwClose(UserHandle); return Status; } @@ -485,15 +484,15 @@ NtSetDefaultUILanguage(IN LANGID LanguageId) (ULONG)LanguageId); ValueLength = (ValueLength + 1) * sizeof(WCHAR); - Status = NtSetValueKey(KeyHandle, + Status = ZwSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, ValueBuffer, ValueLength); - NtClose(KeyHandle); - NtClose(UserHandle); + ZwClose(KeyHandle); + ZwClose(UserHandle); return Status; } diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index d3d7c5415ce..00c5dec9c6c 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/process.c - * PURPOSE: Process managment - * PROGRAMMER: David Welch (welch@cwcom.net) - * REVISION HISTORY: - * 21/07/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/process.c + * PURPOSE: Process managment + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ @@ -18,20 +17,58 @@ /* GLOBALS ******************************************************************/ PEPROCESS EXPORTED PsInitialSystemProcess = NULL; -PEPROCESS PsIdleProcess = NULL; POBJECT_TYPE EXPORTED PsProcessType = NULL; LIST_ENTRY PsProcessListHead; static KSPIN_LOCK PsProcessListLock; -static ULONG PiNextProcessUniqueId = 0; /* TODO */ static LARGE_INTEGER ShortPsLockDelay, PsLockTimeout; -static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ, - PROCESS_WRITE, - PROCESS_EXECUTE, +static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | + PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | + PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, PROCESS_ALL_ACCESS}; +static const INFORMATION_CLASS_INFO PsProcessInfoClass[] = +{ + ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* ProcessBasicInformation */ + ICI_SQ_SAME( sizeof(QUOTA_LIMITS), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessQuotaLimits */ + ICI_SQ_SAME( sizeof(IO_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessIoCounters */ + ICI_SQ_SAME( sizeof(VM_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessVmCounters */ + ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES), sizeof(ULONG), ICIF_QUERY ), /* ProcessTimes */ + ICI_SQ_SAME( sizeof(KPRIORITY), sizeof(ULONG), ICIF_SET ), /* ProcessBasePriority */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET ), /* ProcessRaisePriority */ + ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDebugPort */ + ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_SET ), /* ProcessExceptionPort */ + ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN), sizeof(ULONG), ICIF_SET ), /* ProcessAccessToken */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessLdtInformation */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessLdtSize */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDefaultHardErrorMode */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessIoPortHandlers */ + ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS), sizeof(ULONG), ICIF_QUERY ), /* ProcessPooledUsageAndLimits */ + ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessWorkingSetWatch */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessUserModeIOPL */ + ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessEnableAlignmentFaultFixup */ + ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS), sizeof(USHORT), ICIF_SET ), /* ProcessPriorityClass */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWx86Information */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessHandleCount */ + ICI_SQ_SAME( sizeof(KAFFINITY), sizeof(ULONG), ICIF_SET ), /* ProcessAffinityMask */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityBoost */ + + ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query), /* ProcessDeviceMap */ + /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set), + /*Q*/ sizeof(ULONG), + /*S*/ sizeof(ULONG), + ICIF_QUERY | ICIF_SET ), + + ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessSessionInformation */ + ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessForegroundInformation */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWow64Information */ + ICI_SQ_SAME( sizeof(UNICODE_STRING), sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */ +}; + #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8 @@ -132,28 +169,10 @@ NtOpenProcessToken(IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE TokenHandle) { - PACCESS_TOKEN Token; - HANDLE hToken; - NTSTATUS Status; - - Status = PsOpenTokenOfProcess(ProcessHandle, - &Token); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - Status = ObCreateHandle(PsGetCurrentProcess(), - Token, - DesiredAccess, - FALSE, - &hToken); - ObDereferenceObject(Token); - - if(NT_SUCCESS(Status)) - { - Status = MmCopyToCaller(TokenHandle, &hToken, sizeof(HANDLE)); - } - return(Status); + return NtOpenProcessTokenEx(ProcessHandle, + DesiredAccess, + 0, + TokenHandle); } @@ -169,8 +188,56 @@ NtOpenProcessTokenEx( OUT PHANDLE TokenHandle ) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PACCESS_TOKEN Token; + HANDLE hToken; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode == UserMode) + { + _SEH_TRY + { + ProbeForWrite(TokenHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = PsOpenTokenOfProcess(ProcessHandle, + &Token); + if(NT_SUCCESS(Status)) + { + Status = ObCreateHandle(PsGetCurrentProcess(), + Token, + DesiredAccess, + FALSE, + &hToken); + ObDereferenceObject(Token); + + _SEH_TRY + { + *TokenHandle = hToken; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; } @@ -183,7 +250,7 @@ PsReferencePrimaryToken(PEPROCESS Process) ObReferenceObjectByPointer(Process->Token, TOKEN_ALL_ACCESS, SepTokenObjectType, - UserMode); + KernelMode); return(Process->Token); } @@ -198,16 +265,16 @@ PsOpenTokenOfProcess(HANDLE ProcessHandle, Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_QUERY_INFORMATION, PsProcessType, - UserMode, + ExGetPreviousMode(), (PVOID*)&Process, NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - *Token = PsReferencePrimaryToken(Process); - ObDereferenceObject(Process); - return(STATUS_SUCCESS); + if(NT_SUCCESS(Status)) + { + *Token = PsReferencePrimaryToken(Process); + ObDereferenceObject(Process); + } + + return Status; } @@ -228,7 +295,7 @@ PiKillMostProcesses(VOID) current_entry = current_entry->Flink; if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId && - current->UniqueProcessId != (ULONG)PsGetCurrentProcessId()) + current->UniqueProcessId != PsGetCurrentProcessId()) { PiTerminateProcessThreads(current, STATUS_SUCCESS); } @@ -256,8 +323,8 @@ PsInitProcessManagment(VOID) PsProcessType->Tag = TAG('P', 'R', 'O', 'C'); PsProcessType->TotalObjects = 0; PsProcessType->TotalHandles = 0; - PsProcessType->MaxObjects = ULONG_MAX; - PsProcessType->MaxHandles = ULONG_MAX; + PsProcessType->PeakObjects = 0; + PsProcessType->PeakHandles = 0; PsProcessType->PagedPoolCharge = 0; PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS); PsProcessType->Mapping = &PiProcessMapping; @@ -332,8 +399,17 @@ PsInitProcessManagment(VOID) } #endif - PsInitialSystemProcess->UniqueProcessId = - InterlockedIncrementUL(&PiNextProcessUniqueId); /* TODO */ + strcpy(PsInitialSystemProcess->ImageFileName, "System"); + + Status = PsCreateCidHandle(PsInitialSystemProcess, + PsProcessType, + &PsInitialSystemProcess->UniqueProcessId); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create CID handle (unique process id) for the system process!\n"); + return; + } + PsInitialSystemProcess->Win32WindowStation = (HANDLE)0; KeAcquireSpinLock(&PsProcessListLock, &oldIrql); @@ -341,8 +417,6 @@ PsInitProcessManagment(VOID) &PsInitialSystemProcess->ProcessListEntry); InitializeListHead(&PsInitialSystemProcess->ThreadListHead); KeReleaseSpinLock(&PsProcessListLock, oldIrql); - - strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM"); SepCreateSystemProcessToken(PsInitialSystemProcess); } @@ -569,109 +643,112 @@ IoGetCurrentProcess(VOID) } } -/* - * @implemented - */ -NTSTATUS STDCALL -PsCreateSystemProcess(PHANDLE ProcessHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - HANDLE SystemProcessHandle; - NTSTATUS Status; - - /* FIXME - what about security? should there be any privilege checks or something - security related? */ - - Status = ObCreateHandle(PsGetCurrentProcess(), - PsInitialSystemProcess, - PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION, - FALSE, - &SystemProcessHandle); - if(!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create a handle for the system process!\n"); - return Status; - } - - Status = NtCreateProcess(ProcessHandle, - DesiredAccess, - ObjectAttributes, - SystemProcessHandle, - FALSE, - NULL, - NULL, - NULL); - - NtClose(SystemProcessHandle); - - return Status; -} - -NTSTATUS STDCALL -NtCreateProcess(OUT PHANDLE ProcessHandle, +NTSTATUS +PspCreateProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN HANDLE ParentProcess, + IN HANDLE ParentProcess OPTIONAL, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL) -/* - * FUNCTION: Creates a process. - * ARGUMENTS: - * ProcessHandle (OUT) = Caller supplied storage for the resulting - * handle - * DesiredAccess = Specifies the allowed or desired access to the - * process can be a combination of - * STANDARD_RIGHTS_REQUIRED| .. - * ObjectAttribute = Initialized attributes for the object, contains - * the rootdirectory and the filename - * ParentProcess = Handle to the parent process. - * InheritObjectTable = Specifies to inherit the objects of the parent - * process if true. - * SectionHandle = Handle to a section object to back the image file - * DebugPort = Handle to a DebugPort if NULL the system default debug - * port will be used. - * ExceptionPort = Handle to a exception port. - * REMARKS: - * This function maps to the win32 CreateProcess. - * RETURNS: Status - */ { + HANDLE hProcess; PEPROCESS Process; PEPROCESS pParentProcess; PKPROCESS KProcess; - NTSTATUS Status; KIRQL oldIrql; PVOID LdrStartupAddr; - PVOID ImageBase; - PEPORT pDebugPort; - PEPORT pExceptionPort; PVOID BaseAddress; PMEMORY_AREA MemoryArea; PHYSICAL_ADDRESS BoundaryAddressMultiple; + KPROCESSOR_MODE PreviousMode; + PVOID ImageBase = NULL; + PEPORT pDebugPort = NULL; + PEPORT pExceptionPort = NULL; + PSECTION_OBJECT SectionObject = NULL; + NTSTATUS Status = STATUS_SUCCESS; - DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes); + DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes); + + PreviousMode = ExGetPreviousMode(); BoundaryAddressMultiple.QuadPart = 0; - Status = ObReferenceObjectByHandle(ParentProcess, - PROCESS_CREATE_PROCESS, - PsProcessType, - ExGetPreviousMode(), - (PVOID*)&pParentProcess, - NULL); - if (!NT_SUCCESS(Status)) + if(ParentProcess != NULL) + { + Status = ObReferenceObjectByHandle(ParentProcess, + PROCESS_CREATE_PROCESS, + PsProcessType, + PreviousMode, + (PVOID*)&pParentProcess, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status); + return(Status); + } + } + else + { + pParentProcess = NULL; + } + + /* + * Add the debug port + */ + if (DebugPort != NULL) { - DPRINT("NtCreateProcess() = %x\n",Status); - return(Status); + Status = ObReferenceObjectByHandle(DebugPort, + PORT_ALL_ACCESS, + LpcPortObjectType, + PreviousMode, + (PVOID*)&pDebugPort, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status); + goto exitdereferenceobjects; + } } - Status = ObCreateObject(ExGetPreviousMode(), + /* + * Add the exception port + */ + if (ExceptionPort != NULL) + { + Status = ObReferenceObjectByHandle(ExceptionPort, + PORT_ALL_ACCESS, + LpcPortObjectType, + PreviousMode, + (PVOID*)&pExceptionPort, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status); + goto exitdereferenceobjects; + } + } + + if (SectionHandle != NULL) + { + Status = ObReferenceObjectByHandle(SectionHandle, + 0, + MmSectionObjectType, + PreviousMode, + (PVOID*)&SectionObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status); + goto exitdereferenceobjects; + } + } + + Status = ObCreateObject(PreviousMode, PsProcessType, ObjectAttributes, - ExGetPreviousMode(), + PreviousMode, NULL, sizeof(EPROCESS), 0, @@ -679,32 +756,92 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, (PVOID*)&Process); if (!NT_SUCCESS(Status)) { - ObDereferenceObject(pParentProcess); - DPRINT("ObCreateObject() = %x\n",Status); - return(Status); + DPRINT1("Failed to create process object, Status: 0x%x\n", Status); + +exitdereferenceobjects: + if(SectionObject != NULL) + ObDereferenceObject(SectionObject); + if(pExceptionPort != NULL) + ObDereferenceObject(pExceptionPort); + if(pDebugPort != NULL) + ObDereferenceObject(pDebugPort); + if(pParentProcess != NULL) + ObDereferenceObject(pParentProcess); + return Status; } - Status = ObInsertObject ((PVOID)Process, - NULL, - DesiredAccess, - 0, - NULL, - ProcessHandle); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Process); - ObDereferenceObject (pParentProcess); - DPRINT("ObInsertObject() = %x\n",Status); - return Status; - } + KProcess = &Process->Pcb; + + RtlZeroMemory(Process, sizeof(EPROCESS)); + + Status = PsCreateCidHandle(Process, + PsProcessType, + &Process->UniqueProcessId); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status); + ObDereferenceObject(Process); + goto exitdereferenceobjects; + } - KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader, + Process->DebugPort = pDebugPort; + Process->ExceptionPort = pExceptionPort; + + if(SectionObject != NULL) + { + UNICODE_STRING FileName; + PWCHAR szSrc; + PCHAR szDest; + USHORT lnFName = 0; + + /* + * Determine the image file name and save it to the EPROCESS structure + */ + + FileName = SectionObject->FileObject->FileName; + szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1); + while(szSrc >= FileName.Buffer) + { + if(*szSrc == L'\\') + { + szSrc++; + break; + } + else + { + szSrc--; + lnFName++; + } + } + + /* copy the image file name to the process and truncate it to 15 characters + if necessary */ + szDest = Process->ImageFileName; + lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1); + while(lnFName-- > 0) + { + *(szDest++) = (UCHAR)*(szSrc++); + } + /* *szDest = '\0'; */ + } + + KeInitializeDispatcherHeader(&KProcess->DispatcherHeader, InternalProcessType, sizeof(EPROCESS), FALSE); - KProcess = &Process->Pcb; + /* Inherit parent process's affinity. */ - KProcess->Affinity = pParentProcess->Pcb.Affinity; + if(pParentProcess != NULL) + { + KProcess->Affinity = pParentProcess->Pcb.Affinity; + Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId; + Process->SessionId = pParentProcess->SessionId; + } + else + { + KProcess->Affinity = KeActiveProcessors; + } + KProcess->BasePriority = PROCESS_PRIO_NORMAL; KProcess->IopmOffset = 0xffff; KProcess->LdtDescriptor[0] = 0; @@ -714,13 +851,11 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, KProcess->AutoAlignment = 0; MmInitializeAddressSpace(Process, &Process->AddressSpace); - Process->UniqueProcessId = InterlockedIncrementUL(&PiNextProcessUniqueId); /* TODO */ - Process->InheritedFromUniqueProcessId = - (HANDLE)pParentProcess->UniqueProcessId; + ObCreateHandleTable(pParentProcess, InheritObjectTable, Process); - MmCopyMmInfo(ParentProcess, Process); + MmCopyMmInfo(pParentProcess ? pParentProcess : PsInitialSystemProcess, Process); KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE); Process->LockCount = 0; @@ -736,50 +871,6 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, ExInitializeFastMutex(&Process->TebLock); Process->Pcb.State = PROCESS_STATE_ACTIVE; - /* - * Add the debug port - */ - if (DebugPort != NULL) - { - Status = ObReferenceObjectByHandle(DebugPort, - PORT_ALL_ACCESS, - & LpcPortObjectType, - UserMode, - (PVOID*)&pDebugPort, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - ZwClose(*ProcessHandle); - *ProcessHandle = NULL; - return(Status); - } - Process->DebugPort = pDebugPort; - } - - /* - * Add the exception port - */ - if (ExceptionPort != NULL) - { - Status = ObReferenceObjectByHandle(ExceptionPort, - PORT_ALL_ACCESS, - & LpcPortObjectType, - UserMode, - (PVOID*)&pExceptionPort, - NULL); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - ZwClose(*ProcessHandle); - *ProcessHandle = NULL; - return(Status); - } - Process->ExceptionPort = pExceptionPort; - } - /* * Now we have created the process proper */ @@ -802,7 +893,8 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, { MmUnlockAddressSpace(&Process->AddressSpace); DPRINT1("Failed to protect the highest 64KB of the process address space\n"); - KEBUGCHECK(0); + ObDereferenceObject(Process); + goto exitdereferenceobjects; } /* Protect the lowest 64KB of the process address space */ @@ -822,7 +914,8 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, { MmUnlockAddressSpace(&Process->AddressSpace); DPRINT1("Failed to protect the lowest 64KB of the process address space\n"); - KEBUGCHECK(0); + ObDereferenceObject(Process); + goto exitdereferenceobjects; } #endif @@ -842,7 +935,8 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, { MmUnlockAddressSpace(&Process->AddressSpace); DPRINT1("Failed to protect the memory above the shared user page\n"); - KEBUGCHECK(0); + ObDereferenceObject(Process); + goto exitdereferenceobjects; } /* Create the shared data page */ @@ -860,131 +954,97 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, MmUnlockAddressSpace(&Process->AddressSpace); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create shared data page\n"); - KEBUGCHECK(0); + DPRINT1("Failed to create shared data page\n"); + ObDereferenceObject(Process); + goto exitdereferenceobjects; } - if (SectionHandle != NULL) +#if 1 + /* + * FIXME - the handle should be created after all things are initialized, NOT HERE! + */ + Status = ObInsertObject ((PVOID)Process, + NULL, + DesiredAccess, + 0, + NULL, + &hProcess); + if (!NT_SUCCESS(Status)) { - PSECTION_OBJECT SectionObject; - UNICODE_STRING FileName; - PWCHAR szSrc; - PCHAR szDest; - USHORT lnFName = 0; - - /* - * Determine the image file name and save it to the EPROCESS structure - */ - Status = ObReferenceObjectByHandle(SectionHandle, - 0, - MmSectionObjectType, - UserMode, - (PVOID*)&SectionObject, - NULL); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Failed to reference section object\n", Status); - ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - return(Status); - } - - FileName = SectionObject->FileObject->FileName; - szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1); - while(szSrc >= FileName.Buffer) - { - if(*szSrc == L'\\') - { - szSrc++; - break; - } - else - { - szSrc--; - lnFName++; - } - } - - /* copy the image file name to the process and truncate it to 15 characters - if necessary */ - szDest = Process->ImageFileName; - lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1); - while(lnFName-- > 0) - { - *(szDest++) = (UCHAR)*(szSrc++); - } - *szDest = '\0'; - - - ObDereferenceObject(SectionObject); - } - else - { - Process->ImageFileName[0] = '\0'; + DPRINT1("Failed to create a handle for the process\n"); + ObDereferenceObject(Process); + goto exitdereferenceobjects; } +#endif /* - * Map ntdll + * FIXME - Map ntdll */ - Status = LdrpMapSystemDll(*ProcessHandle, + Status = LdrpMapSystemDll(hProcess, /* FIXME - hProcess shouldn't be available at this point! */ &LdrStartupAddr); if (!NT_SUCCESS(Status)) { DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status); ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - return(Status); + goto exitdereferenceobjects; } /* * Map the process image */ - if (SectionHandle != NULL) + if (SectionObject != NULL) { + ULONG ViewSize = 0; DPRINT("Mapping process image\n"); - Status = LdrpMapImage(*ProcessHandle, - SectionHandle, - &ImageBase); + Status = MmMapViewOfSection(SectionObject, + Process, + (PVOID*)&ImageBase, + 0, + ViewSize, + NULL, + &ViewSize, + 0, + MEM_COMMIT, + PAGE_READWRITE); + ObDereferenceObject(SectionObject); if (!NT_SUCCESS(Status)) { - DbgPrint("LdrpMapImage failed (Status %x)\n", Status); + DbgPrint("Failed to map the process section (Status %x)\n", Status); ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - return(Status); + goto exitdereferenceobjects; } } - else - { - ImageBase = NULL; - } - - /* - * Duplicate the token - */ - Status = SepInitializeNewProcess(Process, pParentProcess); - if (!NT_SUCCESS(Status)) - { - DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status); - ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - return(Status); - } + + if(pParentProcess != NULL) + { + /* + * Duplicate the token + */ + Status = SepInitializeNewProcess(Process, pParentProcess); + if (!NT_SUCCESS(Status)) + { + DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status); + ObDereferenceObject(Process); + goto exitdereferenceobjects; + } + } + else + { + /* FIXME */ + } /* - * + * FIXME - Create PEB */ DPRINT("Creating PEB\n"); - Status = PsCreatePeb(*ProcessHandle, + Status = PsCreatePeb(hProcess, /* FIXME - hProcess shouldn't be available at this point! */ Process, ImageBase); if (!NT_SUCCESS(Status)) { DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status); ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - ZwClose(*ProcessHandle); - *ProcessHandle = NULL; - return(Status); + goto exitdereferenceobjects; } /* @@ -1017,9 +1077,139 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, PspRunCreateProcessNotifyRoutines(Process, TRUE); + /* + * FIXME - the handle should be created not before this point! + */ +#if 0 + Status = ObInsertObject ((PVOID)Process, + NULL, + DesiredAccess, + 0, + NULL, + &hProcess); +#endif + if (NT_SUCCESS(Status)) + { + _SEH_TRY + { + *ProcessHandle = hProcess; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + /* + * don't dereference the debug port, exception port and section object even + * if ObInsertObject() failed, the process is alive! We just couldn't return + * the handle to the caller! + */ + ObDereferenceObject(Process); - ObDereferenceObject(pParentProcess); - return(STATUS_SUCCESS); + if(pParentProcess != NULL) + ObDereferenceObject(pParentProcess); + + return Status; +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +PsCreateSystemProcess(PHANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return PspCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + NULL, /* no parent process */ + FALSE, + NULL, + NULL, + NULL); +} + + +/* + * @implemented + */ +NTSTATUS STDCALL +NtCreateProcess(OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL) +/* + * FUNCTION: Creates a process. + * ARGUMENTS: + * ProcessHandle (OUT) = Caller supplied storage for the resulting + * handle + * DesiredAccess = Specifies the allowed or desired access to the + * process can be a combination of + * STANDARD_RIGHTS_REQUIRED| .. + * ObjectAttribute = Initialized attributes for the object, contains + * the rootdirectory and the filename + * ParentProcess = Handle to the parent process. + * InheritObjectTable = Specifies to inherit the objects of the parent + * process if true. + * SectionHandle = Handle to a section object to back the image file + * DebugPort = Handle to a DebugPort if NULL the system default debug + * port will be used. + * ExceptionPort = Handle to a exception port. + * REMARKS: + * This function maps to the win32 CreateProcess. + * RETURNS: Status + */ +{ + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(ProcessHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + if(ParentProcess == NULL) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = PspCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + ParentProcess, + InheritObjectTable, + SectionHandle, + DebugPort, + ExceptionPort); + } + + return Status; } @@ -1082,7 +1272,7 @@ NtOpenProcess(OUT PHANDLE ProcessHandle, { current = CONTAINING_RECORD(current_entry, EPROCESS, ProcessListEntry); - if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess) + if (current->UniqueProcessId == ClientId->UniqueProcess) { if (current->Pcb.State == PROCESS_STATE_TERMINATED) { @@ -1130,7 +1320,23 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, OUT PULONG ReturnLength OPTIONAL) { PEPROCESS Process; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultQueryInfoBufferCheck(ProcessInformationClass, + PsProcessInfoClass, + ProcessInformation, + ProcessInformationLength, + ReturnLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status); + return Status; + } /* * TODO: Here we should probably check that ProcessInformationLength @@ -1138,12 +1344,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, */ Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_SET_INFORMATION, + PROCESS_QUERY_INFORMATION, PsProcessType, - UserMode, + PreviousMode, (PVOID*)&Process, NULL); - if (Status != STATUS_SUCCESS) + if (!NT_SUCCESS(Status)) { return(Status); } @@ -1151,30 +1357,34 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, switch (ProcessInformationClass) { case ProcessBasicInformation: - if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION)) - { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PPROCESS_BASIC_INFORMATION ProcessBasicInformationP = - (PPROCESS_BASIC_INFORMATION)ProcessInformation; + { + PPROCESS_BASIC_INFORMATION ProcessBasicInformationP = + (PPROCESS_BASIC_INFORMATION)ProcessInformation; + + _SEH_TRY + { ProcessBasicInformationP->ExitStatus = Process->ExitStatus; ProcessBasicInformationP->PebBaseAddress = Process->Peb; ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity; ProcessBasicInformationP->UniqueProcessId = Process->UniqueProcessId; ProcessBasicInformationP->InheritedFromUniqueProcessId = - (ULONG)Process->InheritedFromUniqueProcessId; + Process->InheritedFromUniqueProcessId; ProcessBasicInformationP->BasePriority = Process->Pcb.BasePriority; - + if (ReturnLength) { *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION); } - } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessQuotaLimits: case ProcessIoCounters: @@ -1182,28 +1392,46 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, break; case ProcessTimes: - if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES)) - { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PKERNEL_USER_TIMES ProcessTimeP = - (PKERNEL_USER_TIMES)ProcessInformation; + { + PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation; + _SEH_TRY + { + ProcessTimeP->CreateTime = Process->CreateTime; + ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL; + ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL; + ProcessTimeP->ExitTime = Process->ExitTime; - ProcessTimeP->CreateTime = (TIME) Process->CreateTime; - ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL; - ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL; - ProcessTimeP->ExitTime = (TIME) Process->ExitTime; - - if (ReturnLength) - { - *ReturnLength = sizeof(KERNEL_USER_TIMES); - } - } - break; + if (ReturnLength) + { + *ReturnLength = sizeof(KERNEL_USER_TIMES); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } case ProcessDebugPort: + { + _SEH_TRY + { + *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL); + if (ReturnLength) + { + *ReturnLength = sizeof(HANDLE); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + case ProcessLdtInformation: case ProcessWorkingSetWatch: case ProcessWx86Information: @@ -1211,34 +1439,56 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, break; case ProcessHandleCount: - if (ProcessInformationLength != sizeof(ULONG)) + { + ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable); + + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PULONG HandleCount = (PULONG)ProcessInformation; - *HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable); + *(PULONG)ProcessInformation = HandleCount; if (ReturnLength) { *ReturnLength = sizeof(ULONG); } } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessSessionInformation: + { + PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation; + + _SEH_TRY + { + SessionInfo->SessionId = Process->SessionId; + if (ReturnLength) + { + *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + break; + } + case ProcessWow64Information: + DPRINT1("We currently don't support the ProcessWow64Information information class!\n"); Status = STATUS_NOT_IMPLEMENTED; break; case ProcessVmCounters: - if (ProcessInformationLength != sizeof(VM_COUNTERS)) + { + PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation; + + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation; pOut->PeakVirtualSize = Process->PeakVirtualSize; /* * Here we should probably use VirtualSize.LowPart, but due to @@ -1260,74 +1510,97 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, { *ReturnLength = sizeof(VM_COUNTERS); } - } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessDefaultHardErrorMode: - if (ProcessInformationLength != sizeof(ULONG)) + { + PULONG HardErrMode = (PULONG)ProcessInformation; + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PULONG HardErrMode = (PULONG)ProcessInformation; *HardErrMode = Process->DefaultHardErrorProcessing; - if (ReturnLength) { *ReturnLength = sizeof(ULONG); } } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessPriorityBoost: - if (ProcessInformationLength != sizeof(ULONG)) + { + PULONG BoostEnabled = (PULONG)ProcessInformation; + + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PULONG BoostEnabled = (PULONG)ProcessInformation; *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE; if (ReturnLength) { *ReturnLength = sizeof(ULONG); } - } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessDeviceMap: - if (ProcessInformationLength != sizeof(PROCESS_DEVICEMAP_INFORMATION)) + { + PROCESS_DEVICEMAP_INFORMATION DeviceMap; + + ObQueryDeviceMapInformation(Process, &DeviceMap); + + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - ObQueryDeviceMapInformation(Process, (PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation); + *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap; if (ReturnLength) { *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION); } - } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessPriorityClass: - if (ProcessInformationLength != sizeof(USHORT)) + { + PUSHORT Priority = (PUSHORT)ProcessInformation; + + _SEH_TRY { - Status = STATUS_INFO_LENGTH_MISMATCH; - } - else - { - PUSHORT Priority = (PUSHORT)ProcessInformation; *Priority = Process->PriorityClass; if (ReturnLength) { *ReturnLength = sizeof(USHORT); } - } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; break; + } case ProcessImageFileName: { @@ -1336,23 +1609,124 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, * Propably if we can't find a PEB or ProcessParameters structure for the * process! */ - PRTL_USER_PROCESS_PARAMETERS ProcParams; - ASSERT(Process->Peb); - ASSERT(Process->Peb->ProcessParameters); - ProcParams = Process->Peb->ProcessParameters; - if(ProcessInformationLength < sizeof(UNICODE_STRING) + ProcParams->ImagePathName.Length + sizeof(WCHAR)) + if(Process->Peb != NULL) { - Status = STATUS_INFO_LENGTH_MISMATCH; + PRTL_USER_PROCESS_PARAMETERS ProcParams = NULL; + UNICODE_STRING LocalDest; + BOOLEAN Attached; + ULONG ImagePathLen = 0; + PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation; + + /* we need to attach to the process to make sure we're in the right context! */ + Attached = Process != PsGetCurrentProcess(); + + if(Attached) + KeAttachProcess(&Process->Pcb); + + _SEH_TRY + { + ProcParams = Process->Peb->ProcessParameters; + ImagePathLen = ProcParams->ImagePathName.Length; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + PWSTR StrSource = NULL; + + /* create a DstPath structure on the stack */ + _SEH_TRY + { + LocalDest.Length = ImagePathLen; + LocalDest.MaximumLength = ImagePathLen + sizeof(WCHAR); + LocalDest.Buffer = (PWSTR)(DstPath + 1); + + /* save a copy of the pointer to the source buffer */ + StrSource = ProcParams->ImagePathName.Buffer; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + /* now, let's allocate some anonymous memory to copy the string to. + we can't just copy it to the buffer the caller pointed as it might + be user memory in another context */ + PWSTR PathCopy = ExAllocatePool(PagedPool, LocalDest.Length + sizeof(WCHAR)); + if(PathCopy != NULL) + { + /* make a copy of the buffer to the temporary buffer */ + _SEH_TRY + { + RtlCopyMemory(PathCopy, StrSource, LocalDest.Length); + PathCopy[LocalDest.Length / sizeof(WCHAR)] = L'\0'; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + /* detach from the process */ + if(Attached) + KeDetachProcess(); + + /* only copy the string back to the caller if we were able to + copy it into the temporary buffer! */ + if(NT_SUCCESS(Status)) + { + /* now let's copy the buffer back to the caller */ + _SEH_TRY + { + *DstPath = LocalDest; + RtlCopyMemory(LocalDest.Buffer, PathCopy, LocalDest.Length + sizeof(WCHAR)); + if (ReturnLength) + { + *ReturnLength = sizeof(UNICODE_STRING) + LocalDest.Length + sizeof(WCHAR); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + /* we're done with the copy operation, free the temporary kernel buffer */ + ExFreePool(PathCopy); + + /* we need to bail because we're already detached from the process */ + break; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + } + } + + /* don't forget to detach from the process!!! */ + if(Attached) + KeDetachProcess(); } else { - PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation; - DstPath->Length = ProcParams->ImagePathName.Length; - DstPath->MaximumLength = DstPath->Length + sizeof(WCHAR); - DstPath->Buffer = (PWSTR)(DstPath + 1); - - RtlCopyMemory(DstPath->Buffer, ProcParams->ImagePathName.Buffer, ProcParams->ImagePathName.Length); - DstPath->Buffer[DstPath->Length / sizeof(WCHAR)] = L'\0'; + /* FIXME - what to do here? */ + Status = STATUS_UNSUCCESSFUL; } break; } @@ -1374,8 +1748,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle, default: Status = STATUS_INVALID_INFO_CLASS; } + ObDereferenceObject(Process); - return(Status); + return Status; } @@ -1416,13 +1791,44 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, IN ULONG ProcessInformationLength) { PEPROCESS Process; - NTSTATUS Status; - PHANDLE ProcessAccessTokenP; + KPROCESSOR_MODE PreviousMode; + ACCESS_MASK Access; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + DefaultSetInfoBufferCheck(ProcessInformationClass, + PsProcessInfoClass, + ProcessInformation, + ProcessInformationLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass, ProcessInformation, ProcessInformationLength); + DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status); + return Status; + } + + switch(ProcessInformationClass) + { + case ProcessSessionInformation: + Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID; + break; + case ProcessExceptionPort: + case ProcessDebugPort: + Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT; + break; + + default: + Access = PROCESS_SET_INFORMATION; + break; + } Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_SET_INFORMATION, + Access, PsProcessType, - UserMode, + PreviousMode, (PVOID*)&Process, NULL); if (!NT_SUCCESS(Status)) @@ -1435,19 +1841,296 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, case ProcessQuotaLimits: case ProcessBasePriority: case ProcessRaisePriority: - case ProcessDebugPort: - case ProcessExceptionPort: Status = STATUS_NOT_IMPLEMENTED; break; + case ProcessDebugPort: + { + if(ProcessInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + HANDLE PortHandle = NULL; + + /* make a safe copy of the buffer on the stack */ + _SEH_TRY + { + PortHandle = *(PHANDLE)ProcessInformation; + Status = (PortHandle != NULL ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + PEPORT DebugPort; + + /* in case we had success reading from the buffer, verify the provided + * LPC port handle + */ + Status = ObReferenceObjectByHandle(PortHandle, + 0, + LpcPortObjectType, + PreviousMode, + (PVOID)&DebugPort, + NULL); + if(NT_SUCCESS(Status)) + { + /* lock the process to be thread-safe! */ + + Status = PsLockProcess(Process, FALSE); + if(NT_SUCCESS(Status)) + { + /* + * according to "NT Native API" documentation, setting the debug + * port is only permitted once! + */ + if(Process->DebugPort == NULL) + { + /* keep the reference to the handle! */ + Process->DebugPort = DebugPort; + + if(Process->Peb) + { + /* we're now debugging the process, so set the flag in the PEB + structure. However, to access it we need to attach to the + process so we're sure we're in the right context! */ + + KeAttachProcess(&Process->Pcb); + _SEH_TRY + { + Process->Peb->BeingDebugged = TRUE; + } + _SEH_HANDLE + { + DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process, _SEH_GetExceptionCode()); + } + _SEH_END; + KeDetachProcess(); + } + Status = STATUS_SUCCESS; + } + else + { + ObDereferenceObject(DebugPort); + Status = STATUS_PORT_ALREADY_SET; + } + PsUnlockProcess(Process); + } + else + { + ObDereferenceObject(DebugPort); + } + } + } + } + break; + } + + case ProcessExceptionPort: + { + if(ProcessInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + HANDLE PortHandle = NULL; + + /* make a safe copy of the buffer on the stack */ + _SEH_TRY + { + PortHandle = *(PHANDLE)ProcessInformation; + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + PEPORT ExceptionPort; + + /* in case we had success reading from the buffer, verify the provided + * LPC port handle + */ + Status = ObReferenceObjectByHandle(PortHandle, + 0, + LpcPortObjectType, + PreviousMode, + (PVOID)&ExceptionPort, + NULL); + if(NT_SUCCESS(Status)) + { + /* lock the process to be thread-safe! */ + + Status = PsLockProcess(Process, FALSE); + if(NT_SUCCESS(Status)) + { + /* + * according to "NT Native API" documentation, setting the exception + * port is only permitted once! + */ + if(Process->ExceptionPort == NULL) + { + /* keep the reference to the handle! */ + Process->ExceptionPort = ExceptionPort; + Status = STATUS_SUCCESS; + } + else + { + ObDereferenceObject(ExceptionPort); + Status = STATUS_PORT_ALREADY_SET; + } + PsUnlockProcess(Process); + } + else + { + ObDereferenceObject(ExceptionPort); + } + } + } + } + break; + } + case ProcessAccessToken: - ProcessAccessTokenP = (PHANDLE)ProcessInformation; - Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP); + { + if(ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + HANDLE TokenHandle = NULL; + + /* make a safe copy of the buffer on the stack */ + _SEH_TRY + { + TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->Token; + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + /* in case we had success reading from the buffer, perform the actual task */ + Status = PspAssignPrimaryToken(Process, TokenHandle); + } + } break; + } + + case ProcessDefaultHardErrorMode: + { + if(ProcessInformationLength != sizeof(UINT)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + _SEH_TRY + { + InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing, + *(PLONG)ProcessInformation); + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + break; + } + + case ProcessSessionInformation: + { + if(ProcessInformationLength != sizeof(UINT)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + PROCESS_SESSION_INFORMATION SessionInfo; + Status = STATUS_SUCCESS; + + _SEH_TRY + { + /* copy the structure to the stack */ + SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + /* we successfully copied the structure to the stack, continue processing */ + + /* + * setting the session id requires the SeTcbPrivilege! + */ + if(!SeSinglePrivilegeCheck(SeTcbPrivilege, + PreviousMode)) + { + DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n"); + /* can't set the session id, bail! */ + Status = STATUS_PRIVILEGE_NOT_HELD; + break; + } + + /* FIXME - update the session id for the process token */ + + Status = PsLockProcess(Process, FALSE); + if(NT_SUCCESS(Status)) + { + Process->SessionId = SessionInfo.SessionId; + + /* Update the session id in the PEB structure */ + if(Process->Peb != NULL) + { + /* we need to attach to the process to make sure we're in the right + context to access the PEB structure */ + KeAttachProcess(&Process->Pcb); + + _SEH_TRY + { + /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */ + + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + KeDetachProcess(); + } + + PsUnlockProcess(Process); + } + } + } + break; + } case ProcessLdtInformation: case ProcessLdtSize: - case ProcessDefaultHardErrorMode: case ProcessIoPortHandlers: case ProcessWorkingSetWatch: case ProcessUserModeIOPL: @@ -1890,7 +2573,7 @@ PsIsProcessBeingDebugged( * @implemented */ NTSTATUS STDCALL -PsLookupProcessByProcessId(IN PVOID ProcessId, +PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process) { KIRQL oldIrql; @@ -1905,7 +2588,7 @@ PsLookupProcessByProcessId(IN PVOID ProcessId, current = CONTAINING_RECORD(current_entry, EPROCESS, ProcessListEntry); - if (current->UniqueProcessId == (ULONG)ProcessId) + if (current->UniqueProcessId == ProcessId) { *Process = current; ObReferenceObject(current); @@ -2144,7 +2827,6 @@ PsChargeProcessPoolQuota( ) { PEPROCESS_QUOTA_BLOCK QuotaBlock; - KIRQL OldValue; ULONG NewUsageSize; ULONG NewMaxQuota; @@ -2154,40 +2836,33 @@ PsChargeProcessPoolQuota( /* Quota Operations are not to be done on the SYSTEM Process */ if (Process == PsInitialSystemProcess) return STATUS_SUCCESS; - /* Acquire Spinlock */ - KeAcquireSpinLock(&QuotaBlock->QuotaLock, &OldValue); - /* New Size in use */ - NewUsageSize = QuotaBlock->QuotaPoolUsage[PoolType] + Amount; + NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount; /* Does this size respect the quota? */ - if (NewUsageSize > QuotaBlock->QuotaPoolLimit[PoolType]) { + if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) { /* It doesn't, so keep raising the Quota */ - while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaPoolLimit[PoolType], &NewMaxQuota)) { + while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) { /* Save new Maximum Quota */ - QuotaBlock->QuotaPoolLimit[PoolType] = NewMaxQuota; + QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota; /* See if the new Maximum Quota fulfills our need */ if (NewUsageSize <= NewMaxQuota) goto QuotaChanged; } - KeReleaseSpinLock(&QuotaBlock->QuotaLock, OldValue); return STATUS_QUOTA_EXCEEDED; } QuotaChanged: /* Save new Usage */ - QuotaBlock->QuotaPoolUsage[PoolType] = NewUsageSize; + QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize; /* Is this a new peak? */ - if (NewUsageSize > QuotaBlock->QuotaPeakPoolUsage[PoolType]) { - QuotaBlock->QuotaPeakPoolUsage[PoolType] = NewUsageSize; + if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) { + QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize; } - /* Release spinlock */ - KeReleaseSpinLock(&QuotaBlock->QuotaLock, OldValue); - /* All went well */ return STATUS_SUCCESS; } @@ -2272,11 +2947,18 @@ PsLockProcess(PEPROCESS Process, BOOL Timeout) KernelMode, FALSE, Delay); - if(Status == STATUS_TIMEOUT) + if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT) { +#ifndef NDEBUG + if(Status == STATUS_TIMEOUT) + { + DPRINT1("PsLockProcess(0x%x) timed out!\n", Process); + } +#endif KeLeaveCriticalRegion(); - break; + } + break; } else { diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 8601c6e6229..051d6ae9989 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/psmgr.c - * PURPOSE: Process management - * PROGRAMMER: David Welch (welch@mcmail.com) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/psmgr.c + * PURPOSE: Process management + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES **************************************************************/ diff --git a/reactos/ntoskrnl/ps/suspend.c b/reactos/ntoskrnl/ps/suspend.c index 777704780f2..eeacff4e21b 100644 --- a/reactos/ntoskrnl/ps/suspend.c +++ b/reactos/ntoskrnl/ps/suspend.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/suspend.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/suspend.c + * PURPOSE: Thread managment + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 6004132814f..3acafcfd7e0 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,13 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/thread.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 23/06/98: Created - * 12/10/99: Phillip Susi: Thread priorities, and APC work + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi */ /* @@ -34,18 +33,22 @@ POBJECT_TYPE EXPORTED PsThreadType = NULL; LONG PiNrThreadsAwaitingReaping = 0; +extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; + /* * PURPOSE: List of threads associated with each priority level */ static LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; static ULONG PriorityListMask = 0; +static ULONG IdleProcessorMask = 0; static BOOLEAN DoneInitYet = FALSE; static KEVENT PiReaperThreadEvent; static BOOLEAN PiReaperThreadShouldTerminate = FALSE; -static GENERIC_MAPPING PiThreadMapping = {THREAD_READ, - THREAD_WRITE, - THREAD_EXECUTE, +static GENERIC_MAPPING PiThreadMapping = {STANDARD_RIGHTS_READ | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, + STANDARD_RIGHTS_WRITE | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_ALERT | + THREAD_SET_INFORMATION | THREAD_SET_CONTEXT, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, THREAD_ALL_ACCESS}; /* FUNCTIONS ***************************************************************/ @@ -55,7 +58,7 @@ static GENERIC_MAPPING PiThreadMapping = {THREAD_READ, */ PKTHREAD STDCALL KeGetCurrentThread(VOID) { -#ifdef MP +#ifdef CONFIG_SMP ULONG Flags; PKTHREAD Thread; Ke386SaveFlags(Flags); @@ -298,8 +301,10 @@ VOID PsDumpThreads(BOOLEAN IncludeSystem) Thread = CONTAINING_RECORD(AThread, ETHREAD, ThreadListEntry); nThreads++; - DbgPrint("Thread->Tcb.State %d PID.TID %d.%d Name %.8s Stack: \n", + DbgPrint("Thread->Tcb.State %d Affinity %08x Priority %d PID.TID %d.%d Name %.8s Stack: \n", Thread->Tcb.State, + Thread->Tcb.Affinity, + Thread->Tcb.Priority, Thread->ThreadsProcess->UniqueProcessId, Thread->Cid.UniqueThread, Thread->ThreadsProcess->ImageFileName); @@ -424,6 +429,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) if (Candidate != NULL) { PETHREAD OldThread; + PKTHREAD IdleThread; DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority); @@ -431,6 +437,16 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) OldThread = CurrentThread; CurrentThread = Candidate; + IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread; + + if (&OldThread->Tcb == IdleThread) + { + IdleProcessorMask &= ~Affinity; + } + else if (&CurrentThread->Tcb == IdleThread) + { + IdleProcessorMask |= Affinity; + } MmUpdatePageDir(PsGetCurrentProcess(),(PVOID)CurrentThread->ThreadsProcess, sizeof(EPROCESS)); @@ -458,7 +474,7 @@ PsDispatchThread(ULONG NewThreadStatus) } VOID -PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment) { if (THREAD_STATE_TERMINATED_1 == Thread->Tcb.State || THREAD_STATE_TERMINATED_2 == Thread->Tcb.State) @@ -474,12 +490,57 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) } else { + ULONG Processor; + KAFFINITY Affinity; + + /* FIXME: This propably isn't the right way to do it... */ + if (Thread->Tcb.Priority < LOW_REALTIME_PRIORITY && + Thread->Tcb.BasePriority < LOW_REALTIME_PRIORITY - 2) + { + if (!Thread->Tcb.PriorityDecrement && !Thread->Tcb.DisableBoost) + { + Thread->Tcb.Priority = Thread->Tcb.BasePriority + Increment; + Thread->Tcb.PriorityDecrement = Increment; + } + } + else + { + Thread->Tcb.Quantum = Thread->Tcb.ApcState.Process->ThreadQuantum; + } + if (WaitStatus != NULL) { Thread->Tcb.WaitStatus = *WaitStatus; } Thread->Tcb.State = THREAD_STATE_READY; PsInsertIntoThreadList(Thread->Tcb.Priority, Thread); + Processor = KeGetCurrentProcessorNumber(); + Affinity = Thread->Tcb.Affinity; + if (!(IdleProcessorMask & (1 << Processor) & Affinity) && + (IdleProcessorMask & ~(1 << Processor) & Affinity)) + { + ULONG i; + for (i = 0; i < KeNumberProcessors - 1; i++) + { + Processor++; + if (Processor >= KeNumberProcessors) + { + Processor = 0; + } + if (IdleProcessorMask & (1 << Processor) & Affinity) + { +#if 0 + /* FIXME: + * Reschedule the threads on an other processor + */ + KeReleaseDispatcherDatabaseLockFromDpcLevel(); + KiRequestReschedule(Processor); + KeAcquireDispatcherDatabaseLockAtDpcLevel(); +#endif + break; + } + } + } } } @@ -633,6 +694,10 @@ PsSetThreadWin32Thread( VOID PsApplicationProcessorInit(VOID) { + KIRQL oldIrql; + oldIrql = KeAcquireDispatcherDatabaseLock(); + IdleProcessorMask |= (1 << KeGetCurrentProcessorNumber()); + KeReleaseDispatcherDatabaseLock(oldIrql); } VOID INIT_FUNCTION @@ -647,7 +712,7 @@ PsPrepareForApplicationProcessorInit(ULONG Id) &IdleThreadHandle, THREAD_ALL_ACCESS, NULL, - TRUE); + FALSE); IdleThread->Tcb.State = THREAD_STATE_RUNNING; IdleThread->Tcb.FreezeCount = 0; IdleThread->Tcb.Affinity = 1 << Id; @@ -656,6 +721,9 @@ PsPrepareForApplicationProcessorInit(ULONG Id) IdleThread->Tcb.BasePriority = LOW_PRIORITY; Pcr->PrcbData.IdleThread = &IdleThread->Tcb; Pcr->PrcbData.CurrentThread = &IdleThread->Tcb; + + Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit; + NtClose(IdleThreadHandle); DPRINT("IdleThread for Processor %d has PID %d\n", Id, IdleThread->Cid.UniqueThread); @@ -683,8 +751,8 @@ PsInitThreadManagment(VOID) PsThreadType->Tag = TAG('T', 'H', 'R', 'T'); PsThreadType->TotalObjects = 0; PsThreadType->TotalHandles = 0; - PsThreadType->MaxObjects = 0; - PsThreadType->MaxHandles = 0; + PsThreadType->PeakObjects = 0; + PsThreadType->PeakHandles = 0; PsThreadType->PagedPoolCharge = 0; PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD); PsThreadType->Mapping = &PiThreadMapping; @@ -912,44 +980,6 @@ KeSetAffinityThread(PKTHREAD Thread, } -NTSTATUS STDCALL -NtAlertResumeThread(IN HANDLE ThreadHandle, - OUT PULONG SuspendCount) -{ - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); - -} - - -NTSTATUS STDCALL -NtAlertThread (IN HANDLE ThreadHandle) -{ - PETHREAD Thread; - NTSTATUS Status; - NTSTATUS ThreadStatus; - KIRQL oldIrql; - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - ThreadStatus = STATUS_ALERTED; - oldIrql = KeAcquireDispatcherDatabaseLock(); - (VOID)PsUnblockThread(Thread, &ThreadStatus); - KeReleaseDispatcherDatabaseLock(oldIrql); - - ObDereferenceObject(Thread); - return(STATUS_SUCCESS); -} - /********************************************************************** * NtOpenThread/4 * diff --git a/reactos/ntoskrnl/ps/tinfo.c b/reactos/ntoskrnl/ps/tinfo.c index b1b87bcad31..70455fa2336 100644 --- a/reactos/ntoskrnl/ps/tinfo.c +++ b/reactos/ntoskrnl/ps/tinfo.c @@ -4,11 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/tinfo.c * PURPOSE: Getting/setting thread information - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 - * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com) - * to suppport thread-eventpairs. + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Skywing (skywing@valhallalegends.com) */ /* INCLUDES *****************************************************************/ @@ -253,9 +251,9 @@ NtQueryInformationThread (IN HANDLE ThreadHandle, case ThreadTimes: u.TTI.KernelTime.QuadPart = Thread->Tcb.KernelTime * 100000LL; u.TTI.UserTime.QuadPart = Thread->Tcb.UserTime * 100000LL; - u.TTI.CreateTime = (TIME) Thread->CreateTime; + u.TTI.CreateTime = Thread->CreateTime; /*This works*/ - u.TTI.ExitTime = (TIME) Thread->ExitTime; + u.TTI.ExitTime = Thread->ExitTime; break; case ThreadQuerySetWin32StartAddress: @@ -316,7 +314,7 @@ KeSetPreviousMode (ULONG Mode) /* * @implemented */ -ULONG STDCALL +KPROCESSOR_MODE STDCALL KeGetPreviousMode (VOID) { return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; diff --git a/reactos/ntoskrnl/ps/w32call.c b/reactos/ntoskrnl/ps/w32call.c index 2318a6af27b..48b11ac8259 100644 --- a/reactos/ntoskrnl/ps/w32call.c +++ b/reactos/ntoskrnl/ps/w32call.c @@ -1,13 +1,12 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/thread.c - * PURPOSE: Thread managment - * PROGRAMMER: David Welch (welch@mcmail.com) - * REVISION HISTORY: - * 23/06/98: Created - * 12/10/99: Phillip Susi: Thread priorities, and APC work + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/w32call.c + * PURPOSE: Thread managment + * + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Phillip Susi */ /* @@ -25,7 +24,7 @@ #include #if defined(__GNUC__) -void * alloca(size_t size); +/* void * alloca(size_t size); */ #elif defined(_MSC_VER) void* _alloca(size_t size); #else @@ -292,7 +291,8 @@ NtW32Call (IN ULONG RoutineIndex, memcpy((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA), Thread->Tcb.TrapFrame, sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD))); NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA)); - NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG))); + /* We need the stack pointer to remain 4-byte aligned */ + NewFrame->Esp -= (((ArgumentLength + 3) & (~ 0x3)) + (4 * sizeof(ULONG))); NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher(); UserEsp = (PULONG)NewFrame->Esp; UserEsp[0] = 0; /* Return address. */ diff --git a/reactos/ntoskrnl/ps/win32.c b/reactos/ntoskrnl/ps/win32.c index 767a4f36608..6e9ef4d07ba 100644 --- a/reactos/ntoskrnl/ps/win32.c +++ b/reactos/ntoskrnl/ps/win32.c @@ -1,30 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2002 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ps/win32.c - * PURPOSE: win32k support - * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) - * REVISION HISTORY: - * 04/01/2002: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/win32.c + * PURPOSE: win32k support + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/atom.c b/reactos/ntoskrnl/rtl/atom.c index fec78afa376..d3f897fe3ed 100644 --- a/reactos/ntoskrnl/rtl/atom.c +++ b/reactos/ntoskrnl/rtl/atom.c @@ -2,11 +2,10 @@ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/atom.c + * FILE: ntoskrnl/rtl/atom.c * PURPOSE: Atom managment - * PROGRAMMER: Nobody - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ @@ -378,8 +377,8 @@ RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable, } InsertTailList(&AtomTable->Slot[Hash], &Entry->List); - RtlCreateUnicodeString (&Entry->Name, - AtomName); + RtlpCreateUnicodeString (&Entry->Name, + AtomName, NonPagedPool); Entry->RefCount = 1; Entry->Locked = FALSE; diff --git a/reactos/ntoskrnl/rtl/capture.c b/reactos/ntoskrnl/rtl/capture.c index 08053c387c0..c001291b15e 100644 --- a/reactos/ntoskrnl/rtl/capture.c +++ b/reactos/ntoskrnl/rtl/capture.c @@ -1,29 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * + * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/capture.c * PURPOSE: Helper routines for system calls. - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 02/09/01: Created + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ @@ -35,43 +17,112 @@ /* FUNCTIONS *****************************************************************/ NTSTATUS -RtlCaptureUnicodeString(PUNICODE_STRING Dest, - PUNICODE_STRING UnsafeSrc) +RtlCaptureUnicodeString(OUT PUNICODE_STRING Dest, + IN KPROCESSOR_MODE CurrentMode, + IN POOL_TYPE PoolType, + IN BOOLEAN CaptureIfKernel, + IN PUNICODE_STRING UnsafeSrc) { - PUNICODE_STRING Src; - NTSTATUS Status; - + UNICODE_STRING Src; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT(Dest != NULL); + /* * Copy the source string structure to kernel space. */ - Status = MmCopyFromCaller(&Src, UnsafeSrc, sizeof(UNICODE_STRING)); - if (!NT_SUCCESS(Status)) + + if(CurrentMode == UserMode) + { + _SEH_TRY { - return(Status); + ProbeForRead(UnsafeSrc, + sizeof(UNICODE_STRING), + sizeof(ULONG)); + Src = *UnsafeSrc; + if(Src.Length > 0) + { + ProbeForRead(Src.Buffer, + Src.Length, + sizeof(WCHAR)); + } } - + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else if(!CaptureIfKernel) + { + /* just copy the UNICODE_STRING structure, the pointers are considered valid */ + *Dest = *UnsafeSrc; + return STATUS_SUCCESS; + } + else + { + /* capture the string even though it is considered to be valid */ + Src = *UnsafeSrc; + } + /* * Initialize the destination string. */ - Dest->Length = Src->Length; - Dest->MaximumLength = Src->MaximumLength; - Dest->Buffer = ExAllocatePool(NonPagedPool, Dest->MaximumLength); - if (Dest->Buffer == NULL) + Dest->Length = Src.Length; + if(Src.Length > 0) + { + Dest->MaximumLength = Src.Length + sizeof(WCHAR); + Dest->Buffer = ExAllocatePool(PoolType, Dest->MaximumLength); + if (Dest->Buffer == NULL) { - return(STATUS_NO_MEMORY); + Dest->Length = Dest->MaximumLength = 0; + Dest->Buffer = NULL; + return STATUS_INSUFFICIENT_RESOURCES; } - - /* - * Copy the source string to kernel space. - */ - Status = MmCopyFromCaller(Dest->Buffer, Src->Buffer, Dest->Length); - if (!NT_SUCCESS(Status)) + /* + * Copy the source string to kernel space. + */ + _SEH_TRY + { + RtlCopyMemory(Dest->Buffer, Src.Buffer, Src.Length); + Dest->Buffer[Src.Length / sizeof(WCHAR)] = L'\0'; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) { ExFreePool(Dest->Buffer); - return(Status); + Dest->Buffer = NULL; + Dest->Length = Dest->MaximumLength = 0; } + } + else + { + Dest->MaximumLength = 0; + Dest->Buffer = NULL; + } + + return Status; +} - return(STATUS_SUCCESS); +VOID +RtlReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, + IN KPROCESSOR_MODE CurrentMode, + IN BOOLEAN CaptureIfKernel) +{ + if(CurrentMode != KernelMode || CaptureIfKernel ) + { + RtlFreeUnicodeString(CapturedString); + } } NTSTATUS diff --git a/reactos/ntoskrnl/rtl/ctype.c b/reactos/ntoskrnl/rtl/ctype.c index 4a6887a05ff..3366e1b4b6b 100644 --- a/reactos/ntoskrnl/rtl/ctype.c +++ b/reactos/ntoskrnl/rtl/ctype.c @@ -4,11 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/ctype.c * PURPOSE: Character type and conversion functions - * PROGRAMMERS: ??? - * Eric Kohl - * HISTORY: ???: Created - * 10/01/2000: Added missing functions and changed - * all functions to use ctype table + * + * PROGRAMMERS: Eric Kohl */ #undef __MSVCRT__ #include diff --git a/reactos/ntoskrnl/rtl/handle.c b/reactos/ntoskrnl/rtl/handle.c index c29982d73c9..3765367ee7c 100644 --- a/reactos/ntoskrnl/rtl/handle.c +++ b/reactos/ntoskrnl/rtl/handle.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Handle table - * FILE: lib/ntdll/rtl/handle.c - * PROGRAMER: Eric Kohl + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/handle.c + * PURPOSE: Handle table + * + * PROGRAMMERS: Eric Kohl */ /* INCLUDES ******************************************************************/ diff --git a/reactos/ntoskrnl/rtl/i386/exception.c b/reactos/ntoskrnl/rtl/i386/exception.c index 98eb681e993..f6fdd18ac4b 100755 --- a/reactos/ntoskrnl/rtl/i386/exception.c +++ b/reactos/ntoskrnl/rtl/i386/exception.c @@ -1,10 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Kernel-mode exception support for IA-32 - * FILE: ntoskrnl/rtl/i386/exception.c - * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/i386/exception.c + * PURPOSE: Kernel-mode exception support for IA-32 + * + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index 90af7a673af..6e7b4352dac 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -1,22 +1,22 @@ -/* +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/ntoskrnl/rtl/libsup.c + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/libsupp.c * PURPOSE: Rtl library support routines - * UPDATE HISTORY: * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include -//FIXME: sort this out somehow -#define PCRITICAL_SECTION PVOID -#define LPCRITICAL_SECTION PVOID +//FIXME: sort this out somehow. IAI: Sorted in new header branch +#define PRTL_CRITICAL_SECTION PVOID /* FUNCTIONS *****************************************************************/ @@ -24,73 +24,89 @@ * @implemented */ VOID STDCALL -RtlDeleteCriticalSection(PCRITICAL_SECTION CriticalSection) +RtlAcquirePebLock(VOID) { + } /* * @implemented */ -DWORD STDCALL +VOID STDCALL +RtlReleasePebLock(VOID) +{ + +} + +PPEB +STDCALL +RtlpCurrentPeb(VOID) +{ + return ((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->Peb; +} + +NTSTATUS +STDCALL +RtlDeleteCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) +{ + return STATUS_SUCCESS; +} + +DWORD +STDCALL RtlSetCriticalSectionSpinCount( - LPCRITICAL_SECTION CriticalSection, + PRTL_CRITICAL_SECTION CriticalSection, DWORD SpinCount ) { return 0; } - -/* - * @implemented - */ -VOID STDCALL -RtlEnterCriticalSection(PCRITICAL_SECTION CriticalSection) +NTSTATUS +STDCALL +RtlEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - ExAcquireFastMutex((PFAST_MUTEX) CriticalSection ); + ExAcquireFastMutex((PFAST_MUTEX) CriticalSection); + return STATUS_SUCCESS; } - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlInitializeCriticalSection(PCRITICAL_SECTION CriticalSection) +NTSTATUS +STDCALL +RtlInitializeCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { ExInitializeFastMutex((PFAST_MUTEX)CriticalSection ); return STATUS_SUCCESS; } - -/* - * @implemented - */ -VOID STDCALL -RtlLeaveCriticalSection(PCRITICAL_SECTION CriticalSection) +NTSTATUS +STDCALL +RtlLeaveCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - ExReleaseFastMutex((PFAST_MUTEX) CriticalSection ); + ExReleaseFastMutex((PFAST_MUTEX) CriticalSection ); + return STATUS_SUCCESS; } -/* - * @implemented - */ -BOOLEAN STDCALL -RtlTryEnterCriticalSection(PCRITICAL_SECTION CriticalSection) +BOOLEAN +STDCALL +RtlTryEnterCriticalSection( + PRTL_CRITICAL_SECTION CriticalSection) { - return ExTryToAcquireFastMutex((PFAST_MUTEX) CriticalSection ); + return ExTryToAcquireFastMutex((PFAST_MUTEX) CriticalSection ); } -/* - * @implemented - */ -NTSTATUS STDCALL -RtlInitializeCriticalSectionAndSpinCount ( - PCRITICAL_SECTION CriticalSection, - ULONG SpinCount) +NTSTATUS +STDCALL +RtlInitializeCriticalSectionAndSpinCount( + PRTL_CRITICAL_SECTION CriticalSection, + ULONG SpinCount) { - ExInitializeFastMutex((PFAST_MUTEX)CriticalSection ); - return STATUS_SUCCESS; + ExInitializeFastMutex((PFAST_MUTEX)CriticalSection ); + return STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/ntoskrnl/rtl/message.c b/reactos/ntoskrnl/rtl/message.c index f473b923bf2..630b281ac72 100644 --- a/reactos/ntoskrnl/rtl/message.c +++ b/reactos/ntoskrnl/rtl/message.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Message table functions - * FILE: ntoskrnl/rtl/message.c - * PROGRAMER: Eric Kohl - * REVISION HISTORY: - * 29/05/2001: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/message.c + * PURPOSE: Message table functions + * + * PROGRAMMERS: Eric Kohl */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/misc.c b/reactos/ntoskrnl/rtl/misc.c new file mode 100644 index 00000000000..7bb05ac2a95 --- /dev/null +++ b/reactos/ntoskrnl/rtl/misc.c @@ -0,0 +1,31 @@ +/* $Id:$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/misc.c + * PURPOSE: Various functions + * + * PROGRAMMERS: Hartmut Birr + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +extern ULONG NtGlobalFlag; + +/* FUNCTIONS *****************************************************************/ + +/* +* @implemented +*/ +ULONG +STDCALL +RtlGetNtGlobalFlags(VOID) +{ + return(NtGlobalFlag); +} diff --git a/reactos/ntoskrnl/rtl/nls.c b/reactos/ntoskrnl/rtl/nls.c index f1b1ceed460..c56345c0f61 100644 --- a/reactos/ntoskrnl/rtl/nls.c +++ b/reactos/ntoskrnl/rtl/nls.c @@ -4,8 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/nls.c * PURPOSE: Bitmap functions - * UPDATE HISTORY: - * 20/08/99 Created by Eric Kohl + * + * PROGRAMMERS: Eric Kohl */ #include diff --git a/reactos/ntoskrnl/rtl/purecall.c b/reactos/ntoskrnl/rtl/purecall.c index a8e378a90c3..43012472012 100644 --- a/reactos/ntoskrnl/rtl/purecall.c +++ b/reactos/ntoskrnl/rtl/purecall.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Message table functions - * FILE: ntoskrnl/rtl/message.c - * PROGRAMER: Eric Kohl - * REVISION HISTORY: - * 29/05/2001: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/purecall.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: Eric Kohl */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/rangelist.c b/reactos/ntoskrnl/rtl/rangelist.c index 3e1724768ad..788886c76f6 100644 --- a/reactos/ntoskrnl/rtl/rangelist.c +++ b/reactos/ntoskrnl/rtl/rangelist.c @@ -1,27 +1,11 @@ -/* - * ReactOS kernel - * Copyright (C) 2004 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * PURPOSE: Range list implementation - * FILE: ntoskrnl/rtl/rangelist.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/rangelist.c + * PURPOSE: Range list implementation + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES ****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/regio.c b/reactos/ntoskrnl/rtl/regio.c index 23926ede4dd..826ec431daf 100644 --- a/reactos/ntoskrnl/rtl/regio.c +++ b/reactos/ntoskrnl/rtl/regio.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/rtl/regio.c - * PURPOSE: Register io functions - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * REVISION HISTORY: - * 29/12/1999 Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/regio.c + * PURPOSE: Register io functions + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ #include diff --git a/reactos/ntoskrnl/rtl/sprintf.c b/reactos/ntoskrnl/rtl/sprintf.c index b8c6c1faf25..8faa8ca70b9 100644 --- a/reactos/ntoskrnl/rtl/sprintf.c +++ b/reactos/ntoskrnl/rtl/sprintf.c @@ -4,9 +4,9 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/sprintf.c * PURPOSE: Single byte sprintf functions + * * PROGRAMMERS: David Welch * Eric Kohl - * */ /* diff --git a/reactos/ntoskrnl/rtl/stdlib.c b/reactos/ntoskrnl/rtl/stdlib.c index 36fa2db3390..e77e58b3dff 100644 --- a/reactos/ntoskrnl/rtl/stdlib.c +++ b/reactos/ntoskrnl/rtl/stdlib.c @@ -4,9 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/stdlib.c * PURPOSE: Standard library functions - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * UPDATE HISTORY: - * 1999/07/29 ekohl Created + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/string.c b/reactos/ntoskrnl/rtl/string.c index 50c45a86eb8..c45e7d6cdb8 100644 --- a/reactos/ntoskrnl/rtl/string.c +++ b/reactos/ntoskrnl/rtl/string.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/string.c * PURPOSE: Ascii string functions - * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) - * UPDATE HISTORY: - * 1999/07/29 ekohl Created + * + * PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/strtok.c b/reactos/ntoskrnl/rtl/strtok.c index 7f9f8256f2f..29701b257a4 100644 --- a/reactos/ntoskrnl/rtl/strtok.c +++ b/reactos/ntoskrnl/rtl/strtok.c @@ -1,11 +1,11 @@ -/* +/* $Id$ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/strtok.c * PURPOSE: Unicode and thread safe implementation of strtok - * PROGRAMMER: David Welch (welch@mcmail.com) - * UPDATE HISTORY: - * Created 22/05/98 + * + * PROGRAMMERS: David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/rtl/swprintf.c b/reactos/ntoskrnl/rtl/swprintf.c index 7135a5435e8..b543e05f924 100644 --- a/reactos/ntoskrnl/rtl/swprintf.c +++ b/reactos/ntoskrnl/rtl/swprintf.c @@ -3,10 +3,13 @@ * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/swprintf.c - * PURPOSE: unicode sprintf functions + * PURPOSE: Unicode sprintf functions + * * PROGRAMMERS: David Welch * Eric Kohl - * + */ + +/* * TODO: * - Verify the implementation of '%Z'. */ diff --git a/reactos/ntoskrnl/rtl/wstring.c b/reactos/ntoskrnl/rtl/wstring.c index be30eb8596c..0e2939b781a 100644 --- a/reactos/ntoskrnl/rtl/wstring.c +++ b/reactos/ntoskrnl/rtl/wstring.c @@ -4,11 +4,8 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/rtl/wstring.c * PURPOSE: Wide string functions - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 22/05/98 - * 1998/12/04 RJJ Cleaned up and added i386 def checks. - * 1999/07/29 ekohl Added missing functions. + * + * PROGRAMMERS: David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/se/access.c b/reactos/ntoskrnl/se/access.c index 273de5fb776..422ec1e301b 100644 --- a/reactos/ntoskrnl/se/access.c +++ b/reactos/ntoskrnl/se/access.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Access rights handling functions - * FILE: ntoskrnl/se/access.c - * PROGRAMER: Eric Kohl - * REVISION HISTORY: - * 07/04/2000: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/access.c + * PURPOSE: Access rights handling functions + * + * PROGRAMMERS: Eric Kohl */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/se/acl.c b/reactos/ntoskrnl/se/acl.c index c0ee09f0c79..bdb249ebe04 100644 --- a/reactos/ntoskrnl/se/acl.c +++ b/reactos/ntoskrnl/se/acl.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: kernel/se/acl.c - * PROGRAMER: David Welch - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/acl.c + * PURPOSE: Security manager + * + * PROGRAMMERS: David Welch */ /* INCLUDES *****************************************************************/ @@ -220,8 +219,8 @@ SepInitDACLs(VOID) } NTSTATUS STDCALL -SepCreateImpersonationTokenDacl(PACCESS_TOKEN Token, - PACCESS_TOKEN PrimaryToken, +SepCreateImpersonationTokenDacl(PTOKEN Token, + PTOKEN PrimaryToken, PACL *Dacl) { ULONG AclLength; diff --git a/reactos/ntoskrnl/se/audit.c b/reactos/ntoskrnl/se/audit.c index 1994999069a..d65b6958b40 100644 --- a/reactos/ntoskrnl/se/audit.c +++ b/reactos/ntoskrnl/se/audit.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Audit functions - * FILE: kernel/se/audit.c - * PROGRAMER: Eric Kohl (ekohl@rz-online.de) - * REVISION HISTORY: - * 20/07/2003: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/audit.c + * PURPOSE: Audit functions + * + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/se/lsa.c b/reactos/ntoskrnl/se/lsa.c index 896a825cebe..43dc67fc369 100644 --- a/reactos/ntoskrnl/se/lsa.c +++ b/reactos/ntoskrnl/se/lsa.c @@ -1,4 +1,11 @@ /* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/lsa.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. */ #include diff --git a/reactos/ntoskrnl/se/luid.c b/reactos/ntoskrnl/se/luid.c index 9c79fa32c12..1ea9e71c3fc 100644 --- a/reactos/ntoskrnl/se/luid.c +++ b/reactos/ntoskrnl/se/luid.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: ntoskrnl/se/luid.c - * PROGRAMER: ? - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/luid.c + * PURPOSE: Security manager + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ @@ -20,15 +19,16 @@ static KSPIN_LOCK LuidLock; static LARGE_INTEGER LuidIncrement; static LARGE_INTEGER LuidValue; -#define SYSTEM_LUID 0x3E7; - /* FUNCTIONS *****************************************************************/ VOID INIT_FUNCTION SepInitLuid(VOID) { + LUID DummyLuidValue = SYSTEM_LUID; + KeInitializeSpinLock(&LuidLock); - LuidValue.QuadPart = SYSTEM_LUID; + LuidValue.u.HighPart = DummyLuidValue.HighPart; + LuidValue.u.LowPart = DummyLuidValue.LowPart; LuidIncrement.QuadPart = 1; } diff --git a/reactos/ntoskrnl/se/priv.c b/reactos/ntoskrnl/se/priv.c index 5a37d8155ba..5dceff3ab93 100644 --- a/reactos/ntoskrnl/se/priv.c +++ b/reactos/ntoskrnl/se/priv.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: kernel/se/priv.c - * PROGRAMER: ? - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/priv.c + * PURPOSE: Security manager + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ @@ -98,7 +97,7 @@ SepInitPrivileges (VOID) BOOLEAN -SepPrivilegeCheck (PACCESS_TOKEN Token, +SepPrivilegeCheck (PTOKEN Token, PLUID_AND_ATTRIBUTES Privileges, ULONG PrivilegeCount, ULONG PrivilegeControl, @@ -223,7 +222,7 @@ NtPrivilegeCheck (IN HANDLE ClientToken, IN PBOOLEAN Result) { PLUID_AND_ATTRIBUTES Privilege; - PACCESS_TOKEN Token; + PTOKEN Token; ULONG PrivilegeCount; ULONG PrivilegeControl; ULONG Length; @@ -252,10 +251,10 @@ NtPrivilegeCheck (IN HANDLE ClientToken, Privilege = 0; Status = SeCaptureLuidAndAttributesArray (RequiredPrivileges->Privilege, PrivilegeCount, - 1, + UserMode, + NULL, 0, - 0, - 1, + PagedPool, 1, &Privilege, &Length); diff --git a/reactos/ntoskrnl/se/sd.c b/reactos/ntoskrnl/se/sd.c index 1e79fbbf70a..47ec5ba23fa 100644 --- a/reactos/ntoskrnl/se/sd.c +++ b/reactos/ntoskrnl/se/sd.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: kernel/se/sd.c - * PROGRAMER: David Welch - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/sd.c + * PURPOSE: Security manager + * + * PROGRAMMERS: David Welch */ /* INCLUDES *****************************************************************/ @@ -110,7 +109,7 @@ SepInitSDs(VOID) } /* - * @unimplemented + * @implemented */ NTSTATUS STDCALL @@ -122,8 +121,307 @@ SeCaptureSecurityDescriptor( OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor ) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + SECURITY_DESCRIPTOR DescriptorCopy; + PSECURITY_DESCRIPTOR NewDescriptor; + ULONG OwnerSAC = 0, GroupSAC = 0; + ULONG OwnerSize = 0, GroupSize = 0; + ULONG SaclSize = 0, DaclSize = 0; + ULONG DescriptorSize = 0; + NTSTATUS Status = STATUS_SUCCESS; + + if(OriginalSecurityDescriptor != NULL) + { + if(CurrentMode != KernelMode) + { + _SEH_TRY + { + /* first only probe and copy until the control field of the descriptor + to determine whether it's a self-relative descriptor */ + DescriptorSize = (ULONG)((ULONG_PTR)&OriginalSecurityDescriptor->Control - + (ULONG_PTR)OriginalSecurityDescriptor) + + sizeof(OriginalSecurityDescriptor->Control); + ProbeForRead(OriginalSecurityDescriptor, + DescriptorSize, + sizeof(ULONG)); + + if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) + { + Status = STATUS_UNKNOWN_REVISION; + _SEH_LEAVE; + } + + /* make a copy on the stack */ + DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision; + DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1; + DescriptorCopy.Control = OriginalSecurityDescriptor->Control; + DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ? + sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR)); + + /* probe and copy the entire security descriptor structure. The SIDs + and ACLs will be probed and copied later though */ + ProbeForRead(OriginalSecurityDescriptor, + DescriptorSize, + sizeof(ULONG)); + if(DescriptorCopy.Control & SE_SELF_RELATIVE) + { + PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor; + + DescriptorCopy.Owner = (PSID)RelSD->Owner; + DescriptorCopy.Group = (PSID)RelSD->Group; + DescriptorCopy.Sacl = (PACL)RelSD->Sacl; + DescriptorCopy.Dacl = (PACL)RelSD->Dacl; + } + else + { + DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner; + DescriptorCopy.Group = OriginalSecurityDescriptor->Group; + DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl; + DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl; + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else if(!CaptureIfKernel) + { + if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) + { + return STATUS_UNKNOWN_REVISION; + } + + *CapturedSecurityDescriptor = OriginalSecurityDescriptor; + return STATUS_SUCCESS; + } + else + { + if(OriginalSecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1) + { + return STATUS_UNKNOWN_REVISION; + } + + /* make a copy on the stack */ + DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision; + DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1; + DescriptorCopy.Control = OriginalSecurityDescriptor->Control; + DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ? + sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR)); + if(DescriptorCopy.Control & SE_SELF_RELATIVE) + { + PSECURITY_DESCRIPTOR_RELATIVE RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor; + + DescriptorCopy.Owner = (PSID)RelSD->Owner; + DescriptorCopy.Group = (PSID)RelSD->Group; + DescriptorCopy.Sacl = (PACL)RelSD->Sacl; + DescriptorCopy.Dacl = (PACL)RelSD->Dacl; + } + else + { + DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner; + DescriptorCopy.Group = OriginalSecurityDescriptor->Group; + DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl; + DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl; + } + } + + if(DescriptorCopy.Control & SE_SELF_RELATIVE) + { + /* in case we're dealing with a self-relative descriptor, do a basic convert + to an absolute descriptor. We do this so we can simply access the data + using the pointers without calculating them again. */ + DescriptorCopy.Control &= ~SE_SELF_RELATIVE; + if(DescriptorCopy.Owner != NULL) + { + DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Owner); + } + if(DescriptorCopy.Group != NULL) + { + DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Group); + } + if(DescriptorCopy.Dacl != NULL) + { + DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Dacl); + } + if(DescriptorCopy.Sacl != NULL) + { + DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor + (ULONG_PTR)DescriptorCopy.Sacl); + } + } + + /* determine the size of the SIDs */ +#define DetermineSIDSize(SidType) \ + do { \ + if(DescriptorCopy.SidType != NULL) \ + { \ + SID *SidType = (SID*)DescriptorCopy.SidType; \ + \ + if(CurrentMode != KernelMode) \ + { \ + /* securely access the buffers! */ \ + _SEH_TRY \ + { \ + ProbeForRead(&SidType->SubAuthorityCount, \ + sizeof(SidType->SubAuthorityCount), \ + 1); \ + SidType##SAC = SidType->SubAuthorityCount; \ + SidType##Size = RtlLengthRequiredSid(SidType##SAC); \ + DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \ + ProbeForRead(SidType, \ + SidType##Size, \ + sizeof(ULONG)); \ + if(!RtlValidSid(SidType)) \ + { \ + Status = STATUS_INVALID_SID; \ + } \ + } \ + _SEH_HANDLE \ + { \ + Status = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(Status)) \ + { \ + return Status; \ + } \ + } \ + else \ + { \ + SidType##SAC = SidType->SubAuthorityCount; \ + SidType##Size = RtlLengthRequiredSid(SidType##SAC); \ + DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \ + } \ + } \ + } while(0) + + DetermineSIDSize(Owner); + DetermineSIDSize(Group); + + /* determine the size of the ACLs */ +#define DetermineACLSize(AclType, AclFlag) \ + do { \ + if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \ + DescriptorCopy.AclType != NULL) \ + { \ + PACL AclType = (PACL)DescriptorCopy.AclType; \ + \ + if(CurrentMode != KernelMode) \ + { \ + /* securely access the buffers! */ \ + _SEH_TRY \ + { \ + ProbeForRead(&AclType->AclSize, \ + sizeof(AclType->AclSize), \ + 1); \ + AclType##Size = AclType->AclSize; \ + DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \ + ProbeForRead(AclType, \ + AclType##Size, \ + sizeof(ULONG)); \ + if(!RtlValidAcl(AclType)) \ + { \ + Status = STATUS_INVALID_ACL; \ + } \ + } \ + _SEH_HANDLE \ + { \ + Status = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(Status)) \ + { \ + return Status; \ + } \ + } \ + else \ + { \ + AclType##Size = AclType->AclSize; \ + DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \ + } \ + } \ + else \ + { \ + DescriptorCopy.AclType = NULL; \ + } \ + } while(0) + + DetermineACLSize(Sacl, SACL); + DetermineACLSize(Dacl, DACL); + + /* allocate enough memory to store a complete copy of a self-relative + security descriptor */ + NewDescriptor = ExAllocatePool(PoolType, + DescriptorSize); + if(NewDescriptor != NULL) + { + ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR); + + NewDescriptor->Revision = DescriptorCopy.Revision; + NewDescriptor->Sbz1 = DescriptorCopy.Sbz1; + NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE; + + _SEH_TRY + { + /* setup the offsets and copy the SIDs and ACLs to the new + self-relative security descriptor. Probing the pointers is not + neccessary anymore as we did that when collecting the sizes! */ +#define CopySIDOrACL(Type) \ + do { \ + if(DescriptorCopy.Type != NULL) \ + { \ + NewDescriptor->Type = (PVOID)Offset; \ + RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \ + (ULONG_PTR)NewDescriptor->Type), \ + DescriptorCopy.Type, \ + Type##Size); \ + Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \ + } \ + } while(0) + + CopySIDOrACL(Owner); + CopySIDOrACL(Group); + CopySIDOrACL(Sacl); + CopySIDOrACL(Dacl); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(NT_SUCCESS(Status)) + { + /* we're finally done! copy the pointer to the captured descriptor to + to the caller */ + *CapturedSecurityDescriptor = NewDescriptor; + return STATUS_SUCCESS; + } + else + { + /* we failed to copy the data to the new descriptor */ + ExFreePool(NewDescriptor); + } + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + /* nothing to do... */ + *CapturedSecurityDescriptor = NULL; + } + + return Status; } /* @@ -136,10 +434,11 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor OPTIONAL) { PSECURITY_DESCRIPTOR ObjectSd; - PSID Owner = 0; - PSID Group = 0; - PACL Dacl = 0; - PACL Sacl = 0; + PSECURITY_DESCRIPTOR_RELATIVE RelSD; + PSID Owner = NULL; + PSID Group = NULL; + PACL Dacl = NULL; + PACL Sacl = NULL; ULONG OwnerLength = 0; ULONG GroupLength = 0; ULONG DaclLength = 0; @@ -147,19 +446,20 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, ULONG Control = 0; ULONG_PTR Current; ULONG SdLength; + + RelSD = (PSECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor; if (*ObjectsSecurityDescriptor == NULL) { - if (*Length < sizeof(SECURITY_DESCRIPTOR)) + if (*Length < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) { - *Length = sizeof(SECURITY_DESCRIPTOR); + *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); return STATUS_BUFFER_TOO_SMALL; } - *Length = sizeof(SECURITY_DESCRIPTOR); - RtlCreateSecurityDescriptor(SecurityDescriptor, - SECURITY_DESCRIPTOR_REVISION); - SecurityDescriptor->Control |= SE_SELF_RELATIVE; + *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + RtlCreateSecurityDescriptorRelative(RelSD, + SECURITY_DESCRIPTOR_REVISION); return STATUS_SUCCESS; } @@ -206,26 +506,26 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, } SdLength = OwnerLength + GroupLength + DaclLength + - SaclLength + sizeof(SECURITY_DESCRIPTOR); - if (*Length < sizeof(SECURITY_DESCRIPTOR)) + SaclLength + sizeof(SECURITY_DESCRIPTOR_RELATIVE); + if (*Length < SdLength) { *Length = SdLength; return STATUS_BUFFER_TOO_SMALL; } /* Build the new security descrtiptor */ - RtlCreateSecurityDescriptor(SecurityDescriptor, - SECURITY_DESCRIPTOR_REVISION); - SecurityDescriptor->Control = Control; + RtlCreateSecurityDescriptorRelative(RelSD, + SECURITY_DESCRIPTOR_REVISION); + RelSD->Control = Control; - Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR); + Current = (ULONG_PTR)(RelSD + 1); if (OwnerLength != 0) { RtlCopyMemory((PVOID)Current, Owner, OwnerLength); - SecurityDescriptor->Owner = (PSID)(Current - (ULONG_PTR)SecurityDescriptor); + RelSD->Owner = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); Current += OwnerLength; } @@ -234,7 +534,7 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, RtlCopyMemory((PVOID)Current, Group, GroupLength); - SecurityDescriptor->Group = (PSID)(Current - (ULONG_PTR)SecurityDescriptor); + RelSD->Group = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); Current += GroupLength; } @@ -243,7 +543,7 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, RtlCopyMemory((PVOID)Current, Dacl, DaclLength); - SecurityDescriptor->Dacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor); + RelSD->Dacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); Current += DaclLength; } @@ -252,7 +552,7 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, RtlCopyMemory((PVOID)Current, Sacl, SaclLength); - SecurityDescriptor->Sacl = (PACL)(Current - (ULONG_PTR)SecurityDescriptor); + RelSD->Sacl = (ULONG)(Current - (ULONG_PTR)SecurityDescriptor); Current += SaclLength; } @@ -262,7 +562,7 @@ SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, } /* - * @unimplemented + * @implemented */ NTSTATUS STDCALL @@ -272,8 +572,18 @@ SeReleaseSecurityDescriptor( IN BOOLEAN CaptureIfKernelMode ) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + /* WARNING! You need to call this function with the same value for CurrentMode + and CaptureIfKernelMode that you previously passed to + SeCaptureSecurityDescriptor() in order to avoid memory leaks! */ + if(CapturedSecurityDescriptor != NULL && + (CurrentMode == UserMode || + (CurrentMode == KernelMode && CaptureIfKernelMode))) + { + /* only delete the descriptor when SeCaptureSecurityDescriptor() allocated one! */ + ExFreePool(CapturedSecurityDescriptor); + } + + return STATUS_SUCCESS; } /* @@ -319,7 +629,7 @@ SeValidSecurityDescriptor(IN ULONG Length, IN PSECURITY_DESCRIPTOR SecurityDescriptor) { ULONG SdLength; - PSID Sid; + PISID Sid; PACL Acl; if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH) @@ -355,7 +665,7 @@ SeValidSecurityDescriptor(IN ULONG Length, return FALSE; } - Sid = (PSID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner); + Sid = (PISID)((ULONG_PTR)SecurityDescriptor + (ULONG_PTR)SecurityDescriptor->Owner); if (Sid->Revision != SID_REVISION) { DPRINT1("Invalid Owner SID revision\n"); diff --git a/reactos/ntoskrnl/se/semgr.c b/reactos/ntoskrnl/se/semgr.c index c7c802e718b..1df75460793 100644 --- a/reactos/ntoskrnl/se/semgr.c +++ b/reactos/ntoskrnl/se/semgr.c @@ -1,12 +1,11 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: kernel/se/semgr.c - * PROGRAMER: ? - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/semgr.c + * PURPOSE: Security manager + * + * PROGRAMMERS: No programmer listed. */ /* INCLUDES *****************************************************************/ @@ -84,7 +83,7 @@ SeInitSRM(VOID) OBJ_PERMANENT, 0, NULL); - Status = NtCreateDirectoryObject(&DirectoryHandle, + Status = ZwCreateDirectoryObject(&DirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) @@ -101,7 +100,7 @@ SeInitSRM(VOID) OBJ_PERMANENT, DirectoryHandle, SePublicDefaultSd); - Status = NtCreateEvent(&EventHandle, + Status = ZwCreateEvent(&EventHandle, EVENT_ALL_ACCESS, &ObjectAttributes, SynchronizationEvent, @@ -113,8 +112,8 @@ SeInitSRM(VOID) return FALSE; } - NtClose(EventHandle); - NtClose(DirectoryHandle); + ZwClose(EventHandle); + ZwClose(DirectoryHandle); /* FIXME: Create SRM port and listener thread */ @@ -320,7 +319,7 @@ SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, POOL_TYPE PoolType) { PSECURITY_DESCRIPTOR Descriptor; - PACCESS_TOKEN Token; + PTOKEN Token; ULONG OwnerLength = 0; ULONG GroupLength = 0; ULONG DaclLength = 0; @@ -557,10 +556,11 @@ SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, static BOOLEAN -SepSidInToken(PACCESS_TOKEN Token, +SepSidInToken(PACCESS_TOKEN _Token, PSID Sid) { ULONG i; + PTOKEN Token = (PTOKEN)_Token; if (Token->UserAndGroupCount == 0) { @@ -793,7 +793,7 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, { SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; KPROCESSOR_MODE PreviousMode; - PACCESS_TOKEN Token; + PTOKEN Token; NTSTATUS Status; DPRINT("NtAccessCheck() called\n"); diff --git a/reactos/ntoskrnl/se/sid.c b/reactos/ntoskrnl/se/sid.c index c60dba2640a..d925ee3df63 100644 --- a/reactos/ntoskrnl/se/sid.c +++ b/reactos/ntoskrnl/se/sid.c @@ -1,19 +1,18 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: ntoskrnl/se/sid.c - * PROGRAMER: David Welch - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/sid.c + * PURPOSE: Security manager + * + * PROGRAMMERS: David Welch */ /* INCLUDES *****************************************************************/ -#include -#include +#include +#define NDEBUG #include #define TAG_SID TAG('S', 'I', 'D', 'T') @@ -467,230 +466,4 @@ SepInitSecurityIDs(VOID) return(TRUE); } - -/* - * @implemented - */ -BOOLEAN STDCALL -RtlValidSid(PSID Sid) -{ - if ((Sid->Revision & 0xf) != 1) - { - return(FALSE); - } - if (Sid->SubAuthorityCount > 15) - { - return(FALSE); - } - return(TRUE); -} - - -/* - * @implemented - */ -ULONG STDCALL -RtlLengthRequiredSid(UCHAR SubAuthorityCount) -{ - return(sizeof(SID) + (SubAuthorityCount - 1) * sizeof(ULONG)); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlInitializeSid(PSID Sid, - PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, - UCHAR SubAuthorityCount) -{ - Sid->Revision = 1; - Sid->SubAuthorityCount = SubAuthorityCount; - RtlCopyMemory(&Sid->IdentifierAuthority, - IdentifierAuthority, - sizeof(SID_IDENTIFIER_AUTHORITY)); - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -PULONG STDCALL -RtlSubAuthoritySid(PSID Sid, - ULONG SubAuthority) -{ - return(&Sid->SubAuthority[SubAuthority]); -} - - -/* - * @implemented - */ -PUCHAR STDCALL -RtlSubAuthorityCountSid(PSID Sid) -{ - return(&Sid->SubAuthorityCount); -} - - -/* - * @implemented - */ -BOOLEAN STDCALL -RtlEqualSid(PSID Sid1, - PSID Sid2) -{ - if (Sid1->Revision != Sid2->Revision) - { - return(FALSE); - } - if ((*RtlSubAuthorityCountSid(Sid1)) != - (*RtlSubAuthorityCountSid(Sid2))) - { - return(FALSE); - } - if (memcmp(Sid1, Sid2, RtlLengthSid(Sid1)) != 0) - { - return(FALSE); - } - return(TRUE); -} - - -/* - * @implemented - */ -ULONG STDCALL -RtlLengthSid(PSID Sid) -{ - return(sizeof(SID) + (Sid->SubAuthorityCount-1)*4); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlCopySid(ULONG BufferLength, - PSID Dest, - PSID Src) -{ - if (BufferLength < RtlLengthSid(Src)) - { - return(STATUS_UNSUCCESSFUL); - } - memmove(Dest, Src, RtlLengthSid(Src)); - return(STATUS_SUCCESS); -} - - -NTSTATUS STDCALL -RtlCopySidAndAttributesArray(ULONG Count, - PSID_AND_ATTRIBUTES Src, - ULONG SidAreaSize, - PSID_AND_ATTRIBUTES Dest, - PVOID SidArea, - PVOID* RemainingSidArea, - PULONG RemainingSidAreaSize) -{ - ULONG Length; - ULONG i; - - Length = SidAreaSize; - - for (i=0; i Length) - { - return(STATUS_BUFFER_TOO_SMALL); - } - Length = Length - RtlLengthSid(Src[i].Sid); - Dest[i].Sid = SidArea; - Dest[i].Attributes = Src[i].Attributes; - RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid); - SidArea = (char*)SidArea + RtlLengthSid(Src[i].Sid); - } - *RemainingSidArea = SidArea; - *RemainingSidAreaSize = Length; - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -RtlConvertSidToUnicodeString(PUNICODE_STRING String, - PSID Sid, - BOOLEAN AllocateString) -{ - WCHAR Buffer[256]; - PWSTR Ptr; - ULONG Length; - ULONG i; - - if (!RtlValidSid(Sid)) - return STATUS_INVALID_SID; - - Ptr = Buffer; - Ptr += swprintf (Ptr, - L"S-%u-", - Sid->Revision); - - if(!Sid->IdentifierAuthority.Value[0] && - !Sid->IdentifierAuthority.Value[1]) - { - Ptr += swprintf(Ptr, - L"%u", - (ULONG)Sid->IdentifierAuthority.Value[2] << 24 | - (ULONG)Sid->IdentifierAuthority.Value[3] << 16 | - (ULONG)Sid->IdentifierAuthority.Value[4] << 8 | - (ULONG)Sid->IdentifierAuthority.Value[5]); - } - else - { - Ptr += swprintf(Ptr, - L"0x%02hx%02hx%02hx%02hx%02hx%02hx", - Sid->IdentifierAuthority.Value[0], - Sid->IdentifierAuthority.Value[1], - Sid->IdentifierAuthority.Value[2], - Sid->IdentifierAuthority.Value[3], - Sid->IdentifierAuthority.Value[4], - Sid->IdentifierAuthority.Value[5]); - } - - for (i = 0; i < Sid->SubAuthorityCount; i++) - { - Ptr += swprintf(Ptr, - L"-%u", - Sid->SubAuthority[i]); - } - - Length = (Ptr - Buffer) * sizeof(WCHAR); - - if (AllocateString) - { - String->Buffer = ExAllocatePool(NonPagedPool, - Length + sizeof(WCHAR)); - if (String->Buffer == NULL) - return STATUS_NO_MEMORY; - - String->MaximumLength = Length + sizeof(WCHAR); - } - else - { - if (Length > String->MaximumLength) - return STATUS_BUFFER_TOO_SMALL; - } - String->Length = Length; - memmove(String->Buffer, - Buffer, - Length); - if (Length < String->MaximumLength) - String->Buffer[Length/sizeof(WCHAR)] = 0; - - return STATUS_SUCCESS; -} - /* EOF */ diff --git a/reactos/ntoskrnl/se/token.c b/reactos/ntoskrnl/se/token.c index 9b738e1cfce..048e8dfc332 100644 --- a/reactos/ntoskrnl/se/token.c +++ b/reactos/ntoskrnl/se/token.c @@ -1,23 +1,16 @@ /* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: Security manager - * FILE: kernel/se/token.c - * PROGRAMER: David Welch - * REVISION HISTORY: - * 26/07/98: Added stubs for security functions + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/se/token.c + * PURPOSE: Security manager + * + * PROGRAMMERS: David Welch */ /* INCLUDES *****************************************************************/ -#include -#define NTOS_MODE_KERNEL -#include -#include -#include -#include -#include +#include #define NDEBUG #include @@ -31,8 +24,6 @@ static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ, TOKEN_EXECUTE, TOKEN_ALL_ACCESS}; -//#define SYSTEM_LUID 0x3E7; - /* FUNCTIONS *****************************************************************/ VOID SepFreeProxyData(PVOID ProxyData) @@ -47,10 +38,11 @@ NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src) } NTSTATUS SeExchangePrimaryToken(PEPROCESS Process, - PACCESS_TOKEN NewToken, + PACCESS_TOKEN NewTokenP, PACCESS_TOKEN* OldTokenP) { - PACCESS_TOKEN OldToken; + PTOKEN OldToken; + PTOKEN NewToken = (PTOKEN)NewTokenP; if (NewToken->TokenType != TokenPrimary) { @@ -68,7 +60,7 @@ NTSTATUS SeExchangePrimaryToken(PEPROCESS Process, SepTokenObjectType, KernelMode); OldToken->TokenInUse = 0; - *OldTokenP = OldToken; + *OldTokenP = (PACCESS_TOKEN)OldToken; return(STATUS_SUCCESS); } @@ -88,7 +80,7 @@ RtlLengthSidAndAttributes(ULONG Count, NTSTATUS -SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token, +SepFindPrimaryGroupAndDefaultOwner(PTOKEN Token, PSID PrimaryGroup, PSID DefaultOwner) { @@ -131,13 +123,13 @@ SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token, NTSTATUS -SepDuplicateToken(PACCESS_TOKEN Token, +SepDuplicateToken(PTOKEN Token, POBJECT_ATTRIBUTES ObjectAttributes, BOOLEAN EffectiveOnly, TOKEN_TYPE TokenType, SECURITY_IMPERSONATION_LEVEL Level, KPROCESSOR_MODE PreviousMode, - PACCESS_TOKEN* NewAccessToken) + PTOKEN* NewAccessToken) { NTSTATUS Status; ULONG uLength; @@ -145,14 +137,14 @@ SepDuplicateToken(PACCESS_TOKEN Token, PVOID EndMem; - PACCESS_TOKEN AccessToken; + PTOKEN AccessToken; Status = ObCreateObject(PreviousMode, SepTokenObjectType, ObjectAttributes, PreviousMode, NULL, - sizeof(ACCESS_TOKEN), + sizeof(TOKEN), 0, 0, (PVOID*)&AccessToken); @@ -266,8 +258,8 @@ SepInitializeNewProcess(struct _EPROCESS* NewProcess, struct _EPROCESS* ParentProcess) { NTSTATUS Status; - PACCESS_TOKEN pNewToken; - PACCESS_TOKEN pParentToken; + PTOKEN pNewToken; + PTOKEN pParentToken; OBJECT_ATTRIBUTES ObjectAttributes; @@ -328,7 +320,8 @@ SeCopyClientToken(PACCESS_TOKEN Token, TokenImpersonation, Level, PreviousMode, - NewToken); + (PTOKEN*)&NewToken); + return(Status); } @@ -419,7 +412,7 @@ SeCreateClientSecurity(IN struct _ETHREAD *Thread, ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode; ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly; ClientContext->ServerIsRemote = RemoteClient; - ClientContext->Token = NewToken; + ClientContext->ClientToken = NewToken; return(STATUS_SUCCESS); } @@ -507,7 +500,7 @@ SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext, ServerThread = PsGetCurrentThread(); } PsImpersonateClient(ServerThread, - ClientContext->Token, + ClientContext->ClientToken, 1, (ULONG)b, ClientContext->SecurityQos.ImpersonationLevel); @@ -517,7 +510,7 @@ SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext, VOID STDCALL SepDeleteToken(PVOID ObjectBody) { - PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody; + PTOKEN AccessToken = (PTOKEN)ObjectBody; if (AccessToken->UserAndGroups) ExFreePool(AccessToken->UserAndGroups); @@ -536,12 +529,12 @@ SepInitializeTokenImplementation(VOID) SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T'); - SepTokenObjectType->MaxObjects = ULONG_MAX; - SepTokenObjectType->MaxHandles = ULONG_MAX; + SepTokenObjectType->PeakObjects = 0; + SepTokenObjectType->PeakHandles = 0; SepTokenObjectType->TotalObjects = 0; SepTokenObjectType->TotalHandles = 0; SepTokenObjectType->PagedPoolCharge = 0; - SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN); + SepTokenObjectType->NonpagedPoolCharge = sizeof(TOKEN); SepTokenObjectType->Mapping = &SepTokenMapping; SepTokenObjectType->Dump = NULL; SepTokenObjectType->Open = NULL; @@ -554,8 +547,8 @@ SepInitializeTokenImplementation(VOID) SepTokenObjectType->Create = NULL; SepTokenObjectType->DuplicationNotify = NULL; - RtlCreateUnicodeString(&SepTokenObjectType->TypeName, - L"Token"); + RtlpCreateUnicodeString(&SepTokenObjectType->TypeName, + L"Token", NonPagedPool); ObpCreateTypeObject (SepTokenObjectType); } @@ -573,7 +566,7 @@ NtQueryInformationToken(IN HANDLE TokenHandle, NTSTATUS Status, LengthStatus; PVOID UnusedInfo; PVOID EndMem; - PACCESS_TOKEN Token; + PTOKEN Token; ULONG Length; PTOKEN_GROUPS PtrTokenGroups; PTOKEN_DEFAULT_DACL PtrDefaultDacl; @@ -844,8 +837,18 @@ NtQueryInformationToken(IN HANDLE TokenHandle, break; case TokenSessionId: - DPRINT1("NtQueryInformationToken(TokenSessionId) not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; + DPRINT("NtQueryInformationToken(TokenSessionId)\n"); + if (TokenInformationLength < sizeof(ULONG)) + { + Length = sizeof(ULONG); + Status = MmCopyToCaller(ReturnLength, &Length, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = MmCopyToCaller(TokenInformation, &Token->SessionId, sizeof(ULONG)); + } break; default: @@ -901,7 +904,7 @@ NtSetInformationToken(IN HANDLE TokenHandle, IN ULONG TokenInformationLength) { NTSTATUS Status; - PACCESS_TOKEN Token; + PTOKEN Token; TOKEN_OWNER TokenOwnerSet = { 0 }; TOKEN_PRIMARY_GROUP TokenPrimaryGroupSet = { 0 }; DWORD NeededAccess = 0; @@ -1026,6 +1029,7 @@ NtSetInformationToken(IN HANDLE TokenHandle, * NOTE: Some sources claim 4th param is ImpersonationLevel, but on W2K * this is certainly NOT true, thou i can't say for sure that EffectiveOnly * is correct either. -Gunnar + * This is true. EffectiveOnly overrides SQOS.EffectiveOnly. - IAI */ NTSTATUS STDCALL NtDuplicateToken(IN HANDLE ExistingTokenHandle, @@ -1036,8 +1040,8 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle, OUT PHANDLE NewTokenHandle) { KPROCESSOR_MODE PreviousMode; - PACCESS_TOKEN Token; - PACCESS_TOKEN NewToken; + PTOKEN Token; + PTOKEN NewToken; NTSTATUS Status; PreviousMode = KeGetPreviousMode(); @@ -1058,7 +1062,7 @@ NtDuplicateToken(IN HANDLE ExistingTokenHandle, EffectiveOnly, TokenType, ObjectAttributes->SecurityQualityOfService ? - ObjectAttributes->SecurityQualityOfService->ImpersonationLevel : + ((PSECURITY_QUALITY_OF_SERVICE)(ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel : 0 /*SecurityAnonymous*/, PreviousMode, &NewToken); @@ -1213,7 +1217,7 @@ NtAdjustPrivilegesToken (IN HANDLE TokenHandle, // PLUID_AND_ATTRIBUTES Privileges; KPROCESSOR_MODE PreviousMode; // ULONG PrivilegeCount; - PACCESS_TOKEN Token; + PTOKEN Token; // ULONG Length; ULONG i; ULONG j; @@ -1363,7 +1367,7 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process) ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid); ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid); - PACCESS_TOKEN AccessToken; + PTOKEN AccessToken; PVOID SidArea; @@ -1375,7 +1379,7 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process) NULL, KernelMode, NULL, - sizeof(ACCESS_TOKEN), + sizeof(TOKEN), 0, 0, (PVOID*)&AccessToken); @@ -1559,7 +1563,7 @@ SepCreateSystemProcessToken(struct _EPROCESS* Process) NTSTATUS STDCALL NtCreateToken(OUT PHANDLE UnsafeTokenHandle, IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES UnsafeObjectAttributes, + IN POBJECT_ATTRIBUTES ObjectAttributes, IN TOKEN_TYPE TokenType, IN PLUID AuthenticationId, IN PLARGE_INTEGER ExpirationTime, @@ -1572,24 +1576,14 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle, IN PTOKEN_SOURCE TokenSource) { HANDLE TokenHandle; - PACCESS_TOKEN AccessToken; + PTOKEN AccessToken; NTSTATUS Status; - OBJECT_ATTRIBUTES SafeObjectAttributes; - POBJECT_ATTRIBUTES ObjectAttributes; LUID TokenId; LUID ModifiedId; PVOID EndMem; ULONG uLength; ULONG i; - Status = MmCopyFromCaller(&SafeObjectAttributes, - UnsafeObjectAttributes, - sizeof(OBJECT_ATTRIBUTES)); - if (!NT_SUCCESS(Status)) - return(Status); - - ObjectAttributes = &SafeObjectAttributes; - Status = ZwAllocateLocallyUniqueId(&TokenId); if (!NT_SUCCESS(Status)) return(Status); @@ -1603,7 +1597,7 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle, ObjectAttributes, ExGetPreviousMode(), NULL, - sizeof(ACCESS_TOKEN), + sizeof(TOKEN), 0, 0, (PVOID*)&AccessToken); @@ -1643,7 +1637,8 @@ NtCreateToken(OUT PHANDLE UnsafeTokenHandle, AccessToken->Privileges = 0; AccessToken->TokenType = TokenType; - AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel; + AccessToken->ImpersonationLevel = ((PSECURITY_QUALITY_OF_SERVICE) + (ObjectAttributes->SecurityQualityOfService))->ImpersonationLevel; /* * Normally we would just point these members into the variable information @@ -1744,8 +1739,7 @@ NTSTATUS STDCALL SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, OUT PLUID LogonId) { - LogonId->LowPart = Token->AuthenticationId.LowPart; - LogonId->HighPart = Token->AuthenticationId.HighPart; + *LogonId = ((PTOKEN)Token)->AuthenticationId; return STATUS_SUCCESS; } @@ -1754,10 +1748,11 @@ SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, /* * @implemented */ -SECURITY_IMPERSONATION_LEVEL STDCALL +SECURITY_IMPERSONATION_LEVEL +STDCALL SeTokenImpersonationLevel(IN PACCESS_TOKEN Token) { - return Token->ImpersonationLevel; + return ((PTOKEN)Token)->ImpersonationLevel; } @@ -1767,7 +1762,7 @@ SeTokenImpersonationLevel(IN PACCESS_TOKEN Token) TOKEN_TYPE STDCALL SeTokenType(IN PACCESS_TOKEN Token) { - return Token->TokenType; + return ((PTOKEN)Token)->TokenType; } @@ -1823,7 +1818,7 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle, OUT PHANDLE TokenHandle) { PETHREAD Thread; - PACCESS_TOKEN Token, NewToken, PrimaryToken; + PTOKEN Token, NewToken, PrimaryToken; BOOLEAN CopyOnOpen, EffectiveOnly; SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; SE_IMPERSONATION_STATE ImpersonationState; diff --git a/reactos/ntoskrnl/tests/setup.c b/reactos/ntoskrnl/tests/setup.c index 507484da7bd..8228221448d 100644 --- a/reactos/ntoskrnl/tests/setup.c +++ b/reactos/ntoskrnl/tests/setup.c @@ -1,3 +1,13 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/tests/setup.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #include #include "regtests.h" diff --git a/reactos/ntoskrnl/tests/tests/VirtualMemory.c b/reactos/ntoskrnl/tests/tests/VirtualMemory.c index e6642311f47..d8dc36cbab8 100644 --- a/reactos/ntoskrnl/tests/tests/VirtualMemory.c +++ b/reactos/ntoskrnl/tests/tests/VirtualMemory.c @@ -1,3 +1,13 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/tests/tests/VirtualMemory.c + * PURPOSE: No purpose listed. + * + * PROGRAMMERS: No programmer listed. + */ + #include #include "regtests.h" diff --git a/reactos/regtests/shared/regtests.h b/reactos/regtests/shared/regtests.h index 9d2847d2eda..fe340a71e58 100755 --- a/reactos/regtests/shared/regtests.h +++ b/reactos/regtests/shared/regtests.h @@ -206,7 +206,7 @@ static inline PVOID FrameworkGetFunction(PAPI_DESCRIPTION ApiDescription) { HANDLE hModule; - PVOID function; + PVOID function = NULL; PCHAR exportedFunctionName; exportedFunctionName = FrameworkGetExportedFunctionNameInternal(ApiDescription); diff --git a/reactos/services/directory.xml b/reactos/services/directory.xml index 17f55c00ca0..13d13cc18c5 100644 --- a/reactos/services/directory.xml +++ b/reactos/services/directory.xml @@ -4,3 +4,6 @@ + + + diff --git a/reactos/services/eventlog/eventlog.c b/reactos/services/eventlog/eventlog.c index 77d521aae77..4da6ffcd263 100644 --- a/reactos/services/eventlog/eventlog.c +++ b/reactos/services/eventlog/eventlog.c @@ -52,10 +52,10 @@ VOID CALLBACK ServiceMain(DWORD argc, LPTSTR *argv) { - DPRINT1("ServiceMain() called\n"); + DPRINT("ServiceMain() called\n"); - DPRINT1("ServiceMain() done\n"); + DPRINT("ServiceMain() done\n"); } diff --git a/reactos/services/umpnpmgr/makefile b/reactos/services/umpnpmgr/makefile new file mode 100644 index 00000000000..f96bb8bd878 --- /dev/null +++ b/reactos/services/umpnpmgr/makefile @@ -0,0 +1,23 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = umpnpmgr + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a rpcrt4.a + +TARGET_OBJECTS = umpnpmgr.o + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/reactos/services/umpnpmgr/umpnpmgr.c b/reactos/services/umpnpmgr/umpnpmgr.c new file mode 100644 index 00000000000..b9b5659091b --- /dev/null +++ b/reactos/services/umpnpmgr/umpnpmgr.c @@ -0,0 +1,155 @@ +/* + * ReactOS kernel + * Copyright (C) 2005 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/umpnpmgr/umpnpmgr.c + * PURPOSE: User-mode Plug and Play manager + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#define UNICODE +#define _UNICODE + +#define NTOS_MODE_USER +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DBG +#define NDEBUG +#include + + + +/* GLOBALS ******************************************************************/ + +static VOID CALLBACK +ServiceMain(DWORD argc, LPTSTR *argv); + +static SERVICE_TABLE_ENTRY ServiceTable[2] = +{ + {_T("PlugPlay"), ServiceMain}, + {NULL, NULL} +}; + + +/* FUNCTIONS *****************************************************************/ + +static DWORD WINAPI +PnpEventThread(LPVOID lpParameter) +{ + PPLUGPLAY_EVENT_BLOCK PnpEvent; + ULONG PnpEventSize; + NTSTATUS Status; + RPC_STATUS RpcStatus; + + PnpEventSize = 0x1000; + PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize); + if (PnpEvent == NULL) + return ERROR_OUTOFMEMORY; + + for (;;) + { + DPRINT("Calling NtGetPlugPlayEvent()\n"); + + /* Wait for the next pnp event */ + Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize); + /* Resize the buffer for the PnP event if it's too small. */ + if (Status == STATUS_BUFFER_TOO_SMALL) + { + PnpEventSize += 0x400; + PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize); + if (PnpEvent == NULL) + return ERROR_OUTOFMEMORY; + continue; + } + if (!NT_SUCCESS(Status)) + { + DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status); + break; + } + + DPRINT("Received PnP Event\n"); + if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) + { + DPRINT1("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds); + } + else + { + DPRINT1("Unknown event\n"); + } + + /* FIXME: Process the pnp event */ + + /* Dequeue the current pnp event and signal the next one */ + NtPlugPlayControl(PLUGPLAY_USER_RESPONSE, NULL, 0); + } + + HeapFree(GetProcessHeap(), 0, PnpEvent); + + return ERROR_SUCCESS; +} + + +static VOID CALLBACK +ServiceMain(DWORD argc, LPTSTR *argv) +{ + HANDLE hThread; + DWORD dwThreadId; + + DPRINT("ServiceMain() called\n"); + + hThread = CreateThread(NULL, + 0, + PnpEventThread, + NULL, + 0, + &dwThreadId); + if (hThread != NULL) + CloseHandle(hThread); + + DPRINT("ServiceMain() done\n"); +} + + +int +main(int argc, char *argv[]) +{ + DPRINT("Umpnpmgr: main() started\n"); + + StartServiceCtrlDispatcher(ServiceTable); + + DPRINT("Umpnpmgr: main() done\n"); + + ExitThread(0); + + return 0; +} + +/* EOF */ diff --git a/reactos/services/umpnpmgr/umpnpmgr.rc b/reactos/services/umpnpmgr/umpnpmgr.rc new file mode 100644 index 00000000000..9e3f836493b --- /dev/null +++ b/reactos/services/umpnpmgr/umpnpmgr.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "User-Mode Plug and Play manager\0" +#define REACTOS_STR_INTERNAL_NAME "Umpnpmgr\0" +#define REACTOS_STR_ORIGINAL_FILENAME "Umpnpmgr.exe\0" +#include diff --git a/reactos/services/umpnpmgr/umpnpmgr.xml b/reactos/services/umpnpmgr/umpnpmgr.xml new file mode 100644 index 00000000000..fbeeff11517 --- /dev/null +++ b/reactos/services/umpnpmgr/umpnpmgr.xml @@ -0,0 +1,10 @@ + + . + + ntdll + kernel32 + advapi32 + rpcrt4 + umpnpmgr.c + umpnpmgr.rc + diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index 9f53fe51c3c..7a5bd60d846 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -25,7 +25,7 @@ static ULONG NrProcess; static PCSRSS_PROCESS_DATA ProcessData[256]; -CRITICAL_SECTION ProcessDataLock; +RTL_CRITICAL_SECTION ProcessDataLock; /* FUNCTIONS *****************************************************************/ @@ -36,12 +36,12 @@ VOID STDCALL CsrInitProcessData(VOID) RtlInitializeCriticalSection( &ProcessDataLock ); } -PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId) +PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(HANDLE ProcessId) { ULONG hash; PCSRSS_PROCESS_DATA pProcessData; - hash = ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData)); + hash = (ULONG_PTR)ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData)); LOCK; @@ -55,12 +55,12 @@ PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId) return pProcessData; } -PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(ULONG ProcessId) +PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(HANDLE ProcessId) { ULONG hash; PCSRSS_PROCESS_DATA pProcessData; - hash = ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData)); + hash = (ULONG_PTR)ProcessId % (sizeof(ProcessData) / sizeof(*ProcessData)); LOCK; @@ -94,13 +94,13 @@ PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(ULONG ProcessId) return pProcessData; } -NTSTATUS STDCALL CsrFreeProcessData(ULONG Pid) +NTSTATUS STDCALL CsrFreeProcessData(HANDLE Pid) { ULONG hash; int c; PCSRSS_PROCESS_DATA pProcessData, pPrevProcessData = NULL; - hash = Pid % (sizeof(ProcessData) / sizeof(*ProcessData)); + hash = (ULONG_PTR)Pid % (sizeof(ProcessData) / sizeof(*ProcessData)); LOCK; diff --git a/reactos/subsys/csrss/api/wapi.c b/reactos/subsys/csrss/api/wapi.c index 08f9ad93c91..bb37e9bc398 100644 --- a/reactos/subsys/csrss/api/wapi.c +++ b/reactos/subsys/csrss/api/wapi.c @@ -123,18 +123,18 @@ ClientConnectionThread(HANDLE ServerPort) if (LpcRequest.Header.MessageType == LPC_PORT_CLOSED) { - CsrFreeProcessData( (ULONG)LpcRequest.Header.ClientId.UniqueProcess ); + CsrFreeProcessData( LpcRequest.Header.ClientId.UniqueProcess ); break; } Request = (PCSRSS_API_REQUEST)&LpcRequest; Reply = (PCSRSS_API_REPLY)&LpcReply; - ProcessData = CsrGetProcessData((ULONG)LpcRequest.Header.ClientId.UniqueProcess); + ProcessData = CsrGetProcessData(LpcRequest.Header.ClientId.UniqueProcess); if (ProcessData == NULL) { - DPRINT1("CSR: Message %d: Unable to find data for process %d\n", - LpcRequest.Header.MessageType, (ULONG)LpcRequest.Header.ClientId.UniqueProcess); + DPRINT1("CSR: Message %d: Unable to find data for process 0x%x\n", + LpcRequest.Header.MessageType, LpcRequest.Header.ClientId.UniqueProcess); break; } @@ -187,11 +187,11 @@ ServerApiPortThead(PVOID PortHandle) break; } - ProcessData = CsrCreateProcessData((ULONG)Request.Header.ClientId.UniqueProcess); + ProcessData = CsrCreateProcessData(Request.Header.ClientId.UniqueProcess); if (ProcessData == NULL) { - DPRINT1("Unable to allocate or find data for process %d\n", - (ULONG)Request.Header.ClientId.UniqueProcess); + DPRINT1("Unable to allocate or find data for process 0x%x\n", + Request.Header.ClientId.UniqueProcess); Status = STATUS_UNSUCCESSFUL; break; } diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index 07f6b47e042..46ccf091ff0 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -36,7 +36,7 @@ typedef struct _CSRSS_PROCESS_DATA PCSRSS_CONSOLE Console; ULONG HandleTableSize; Object_t ** HandleTable; - ULONG ProcessId; + HANDLE ProcessId; ULONG ShutdownLevel; ULONG ShutdownFlags; HANDLE ConsoleEvent; @@ -106,9 +106,9 @@ VOID STDCALL CsrInitConsoleSupport(VOID); /* api/process.c */ VOID STDCALL CsrInitProcessData(VOID); -PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId); -PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(ULONG ProcessId); -NTSTATUS STDCALL CsrFreeProcessData( ULONG Pid ); +PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(HANDLE ProcessId); +PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(HANDLE ProcessId); +NTSTATUS STDCALL CsrFreeProcessData( HANDLE Pid ); /* api/handle.c */ NTSTATUS FASTCALL CsrRegisterObjectDefinitions(PCSRSS_OBJECT_DEFINITION NewDefinitions); diff --git a/reactos/subsys/csrss/include/conio.h b/reactos/subsys/csrss/include/conio.h index 082fab28707..2f9fca25acb 100644 --- a/reactos/subsys/csrss/include/conio.h +++ b/reactos/subsys/csrss/include/conio.h @@ -139,6 +139,7 @@ CSR_API(CsrGetConsoleCodePage); CSR_API(CsrSetConsoleCodePage); CSR_API(CsrGetConsoleOutputCodePage); CSR_API(CsrSetConsoleOutputCodePage); +CSR_API(CsrGetProcessList); #define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff)) #define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region)) diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index 2a351084746..4c82d872b59 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * reactos/subsys/csrss/win32csr/conio.c * * Console I/O functions @@ -81,10 +80,26 @@ ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData) if (ProcessData->CtrlDispatcher) { - Process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, ProcessData->ProcessId); - if (NULL == Process) + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + NTSTATUS Status; + + ClientId.UniqueThread = NULL; + ClientId.UniqueProcess = ProcessData->ProcessId; + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + + /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */ + Status = NtOpenProcess(&Process, + PROCESS_DUP_HANDLE, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(Status)) { - DPRINT1("Failed for handle duplication\n"); + DPRINT1("Failed for handle duplication, Status: 0x%x\n", Status); return; } @@ -139,7 +154,7 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, { return STATUS_INSUFFICIENT_RESOURCES; } - RtlInitializeCriticalSection(&Buffer->Header.Lock); + InitializeCriticalSection(&Buffer->Header.Lock); ConioInitScreenBuffer(Console, Buffer); /* initialize buffer to be empty with default attributes */ for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) @@ -193,7 +208,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) return STATUS_UNSUCCESSFUL; } Console->PrivateData = NULL; - RtlInitializeCriticalSection(&Console->Header.Lock); + InitializeCriticalSection(&Console->Header.Lock); GuiMode = DtbgIsDesktopVisible(); if (! GuiMode) { @@ -210,7 +225,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) if (! NT_SUCCESS(Status)) { RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return Status; } @@ -221,7 +236,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); return STATUS_INSUFFICIENT_RESOURCES; } @@ -230,7 +245,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) { ConioCleanupConsole(Console); RtlFreeUnicodeString(&Console->Title); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); CloseHandle(Console->ActiveEvent); HeapFree(Win32CsrApiHeap, 0, NewBuffer); return Status; @@ -249,6 +264,8 @@ CsrInitConsole(PCSRSS_CONSOLE Console) CSR_API(CsrAllocConsole) { PCSRSS_CONSOLE Console; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; HANDLE Process; NTSTATUS Status; @@ -302,10 +319,22 @@ CSR_API(CsrAllocConsole) return Reply->Status = Status; } - Process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, ProcessData->ProcessId); - if (NULL == Process) + ClientId.UniqueThread = NULL; + ClientId.UniqueProcess = ProcessData->ProcessId; + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + + /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */ + Status = NtOpenProcess(&Process, + PROCESS_DUP_HANDLE, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(Status)) { - DPRINT1("OpenProcess() failed for handle duplication\n"); + DPRINT1("NtOpenProcess() failed for handle duplication, Status: 0x%x\n", Status); Console->Header.ReferenceCount--; ProcessData->Console = 0; Win32CsrReleaseObject(ProcessData, Reply->Data.AllocConsoleReply.OutputHandle); @@ -313,6 +342,7 @@ CSR_API(CsrAllocConsole) Reply->Status = Status; return Status; } + if (! DuplicateHandle(GetCurrentProcess(), ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, EVENT_ALL_ACCESS, FALSE, 0)) { @@ -956,7 +986,7 @@ VOID STDCALL ConioDeleteScreenBuffer(Object_t *Object) { PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object; - RtlDeleteCriticalSection(&Buffer->Header.Lock); + DeleteCriticalSection(&Buffer->Header.Lock); HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); HeapFree(Win32CsrApiHeap, 0, Buffer); } @@ -998,7 +1028,7 @@ ConioDeleteConsole(Object_t *Object) ConioCleanupConsole(Console); CloseHandle(Console->ActiveEvent); - RtlDeleteCriticalSection(&Console->Header.Lock); + DeleteCriticalSection(&Console->Header.Lock); RtlFreeUnicodeString(&Console->Title); HeapFree(Win32CsrApiHeap, 0, Console); } @@ -1127,7 +1157,7 @@ ConioProcessChar(PCSRSS_CONSOLE Console, if (0 == (Console->Mode & ENABLE_LINE_INPUT) || Console->EarlyReturn || ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar - && ! KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)) + && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)) { if ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar) { @@ -3133,4 +3163,51 @@ CSR_API(CsrSetConsoleOutputCodePage) return Reply->Status = STATUS_UNSUCCESSFUL; } +CSR_API(CsrGetProcessList) +{ + PHANDLE Buffer; + PCSRSS_CONSOLE Console; + PCSRSS_PROCESS_DATA current; + PLIST_ENTRY current_entry; + ULONG nItems, nCopied; + NTSTATUS Status; + + DPRINT("CsrGetProcessList\n"); + + Buffer = Reply->Data.GetProcessListReply.ProcessId; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - LPC_MESSAGE_BASE_SIZE; + + nItems = nCopied = 0; + Reply->Data.GetProcessListReply.nProcessIdsCopied = 0; + Reply->Data.GetProcessListReply.nProcessIdsTotal = 0; + + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + + DPRINT1("Console_Api Ctrl-C\n"); + + for(current_entry = Console->ProcessList.Flink; + current_entry != &Console->ProcessList; + current_entry = current_entry->Flink) + { + current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry); + if(nItems++ < Request->Data.GetProcessListRequest.nMaxIds) + { + *(Buffer++) = current->ProcessId; + nCopied++; + } + } + + ConioUnlockConsole(Console); + + Reply->Data.GetProcessListReply.nProcessIdsCopied = nCopied; + Reply->Data.GetProcessListReply.nProcessIdsTotal = nItems; + + return Reply->Status = STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/subsys/csrss/win32csr/dllmain.c b/reactos/subsys/csrss/win32csr/dllmain.c index 7fd2f7b6c12..44da402f033 100644 --- a/reactos/subsys/csrss/win32csr/dllmain.c +++ b/reactos/subsys/csrss/win32csr/dllmain.c @@ -71,6 +71,7 @@ static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] = CSRSS_DEFINE_API(CSRSS_SET_CONSOLE_CP, CsrSetConsoleCodePage), CSRSS_DEFINE_API(CSRSS_GET_CONSOLE_OUTPUT_CP, CsrGetConsoleOutputCodePage), CSRSS_DEFINE_API(CSRSS_SET_CONSOLE_OUTPUT_CP, CsrSetConsoleOutputCodePage), + CSRSS_DEFINE_API(CSRSS_GET_PROCESS_LIST, CsrGetProcessList), { 0, 0, 0, NULL } }; diff --git a/reactos/subsys/csrss/win32csr/exitros.c b/reactos/subsys/csrss/win32csr/exitros.c index 57c9443eea1..11a0f247986 100644 --- a/reactos/subsys/csrss/win32csr/exitros.c +++ b/reactos/subsys/csrss/win32csr/exitros.c @@ -17,7 +17,7 @@ #include static HWND LogonNotifyWindow = NULL; -static DWORD LogonProcess = 0; +static HANDLE LogonProcess = NULL; CSR_API(CsrRegisterLogonProcess) { @@ -35,7 +35,7 @@ CSR_API(CsrRegisterLogonProcess) } else { - if ((DWORD) Request->Header.ClientId.UniqueProcess != LogonProcess) + if (Request->Header.ClientId.UniqueProcess != LogonProcess) { DPRINT1("Current logon process 0x%x, can't deregister from process 0x%x\n", LogonProcess, Request->Header.ClientId.UniqueProcess); @@ -64,7 +64,7 @@ CSR_API(CsrSetLogonNotifyWindow) Reply->Status = STATUS_INVALID_HANDLE; return Reply->Status; } - if (WindowCreator != LogonProcess) + if (WindowCreator != (DWORD)LogonProcess) { DPRINT1("Trying to register window not created by winlogon as notify window\n"); Reply->Status = STATUS_ACCESS_DENIED; diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index 46d5c4bd340..1d44b97937f 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -737,7 +737,7 @@ GuiConsoleRightMouseDown(HWND hWnd) static LRESULT CALLBACK GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - LRESULT Result; + LRESULT Result = 0; switch(msg) { @@ -746,7 +746,6 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_PAINT: GuiConsoleHandlePaint(hWnd); - Result = 0; break; case WM_KEYDOWN: case WM_KEYUP: @@ -754,19 +753,15 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_SYSKEYUP: case WM_CHAR: GuiConsoleHandleKey(hWnd, msg, wParam, lParam); - Result = 0; break; case WM_TIMER: GuiConsoleHandleTimer(hWnd); - Result = 0; break; case WM_CLOSE: GuiConsoleHandleClose(hWnd); - Result = 0; break; case WM_NCDESTROY: GuiConsoleHandleNcDestroy(hWnd); - Result = 0; break; case WM_LBUTTONDOWN: GuiConsoleLeftMouseDown(hWnd, lParam); @@ -802,7 +797,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) SetWindowLongW(hWnd, GWL_USERDATA, 0); return 0; case PM_CREATE_CONSOLE: - NewWindow = CreateWindowW(L"Win32CsrConsole", + NewWindow = CreateWindowW(L"ConsoleWindowClass", Console->Title.Buffer, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, @@ -911,7 +906,7 @@ GuiInit(VOID) } wc.cbSize = sizeof(WNDCLASSEXW); - wc.lpszClassName = L"Win32CsrConsole"; + wc.lpszClassName = L"ConsoleWindowClass"; wc.lpfnWndProc = GuiConsoleWndProc; wc.style = 0; wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL); diff --git a/reactos/subsys/smss/client.c b/reactos/subsys/smss/client.c new file mode 100644 index 00000000000..b25535e5c85 --- /dev/null +++ b/reactos/subsys/smss/client.c @@ -0,0 +1,148 @@ +/* $Id: smss.c 12852 2005-01-06 13:58:04Z mf $ + * + * client.c - Session Manager client Management + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ +#define NTOS_MODE_USER +#include +#include "smss.h" + +/* Private ADT */ + +typedef struct _SM_CLIENT_DATA +{ + USHORT SubsystemId; + BOOL Initialized; + HANDLE ServerProcess; + HANDLE ApiPort; + HANDLE SbApiPort; + struct _SM_CLIENT_DATA * Next; + +} SM_CLIENT_DATA, *PSM_CLIENT_DATA; + + +struct _SM_CLIENT_DIRECTORY +{ + RTL_CRITICAL_SECTION Lock; + ULONG Count; + PSM_CLIENT_DATA Client; + +} SmpClientDirectory; + +/********************************************************************** + * SmInitializeClientManagement/0 + */ +NTSTATUS +SmInitializeClientManagement (VOID) +{ + RtlInitializeCriticalSection(& SmpClientDirectory.Lock); + SmpClientDirectory.Count = 0; + SmpClientDirectory.Client = NULL; + return STATUS_SUCCESS; +} + +/********************************************************************** + * SmpLookupClient/1 + */ +PSM_CLIENT_DATA STDCALL +SmpLookupClient (USHORT SubsystemId) +{ + PSM_CLIENT_DATA Client = NULL; + + if (SmpClientDirectory.Count > 0) + { + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + Client = SmpClientDirectory.Client; + while (NULL != Client->Next) + { + if (SubsystemId == Client->SubsystemId) break; + Client = Client->Next; + } + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + } + return Client; +} + +/********************************************************************** + * SmpCreateClient/1 + */ +NTSTATUS STDCALL +SmpCreateClient(SM_PORT_MESSAGE Request) +{ + PSM_CLIENT_DATA pClient = NULL; + + /* + * Check if a client for the ID already exist. + */ + if (SmpLookupClient(0)) //FIXME + { + DbgPrint("SMSS: %s: attempt to register again subsystem %d.\n",__FUNCTION__,0); + return STATUS_UNSUCCESSFUL; + } + /* + * Allocate the storage for client data + */ + pClient = RtlAllocateHeap (SmpHeap, + HEAP_ZERO_MEMORY, + sizeof (SM_CLIENT_DATA)); + if (NULL == pClient) return STATUS_NO_MEMORY; + /* + * Initialize the client data + */ +// pClient->SubsystemId = Request->Subsystem; + pClient->Initialized = FALSE; + // TODO + /* + * Insert the new descriptor in the + * client directory. + */ + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + if (NULL == SmpClientDirectory.Client) + { + SmpClientDirectory.Client = pClient; + } else { + PSM_CLIENT_DATA pCD = NULL; + + for (pCD=SmpClientDirectory.Client; + (NULL != pCD->Next); + pCD = pCD->Next); + pCD->Next = pClient; + } + ++ SmpClientDirectory.Count; + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return STATUS_SUCCESS; +} + +/********************************************************************** + * SmpDestroyClient/1 + */ +NTSTATUS STDCALL +SmpDestroyClient (ULONG SubsystemId) +{ + RtlEnterCriticalSection (& SmpClientDirectory.Lock); + /* TODO */ + RtlLeaveCriticalSection (& SmpClientDirectory.Lock); + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/subsys/smss/debug.c b/reactos/subsys/smss/debug.c new file mode 100644 index 00000000000..e7848df3d62 --- /dev/null +++ b/reactos/subsys/smss/debug.c @@ -0,0 +1,92 @@ +/* $Id: smss.c 12852 2005-01-06 13:58:04Z mf $ + * + * debug.c - Session Manager debug messages switch and router + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ +#define NTOS_MODE_USER +#include +#include +#include +#include "smss.h" + +/* GLOBALS ***********************************************************/ + +HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE; +HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE; + +/* FUNCTIONS *********************************************************/ + +NTSTATUS +SmInitializeDbgSs (VOID) +{ + NTSTATUS Status; + UNICODE_STRING UnicodeString; + OBJECT_ATTRIBUTES ObjectAttributes; + + + /* Create the \DbgSsApiPort object (LPC) */ + RtlRosInitUnicodeStringFromLiteral(&UnicodeString, + L"\\DbgSsApiPort"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + PORT_ALL_ACCESS, + NULL, + NULL); + + Status = NtCreatePort(&DbgSsApiPort, + &ObjectAttributes, + 0, + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + DbgPrint("SMSS: %s: \\DbgSsApiPort created\n",__FUNCTION__); + + /* Create the \DbgUiApiPort object (LPC) */ + RtlRosInitUnicodeStringFromLiteral(&UnicodeString, + L"\\DbgUiApiPort"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + PORT_ALL_ACCESS, + NULL, + NULL); + + Status = NtCreatePort(&DbgUiApiPort, + &ObjectAttributes, + 0, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + DbgPrint("SMSS: %s: \\DbgUiApiPort created\n",__FUNCTION__); + + return STATUS_SUCCESS; +} + +/* EOF */ + diff --git a/reactos/subsys/smss/init.c b/reactos/subsys/smss/init.c index a71ae7960a3..0dcd79dac75 100644 --- a/reactos/subsys/smss/init.c +++ b/reactos/subsys/smss/init.c @@ -22,762 +22,19 @@ * MA 02139, USA. * * -------------------------------------------------------------------- - * - * 19990530 (Emanuele Aliberti) - * Compiled successfully with egcs 1.1.2 */ -/* INCLUDES *****************************************************************/ - -#include -#include -#include -#include - #include "smss.h" +#include #define NDEBUG #include -/* GLOBALS ******************************************************************/ - -HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE; -HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE; - -PWSTR SmSystemEnvironment = NULL; - /* FUNCTIONS ****************************************************************/ -static NTSTATUS STDCALL -SmObjectDirectoryQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING UnicodeString; - HANDLE WindowsDirectory; - NTSTATUS Status = STATUS_SUCCESS; - -#ifndef NDEBUG - DbgPrint("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DbgPrint("ValueData '%S'\n", (PWSTR)ValueData); -#endif - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - RtlInitUnicodeString(&UnicodeString, - (PWSTR)ValueData); - - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - 0, - NULL, - NULL); - - Status = ZwCreateDirectoryObject(&WindowsDirectory, - 0, - &ObjectAttributes); - - return(Status); -} - - static NTSTATUS -SmCreateObjectDirectories(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"ObjectDirectories"; - QueryTable[0].QueryRoutine = SmObjectDirectoryQueryRoutine; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager", - QueryTable, - NULL, - NULL); - - return(Status); -} - - -static NTSTATUS STDCALL -SmDosDevicesQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING DeviceName; - UNICODE_STRING LinkName; - HANDLE LinkHandle; - WCHAR LinkBuffer[80]; - NTSTATUS Status; - - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - swprintf(LinkBuffer, - L"\\??\\%s", - ValueName); - RtlInitUnicodeString(&LinkName, - LinkBuffer); - RtlInitUnicodeString(&DeviceName, - (PWSTR)ValueData); - - DPRINT("SM: Linking %wZ --> %wZ\n", - &LinkName, - &DeviceName); - - /* create symbolic link */ - InitializeObjectAttributes(&ObjectAttributes, - &LinkName, - OBJ_PERMANENT, - NULL, - NULL); - Status = NtCreateSymbolicLinkObject(&LinkHandle, - SYMBOLIC_LINK_ALL_ACCESS, - &ObjectAttributes, - &DeviceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SmDosDevicesQueryRoutine: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n", - &LinkName, - &DeviceName); - } - NtClose(LinkHandle); - - return(Status); -} - - -static NTSTATUS -SmInitDosDevices(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].QueryRoutine = SmDosDevicesQueryRoutine; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager\\DOS Devices", - QueryTable, - NULL, - NULL); - return(Status); -} - - -static NTSTATUS STDCALL -SmRunBootAppsQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - PRTL_USER_PROCESS_PARAMETERS ProcessParameters; - RTL_PROCESS_INFO ProcessInfo; - UNICODE_STRING ImagePathString; - UNICODE_STRING CommandLineString; - WCHAR Description[256]; - WCHAR ImageName[256]; - WCHAR ImagePath[256]; - WCHAR CommandLine[256]; - PWSTR p1, p2; - ULONG len; - NTSTATUS Status; - - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - /* Extract the description */ - p1 = wcschr((PWSTR)ValueData, L' '); - len = p1 - (PWSTR)ValueData; - memcpy(Description,ValueData, len * sizeof(WCHAR)); - Description[len] = 0; - - /* Extract the image name */ - p1++; - p2 = wcschr(p1, L' '); - if (p2 != NULL) - len = p2 - p1; - else - len = wcslen(p1); - memcpy(ImageName, p1, len * sizeof(WCHAR)); - ImageName[len] = 0; - - /* Extract the command line */ - if (p2 == NULL) - { - CommandLine[0] = 0; - } - else - { - p2++; - wcscpy(CommandLine, p2); - } - - DPRINT("Running %S...\n", Description); - DPRINT("ImageName: '%S'\n", ImageName); - DPRINT("CommandLine: '%S'\n", CommandLine); - - /* initialize executable path */ - wcscpy(ImagePath, L"\\SystemRoot\\system32\\"); - wcscat(ImagePath, ImageName); - wcscat(ImagePath, L".exe"); - - RtlInitUnicodeString(&ImagePathString, - ImagePath); - - RtlInitUnicodeString(&CommandLineString, - CommandLine); - - RtlCreateProcessParameters(&ProcessParameters, - &ImagePathString, - NULL, - NULL, - &CommandLineString, - NULL, - NULL, - NULL, - NULL, - NULL); - - Status = RtlCreateUserProcess(&ImagePathString, - OBJ_CASE_INSENSITIVE, - ProcessParameters, - NULL, - NULL, - NULL, - FALSE, - NULL, - NULL, - &ProcessInfo); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Running %s failed (Status %lx)\n", Description, Status); - return(STATUS_SUCCESS); - } - - RtlDestroyProcessParameters(ProcessParameters); - - /* Wait for process termination */ - NtWaitForSingleObject(ProcessInfo.ProcessHandle, - FALSE, - NULL); - - NtClose(ProcessInfo.ThreadHandle); - NtClose(ProcessInfo.ProcessHandle); - - return(STATUS_SUCCESS); -} - - -/* - * Run native applications listed in the registry. - * - * Key: - * \Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager - * - * Value (format: " ": - * BootExecute = "autocheck autochk *" - */ -static NTSTATUS -SmRunBootApps(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"BootExecute"; - QueryTable[0].QueryRoutine = SmRunBootAppsQueryRoutine; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager", - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SmRunBootApps: RtlQueryRegistryValues() failed! (Status %lx)\n", Status); - } - - return(Status); -} - - -static NTSTATUS -SmProcessFileRenameList(VOID) -{ - DPRINT("SmProcessFileRenameList() called\n"); - - /* FIXME: implement it! */ - - DPRINT("SmProcessFileRenameList() done\n"); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS STDCALL -SmKnownDllsQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING ImageName; - HANDLE FileHandle; - HANDLE SectionHandle; - NTSTATUS Status; - - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S' Context %p EntryContext %p\n", (PWSTR)ValueData, Context, EntryContext); - - /* Ignore the 'DllDirectory' value */ - if (!_wcsicmp(ValueName, L"DllDirectory")) - return STATUS_SUCCESS; - - /* Open the DLL image file */ - RtlInitUnicodeString(&ImageName, - ValueData); - InitializeObjectAttributes(&ObjectAttributes, - &ImageName, - OBJ_CASE_INSENSITIVE, - (HANDLE)Context, - NULL); - Status = NtOpenFile(&FileHandle, - SYNCHRONIZE | FILE_EXECUTE, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); - return STATUS_SUCCESS; - } - - DPRINT("Opened file %wZ successfully\n", &ImageName); - - /* Check for valid image checksum */ - Status = LdrVerifyImageMatchesChecksum (FileHandle, - 0, - 0, - 0); - if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) - { - /* Raise a hard error (crash the system/BSOD) */ - NtRaiseHardError (Status, - 0, - 0, - 0, - 0, - 0); - } - else if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to check the image checksum\n"); - - NtClose(SectionHandle); - NtClose(FileHandle); - - return STATUS_SUCCESS; - } - - InitializeObjectAttributes(&ObjectAttributes, - &ImageName, - OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, - (HANDLE)EntryContext, - NULL); - Status = NtCreateSection(&SectionHandle, - SECTION_ALL_ACCESS, - &ObjectAttributes, - NULL, - PAGE_EXECUTE, - SEC_IMAGE, - FileHandle); - if (NT_SUCCESS(Status)) - { - DPRINT("Created section successfully\n"); - NtClose(SectionHandle); - } - - NtClose(FileHandle); - - return STATUS_SUCCESS; -} - - -static NTSTATUS -SmLoadKnownDlls(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING DllDosPath; - UNICODE_STRING DllNtPath; - UNICODE_STRING Name; - HANDLE ObjectDirHandle; - HANDLE FileDirHandle; - HANDLE SymlinkHandle; - NTSTATUS Status; - - DPRINT("SmLoadKnownDlls() called\n"); - - /* Create 'KnownDlls' object directory */ - RtlInitUnicodeString(&Name, - L"\\KnownDlls"); - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - NULL, - NULL); - Status = NtCreateDirectoryObject(&ObjectDirHandle, - DIRECTORY_ALL_ACCESS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtCreateDirectoryObject() failed (Status %lx)\n", Status); - return Status; - } - - RtlInitUnicodeString(&DllDosPath, NULL); - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"DllDirectory"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[0].EntryContext = &DllDosPath; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager\\KnownDlls", - QueryTable, - NULL, - SmSystemEnvironment); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - return Status; - } - - DPRINT("DllDosPath: '%wZ'\n", &DllDosPath); - - if (!RtlDosPathNameToNtPathName_U(DllDosPath.Buffer, - &DllNtPath, - NULL, - NULL)) - { - DPRINT1("RtlDosPathNameToNtPathName_U() failed\n"); - return STATUS_OBJECT_NAME_INVALID; - } - - DPRINT("DllNtPath: '%wZ'\n", &DllNtPath); - - /* Open the dll path directory */ - InitializeObjectAttributes(&ObjectAttributes, - &DllNtPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = NtOpenFile(&FileDirHandle, - SYNCHRONIZE | FILE_READ_DATA, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenFile(%wZ) failed (Status %lx)\n", &DllNtPath, Status); - return Status; - } - - /* Link 'KnownDllPath' the dll path directory */ - RtlInitUnicodeString(&Name, - L"KnownDllPath"); - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - ObjectDirHandle, - NULL); - Status = NtCreateSymbolicLinkObject(&SymlinkHandle, - SYMBOLIC_LINK_ALL_ACCESS, - &ObjectAttributes, - &DllDosPath); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtCreateSymbolicLink() failed (Status %lx)\n", Status); - return Status; - } - - NtClose(SymlinkHandle); - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].QueryRoutine = SmKnownDllsQueryRoutine; - QueryTable[0].EntryContext = ObjectDirHandle; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager\\KnownDlls", - QueryTable, - (PVOID)FileDirHandle, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - } - - DPRINT("SmLoadKnownDlls() done\n"); - - return Status; -} - - -static NTSTATUS STDCALL -SmPagingFilesQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - UNICODE_STRING FileName; - LARGE_INTEGER InitialSize; - LARGE_INTEGER MaximumSize; - NTSTATUS Status; - LPWSTR p; - - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - /* - * Format: "[ [ ]]" - */ - if ((p = wcschr(ValueData, ' ')) != NULL) - { - *p = L'\0'; - InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096; - if (*p == ' ') - { - MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096; - } - else - MaximumSize = InitialSize; - } - else - { - InitialSize.QuadPart = 50 * 4096; - MaximumSize.QuadPart = 80 * 4096; - } - - if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, - &FileName, - NULL, - NULL)) - { - return (STATUS_SUCCESS); - } - - DPRINT("SMSS: Created paging file %wZ with size %dKB\n", - &FileName, InitialSize.QuadPart / 1024); - Status = NtCreatePagingFile(&FileName, - &InitialSize, - &MaximumSize, - 0); - - RtlFreeUnicodeString(&FileName); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS -SmCreatePagingFiles(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - /* - * Disable paging file on MiniNT/Live CD. - */ - if (RtlCheckRegistryKey(RTL_REGISTRY_CONTROL, L"MiniNT") == STATUS_SUCCESS) - { - return STATUS_SUCCESS; - } - - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"PagingFiles"; - QueryTable[0].QueryRoutine = SmPagingFilesQueryRoutine; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager\\Memory Management", - QueryTable, - NULL, - NULL); - - return(Status); -} - - -static NTSTATUS STDCALL -SmEnvironmentQueryRoutine(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - UNICODE_STRING EnvVariable; - UNICODE_STRING EnvValue; - - DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); - DPRINT("ValueData '%S'\n", (PWSTR)ValueData); - - if (ValueType != REG_SZ) - { - return(STATUS_SUCCESS); - } - - RtlInitUnicodeString(&EnvVariable, - ValueName); - RtlInitUnicodeString(&EnvValue, - (PWSTR)ValueData); - RtlSetEnvironmentVariable(Context, - &EnvVariable, - &EnvValue); - - return(STATUS_SUCCESS); -} - - -static NTSTATUS -SmSetEnvironmentVariables(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - UNICODE_STRING EnvVariable; - UNICODE_STRING EnvValue; - WCHAR ValueBuffer[MAX_PATH]; - NTSTATUS Status; - - /* - * The following environment variables must be set prior to reading - * other variables from the registry. - * - * Variables (example): - * SystemRoot = "C:\reactos" - * SystemDrive = "C:" - */ - - /* Copy system root into value buffer */ - wcscpy(ValueBuffer, - SharedUserData->NtSystemRoot); - - /* Set SystemRoot = "C:\reactos" */ - RtlRosInitUnicodeStringFromLiteral(&EnvVariable, - L"SystemRoot"); - RtlInitUnicodeString(&EnvValue, - ValueBuffer); - RtlSetEnvironmentVariable(&SmSystemEnvironment, - &EnvVariable, - &EnvValue); - - /* Cut off trailing path */ - ValueBuffer[2] = 0; - - /* Set SystemDrive = "C:" */ - RtlRosInitUnicodeStringFromLiteral(&EnvVariable, - L"SystemDrive"); - RtlInitUnicodeString(&EnvValue, - ValueBuffer); - RtlSetEnvironmentVariable(&SmSystemEnvironment, - &EnvVariable, - &EnvValue); - - /* Read system environment from the registry. */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].QueryRoutine = SmEnvironmentQueryRoutine; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"\\Session Manager\\Environment", - QueryTable, - &SmSystemEnvironment, - SmSystemEnvironment); - - return(Status); -} - - -static NTSTATUS -SmLoadSubsystems(VOID) -{ - SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo; - NTSTATUS Status; - - /* Load kernel mode subsystem (aka win32k.sys) */ - RtlRosInitUnicodeStringFromLiteral(&ImageInfo.ModuleName, - L"\\SystemRoot\\system32\\win32k.sys"); - - Status = NtSetSystemInformation(SystemLoadAndCallImage, - &ImageInfo, - sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)); - - DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status); -#if 0 - if (!NT_SUCCESS(Status)) - { - return(Status); - } -#endif - - /* FIXME: load more subsystems (csrss!) */ - - return(Status); -} - - -static VOID -SignalInitEvent() +SmpSignalInitEvent(VOID) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; @@ -810,283 +67,58 @@ SignalInitEvent() /* We don't really care if this fails */ DPRINT1("SM: Failed to open ReactOS init notification event\n"); } + return Status; } +typedef NTSTATUS (* SM_INIT_ROUTINE)(VOID); + +struct { + BOOL Required; + SM_INIT_ROUTINE EntryPoint; + PCHAR ErrorMessage; +} InitRoutine [] = { + {TRUE, SmCreateHeap, "create private heap, aborting"}, + {TRUE, SmCreateObjectDirectories, "create object directories"}, + {TRUE, SmCreateApiPort, "create \\SmApiPort"}, + {TRUE, SmCreateEnvironment, "create the system environment"}, + {TRUE, SmSetEnvironmentVariables, "set system environment variables"}, + {TRUE, SmInitDosDevices, "create dos device links"}, + {TRUE, SmRunBootApplications, "run boot applications"}, + {TRUE, SmProcessFileRenameList, "process the file rename list"}, + {FALSE, SmLoadKnownDlls, "preload system DLLs"}, + {TRUE, SmCreatePagingFiles, "create paging files"}, + {TRUE, SmInitializeRegistry, "initialize the registry"}, + {FALSE, SmUpdateEnvironment, "update environment variables"}, + {TRUE, SmInitializeClientManagement, "initialize client management"}, + {TRUE, SmLoadSubsystems, "load subsystems"}, + {FALSE, SmpSignalInitEvent, "open ReactOS init notification event"}, + {TRUE, SmRunCsrss, "run csrss"}, + {TRUE, SmRunWinlogon, "run winlogon"}, + {TRUE, SmInitializeDbgSs, "initialize DbgSs"} +}; NTSTATUS InitSessionManager(HANDLE Children[]) { + int i; NTSTATUS Status; - UNICODE_STRING UnicodeString; - OBJECT_ATTRIBUTES ObjectAttributes; - PRTL_USER_PROCESS_PARAMETERS ProcessParameters; - RTL_PROCESS_INFO ProcessInfo; - HANDLE CsrssInitEvent; - WCHAR UnicodeBuffer[MAX_PATH]; - /* Create object directories */ - Status = SmCreateObjectDirectories(); - if (!NT_SUCCESS(Status)) + for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++) + { + Status = InitRoutine[i].EntryPoint(); + if(!NT_SUCCESS(Status)) { - DPRINT1("SM: Failed to create object directories (Status %lx)\n", Status); - return(Status); + DPRINT1("SM: %s: failed to %s (Status=%lx)\n", + __FUNCTION__, + InitRoutine[i].ErrorMessage, + Status); + if (InitRoutine[i].Required) + { + return(Status); + } } + } - /* Create the SmApiPort object (LPC) */ - Status = SmCreateApiPort(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to create SmApiPort (Status %lx)\n", Status); - return(Status); - } - - /* Create the system environment */ - Status = RtlCreateEnvironment(FALSE, - &SmSystemEnvironment); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to create the system environment (Status %lx)\n", Status); - return(Status); - } - - /* Set environment variables */ - Status = SmSetEnvironmentVariables(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to set system environment variables (Status %lx)\n", Status); - return(Status); - } - - /* Define symbolic links to kernel devices (MS-DOS names) */ - Status = SmInitDosDevices(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to create dos device links (Status %lx)\n", Status); - return(Status); - } - - /* Run all programs in the boot execution list */ - Status = SmRunBootApps(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to run boot applications (Status %lx)\n", Status); - return(Status); - } - - /* Process the file rename list */ - Status = SmProcessFileRenameList(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to process the file rename list (Status %lx)\n", Status); - return(Status); - } - - DPRINT("SM: loading well-known DLLs\n"); - - /* Load the well known DLLs */ - Status = SmLoadKnownDlls(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to preload system DLLs (Status %lx)\n", Status); - /* Don't crash ReactOS if DLLs cannot be loaded */ - } - - DPRINT("SM: creating system paging files\n"); - - /* Create paging files */ - Status = SmCreatePagingFiles(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to create paging files (Status %lx)\n", Status); - return(Status); - } - - DPRINT("SM: initializing registry\n"); - - /* Load remaining registry hives */ - NtInitializeRegistry(FALSE); - - /* Set environment variables from registry */ -#if 0 - Status = SmUpdateEnvironment(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to update environment variables (Status %lx)\n", Status); - return(Status); - } -#endif - - DPRINT("SM: loading subsystems\n"); - - /* Load the subsystems */ - Status = SmLoadSubsystems(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SM: Failed to load subsystems (Status %lx)\n", Status); - return(Status); - } - - - SignalInitEvent(); - - - DPRINT("SM: initializing csrss\n"); - - /* Run csrss.exe */ - RtlRosInitUnicodeStringFromLiteral(&UnicodeString, - L"\\CsrssInitDone"); - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - EVENT_ALL_ACCESS, - 0, - NULL); - Status = NtCreateEvent(&CsrssInitEvent, - EVENT_ALL_ACCESS, - &ObjectAttributes, - NotificationEvent, - FALSE); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Failed to create csrss notification event\n"); - } - - /* - * Start the Win32 subsystem (csrss.exe) - */ - - /* initialize executable path */ - wcscpy(UnicodeBuffer, L"\\??\\"); - wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); - wcscat(UnicodeBuffer, L"\\system32\\csrss.exe"); - RtlInitUnicodeString(&UnicodeString, - UnicodeBuffer); - - RtlCreateProcessParameters(&ProcessParameters, - &UnicodeString, - NULL, - NULL, - NULL, - SmSystemEnvironment, - NULL, - NULL, - NULL, - NULL); - - Status = RtlCreateUserProcess(&UnicodeString, - OBJ_CASE_INSENSITIVE, - ProcessParameters, - NULL, - NULL, - NULL, - FALSE, - NULL, - NULL, - &ProcessInfo); - - RtlDestroyProcessParameters (ProcessParameters); - - if (!NT_SUCCESS(Status)) - { - DisplayString(L"SM: Loading csrss.exe failed!\n"); - return(Status); - } - - NtWaitForSingleObject(CsrssInitEvent, - FALSE, - NULL); - - Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle; - - /* - * Start the logon process (winlogon.exe) - */ - - DPRINT("SM: starting winlogon\n"); - - /* initialize executable path */ - wcscpy(UnicodeBuffer, L"\\??\\"); - wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); - wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe"); - RtlInitUnicodeString(&UnicodeString, - UnicodeBuffer); - - RtlCreateProcessParameters(&ProcessParameters, - &UnicodeString, - NULL, - NULL, - NULL, - SmSystemEnvironment, - NULL, - NULL, - NULL, - NULL); - - Status = RtlCreateUserProcess(&UnicodeString, - OBJ_CASE_INSENSITIVE, - ProcessParameters, - NULL, - NULL, - NULL, - FALSE, - NULL, - NULL, - &ProcessInfo); - - RtlDestroyProcessParameters(ProcessParameters); - - if (!NT_SUCCESS(Status)) - { - DisplayString(L"SM: Loading winlogon.exe failed!\n"); - NtTerminateProcess(Children[CHILD_CSRSS], - 0); - return(Status); - } - Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle; - - /* Create the \DbgSsApiPort object (LPC) */ - RtlRosInitUnicodeStringFromLiteral(&UnicodeString, - L"\\DbgSsApiPort"); - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - PORT_ALL_ACCESS, - NULL, - NULL); - - Status = NtCreatePort(&DbgSsApiPort, - &ObjectAttributes, - 0, - 0, - 0); - - if (!NT_SUCCESS(Status)) - { - return(Status); - } -#ifndef NDEBUG - DisplayString(L"SM: DbgSsApiPort created...\n"); -#endif - - /* Create the \DbgUiApiPort object (LPC) */ - RtlRosInitUnicodeStringFromLiteral(&UnicodeString, - L"\\DbgUiApiPort"); - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - PORT_ALL_ACCESS, - NULL, - NULL); - - Status = NtCreatePort(&DbgUiApiPort, - &ObjectAttributes, - 0, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - return(Status); - } -#ifndef NDEBUG - DisplayString (L"SM: DbgUiApiPort created...\n"); -#endif return(STATUS_SUCCESS); } diff --git a/reactos/subsys/smss/initdosdev.c b/reactos/subsys/smss/initdosdev.c new file mode 100644 index 00000000000..30e839f6720 --- /dev/null +++ b/reactos/subsys/smss/initdosdev.c @@ -0,0 +1,109 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initdosdev.c - Define symbolic links to kernel devices (MS-DOS names) + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +static NTSTATUS STDCALL +SmpDosDevicesQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + UNICODE_STRING LinkName; + HANDLE LinkHandle; + WCHAR LinkBuffer[80]; + NTSTATUS Status; + + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", (PWSTR)ValueData); + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + swprintf(LinkBuffer, + L"\\??\\%s", + ValueName); + RtlInitUnicodeString(&LinkName, + LinkBuffer); + RtlInitUnicodeString(&DeviceName, + (PWSTR)ValueData); + + DPRINT("SM: Linking %wZ --> %wZ\n", + &LinkName, + &DeviceName); + + /* create symbolic link */ + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_PERMANENT, + NULL, + NULL); + Status = NtCreateSymbolicLinkObject(&LinkHandle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes, + &DeviceName); + if (!NT_SUCCESS(Status)) + { + DPRINT1("%s: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n", + __FUNCTION__, + &LinkName, + &DeviceName); + } + NtClose(LinkHandle); + + return(Status); +} + + +NTSTATUS +SmInitDosDevices(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].QueryRoutine = SmpDosDevicesQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\DOS Devices", + QueryTable, + NULL, + NULL); + return(Status); +} + +/* EOF */ diff --git a/reactos/subsys/smss/initenv.c b/reactos/subsys/smss/initenv.c new file mode 100644 index 00000000000..97341d30b5a --- /dev/null +++ b/reactos/subsys/smss/initenv.c @@ -0,0 +1,139 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initenv.c - Environment initialization + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +/* GLOBALS */ + +PWSTR SmSystemEnvironment = NULL; + + +/* FUNCTIONS */ + +NTSTATUS +SmCreateEnvironment(VOID) +{ + return RtlCreateEnvironment(FALSE, &SmSystemEnvironment); +} + + +static NTSTATUS +SmpSetEnvironmentVariable(PVOID Context, + PWSTR ValueName, + PVOID ValueData) +{ + UNICODE_STRING EnvVariable; + UNICODE_STRING EnvValue; + + RtlInitUnicodeString(&EnvVariable, + ValueName); + RtlInitUnicodeString(&EnvValue, + (PWSTR)ValueData); + RtlSetEnvironmentVariable(Context, + &EnvVariable, + &EnvValue); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +SmpEnvironmentQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", (PWSTR)ValueData); + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + return SmpSetEnvironmentVariable(Context,ValueName,ValueData); +} + + +NTSTATUS +SmSetEnvironmentVariables(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + WCHAR ValueBuffer[MAX_PATH]; + NTSTATUS Status; + + /* + * The following environment variables must be set prior to reading + * other variables from the registry. + * + * Variables (example): + * SystemRoot = "C:\reactos" + * SystemDrive = "C:" + */ + + /* Copy system root into value buffer */ + wcscpy(ValueBuffer, + SharedUserData->NtSystemRoot); + + /* Set SystemRoot = "C:\reactos" */ + SmpSetEnvironmentVariable(&SmSystemEnvironment,L"SystemRoot",ValueBuffer); + + /* Cut off trailing path */ + ValueBuffer[2] = 0; + + /* Set SystemDrive = "C:" */ + SmpSetEnvironmentVariable(&SmSystemEnvironment,L"SystemDrive",ValueBuffer); + + /* Read system environment from the registry. */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].QueryRoutine = SmpEnvironmentQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\Environment", + QueryTable, + &SmSystemEnvironment, + SmSystemEnvironment); + + return(Status); +} + +/********************************************************************** + * Set environment variables from registry + */ +NTSTATUS +SmUpdateEnvironment(VOID) +{ + /* TODO */ + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/subsys/smss/initheap.c b/reactos/subsys/smss/initheap.c new file mode 100644 index 00000000000..7d62ed4919f --- /dev/null +++ b/reactos/subsys/smss/initheap.c @@ -0,0 +1,47 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initenv.c - Create the SM private heap + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +HANDLE SmpHeap = NULL; + +NTSTATUS +SmCreateHeap(VOID) +{ + /* Create our own heap */ + SmpHeap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 65536, + 65536, + NULL, + NULL); + return (NULL == SmpHeap) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/subsys/smss/initmv.c b/reactos/subsys/smss/initmv.c new file mode 100644 index 00000000000..aa78ea5e187 --- /dev/null +++ b/reactos/subsys/smss/initmv.c @@ -0,0 +1,44 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initmv.c - Process the file rename list + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +NTSTATUS +SmProcessFileRenameList(VOID) +{ + DPRINT("SmProcessFileRenameList() called\n"); + + /* FIXME: implement it! */ + + DPRINT("SmProcessFileRenameList() done\n"); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/reactos/subsys/smss/initobdir.c b/reactos/subsys/smss/initobdir.c new file mode 100644 index 00000000000..438638986de --- /dev/null +++ b/reactos/subsys/smss/initobdir.c @@ -0,0 +1,93 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initobdir.c - Session Manager object directories + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + + +#include "smss.h" + +#define NDEBUG +#include + +static NTSTATUS STDCALL +SmpObjectDirectoryQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeString; + HANDLE WindowsDirectory; + NTSTATUS Status = STATUS_SUCCESS; + +#ifndef NDEBUG + DbgPrint("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DbgPrint("ValueData '%S'\n", (PWSTR)ValueData); +#endif + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + RtlInitUnicodeString(&UnicodeString, + (PWSTR)ValueData); + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + 0, + NULL, + NULL); + + Status = ZwCreateDirectoryObject(&WindowsDirectory, + 0, + &ObjectAttributes); + + return(Status); +} + + +NTSTATUS +SmCreateObjectDirectories(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"ObjectDirectories"; + QueryTable[0].QueryRoutine = SmpObjectDirectoryQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager", + QueryTable, + NULL, + NULL); + + return(Status); +} + +/* EOF */ diff --git a/reactos/subsys/smss/initpage.c b/reactos/subsys/smss/initpage.c new file mode 100644 index 00000000000..69d672e21b7 --- /dev/null +++ b/reactos/subsys/smss/initpage.c @@ -0,0 +1,127 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initpage.c - + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ +#include "smss.h" +#include +#include + +#define NDEBUG +#include + +static NTSTATUS STDCALL +SmpPagingFilesQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + UNICODE_STRING FileName; + LARGE_INTEGER InitialSize; + LARGE_INTEGER MaximumSize; + NTSTATUS Status; + LPWSTR p; + + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", (PWSTR)ValueData); + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + /* + * Format: "[ [ ]]" + */ + if ((p = wcschr(ValueData, ' ')) != NULL) + { + *p = L'\0'; + InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096; + if (*p == ' ') + { + MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096; + } + else + MaximumSize = InitialSize; + } + else + { + InitialSize.QuadPart = 50 * 4096; + MaximumSize.QuadPart = 80 * 4096; + } + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, + &FileName, + NULL, + NULL)) + { + return (STATUS_SUCCESS); + } + + DPRINT("SMSS: Created paging file %wZ with size %dKB\n", + &FileName, InitialSize.QuadPart / 1024); + Status = NtCreatePagingFile(&FileName, + &InitialSize, + &MaximumSize, + 0); + + RtlFreeUnicodeString(&FileName); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +SmCreatePagingFiles(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + DPRINT("SM: creating system paging files\n"); + /* + * Disable paging file on MiniNT/Live CD. + */ + if (RtlCheckRegistryKey(RTL_REGISTRY_CONTROL, L"MiniNT") == STATUS_SUCCESS) + { + return STATUS_SUCCESS; + } + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"PagingFiles"; + QueryTable[0].QueryRoutine = SmpPagingFilesQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\Memory Management", + QueryTable, + NULL, + NULL); + + return(Status); +} + + +/* EOF */ diff --git a/reactos/subsys/smss/initreg.c b/reactos/subsys/smss/initreg.c new file mode 100644 index 00000000000..6bfbfacf7be --- /dev/null +++ b/reactos/subsys/smss/initreg.c @@ -0,0 +1,41 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initenv.c - Environment initialization + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +NTSTATUS +SmInitializeRegistry(VOID) +{ + DPRINT("SM: %s: initializing registry\n", __FUNCTION__); + + /* Load remaining registry hives */ + return NtInitializeRegistry(FALSE); +} + +/* EOF */ diff --git a/reactos/subsys/smss/initrun.c b/reactos/subsys/smss/initrun.c new file mode 100644 index 00000000000..841c988b844 --- /dev/null +++ b/reactos/subsys/smss/initrun.c @@ -0,0 +1,183 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initrun.c - Run all programs in the boot execution list + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +HANDLE Children[2] = {0, 0}; /* csrss, winlogon */ + + +static NTSTATUS STDCALL +SmpRunBootAppsQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + RTL_PROCESS_INFO ProcessInfo; + UNICODE_STRING ImagePathString; + UNICODE_STRING CommandLineString; + WCHAR Description[256]; + WCHAR ImageName[256]; + WCHAR ImagePath[256]; + WCHAR CommandLine[256]; + PWSTR p1, p2; + ULONG len; + NTSTATUS Status; + + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S'\n", (PWSTR)ValueData); + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + /* Extract the description */ + p1 = wcschr((PWSTR)ValueData, L' '); + len = p1 - (PWSTR)ValueData; + memcpy(Description,ValueData, len * sizeof(WCHAR)); + Description[len] = 0; + + /* Extract the image name */ + p1++; + p2 = wcschr(p1, L' '); + if (p2 != NULL) + len = p2 - p1; + else + len = wcslen(p1); + memcpy(ImageName, p1, len * sizeof(WCHAR)); + ImageName[len] = 0; + + /* Extract the command line */ + if (p2 == NULL) + { + CommandLine[0] = 0; + } + else + { + p2++; + wcscpy(CommandLine, p2); + } + + DPRINT("Running %S...\n", Description); + DPRINT("ImageName: '%S'\n", ImageName); + DPRINT("CommandLine: '%S'\n", CommandLine); + + /* initialize executable path */ + wcscpy(ImagePath, L"\\SystemRoot\\system32\\"); + wcscat(ImagePath, ImageName); + wcscat(ImagePath, L".exe"); + + RtlInitUnicodeString(&ImagePathString, + ImagePath); + + RtlInitUnicodeString(&CommandLineString, + CommandLine); + + RtlCreateProcessParameters(&ProcessParameters, + &ImagePathString, + NULL, + NULL, + &CommandLineString, + NULL, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&ImagePathString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Running %s failed (Status %lx)\n", Description, Status); + return(STATUS_SUCCESS); + } + + RtlDestroyProcessParameters(ProcessParameters); + + /* Wait for process termination */ + NtWaitForSingleObject(ProcessInfo.ProcessHandle, + FALSE, + NULL); + + NtClose(ProcessInfo.ThreadHandle); + NtClose(ProcessInfo.ProcessHandle); + + return(STATUS_SUCCESS); +} + + +/* + * Run native applications listed in the registry. + * + * Key: + * \Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager + * + * Value (format: " ": + * BootExecute = "autocheck autochk *" + */ +NTSTATUS +SmRunBootApplications(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"BootExecute"; + QueryTable[0].QueryRoutine = SmpRunBootAppsQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("%s: RtlQueryRegistryValues() failed! (Status %lx)\n", + __FUNCTION__, + Status); + } + + return(Status); +} + + +/* EOF */ diff --git a/reactos/subsys/smss/initss.c b/reactos/subsys/smss/initss.c new file mode 100644 index 00000000000..0f804563e24 --- /dev/null +++ b/reactos/subsys/smss/initss.c @@ -0,0 +1,220 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initss.c - Load the subsystems + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + + +#include "smss.h" +#include + +#define NDEBUG +#include + +/* TODO: this file should be totally rewritten + * + * a) look if a special option is set for smss.exe in + * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options + * + * b) make smss register with itself for IMAGE_SUBSYSTEM_NATIVE + * (programmatically) + * + * c) make smss load win32k.sys as set in Kmode key + * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems + * + * d) make smss initialize Debug (DBGSS) and Windows (CSRSS) as described + * in the registry key Required="Debug Windows" + * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems + * + * e) make optional subsystems loadable (again: they must be described in the registry + * key Optional="Posix Os2" to be allowed to run) + */ +NTSTATUS +SmLoadSubsystems(VOID) +{ + SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo; + NTSTATUS Status; + + DPRINT("SM: loading subsystems\n"); + + /* Load kernel mode subsystem (aka win32k.sys) */ + RtlRosInitUnicodeStringFromLiteral(&ImageInfo.ModuleName, + L"\\SystemRoot\\system32\\win32k.sys"); + + Status = NtSetSystemInformation(SystemLoadAndCallImage, + &ImageInfo, + sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)); + + DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status); +#if 0 + if (!NT_SUCCESS(Status)) + { + return(Status); + } +#endif + + /* FIXME: load more subsystems (csrss!) */ + + return(Status); +} + +NTSTATUS +SmRunCsrss(VOID) +{ + NTSTATUS Status; + UNICODE_STRING UnicodeString; + OBJECT_ATTRIBUTES ObjectAttributes; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + RTL_PROCESS_INFO ProcessInfo; + HANDLE CsrssInitEvent; + WCHAR UnicodeBuffer[MAX_PATH]; + + DPRINT("SM: initializing csrss\n"); + + /* Run csrss.exe */ + RtlRosInitUnicodeStringFromLiteral(&UnicodeString, + L"\\CsrssInitDone"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + EVENT_ALL_ACCESS, + 0, + NULL); + Status = NtCreateEvent(&CsrssInitEvent, + EVENT_ALL_ACCESS, + &ObjectAttributes, + NotificationEvent, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to create csrss notification event\n"); + } + + /* + * Start the Win32 subsystem (csrss.exe) + */ + + /* initialize executable path */ + wcscpy(UnicodeBuffer, L"\\??\\"); + wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); + wcscat(UnicodeBuffer, L"\\system32\\csrss.exe"); + RtlInitUnicodeString(&UnicodeString, + UnicodeBuffer); + + RtlCreateProcessParameters(&ProcessParameters, + &UnicodeString, + NULL, + NULL, + NULL, + SmSystemEnvironment, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&UnicodeString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + + RtlDestroyProcessParameters (ProcessParameters); + + if (!NT_SUCCESS(Status)) + { + DPRINT("SM: %s: Loading csrss.exe failed!\n", __FUNCTION__); + return(Status); + } + + Status = NtWaitForSingleObject(CsrssInitEvent, + FALSE, + NULL); + + Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle; + + return Status; +} + +NTSTATUS +SmRunWinlogon(VOID) +{ + NTSTATUS Status; + UNICODE_STRING UnicodeString; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + RTL_PROCESS_INFO ProcessInfo; + WCHAR UnicodeBuffer[MAX_PATH]; + + /* + * Start the logon process (winlogon.exe) + */ + + DPRINT("SM: starting winlogon\n"); + + /* initialize executable path */ + wcscpy(UnicodeBuffer, L"\\??\\"); + wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); + wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe"); + RtlInitUnicodeString(&UnicodeString, + UnicodeBuffer); + + RtlCreateProcessParameters(&ProcessParameters, + &UnicodeString, + NULL, + NULL, + NULL, + SmSystemEnvironment, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&UnicodeString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + + RtlDestroyProcessParameters(ProcessParameters); + + if (!NT_SUCCESS(Status)) + { + DPRINT("SM: %s: Loading winlogon.exe failed!\n", __FUNCTION__); + NtTerminateProcess(Children[CHILD_CSRSS], + 0); + return(Status); + } + Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle; + + return Status; +} + +/* EOF */ diff --git a/reactos/subsys/smss/initwkdll.c b/reactos/subsys/smss/initwkdll.c new file mode 100644 index 00000000000..e853d8b214d --- /dev/null +++ b/reactos/subsys/smss/initwkdll.c @@ -0,0 +1,254 @@ +/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $ + * + * initwkdll.c - Load the well known DLLs + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + */ + +#include "smss.h" + +#define NDEBUG +#include + +static NTSTATUS STDCALL +SmpKnownDllsQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING ImageName; + HANDLE FileHandle; + HANDLE SectionHandle; + NTSTATUS Status; + + DPRINT("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + DPRINT("ValueData '%S' Context %p EntryContext %p\n", (PWSTR)ValueData, Context, EntryContext); + + /* Ignore the 'DllDirectory' value */ + if (!_wcsicmp(ValueName, L"DllDirectory")) + return STATUS_SUCCESS; + + /* Open the DLL image file */ + RtlInitUnicodeString(&ImageName, + ValueData); + InitializeObjectAttributes(&ObjectAttributes, + &ImageName, + OBJ_CASE_INSENSITIVE, + (HANDLE)Context, + NULL); + Status = NtOpenFile(&FileHandle, + SYNCHRONIZE | FILE_EXECUTE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); + return STATUS_SUCCESS; + } + + DPRINT("Opened file %wZ successfully\n", &ImageName); + + /* Check for valid image checksum */ + Status = LdrVerifyImageMatchesChecksum (FileHandle, + 0, + 0, + 0); + if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) + { + /* Raise a hard error (crash the system/BSOD) */ + NtRaiseHardError (Status, + 0, + 0, + 0, + 0, + 0); + } + else if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to check the image checksum\n"); + + NtClose(SectionHandle); + NtClose(FileHandle); + + return STATUS_SUCCESS; + } + + InitializeObjectAttributes(&ObjectAttributes, + &ImageName, + OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, + (HANDLE)EntryContext, + NULL); + Status = NtCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + FileHandle); + if (NT_SUCCESS(Status)) + { + DPRINT("Created section successfully\n"); + NtClose(SectionHandle); + } + + NtClose(FileHandle); + + return STATUS_SUCCESS; +} + + +NTSTATUS +SmLoadKnownDlls(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING DllDosPath; + UNICODE_STRING DllNtPath; + UNICODE_STRING Name; + HANDLE ObjectDirHandle; + HANDLE FileDirHandle; + HANDLE SymlinkHandle; + NTSTATUS Status; + + + DPRINT("SM: loading well-known DLLs\n"); + + DPRINT("SmLoadKnownDlls() called\n"); + + /* Create 'KnownDlls' object directory */ + RtlInitUnicodeString(&Name, + L"\\KnownDlls"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + NULL, + NULL); + Status = NtCreateDirectoryObject(&ObjectDirHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateDirectoryObject() failed (Status %lx)\n", Status); + return Status; + } + + RtlInitUnicodeString(&DllDosPath, NULL); + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"DllDirectory"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &DllDosPath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\KnownDlls", + QueryTable, + NULL, + SmSystemEnvironment); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + return Status; + } + + DPRINT("DllDosPath: '%wZ'\n", &DllDosPath); + + if (!RtlDosPathNameToNtPathName_U(DllDosPath.Buffer, + &DllNtPath, + NULL, + NULL)) + { + DPRINT1("RtlDosPathNameToNtPathName_U() failed\n"); + return STATUS_OBJECT_NAME_INVALID; + } + + DPRINT("DllNtPath: '%wZ'\n", &DllNtPath); + + /* Open the dll path directory */ + InitializeObjectAttributes(&ObjectAttributes, + &DllNtPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenFile(&FileDirHandle, + SYNCHRONIZE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenFile(%wZ) failed (Status %lx)\n", &DllNtPath, Status); + return Status; + } + + /* Link 'KnownDllPath' the dll path directory */ + RtlInitUnicodeString(&Name, + L"KnownDllPath"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + ObjectDirHandle, + NULL); + Status = NtCreateSymbolicLinkObject(&SymlinkHandle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes, + &DllDosPath); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateSymbolicLink() failed (Status %lx)\n", Status); + return Status; + } + + NtClose(SymlinkHandle); + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].QueryRoutine = SmpKnownDllsQueryRoutine; + QueryTable[0].EntryContext = ObjectDirHandle; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\KnownDlls", + QueryTable, + (PVOID)FileDirHandle, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + } + + DPRINT("SmLoadKnownDlls() done\n"); + + return Status; +} + + +/* EOF */ diff --git a/reactos/subsys/smss/makefile b/reactos/subsys/smss/makefile index ad4bd929842..12af5d6800f 100644 --- a/reactos/subsys/smss/makefile +++ b/reactos/subsys/smss/makefile @@ -15,7 +15,12 @@ TARGET_CFLAGS = -D__NTAPP__ # require os code to explicitly request A/W version of structs/functions TARGET_CFLAGS += -D_DISABLE_TIDENTS -Wall -Werror -TARGET_OBJECTS = $(TARGET_NAME).o init.o smapi.o +TARGET_OBJECTS = $(TARGET_NAME).o \ + init.o initheap.o initenv.o initobdir.o initdosdev.o \ + initrun.o initmv.o initwkdll.o initpage.o initss.o \ + initreg.o \ + smapi.o \ + client.o debug.o include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/subsys/smss/smapi.c b/reactos/subsys/smss/smapi.c index 3a2f4689fec..1e132375c9a 100644 --- a/reactos/subsys/smss/smapi.c +++ b/reactos/subsys/smss/smapi.c @@ -5,10 +5,12 @@ * */ -#include -#include +/*#include +#include */ +#define NTOS_MODE_USER +#include +#include #include - #include "smss.h" #define NDEBUG @@ -17,60 +19,125 @@ static HANDLE SmApiPort = INVALID_HANDLE_VALUE; -/* FUNCTIONS ****************************************************************/ +/* SM API *******************************************************************/ +#define SMAPI(n) \ +NTSTATUS FASTCALL n (PSM_PORT_MESSAGE Request) -VOID STDCALL -SmApiThread(HANDLE Port) +SMAPI(SmInvalid) { - NTSTATUS Status; - ULONG Unknown; - PLPC_MESSAGE Reply = NULL; - LPC_MESSAGE Message; + DbgPrint("SMSS: %s called\n",__FUNCTION__); + Request->Status = STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; +} -#ifndef NDEBUG - DisplayString(L"SmApiThread: running\n"); -#endif +SMAPI(SmCompSes) +{ + DbgPrint("SMSS: %s called\n",__FUNCTION__); + Request->Status = STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; +} +SMAPI(SmExecPgm) +{ + DbgPrint("SMSS: %s called\n",__FUNCTION__); + Request->Status = STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; +} - while (TRUE) - { -#ifndef NDEBUG - DisplayString(L"SmApiThread: waiting for message\n"); -#endif +/* SM API Table */ +typedef NTSTATUS (FASTCALL * SM_PORT_API)(PSM_PORT_MESSAGE); - Status = NtReplyWaitReceivePort(Port, - &Unknown, - Reply, - &Message); - if (NT_SUCCESS(Status)) +SM_PORT_API SmApi [] = +{ + SmInvalid, /* unused */ + SmCompSes, + SmInvalid, /* obsolete */ + SmInvalid, /* unknown */ + SmExecPgm +}; + + +/********************************************************************** + * NAME + * SmpHandleConnectionRequest/2 + * + * REMARKS + * Quoted in http://support.microsoft.com/kb/258060/EN-US/ + */ +NTSTATUS STDCALL +SmpHandleConnectionRequest (HANDLE Port, PSM_PORT_MESSAGE Request) +{ + DbgPrint("SMSS: %s called\n",__FUNCTION__); + return STATUS_SUCCESS; +} + +/********************************************************************** + * NAME + * SmpApiThread/1 + * + * DESCRIPTION + * Entry point for the listener thread of LPC port "\SmApiPort". + */ +VOID STDCALL +SmpApiThread(HANDLE Port) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG Unknown = 0; + PLPC_MESSAGE Reply = NULL; + SM_PORT_MESSAGE Request = {{0}}; + + DbgPrint("SMSS: %s running.\n",__FUNCTION__); + + while (TRUE) { -#ifndef NDEBUG - DisplayString(L"SmApiThread: message received\n"); -#endif + DbgPrint("SMSS: %s: waiting for message\n",__FUNCTION__); - if (Message.MessageType == LPC_CONNECTION_REQUEST) - { -// SmHandleConnectionRequest (Port, &Message); - Reply = NULL; - } - else if (Message.MessageType == LPC_DEBUG_EVENT) - { -// DbgSsHandleKmApiMsg (&Message, 0); - Reply = NULL; - } - else if (Message.MessageType == LPC_PORT_CLOSED) - { - Reply = NULL; - } - else - { -// Reply = &Message; - } + Status = NtReplyWaitReceivePort(Port, + & Unknown, + Reply, + (PLPC_MESSAGE) & Request); + if (NT_SUCCESS(Status)) + { + DbgPrint("SMSS: %s: message received\n",__FUNCTION__); + + switch (Request.Header.MessageType) + { + case LPC_CONNECTION_REQUEST: + SmpHandleConnectionRequest (Port, &Request); + Reply = NULL; + break; + case LPC_DEBUG_EVENT: +// DbgSsHandleKmApiMsg (&Request, 0); + Reply = NULL; + break; + case LPC_PORT_CLOSED: + Reply = NULL; + break; + default: + if ((Request.ApiIndex) && + (Request.ApiIndex < (sizeof SmApi / sizeof SmApi[0]))) + { + Status = SmApi[Request.ApiIndex](&Request); + Reply = (PLPC_MESSAGE) & Request; + } else { + Request.Status = STATUS_NOT_IMPLEMENTED; + Reply = (PLPC_MESSAGE) & Request; + } + } + } } - } } +/* LPC PORT INITIALIZATION **************************************************/ + + +/********************************************************************** + * NAME + * SmCreateApiPort/0 + * + * DECRIPTION + */ NTSTATUS SmCreateApiPort(VOID) { @@ -103,7 +170,7 @@ SmCreateApiPort(VOID) 0, NULL, NULL, - (PTHREAD_START_ROUTINE)SmApiThread, + (PTHREAD_START_ROUTINE)SmpApiThread, (PVOID)SmApiPort, NULL, NULL); @@ -114,7 +181,7 @@ SmCreateApiPort(VOID) 0, NULL, NULL, - (PTHREAD_START_ROUTINE)SmApiThread, + (PTHREAD_START_ROUTINE)SmpApiThread, (PVOID)SmApiPort, NULL, NULL); diff --git a/reactos/subsys/smss/smss.c b/reactos/subsys/smss/smss.c index 42673e7bc33..80ee0e6daa6 100644 --- a/reactos/subsys/smss/smss.c +++ b/reactos/subsys/smss/smss.c @@ -22,60 +22,31 @@ * MA 02139, USA. * * -------------------------------------------------------------------- - * - * 19990529 (Emanuele Aliberti) - * Compiled successfully with egcs 1.1.2 */ -#include - #include "smss.h" +#include #define NDEBUG #include - -void -DisplayString(LPCWSTR lpwString) -{ - UNICODE_STRING us; - - RtlInitUnicodeString(&us, lpwString); - NtDisplayString(&us); -} - - -void -PrintString(char* fmt,...) -{ - char buffer[512]; - va_list ap; - UNICODE_STRING UnicodeString; - ANSI_STRING AnsiString; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - RtlInitAnsiString(&AnsiString, buffer); - RtlAnsiStringToUnicodeString(&UnicodeString, - &AnsiString, - TRUE); - NtDisplayString(&UnicodeString); - RtlFreeUnicodeString(&UnicodeString); -} - - /* Native image's entry point */ VOID STDCALL NtProcessStartup(PPEB Peb) { - HANDLE Children[2]; /* csrss, winlogon */ NTSTATUS Status; Status = InitSessionManager(Children); if (!NT_SUCCESS(Status)) { + int i; + for (i=0; i < (sizeof Children / sizeof Children[0]); i++) + { + if (Children[i]) + { + NtTerminateProcess(Children[i],0); + } + } DPRINT1("SM: Initialization failed!\n"); goto ByeBye; } diff --git a/reactos/subsys/smss/smss.h b/reactos/subsys/smss/smss.h index 295f1a3b1dc..0a8a3d1dee5 100644 --- a/reactos/subsys/smss/smss.h +++ b/reactos/subsys/smss/smss.h @@ -1,38 +1,66 @@ - #ifndef _SMSS_H_INCLUDED_ #define _SMSS_H_INCLUDED_ +#define NTOS_MODE_USER +#include +#include #define CHILD_CSRSS 0 #define CHILD_WINLOGON 1 - -/* GLOBAL VARIABLES ****/ - -//extern HANDLE SmApiPort; - - -/* FUNCTIONS ***********/ - /* init.c */ -NTSTATUS -InitSessionManager(HANDLE Children[]); +extern HANDLE SmpHeap; +NTSTATUS InitSessionManager(HANDLE Children[]); +/* initheap.c */ +NTSTATUS SmCreateHeap(VOID); -/* smss.c */ -void DisplayString (LPCWSTR lpwString); -void PrintString (char* fmt,...); +/* initenv.c */ +extern PWSTR SmSystemEnvironment; +NTSTATUS SmCreateEnvironment(VOID); +NTSTATUS SmSetEnvironmentVariables(VOID); +NTSTATUS SmUpdateEnvironment(VOID); +/* initobdir.c */ +NTSTATUS SmCreateObjectDirectories(VOID); + +/* initdosdev.c */ +NTSTATUS SmInitDosDevices(VOID); + +/* initrun.c */ +extern HANDLE Children[2]; +NTSTATUS SmRunBootApplications(VOID); + +/* initmv.c */ +NTSTATUS SmProcessFileRenameList(VOID); + +/* initwkdll.c */ +NTSTATUS SmLoadKnownDlls(VOID); + +/* initpage.c */ +NTSTATUS SmCreatePagingFiles(VOID); + +/* initreg.c */ +NTSTATUS SmInitializeRegistry(VOID); + +/* initss.c */ +NTSTATUS SmLoadSubsystems(VOID); +NTSTATUS SmRunCsrss(VOID); +NTSTATUS SmRunWinlogon(VOID); /* smapi.c */ +NTSTATUS SmCreateApiPort(VOID); +VOID STDCALL SmpApiThread(HANDLE Port); -NTSTATUS -SmCreateApiPort(VOID); - -VOID STDCALL -SmApiThread(HANDLE Port); - +/* client.c */ +NTSTATUS SmInitializeClientManagement(VOID); +NTSTATUS STDCALL SmpCreateClient(SM_PORT_MESSAGE); +NTSTATUS STDCALL SmpDestroyClient(ULONG); +/* debug.c */ +extern HANDLE DbgSsApiPort; +extern HANDLE DbgUiApiPort; +NTSTATUS SmInitializeDbgSs(VOID); #endif /* _SMSS_H_INCLUDED_ */ diff --git a/reactos/subsys/smss/smss.xml b/reactos/subsys/smss/smss.xml index ebb5019d7cf..c71a07130dc 100644 --- a/reactos/subsys/smss/smss.xml +++ b/reactos/subsys/smss/smss.xml @@ -2,7 +2,19 @@ . ntdll + client.c + Debug.c init.c + initdosdev.c + initenv.c + initheap.c + initmv.c + initobdir.c + initpage.c + initreg.c + initrun.c + initss.c + initwkdll.c smapi.c smss.c smss.rc diff --git a/reactos/subsys/system/autochk/autochk.c b/reactos/subsys/system/autochk/autochk.c index 5cfad8c5ffb..1c27750549c 100644 --- a/reactos/subsys/system/autochk/autochk.c +++ b/reactos/subsys/system/autochk/autochk.c @@ -76,8 +76,8 @@ NtProcessStartup(PPEB Peb) Status = NtQueryInformationProcess(NtCurrentProcess(), ProcessDeviceMap, - &DeviceMap, - sizeof(DeviceMap), + &DeviceMap.Query, + sizeof(DeviceMap.Query), NULL); if(NT_SUCCESS(Status)) { diff --git a/reactos/subsys/system/explorer/Jamfile b/reactos/subsys/system/explorer/Jamfile index 640bd6f75f3..e0720405d48 100644 --- a/reactos/subsys/system/explorer/Jamfile +++ b/reactos/subsys/system/explorer/Jamfile @@ -44,7 +44,7 @@ exe explorer : dialogs/settings.cpp i386-stub-win32.c : WIN32 _WIN32_IE=0x0600 _WIN32_WINNT=0x0501 WINVER=0x0500 - -I$(INCLUDE) + -I$(INCLUDE) -I. #nur für GCC: -fexceptions -Wall gdi32 ole32 diff --git a/reactos/subsys/system/explorer/Makefile.MinGW b/reactos/subsys/system/explorer/Makefile.MinGW index 96def265ac7..d6356477d51 100644 --- a/reactos/subsys/system/explorer/Makefile.MinGW +++ b/reactos/subsys/system/explorer/Makefile.MinGW @@ -8,6 +8,7 @@ CC = gcc CXX = g++ LINK = g++ +# -D_NO_ALPHABLEND for builds without msimg32.dll dependency CFLAGS = -DWIN32 -D_WIN32_IE=0x0600 -D_WIN32_WINNT=0x0501 -DWINVER=0x0500 -fexceptions -Wall -I. RCFLAGS = -DWIN32 -D__WINDRES__ LFLAGS = -Wl,--subsystem,windows diff --git a/reactos/subsys/system/explorer/desktop/desktop.cpp b/reactos/subsys/system/explorer/desktop/desktop.cpp index 1a1036f9a54..626c1689439 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.cpp +++ b/reactos/subsys/system/explorer/desktop/desktop.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -522,11 +522,11 @@ bool DesktopShellView::InitDragDrop() return true; } -LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_CONTEXTMENU: - if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) + if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam), _cm_ifs)) DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); break; @@ -558,7 +558,7 @@ int DesktopShellView::Notify(int id, NMHDR* pnmh) return super::Notify(id, pnmh); } -bool DesktopShellView::DoContextMenu(int x, int y) +bool DesktopShellView::DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs) { IDataObject* selection; @@ -588,7 +588,7 @@ bool DesktopShellView::DoContextMenu(int x, int y) for(int i=pida->cidl; i>0; --i) apidl[i-1] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]); - hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y); + hr = ShellFolderContextMenu(ShellFolder(parent_pidl), _hwnd, pida->cidl, apidl, x, y, cm_ifs); selection->Release(); @@ -604,6 +604,8 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm); if (SUCCEEDED(hr)) { + pcm = _cm_ifs.query_interfaces(pcm); + HMENU hmenu = CreatePopupMenu(); if (hmenu) { @@ -615,6 +617,8 @@ HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL); + _cm_ifs.reset(); + if (idCmd == FCIDM_SHVIEWLAST-1) { explorer_about(_hwnd); } else if (idCmd) { diff --git a/reactos/subsys/system/explorer/desktop/desktop.h b/reactos/subsys/system/explorer/desktop/desktop.h index 752a3de266f..751ffe4e18c 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.h +++ b/reactos/subsys/system/explorer/desktop/desktop.h @@ -165,9 +165,9 @@ public: /// subclassed ShellView window -struct DesktopShellView : public SubclassedWindow +struct DesktopShellView : public ExtContextMenuHandlerT { - typedef SubclassedWindow super; + typedef ExtContextMenuHandlerT super; DesktopShellView(HWND hwnd, IShellView* pShellView); @@ -180,7 +180,7 @@ protected: int Command(int id, int code); int Notify(int id, NMHDR* pnmh); - bool DoContextMenu(int x, int y); + bool DoContextMenu(int x, int y, CtxMenuInterfaces& cm_ifs); HRESULT DoDesktopContextMenu(int x, int y); void PositionIcons(int dir=1); diff --git a/reactos/subsys/system/explorer/doc/changes.txt b/reactos/subsys/system/explorer/doc/changes.txt index c87c89d3ae8..bbb64df1ae6 100644 --- a/reactos/subsys/system/explorer/doc/changes.txt +++ b/reactos/subsys/system/explorer/doc/changes.txt @@ -1,6 +1,6 @@ -0You will find only major changes in this file. +You will find only major changes in this file. Small bug fixes and developments steps are not listet here. -If you search for more information, look into the CVS repository. +If you search for more information, look into the Subversion repository. 14.10.2002 m. fuchs Korrektur der Anpassungen durch Übernahme in wine: Anzeige der Verzeichnisnamen in Tree Pane m. fuchs Wieder-Anpassung an natives Übersetzen unter WIN32 mit VC++ diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index b55ed0aa4cd..90e91efff22 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -635,10 +635,10 @@ static void InitInstance(HINSTANCE hInstance) // register frame window class g_Globals._hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_EXPLORER); - // register child windows class + // register child window class WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register(); - // register tree windows class + // register tree window class WindowClass(CLASSNAME_WINEFILETREE, CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW).Register(); g_Globals._cfStrFName = RegisterClipboardFormat(CFSTR_FILENAME); @@ -696,6 +696,9 @@ int main(int argc, char* argv[]) while(*cmdline && !_istspace(*cmdline)) ++cmdline; + while(_istspace(*cmdline)) + ++cmdline; + return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd); } diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp index 840cc39e5bd..eb9763211db 100644 --- a/reactos/subsys/system/explorer/explorer.dsp +++ b/reactos/subsys/system/explorer/explorer.dsp @@ -1,789 +1,789 @@ -# Microsoft Developer Studio Project File - Name="explorer" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=explorer - Win32 WineDll -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "explorer.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "explorer.mak" CFG="explorer - Win32 WineDll" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "explorer - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 Debug Release" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 Unicode Release" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 Unicode Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 _NO_COMUTIL" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 WineRelease" (based on "Win32 (x86) Console Application") -!MESSAGE "explorer - Win32 WineDll" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "explorer - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O1 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x407 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 Debug Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "DRelease" -# PROP BASE Intermediate_Dir "DRelease" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "DRelease" -# PROP Intermediate_Dir "DRelease" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_ROS_" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /c -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x407 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "URelease" -# PROP BASE Intermediate_Dir "URelease" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "URelease" -# PROP Intermediate_Dir "URelease" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x407 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "UDebug" -# PROP BASE Intermediate_Dir "UDebug" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "UDebug" -# PROP Intermediate_Dir "UDebug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /FR /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "explorer___Win32__NO_COMUTIL" -# PROP BASE Intermediate_Dir "explorer___Win32__NO_COMUTIL" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "_NO_COMUTIL" -# PROP Intermediate_Dir "_NO_COMUTIL" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "_NO_COMUTIL" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# SUBTRACT BASE LINK32 /pdb:none -# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Win32" -# PROP BASE Intermediate_Dir "Win32" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Win32" -# PROP Intermediate_Dir "Win32" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# SUBTRACT BASE LINK32 /pdb:none -# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Win32/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 WineRelease" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "explorer___Win32_WineRelease" -# PROP BASE Intermediate_Dir "explorer___Win32_WineRelease" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WineRelease" -# PROP Intermediate_Dir "WineRelease" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c -# ADD CPP /nologo /MT /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# SUBTRACT BASE LINK32 /pdb:none -# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /incremental:no /machine:I386 /out:"WineRelease/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "explorer - Win32 WineDll" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "explorer___Win32_WineDll" -# PROP BASE Intermediate_Dir "explorer___Win32_WineDll" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WineDll" -# PROP Intermediate_Dir "WineDll" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FD /c -# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /machine:I386 /pdbtype:sept -# SUBTRACT BASE LINK32 /pdb:none /debug -# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"WineDll/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "explorer - Win32 Release" -# Name "explorer - Win32 Debug" -# Name "explorer - Win32 Debug Release" -# Name "explorer - Win32 Unicode Release" -# Name "explorer - Win32 Unicode Debug" -# Name "explorer - Win32 _NO_COMUTIL" -# Name "explorer - Win32" -# Name "explorer - Win32 WineRelease" -# Name "explorer - Win32 WineDll" -# Begin Group "utility" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\utility\dragdropimpl.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\dragdropimpl.h -# End Source File -# Begin Source File - -SOURCE=.\utility\shellbrowserimpl.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\shellbrowserimpl.h -# End Source File -# Begin Source File - -SOURCE=.\utility\shellclasses.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\shellclasses.h -# End Source File -# Begin Source File - -SOURCE=.\utility\treedroptarget.h -# End Source File -# Begin Source File - -SOURCE=.\utility\utility.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\utility.h -# End Source File -# Begin Source File - -SOURCE=.\utility\window.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\window.h -# End Source File -# Begin Source File - -SOURCE=.\utility\xmlstorage.cpp -# End Source File -# Begin Source File - -SOURCE=.\utility\xmlstorage.h -# End Source File -# End Group -# Begin Group "resources" - -# PROP Default_Filter "bmp,ico" -# Begin Source File - -SOURCE=.\res\action.ico -# End Source File -# Begin Source File - -SOURCE=.\res\appicon.ico -# End Source File -# Begin Source File - -SOURCE=.\res\apps.ico -# End Source File -# Begin Source File - -SOURCE=.\res\arrow.ico -# End Source File -# Begin Source File - -SOURCE=.\res\arrow_dwn.ico -# End Source File -# Begin Source File - -SOURCE=.\res\arrow_up.ico -# End Source File -# Begin Source File - -SOURCE=.\res\arrowsel.ico -# End Source File -# Begin Source File - -SOURCE=.\res\computer.ico -# End Source File -# Begin Source File - -SOURCE=.\res\config.ico -# End Source File -# Begin Source File - -SOURCE=.\res\documents.ico -# End Source File -# Begin Source File - -SOURCE=.\res\dot.ico -# End Source File -# Begin Source File - -SOURCE=.\res\dot_red.ico -# End Source File -# Begin Source File - -SOURCE=.\res\dot_trans.ico -# End Source File -# Begin Source File - -SOURCE=.\res\drivebar.bmp -# End Source File -# Begin Source File - -SOURCE=".\explorer-jp.rc" -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\res\explorer.ico -# End Source File -# Begin Source File - -SOURCE=.\explorer_intres.h -# End Source File -# Begin Source File - -SOURCE=.\explorer_intres.rc -# End Source File -# Begin Source File - -SOURCE=.\res\favorites.ico -# End Source File -# Begin Source File - -SOURCE=.\res\floating.ico -# End Source File -# Begin Source File - -SOURCE=.\res\folder.ico -# End Source File -# Begin Source File - -SOURCE=.\res\icoali10.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig0.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig1.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig2.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig3.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig4.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig5.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig6.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig7.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig8.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\icoalig9.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\images.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\info.ico -# End Source File -# Begin Source File - -SOURCE=.\res\logoff.ico -# End Source File -# Begin Source File - -SOURCE=.\res\logov.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\logov16.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\logov256.bmp -# End Source File -# Begin Source File - -SOURCE=.\res\network.ico -# End Source File -# Begin Source File - -SOURCE=.\res\notify_l.ico -# End Source File -# Begin Source File - -SOURCE=.\res\notify_r.ico -# End Source File -# Begin Source File - -SOURCE=.\res\printer.ico -# End Source File -# Begin Source File - -SOURCE=.\res\reactos.ico -# End Source File -# Begin Source File - -SOURCE=".\res\ros-big.ico" -# End Source File -# Begin Source File - -SOURCE=".\res\search-doc.ico" -# End Source File -# Begin Source File - -SOURCE=.\res\search.ico -# End Source File -# Begin Source File - -SOURCE=.\res\speaker.ico -# End Source File -# Begin Source File - -SOURCE=.\res\startmenu.ico -# End Source File -# Begin Source File - -SOURCE=.\res\toolbar.bmp -# End Source File -# End Group -# Begin Group "taskbar" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\taskbar\desktopbar.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\desktopbar.h -# End Source File -# Begin Source File - -SOURCE=.\taskbar\favorites.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\favorites.h -# End Source File -# Begin Source File - -SOURCE=.\notifyhook\notifyhook.h -# End Source File -# Begin Source File - -SOURCE=.\taskbar\quicklaunch.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\quicklaunch.h -# End Source File -# Begin Source File - -SOURCE=.\taskbar\startmenu.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\startmenu.h -# End Source File -# Begin Source File - -SOURCE=.\taskbar\taskbar.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\taskbar.h -# End Source File -# Begin Source File - -SOURCE=.\taskbar\traynotify.cpp -# End Source File -# Begin Source File - -SOURCE=.\taskbar\traynotify.h -# End Source File -# End Group -# Begin Group "desktop" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\desktop\desktop.cpp -# End Source File -# Begin Source File - -SOURCE=.\desktop\desktop.h -# End Source File -# End Group -# Begin Group "doc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\doc\changes.txt -# End Source File -# Begin Source File - -SOURCE=.\doc\readme.txt -# End Source File -# Begin Source File - -SOURCE=.\doc\TODO.txt -# End Source File -# End Group -# Begin Group "shell" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\shell\entries.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\entries.h -# End Source File -# Begin Source File - -SOURCE=.\shell\fatfs.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\fatfs.h -# End Source File -# Begin Source File - -SOURCE=.\shell\filechild.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\filechild.h -# End Source File -# Begin Source File - -SOURCE=.\shell\mainframe.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\mainframe.h -# End Source File -# Begin Source File - -SOURCE=.\shell\ntobjfs.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\ntobjfs.h -# End Source File -# Begin Source File - -SOURCE=.\shell\pane.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\pane.h -# End Source File -# Begin Source File - -SOURCE=.\shell\regfs.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\regfs.h -# End Source File -# Begin Source File - -SOURCE=.\shell\shellbrowser.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\shellbrowser.h -# End Source File -# Begin Source File - -SOURCE=.\shell\shellfs.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\shellfs.h -# End Source File -# Begin Source File - -SOURCE=.\shell\startup.c -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\shell\unixfs.cpp -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\shell\unixfs.h -# End Source File -# Begin Source File - -SOURCE=.\shell\webchild.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\webchild.h -# End Source File -# Begin Source File - -SOURCE=.\shell\winfs.cpp -# End Source File -# Begin Source File - -SOURCE=.\shell\winfs.h -# End Source File -# End Group -# Begin Group "dialogs" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\dialogs\searchprogram.cpp -# End Source File -# Begin Source File - -SOURCE=.\dialogs\searchprogram.h -# End Source File -# Begin Source File - -SOURCE=.\dialogs\settings.cpp -# End Source File -# Begin Source File - -SOURCE=.\dialogs\settings.h -# End Source File -# End Group -# Begin Group "main" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\explorer.cpp -# End Source File -# Begin Source File - -SOURCE=.\explorer.h -# End Source File -# Begin Source File - -SOURCE=.\externals.h -# End Source File -# Begin Source File - -SOURCE=.\globals.h -# End Source File -# Begin Source File - -SOURCE=".\i386-stub-win32.c" -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\precomp.cpp -# ADD CPP /Yc"precomp.h" -# End Source File -# Begin Source File - -SOURCE=.\precomp.h -# End Source File -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="explorer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=explorer - Win32 WineDll +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "explorer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "explorer.mak" CFG="explorer - Win32 WineDll" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "explorer - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 Debug Release" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 Unicode Release" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 Unicode Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 _NO_COMUTIL" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 WineRelease" (based on "Win32 (x86) Console Application") +!MESSAGE "explorer - Win32 WineDll" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "explorer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O1 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 Debug Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "DRelease" +# PROP BASE Intermediate_Dir "DRelease" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "DRelease" +# PROP Intermediate_Dir "DRelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_ROS_" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "URelease" +# PROP BASE Intermediate_Dir "URelease" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "URelease" +# PROP Intermediate_Dir "URelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "UDebug" +# PROP BASE Intermediate_Dir "UDebug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "UDebug" +# PROP Intermediate_Dir "UDebug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 _NO_COMUTIL" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "explorer___Win32__NO_COMUTIL" +# PROP BASE Intermediate_Dir "explorer___Win32__NO_COMUTIL" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "_NO_COMUTIL" +# PROP Intermediate_Dir "_NO_COMUTIL" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "_NO_COMUTIL" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 shell32.lib comctl32.lib gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Win32" +# PROP BASE Intermediate_Dir "Win32" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Win32" +# PROP Intermediate_Dir "Win32" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib comctl32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Win32/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 WineRelease" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "explorer___Win32_WineRelease" +# PROP BASE Intermediate_Dir "explorer___Win32_WineRelease" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WineRelease" +# PROP Intermediate_Dir "WineRelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FR /YX /FD /GZ /c +# ADD CPP /nologo /MT /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /incremental:no /machine:I386 /out:"WineRelease/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "explorer - Win32 WineDll" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "explorer___Win32_WineDll" +# PROP BASE Intermediate_Dir "explorer___Win32_WineDll" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WineDll" +# PROP Intermediate_Dir "WineDll" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D "_ROS_" /D _WIN32_IE=0x0501 /D _WIN32_WINNT=0x0501 /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib ole32.lib /nologo /subsystem:windows /machine:I386 /pdbtype:sept +# SUBTRACT BASE LINK32 /pdb:none /debug +# ADD LINK32 gdi32.lib user32.lib advapi32.lib ole32.lib delayimp.lib /nologo /subsystem:windows /machine:I386 /out:"WineDll/wexplorer.exe" /pdbtype:sept /delayload:oleaut32.dll /delayload:wsock32.dll +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "explorer - Win32 Release" +# Name "explorer - Win32 Debug" +# Name "explorer - Win32 Debug Release" +# Name "explorer - Win32 Unicode Release" +# Name "explorer - Win32 Unicode Debug" +# Name "explorer - Win32 _NO_COMUTIL" +# Name "explorer - Win32" +# Name "explorer - Win32 WineRelease" +# Name "explorer - Win32 WineDll" +# Begin Group "utility" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\utility\dragdropimpl.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\dragdropimpl.h +# End Source File +# Begin Source File + +SOURCE=.\utility\shellbrowserimpl.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\shellbrowserimpl.h +# End Source File +# Begin Source File + +SOURCE=.\utility\shellclasses.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\shellclasses.h +# End Source File +# Begin Source File + +SOURCE=.\utility\treedroptarget.h +# End Source File +# Begin Source File + +SOURCE=.\utility\utility.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\utility.h +# End Source File +# Begin Source File + +SOURCE=.\utility\window.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\window.h +# End Source File +# Begin Source File + +SOURCE=.\utility\xmlstorage.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\xmlstorage.h +# End Source File +# End Group +# Begin Group "resources" + +# PROP Default_Filter "bmp,ico" +# Begin Source File + +SOURCE=.\res\action.ico +# End Source File +# Begin Source File + +SOURCE=.\res\appicon.ico +# End Source File +# Begin Source File + +SOURCE=.\res\apps.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrow.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrow_dwn.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrow_up.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrowsel.ico +# End Source File +# Begin Source File + +SOURCE=.\res\computer.ico +# End Source File +# Begin Source File + +SOURCE=.\res\config.ico +# End Source File +# Begin Source File + +SOURCE=.\res\documents.ico +# End Source File +# Begin Source File + +SOURCE=.\res\dot.ico +# End Source File +# Begin Source File + +SOURCE=.\res\dot_red.ico +# End Source File +# Begin Source File + +SOURCE=.\res\dot_trans.ico +# End Source File +# Begin Source File + +SOURCE=.\res\drivebar.bmp +# End Source File +# Begin Source File + +SOURCE=".\explorer-jp.rc" +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\res\explorer.ico +# End Source File +# Begin Source File + +SOURCE=.\explorer_intres.h +# End Source File +# Begin Source File + +SOURCE=.\explorer_intres.rc +# End Source File +# Begin Source File + +SOURCE=.\res\favorites.ico +# End Source File +# Begin Source File + +SOURCE=.\res\floating.ico +# End Source File +# Begin Source File + +SOURCE=.\res\folder.ico +# End Source File +# Begin Source File + +SOURCE=.\res\icoali10.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig0.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig1.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig2.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig3.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig4.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig5.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig6.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig7.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig8.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\icoalig9.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\images.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\info.ico +# End Source File +# Begin Source File + +SOURCE=.\res\logoff.ico +# End Source File +# Begin Source File + +SOURCE=.\res\logov.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\logov16.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\logov256.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\network.ico +# End Source File +# Begin Source File + +SOURCE=.\res\notify_l.ico +# End Source File +# Begin Source File + +SOURCE=.\res\notify_r.ico +# End Source File +# Begin Source File + +SOURCE=.\res\printer.ico +# End Source File +# Begin Source File + +SOURCE=.\res\reactos.ico +# End Source File +# Begin Source File + +SOURCE=".\res\ros-big.ico" +# End Source File +# Begin Source File + +SOURCE=".\res\search-doc.ico" +# End Source File +# Begin Source File + +SOURCE=.\res\search.ico +# End Source File +# Begin Source File + +SOURCE=.\res\speaker.ico +# End Source File +# Begin Source File + +SOURCE=.\res\startmenu.ico +# End Source File +# Begin Source File + +SOURCE=.\res\toolbar.bmp +# End Source File +# End Group +# Begin Group "taskbar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\taskbar\desktopbar.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\desktopbar.h +# End Source File +# Begin Source File + +SOURCE=.\taskbar\favorites.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\favorites.h +# End Source File +# Begin Source File + +SOURCE=.\notifyhook\notifyhook.h +# End Source File +# Begin Source File + +SOURCE=.\taskbar\quicklaunch.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\quicklaunch.h +# End Source File +# Begin Source File + +SOURCE=.\taskbar\startmenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\startmenu.h +# End Source File +# Begin Source File + +SOURCE=.\taskbar\taskbar.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\taskbar.h +# End Source File +# Begin Source File + +SOURCE=.\taskbar\traynotify.cpp +# End Source File +# Begin Source File + +SOURCE=.\taskbar\traynotify.h +# End Source File +# End Group +# Begin Group "desktop" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\desktop\desktop.cpp +# End Source File +# Begin Source File + +SOURCE=.\desktop\desktop.h +# End Source File +# End Group +# Begin Group "doc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\doc\changes.txt +# End Source File +# Begin Source File + +SOURCE=.\doc\readme.txt +# End Source File +# Begin Source File + +SOURCE=.\doc\TODO.txt +# End Source File +# End Group +# Begin Group "shell" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\shell\entries.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\entries.h +# End Source File +# Begin Source File + +SOURCE=.\shell\fatfs.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\fatfs.h +# End Source File +# Begin Source File + +SOURCE=.\shell\filechild.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\filechild.h +# End Source File +# Begin Source File + +SOURCE=.\shell\mainframe.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\mainframe.h +# End Source File +# Begin Source File + +SOURCE=.\shell\ntobjfs.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\ntobjfs.h +# End Source File +# Begin Source File + +SOURCE=.\shell\pane.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\pane.h +# End Source File +# Begin Source File + +SOURCE=.\shell\regfs.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\regfs.h +# End Source File +# Begin Source File + +SOURCE=.\shell\shellbrowser.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\shellbrowser.h +# End Source File +# Begin Source File + +SOURCE=.\shell\shellfs.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\shellfs.h +# End Source File +# Begin Source File + +SOURCE=.\shell\startup.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\shell\unixfs.cpp +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\shell\unixfs.h +# End Source File +# Begin Source File + +SOURCE=.\shell\webchild.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\webchild.h +# End Source File +# Begin Source File + +SOURCE=.\shell\winfs.cpp +# End Source File +# Begin Source File + +SOURCE=.\shell\winfs.h +# End Source File +# End Group +# Begin Group "dialogs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\dialogs\searchprogram.cpp +# End Source File +# Begin Source File + +SOURCE=.\dialogs\searchprogram.h +# End Source File +# Begin Source File + +SOURCE=.\dialogs\settings.cpp +# End Source File +# Begin Source File + +SOURCE=.\dialogs\settings.h +# End Source File +# End Group +# Begin Group "main" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\explorer.cpp +# End Source File +# Begin Source File + +SOURCE=.\explorer.h +# End Source File +# Begin Source File + +SOURCE=.\externals.h +# End Source File +# Begin Source File + +SOURCE=.\globals.h +# End Source File +# Begin Source File + +SOURCE=".\i386-stub-win32.c" +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\precomp.cpp +# ADD CPP /Yc"precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\precomp.h +# End Source File +# End Group +# End Target +# End Project diff --git a/reactos/subsys/system/explorer/explorer.dsw b/reactos/subsys/system/explorer/explorer.dsw index 51e9b3bd73e..d212f1818ff 100644 --- a/reactos/subsys/system/explorer/explorer.dsw +++ b/reactos/subsys/system/explorer/explorer.dsw @@ -1,53 +1,56 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "explorer"=.\explorer.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "make_explorer"=.\make_explorer.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "notifyhook"=.\notifyhook\notifyhook.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "explorer"=.\explorer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name notifyhook + End Project Dependency +}}} + +############################################################################### + +Project: "make_explorer"=.\make_explorer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "notifyhook"=.\notifyhook\notifyhook.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/reactos/subsys/system/explorer/explorer_intres.rc b/reactos/subsys/system/explorer/explorer_intres.rc index 6c2b8e91705..ae63eb852c5 100644 --- a/reactos/subsys/system/explorer/explorer_intres.rc +++ b/reactos/subsys/system/explorer/explorer_intres.rc @@ -348,7 +348,7 @@ BEGIN MENUITEM "&Suchen...\tF1", ID_HELP MENUITEM "Hilfe &verwenden\tF1", ID_HELP_USING MENUITEM SEPARATOR - MENUITEM "Info about &Winefile...", ID_ABOUT_WINEFILE + MENUITEM "&Info about ReactOS Explorer...", ID_ABOUT_WINEFILE END END @@ -386,8 +386,8 @@ BEGIN POPUP "&Hilfe" BEGIN MENUITEM "Explorer &FAQ...", ID_EXPLORER_FAQ - MENUITEM "&About Explorer...", ID_ABOUT_EXPLORER - MENUITEM "About &OS...", ID_ABOUT_WINDOWS + MENUITEM "&Über ReactOS Explorer...", ID_ABOUT_EXPLORER + MENUITEM "Über React&OS...", ID_ABOUT_WINDOWS END END @@ -620,7 +620,7 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_STARTMENU "Startmenu" + IDS_STARTMENU "Startmenü" IDS_MINIMIZE_ALL "alle Fenster minimieren" IDS_DESKTOP_NUM "Desktop %d" IDS_VOLUME "Lautstärke" @@ -773,8 +773,8 @@ BEGIN MENUITEM "&Status Bar", ID_VIEW_STATUSBAR, CHECKED MENUITEM "F&ull Screen\tCtrl+Shift+S", ID_VIEW_FULLSCREEN MENUITEM SEPARATOR - MENUITEM "&Symbol nach Programmstart", 65535 - MENUITEM "&Einstellungen beim Beenden speichern", 511 + MENUITEM "&Symbol after Running", 65535 + MENUITEM "&Save Changes on Exit", 511 END POPUP "&Security" BEGIN @@ -1099,7 +1099,7 @@ BEGIN IDS_CONTROL_PANEL "Control Panel" IDS_PRINTERS "Printers" IDS_BROWSE "Browse Files" - IDS_SEARCH_PRG "Search Programm..." + IDS_SEARCH_PRG "Search Program..." IDS_ALL_USERS "All Users\\" IDS_SEARCH "Search" IDS_ABOUT_EXPLORER "&About Explorer..." diff --git a/reactos/subsys/system/explorer/i386-stub-win32.c b/reactos/subsys/system/explorer/i386-stub-win32.c index 2fa2d56643f..5387fe18a2c 100644 --- a/reactos/subsys/system/explorer/i386-stub-win32.c +++ b/reactos/subsys/system/explorer/i386-stub-win32.c @@ -625,13 +625,10 @@ putpacket (unsigned char *buffer) while (getDebugChar () != '+'); } -void -debug_error (format, parm) - char *format; - char *parm; +void debug_error (char* format/*, char* parm*/) { if (remote_debug) - fprintf (stderr, format, parm); + fprintf (stderr, format/*, parm*/); } /* Address of a routine to RTE to if we get a memory fault. */ diff --git a/reactos/subsys/system/explorer/make_explorer.dsp b/reactos/subsys/system/explorer/make_explorer.dsp index 77b23cf9218..ac74928ae8c 100644 --- a/reactos/subsys/system/explorer/make_explorer.dsp +++ b/reactos/subsys/system/explorer/make_explorer.dsp @@ -1,209 +1,209 @@ -# Microsoft Developer Studio Project File - Name="make_explorer" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) External Target" 0x0106 - -CFG=make_explorer - Win32 bjam -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "make_explorer.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "make_explorer.mak" CFG="make_explorer - Win32 bjam" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "make_explorer - Win32 Release" (based on "Win32 (x86) External Target") -!MESSAGE "make_explorer - Win32 Debug" (based on "Win32 (x86) External Target") -!MESSAGE "make_explorer - Win32 Unicode Debug" (based on "Win32 (x86) External Target") -!MESSAGE "make_explorer - Win32 Unicode Release" (based on "Win32 (x86) External Target") -!MESSAGE "make_explorer - Win32 doxy docu" (based on "Win32 (x86) External Target") -!MESSAGE "make_explorer - Win32 bjam" (based on "Win32 (x86) External Target") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" - -!IF "$(CFG)" == "make_explorer - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Cmd_Line "NMAKE /f make_explorer.mak" -# PROP BASE Rebuild_Opt "/a" -# PROP BASE Target_File "make_explorer.exe" -# PROP BASE Bsc_Name "make_explorer.bsc" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0" -# PROP Rebuild_Opt "clean all" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Cmd_Line "NMAKE /f make_explorer.mak" -# PROP BASE Rebuild_Opt "/a" -# PROP BASE Target_File "make_explorer.exe" -# PROP BASE Bsc_Name "make_explorer.bsc" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0 DEBUG=1" -# PROP Rebuild_Opt "clean all" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=0 DEBUG=1" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "UDebug" -# PROP BASE Intermediate_Dir "UDebug" -# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" -# PROP BASE Rebuild_Opt "clean all" -# PROP BASE Target_File "explorer.exe" -# PROP BASE Bsc_Name "" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "UDebug" -# PROP Intermediate_Dir "UDebug" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" -# PROP Rebuild_Opt "clean all" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "URelease" -# PROP BASE Intermediate_Dir "URelease" -# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1" -# PROP BASE Rebuild_Opt "clean all" -# PROP BASE Target_File "explorer.exe" -# PROP BASE Bsc_Name "" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "URelease" -# PROP Intermediate_Dir "URelease" -# PROP Cmd_Line "msdevfilt -gcc make -f Makefile.PCH UNICODE=1" -# PROP Rebuild_Opt "clean all" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 doxy docu" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1" -# PROP BASE Rebuild_Opt "clean all" -# PROP BASE Target_File "explorer.exe" -# PROP BASE Bsc_Name "" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Cmd_Line "msdevfilt -java make docu" -# PROP Rebuild_Opt "full-docu" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 bjam" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1" -# PROP BASE Rebuild_Opt "clean all" -# PROP BASE Target_File "explorer.exe" -# PROP BASE Bsc_Name "" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" bjam" -# PROP Rebuild_Opt "clean&bjam release" -# PROP Target_File "explorer.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ENDIF - -# Begin Target - -# Name "make_explorer - Win32 Release" -# Name "make_explorer - Win32 Debug" -# Name "make_explorer - Win32 Unicode Debug" -# Name "make_explorer - Win32 Unicode Release" -# Name "make_explorer - Win32 doxy docu" -# Name "make_explorer - Win32 bjam" - -!IF "$(CFG)" == "make_explorer - Win32 Release" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Debug" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 doxy docu" - -!ELSEIF "$(CFG)" == "make_explorer - Win32 bjam" - -!ENDIF - -# Begin Source File - -SOURCE=..\..\..\ChangeLog -# End Source File -# Begin Source File - -SOURCE=.\Jamfile -# End Source File -# Begin Source File - -SOURCE=.\Makefile -# End Source File -# Begin Source File - -SOURCE=.\Makefile.MinGW -# End Source File -# Begin Source File - -SOURCE=.\Makefile.PCH -# End Source File -# Begin Source File - -SOURCE=.\Makefile.Wine -# End Source File -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="make_explorer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=make_explorer - Win32 bjam +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "make_explorer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "make_explorer.mak" CFG="make_explorer - Win32 bjam" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "make_explorer - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "make_explorer - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE "make_explorer - Win32 Unicode Debug" (based on "Win32 (x86) External Target") +!MESSAGE "make_explorer - Win32 Unicode Release" (based on "Win32 (x86) External Target") +!MESSAGE "make_explorer - Win32 doxy docu" (based on "Win32 (x86) External Target") +!MESSAGE "make_explorer - Win32 bjam" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "make_explorer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f make_explorer.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "make_explorer.exe" +# PROP BASE Bsc_Name "make_explorer.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f make_explorer.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "make_explorer.exe" +# PROP BASE Bsc_Name "make_explorer.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0 DEBUG=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=0 DEBUG=1" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "UDebug" +# PROP BASE Intermediate_Dir "UDebug" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "explorer.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "UDebug" +# PROP Intermediate_Dir "UDebug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "URelease" +# PROP BASE Intermediate_Dir "URelease" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "explorer.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "URelease" +# PROP Intermediate_Dir "URelease" +# PROP Cmd_Line "msdevfilt -gcc make -f Makefile.PCH UNICODE=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 doxy docu" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "explorer.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "msdevfilt -java make docu" +# PROP Rebuild_Opt "full-docu" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 bjam" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "explorer.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" bjam" +# PROP Rebuild_Opt "clean&bjam release" +# PROP Target_File "explorer.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "make_explorer - Win32 Release" +# Name "make_explorer - Win32 Debug" +# Name "make_explorer - Win32 Unicode Debug" +# Name "make_explorer - Win32 Unicode Release" +# Name "make_explorer - Win32 doxy docu" +# Name "make_explorer - Win32 bjam" + +!IF "$(CFG)" == "make_explorer - Win32 Release" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Debug" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Debug" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 Unicode Release" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 doxy docu" + +!ELSEIF "$(CFG)" == "make_explorer - Win32 bjam" + +!ENDIF + +# Begin Source File + +SOURCE=..\..\..\ChangeLog +# End Source File +# Begin Source File + +SOURCE=.\Jamfile +# End Source File +# Begin Source File + +SOURCE=.\Makefile +# End Source File +# Begin Source File + +SOURCE=.\Makefile.MinGW +# End Source File +# Begin Source File + +SOURCE=.\Makefile.PCH +# End Source File +# Begin Source File + +SOURCE=.\Makefile.Wine +# End Source File +# End Target +# End Project diff --git a/reactos/subsys/system/explorer/rc-mingw.jam b/reactos/subsys/system/explorer/rc-mingw.jam index 9f456560f6f..62f8f96bc58 100644 --- a/reactos/subsys/system/explorer/rc-mingw.jam +++ b/reactos/subsys/system/explorer/rc-mingw.jam @@ -33,12 +33,12 @@ actions quietly resource-compile-nt actions quietly resource-compile-mingw { - windres -o "$(<)" -i "$(>)" + windres -D__WINDRES__ -o "$(<)" -i "$(>)" } actions quietly resource-compile-cygwin { - windres --include-dir "$(>:D)" -o "$(<)" -i "$(>)" + windres -D__WINDRES__ --include-dir "$(>:D)" -o "$(<)" -i "$(>)" } actions quietly create-empty-object diff --git a/reactos/subsys/system/explorer/shell/entries.cpp b/reactos/subsys/system/explorer/shell/entries.cpp index cb008704068..4f12f01e474 100644 --- a/reactos/subsys/system/explorer/shell/entries.cpp +++ b/reactos/subsys/system/explorer/shell/entries.cpp @@ -401,7 +401,7 @@ BOOL Entry::launch_entry(HWND hwnd, UINT nCmdShow) } -HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) +HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs) { ShellPath shell_path = create_absolute_pidl(); LPCITEMIDLIST pidl_abs = shell_path; @@ -419,7 +419,7 @@ HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) HRESULT hr = (*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); if (SUCCEEDED(hr)) { - hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y); + hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); parentFolder->Release(); } @@ -442,7 +442,7 @@ HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos) ShellFolder parent_folder = parent_path; return ShellFolderContextMenu(parent_folder, hwnd, 1, &pidl, pos.x, pos.y); */ - return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y); + return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y, cm_ifs); } } diff --git a/reactos/subsys/system/explorer/shell/entries.h b/reactos/subsys/system/explorer/shell/entries.h index a1861ec55c4..49991084e31 100644 --- a/reactos/subsys/system/explorer/shell/entries.h +++ b/reactos/subsys/system/explorer/shell/entries.h @@ -112,7 +112,7 @@ public: virtual ShellPath create_absolute_pidl() const {return (LPCITEMIDLIST)NULL;} virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); - virtual HRESULT do_context_menu(HWND hwnd, const POINT& pos); + virtual HRESULT do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs); }; diff --git a/reactos/subsys/system/explorer/shell/filechild.cpp b/reactos/subsys/system/explorer/shell/filechild.cpp index 3cedc016301..bf457183610 100644 --- a/reactos/subsys/system/explorer/shell/filechild.cpp +++ b/reactos/subsys/system/explorer/shell/filechild.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -123,7 +123,7 @@ INT_PTR CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPA // FileChildWindow FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) - : ChildWindow(hwnd, info) + : super(hwnd, info) { CONTEXT("FileChildWindow::FileChildWindow()"); @@ -431,12 +431,15 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam; Entry* entry = (Entry*) dis->itemData; - if (dis->CtlID == IDW_TREE_LEFT) + if (dis->CtlID == IDW_TREE_LEFT) { _left->draw_item(dis, entry); - else + return TRUE; + } else if (dis->CtlID == IDW_TREE_RIGHT) { _right->draw_item(dis, entry); + return TRUE; + } - return TRUE;} + goto def;} case WM_SIZE: if (wparam != SIZE_MINIMIZED) @@ -507,7 +510,7 @@ LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) if (idx != -1) { Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx); - CHECKERROR(entry->do_context_menu(_hwnd, pt_screen)); + CHECKERROR(entry->do_context_menu(_hwnd, pt_screen, _cm_ifs)); } break;} diff --git a/reactos/subsys/system/explorer/shell/filechild.h b/reactos/subsys/system/explorer/shell/filechild.h index d5d0721424c..a81ea0ddd0e 100644 --- a/reactos/subsys/system/explorer/shell/filechild.h +++ b/reactos/subsys/system/explorer/shell/filechild.h @@ -85,9 +85,9 @@ struct WebChildWndInfo : public FileChildWndInfo /// MDI child window displaying file lists -struct FileChildWindow : public ChildWindow +struct FileChildWindow : public ExtContextMenuHandlerT { - typedef ChildWindow super; + typedef ExtContextMenuHandlerT super; FileChildWindow(HWND hwnd, const FileChildWndInfo& info); diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index 38df78cd364..10699aa7b6d 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -50,13 +50,12 @@ HWND MainFrameBase::Create(LPCTSTR path, bool mdi, UINT cmdshow) hMainFrame = SDIMainFrame::Create(); if (hMainFrame) { - String sPath; HWND hwndOld = g_Globals._hMainWnd; g_Globals._hMainWnd = hMainFrame; if (path) { - sPath = path; // copy path to avoid accessing freed memory + static String sPath = path; // copy path to avoid accessing freed memory path = sPath; } @@ -1565,7 +1564,7 @@ void SDIMainFrame::update_shell_browser() } _shellBrowser = auto_ptr(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd, - _shellpath_info, _himlSmall, this)); + _shellpath_info, _himlSmall, this, _cm_ifs)); _shellBrowser->Init(_hwnd); diff --git a/reactos/subsys/system/explorer/shell/mainframe.h b/reactos/subsys/system/explorer/shell/mainframe.h index a41d6508e7c..5cdc3206ce5 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.h +++ b/reactos/subsys/system/explorer/shell/mainframe.h @@ -124,9 +124,13 @@ protected: #endif -struct SDIMainFrame : public ShellBrowserChildT +struct SDIMainFrame : public ExtContextMenuHandlerT< + ShellBrowserChildT + > { - typedef ShellBrowserChildT super; + typedef ExtContextMenuHandlerT< + ShellBrowserChildT + > super; SDIMainFrame(HWND hwnd); diff --git a/reactos/subsys/system/explorer/shell/ntobjfs.cpp b/reactos/subsys/system/explorer/shell/ntobjfs.cpp index 286a8f8963e..f7e86a0a691 100644 --- a/reactos/subsys/system/explorer/shell/ntobjfs.cpp +++ b/reactos/subsys/system/explorer/shell/ntobjfs.cpp @@ -227,6 +227,16 @@ void NtObjDirectory::read_directory(int scan_flags) memset(&w32fd, 0, sizeof(WIN32_FIND_DATA)); #ifdef UNICODE + if (info->name.string_ptr) { + info->name.string_ptr[info->name.string_len / sizeof(WCHAR)] = 0; + } else { + info->name.string_ptr = TEXT(""); + } + if (info->type.string_ptr) { + info->type.string_ptr[info->type.string_len / sizeof(WCHAR)] = 0; + } else { + info->type.string_ptr = TEXT(""); + } wcscpyn(p, info->name.string_ptr, _MAX_PATH); #else WideCharToMultiByte(CP_ACP, 0, info->name.string_ptr, info->name.string_len, p, MAX_PATH, 0, 0); diff --git a/reactos/subsys/system/explorer/shell/pane.cpp b/reactos/subsys/system/explorer/shell/pane.cpp index 523e57dc190..975379939b5 100644 --- a/reactos/subsys/system/explorer/shell/pane.cpp +++ b/reactos/subsys/system/explorer/shell/pane.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.cpp b/reactos/subsys/system/explorer/shell/shellbrowser.cpp index 3f958eb0b57..91a4dd45e07 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.cpp +++ b/reactos/subsys/system/explorer/shell/shellbrowser.cpp @@ -31,13 +31,15 @@ #include "../explorer_intres.h" -ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, HIMAGELIST himl, BrowserCallback* cb) +ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, + HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs) : _hwnd(hwnd), _left_hwnd(left_hwnd), _right_hwnd(right_hwnd), _create_info(create_info), _himl(himl), - _callback(cb) + _callback(cb), + _cm_ifs(cm_ifs) { _pShellView = NULL; _pDropTarget = NULL; @@ -204,7 +206,7 @@ void ShellBrowser::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh) Entry* entry = (Entry*)itemData; ClientToScreen(_left_hwnd, &tvhti.pt); - CHECKERROR(entry->do_context_menu(_hwnd, tvhti.pt)); + CHECKERROR(entry->do_context_menu(_hwnd, tvhti.pt, _cm_ifs)); } } } @@ -574,7 +576,7 @@ void MDIShellBrowserChild::update_shell_browser() } _shellBrowser = auto_ptr(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd, - _shellpath_info, _himlSmall, this)); + _shellpath_info, _himlSmall, this, _cm_ifs)); _shellBrowser->Init(_hwndFrame); } diff --git a/reactos/subsys/system/explorer/shell/shellbrowser.h b/reactos/subsys/system/explorer/shell/shellbrowser.h index 18360e9faac..d256a6b03c2 100644 --- a/reactos/subsys/system/explorer/shell/shellbrowser.h +++ b/reactos/subsys/system/explorer/shell/shellbrowser.h @@ -57,7 +57,8 @@ struct BrowserCallback /// Implementation of IShellBrowserImpl interface in explorer child windows struct ShellBrowser : public IShellBrowserImpl { - ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, HIMAGELIST himl, BrowserCallback* cb); + ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info, + HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs); virtual ~ShellBrowser(); //IOleWindow @@ -153,6 +154,8 @@ protected: Root _root; ShellDirectory* _cur_dir; + CtxMenuInterfaces& _cm_ifs; + void InitializeTree(HIMAGELIST himl); bool InitDragDrop(); @@ -231,9 +234,13 @@ protected: #ifndef _NO_MDI -struct MDIShellBrowserChild : public ShellBrowserChildT +struct MDIShellBrowserChild : public ExtContextMenuHandlerT< + ShellBrowserChildT + > { - typedef ShellBrowserChildT super; + typedef ExtContextMenuHandlerT< + ShellBrowserChildT + > super; MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info); diff --git a/reactos/subsys/system/explorer/shell/shellfs.cpp b/reactos/subsys/system/explorer/shell/shellfs.cpp index 49748a7f60e..d6360979dae 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.cpp +++ b/reactos/subsys/system/explorer/shell/shellfs.cpp @@ -202,14 +202,14 @@ BOOL ShellEntry::launch_entry(HWND hwnd, UINT nCmdShow) } -HRESULT ShellEntry::do_context_menu(HWND hwnd, LPPOINT pptScreen) +HRESULT ShellEntry::do_context_menu(HWND hwnd, LPPOINT pptScreen, CtxMenuInterfaces& cm_ifs) { ShellDirectory* dir = static_cast(_up); ShellFolder folder = dir? dir->_folder: GetDesktopFolder(); LPCITEMIDLIST pidl = _pidl; - return ShellFolderContextMenu(folder, hwnd, 1, &pidl, pptScreen->x, pptScreen->y); + return ShellFolderContextMenu(folder, hwnd, 1, &pidl, pptScreen->x, pptScreen->y, cm_ifs); } diff --git a/reactos/subsys/system/explorer/shell/shellfs.h b/reactos/subsys/system/explorer/shell/shellfs.h index dd5576fc68d..9f8276d18db 100644 --- a/reactos/subsys/system/explorer/shell/shellfs.h +++ b/reactos/subsys/system/explorer/shell/shellfs.h @@ -36,7 +36,7 @@ struct ShellEntry : public Entry virtual ShellPath create_absolute_pidl() const; virtual HRESULT GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut); virtual BOOL launch_entry(HWND hwnd, UINT nCmdShow=SW_SHOWNORMAL); - virtual HRESULT do_context_menu(HWND hwnd, LPPOINT pptScreen); + virtual HRESULT do_context_menu(HWND hwnd, LPPOINT pptScreen, CtxMenuInterfaces& cm_ifs); IShellFolder* get_parent_folder() const; diff --git a/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp b/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp index 529324c4187..f10fb26a7f3 100644 --- a/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp +++ b/reactos/subsys/system/explorer/taskbar/quicklaunch.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -247,7 +247,7 @@ LRESULT QuickLaunchBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) } if (entry) // entry is NULL for desktop switch buttons - CHECKERROR(entry->do_context_menu(_hwnd, screen_pt)); + CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs)); else goto def; break;} diff --git a/reactos/subsys/system/explorer/taskbar/quicklaunch.h b/reactos/subsys/system/explorer/taskbar/quicklaunch.h index ff1230ca567..cd762a44110 100644 --- a/reactos/subsys/system/explorer/taskbar/quicklaunch.h +++ b/reactos/subsys/system/explorer/taskbar/quicklaunch.h @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -57,9 +57,9 @@ struct QuickLaunchMap : public map /// quick launch bar window -struct QuickLaunchBar : public SubclassedWindow +struct QuickLaunchBar : public ExtContextMenuHandlerT { - typedef SubclassedWindow super; + typedef ExtContextMenuHandlerT super; QuickLaunchBar(HWND hwnd); ~QuickLaunchBar(); diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index 70befc550ba..a113bfb1651 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -442,7 +442,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) Entry* entry = *it; if (entry) { - CHECKERROR(entry->do_context_menu(_hwnd, screen_pt)); // may close start menu because of focus loss + CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs)); // may close start menu because of focus loss break; ///@todo handle context menu for more than one entry } } @@ -1254,7 +1254,7 @@ void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries) SHELLEXECUTEINFO shexinfo; shexinfo.cbSize = sizeof(SHELLEXECUTEINFO); - shexinfo.fMask = SEE_MASK_INVOKEIDLIST; // SEE_MASK_IDLIST is also possible. + shexinfo.fMask = SEE_MASK_IDLIST; // SEE_MASK_INVOKEIDLIST is also possible. shexinfo.hwnd = hparent; shexinfo.lpVerb = NULL; shexinfo.lpFile = NULL; diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index fb2a9e72666..21bb72d31af 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -202,15 +202,15 @@ extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON */ struct StartMenu : #ifdef _LIGHT_STARTMENU - public OwnerDrawParent + public ExtContextMenuHandlerT > #else - public OwnerDrawParent + public ExtContextMenuHandlerT > #endif { #ifdef _LIGHT_STARTMENU - typedef OwnerDrawParent super; + typedef ExtContextMenuHandlerT > super; #else - typedef OwnerDrawParent super; + typedef ExtContextMenuHandlerT > super; #endif StartMenu(HWND hwnd); diff --git a/reactos/subsys/system/explorer/taskbar/taskbar.cpp b/reactos/subsys/system/explorer/taskbar/taskbar.cpp index dc0b214dfe3..c18f1a1c550 100644 --- a/reactos/subsys/system/explorer/taskbar/taskbar.cpp +++ b/reactos/subsys/system/explorer/taskbar/taskbar.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/reactos/subsys/system/explorer/taskbar/taskbar.h b/reactos/subsys/system/explorer/taskbar/taskbar.h index 6337ec3cbe5..bc1d4e0bb03 100644 --- a/reactos/subsys/system/explorer/taskbar/taskbar.h +++ b/reactos/subsys/system/explorer/taskbar/taskbar.h @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.cpp b/reactos/subsys/system/explorer/taskbar/traynotify.cpp index 07c0491cc01..072e387318c 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.cpp +++ b/reactos/subsys/system/explorer/taskbar/traynotify.cpp @@ -635,9 +635,11 @@ void NotifyArea::UpdateIcons() UpdateWindow(_hwnd); } +#ifndef _NO_ALPHABLEND #ifdef _MSC_VER #pragma comment(lib, "msimg32") // for AlphaBlend() #endif +#endif void NotifyArea::Paint() { @@ -658,17 +660,21 @@ void NotifyArea::Paint() x += NOTIFYICON_DIST; } +#ifndef _NO_ALPHABLEND MemCanvas mem_dc; SelectedBitmap bmp(mem_dc, CreateCompatibleBitmap(canvas, NOTIFYICON_SIZE, NOTIFYICON_SIZE)); RECT rect = {0, 0, NOTIFYICON_SIZE, NOTIFYICON_SIZE}; BLENDFUNCTION blend = {AC_SRC_OVER, 0, 128, 0}; // 50 % visible +#endif for(NotifyIconSet::const_iterator it=_sorted_icons.begin(); it!=_sorted_icons.end(); ++it) { +#ifndef _NO_ALPHABLEND if (it->_dwState & NIS_HIDDEN) { FillRect(mem_dc, &rect, GetSysColorBrush(COLOR_BTNFACE)); DrawIconEx(mem_dc, 0, 0, it->_hIcon, NOTIFYICON_SIZE, NOTIFYICON_SIZE, 0, 0, DI_NORMAL); AlphaBlend(canvas, x, y, NOTIFYICON_SIZE, NOTIFYICON_SIZE, mem_dc, 0, 0, NOTIFYICON_SIZE, NOTIFYICON_SIZE, blend); } else +#endif DrawIconEx(canvas, x, y, it->_hIcon, NOTIFYICON_SIZE, NOTIFYICON_SIZE, 0, 0, DI_NORMAL); x += NOTIFYICON_DIST; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.cpp b/reactos/subsys/system/explorer/utility/shellclasses.cpp index 4b999d97610..bbe52b3ffa6 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.cpp +++ b/reactos/subsys/system/explorer/utility/shellclasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -472,7 +472,56 @@ SpecialFolderFSPath::SpecialFolderFSPath(int folder, HWND hwnd) } -HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* apidl, int x, int y) +void CtxMenuInterfaces::reset() +{ + _pctxmenu2 = NULL; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + _pctxmenu3 = NULL; +#endif +} + +bool CtxMenuInterfaces::HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + if (_pctxmenu3) { + if (SUCCEEDED(_pctxmenu3->HandleMenuMsg(nmsg, wparam, lparam))) + return true; + } +#endif + + if (_pctxmenu2) + if (SUCCEEDED(_pctxmenu2->HandleMenuMsg(nmsg, wparam, lparam))) + return true; + + return false; +} + +IContextMenu* CtxMenuInterfaces::query_interfaces(IContextMenu* pcm1) +{ + IContextMenu* pcm = NULL; + + reset(); + + // Get the higher version context menu interfaces. +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + if (pcm1->QueryInterface(IID_IContextMenu3, (void**)&pcm) == NOERROR) + _pctxmenu3 = (LPCONTEXTMENU3)pcm; + else +#endif + if (pcm1->QueryInterface (IID_IContextMenu2, (void**)&pcm) == NOERROR) + _pctxmenu2 = (LPCONTEXTMENU2)pcm; + + if (pcm) { + pcm1->Release(); + return pcm; + } else + return pcm1; +} + + +HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, + LPCITEMIDLIST* apidl, int x, int y, CtxMenuInterfaces& cm_ifs) { IContextMenu* pcm; @@ -480,6 +529,8 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int // HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); if (SUCCEEDED(hr)) { + pcm = cm_ifs.query_interfaces(pcm); + HMENU hmenu = CreatePopupMenu(); if (hmenu) { @@ -488,6 +539,8 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int if (SUCCEEDED(hr)) { UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL); + cm_ifs.reset(); + if (idCmd) { CMINVOKECOMMANDINFO cmi; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.h b/reactos/subsys/system/explorer/utility/shellclasses.h index f3e66a47265..0e1f6ff7dfe 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.h +++ b/reactos/subsys/system/explorer/utility/shellclasses.h @@ -1,5 +1,5 @@ /* - * Copyright 2003, 2004 Martin Fuchs + * Copyright 2003, 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1003,4 +1003,77 @@ protected: LPIDA _pIDList; }; -extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, LPCITEMIDLIST* ppidl, int x, int y); + +struct CtxMenuInterfaces +{ + CtxMenuInterfaces() + { + reset(); + } + + void reset(); + bool HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam); + IContextMenu* query_interfaces(IContextMenu* pcm1); + + IContextMenu2* _pctxmenu2; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + IContextMenu3* _pctxmenu3; +#endif +}; + +template struct ExtContextMenuHandlerT + : public BASE +{ + typedef BASE super; + + ExtContextMenuHandlerT(HWND hwnd) + : super(hwnd) + { + } + + template ExtContextMenuHandlerT(HWND hwnd, const PARA& info) + : super(hwnd, info) + { + } + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case WM_DRAWITEM: + case WM_MEASUREITEM: + if (!wparam) // Is the message menu-related? + if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam)) + return TRUE; + + break; + + case WM_INITMENUPOPUP: + if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam)) + return 0; + + break; + +#ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005) + case WM_MENUCHAR: // only supported by IContextMenu3 + if (_cm_ifs._pctxmenu3) { + LRESULT lResult = 0; + + _cm_ifs._pctxmenu3->HandleMenuMsg2(nmsg, wparam, lparam, &lResult); + + return lResult; + } + + return 0; +#endif + } + + return super::WndProc(nmsg, wparam, lparam); + } + +protected: + CtxMenuInterfaces _cm_ifs; +}; + +extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl, + LPCITEMIDLIST* ppidl, int x, int y, CtxMenuInterfaces& cm_ifs); diff --git a/reactos/subsys/system/explorer/utility/xmlstorage.h b/reactos/subsys/system/explorer/utility/xmlstorage.h index fdf862ee5fc..60b5fab1daf 100644 --- a/reactos/subsys/system/explorer/utility/xmlstorage.h +++ b/reactos/subsys/system/explorer/utility/xmlstorage.h @@ -612,23 +612,6 @@ struct XMLNode : public XS_String return out; } -protected: - Children _children; - AttributeMap _attributes; - - std::string _leading; - std::string _content; - std::string _end_leading; - std::string _trailing; - - XMLNode* get_first_child() const - { - if (!_children.empty()) - return _children.front(); - else - return NULL; - } - XMLNode* find(const XS_String& name, int n=0) const { for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) @@ -687,6 +670,23 @@ protected: /// relative XPath create function XMLNode* create_relative(const char* path); +protected: + Children _children; + AttributeMap _attributes; + + std::string _leading; + std::string _content; + std::string _end_leading; + std::string _trailing; + + XMLNode* get_first_child() const + { + if (!_children.empty()) + return _children.front(); + else + return NULL; + } + void write_worker(std::ostream& out, int indent) const; void pretty_write_worker(std::ostream& out, int indent) const; void smart_write_worker(std::ostream& out, int indent) const; diff --git a/reactos/subsys/system/ibrowser/Makefile b/reactos/subsys/system/ibrowser/Makefile new file mode 100644 index 00000000000..36881540edb --- /dev/null +++ b/reactos/subsys/system/ibrowser/Makefile @@ -0,0 +1,47 @@ +# +# ROS Internet Web Browser +# +# Makefile +# + +PATH_TO_TOP := ../../.. + +TARGET_TYPE := program + +TARGET_APPTYPE := windows + +TARGET_NAME := ibrowser + +TARGET_INSTALLDIR := . + +TARGET_CFLAGS := \ + -D__USE_W32API -DWIN32 -D_ROS_ \ + -D_WIN32_IE=0x0600 -D_WIN32_WINNT=0x0501 -DWINVER=0x0500 \ + -DUNICODE -fexceptions -Wall + +TARGET_CPPFLAGS := $(TARGET_CFLAGS) + +TARGET_RCFLAGS := -D__USE_W32API -DWIN32 -D_ROS_ -D__WINDRES__ + +TARGET_SDKLIBS := gdi32.a comctl32.a ole32.a oleaut32.a shell32.a expat.a + +TARGET_GCCLIBS := stdc++ uuid + +TARGET_OBJECTS := \ + ibrowser.o \ + mainframe.o \ + webchild.o \ + favorites.o \ + utility/utility.o \ + utility/window.o \ + utility/xmlstorage.o + +TARGET_CPPAPP := yes + +TARGET_PCH := precomp.h + +DEP_OBJECTS := $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak +include $(TOOLS_PATH)/helper.mk +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/subsys/system/ibrowser/Makefile.MinGW b/reactos/subsys/system/ibrowser/Makefile.MinGW new file mode 100644 index 00000000000..b968c1c4938 --- /dev/null +++ b/reactos/subsys/system/ibrowser/Makefile.MinGW @@ -0,0 +1,67 @@ +# +# ROS Internet Web Browser +# +# Makefile.MinGW +# + +CC = gcc +CXX = g++ +LINK = g++ + +CFLAGS = -DWIN32 -D_WIN32_IE=0x0600 -D_WIN32_WINNT=0x0501 -DWINVER=0x0500 -fexceptions -Wall -I. +RCFLAGS = -DWIN32 -D__WINDRES__ +LFLAGS = -Wl,--subsystem,windows + +ifdef DEBUG +CFLAGS += -D_DEBUG -g +RCFLAGS += -D_DEBUG +LFLAGS += -g +else +CFLAGS += -DNDEBUG -Os +RCFLAGS += -DNDEBUG +LFLAGS += -s +endif + +ifndef UNICODE +UNICODE = 1 +endif + +ifeq ($(UNICODE),1) +CFLAGS += -DUNICODE +# LFLAGS+= -Wl,--entry,_wWinMain@16 +RCFLAGS += -DUNICODE +endif + +CXXFLAGS = $(CFLAGS) + +EXEC_SUFFIX = .exe +RES_SUFFIX = .coff + +VPATH = utility + +PROGRAM = ibrowser + +TARGET = $(PROGRAM)$(EXEC_SUFFIX) + +OBJECTS = \ + utility.o \ + window.o \ + ibrowser.o \ + webchild.o \ + mainframe.o \ + favorites.o \ + xmlstorage.o + +LIBS = gdi32 comctl32 shell32 ole32 uuid oleaut32 + +all: $(TARGET) + +$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) libexpat.dll + $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS)) + +ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico + windres $(RCFLAGS) -o $@ $(PROGRAM)_intres.rc + +clean: + rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) \ + desktop/*.o dialogs/*.o shell/*.o taskbar/*.o utility/*.o diff --git a/reactos/subsys/system/ibrowser/Makefile.PCH b/reactos/subsys/system/ibrowser/Makefile.PCH new file mode 100644 index 00000000000..71fc8575fa3 --- /dev/null +++ b/reactos/subsys/system/ibrowser/Makefile.PCH @@ -0,0 +1,72 @@ +# +# ROS Internet Web Browser +# +# Makefile.PCH +# +# MinGW Makefile with precompiled header support +# + +CC = gcc +CXX = g++ +LINK = g++ + +CFLAGS = -DWIN32 -D_WIN32_IE=0x0600 -D_WIN32_WINNT=0x0501 -DWINVER=0x0500 -fexceptions -Wall -I. +RCFLAGS = -DWIN32 -D__WINDRES__ +LFLAGS = -Wl,--subsystem,windows + +ifdef DEBUG +CFLAGS += -D_DEBUG -g +RCFLAGS += -D_DEBUG +LFLAGS += -g +else +CFLAGS += -DNDEBUG -Os -march=pentium4 +RCFLAGS += -DNDEBUG +LFLAGS += -s +endif + +ifndef UNICODE +UNICODE = 1 +endif + +ifeq ($(UNICODE),1) +CFLAGS += -DUNICODE +# LFLAGS+= -Wl,--entry,_wWinMain@16 +RCFLAGS += -DUNICODE +endif + +CXXFLAGS = $(CFLAGS) + +EXEC_SUFFIX = .exe +RES_SUFFIX = .coff + +VPATH = utility + +PROGRAM = ibrowser + +TARGET = $(PROGRAM)$(EXEC_SUFFIX) + +OBJECTS = \ + utility.o \ + window.o \ + ibrowser.o \ + webchild.o \ + mainframe.o \ + favorites.o \ + xmlstorage.o + +LIBS = gdi32 comctl32 shell32 ole32 oleaut32 uuid + +all: precomp.h.gch $(TARGET) + +precomp.h.gch: *.h utility/*.h + $(CXX) $(CFLAGS) precomp.h + +$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) libexpat.dll + $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS)) + +ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico + windres $(RCFLAGS) -o $@ $(PROGRAM)_intres.rc + +clean: + rm -f $(TARGET) $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) precomp.h.gch \ + utility/*.o diff --git a/reactos/subsys/system/ibrowser/expat.license b/reactos/subsys/system/ibrowser/expat.license new file mode 100644 index 00000000000..5c5d524a1f8 --- /dev/null +++ b/reactos/subsys/system/ibrowser/expat.license @@ -0,0 +1,22 @@ +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + and Clark Cooper +Copyright (c) 2001, 2002, 2003 Expat maintainers. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/reactos/subsys/system/ibrowser/favorites.cpp b/reactos/subsys/system/ibrowser/favorites.cpp new file mode 100644 index 00000000000..0da5cc365e2 --- /dev/null +++ b/reactos/subsys/system/ibrowser/favorites.cpp @@ -0,0 +1,494 @@ +/* + * Copyright 2004 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // Explorer and Desktop clone + // + // favorites.cpp + // + // Martin Fuchs, 04.04.2004 + // + + +#include "precomp.h" + + +String DecodeURLString(const char* s) +{ + TCHAR buffer[BUFFER_LEN]; + LPTSTR o = buffer; + + for(const char* p=s; *p; ++p) + if (*p == '%') { + if (!strncmp(p+1, "20", 2)) { + *o++ = ' '; + p += 2; + } else + *o++ = *p; + } else + *o++ = *p; + + return String(buffer, o-buffer); +} + + + /// read .URL file +bool Bookmark::read_url(LPCTSTR path) +{ + char line[BUFFER_LEN]; + + tifstream in(path); + + while(in.good()) { + in.getline(line, BUFFER_LEN); + + const char* p = line; + while(isspace(*p)) + ++p; + + const char* keyword = p; + const char* eq = strchr(p, '='); + + if (eq) { + const char* cont = eq + 1; + while(isspace(*cont)) + ++cont; + + if (!strnicmp(keyword, "URL", 3)) + _url = DecodeURLString(cont); + else if (!strnicmp(keyword, "IconFile", 8)) + _icon_path = DecodeURLString(cont); + } + } + + return true; +} + + /// convert XBEL bookmark node +bool Bookmark::read(const_XMLPos& pos) +{ + _url = pos.get("href").c_str(); + + if (pos.go_down("title")) { + _name = pos->get_content(); + pos.back(); + } + + if (pos.go_down("desc")) { + _description = pos->get_content(); + pos.back(); + } + + if (pos.go_down("info")) { + const_XMLChildrenFilter metadata(pos, "metadata"); + + for(const_XMLChildrenFilter::const_iterator it=metadata.begin(); it!=metadata.end(); ++it) { + const XMLNode& node = **it; + const_XMLPos sub_pos(&node); + + if (node.get("owner") == "ros-explorer") { + if (sub_pos.go_down("icon")) { + _icon_path = sub_pos.get("path").c_str(); + _icon_idx = XS_toi(sub_pos.get("index")); + + sub_pos.back(); // + } + } + } + + pos.back(); // + pos.back(); // + } + + return !_url.empty(); // _url is mandatory. +} + + /// write XBEL bookmark node +void Bookmark::write(XMLPos& pos) const +{ + pos.create("bookmark"); + + pos["href"] = _url.c_str(); + + if (!_name.empty()) { + pos.create("title"); + pos->set_content(_name); + pos.back(); + } + + if (!_description.empty()) { + pos.create("desc"); + pos->set_content(_description); + pos.back(); + } + + if (!_icon_path.empty()) { + pos.create("info"); + pos.create("metadata"); + pos["owner"] = "ros-explorer"; + pos.create("icon"); + pos["path"] = _icon_path.c_str(); + pos["index"].printf(XS_TEXT("%d"), _icon_idx); + pos.back(); // + pos.back(); // + pos.back(); // + } + + pos.back(); +} + + + /// read bookmark folder from XBEL formated XML tree +void BookmarkFolder::read(const_XMLPos& pos) +{ + if (pos.go_down("title")) { + _name = pos->get_content(); + pos.back(); + } + + if (pos.go_down("desc")) { + _description = pos->get_content(); + pos.back(); + } + + _bookmarks.read(pos); +} + + /// write bookmark folder content from XBEL formated XML tree +void BookmarkFolder::write(XMLPos& pos) const +{ + pos.create("folder"); + + if (!_name.empty()) { + pos.create("title"); + pos->set_content(_name); + pos.back(); + } + + if (!_description.empty()) { + pos.create("desc"); + pos->set_content(_description); + pos.back(); + } + + _bookmarks.write(pos); +} + + +BookmarkNode::BookmarkNode() + : _type(BMNT_NONE) +{ + _pbookmark = NULL; +} + +BookmarkNode::BookmarkNode(const Bookmark& bm) + : _type(BMNT_BOOKMARK) +{ + _pbookmark = new Bookmark(bm); +} + +BookmarkNode::BookmarkNode(const BookmarkFolder& bmf) + : _type(BMNT_FOLDER) +{ + _pfolder = new BookmarkFolder(bmf); +} + +BookmarkNode::BookmarkNode(const BookmarkNode& other) + : _type(other._type) +{ + if (other._type == BMNT_BOOKMARK) + _pbookmark = new Bookmark(*other._pbookmark); + else if (other._type == BMNT_FOLDER) + _pfolder = new BookmarkFolder(*other._pfolder); + else + _pbookmark = NULL; +} + +BookmarkNode::~BookmarkNode() +{ + if (_type == BMNT_BOOKMARK) + delete _pbookmark; + else if (_type == BMNT_FOLDER) + delete _pfolder; +} + +BookmarkNode& BookmarkNode::operator=(const Bookmark& bm) +{ + clear(); + + _pbookmark = new Bookmark(bm); + + return *this; +} + +BookmarkNode& BookmarkNode::operator=(const BookmarkFolder& bmf) +{ + clear(); + + _pfolder = new BookmarkFolder(bmf); + + return *this; +} + +BookmarkNode& BookmarkNode::operator=(const BookmarkNode& other) +{ + clear(); + + _type = other._type; + + if (other._type == BMNT_BOOKMARK) + _pbookmark = new Bookmark(*other._pbookmark); + else if (other._type == BMNT_FOLDER) + _pfolder = new BookmarkFolder(*other._pfolder); + + return *this; +} + +void BookmarkNode::clear() +{ + if (_type == BMNT_BOOKMARK) { + delete _pbookmark; + _pbookmark = NULL; + } + else if (_type == BMNT_FOLDER) { + delete _pfolder; + _pfolder = NULL; + } + + _type = BMNT_NONE; +} + + + /// read bookmark list from XBEL formated XML tree +void BookmarkList::read(const_XMLPos& pos) +{ + const XMLNode::Children& children = pos->get_children(); + + for(XMLNode::Children::const_iterator it=children.begin(); it!=children.end(); ++it) { + const XMLNode& node = **it; + const_XMLPos sub_pos(&node); + + if (node == "folder") { + BookmarkFolder folder; + + folder.read(sub_pos); + + push_back(folder); + } else if (node == "bookmark") { + Bookmark bookmark; + + if (bookmark.read(sub_pos)) + push_back(bookmark); + } + } +} + + /// write bookmark list into XBEL formated XML tree +void BookmarkList::write(XMLPos& pos) const +{ + for(const_iterator it=begin(); it!=end(); ++it) { + const BookmarkNode& node = *it; + + if (node._type == BookmarkNode::BMNT_FOLDER) { + const BookmarkFolder& folder = *node._pfolder; + + folder.write(pos); + + pos.back(); + } else if (node._type == BookmarkNode::BMNT_BOOKMARK) { + const Bookmark& bookmark = *node._pbookmark; + + if (!bookmark._url.empty()) + bookmark.write(pos); + } + } +} + + + /// fill treeview control with bookmark tree content +void BookmarkList::fill_tree(HWND hwnd, HTREEITEM parent, HIMAGELIST himagelist, HDC hdc_wnd) const +{ + TV_INSERTSTRUCT tvi; + + tvi.hParent = parent; + tvi.hInsertAfter = TVI_LAST; + + TV_ITEM& tv = tvi.item; + tv.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; + + for(const_iterator it=begin(); it!=end(); ++it) { + const BookmarkNode& node = *it; + + tv.lParam = (LPARAM)&node; + + if (node._type == BookmarkNode::BMNT_FOLDER) { + const BookmarkFolder& folder = *node._pfolder; + + tv.pszText = (LPTSTR)folder._name.c_str(); + tv.iImage = 3; // folder + tv.iSelectedImage = 4; // open folder + HTREEITEM hitem = TreeView_InsertItem(hwnd, &tvi); + + folder._bookmarks.fill_tree(hwnd, hitem, himagelist, hdc_wnd); + } else if (node._type == BookmarkNode::BMNT_BOOKMARK) { + const Bookmark& bookmark = *node._pbookmark; + + tv.pszText = (LPTSTR)bookmark._name.c_str(); + tv.iImage = 1; // bookmark + tv.iSelectedImage = 2; // selected bookmark + + if (!bookmark._icon_path.empty()) { + const Icon& icon = g_icon_cache.extract(bookmark._icon_path, bookmark._icon_idx); + + if ((ICON_ID)icon != ICID_NONE) + tv.iImage = tv.iSelectedImage = icon.add_to_imagelist(himagelist, hdc_wnd); + } + + TreeView_InsertItem(hwnd, &tvi); + } + } +} + + +/*@@ + + /// import Internet Explorer bookmarks from Favorites folder into bookmark list +void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd) +{ + TCHAR path[MAX_PATH], ext[_MAX_EXT]; + + dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM); + + for(Entry*entry=dir._down; entry; entry=entry->_next) { + if (entry->_shell_attribs & SFGAO_HIDDEN) // ignore files like "desktop.ini" + continue; + + String name; + + if (entry->_etype == ET_SHELL) + name = dir._folder.get_name(static_cast(entry)->_pidl); + else + name = entry->_display_name; + + if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + BookmarkFolder new_folder; + + new_folder._name = DecodeXMLString(name); + + if (entry->_etype == ET_SHELL) { + ShellDirectory new_dir(dir._folder, static_cast(entry)->_pidl, hwnd); + new_folder._bookmarks.import_IE_favorites(new_dir, hwnd); + } else { + entry->get_path(path); + ShellDirectory new_dir(GetDesktopFolder(), path, hwnd); + new_folder._bookmarks.import_IE_favorites(new_dir, hwnd); + } + + push_back(new_folder); + } else { + Bookmark bookmark; + + bookmark._name = DecodeXMLString(name); + + entry->get_path(path); + _tsplitpath(path, NULL, NULL, NULL, ext); + + if (!_tcsicmp(ext, TEXT(".url"))) { + bookmark.read_url(path); + push_back(bookmark); + } else { + ///@todo read shell links + //assert(0); + } + } + } +} + +*/ + + + /// read XBEL bookmark file +bool Favorites::read(LPCTSTR path) +{ + XMLDoc xbel; + + if (!xbel.read(path)) + if (xbel._last_error == XML_ERROR_NO_ELEMENTS) + return false; + else + MessageBox(0/*@@g_Globals._hwndDesktop*/, String(xbel._last_error_msg.c_str()), + TEXT("ROS Explorer - reading bookmark file"), MB_OK); + + const_XMLPos pos(&xbel); + + if (!pos.go_down("xbel")) + return false; + + super::read(pos); + + pos.back(); + + return true; +} + + /// write XBEL bookmark file +void Favorites::write(LPCTSTR path) const +{ + XMLDoc xbel; + + XMLPos pos(&xbel); + pos.create("xbel"); + super::write(pos); + pos.back(); + + xbel.write(path, XMLNode::FORMAT_SMART, XMLHeader("1.0", "UTF-8", "")); +} + + +/*@@ + + /// import Internet Explorer bookmarks from Favorites folder +bool Favorites::import_IE_favorites(HWND hwnd) +{ + WaitCursor wait; + + StartMenuShellDirs dirs; + + try { + dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES, hwnd), hwnd)); + dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES, hwnd), hwnd)); + } catch(COMException&) { + } + + for(StartMenuShellDirs::iterator it=dirs.begin(); it!=dirs.end(); ++it) { + StartMenuDirectory& smd = *it; + ShellDirectory& dir = smd._dir; + + try { + super::import_IE_favorites(dir, hwnd); + } catch(COMException&) { + } + } + + return true; +} + +*/ diff --git a/reactos/subsys/system/ibrowser/favorites.h b/reactos/subsys/system/ibrowser/favorites.h new file mode 100644 index 00000000000..4d139ee0d1d --- /dev/null +++ b/reactos/subsys/system/ibrowser/favorites.h @@ -0,0 +1,104 @@ +/* + * Copyright 2004 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // Explorer and Desktop clone + // + // favorites.h + // + // Martin Fuchs, 04.04.2004 + // + + +extern String DecodeURLString(const char* s); + + +struct Bookmark +{ + Bookmark() : _icon_idx(0) {} + + String _name; + String _description; + String _url; + String _icon_path; + int _icon_idx; + + bool read_url(LPCTSTR path); + bool read(const_XMLPos& pos); + void write(XMLPos& pos) const; +}; + +struct BookmarkFolder; + +struct BookmarkNode +{ + BookmarkNode(); + BookmarkNode(const Bookmark& bm); + BookmarkNode(const BookmarkFolder& bmf); + BookmarkNode(const BookmarkNode& other); + + ~BookmarkNode(); + + BookmarkNode& operator=(const Bookmark& bm); + BookmarkNode& operator=(const BookmarkFolder& bmf); + BookmarkNode& operator=(const BookmarkNode& other); + + void clear(); + + enum BOOKMARKNODE_TYPE { + BMNT_NONE, BMNT_BOOKMARK, BMNT_FOLDER + }; + + BOOKMARKNODE_TYPE _type; + + union { + Bookmark* _pbookmark; + BookmarkFolder* _pfolder; + }; +}; + +struct BookmarkList : public list +{ + void import_IE_favorites(struct ShellDirectory& dir, HWND hwnd); + + void read(const_XMLPos& pos); + void write(XMLPos& pos) const; + + void fill_tree(HWND hwnd, HTREEITEM parent, HIMAGELIST, HDC hdc_wnd) const; +}; + +struct BookmarkFolder +{ + String _name; + String _description; + BookmarkList _bookmarks; + + void read(const_XMLPos& pos); + void write(XMLPos& pos) const; +}; + +struct Favorites : public BookmarkList +{ + typedef BookmarkList super; + + bool read(LPCTSTR path); + void write(LPCTSTR path) const; + + bool import_IE_favorites(HWND hwnd); +}; diff --git a/reactos/subsys/system/ibrowser/ibrowser.cpp b/reactos/subsys/system/ibrowser/ibrowser.cpp new file mode 100644 index 00000000000..a70c3d57c98 --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser.cpp @@ -0,0 +1,520 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // ibrowser.cpp + // + // Martin Fuchs, 24.01.2005 + // + + +#include "precomp.h" + +#include "ibrowser_intres.h" + +#include // for setlocale() + +#ifndef __WINE__ +#include // for dup2() +#include // for _O_RDONLY +#endif + + + // globals + +HINSTANCE g_hInstance; +IconCache g_icon_cache; +ATOM g_hframeClass; + + +/*@@ +void ExplorerGlobals::read_persistent() +{ + // read configuration file + _cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0)); + _cfg_path.printf(TEXT("%s\\ros-ibrowser-cfg.xml"), _cfg_dir.c_str()); + + if (!_cfg.read(_cfg_path)) { + if (_cfg._last_error != XML_ERROR_NO_ELEMENTS) + MessageBox(g_Globals._hwndDesktop, String(_cfg._last_error_msg.c_str()), + TEXT("ROS Explorer - reading user settings"), MB_OK); + + _cfg.read(TEXT("ibrowser-cfg-template.xml")); + } + + // read bookmarks + _favorites_path.printf(TEXT("%s\\ros-ibrowser-bookmarks.xml"), _cfg_dir.c_str()); + + if (!_favorites.read(_favorites_path)) { + _favorites.import_IE_favorites(0); + _favorites.write(_favorites_path); + } +} + +void ExplorerGlobals::write_persistent() +{ + // write configuration file + RecursiveCreateDirectory(_cfg_dir); + + _cfg.write(_cfg_path); + _favorites.write(_favorites_path); +} + + +XMLPos ExplorerGlobals::get_cfg() +{ + XMLPos cfg_pos(&_cfg); + + cfg_pos.smart_create("ibrowser-cfg"); + + return cfg_pos; +} + +XMLPos ExplorerGlobals::get_cfg(const char* path) +{ + XMLPos cfg_pos(&_cfg); + + cfg_pos.smart_create("ibrowser-cfg"); + cfg_pos.create_relative(path); + + return cfg_pos; +} +*/ + + +Icon::Icon() + : _id(ICID_UNKNOWN), + _itype(IT_STATIC), + _hicon(0) +{ +} + +Icon::Icon(ICON_ID id, UINT nid) + : _id(id), + _itype(IT_STATIC), + _hicon(SmallIcon(nid)) +{ +} + +Icon::Icon(ICON_TYPE itype, int id, HICON hIcon) + : _id((ICON_ID)id), + _itype(itype), + _hicon(hIcon) +{ +} + +Icon::Icon(ICON_TYPE itype, int id, int sys_idx) + : _id((ICON_ID)id), + _itype(itype), + _sys_idx(sys_idx) +{ +} + +void Icon::draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const +{ + if (_itype == IT_SYSCACHE) + ImageList_DrawEx(g_icon_cache.get_sys_imagelist(), _sys_idx, hdc, x, y, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL); + else + DrawIconEx(hdc, x, y, _hicon, cx, cy, 0, bk_brush, DI_NORMAL); +} + +HBITMAP Icon::create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const +{ + if (_itype == IT_SYSCACHE) { + HIMAGELIST himl = g_icon_cache.get_sys_imagelist(); + + int cx, cy; + ImageList_GetIconSize(himl, &cx, &cy); + + HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy); + HDC hdc = CreateCompatibleDC(hdc_wnd); + HBITMAP hbmp_old = SelectBitmap(hdc, hbmp); + ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL); + SelectBitmap(hdc, hbmp_old); + DeleteDC(hdc); + + return hbmp; + } else + return create_bitmap_from_icon(_hicon, hbrBkgnd, hdc_wnd); +} + + +int Icon::add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color, HBRUSH bk_brush) const +{ + int ret; + + if (_itype == IT_SYSCACHE) { + HIMAGELIST himl = g_icon_cache.get_sys_imagelist(); + + int cx, cy; + ImageList_GetIconSize(himl, &cx, &cy); + + HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy); + HDC hdc = CreateCompatibleDC(hdc_wnd); + HBITMAP hbmp_old = SelectBitmap(hdc, hbmp); + ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL); + SelectBitmap(hdc, hbmp_old); + DeleteDC(hdc); + + ret = ImageList_Add(himl, hbmp, 0); + + DeleteObject(hbmp); + } else + ret = ImageList_AddAlphaIcon(himl, _hicon, bk_brush, hdc_wnd); + + return ret; +} + +HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd) +{ + int cx = GetSystemMetrics(SM_CXSMICON); + int cy = GetSystemMetrics(SM_CYSMICON); + HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy); + + MemCanvas canvas; + BitmapSelection sel(canvas, hbmp); + + RECT rect = {0, 0, cx, cy}; + FillRect(canvas, &rect, hbrush_bkgnd); + + DrawIconEx(canvas, 0, 0, hIcon, cx, cy, 0, hbrush_bkgnd, DI_NORMAL); + + return hbmp; +} + +int ImageList_AddAlphaIcon(HIMAGELIST himl, HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd) +{ + HBITMAP hbmp = create_bitmap_from_icon(hIcon, hbrush_bkgnd, hdc_wnd); + + int ret = ImageList_Add(himl, hbmp, 0); + + DeleteObject(hbmp); + + return ret; +} + + +int IconCache::s_next_id = ICID_DYNAMIC; + + +void IconCache::init() +{ + _icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, (HICON)0); + + _icons[ICID_IBROWSER] = Icon(ICID_IBROWSER, IDI_IBROWSER); + _icons[ICID_BOOKMARK] = Icon(ICID_BOOKMARK, IDI_DOT_TRANS); +} + + +const Icon& IconCache::extract(const String& path) +{ + PathMap::iterator found = _pathMap.find(path); + + if (found != _pathMap.end()) + return _icons[found->second]; + + SHFILEINFO sfi; + +#if 1 // use system image list + HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON); + + if (himlSys) { + _himlSys = himlSys; + + const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/); +#else + if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) { + const Icon& icon = add(sfi.hIcon, IT_CACHED); +#endif + + ///@todo limit cache size + _pathMap[path] = icon; + + return icon; + } else + return _icons[ICID_NONE]; +} + +const Icon& IconCache::extract(LPCTSTR path, int idx) +{ + CachePair key(path, idx); + +#ifndef __WINE__ ///@todo _tcslwr() for Wine + _tcslwr((LPTSTR)key.first.c_str()); +#endif + + PathIdxMap::iterator found = _pathIdxMap.find(key); + + if (found != _pathIdxMap.end()) + return _icons[found->second]; + + HICON hIcon; + + if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) { + const Icon& icon = add(hIcon, IT_CACHED); + + _pathIdxMap[key] = icon; + + return icon; + } else { + + ///@todo retreive "http://.../favicon.ico" format icons + + return _icons[ICID_NONE]; + } +} + + +const Icon& IconCache::add(HICON hIcon, ICON_TYPE type) +{ + int id = ++s_next_id; + + return _icons[id] = Icon(type, id, hIcon); +} + +const Icon& IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/) +{ + int id = ++s_next_id; + + return _icons[id] = SysCacheIcon(id, sys_idx); +} + +const Icon& IconCache::get_icon(int id) +{ + return _icons[id]; +} + +void IconCache::free_icon(int icon_id) +{ + IconMap::iterator found = _icons.find(icon_id); + + if (found != _icons.end()) { + Icon& icon = found->second; + + if (icon.destroy()) + _icons.erase(found); + } +} + + +ResString::ResString(UINT nid) +{ + TCHAR buffer[BUFFER_LEN]; + + int len = LoadString(g_hInstance, nid, buffer, sizeof(buffer)/sizeof(TCHAR)); + + super::assign(buffer, len); +} + + +ResIcon::ResIcon(UINT nid) +{ + _hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(nid)); +} + +SmallIcon::SmallIcon(UINT nid) +{ + _hicon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); +} + +ResIconEx::ResIconEx(UINT nid, int w, int h) +{ + _hicon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED); +} + + +void SetWindowIcon(HWND hwnd, UINT nid) +{ + HICON hIcon = ResIcon(nid); + Window_SetIcon(hwnd, ICON_BIG, hIcon); + + HICON hIconSmall = SmallIcon(nid); + Window_SetIcon(hwnd, ICON_SMALL, hIconSmall); +} + + +ResBitmap::ResBitmap(UINT nid) +{ + _hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(nid)); +} + + +void ibrowser_show_frame(int cmdshow, LPTSTR lpCmdLine) +{ + MainFrameBase::Create(lpCmdLine, cmdshow); +} + + +PopupMenu::PopupMenu(UINT nid) +{ + HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(nid)); + _hmenu = GetSubMenu(hMenu, 0); +} + + + /// "About" Dialog +struct ExplorerAboutDlg : public + CtlColorParent< + OwnerDrawParent + > +{ + typedef CtlColorParent< + OwnerDrawParent + > super; + + ExplorerAboutDlg(HWND hwnd) + : super(hwnd) + { + SetWindowIcon(hwnd, IDI_REACTOS); + + new FlatButton(hwnd, IDOK); + + _hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif")); + new ColorStatic(hwnd, IDC_ROS_IBROWSER, RGB(32,32,128), 0, _hfont); + + new HyperlinkCtrl(hwnd, IDC_WWW); + + FmtString ver_txt(ResString(IDS_IBROWSER_VERSION_STR), (LPCTSTR)ResString(IDS_VERSION_STR)); + SetWindowText(GetDlgItem(hwnd, IDC_VERSION_TXT), ver_txt); + + /*@@ + HWND hwnd_winver = GetDlgItem(hwnd, IDC_WIN_VERSION); + SetWindowText(hwnd_winver, get_windows_version_str()); + SetWindowFont(hwnd_winver, GetStockFont(DEFAULT_GUI_FONT), FALSE); + */ + + CenterWindow(hwnd); + } + + ~ExplorerAboutDlg() + { + DeleteObject(_hfont); + } + +protected: + HFONT _hfont; +}; + +void ibrowser_about(HWND hwndParent) +{ + Dialog::DoModal(IDD_ABOUT_IBROWSER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent); +} + + +static void InitInstance(HINSTANCE hInstance) +{ + CONTEXT("InitInstance"); + + // register frame window class + g_hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_IBROWSER); + + // register child window class + WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_VREDRAW).Register(); +} + + +int ibrowser_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdshow) +{ + CONTEXT("ibrowser_main"); + + // initialize Common Controls library + CommonControlInit usingCmnCtrl; + + try { + InitInstance(hInstance); + } catch(COMException& e) { + HandleException(e, GetDesktopWindow()); + return -1; + } + + if (cmdshow != SW_HIDE) { +/* // don't maximize if being called from the ROS desktop + if (cmdshow == SW_SHOWNORMAL) + ///@todo read window placement from registry + cmdshow = SW_MAXIMIZE; +*/ + + ibrowser_show_frame(cmdshow, lpCmdLine); + } + + return Window::MessageLoop(); +} + + + // MinGW does not provide a Unicode startup routine, so we have to implement an own. +#if defined(__MINGW32__) && defined(UNICODE) + +#define _tWinMain wWinMain +int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int); + +int main(int argc, char* argv[]) +{ + CONTEXT("main"); + + STARTUPINFO startupinfo; + int nShowCmd = SW_SHOWNORMAL; + + GetStartupInfo(&startupinfo); + + if (startupinfo.dwFlags & STARTF_USESHOWWINDOW) + nShowCmd = startupinfo.wShowWindow; + + LPWSTR cmdline = GetCommandLineW(); + + while(*cmdline && !_istspace(*cmdline)) + ++cmdline; + + while(_istspace(*cmdline)) + ++cmdline; + + return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd); +} + +#endif // __MINGW && UNICODE + + +int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd) +{ + CONTEXT("WinMain()"); + + g_hInstance = hInstance; + + // initialize COM and OLE before creating the desktop window + OleInit usingCOM; + + // init common controls library + CommonControlInit usingCmnCtrl; + +//@@ g_Globals.read_persistent(); + + /**TODO fix command line handling */ + if (*lpCmdLine=='"' && lpCmdLine[_tcslen(lpCmdLine)-1]=='"') { + ++lpCmdLine; + lpCmdLine[_tcslen(lpCmdLine)-1] = '\0'; + } + + int ret = ibrowser_main(hInstance, lpCmdLine, nShowCmd); + + // write configuration file +//@@ g_Globals.write_persistent(); + + return ret; +} diff --git a/reactos/subsys/system/ibrowser/ibrowser.dsp b/reactos/subsys/system/ibrowser/ibrowser.dsp new file mode 100644 index 00000000000..02291f30a2a --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser.dsp @@ -0,0 +1,305 @@ +# Microsoft Developer Studio Project File - Name="ibrowser" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=IBROWSER - WIN32 DEBUG +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ibrowser.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ibrowser.mak" CFG="IBROWSER - WIN32 DEBUG" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ibrowser - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ibrowser - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "ibrowser - Win32 Debug Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ibrowser - Win32 Unicode Release" (based on "Win32 (x86) Console Application") +!MESSAGE "ibrowser - Win32 Unicode Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ibrowser - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O1 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 gdi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ibrowser - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib gdi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ibrowser - Win32 Debug Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "DRelease" +# PROP BASE Intermediate_Dir "DRelease" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "DRelease" +# PROP Intermediate_Dir "DRelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_ROS_" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 gdi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ibrowser - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "URelease" +# PROP BASE Intermediate_Dir "URelease" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "URelease" +# PROP Intermediate_Dir "URelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "NDEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /Yu"precomp.h" /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 gdi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /machine:I386 /libpath:"Release" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "ibrowser - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "UDebug" +# PROP BASE Intermediate_Dir "UDebug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "UDebug" +# PROP Intermediate_Dir "UDebug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "UNICODE" /D "_ROS_" /FR /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "UNICODE" /D "WIN32" /D _WIN32_IE=0x0600 /D _WIN32_WINNT=0x0501 /FR /Yu"precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 user32.lib gdi32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 gdi32.lib comctl32.lib shell32.lib ole32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"Debug" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "ibrowser - Win32 Release" +# Name "ibrowser - Win32 Debug" +# Name "ibrowser - Win32 Debug Release" +# Name "ibrowser - Win32 Unicode Release" +# Name "ibrowser - Win32 Unicode Debug" +# Begin Group "utility" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\utility\comutil.h +# End Source File +# Begin Source File + +SOURCE=.\utility\expat.h +# End Source File +# Begin Source File + +SOURCE=.\utility\utility.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\utility.h +# End Source File +# Begin Source File + +SOURCE=.\utility\window.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\window.h +# End Source File +# Begin Source File + +SOURCE=.\utility\xmlstorage.cpp +# End Source File +# Begin Source File + +SOURCE=.\utility\xmlstorage.h +# End Source File +# End Group +# Begin Group "resources" + +# PROP Default_Filter "bmp,ico" +# Begin Source File + +SOURCE=.\res\dot.ico +# End Source File +# Begin Source File + +SOURCE=.\res\dot_red.ico +# End Source File +# Begin Source File + +SOURCE=.\res\dot_trans.ico +# End Source File +# Begin Source File + +SOURCE=.\res\favorites.ico +# End Source File +# Begin Source File + +SOURCE=.\res\ibrowser.ico +# End Source File +# Begin Source File + +SOURCE=.\ibrowser_intres.h +# End Source File +# Begin Source File + +SOURCE=.\ibrowser_intres.rc +# End Source File +# Begin Source File + +SOURCE=.\res\iexplore.ico +# End Source File +# Begin Source File + +SOURCE=.\res\network.ico +# End Source File +# Begin Source File + +SOURCE=.\res\reactos.ico +# End Source File +# Begin Source File + +SOURCE=.\res\toolbar.bmp +# End Source File +# End Group +# Begin Group "main" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\favorites.cpp +# End Source File +# Begin Source File + +SOURCE=.\favorites.h +# End Source File +# Begin Source File + +SOURCE=.\ibrowser.cpp +# End Source File +# Begin Source File + +SOURCE=.\ibrowser.h +# End Source File +# Begin Source File + +SOURCE=.\mainframe.cpp +# End Source File +# Begin Source File + +SOURCE=.\mainframe.h +# End Source File +# Begin Source File + +SOURCE=.\precomp.cpp +# ADD CPP /Yc"precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\precomp.h +# End Source File +# Begin Source File + +SOURCE=.\webchild.cpp +# End Source File +# Begin Source File + +SOURCE=.\webchild.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\readme.txt +# End Source File +# End Target +# End Project diff --git a/reactos/lib/cpl/desk/desk.dsw b/reactos/subsys/system/ibrowser/ibrowser.dsw similarity index 61% rename from reactos/lib/cpl/desk/desk.dsw rename to reactos/subsys/system/ibrowser/ibrowser.dsw index 6370057e41c..eb8d2593f88 100644 --- a/reactos/lib/cpl/desk/desk.dsw +++ b/reactos/subsys/system/ibrowser/ibrowser.dsw @@ -1,29 +1,41 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "desk"=.\desk.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ibrowser"=.\ibrowser.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "make_ibrowser"=.\make_ibrowser.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/reactos/subsys/system/ibrowser/ibrowser.h b/reactos/subsys/system/ibrowser/ibrowser.h new file mode 100644 index 00000000000..39265f27dbd --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser.h @@ -0,0 +1,216 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // ibrowser.h + // + // Martin Fuchs, 25.01.2005 + // + + +#include "utility/window.h" + + +#define IDW_STATUSBAR 0x100 +#define IDW_TOOLBAR 0x101 +#define IDW_EXTRABAR 0x102 +#define IDW_ADDRESSBAR 0x104 +#define IDW_SIDEBAR 0x106 +#define IDW_FIRST_CHILD 0xC000 /*0x200*/ + + +#define PM_GET_FILEWND_PTR (WM_APP+0x05) +#define PM_GET_SHELLBROWSER_PTR (WM_APP+0x06) + +#define PM_GET_CONTROLWINDOW (WM_APP+0x16) + +#define PM_RESIZE_CHILDREN (WM_APP+0x17) +#define PM_GET_WIDTH (WM_APP+0x18) + +#define PM_REFRESH (WM_APP+0x1B) +#define PM_REFRESH_CONFIG (WM_APP+0x1C) + + +#define CLASSNAME_FRAME TEXT("IBrowserFrameWClass") + +#define CLASSNAME_CHILDWND TEXT("IBrowserChildWClass") + + +#include "mainframe.h" + + + /// convenient loading of string resources +struct ResString : public String +{ + ResString(UINT nid); +}; + + /// convenient loading of standard (32x32) icon resources +struct ResIcon +{ + ResIcon(UINT nid); + + operator HICON() const {return _hicon;} + +protected: + HICON _hicon; +}; + + /// convenient loading of small (16x16) icon resources +struct SmallIcon +{ + SmallIcon(UINT nid); + + operator HICON() const {return _hicon;} + +protected: + HICON _hicon; +}; + + /// convenient loading of icon resources with specified sizes +struct ResIconEx +{ + ResIconEx(UINT nid, int w, int h); + + operator HICON() const {return _hicon;} + +protected: + HICON _hicon; +}; + + /// set big and small icons out of the resources for a window +extern void SetWindowIcon(HWND hwnd, UINT nid); + + /// convenient loading of bitmap resources +struct ResBitmap +{ + ResBitmap(UINT nid); + ~ResBitmap() {DeleteObject(_hBmp);} + + operator HBITMAP() const {return _hBmp;} + +protected: + HBITMAP _hBmp; +}; + + +enum ICON_TYPE { + IT_STATIC, + IT_CACHED, + IT_DYNAMIC, + IT_SYSCACHE +}; + +enum ICON_ID { + ICID_UNKNOWN, + ICID_NONE, + + ICID_IBROWSER, + ICID_BOOKMARK, + + ICID_DYNAMIC +}; + +struct Icon { + Icon(); + Icon(ICON_ID id, UINT nid); + Icon(ICON_TYPE itype, int id, HICON hIcon); + Icon(ICON_TYPE itype, int id, int sys_idx); + + operator ICON_ID() const {return _id;} + + void draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const; + HBITMAP create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const; + int add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color=GetSysColor(COLOR_WINDOW), HBRUSH bk_brush=GetSysColorBrush(COLOR_WINDOW)) const; + + int get_sysiml_idx() const {return _itype==IT_SYSCACHE? _sys_idx: -1;} + + bool destroy() {if (_itype == IT_DYNAMIC) {DestroyIcon(_hicon); return true;} else return false;} + +protected: + ICON_ID _id; + ICON_TYPE _itype; + HICON _hicon; + int _sys_idx; +}; + +struct SysCacheIcon : public Icon { + SysCacheIcon(int id, int sys_idx) + : Icon(IT_SYSCACHE, id, sys_idx) {} +}; + +struct IconCache { + IconCache() : _himlSys(0) {} + + void init(); + + const Icon& extract(const String& path); + const Icon& extract(LPCTSTR path, int idx); + const Icon& extract(IExtractIcon* pExtract, LPCTSTR path, int idx); + + const Icon& add(HICON hIcon, ICON_TYPE type=IT_DYNAMIC); + const Icon& add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/); + + const Icon& get_icon(int icon_id); + HIMAGELIST get_sys_imagelist() const {return _himlSys;} + + void free_icon(int icon_id); + +protected: + static int s_next_id; + + typedef map IconMap; + IconMap _icons; + + typedef map PathMap; + PathMap _pathMap; + + typedef pair CachePair; + typedef map PathIdxMap; + PathIdxMap _pathIdxMap; + + HIMAGELIST _himlSys; +}; + + + /// create a bitmap from an icon +extern HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd); + + /// add icon with alpha channel to imagelist using the specified background color +extern int ImageList_AddAlphaIcon(HIMAGELIST himl, HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd); + + +#include "utility/xmlstorage.h" + +using namespace XMLStorage; + +#include "favorites.h" + + + // globals +extern HINSTANCE g_hInstance; +extern IconCache g_icon_cache; +extern ATOM g_hframeClass; + + + // display explorer "About" dialog +extern void ibrowser_about(HWND hwndParent); + diff --git a/reactos/subsys/system/ibrowser/ibrowser.rc b/reactos/subsys/system/ibrowser/ibrowser.rc new file mode 100644 index 00000000000..6868a248ca4 --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser.rc @@ -0,0 +1,24 @@ +/* $Id: ibrowser.rc 12752 2005-01-03 11:25:40Z mf $ */ + +#include + +#include "ibrowser_intres.rc" + +#define REACTOS_STR_FILE_DESCRIPTION "ROS Internet Web Browser\0" +#define REACTOS_STR_INTERNAL_NAME "ibrowser\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ibrowser.exe\0" +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#define IDS_VERSION_STR 5000 +#define IDS_IBROWSER_VERSION_STR 5001 + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +STRINGTABLE DISCARDABLE +BEGIN + IDS_VERSION_STR REACTOS_STR_PRODUCT_VERSION + IDS_IBROWSER_VERSION_STR "ReactOS %s Web Browser" +END + diff --git a/reactos/subsys/system/ibrowser/ibrowser_intres.h b/reactos/subsys/system/ibrowser/ibrowser_intres.h new file mode 100644 index 00000000000..ec6e1882c44 --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser_intres.h @@ -0,0 +1,51 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ibrowser_intres.rc +// +#define IDS_TITLE 1 +#define IDS_EMPTY 13 +#define IDS_ABOUT_IBROWSER 27 +#define IDI_REACTOS 100 +#define IDB_TOOLBAR 103 +#define IDA_IBROWSER 104 +#define IDM_SDIFRAME 113 +#define IDD_ABOUT_IBROWSER 135 +#define IDI_FAVORITES 140 +#define IDI_DOT 163 +#define IDI_DOT_TRANS 164 +#define IDI_DOT_RED 165 +#define IDI_IBROWSER 169 +#define ID_VIEW_STATUSBAR 503 +#define ID_VIEW_TOOL_BAR 508 +#define ID_VIEW_SIDE_BAR 510 +#define IDC_ROS_IBROWSER 1000 +#define IDC_WWW 1012 +#define IDC_VERSION_TXT 1029 +#define IDC_WIN_VERSION 1030 +#define ID_REFRESH 1704 +#define IDS_VERSION_STR 5000 +#define IDS_IBROWSER_VERSION_STR 5001 +#define ID_IBROWSER_FAQ 10002 +#define ID_VIEW_FULLSCREEN 0x8004 +#define ID_ABOUT_WINDOWS 40002 +#define ID_ABOUT_IBROWSER 40003 +#define ID_GO_BACK 40005 +#define ID_GO_FORWARD 40006 +#define ID_GO_HOME 40007 +#define ID_GO_SEARCH 40008 +#define ID_GO_UP 40009 +#define ID_STOP 40010 +#define ID_FILE_EXIT 0xE141 +#define ID_HELP 0xE146 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 170 +#define _APS_NEXT_COMMAND_VALUE 40024 +#define _APS_NEXT_CONTROL_VALUE 1033 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/reactos/subsys/system/ibrowser/ibrowser_intres.rc b/reactos/subsys/system/ibrowser/ibrowser_intres.rc new file mode 100644 index 00000000000..a1857e6ade3 --- /dev/null +++ b/reactos/subsys/system/ibrowser/ibrowser_intres.rc @@ -0,0 +1,398 @@ +//Microsoft Developer Studio generated resource script. +// +#include "ibrowser_intres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_SDIFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&Fiºier" + BEGIN + MENUITEM "&Ieºire", ID_FILE_EXIT + END + POPUP "&Prezentare" + BEGIN + MENUITEM "&Bara cu instrumente", ID_VIEW_TOOL_BAR + MENUITEM "&Side Bar", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "&Bara de stare", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Resetare\tF5", ID_REFRESH + MENUITEM "F&ull Screen\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + END + POPUP "&Ajutor" + BEGIN + MENUITEM "IBrowser &FAQ...", ID_IBROWSER_FAQ + MENUITEM "&Despre IBrowser...", ID_ABOUT_IBROWSER + MENUITEM "Despre &OS...", ID_ABOUT_WINDOWS + END +END + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_TOOLBAR BITMAP DISCARDABLE "res/toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDA_IBROWSER ACCELERATORS DISCARDABLE +BEGIN + "X", ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT + "S", ID_VIEW_FULLSCREEN, VIRTKEY, SHIFT, CONTROL, + NOINVERT +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_SDIFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&Datei" + BEGIN + MENUITEM "&Beenden", ID_FILE_EXIT + END + POPUP "&Ansicht" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOL_BAR + MENUITEM "S&ide Bar", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "&Status Bar", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Aktualisieren\tF5", ID_REFRESH + MENUITEM "&Vollbild\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + END + POPUP "&Hilfe" + BEGIN + MENUITEM "IBrowser &FAQ...", ID_IBROWSER_FAQ + MENUITEM "&About IBrowser...", ID_ABOUT_IBROWSER + MENUITEM "About &OS...", ID_ABOUT_WINDOWS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT_IBROWSER DIALOG DISCARDABLE 0, 0, 199, 106 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About ReactOS Web Browser" +FONT 10, "MS Sans Serif" +BEGIN + LTEXT "ReactOS Web Browser",IDC_ROS_IBROWSER,91,13,104,11 + LTEXT "V 0.9",IDC_VERSION_TXT,91,27,104,8 + LTEXT "(c) 2005 Martin Fuchs",IDC_STATIC,91,42,104,8 + LTEXT "",IDC_WIN_VERSION,91,58,98,22 + LTEXT "http://www.sky.franken.de/explorer/",IDC_WWW,17,84,129, + 8 + CONTROL "&OK",IDOK,"Button",BS_OWNERDRAW | BS_FLAT | WS_GROUP, + 154,90,38,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUT_IBROWSER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 192 + TOPMARGIN, 7 + BOTTOMMARGIN, 102 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "ibrowser_intres.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include \r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#ifndef _ROS_\r\n" + "LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r\n" + "STRINGTABLE DISCARDABLE \r\n" + "BEGIN\r\n" + "IDS_VERSION_STR """"\r\n" + "#ifdef UNICODE\r\n" + "IDS_IBROWSER_VERSION_STR ""ROS IBrowser%0s""\r\n" + "#else\r\n" + "IDS_IBROWSER_VERSION_STR ""ROS IBrowser Ansi%0s""\r\n" + "#endif\r\n" + "END\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_REACTOS ICON DISCARDABLE "res/reactos.ico" +IDI_FAVORITES ICON DISCARDABLE "res/favorites.ico" +IDI_DOT ICON DISCARDABLE "res/dot.ico" +IDI_DOT_TRANS ICON DISCARDABLE "res/dot_trans.ico" +IDI_DOT_RED ICON DISCARDABLE "res/dot_red.ico" +IDI_IBROWSER ICON DISCARDABLE "res/ibrowser.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TITLE "Reactos Internet Web Browser" + IDS_EMPTY "(Empty)" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ABOUT_IBROWSER "&Über..." +END + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_SDIFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOL_BAR + MENUITEM "S&ide Bar", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "&Status Bar", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Refresh\tF5", ID_REFRESH + MENUITEM "F&ull Screen\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + END + POPUP "&Help" + BEGIN + MENUITEM "IBrowser &FAQ...", ID_IBROWSER_FAQ + MENUITEM "&About IBrowser...", ID_ABOUT_IBROWSER + MENUITEM "About &OS...", ID_ABOUT_WINDOWS + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TITLE "Reactos Internet Web Browser" + IDS_EMPTY "(Empty)" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ABOUT_IBROWSER "&About..." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Castilian) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESP) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_SDIFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&Archivo" + BEGIN + MENUITEM "S&alir", ID_FILE_EXIT + END + POPUP "&Ver" + BEGIN + MENUITEM "&Barra de Herramientas", ID_VIEW_TOOL_BAR + MENUITEM "Barra &Lateral", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "Barra de &Estado", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Actualizar\tF5", ID_REFRESH + MENUITEM "P&antalla Completa\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + END + POPUP "&Ayuda" + BEGIN + MENUITEM "IBrowser &FAQ...", ID_IBROWSER_FAQ + MENUITEM "&Acerca de IBrowser...", ID_ABOUT_IBROWSER + MENUITEM "Acerca de &OS...", ID_ABOUT_WINDOWS + END +END + +#endif // Spanish (Castilian) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// French (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_SDIFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&Fichier" + BEGIN + MENUITEM "&Fermer", ID_FILE_EXIT + END + POPUP "&Affichage" + BEGIN + MENUITEM "Barre d'&outils", ID_VIEW_TOOL_BAR + MENUITEM "&Side Bar", ID_VIEW_SIDE_BAR, GRAYED + MENUITEM "Barre d'&état", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "&Refresh\tF5", ID_REFRESH + MENUITEM "F&ull Screen\tCtrl+Shift+S", ID_VIEW_FULLSCREEN + END + POPUP "A&ide" + BEGIN + MENUITEM "&FAQ Explorateur...", ID_IBROWSER_FAQ + MENUITEM "A propos de l'&explorateur...", ID_ABOUT_WINDOWS + MENUITEM "A propos de l'&OS...", ID_ABOUT_IBROWSER + END +END + +#endif // French (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#ifndef _ROS_ +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +STRINGTABLE DISCARDABLE +BEGIN +IDS_VERSION_STR "" +#ifdef UNICODE +IDS_IBROWSER_VERSION_STR "ROS IBrowser%0s" +#else +IDS_IBROWSER_VERSION_STR "ROS IBrowser Ansi%0s" +#endif +END +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/reactos/subsys/system/ibrowser/mainframe.cpp b/reactos/subsys/system/ibrowser/mainframe.cpp new file mode 100644 index 00000000000..dc1af6b52f7 --- /dev/null +++ b/reactos/subsys/system/ibrowser/mainframe.cpp @@ -0,0 +1,787 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // mainframe.cpp + // + // Martin Fuchs, 25.01.2005 + // + + +#include "precomp.h" + +/* We can't include webchild.h here - otherwise MinGW produces errors like: "multiple definition of `QACONTAINERFLAGS'" +#include "webchild.h" +*/ +extern HWND create_webchildwindow(const WebChildWndInfo& info); + +#include "ibrowser_intres.h" + + +HWND MainFrameBase::Create(LPCTSTR url, UINT cmdshow) +{ + HWND hMainFrame; + + hMainFrame = MainFrame::Create(); + //@@hMainFrame = MainFrame::Create(url); + + if (hMainFrame) { + if (url) { + static String sPath = url; // copy url to avoid accessing freed memory + url = sPath; + } + + ShowWindow(hMainFrame, cmdshow); + UpdateWindow(hMainFrame); + + // Open the first child window after initializing the application + PostMessage(hMainFrame, PM_OPEN_WINDOW, 0, (LPARAM)url); + } + + return hMainFrame; +} + + +MainFrameBase::MainFrameBase(HWND hwnd) + : super(hwnd), + _himl(ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK|ILC_COLOR24, 2, 0)) +{ + _hMenuFrame = GetMenu(hwnd); + _hMenuWindow = GetSubMenu(_hMenuFrame, GetMenuItemCount(_hMenuFrame)-3); + + _menu_info._hMenuView = GetSubMenu(_hMenuFrame, 1); + + _hAccel = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDA_IBROWSER)); + + + TBBUTTON toolbarBtns[] = { +#ifdef _NO_REBAR + {0, 0, 0, BTNS_SEP, {0, 0}, 0, 0}, +#endif + {7, ID_GO_BACK, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {8, ID_GO_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {9, ID_GO_UP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {10, ID_GO_HOME, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {11, ID_GO_SEARCH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {12, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}, + {13, ID_STOP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0} + }; + + _htoolbar = CreateToolbarEx(hwnd, +#ifndef _NO_REBAR + CCS_NOPARENTALIGN|CCS_NORESIZE| +#endif + WS_CHILD|WS_VISIBLE, IDW_TOOLBAR, 2, g_hInstance, IDB_TOOLBAR, + toolbarBtns, sizeof(toolbarBtns)/sizeof(TBBUTTON), + 16, 15, 16, 15, sizeof(TBBUTTON)); + + CheckMenuItem(_menu_info._hMenuView, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED); + + + // address bar + WindowCanvas canvas(hwnd); + RECT rect = {0, 0, 0, 0}; + DrawText(canvas, TEXT("My"), -1, &rect, DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT); + HFONT hfont = GetStockFont(DEFAULT_GUI_FONT); + + _haddressedit = CreateWindow(TEXT("EDIT"), NULL, WS_CHILD|WS_VISIBLE|WS_BORDER, 0, 0, 0, rect.bottom, + hwnd, (HMENU)IDW_ADDRESSBAR, g_hInstance, 0); + SetWindowFont(_haddressedit, hfont, FALSE); + new EditController(_haddressedit); + + /* CreateStatusWindow does not accept WS_BORDER + _hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0, + WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0, + hwnd, (HMENU)IDW_STATUSBAR, g_hInstance, 0);*/ + + _hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, hwnd, IDW_STATUSBAR); + CheckMenuItem(_menu_info._hMenuView, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED); + + _hsidebar = CreateWindowEx(WS_EX_STATICEDGE, WC_TREEVIEW, TEXT("Sidebar"), + WS_CHILD|WS_TABSTOP|WS_BORDER|/*WS_VISIBLE|*/WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_INFOTIP, + -1, -1, 200, 0, _hwnd, (HMENU)IDW_SIDEBAR, g_hInstance, 0); + + TreeView_SetImageList(_hsidebar, _himl, TVSIL_NORMAL); + + CheckMenuItem(_menu_info._hMenuView, ID_VIEW_SIDE_BAR, MF_BYCOMMAND|MF_UNCHECKED/*MF_CHECKED*/); + + + // create rebar window to manage toolbar and address bar +#ifndef _NO_REBAR + _hwndrebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, + WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN| + RBS_VARHEIGHT|RBS_AUTOSIZE|RBS_DBLCLKTOGGLE| + CCS_NODIVIDER|CCS_NOPARENTALIGN, + 0, 0, 0, 0, _hwnd, 0, g_hInstance, 0); + + int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0)); + + REBARBANDINFO rbBand; + + rbBand.cbSize = sizeof(REBARBANDINFO); + rbBand.fMask = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE; +#ifndef RBBS_HIDETITLE // missing in MinGW headers as of 25.02.2004 +#define RBBS_HIDETITLE 0x400 +#endif + rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE; + + rbBand.cxMinChild = 0; + rbBand.cyMinChild = 0; + rbBand.cyChild = 0; + rbBand.cyMaxChild = 0; + rbBand.cyIntegral = btn_hgt; + + rbBand.lpText = TEXT("Toolbar"); + rbBand.hwndChild = _htoolbar; + rbBand.cxMinChild = 0; + rbBand.cyMinChild = btn_hgt + 4; + rbBand.cx = 182; + SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); + + rbBand.lpText = TEXT("Address"); + rbBand.hwndChild = _haddressedit; + rbBand.cxMinChild = 0; + rbBand.cyMinChild = btn_hgt - 2; + rbBand.cx = 284; + SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); +#endif +} + + +MainFrameBase::~MainFrameBase() +{ + ImageList_Destroy(_himl); + +//@@if (g_Globals._hMainWnd == _hwnd) + PostQuitMessage(0); +} + + +LRESULT MainFrameBase::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + LRESULT res; + + if (ProcessMessage(nmsg, wparam, lparam, &res)) + return res; + else + return super::WndProc(nmsg, wparam, lparam); +} + +bool MainFrameBase::ProcessMessage(UINT nmsg, WPARAM wparam, LPARAM lparam, LRESULT* pres) +{ + switch(nmsg) { + case PM_TRANSLATE_MSG: + *pres = TranslateMsg((MSG*)lparam); + return true; + + case WM_SHOWWINDOW: + if (wparam) // trigger child resizing after window creation - now we can succesfully call IsWindowVisible() + resize_frame_client(); + return false; // goto def; + + case WM_CLOSE: + DestroyWindow(_hwnd); +//@@ g_Globals._hMainWnd = 0; + break; + + case WM_DESTROY: + break; + + case WM_SIZE: + resize_frame(LOWORD(lparam), HIWORD(lparam)); + break; // do not pass message to DefFrameProc + + case WM_GETMINMAXINFO: { + LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam; + + lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */ + lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */ + break;} + + case PM_FRM_CALC_CLIENT: + frame_get_clientspace((PRECT)lparam); + *pres = TRUE; + return true; + + case PM_FRM_GET_MENUINFO: + *pres = (LPARAM)&_menu_info; + return true; + + case PM_GET_CONTROLWINDOW: + if (wparam == FCW_STATUS) { + *pres = (LRESULT)(HWND)_hstatusbar; + return true; + } + break; + + case PM_SETSTATUSTEXT: + SendMessage(_hstatusbar, SB_SETTEXT, 0, lparam); + break; + + case PM_URL_CHANGED: + SetWindowText(_haddressedit, (LPCTSTR)lparam); + break; + + default: + return false; + } + + *pres = 0; + return true; +} + +BOOL MainFrameBase::TranslateMsg(MSG* pmsg) +{ + if (TranslateAccelerator(_hwnd, _hAccel, pmsg)) + return TRUE; + + return FALSE; +} + + +int MainFrameBase::Command(int id, int code) +{ + CONTEXT("MainFrameBase::Command()"); + + switch(id) { + case ID_FILE_EXIT: + SendMessage(_hwnd, WM_CLOSE, 0, 0); + break; + + case ID_VIEW_TOOL_BAR: + toggle_child(_hwnd, id, _htoolbar, 0); + break; + + case ID_VIEW_STATUSBAR: + toggle_child(_hwnd, id, _hstatusbar); + break; + + case ID_VIEW_SIDE_BAR: + // lazy initialization + if (!TreeView_GetCount(_hsidebar)) + FillBookmarks(); + + toggle_child(_hwnd, id, _hsidebar); + break; + + case ID_HELP: + WinHelp(_hwnd, TEXT("ibrowser")/*file ibrowser.hlp*/, HELP_INDEX, 0); + break; + + case ID_VIEW_FULLSCREEN: + CheckMenuItem(_menu_info._hMenuView, id, toggle_fullscreen()?MF_CHECKED:0); + break; + + case ID_ABOUT_WINDOWS: + ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0); + break; + + case ID_ABOUT_IBROWSER: + ibrowser_about(_hwnd); + break; + + case ID_IBROWSER_FAQ: + launch_file(_hwnd, TEXT("http://www.sky.franken.de/explorer/"), SW_SHOW); + break; + + case IDW_ADDRESSBAR: + if (code == 1) { + TCHAR url[BUFFER_LEN]; + + if (GetWindowText(_haddressedit, url, BUFFER_LEN)) + go_to(url, false); + } + break; + + default: + return 1; // no command handlers in Window::Command() + } + + return 0; +} + + +int MainFrameBase::Notify(int id, NMHDR* pnmh) +{ + switch(pnmh->code) { + // resize children windows when the rebar size changes + case RBN_AUTOSIZE: + resize_frame_client(); + break; + + case TVN_GETINFOTIP: { + NMTVGETINFOTIP* pnmgit = (NMTVGETINFOTIP*)pnmh; + + if (pnmgit->lParam) { + const BookmarkNode& node = *(BookmarkNode*)pnmgit->lParam; + + if (node._type == BookmarkNode::BMNT_FOLDER) { + // display tooltips for bookmark folders + if (!node._pfolder->_description.empty()) + lstrcpyn(pnmgit->pszText, node._pfolder->_description.c_str(), pnmgit->cchTextMax); + } else if (node._type == BookmarkNode::BMNT_BOOKMARK) { + // display tooltips for bookmark folders + String txt = node._pbookmark->_description; + + if (!node._pbookmark->_url.empty()) { + if (!txt.empty()) + txt += TEXT(" - "); + + txt += node._pbookmark->_url; + } + + lstrcpyn(pnmgit->pszText, txt.c_str(), pnmgit->cchTextMax); + } + } + break;} + + case NM_DBLCLK: { + HTREEITEM hitem = TreeView_GetSelection(_hsidebar); + LPARAM lparam = TreeView_GetItemData(_hsidebar, hitem); + + if (lparam) { + const BookmarkNode& node = *(BookmarkNode*)lparam; + + if (node._type == BookmarkNode::BMNT_BOOKMARK) { + bool new_window = GetAsyncKeyState(VK_SHIFT)<0; + + go_to(node._pbookmark->_url, new_window); + } + } + break;} + } + + return 0; +} + + +void MainFrameBase::resize_frame(int cx, int cy) +{ + if (cy <= 0) + return; // avoid resizing children when receiving RBN_AUTOSIZE while getting minimized + + RECT rect = {0, 0, cx, cy}; + + if (_hwndrebar) { + int height = ClientRect(_hwndrebar).bottom; + MoveWindow(_hwndrebar, rect.left, rect.top, rect.right-rect.left, height, TRUE); + rect.top += height; + } else { + if (IsWindowVisible(_htoolbar)) { + SendMessage(_htoolbar, WM_SIZE, 0, 0); + WindowRect rt(_htoolbar); + rect.top = rt.bottom; + // rect.bottom -= rt.bottom; + } + } + + if (IsWindowVisible(_hstatusbar)) { + int parts[] = {300, 500}; + + SendMessage(_hstatusbar, WM_SIZE, 0, 0); + SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts); + ClientRect rt(_hstatusbar); + rect.bottom -= rt.bottom; + } + + if (IsWindowVisible(_hsidebar)) { + WindowRect rt(_hsidebar); + rect.left += rt.right-rt.left; + + SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER); + } +} + +void MainFrameBase::resize_frame_client() +{ + ClientRect rect(_hwnd); + + resize_frame(rect.right, rect.bottom); +} + +void MainFrameBase::frame_get_clientspace(PRECT prect) +{ + if (!IsIconic(_hwnd)) + GetClientRect(_hwnd, prect); + else { + WINDOWPLACEMENT wp; + + GetWindowPlacement(_hwnd, &wp); + + prect->left = prect->top = 0; + prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left- + 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE)); + prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top- + 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))- + GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE); + } + + if (IsWindowVisible(_htoolbar)) { + ClientRect rt(_htoolbar); + prect->top += rt.bottom+2; + } + + if (IsWindowVisible(_hstatusbar)) { + ClientRect rt(_hstatusbar); + prect->bottom -= rt.bottom; + } +} + +BOOL MainFrameBase::toggle_fullscreen() +{ + RECT rt; + + if ((_fullscreen._mode=!_fullscreen._mode)) { + GetWindowRect(_hwnd, &_fullscreen._orgPos); + _fullscreen._wasZoomed = IsZoomed(_hwnd); + + Frame_CalcFrameClient(_hwnd, &rt); + ClientToScreen(_hwnd, (LPPOINT)&rt.left); + ClientToScreen(_hwnd, (LPPOINT)&rt.right); + + rt.left = _fullscreen._orgPos.left-rt.left; + rt.top = _fullscreen._orgPos.top-rt.top; + rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right; + rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom; + + MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); + } else { + MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top, + _fullscreen._orgPos.right-_fullscreen._orgPos.left, + _fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE); + + if (_fullscreen._wasZoomed) + ShowWindow(_hwnd, WS_MAXIMIZE); + } + + return _fullscreen._mode; +} + +void MainFrameBase::fullscreen_move() +{ + RECT rt, pos; + GetWindowRect(_hwnd, &pos); + + Frame_CalcFrameClient(_hwnd, &rt); + ClientToScreen(_hwnd, (LPPOINT)&rt.left); + ClientToScreen(_hwnd, (LPPOINT)&rt.right); + + rt.left = pos.left-rt.left; + rt.top = pos.top-rt.top; + rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right; + rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom; + + MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); +} + + +void MainFrameBase::toggle_child(HWND hwnd, UINT cmd, HWND hchild, int band_idx) +{ + BOOL vis = IsWindowVisible(hchild); + + CheckMenuItem(_menu_info._hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED); + + if (band_idx != -1) + SendMessage(_hwndrebar, RB_SHOWBAND, band_idx, !vis); + else + ShowWindow(hchild, vis? SW_HIDE: SW_SHOW); + + if (_fullscreen._mode) + fullscreen_move(); + + resize_frame_client(); +} + +void MainFrameBase::FillBookmarks() +{ +/*@@ + HiddenWindow hide(_hsidebar); + WindowCanvas canvas(_hwnd); + + TreeView_DeleteAllItems(_hsidebar); + + g_icon_cache.get_icon(ICID_FAVORITES).add_to_imagelist(_himl, canvas); + g_icon_cache.get_icon(ICID_BOOKMARK).add_to_imagelist(_himl, canvas); + ImageList_AddAlphaIcon(_himl, SmallIcon(IDI_DOT), GetStockBrush(WHITE_BRUSH), canvas); + g_icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas); + g_icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas); + + TV_INSERTSTRUCT tvi; + + tvi.hParent = TVI_ROOT; + tvi.hInsertAfter = TVI_LAST; + tvi.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE; + ResString sFavorites(IDS_FAVORITES); + tvi.item.pszText = (LPTSTR)sFavorites.c_str(); + tvi.item.iSelectedImage = tvi.item.iImage = 0; + + HTREEITEM hitem_bookmarks = TreeView_InsertItem(_hsidebar, &tvi); + + g_Globals._favorites.fill_tree(_hsidebar, hitem_bookmarks, _himl, canvas); + + TreeView_Expand(_hsidebar, hitem_bookmarks, TVE_EXPAND); +*/ +} + + +MainFrame::MainFrame(HWND hwnd) + : super(hwnd) +{ + _split_pos = DEFAULT_SPLIT_POS; + _last_split = DEFAULT_SPLIT_POS; +} + +HWND MainFrame::Create() +{ + HMENU hMenuFrame = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_SDIFRAME)); + + return Window::Create(WINDOW_CREATOR(MainFrame), 0, + (LPCTSTR)(int)g_hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + 0/*hwndDesktop*/, hMenuFrame); +} + +/*@@ +HWND MainFrame::Create(LPCTSTR url) +{ + HWND hFrame = Create(); + if (!hFrame) + return 0; + + ShowWindow(hFrame, SW_SHOW); + + MainFrame* pFrame = GET_WINDOW(MainFrame, hFrame); + + if (pFrame) + pFrame->set_url(url); + + return hFrame; +} +*/ + +LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + switch(nmsg) { + case WM_SIZE: + resize_frame(LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_PAINT: { + PaintCanvas canvas(_hwnd); + + if (_left_hwnd && _right_hwnd) { + ClientRect rt(_hwnd); + rt.left = _split_pos-SPLIT_WIDTH/2; + rt.right = _split_pos+SPLIT_WIDTH/2+1; + + if (_right_hwnd) { + WindowRect right_rect(_right_hwnd); + ScreenToClient(_hwnd, &right_rect); + rt.top = right_rect.top; + rt.bottom = right_rect.bottom; + } + + HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR)); + Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1); + SelectObject(canvas, lastBrush); + } + break;} + + case WM_SETCURSOR: + if (LOWORD(lparam) == HTCLIENT) { + POINT pt; + GetCursorPos(&pt); + ScreenToClient(_hwnd, &pt); + + if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) { + SetCursor(LoadCursor(0, IDC_SIZEWE)); + return TRUE; + } + } + goto def; + + case WM_LBUTTONDOWN: { + int x = GET_X_LPARAM(lparam); + + ClientRect rt(_hwnd); + + if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) { + _last_split = _split_pos; + SetCapture(_hwnd); + } + + break;} + + case WM_LBUTTONUP: + if (GetCapture() == _hwnd) + ReleaseCapture(); + break; + + case WM_KEYDOWN: + if (wparam == VK_ESCAPE) + if (GetCapture() == _hwnd) { + _split_pos = _last_split; + resize_children(); + _last_split = -1; + ReleaseCapture(); + SetCursor(LoadCursor(0, IDC_ARROW)); + } + break; + + case WM_MOUSEMOVE: + if (GetCapture() == _hwnd) { + int x = LOWORD(lparam); + + ClientRect rt(_hwnd); + + if (x>=0 && x +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=make_ibrowser - Win32 bjam +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "make_ibrowser.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "make_ibrowser.mak" CFG="make_ibrowser - Win32 bjam" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "make_ibrowser - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "make_ibrowser - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE "make_ibrowser - Win32 Unicode Debug" (based on "Win32 (x86) External Target") +!MESSAGE "make_ibrowser - Win32 Unicode Release" (based on "Win32 (x86) External Target") +!MESSAGE "make_ibrowser - Win32 bjam" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "make_ibrowser - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f make_ibrowser.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "make_ibrowser.exe" +# PROP BASE Bsc_Name "make_ibrowser.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "ibrowser.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f make_ibrowser.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "make_ibrowser.exe" +# PROP BASE Bsc_Name "make_ibrowser.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.PCH UNICODE=0 DEBUG=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "ibrowser.exe" +# PROP Bsc_Name "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=0 DEBUG=1" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Unicode Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "UDebug" +# PROP BASE Intermediate_Dir "UDebug" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "ibrowser.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "UDebug" +# PROP Intermediate_Dir "UDebug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "ibrowser.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Unicode Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "URelease" +# PROP BASE Intermediate_Dir "URelease" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "ibrowser.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "URelease" +# PROP Intermediate_Dir "URelease" +# PROP Cmd_Line "msdevfilt -gcc make -f Makefile.PCH UNICODE=1" +# PROP Rebuild_Opt "clean all" +# PROP Target_File "ibrowser.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 bjam" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW DEBUG=1" +# PROP BASE Rebuild_Opt "clean all" +# PROP BASE Target_File "ibrowser.exe" +# PROP BASE Bsc_Name "" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" bjam" +# PROP Rebuild_Opt "clean&bjam release" +# PROP Target_File "ibrowser.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "make_ibrowser - Win32 Release" +# Name "make_ibrowser - Win32 Debug" +# Name "make_ibrowser - Win32 Unicode Debug" +# Name "make_ibrowser - Win32 Unicode Release" +# Name "make_ibrowser - Win32 bjam" + +!IF "$(CFG)" == "make_ibrowser - Win32 Release" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Debug" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Unicode Debug" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 Unicode Release" + +!ELSEIF "$(CFG)" == "make_ibrowser - Win32 bjam" + +!ENDIF + +# Begin Source File + +SOURCE=.\Jamfile +# End Source File +# Begin Source File + +SOURCE=.\Makefile +# End Source File +# Begin Source File + +SOURCE=.\Makefile.MinGW +# End Source File +# Begin Source File + +SOURCE=.\Makefile.PCH +# End Source File +# End Target +# End Project diff --git a/reactos/lib/crtdll/stdio/fgetchar.c b/reactos/subsys/system/ibrowser/precomp.cpp similarity index 72% rename from reactos/lib/crtdll/stdio/fgetchar.c rename to reactos/subsys/system/ibrowser/precomp.cpp index ccf9253a745..c786813cbda 100644 --- a/reactos/lib/crtdll/stdio/fgetchar.c +++ b/reactos/subsys/system/ibrowser/precomp.cpp @@ -1,10 +1,5 @@ -/* $Id$ - * - * ReactOS msvcrt library - * - * fgetchar.c - * - * Copyright (C) 2002 Robert Dickenson +/* + * Copyright 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,18 +16,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -int _fgetchar (void) -{ - return _getch(); -} + // + // ROS Internet Web Browser - precompiled header support + // + // precomp.h + // + // Martin Fuchs, 25.01.2005 + // -/* - * @implemented - */ -int _fgetwchar (void) -{ - return _getch(); -} +#include "precomp.h" diff --git a/reactos/subsys/system/ibrowser/precomp.h b/reactos/subsys/system/ibrowser/precomp.h new file mode 100644 index 00000000000..c0d382d9681 --- /dev/null +++ b/reactos/subsys/system/ibrowser/precomp.h @@ -0,0 +1,32 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser - precompiled header support + // + // precomp.h + // + // Martin Fuchs, 25.01.2005 + // + +#include "utility/utility.h" +#include "utility/comutil.h" + +#include "ibrowser.h" + diff --git a/reactos/subsys/system/ibrowser/readme.txt b/reactos/subsys/system/ibrowser/readme.txt new file mode 100644 index 00000000000..234c112c97e --- /dev/null +++ b/reactos/subsys/system/ibrowser/readme.txt @@ -0,0 +1,9 @@ + +IBrowser is a Web Browser User Interface similar derived from ROS Explorer. +It encapsulates the Mozilla or MS Web Browser Control. + + +For more information about ReactOS Explorer please look at the FAQ web page: + +http://www.sky.franken.de/explorer/ + diff --git a/reactos/subsys/system/ibrowser/res/dot.ico b/reactos/subsys/system/ibrowser/res/dot.ico new file mode 100644 index 00000000000..9ddbb8a41c7 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/dot.ico differ diff --git a/reactos/subsys/system/ibrowser/res/dot_red.ico b/reactos/subsys/system/ibrowser/res/dot_red.ico new file mode 100644 index 00000000000..4d176eef1d5 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/dot_red.ico differ diff --git a/reactos/subsys/system/ibrowser/res/dot_trans.ico b/reactos/subsys/system/ibrowser/res/dot_trans.ico new file mode 100644 index 00000000000..d5ede5a3800 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/dot_trans.ico differ diff --git a/reactos/subsys/system/ibrowser/res/favorites.ico b/reactos/subsys/system/ibrowser/res/favorites.ico new file mode 100644 index 00000000000..558748e9ed0 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/favorites.ico differ diff --git a/reactos/subsys/system/ibrowser/res/ibrowser.ico b/reactos/subsys/system/ibrowser/res/ibrowser.ico new file mode 100644 index 00000000000..700ca0da4b1 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/ibrowser.ico differ diff --git a/reactos/subsys/system/ibrowser/res/network.ico b/reactos/subsys/system/ibrowser/res/network.ico new file mode 100644 index 00000000000..5bcf5ec7cbf Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/network.ico differ diff --git a/reactos/subsys/system/ibrowser/res/reactos.ico b/reactos/subsys/system/ibrowser/res/reactos.ico new file mode 100644 index 00000000000..492e388a939 Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/reactos.ico differ diff --git a/reactos/subsys/system/ibrowser/res/toolbar.bmp b/reactos/subsys/system/ibrowser/res/toolbar.bmp new file mode 100644 index 00000000000..7e88726f33b Binary files /dev/null and b/reactos/subsys/system/ibrowser/res/toolbar.bmp differ diff --git a/reactos/subsys/system/ibrowser/utility/comutil.h b/reactos/subsys/system/ibrowser/utility/comutil.h new file mode 100644 index 00000000000..d73b7b42327 --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/comutil.h @@ -0,0 +1,321 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // comutil.h + // + // C++ wrapper classes for COM interfaces + // + // Martin Fuchs, 25.01.2005 + // + + + // windows shell headers +#include +#include + +/*@@ +#if _MSC_VER>=1300 // VS.Net +#include +using namespace _com_util; +#endif +*/ + +#ifndef _INC_COMUTIL // is comutil.h of MS headers not available? +#ifndef _NO_COMUTIL +#define _NO_COMUTIL +#endif +#endif + + + // Exception Handling + +#ifndef _NO_COMUTIL + +#define COMExceptionBase _com_error + +#else + + /// COM ExceptionBase class as replacement for _com_error +struct COMExceptionBase +{ + COMExceptionBase(HRESULT hr) + : _hr(hr) + { + } + + HRESULT Error() const + { + return _hr; + } + + LPCTSTR ErrorMessage() const + { + if (_msg.empty()) { + LPTSTR pBuf; + + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + 0, _hr, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&pBuf, 0, NULL)) { + _msg = pBuf; + LocalFree(pBuf); + } else { + TCHAR buffer[128]; + _stprintf(buffer, TEXT("unknown Exception: 0x%08lX"), _hr); + _msg = buffer; + } + } + + return _msg; + } + +protected: + HRESULT _hr; + mutable String _msg; +}; + +#endif + + + /// Exception with context information + +struct COMException : public COMExceptionBase +{ + typedef COMExceptionBase super; + + COMException(HRESULT hr) + : super(hr), + _context(CURRENT_CONTEXT), + _file(NULL), _line(0) + { + LOG(toString()); + LOG(CURRENT_CONTEXT.getStackTrace()); + } + + COMException(HRESULT hr, const char* file, int line) + : super(hr), + _context(CURRENT_CONTEXT), + _file(file), _line(line) + { + LOG(toString()); + LOG(CURRENT_CONTEXT.getStackTrace()); + } + + COMException(HRESULT hr, const String& obj) + : super(hr), + _context(CURRENT_CONTEXT), + _file(NULL), _line(0) + { + LOG(toString()); + LOG(CURRENT_CONTEXT.getStackTrace()); + } + + COMException(HRESULT hr, const String& obj, const char* file, int line) + : super(hr), + _context(CURRENT_CONTEXT), + _file(file), _line(line) + { + LOG(toString()); + LOG(CURRENT_CONTEXT.getStackTrace()); + } + + String toString() const; + + Context _context; + + const char* _file; + int _line; +}; + +#define THROW_EXCEPTION(hr) throw COMException(hr, __FILE__, __LINE__) +#define CHECKERROR(hr) ((void)(FAILED(hr)? THROW_EXCEPTION(hr): 0)) + + +#ifdef _NO_COMUTIL + +inline void CheckError(HRESULT hr) +{ + if (FAILED(hr)) + throw COMException(hr); +} + +#endif + + + /// COM Initialisation + +struct ComInit +{ + ComInit() + { + CHECKERROR(CoInitialize(0)); + } + +#if (_WIN32_WINNT>=0x0400) || defined(_WIN32_DCOM) + ComInit(DWORD flag) + { + CHECKERROR(CoInitializeEx(0, flag)); + } +#endif + + ~ComInit() + { + CoUninitialize(); + } +}; + + + /// OLE initialisation for drag drop support + +struct OleInit +{ + OleInit() + { + CHECKERROR(OleInitialize(0)); + } + + ~OleInit() + { + OleUninitialize(); + } +}; + + + /// Exception Handler for COM exceptions + +extern void HandleException(COMException& e, HWND hwnd); + + + /// wrapper class for COM interface pointers + +template struct SIfacePtr +{ + SIfacePtr() + : _p(0) + { + } + + SIfacePtr(T* p) + : _p(p) + { + if (p) + p->AddRef(); + } + + SIfacePtr(IUnknown* unknown, REFIID riid) + { + CHECKERROR(unknown->QueryInterface(riid, (LPVOID*)&_p)); + } + + ~SIfacePtr() + { + Free(); + } + + T* operator->() + { + return _p; + } + + const T* operator->() const + { + return _p; + } + +/* not GCC compatible + operator const T*() const + { + return _p; + } */ + + operator T*() + { + return _p; + } + + T** operator&() + { + return &_p; + } + + bool empty() const //NOTE: GCC seems not to work correctly when defining operator bool() AND operator T*() at one time + { + return !_p; + } + + SIfacePtr& operator=(T* p) + { + Free(); + + if (p) { + p->AddRef(); + _p = p; + } + + return *this; + } + + void operator=(SIfacePtr const& o) + { + T* h = _p; + + if (o._p) + o._p->AddRef(); + + _p = o._p; + + if (h) + h->Release(); + } + + HRESULT CreateInstance(REFIID clsid, REFIID riid) + { + return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&_p); + } + + template HRESULT QueryInterface(REFIID riid, I* p) + { + return _p->QueryInterface(riid, (LPVOID*)p); + } + + T* get() + { + return _p; + } + + void Free() + { + T* h = _p; + _p = NULL; + + if (h) + h->Release(); + } + +protected: + SIfacePtr(const SIfacePtr& o) + : _p(o._p) + { + if (_p) + _p->AddRef(); + } + + T* _p; +}; diff --git a/reactos/subsys/system/ibrowser/utility/expat.h b/reactos/subsys/system/ibrowser/utility/expat.h new file mode 100644 index 00000000000..b34f94ea8dd --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/expat.h @@ -0,0 +1,1081 @@ +/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#ifndef XmlParse_INCLUDED +#define XmlParse_INCLUDED 1 + +#ifdef __VMS +/* 0 1 2 3 0 1 2 3 + 1234567890123456789012345678901 1234567890123456789012345678901 */ +#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler +#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler +#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler +#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg +#endif + +#include + +#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) +#define XML_USE_MSC_EXTENSIONS 1 +#endif + +/* Expat tries very hard to make the API boundary very specifically + defined. There are two macros defined to control this boundary; + each of these can be defined before including this header to + achieve some different behavior, but doing so it not recommended or + tested frequently. + + XMLCALL - The calling convention to use for all calls across the + "library boundary." This will default to cdecl, and + try really hard to tell the compiler that's what we + want. + + XMLIMPORT - Whatever magic is needed to note that a function is + to be imported from a dynamically loaded library + (.dll, .so, or .sl, depending on your platform). + + The XMLCALL macro was added in Expat 1.95.7. The only one which is + expected to be directly useful in client code is XMLCALL. + + Note that on at least some Unix versions, the Expat library must be + compiled with the cdecl calling convention as the default since + system headers may assume the cdecl convention. +*/ +#ifndef XMLCALL +#if defined(XML_USE_MSC_EXTENSIONS) +#define XMLCALL __cdecl +#elif defined(__GNUC__) && defined(__i386) +//MF#define XMLCALL __attribute__((cdecl)) +#define XMLCALL//MF +#else +/* For any platform which uses this definition and supports more than + one calling convention, we need to extend this definition to + declare the convention used on that platform, if it's possible to + do so. + + If this is the case for your platform, please file a bug report + with information on how to identify your platform via the C + pre-processor and how to specify the same calling convention as the + platform's malloc() implementation. +*/ +#define XMLCALL +#endif +#endif /* not defined XMLCALL */ + + +#if !defined(XML_STATIC) && !defined(XMLIMPORT) +#ifndef XML_BUILDING_EXPAT +/* using Expat from an application */ + +#ifdef XML_USE_MSC_EXTENSIONS +#define XMLIMPORT __declspec(dllimport) +#endif + +#endif +#endif /* not defined XML_STATIC */ + +/* If we didn't define it above, define it away: */ +#ifndef XMLIMPORT +#define XMLIMPORT +#endif + + +#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef XML_UNICODE_WCHAR_T +#define XML_UNICODE +#endif + +struct XML_ParserStruct; +typedef struct XML_ParserStruct *XML_Parser; + +#ifdef XML_UNICODE /* Information is UTF-16 encoded. */ +#ifdef XML_UNICODE_WCHAR_T +typedef wchar_t XML_Char; +typedef wchar_t XML_LChar; +#else +typedef unsigned short XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE_WCHAR_T */ +#else /* Information is UTF-8 encoded. */ +typedef char XML_Char; +typedef char XML_LChar; +#endif /* XML_UNICODE */ + +/* Should this be defined using stdbool.h when C99 is available? */ +typedef unsigned char XML_Bool; +#define XML_TRUE ((XML_Bool) 1) +#define XML_FALSE ((XML_Bool) 0) + +/* The XML_Status enum gives the possible return values for several + API functions. The preprocessor #defines are included so this + stanza can be added to code that still needs to support older + versions of Expat 1.95.x: + + #ifndef XML_STATUS_OK + #define XML_STATUS_OK 1 + #define XML_STATUS_ERROR 0 + #endif + + Otherwise, the #define hackery is quite ugly and would have been + dropped. +*/ +enum XML_Status { + XML_STATUS_ERROR = 0, +#define XML_STATUS_ERROR XML_STATUS_ERROR + XML_STATUS_OK = 1, +#define XML_STATUS_OK XML_STATUS_OK + XML_STATUS_SUSPENDED = 2, +#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED +}; + +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE, + XML_ERROR_UNEXPECTED_STATE, + XML_ERROR_ENTITY_DECLARED_IN_PE, + XML_ERROR_FEATURE_REQUIRES_XML_DTD, + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, + XML_ERROR_UNBOUND_PREFIX, + XML_ERROR_SUSPENDED, + XML_ERROR_NOT_SUSPENDED, + XML_ERROR_ABORTED, + XML_ERROR_FINISHED, + XML_ERROR_SUSPEND_PE +}; + +enum XML_Content_Type { + XML_CTYPE_EMPTY = 1, + XML_CTYPE_ANY, + XML_CTYPE_MIXED, + XML_CTYPE_NAME, + XML_CTYPE_CHOICE, + XML_CTYPE_SEQ +}; + +enum XML_Content_Quant { + XML_CQUANT_NONE, + XML_CQUANT_OPT, + XML_CQUANT_REP, + XML_CQUANT_PLUS +}; + +/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be + XML_CQUANT_NONE, and the other fields will be zero or NULL. + If type == XML_CTYPE_MIXED, then quant will be NONE or REP and + numchildren will contain number of elements that may be mixed in + and children point to an array of XML_Content cells that will be + all of XML_CTYPE_NAME type with no quantification. + + If type == XML_CTYPE_NAME, then the name points to the name, and + the numchildren field will be zero and children will be NULL. The + quant fields indicates any quantifiers placed on the name. + + CHOICE and SEQ will have name NULL, the number of children in + numchildren and children will point, recursively, to an array + of XML_Content cells. + + The EMPTY, ANY, and MIXED types will only occur at top level. +*/ + +typedef struct XML_cp XML_Content; + +struct XML_cp { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + XML_Char * name; + unsigned int numchildren; + XML_Content * children; +}; + + +/* This is called for an element declaration. See above for + description of the model argument. It's the caller's responsibility + to free model when finished with it. +*/ +typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData, + const XML_Char *name, + XML_Content *model); + +XMLPARSEAPI(void) +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl); + +/* The Attlist declaration handler is called for *each* attribute. So + a single Attlist declaration with multiple attributes declared will + generate multiple calls to this handler. The "default" parameter + may be NULL in the case of the "#IMPLIED" or "#REQUIRED" + keyword. The "isrequired" parameter will be true and the default + value will be NULL in the case of "#REQUIRED". If "isrequired" is + true and default is non-NULL, then this is a "#FIXED" default. +*/ +typedef void (XMLCALL *XML_AttlistDeclHandler) ( + void *userData, + const XML_Char *elname, + const XML_Char *attname, + const XML_Char *att_type, + const XML_Char *dflt, + int isrequired); + +XMLPARSEAPI(void) +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl); + +/* The XML declaration handler is called for *both* XML declarations + and text declarations. The way to distinguish is that the version + parameter will be NULL for text declarations. The encoding + parameter may be NULL for XML declarations. The standalone + parameter will be -1, 0, or 1 indicating respectively that there + was no standalone parameter in the declaration, that it was given + as no, or that it was given as yes. +*/ +typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData, + const XML_Char *version, + const XML_Char *encoding, + int standalone); + +XMLPARSEAPI(void) +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler xmldecl); + + +typedef struct { + void *(XMLCALL *malloc_fcn)(size_t size); + void *(XMLCALL *realloc_fcn)(void *ptr, size_t size); + void (XMLCALL *free_fcn)(void *ptr); +} XML_Memory_Handling_Suite; + +/* Constructs a new parser; encoding is the encoding specified by the + external protocol or NULL if there is none specified. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate(const XML_Char *encoding); + +/* Constructs a new parser and namespace processor. Element type + names and attribute names that belong to a namespace will be + expanded; unprefixed attribute names are never expanded; unprefixed + element type names are expanded only if there is a default + namespace. The expanded name is the concatenation of the namespace + URI, the namespace separator character, and the local part of the + name. If the namespace separator is '\0' then the namespace URI + and the local part will be concatenated without any separator. + When a namespace is not declared, the name and prefix will be + passed through without expansion. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); + + +/* Constructs a new parser using the memory management suite referred to + by memsuite. If memsuite is NULL, then use the standard library memory + suite. If namespaceSeparator is non-NULL it creates a parser with + namespace processing as described above. The character pointed at + will serve as the namespace separator. + + All further memory operations used for the created parser will come from + the given suite. +*/ +XMLPARSEAPI(XML_Parser) +XML_ParserCreate_MM(const XML_Char *encoding, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *namespaceSeparator); + +/* Prepare a parser object to be re-used. This is particularly + valuable when memory allocation overhead is disproportionatly high, + such as when a large number of small documnents need to be parsed. + All handlers are cleared from the parser, except for the + unknownEncodingHandler. The parser's external state is re-initialized + except for the values of ns and ns_triplets. + + Added in Expat 1.95.3. +*/ +XMLPARSEAPI(XML_Bool) +XML_ParserReset(XML_Parser parser, const XML_Char *encoding); + +/* atts is array of name/value pairs, terminated by 0; + names and values are 0 terminated. +*/ +typedef void (XMLCALL *XML_StartElementHandler) (void *userData, + const XML_Char *name, + const XML_Char **atts); + +typedef void (XMLCALL *XML_EndElementHandler) (void *userData, + const XML_Char *name); + + +/* s is not 0 terminated. */ +typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData, + const XML_Char *s, + int len); + +/* target and data are 0 terminated */ +typedef void (XMLCALL *XML_ProcessingInstructionHandler) ( + void *userData, + const XML_Char *target, + const XML_Char *data); + +/* data is 0 terminated */ +typedef void (XMLCALL *XML_CommentHandler) (void *userData, + const XML_Char *data); + +typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData); +typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData); + +/* This is called for any characters in the XML document for which + there is no applicable handler. This includes both characters that + are part of markup which is of a kind that is not reported + (comments, markup declarations), or characters that are part of a + construct which could be reported but for which no handler has been + supplied. The characters are passed exactly as they were in the XML + document except that they will be encoded in UTF-8 or UTF-16. + Line boundaries are not normalized. Note that a byte order mark + character is not passed to the default handler. There are no + guarantees about how characters are divided between calls to the + default handler: for example, a comment might be split between + multiple calls. +*/ +typedef void (XMLCALL *XML_DefaultHandler) (void *userData, + const XML_Char *s, + int len); + +/* This is called for the start of the DOCTYPE declaration, before + any DTD or internal subset is parsed. +*/ +typedef void (XMLCALL *XML_StartDoctypeDeclHandler) ( + void *userData, + const XML_Char *doctypeName, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset); + +/* This is called for the start of the DOCTYPE declaration when the + closing > is encountered, but after processing any external + subset. +*/ +typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); + +/* This is called for entity declarations. The is_parameter_entity + argument will be non-zero if the entity is a parameter entity, zero + otherwise. + + For internal entities (), value will + be non-NULL and systemId, publicID, and notationName will be NULL. + The value string is NOT nul-terminated; the length is provided in + the value_length argument. Since it is legal to have zero-length + values, do not use this argument to test for internal entities. + + For external entities, value will be NULL and systemId will be + non-NULL. The publicId argument will be NULL unless a public + identifier was provided. The notationName argument will have a + non-NULL value only for unparsed entity declarations. + + Note that is_parameter_entity can't be changed to XML_Bool, since + that would break binary compatibility. +*/ +typedef void (XMLCALL *XML_EntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +XMLPARSEAPI(void) +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler); + +/* OBSOLETE -- OBSOLETE -- OBSOLETE + This handler has been superceded by the EntityDeclHandler above. + It is provided here for backward compatibility. + + This is called for a declaration of an unparsed (NDATA) entity. + The base argument is whatever was set by XML_SetBase. The + entityName, systemId and notationName arguments will never be + NULL. The other arguments may be. +*/ +typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) ( + void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +/* This is called for a declaration of notation. The base argument is + whatever was set by XML_SetBase. The notationName will never be + NULL. The other arguments can be. +*/ +typedef void (XMLCALL *XML_NotationDeclHandler) ( + void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* When namespace processing is enabled, these are called once for + each namespace declaration. The call to the start and end element + handlers occur between the calls to the start and end namespace + declaration handlers. For an xmlns attribute, prefix will be + NULL. For an xmlns="" attribute, uri will be NULL. +*/ +typedef void (XMLCALL *XML_StartNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix, + const XML_Char *uri); + +typedef void (XMLCALL *XML_EndNamespaceDeclHandler) ( + void *userData, + const XML_Char *prefix); + +/* This is called if the document is not standalone, that is, it has an + external subset or a reference to a parameter entity, but does not + have standalone="yes". If this handler returns XML_STATUS_ERROR, + then processing will not continue, and the parser will return a + XML_ERROR_NOT_STANDALONE error. + If parameter entity parsing is enabled, then in addition to the + conditions above this handler will only be called if the referenced + entity was actually read. +*/ +typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData); + +/* This is called for a reference to an external parsed general + entity. The referenced entity is not automatically parsed. The + application can parse it immediately or later using + XML_ExternalEntityParserCreate. + + The parser argument is the parser parsing the entity containing the + reference; it can be passed as the parser argument to + XML_ExternalEntityParserCreate. The systemId argument is the + system identifier as specified in the entity declaration; it will + not be NULL. + + The base argument is the system identifier that should be used as + the base for resolving systemId if systemId was relative; this is + set by XML_SetBase; it may be NULL. + + The publicId argument is the public identifier as specified in the + entity declaration, or NULL if none was specified; the whitespace + in the public identifier will have been normalized as required by + the XML spec. + + The context argument specifies the parsing context in the format + expected by the context argument to XML_ExternalEntityParserCreate; + context is valid only until the handler returns, so if the + referenced entity is to be parsed later, it must be copied. + context is NULL only when the entity is a parameter entity. + + The handler should return XML_STATUS_ERROR if processing should not + continue because of a fatal error in the handling of the external + entity. In this case the calling parser will return an + XML_ERROR_EXTERNAL_ENTITY_HANDLING error. + + Note that unlike other handlers the first argument is the parser, + not userData. +*/ +typedef int (XMLCALL *XML_ExternalEntityRefHandler) ( + XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* This is called in two situations: + 1) An entity reference is encountered for which no declaration + has been read *and* this is not an error. + 2) An internal entity reference is read, but not expanded, because + XML_SetDefaultHandler has been called. + Note: skipped parameter entities in declarations and skipped general + entities in attribute values cannot be reported, because + the event would be out of sync with the reporting of the + declarations or attribute values +*/ +typedef void (XMLCALL *XML_SkippedEntityHandler) ( + void *userData, + const XML_Char *entityName, + int is_parameter_entity); + +/* This structure is filled in by the XML_UnknownEncodingHandler to + provide information to the parser about encodings that are unknown + to the parser. + + The map[b] member gives information about byte sequences whose + first byte is b. + + If map[b] is c where c is >= 0, then b by itself encodes the + Unicode scalar value c. + + If map[b] is -1, then the byte sequence is malformed. + + If map[b] is -n, where n >= 2, then b is the first byte of an + n-byte sequence that encodes a single Unicode scalar value. + + The data member will be passed as the first argument to the convert + function. + + The convert function is used to convert multibyte sequences; s will + point to a n-byte sequence where map[(unsigned char)*s] == -n. The + convert function must return the Unicode scalar value represented + by this byte sequence or -1 if the byte sequence is malformed. + + The convert function may be NULL if the encoding is a single-byte + encoding, that is if map[b] >= -1 for all bytes b. + + When the parser is finished with the encoding, then if release is + not NULL, it will call release passing it the data member; once + release has been called, the convert function will not be called + again. + + Expat places certain restrictions on the encodings that are supported + using this mechanism. + + 1. Every ASCII character that can appear in a well-formed XML document, + other than the characters + + $@\^`{}~ + + must be represented by a single byte, and that byte must be the + same byte that represents that character in ASCII. + + 2. No character may require more than 4 bytes to encode. + + 3. All characters encoded must have Unicode scalar values <= + 0xFFFF, (i.e., characters that would be encoded by surrogates in + UTF-16 are not allowed). Note that this restriction doesn't + apply to the built-in support for UTF-8 and UTF-16. + + 4. No Unicode character may be encoded by more than one distinct + sequence of bytes. +*/ +typedef struct { + int map[256]; + void *data; + int (XMLCALL *convert)(void *data, const char *s); + void (XMLCALL *release)(void *data); +} XML_Encoding; + +/* This is called for an encoding that is unknown to the parser. + + The encodingHandlerData argument is that which was passed as the + second argument to XML_SetUnknownEncodingHandler. + + The name argument gives the name of the encoding as specified in + the encoding declaration. + + If the callback can provide information about the encoding, it must + fill in the XML_Encoding structure, and return XML_STATUS_OK. + Otherwise it must return XML_STATUS_ERROR. + + If info does not describe a suitable encoding, then the parser will + return an XML_UNKNOWN_ENCODING error. +*/ +typedef int (XMLCALL *XML_UnknownEncodingHandler) ( + void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + +XMLPARSEAPI(void) +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end); + +XMLPARSEAPI(void) +XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler handler); + +XMLPARSEAPI(void) +XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler handler); + +XMLPARSEAPI(void) +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler); + +XMLPARSEAPI(void) +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler); +XMLPARSEAPI(void) +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler); + +XMLPARSEAPI(void) +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end); + +XMLPARSEAPI(void) +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start); + +XMLPARSEAPI(void) +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end); + +/* This sets the default handler and also inhibits expansion of + internal entities. These entity references will be passed to the + default handler, or to the skipped entity handler, if one is set. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler); + +/* This sets the default handler but does not inhibit expansion of + internal entities. The entity reference will not be passed to the + default handler. +*/ +XMLPARSEAPI(void) +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler); + +XMLPARSEAPI(void) +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler); + +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler); + +/* If a non-NULL value for arg is specified here, then it will be + passed as the first argument to the external entity ref handler + instead of the parser object. +*/ +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandlerArg(XML_Parser parser, + void *arg); + +XMLPARSEAPI(void) +XML_SetSkippedEntityHandler(XML_Parser parser, + XML_SkippedEntityHandler handler); + +XMLPARSEAPI(void) +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + +/* This can be called within a handler for a start element, end + element, processing instruction or character data. It causes the + corresponding markup to be passed to the default handler. +*/ +XMLPARSEAPI(void) +XML_DefaultCurrent(XML_Parser parser); + +/* If do_nst is non-zero, and namespace processing is in effect, and + a name has a prefix (i.e. an explicit namespace qualifier) then + that name is returned as a triplet in a single string separated by + the separator character specified when the parser was created: URI + + sep + local_name + sep + prefix. + + If do_nst is zero, then namespace information is returned in the + default manner (URI + sep + local_name) whether or not the name + has a prefix. + + Note: Calling XML_SetReturnNSTriplet after XML_Parse or + XML_ParseBuffer has no effect. +*/ + +XMLPARSEAPI(void) +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); + +/* This value is passed as the userData argument to callbacks. */ +XMLPARSEAPI(void) +XML_SetUserData(XML_Parser parser, void *userData); + +/* Returns the last value set by XML_SetUserData or NULL. */ +#define XML_GetUserData(parser) (*(void **)(parser)) + +/* This is equivalent to supplying an encoding argument to + XML_ParserCreate. On success XML_SetEncoding returns non-zero, + zero otherwise. + Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer + has no effect and returns XML_STATUS_ERROR. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); + +/* If this function is called, then the parser will be passed as the + first argument to callbacks instead of userData. The userData will + still be accessible using XML_GetUserData. +*/ +XMLPARSEAPI(void) +XML_UseParserAsHandlerArg(XML_Parser parser); + +/* If useDTD == XML_TRUE is passed to this function, then the parser + will assume that there is an external subset, even if none is + specified in the document. In such a case the parser will call the + externalEntityRefHandler with a value of NULL for the systemId + argument (the publicId and context arguments will be NULL as well). + Note: If this function is called, then this must be done before + the first call to XML_Parse or XML_ParseBuffer, since it will + have no effect after that. Returns + XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. + Note: If the document does not have a DOCTYPE declaration at all, + then startDoctypeDeclHandler and endDoctypeDeclHandler will not + be called, despite an external subset being parsed. + Note: If XML_DTD is not defined when Expat is compiled, returns + XML_ERROR_FEATURE_REQUIRES_XML_DTD. +*/ +XMLPARSEAPI(enum XML_Error) +XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); + + +/* Sets the base to be used for resolving relative URIs in system + identifiers in declarations. Resolving relative identifiers is + left to the application: this value will be passed through as the + base argument to the XML_ExternalEntityRefHandler, + XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base + argument will be copied. Returns XML_STATUS_ERROR if out of memory, + XML_STATUS_OK otherwise. +*/ +XMLPARSEAPI(enum XML_Status) +XML_SetBase(XML_Parser parser, const XML_Char *base); + +XMLPARSEAPI(const XML_Char *) +XML_GetBase(XML_Parser parser); + +/* Returns the number of the attribute/value pairs passed in last call + to the XML_StartElementHandler that were specified in the start-tag + rather than defaulted. Each attribute/value pair counts as 2; thus + this correspondds to an index into the atts array passed to the + XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetSpecifiedAttributeCount(XML_Parser parser); + +/* Returns the index of the ID attribute passed in the last call to + XML_StartElementHandler, or -1 if there is no ID attribute. Each + attribute/value pair counts as 2; thus this correspondds to an + index into the atts array passed to the XML_StartElementHandler. +*/ +XMLPARSEAPI(int) +XML_GetIdAttributeIndex(XML_Parser parser); + +/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is + detected. The last call to XML_Parse must have isFinal true; len + may be zero for this call (or any other). + + Though the return values for these functions has always been + described as a Boolean value, the implementation, at least for the + 1.95.x series, has always returned exactly one of the XML_Status + values. +*/ +XMLPARSEAPI(enum XML_Status) +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); + +XMLPARSEAPI(void *) +XML_GetBuffer(XML_Parser parser, int len); + +XMLPARSEAPI(enum XML_Status) +XML_ParseBuffer(XML_Parser parser, int len, int isFinal); + +/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return. + Must be called from within a call-back handler, except when aborting + (resumable = 0) an already suspended parser. Some call-backs may + still follow because they would otherwise get lost. Examples: + - endElementHandler() for empty elements when stopped in + startElementHandler(), + - endNameSpaceDeclHandler() when stopped in endElementHandler(), + and possibly others. + + Can be called from most handlers, including DTD related call-backs, + except when parsing an external parameter entity and resumable != 0. + Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. + Possible error codes: + - XML_ERROR_SUSPENDED: when suspending an already suspended parser. + - XML_ERROR_FINISHED: when the parser has already finished. + - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. + + When resumable != 0 (true) then parsing is suspended, that is, + XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. + Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() + return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. + + *Note*: + This will be applied to the current parser instance only, that is, if + there is a parent parser then it will continue parsing when the + externalEntityRefHandler() returns. It is up to the implementation of + the externalEntityRefHandler() to call XML_StopParser() on the parent + parser (recursively), if one wants to stop parsing altogether. + + When suspended, parsing can be resumed by calling XML_ResumeParser(). +*/ +XMLPARSEAPI(enum XML_Status) +XML_StopParser(XML_Parser parser, XML_Bool resumable); + +/* Resumes parsing after it has been suspended with XML_StopParser(). + Must not be called from within a handler call-back. Returns same + status codes as XML_Parse() or XML_ParseBuffer(). + Additional error code XML_ERROR_NOT_SUSPENDED possible. + + *Note*: + This must be called on the most deeply nested child parser instance + first, and on its parent parser only after the child parser has finished, + to be applied recursively until the document entity's parser is restarted. + That is, the parent parser will not resume by itself and it is up to the + application to call XML_ResumeParser() on it at the appropriate moment. +*/ +XMLPARSEAPI(enum XML_Status) +XML_ResumeParser(XML_Parser parser); + +enum XML_Parsing { + XML_INITIALIZED, + XML_PARSING, + XML_FINISHED, + XML_SUSPENDED +}; + +typedef struct { + enum XML_Parsing parsing; + XML_Bool finalBuffer; +} XML_ParsingStatus; + +/* Returns status of parser with respect to being initialized, parsing, + finished, or suspended and processing the final buffer. + XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus, + XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED +*/ +XMLPARSEAPI(void) +XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status); + +/* Creates an XML_Parser object that can parse an external general + entity; context is a '\0'-terminated string specifying the parse + context; encoding is a '\0'-terminated string giving the name of + the externally specified encoding, or NULL if there is no + externally specified encoding. The context string consists of a + sequence of tokens separated by formfeeds (\f); a token consisting + of a name specifies that the general entity of the name is open; a + token of the form prefix=uri specifies the namespace for a + particular prefix; a token of the form =uri specifies the default + namespace. This can be called at any point after the first call to + an ExternalEntityRefHandler so longer as the parser has not yet + been freed. The new parser is completely independent and may + safely be used in a separate thread. The handlers and userData are + initialized from the parser argument. Returns NULL if out of memory. + Otherwise returns a new XML_Parser object. +*/ +XMLPARSEAPI(XML_Parser) +XML_ExternalEntityParserCreate(XML_Parser parser, + const XML_Char *context, + const XML_Char *encoding); + +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS +}; + +/* Controls parsing of parameter entities (including the external DTD + subset). If parsing of parameter entities is enabled, then + references to external parameter entities (including the external + DTD subset) will be passed to the handler set with + XML_SetExternalEntityRefHandler. The context passed will be 0. + + Unlike external general entities, external parameter entities can + only be parsed synchronously. If the external parameter entity is + to be parsed, it must be parsed during the call to the external + entity ref handler: the complete sequence of + XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and + XML_ParserFree calls must be made during this call. After + XML_ExternalEntityParserCreate has been called to create the parser + for the external parameter entity (context must be 0 for this + call), it is illegal to make any calls on the old parser until + XML_ParserFree has been called on the newly created parser. + If the library has been compiled without support for parameter + entity parsing (ie without XML_DTD being defined), then + XML_SetParamEntityParsing will return 0 if parsing of parameter + entities is requested; otherwise it will return non-zero. + Note: If XML_SetParamEntityParsing is called after XML_Parse or + XML_ParseBuffer, then it has no effect and will always return 0. +*/ +XMLPARSEAPI(int) +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing); + +/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then + XML_GetErrorCode returns information about the error. +*/ +XMLPARSEAPI(enum XML_Error) +XML_GetErrorCode(XML_Parser parser); + +/* These functions return information about the current parse + location. They may be called from any callback called to report + some parse event; in this case the location is the location of the + first of the sequence of characters that generated the event. When + called from callbacks generated by declarations in the document + prologue, the location identified isn't as neatly defined, but will + be within the relevant markup. When called outside of the callback + functions, the position indicated will be just past the last parse + event (regardless of whether there was an associated callback). + + They may also be called after returning from a call to XML_Parse + or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then + the location is the location of the character at which the error + was detected; otherwise the location is the location of the last + parse event, as described above. +*/ +XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); +XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); +XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); + +/* Return the number of bytes in the current event. + Returns 0 if the event is in an internal entity. +*/ +XMLPARSEAPI(int) +XML_GetCurrentByteCount(XML_Parser parser); + +/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets + the integer pointed to by offset to the offset within this buffer + of the current parse position, and sets the integer pointed to by size + to the size of this buffer (the number of input bytes). Otherwise + returns a NULL pointer. Also returns a NULL pointer if a parse isn't + active. + + NOTE: The character pointer returned should not be used outside + the handler that makes the call. +*/ +XMLPARSEAPI(const char *) +XML_GetInputContext(XML_Parser parser, + int *offset, + int *size); + +/* For backwards compatibility with previous versions. */ +#define XML_GetErrorLineNumber XML_GetCurrentLineNumber +#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +#define XML_GetErrorByteIndex XML_GetCurrentByteIndex + +/* Frees the content model passed to the element declaration handler */ +XMLPARSEAPI(void) +XML_FreeContentModel(XML_Parser parser, XML_Content *model); + +/* Exposing the memory handling functions used in Expat */ +XMLPARSEAPI(void *) +XML_MemMalloc(XML_Parser parser, size_t size); + +XMLPARSEAPI(void *) +XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); + +XMLPARSEAPI(void) +XML_MemFree(XML_Parser parser, void *ptr); + +/* Frees memory used by the parser. */ +XMLPARSEAPI(void) +XML_ParserFree(XML_Parser parser); + +/* Returns a string describing the error. */ +XMLPARSEAPI(const XML_LChar *) +XML_ErrorString(enum XML_Error code); + +/* Return a string containing the version number of this expat */ +XMLPARSEAPI(const XML_LChar *) +XML_ExpatVersion(void); + +typedef struct { + int major; + int minor; + int micro; +} XML_Expat_Version; + +/* Return an XML_Expat_Version structure containing numeric version + number information for this version of expat. +*/ +XMLPARSEAPI(XML_Expat_Version) +XML_ExpatVersionInfo(void); + +/* Added in Expat 1.95.5. */ +enum XML_FeatureEnum { + XML_FEATURE_END = 0, + XML_FEATURE_UNICODE, + XML_FEATURE_UNICODE_WCHAR_T, + XML_FEATURE_DTD, + XML_FEATURE_CONTEXT_BYTES, + XML_FEATURE_MIN_SIZE, + XML_FEATURE_SIZEOF_XML_CHAR, + XML_FEATURE_SIZEOF_XML_LCHAR + /* Additional features must be added to the end of this enum. */ +}; + +typedef struct { + enum XML_FeatureEnum feature; + const XML_LChar *name; + long int value; +} XML_Feature; + +XMLPARSEAPI(const XML_Feature *) +XML_GetFeatureList(void); + + +/* Expat follows the GNU/Linux convention of odd number minor version for + beta/development releases and even number minor version for stable + releases. Micro is bumped with each release, and set to 0 with each + change to major or minor version. +*/ +#define XML_MAJOR_VERSION 1 +#define XML_MINOR_VERSION 95 +#define XML_MICRO_VERSION 8 + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlParse_INCLUDED */ diff --git a/reactos/subsys/system/ibrowser/utility/utility.cpp b/reactos/subsys/system/ibrowser/utility/utility.cpp new file mode 100644 index 00000000000..6d51acf72a8 --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/utility.cpp @@ -0,0 +1,419 @@ +/* + * Copyright 2003, 2004, 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // Explorer clone + // + // utility.cpp + // + // Martin Fuchs, 23.07.2003 + // + + +#include "precomp.h" + +//#include + +#include +#include + + +DWORD WINAPI Thread::ThreadProc(void* para) +{ + Thread* pThis = (Thread*) para; + + int ret = pThis->Run(); + + pThis->_alive = false; + + return ret; +} + + +void CenterWindow(HWND hwnd) +{ + RECT rt, prt; + GetWindowRect(hwnd, &rt); + + DWORD style; + HWND owner = 0; + + for(HWND wh=hwnd; (wh=GetWindow(wh,GW_OWNER))!=0; ) + if (((style=GetWindowStyle(wh))&WS_VISIBLE) && !(style&WS_MINIMIZE)) + {owner=wh; break;} + + if (owner) + GetWindowRect(owner, &prt); + else + SystemParametersInfo(SPI_GETWORKAREA, 0, &prt, 0); //@@ GetDesktopWindow() wäre auch hilfreich. + + SetWindowPos(hwnd, 0, (prt.left+prt.right+rt.left-rt.right)/2, + (prt.top+prt.bottom+rt.top-rt.bottom)/2, 0,0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); + + MoveVisible(hwnd); +} + +void MoveVisible(HWND hwnd) +{ + RECT rc; + GetWindowRect(hwnd, &rc); + int left=rc.left, top=rc.top; + + int xmax = GetSystemMetrics(SM_CXSCREEN); + int ymax = GetSystemMetrics(SM_CYSCREEN); + + if (rc.left < 0) + rc.left = 0; + else if (rc.right > xmax) + if ((rc.left-=rc.right-xmax) < 0) + rc.left = 0; + + if (rc.top < 0) + rc.top = 0; + else if (rc.bottom > ymax) + if ((rc.top-=rc.bottom-ymax) < 0) + rc.top = 0; + + if (rc.left!=left || rc.top!=top) + SetWindowPos(hwnd, 0, rc.left,rc.top, 0,0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE); +} + + +void display_error(HWND hwnd, DWORD error) //@@ CONTEXT mit ausgeben -> display_error(HWND hwnd, const Exception& e) +{ + PTSTR msg; + + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) { + LOG(FmtString(TEXT("display_error(%#x): %s"), error, msg)); + + SetLastError(0); + MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); + + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); + } else { + LOG(FmtString(TEXT("Unknown Error %#x"), error)); + + FmtString msg(TEXT("Unknown Error %#x"), error); + + SetLastError(0); + MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); + + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); + } + + LocalFree(msg); +} + + +Context Context::s_main("-NO-CONTEXT-"); +Context* Context::s_current = &Context::s_main; + +String Context::toString() const +{ + String str = _ctx; + + if (!_obj.empty()) + str.appendf(TEXT("\nObject: %s"), (LPCTSTR)_obj); + + return str; +} + +String Context::getStackTrace() const +{ + ostringstream str; + + str << "Context Trace:\n"; + + for(const Context*p=this; p && p!=&s_main; p=p->_last) { + str << "- " << p->_ctx; + + if (!p->_obj.empty()) + str << " obj=" << ANS(p->_obj); + + str << '\n'; + } + + return str.str(); +} + + +BOOL time_to_filetime(const time_t* t, FILETIME* ftime) +{ + struct tm* tm = gmtime(t); + SYSTEMTIME stime; + + if (!tm) + return FALSE; + + stime.wYear = tm->tm_year+1900; + stime.wMonth = tm->tm_mon+1; + stime.wDayOfWeek = (WORD)-1; + stime.wDay = tm->tm_mday; + stime.wHour = tm->tm_hour; + stime.wMinute = tm->tm_min; + stime.wSecond = tm->tm_sec; + stime.wMilliseconds = 0; + + return SystemTimeToFileTime(&stime, ftime); +} + + +BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow, LPCTSTR parameters) +{ + CONTEXT("launch_file()"); + + HINSTANCE hinst = ShellExecute(hwnd, NULL/*operation*/, cmd, parameters, NULL/*dir*/, nCmdShow); + + if ((int)hinst <= 32) { + display_error(hwnd, GetLastError()); + return FALSE; + } + + return TRUE; +} + +#ifdef UNICODE +BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow, LPCSTR parameters) +{ + HINSTANCE hinst = ShellExecuteA(hwnd, NULL/*operation*/, cmd, parameters, NULL/*dir*/, nCmdShow); + + if ((int)hinst <= 32) { + display_error(hwnd, GetLastError()); + return FALSE; + } + + return TRUE; +} +#endif + + +/* search for already running instance */ + +static int g_foundPrevInstance = 0; + +static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lparam) +{ + TCHAR cls[128]; + + GetClassName(hwnd, cls, 128); + + if (!lstrcmp(cls, (LPCTSTR)lparam)) { + g_foundPrevInstance++; + return FALSE; + } + + return TRUE; +} + +/* search for window of given class name to allow only one running instance */ +int find_window_class(LPCTSTR classname) +{ + EnumWindows(EnumWndProc, (LPARAM)classname); + + if (g_foundPrevInstance) + return 1; + + return 0; +} + + +typedef void (WINAPI*RUNDLLPROC)(HWND hwnd, HINSTANCE hinst, LPCTSTR cmdline, DWORD nCmdShow); + +BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow) +{ + HMODULE hmod = LoadLibrary(dllname); + if (!hmod) + return FALSE; + +/*TODO + + It is possible to create a Unicode version of the function. + Rundll32 first tries to find a function named EntryPointW. + If it cannot find this function, it tries EntryPointA, then EntryPoint. + To create a DLL that supports ANSI on Windows 95/98/Me and Unicode otherwise, + export two functions: EntryPointW and EntryPoint. +*/ + RUNDLLPROC proc = (RUNDLLPROC)GetProcAddress(hmod, procname); + if (!proc) { + FreeLibrary(hmod); + return FALSE; + } + + proc(hwnd, hmod, cmdline, nCmdShow); + + FreeLibrary(hmod); + + return TRUE; +} + + +BOOL launch_cpanel(HWND hwnd, LPCTSTR applet) +{ + //launch_file(_hwnd, applet, SW_SHOWNORMAL); // This would be enough, but we want the fastest solution. + //launch_file(_hwnd, TEXT("rundll32.exe /d shell32.dll,Control_RunDLL ")+applet, SW_SHOWNORMAL); + + return RunDLL(hwnd, TEXT("shell32"), "Control_RunDLL", applet, SW_SHOWNORMAL); +} + + +BOOL RecursiveCreateDirectory(LPCTSTR path_in) +{ + TCHAR path[MAX_PATH], hole_path[MAX_PATH]; + + _tcscpy(hole_path, path_in); + + int drv_len = 0; + LPCTSTR d; + + for(d=hole_path; *d && *d!='/' && *d!='\\'; ++d) { + ++drv_len; + + if (*d == ':') + break; + } + + LPTSTR dir = hole_path + drv_len; + + int l; + LPTSTR p = hole_path + (l=_tcslen(hole_path)); + + while(--p>=hole_path && (*p=='/' || *p=='\\')) + *p = '\0'; + + WIN32_FIND_DATA w32fd; + + HANDLE hFind = FindFirstFile(hole_path, &w32fd); + + if (hFind == INVALID_HANDLE_VALUE) { + _tcsncpy(path, hole_path, drv_len); + int i = drv_len; + + for(p=dir; *p=='/'||*p=='\\'; p++) + path[i++] = *p++; + + for(; i + + // Unicode support +#ifdef UNICODE +#define _UNICODE +#endif +#include + +#include // for SelectBrush(), ListBox_SetSel(), SubclassWindow(), ... +#include + +#ifndef _MSC_VER +#include +#endif +#include // for VARIANT + +#include // for alloca() +#include +#include // for _MAX_DIR, ... +#include // for sprintf() +#include + +#ifndef _MAX_PATH +#define _MAX_DRIVE 3 +#define _MAX_FNAME 256 +#define _MAX_DIR _MAX_FNAME +#define _MAX_EXT _MAX_FNAME +#define _MAX_PATH 260 +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define for if (0) {} else for + +#define COUNTOF(x) (sizeof(x)/sizeof(x[0])) + + +#define BUFFER_LEN 2048 + + +#define LOG(txt) + + +#ifndef _tcsrchr +#ifdef UNICODE +#define _tcsrchr wcsrchr +#else +#define _tcsrchr strrchr +#endif +#endif + +#ifndef _stprintf +#ifdef UNICODE +#define _stprintf wcsprintf +#else +#define _stprintf sprintf +#endif +#endif + +#define U2A(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, -1, d, l, NULL, NULL) +#define U2nA(s, d, l) WideCharToMultiByte(CP_ACP, 0, s, l, d, l, NULL, NULL) +#define A2U(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, -1, d, l) +#define A2nU(s, d, l) MultiByteToWideChar(CP_ACP, 0, s, l, d, l) + + +#ifdef __WINE__ +#ifdef UNICODE +extern void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* ext); +#else +extern void _splitpath(const CHAR* path, CHAR* drv, CHAR* dir, CHAR* name, CHAR* ext); +#endif +#define _tcsnicmp strncasecmp +#define _tcsicoll strcasecmp +#endif + +#ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED +#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040 +#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 +#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 +#endif + + +#define SetDlgCtrlID(hwnd, id) SetWindowLong(hwnd, GWL_ID, id) +#define SetWindowStyle(hwnd, val) (DWORD)SetWindowLong(hwnd, GWL_STYLE, val) +#define SetWindowExStyle(h, val) (DWORD)SetWindowLong(hwnd, GWL_EXSTYLE, val) +#define Window_SetIcon(hwnd, type, hicon) (HICON)SendMessage(hwnd, WM_SETICON, type, (LPARAM)(hicon)) + + + // center window in respect to its parent window +extern void CenterWindow(HWND hwnd); + + // move window into visibility +extern void MoveVisible(HWND hwnd); + + // display error message +extern void display_error(HWND hwnd, DWORD error); + + // convert time_t to WIN32 FILETIME +extern BOOL time_to_filetime(const time_t* t, FILETIME* ftime); + + // search for windows of a specific classname +extern int find_window_class(LPCTSTR classname); + + // create a directory with all missing parent directories +BOOL RecursiveCreateDirectory(LPCTSTR path_in); + + // test for existing directory +BOOL exists_path(LPCTSTR path); + + +#ifdef __cplusplus +} // extern "C" +#endif + + +#ifdef __cplusplus + +#ifdef _MSC_VER +#pragma warning(disable: 4786) // disable warnings about too long debug information symbols +#endif + + // STL headers for strings and streams +#include +#include +using namespace std; + + // containers +#include +#include +#include +#include +#include + + +#if _MSC_VER>=1300 // VS.Net +#define _NO_COMUTIL //@@ +#endif + +#if defined(_MSC_VER) && !defined(_NO_COMUTIL) + + // COM utility headers +#include +using namespace _com_util; + +#endif // _MSC_VER && !_NO_COMUTIL + + + // launch a program or document file +extern BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow, LPCTSTR parameters=NULL); +#ifdef UNICODE +extern BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow, LPCSTR parameters=NULL); +#else +#define launch_fileA launch_file +#endif + + // call an DLL export like rundll32 +extern BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow); + + // launch control panel applet +extern BOOL launch_cpanel(HWND hwnd, LPCTSTR applet); + + + /// initialization of windows common controls +struct CommonControlInit +{ + CommonControlInit(DWORD flags=ICC_LISTVIEW_CLASSES|ICC_TREEVIEW_CLASSES|ICC_BAR_CLASSES|ICC_PROGRESS_CLASS|ICC_COOL_CLASSES) + { + INITCOMMONCONTROLSEX icc = {sizeof(INITCOMMONCONTROLSEX), flags}; + + InitCommonControlsEx(&icc); + } +}; + + + /// wait cursor + +struct WaitCursor ///@todo integrate with WM_SETCURSOR to enable multithreaded background tasks as program launching +{ + WaitCursor() + { + _old_cursor = SetCursor(LoadCursor(0, IDC_WAIT)); + } + + ~WaitCursor() + { + SetCursor(_old_cursor); + } + +protected: + HCURSOR _old_cursor; +}; + + + /// base of all structures storing a window handle +struct WindowHandle +{ + WindowHandle(HWND hwnd=0) + : _hwnd(hwnd) {} + + operator HWND() const {return _hwnd;} + HWND* operator&() {return &_hwnd;} + +protected: + HWND _hwnd; +}; + + + /// locally hide a window +struct HiddenWindow : public WindowHandle +{ + HiddenWindow(HWND hwnd) + : WindowHandle(IsWindowVisible(hwnd)? hwnd: 0) + { + if (_hwnd) + SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER); + } + + ~HiddenWindow() + { + if (_hwnd) + SetWindowPos(_hwnd, 0, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER); + } +}; + + + /// critical section wrapper + +struct CritSect : public CRITICAL_SECTION +{ + CritSect() + { + InitializeCriticalSection(this); + } + + ~CritSect() + { + DeleteCriticalSection(this); + } +}; + + + /// Lock protects a code section utilizing a critical section + +struct Lock +{ + Lock(CritSect& crit_sect) + : _crit_sect(crit_sect) + { + EnterCriticalSection(&crit_sect); + } + + ~Lock() + { + LeaveCriticalSection(&_crit_sect); + } + +protected: + CritSect& _crit_sect; +}; + + + /// Thread base class + +struct Thread +{ + Thread() + : _alive(false) + { + _hThread = INVALID_HANDLE_VALUE; + } + + virtual ~Thread() + { + Stop(); + + CloseHandle(_hThread); + } + + void Start() + { + if (!_alive) { + _alive = true; + _hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL); + } + } + + void Stop() + { + if (_alive) { + { + Lock lock(_crit_sect); + _alive = false; + } + + // wait for finishing + WaitForSingleObject(_hThread, INFINITE); + } + } + + virtual int Run() = 0; + + bool is_alive() const {return _alive;} + + CritSect _crit_sect; + +protected: + static DWORD WINAPI ThreadProc(void* para); + + HANDLE _hThread; + bool _alive; +}; + + + // window utilities + + /// ClientRect retreives the client area rectangle of a window. +struct ClientRect : public RECT +{ + ClientRect(HWND hwnd) + { + GetClientRect(hwnd, this); + } + + operator LPRECT() {return this;} + + POINT& pos() {return *(LPPOINT)this;} +}; + + /// ClientRect retreives the window rectangle of a window. +struct WindowRect : public RECT +{ + WindowRect(HWND hwnd) + { + GetWindowRect(hwnd, this); + } + + operator LPRECT() {return this;} + + POINT& pos() {return *(LPPOINT)this;} +}; + + /// PointL encapsulates the POINT structure into a C++ object. +struct Point : public POINT +{ + Point(LONG x_, LONG y_) + { + x = x_; + y = y_; + } + + // constructor for being used in processing WM_MOUSEMOVE, WM_LBUTTONDOWN, ... messages + Point(LPARAM lparam) + { + x = GET_X_LPARAM(lparam); + y = GET_Y_LPARAM(lparam); + } + + operator LPPOINT() {return this;} +}; + + + /// transform coordinates in a RECT from client to screen coordiantes +inline void ClientToScreen(HWND hwnd, RECT* prect) + {::ClientToScreen(hwnd,(LPPOINT)&prect->left); ::ClientToScreen(hwnd,(LPPOINT)&prect->right);} + + /// transform coordinates in a RECT from screen to client coordiantes +inline void ScreenToClient(HWND hwnd, RECT* prect) + {::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);} + + + /// structure containing information about full screen display of the frame window +struct FullScreenParameters +{ + FullScreenParameters() + : _mode(FALSE) + { + } + + BOOL _mode; + RECT _orgPos; + BOOL _wasZoomed; +}; + + + // drawing utilities + + /// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint(). +struct PaintCanvas : public PAINTSTRUCT +{ + PaintCanvas(HWND hwnd) + : _hwnd(hwnd) + { + BeginPaint(hwnd, this); + } + + ~PaintCanvas() + { + EndPaint(_hwnd, this); + } + + operator HDC() const {return hdc;} + +protected: + HWND _hwnd; +}; + + /// Canvas is a encapsulation of device contexts. +struct Canvas +{ + Canvas(HDC hdc) : _hdc(hdc) {} + + operator HDC() {return _hdc;} + +protected: + HDC _hdc; +}; + + /// WindowCanvas is a encapsulation of client area device contexts. +struct WindowCanvas : public Canvas +{ + WindowCanvas(HWND hwnd) + : Canvas(GetDC(hwnd)), _hwnd(hwnd) {} + + ~WindowCanvas() {ReleaseDC(_hwnd, _hdc);} + +protected: + HWND _hwnd; +}; + + + // double buffering classes + + /// Memory Canvas creates and destroys memory devoce contexts. +struct MemCanvas : public Canvas +{ + MemCanvas(HDC hdc=0) + : Canvas(CreateCompatibleDC(hdc)) {assert(_hdc);} + + ~MemCanvas() {DeleteDC(_hdc);} +}; + + /// SelectedBitmap is used to localy select bitmaps into device contexts. +struct SelectedBitmap +{ + SelectedBitmap(HDC hdc, HBITMAP hbmp) + : _hdc(hdc), _old_hbmp(SelectBitmap(hdc, hbmp)) {} + + ~SelectedBitmap() {DeleteObject(SelectBitmap(_hdc, _old_hbmp));} + +protected: + HDC _hdc; + HBITMAP _old_hbmp; +}; + + /// BufferCanvas manages offscreen bitmaps selected into memory device contexts. +struct BufferCanvas : public MemCanvas +{ + BufferCanvas(HDC hdc, int x, int y, int w, int h) + : MemCanvas(hdc), _hdctarg(hdc), + _x(x), _y(y), _w(w), _h(h), + _bmp(_hdc, CreateCompatibleBitmap(hdc, w, h)) {} + + BufferCanvas(HDC hdc, const RECT& rect) + : MemCanvas(hdc), _hdctarg(hdc), + _x(rect.left), _y(rect.top), _w(rect.right-rect.left), _h(rect.bottom-rect.top), + _bmp(_hdc, CreateCompatibleBitmap(hdc, _w, _h)) {} + +protected: + HDC _hdctarg; + int _x, _y, _w, _h; + SelectedBitmap _bmp; +}; + + /// BufferedCanvas enables double buffering for a device context. +struct BufferedCanvas : public BufferCanvas +{ + BufferedCanvas(HDC hdc, int x, int y, int w, int h, DWORD mode=SRCCOPY) + : BufferCanvas(hdc, x, y, w, h), _mode(mode) {} + + BufferedCanvas(HDC hdc, const RECT& rect, DWORD mode=SRCCOPY) + : BufferCanvas(hdc, rect), _mode(mode) {} + + ~BufferedCanvas() {BitBlt(_hdctarg, _x, _y, _w, _h, _hdc, 0, 0, _mode);} + + DWORD _mode; +}; + + /// BufferedPaintCanvas extends PaintCanvas for double buffering. +struct BufferedPaintCanvas : public PaintCanvas, public BufferedCanvas +{ + BufferedPaintCanvas(HWND hwnd) + : PaintCanvas(hwnd), + BufferedCanvas(PAINTSTRUCT::hdc, 0, 0, rcPaint.right, rcPaint.bottom) + { + } + + operator HDC() {return BufferedCanvas::_hdc;} +}; + + + /// TextColor locally selects a text color for drawing. +struct TextColor +{ + TextColor(HDC hdc, COLORREF color) + : _hdc(hdc), _old_color(SetTextColor(hdc, color)) {} + + ~TextColor() {SetTextColor(_hdc, _old_color);} + +protected: + HDC _hdc; + COLORREF _old_color; +}; + + /// BkMode locally sets the background mode for drawing. +struct BkMode +{ + BkMode(HDC hdc, int bkmode) + : _hdc(hdc), _old_bkmode(SetBkMode(hdc, bkmode)) {} + + ~BkMode() {SetBkMode(_hdc, _old_bkmode);} + +protected: + HDC _hdc; + COLORREF _old_bkmode; +}; + + /// FontSelection locally selects a font for drawing. +struct FontSelection +{ + FontSelection(HDC hdc, HFONT hFont) + : _hdc(hdc), _old_hFont(SelectFont(hdc, hFont)) {} + + ~FontSelection() {SelectFont(_hdc, _old_hFont);} + +protected: + HDC _hdc; + HFONT _old_hFont; +}; + + /// BitmapSelection locally selects a bitmap into a device context. +struct BitmapSelection +{ + BitmapSelection(HDC hdc, HBITMAP hBmp) + : _hdc(hdc), _old_hBmp(SelectBitmap(hdc, hBmp)) {} + + ~BitmapSelection() {SelectBitmap(_hdc, _old_hBmp);} + +protected: + HDC _hdc; + HBITMAP _old_hBmp; +}; + + /// BrushSelection locally selects a brush into a device context. +struct BrushSelection +{ + BrushSelection(HDC hdc, HBRUSH hBrush) + : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {} + + ~BrushSelection() {SelectBrush(_hdc, _old_hBrush);} + +protected: + HDC _hdc; + HBRUSH _old_hBrush; +}; + + + /// Popup Menus +struct PopupMenu +{ + PopupMenu() + : _hmenu(CreatePopupMenu()) + { + } + + PopupMenu(UINT nid); + + operator HMENU() {return _hmenu;} + + void Append(UINT id, LPCTSTR str, UINT flags=MF_STRING) + { + AppendMenu(_hmenu, flags, id, str); + } + + int TrackPopupMenu(HWND hwnd, const POINT& pt, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON, LPTPMPARAMS tpm=NULL) { + return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, tpm); + } + + int PopupContextMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) { + POINT pt; POINTSTOPOINT(pt, pos); + return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL); + } + + int TrackPopupMenu(HWND hwnd, POINTS pos, UINT flags=TPM_LEFTBUTTON|TPM_RIGHTBUTTON) { + POINT pt; POINTSTOPOINT(pt, pos); + ClientToScreen(hwnd, &pt); + return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL); + } + + int TrackPopupMenuAtCursor(HWND hwnd, UINT flags=TPM_LEFTBUTTON) { + POINT pt; GetCursorPos(&pt); + return TrackPopupMenuEx(_hmenu, flags, pt.x, pt.y, hwnd, NULL); + } + + int TrackPopupMenuAtPos(HWND hwnd, DWORD pos, UINT flags=TPM_LEFTBUTTON) { + return TrackPopupMenuEx(_hmenu, flags, GET_X_LPARAM(pos), GET_Y_LPARAM(pos), hwnd, NULL); + } + +protected: + HMENU _hmenu; +}; + + +struct Variant : public VARIANT +{ + Variant() {VariantInit(this);} + Variant(const VARIANT& var); + Variant(const VARIANT* var); + ~Variant(); + + operator long() const; + operator bool() const; + operator VARIANT_BOOL() const; + operator IDispatch*() const; +}; + + +struct BStr +{ + BStr() + { + _p = NULL; + } + + BStr(const BSTR s) + { + _p = SysAllocString(s); + } + + BStr(LPCSTR s) + { + WCHAR b[BUFFER_LEN]; + + if (s) + _p = SysAllocStringLen(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1); + else + _p = NULL; + } + + BStr(LPCWSTR s) + { + _p = SysAllocString(s); + } + + BStr(const VARIANT& var) + : _p(NULL) + { + assign(var); + } + + ~BStr() + { + SysFreeString(_p); + } + + void assign(BSTR s); + void assign(const VARIANT& var); + + operator BSTR() const + { + return _p? _p: (BSTR)L""; + } + + int length() const + { + return _p? wcslen(_p): 0; + } + +protected: + BSTR _p; +}; + + + /// string class for TCHAR strings +struct String +#ifdef UNICODE + : public wstring +#else + : public string +#endif +{ +#ifdef UNICODE + typedef wstring super; +#else + typedef string super; +#endif + + String() {} + + String(LPCTSTR s) {if (s) super::assign(s);} + String(LPCTSTR s, int l) : super(s, l) {} + + String(const super& other) : super(other) {} + String(const String& other) : super(other) {} + +#ifdef UNICODE + String(LPCSTR s) {assign(s);} + String(LPCSTR s, int l) {assign(s, l);} + String(const string& other) {assign(other.c_str());} + String& operator=(LPCSTR s) {assign(s); return *this;} + void assign(LPCSTR s) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, -1, b, BUFFER_LEN)-1);} else erase();} + void assign(LPCSTR s, int l) {if (s) {TCHAR b[BUFFER_LEN]; super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, BUFFER_LEN));} else erase();} + void assign(const BStr& s) {int l = s.length(); super::assign(s, l);} +#else + String(LPCWSTR s) {assign(s);} + String(LPCWSTR s, int l) {assign(s, l);} + String(const wstring& other) {assign(other.c_str());} + String& operator=(LPCWSTR s) {assign(s); return *this;} + void assign(LPCWSTR s) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, -1, b, BUFFER_LEN, 0, 0)-1);} else erase();} + void assign(LPCWSTR s, int l) {if (s) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();} + void assign(const BStr& s) {int l = s.length(); if (l) {char b[BUFFER_LEN]; super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, BUFFER_LEN, 0, 0));} else erase();} +#endif + String(const BStr& s) {assign(s);} + String& operator=(const BStr& s) {assign(s); return *this;} + + String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;} + String& operator=(const super& s) {super::assign(s); return *this;} + void assign(LPCTSTR s) {super::assign(s);} + void assign(LPCTSTR s, int l) {super::assign(s, l);} + + operator LPCTSTR() const {return c_str();} + +#ifdef UNICODE + operator string() const {char b[BUFFER_LEN]; return string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN, 0, 0)-1);} +#else + operator wstring() const {WCHAR b[BUFFER_LEN]; return wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), -1, b, BUFFER_LEN)-1);} +#endif + + String& printf(LPCTSTR fmt, ...) + { + va_list l; + TCHAR b[BUFFER_LEN]; + + va_start(l, fmt); + super::assign(b, _vstprintf(b, fmt, l)); + va_end(l); + + return *this; + } + + String& vprintf(LPCTSTR fmt, va_list l) + { + TCHAR b[BUFFER_LEN]; + + super::assign(b, _vstprintf(b, fmt, l)); + + return *this; + } + + String& appendf(LPCTSTR fmt, ...) + { + va_list l; + TCHAR b[BUFFER_LEN]; + + va_start(l, fmt); + super::append(b, _vstprintf(b, fmt, l)); + va_end(l); + + return *this; + } + + String& vappendf(LPCTSTR fmt, va_list l) + { + TCHAR b[BUFFER_LEN]; + + super::append(b, _vstprintf(b, fmt, l)); + + return *this; + } +}; + +#define _STRING_DEFINED + + +struct FmtString : public String +{ + FmtString(LPCTSTR fmt, ...) + { + va_list l; + + va_start(l, fmt); + vprintf(fmt, l); + va_end(l); + } +}; + + +#ifdef UNICODE + +struct ANS +{ + ANS(LPCWSTR s) + { + int l = wcslen(s) + 1; + _str = (LPSTR) malloc(2*l); + + if (WideCharToMultiByte(CP_ACP, 0, s, -1, _str, 2*l, 0, 0) <= 0) + *_str = '\0'; + } + + ~ANS() + { + free(_str); + } + + operator LPCSTR() {return _str;} + +protected: + LPSTR _str; +}; + +#define UNC(x) ((LPCWSTR)(x)) + +#else + +#define ANS(x) ((LPCSTR)(x)) + +struct UNC +{ + UNC(LPCSTR s) + { + int l = strlen(s) + 1; + _str = (LPWSTR) malloc(2*l); + + if (MultiByteToWideChar(CP_ACP, 0, s, -1, _str, l) <= 0) + *_str = '\0'; + } + + ~UNC() + { + free(_str); + } + + operator LPCWSTR() {return _str;} + +protected: + LPWSTR _str; +}; + +#endif + + + // determine windows version string +//@@String get_windows_version_str(); + + + /// link dynamicly to functions by using GetModuleHandle() and GetProcAddress() +template struct DynamicFct +{ + DynamicFct(LPCTSTR moduleName, UINT ordinal) + { + HMODULE hModule = GetModuleHandle(moduleName); + + _fct = (FCT) GetProcAddress(hModule, (LPCSTR)ordinal); + } + + DynamicFct(LPCTSTR moduleName, LPCSTR name) + { + HMODULE hModule = GetModuleHandle(moduleName); + + _fct = (FCT) GetProcAddress(hModule, name); + } + + FCT operator*() const {return _fct;} + operator bool() const {return _fct? true: false;} + +protected: + FCT _fct; +}; + + + /// link dynamicly to functions by using LoadLibrary() and GetProcAddress() +template struct DynamicLoadLibFct +{ + DynamicLoadLibFct(LPCTSTR moduleName, UINT ordinal) + { + _hModule = LoadLibrary(moduleName); + + _fct = (FCT) GetProcAddress(_hModule, (LPCSTR)ordinal); + } + + DynamicLoadLibFct(LPCTSTR moduleName, LPCSTR name) + { + _hModule = LoadLibrary(moduleName); + + _fct = (FCT) GetProcAddress(_hModule, name); + } + + ~DynamicLoadLibFct() + { + FreeLibrary(_hModule); + } + + FCT operator*() const {return _fct;} + operator bool() const {return _fct? true: false;} + +protected: + HMODULE _hModule; + FCT _fct; +}; + + +struct Context +{ + Context(const char* ctx) + : _ctx(ctx) + { + _last = s_current; + s_current = this; + } + + Context(const char* ctx, LPCSTR obj) + : _ctx(ctx), + _obj(obj) + { + _last = s_current; + s_current = this; + } + + Context(const char* ctx, LPCWSTR obj) + : _ctx(ctx), + _obj(obj) + { + _last = s_current; + s_current = this; + } + + Context(const Context& other) + : _ctx(other._ctx), + _obj(other._obj) + { + _last = NULL; + } + + ~Context() + { + if (_last) { + s_current = _last; + _last = NULL; + } + } + + String toString() const; + String getStackTrace() const; + + const char* _ctx; + String _obj; + + static Context& current() {return *s_current;} + +protected: + Context* _last; + + static Context* s_current; ///@todo use TLS + static Context s_main; +}; + +#define CONTEXT_OBJ __ctx__._obj +#define CONTEXT(c) Context __ctx__(c) +#define CURRENT_CONTEXT Context::current() +#define OBJ_CONTEXT(c, o) Context __ctx__(c, o) + + +extern bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out); + + +#endif // __cplusplus diff --git a/reactos/subsys/system/ibrowser/utility/window.cpp b/reactos/subsys/system/ibrowser/utility/window.cpp new file mode 100644 index 00000000000..c9d7085a98d --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/window.cpp @@ -0,0 +1,1206 @@ +/* + * Copyright 2003, 2004, 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // window.cpp + // + // Martin Fuchs, 23.07.2003 + // + + +#include "precomp.h" + +#include "../ibrowser_intres.h" // for ID_GO_BACK, ... + + +WindowClass::WindowClass(LPCTSTR classname, UINT style_, WNDPROC wndproc) +{ + memset(this, 0, sizeof(WNDCLASSEX)); + + cbSize = sizeof(WNDCLASSEX); + style = style_; + hInstance = g_hInstance; + hCursor = LoadCursor(0, IDC_ARROW); + + lpszClassName = classname; + lpfnWndProc = wndproc; + + _atomClass = 0; +} + + +IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPROC wndproc) + : WindowClass(classname, style, wndproc) +{ + hIcon = ResIcon(nid); + hIconSm = SmallIcon(nid); +} + + +Window::WindowMap Window::s_wnd_map; + +Window::CREATORFUNC Window::s_window_creator = NULL; +const void* Window::s_new_info = NULL; + + +Window::StaticWindowData& Window::GetStaticWindowData() +{ + static StaticWindowData s_initialized_data; + + return s_initialized_data; +} + + +Window::Window(HWND hwnd) + : WindowHandle(hwnd) +{ + Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map + + s_wnd_map[_hwnd] = this; +} + +Window::~Window() +{ + Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map + + s_wnd_map.erase(_hwnd); +} + + +HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle, + LPCTSTR lpClassName, LPCTSTR lpWindowName, + DWORD dwStyle, int x, int y, int w, int h, + HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/) +{ + Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info + + s_window_creator = creator; + s_new_info = NULL; + + return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, + x, y, w, h, + hwndParent, hMenu, g_hInstance, 0/*lpParam*/); +} + +HWND Window::Create(CREATORFUNC_INFO creator, const void* info, DWORD dwExStyle, + LPCTSTR lpClassName, LPCTSTR lpWindowName, + DWORD dwStyle, int x, int y, int w, int h, + HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/) +{ + Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info + + s_window_creator = (CREATORFUNC) creator; + s_new_info = info; + + return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, + x, y, w, h, + hwndParent, hMenu, g_hInstance, 0/*lpParam*/); +} + + + /// get window controller from window handle + +Window* Window::get_window(HWND hwnd) +{ + { + Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map + + WindowMap::const_iterator found = s_wnd_map.find(hwnd); + + if (found!=s_wnd_map.end()) + return found->second; + } + + return NULL; +} + + + /// create controller for a new window + +Window* Window::create_controller(HWND hwnd) +{ + if (s_window_creator) { // protect for recursion and create the window object only for the first window + Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info + + const void* info = s_new_info; + s_new_info = NULL; + + CREATORFUNC window_creator = s_window_creator; + s_window_creator = NULL; + + if (info) + return CREATORFUNC_INFO(window_creator)(hwnd, info); + else + return CREATORFUNC(window_creator)(hwnd); + } + + return NULL; +} + + +LRESULT Window::Init(LPCREATESTRUCT pcs) +{ + return 0; +} + + +LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + Window* pThis = get_window(hwnd); + + if (!pThis) + pThis = create_controller(hwnd); + + if (pThis) { + switch(nmsg) { + case WM_COMMAND: + return pThis->Command(LOWORD(wparam), HIWORD(wparam)); + + case WM_NOTIFY: + return pThis->Notify(wparam, (NMHDR*)lparam); + + case WM_NOTIFYFORMAT: + return NFR_CURRENT; + + case WM_CREATE: + return pThis->Init((LPCREATESTRUCT)lparam); + + case WM_NCDESTROY: + delete pThis; + return 0; + + default: + return pThis->WndProc(nmsg, wparam, lparam); + } + } + else + return DefWindowProc(hwnd, nmsg, wparam, lparam); +} + +LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + return DefWindowProc(_hwnd, nmsg, wparam, lparam); +} + +int Window::Command(int id, int code) +{ + return 1; // no command handler found +} + +int Window::Notify(int id, NMHDR* pnmh) +{ + return 0; +} + +void Window::CancelModes(HWND hwnd) +{ + if (hwnd) + PostMessage(hwnd, WM_CANCELMODE, 0, 0); + else + PostMessage(HWND_BROADCAST, WM_CANCELMODE, 0, 0); +} + + +SubclassedWindow::SubclassedWindow(HWND hwnd) + : super(hwnd) +{ + _orgWndProc = SubclassWindow(_hwnd, SubclassedWndProc); + + if (!_orgWndProc) + delete this; +} + +LRESULT CALLBACK SubclassedWindow::SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + SubclassedWindow* pThis = GET_WINDOW(SubclassedWindow, hwnd); + assert(pThis); + + if (pThis) { + switch(nmsg) { + case WM_COMMAND: + if (!pThis->Command(LOWORD(wparam), HIWORD(wparam))) + return 0; + break; + + case WM_NOTIFY: + return pThis->Notify(wparam, (NMHDR*)lparam); + + case WM_NOTIFYFORMAT: + return NFR_CURRENT; + + case WM_CREATE: + return pThis->Init((LPCREATESTRUCT)lparam); + + case WM_NCDESTROY: + delete pThis; + return 0; + + default: + return pThis->WndProc(nmsg, wparam, lparam); + } + } + + return CallWindowProc(pThis->_orgWndProc, hwnd, nmsg, wparam, lparam); +} + +LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + return CallWindowProc(_orgWndProc, _hwnd, nmsg, wparam, lparam); +} + +int SubclassedWindow::Command(int id, int code) +{ + return 1; // no command handler found +} + +int SubclassedWindow::Notify(int id, NMHDR* pnmh) +{ + return CallWindowProc(_orgWndProc, _hwnd, WM_NOTIFY, id, (LPARAM)pnmh); +} + + +ChildWindow::ChildWindow(HWND hwnd, HWND hwndFrame) + : super(hwnd), + _hwndFrame(hwndFrame) +{ +} + + +ChildWindow* ChildWindow::create(const ChildWndInfo& info, CREATORFUNC_INFO creator, + LPCTSTR classname, LPCTSTR title, DWORD style) +{ + HWND hwnd = Window::Create(creator, &info, 0, classname, title, style, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, info._hwndFrame); + + return GET_WINDOW(ChildWindow, hwnd); +} + + +LRESULT ChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + switch(nmsg) { + case PM_JUMP_TO_URL: + return go_to((LPCTSTR)lparam)? TRUE: FALSE; + + default: + return super::WndProc(nmsg, wparam, lparam); + } + + return 0; +} + + +bool ChildWindow::go_to(LPCTSTR url) +{ + const String& url_str = jump_to_int(url); + + if (!url_str.empty()) { + set_url(url_str); + + _url_history.push(url_str); + + return true; + } else + return false; +} + +void ChildWindow::set_url(LPCTSTR url) +{ + if (_url != url) { + _url = url; + + SendMessage(_hwndFrame, PM_URL_CHANGED, 0, (LPARAM)url); + } +} + + +WindowSet Window::s_pretranslate_windows; + +void Window::register_pretranslate(HWND hwnd) +{ + s_pretranslate_windows.insert(hwnd); +} + +void Window::unregister_pretranslate(HWND hwnd) +{ + s_pretranslate_windows.erase(hwnd); +} + +BOOL Window::pretranslate_msg(LPMSG pmsg) +{ + for(WindowSet::const_iterator it=Window::s_pretranslate_windows.begin(); it!=s_pretranslate_windows.end(); ++it) + if (SendMessage(*it, PM_TRANSLATE_MSG, 0, (LPARAM)pmsg)) + return TRUE; + + return FALSE; +} + + +WindowSet Window::s_dialogs; + +void Window::register_dialog(HWND hwnd) +{ + s_dialogs.insert(hwnd); +} + +void Window::unregister_dialog(HWND hwnd) +{ + s_dialogs.erase(hwnd); +} + +BOOL Window::dispatch_dialog_msg(MSG* pmsg) +{ + for(WindowSet::const_iterator it=Window::s_dialogs.begin(); it!=s_dialogs.end(); ++it) + if (IsDialogMessage(*it, pmsg)) + return TRUE; + + return FALSE; +} + + +int Window::MessageLoop() +{ + MSG msg; + + while(GetMessage(&msg, 0, 0, 0)) { + try { + if (pretranslate_msg(&msg)) + continue; + + if (dispatch_dialog_msg(&msg)) + continue; + + TranslateMessage(&msg); + + try { + DispatchMessage(&msg); + } catch(COMException& e) { + HandleException(e, 0); + } + } catch(COMException& e) { + HandleException(e, 0); + } + } + + return msg.wParam; +} + + +LRESULT Window::SendParent(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + HWND parent = GetParent(_hwnd); + + if (!parent) + return 0; + + return SendMessage(parent, nmsg, wparam, lparam); +} + +LRESULT Window::PostParent(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + HWND parent = GetParent(_hwnd); + + if (!parent) + return 0; + + return PostMessage(parent, nmsg, wparam, lparam); +} + + +PreTranslateWindow::PreTranslateWindow(HWND hwnd) + : super(hwnd) +{ + register_pretranslate(hwnd); +} + +PreTranslateWindow::~PreTranslateWindow() +{ + unregister_pretranslate(_hwnd); +} + + +Dialog::Dialog(HWND hwnd) + : super(hwnd) +{ + register_dialog(hwnd); +} + +Dialog::~Dialog() +{ + unregister_dialog(_hwnd); +} + +int Dialog::DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent) +{ + Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info + + s_window_creator = creator; + s_new_info = NULL; + + ///@todo call Window::pretranslate_msg() + + return DialogBoxParam(g_hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/); +} + +int Dialog::DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent) +{ + Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info + + s_window_creator = (CREATORFUNC) creator; + s_new_info = NULL; + + ///@todo call Window::pretranslate_msg() + + return DialogBoxParam(g_hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/); +} + +INT_PTR CALLBACK Window::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + Window* pThis = get_window(hwnd); + + if (pThis) { + switch(nmsg) { + case WM_COMMAND: + pThis->Command(LOWORD(wparam), HIWORD(wparam)); + return TRUE; // message has been processed + + case WM_NOTIFY: + pThis->Notify(wparam, (NMHDR*)lparam); + return TRUE; // message has been processed + + case WM_NOTIFYFORMAT: + SetWindowLong(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT + return TRUE; // message has been processed + + case WM_NCDESTROY: + delete pThis; + return TRUE; // message has been processed + + default: + return pThis->WndProc(nmsg, wparam, lparam); + } + } else if (nmsg == WM_INITDIALOG) { + pThis = create_controller(hwnd); + + if (pThis) + return pThis->Init(NULL); + } + + return FALSE; // message has not been processed +} + +LRESULT Dialog::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + return FALSE; // message has not been processed +} + +int Dialog::Command(int id, int code) +{ + if (code == BN_CLICKED) { + EndDialog(_hwnd, id); + return 0; // message has been processed + } + + return 1; +} + + +ResizeManager::ResizeManager(HWND hwnd) + : _hwnd(hwnd) +{ + ClientRect clnt(hwnd); + _last_size.cx = clnt.right; + _last_size.cy = clnt.bottom; + + WindowRect rect(hwnd); + _min_wnd_size.cx = rect.right - rect.left; + _min_wnd_size.cy = rect.bottom - rect.top; +} + +void ResizeManager::HandleSize(int cx, int cy) +{ + ClientRect clnt_rect(_hwnd); + SIZE new_size = {cx, cy}; + + int dx = new_size.cx - _last_size.cx; + int dy = new_size.cy - _last_size.cy; + + if (!dx && !dy) + return; + + _last_size = new_size; + + HDWP hDWP = BeginDeferWindowPos(size()); + + for(ResizeManager::const_iterator it=begin(); it!=end(); ++it) { + const ResizeEntry& e = *it; + RECT move = {0}; + + if (e._flags & MOVE_LEFT) + move.left += dx; + + if (e._flags & MOVE_RIGHT) + move.right += dx; + + if (e._flags & MOVE_TOP) + move.top += dy; + + if (e._flags & MOVE_BOTTOM) + move.bottom += dy; + + UINT flags = 0; + + if (!move.left && !move.top) + flags = SWP_NOMOVE; + + if (move.right==move.left && move.bottom==move.top) + flags |= SWP_NOSIZE; + + if (flags != (SWP_NOMOVE|SWP_NOSIZE)) { + HWND hwnd = GetDlgItem(_hwnd, e._id); + + if (hwnd) { + WindowRect rect(hwnd); + ScreenToClient(_hwnd, rect); + + rect.left += move.left; + rect.right += move.right; + rect.top += move.top; + rect.bottom += move.bottom; + + hDWP = DeferWindowPos(hDWP, hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, flags|SWP_NOACTIVATE|SWP_NOZORDER); + } + } + } + + EndDeferWindowPos(hDWP); +} + +void ResizeManager::Resize(int dx, int dy) +{ + ::SetWindowPos(_hwnd, 0, 0, 0, _min_wnd_size.cx+dx, _min_wnd_size.cy+dy, SWP_NOMOVE|SWP_NOACTIVATE); + MoveVisible(_hwnd); + + ClientRect clnt_rect(_hwnd); + HandleSize(clnt_rect.right, clnt_rect.bottom); +} + + +Button::Button(HWND parent, LPCTSTR title, int left, int top, int width, int height, + int id, DWORD flags, DWORD exStyle) + : WindowHandle(CreateWindowEx(exStyle, TEXT("BUTTON"), title, flags, left, top, width, height, + parent, (HMENU)id, g_hInstance, 0)) +{ +} + + +LRESULT OwnerdrawnButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + if (nmsg == PM_DISPATCH_DRAWITEM) { + DrawItem((LPDRAWITEMSTRUCT)lparam); + return TRUE; + } else + return super::WndProc(nmsg, wparam, lparam); +} + + +Static::Static(HWND parent, LPCTSTR title, int left, int top, int width, int height, + int id, DWORD flags, DWORD exStyle) + : WindowHandle(CreateWindowEx(exStyle, TEXT("STATIC"), title, flags, left, top, width, height, + parent, (HMENU)id, g_hInstance, 0)) +{ +} + + +static RECT s_MyDrawText_Rect = {0, 0, 0, 0}; + +static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt) +{ + ::DrawText(hdc, (LPCTSTR)data, cnt, &s_MyDrawText_Rect, DT_SINGLELINE); + return TRUE; +} + +void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR title, int dt_flags) +{ + COLORREF gray = GetSysColor(COLOR_GRAYTEXT); + + if (gray) { + TextColor lcColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT)); + RECT shadowRect = {pRect->left+1, pRect->top+1, pRect->right+1, pRect->bottom+1}; + DrawText(hdc, title, -1, &shadowRect, dt_flags); + + SetTextColor(hdc, gray); + DrawText(hdc, title, -1, pRect, dt_flags); + } else { + int old_r = pRect->right; + int old_b = pRect->bottom; + + DrawText(hdc, title, -1, pRect, dt_flags|DT_CALCRECT); + + int x = pRect->left + (old_r-pRect->right)/2; + int y = pRect->top + (old_b-pRect->bottom)/2; + int w = pRect->right-pRect->left; + int h = pRect->bottom-pRect->top; + s_MyDrawText_Rect.right = w; + s_MyDrawText_Rect.bottom = h; + + GrayString(hdc, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)title, -1, x, y, w, h); + } +} + + +/* not yet used +void ColorButton::DrawItem(LPDRAWITEMSTRUCT dis) +{ + UINT state = DFCS_BUTTONPUSH; + + if (dis->itemState & ODS_DISABLED) + state |= DFCS_INACTIVE; + + RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4}; + + if (dis->itemState & ODS_SELECTED) { + state |= DFCS_PUSHED; + ++textRect.left; ++textRect.top; + ++textRect.right; ++textRect.bottom; + } + + DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state); + + TCHAR title[BUFFER_LEN]; + GetWindowText(_hwnd, title, BUFFER_LEN); + + BkMode bk_mode(dis->hDC, TRANSPARENT); + + if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) + DrawGrayText(dis, &textRect, title, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + else { + TextColor lcColor(dis->hDC, _textColor); + DrawText(dis->hDC, title, -1, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } + + if (dis->itemState & ODS_FOCUS) { + RECT rect = { + dis->rcItem.left+3, dis->rcItem.top+3, + dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 + }; + if (dis->itemState & ODS_SELECTED) { + ++rect.left; ++rect.top; + ++rect.right; ++rect.bottom; + } + DrawFocusRect(dis->hDC, &rect); + } +} +*/ + + +void PictureButton::DrawItem(LPDRAWITEMSTRUCT dis) +{ + UINT state = DFCS_BUTTONPUSH; + int style = GetWindowStyle(_hwnd); + + if (dis->itemState & ODS_DISABLED) + state |= DFCS_INACTIVE; + + POINT imagePos; + RECT textRect; + int dt_flags; + + if (style & BS_BOTTOM) { + // align horizontal centered, vertical floating + imagePos.x = (dis->rcItem.left + dis->rcItem.right - _cx) / 2; + imagePos.y = dis->rcItem.top + 3; + + textRect.left = dis->rcItem.left + 2; + textRect.top = dis->rcItem.top + _cy + 4; + textRect.right = dis->rcItem.right - 4; + textRect.bottom = dis->rcItem.bottom - 4; + + dt_flags = DT_SINGLELINE|DT_CENTER|DT_VCENTER; + } else { + // horizontal floating, vertical centered + imagePos.x = dis->rcItem.left + 3; + imagePos.y = (dis->rcItem.top + dis->rcItem.bottom - _cy)/2; + + textRect.left = dis->rcItem.left + _cx + 4; + textRect.top = dis->rcItem.top + 2; + textRect.right = dis->rcItem.right - 4; + textRect.bottom = dis->rcItem.bottom - 4; + + dt_flags = DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/; + } + + if (dis->itemState & ODS_SELECTED) { + state |= DFCS_PUSHED; + ++imagePos.x; ++imagePos.y; + ++textRect.left; ++textRect.top; + ++textRect.right; ++textRect.bottom; + } + + if (_flat) { + FillRect(dis->hDC, &dis->rcItem, _hBrush); + + if (style & BS_FLAT) // Only with BS_FLAT set, there will be drawn a frame without highlight. + DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT); + } else + DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state); + + if (_hIcon) + DrawIconEx(dis->hDC, imagePos.x, imagePos.y, _hIcon, _cx, _cy, 0, _hBrush, DI_NORMAL); + else { + MemCanvas mem_dc; + BitmapSelection sel(mem_dc, _hBmp); + BitBlt(dis->hDC, imagePos.x, imagePos.y, _cx, _cy, mem_dc, 0, 0, SRCCOPY); + } + + TCHAR title[BUFFER_LEN]; + GetWindowText(_hwnd, title, BUFFER_LEN); + + BkMode bk_mode(dis->hDC, TRANSPARENT); + + if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) + DrawGrayText(dis->hDC, &textRect, title, dt_flags); + else { + TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNTEXT)); + DrawText(dis->hDC, title, -1, &textRect, dt_flags); + } + + if (dis->itemState & ODS_FOCUS) { + RECT rect = { + dis->rcItem.left+3, dis->rcItem.top+3, + dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 + }; + if (dis->itemState & ODS_SELECTED) { + ++rect.left; ++rect.top; + ++rect.right; ++rect.bottom; + } + DrawFocusRect(dis->hDC, &rect); + } +} + + +void FlatButton::DrawItem(LPDRAWITEMSTRUCT dis) +{ + UINT style = DFCS_BUTTONPUSH; + + if (dis->itemState & ODS_DISABLED) + style |= DFCS_INACTIVE; + + RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4}; + + if (dis->itemState & ODS_SELECTED) { + style |= DFCS_PUSHED; + ++textRect.left; ++textRect.top; + ++textRect.right; ++textRect.bottom; + } + + FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_BTNFACE)); + + // highlight the button? + if (_active) + DrawEdge(dis->hDC, &dis->rcItem, EDGE_ETCHED, BF_RECT); + else if (GetWindowStyle(_hwnd) & BS_FLAT) // Only with BS_FLAT there will be drawn a frame to show highlighting. + DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT); + + TCHAR txt[BUFFER_LEN]; + int txt_len = GetWindowText(_hwnd, txt, BUFFER_LEN); + + if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) { + COLORREF gray = GetSysColor(COLOR_GRAYTEXT); + + if (gray) { + { + TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNHIGHLIGHT)); + RECT shadowRect = {textRect.left+1, textRect.top+1, textRect.right+1, textRect.bottom+1}; + DrawText(dis->hDC, txt, txt_len, &shadowRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } + + BkMode mode(dis->hDC, TRANSPARENT); + TextColor lcColor(dis->hDC, gray); + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } else { + int old_r = textRect.right; + int old_b = textRect.bottom; + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_CALCRECT); + int x = textRect.left + (old_r-textRect.right)/2; + int y = textRect.top + (old_b-textRect.bottom)/2; + int w = textRect.right-textRect.left; + int h = textRect.bottom-textRect.top; + s_MyDrawText_Rect.right = w; + s_MyDrawText_Rect.bottom = h; + GrayString(dis->hDC, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)txt, txt_len, x, y, w, h); + } + } else { + TextColor lcColor(dis->hDC, _active? _activeColor: _textColor); + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } + + if (dis->itemState & ODS_FOCUS) { + RECT rect = { + dis->rcItem.left+3, dis->rcItem.top+3, + dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 + }; + if (dis->itemState & ODS_SELECTED) { + ++rect.left; ++rect.top; + ++rect.right; ++rect.bottom; + } + DrawFocusRect(dis->hDC, &rect); + } +} + +LRESULT FlatButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + switch(nmsg) { + case WM_MOUSEMOVE: { + bool active = false; + + if (IsWindowEnabled(_hwnd)) { + DWORD pid_foreground; + HWND hwnd_foreground = GetForegroundWindow(); //@@ may be better look for WM_ACTIVATEAPP ? + GetWindowThreadProcessId(hwnd_foreground, &pid_foreground); + + if (GetCurrentProcessId() == pid_foreground) { + POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + ClientRect clntRect(_hwnd); + + // highlight the button? + if (pt.x>=clntRect.left && pt.x=clntRect.top && pt.y=clntRect.right || pt.y=clntRect.bottom) + goto cancel_press; + + goto def;} + + case WM_CANCELMODE: + cancel_press: { + TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE|TME_CANCEL, _hwnd/*, HOVER_DEFAULT*/}; + _TrackMouseEvent(&tme); + _active = false; + ReleaseCapture();} + // fall through + + case WM_MOUSELEAVE: + if (_active) { + _active = false; + + InvalidateRect(_hwnd, NULL, TRUE); + } + + return 0; + + default: def: + return super::WndProc(nmsg, wparam, lparam); + } +} + + +HyperlinkCtrl::HyperlinkCtrl(HWND hwnd, COLORREF colorLink, COLORREF colorVisited) + : super(hwnd), + _cmd(ResString(GetDlgCtrlID(hwnd))), + _textColor(colorLink), + _colorVisited(colorVisited), + _hfont(0), + _crsr_link(0) +{ + init(); +} + +HyperlinkCtrl::HyperlinkCtrl(HWND owner, int id, COLORREF colorLink, COLORREF colorVisited) + : super(GetDlgItem(owner, id)), + _cmd(ResString(id)), + _textColor(colorLink), + _colorVisited(colorVisited), + _hfont(0), + _crsr_link(0) +{ + init(); +} + +void HyperlinkCtrl::init() +{ + if (_cmd.empty()) { + TCHAR txt[BUFFER_LEN]; + _cmd.assign(txt, GetWindowText(_hwnd, txt, BUFFER_LEN)); + } +} + +HyperlinkCtrl::~HyperlinkCtrl() +{ + if (_hfont) + DeleteObject(_hfont); +} + +LRESULT HyperlinkCtrl::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + switch(nmsg) { + case PM_DISPATCH_CTLCOLOR: { + if (!_hfont) { + HFONT hfont = (HFONT) SendMessage(_hwnd, WM_GETFONT, 0, 0); + LOGFONT lf; GetObject(hfont, sizeof(lf), &lf); + lf.lfUnderline = TRUE; + _hfont = CreateFontIndirect(&lf); + } + + HDC hdc = (HDC) wparam; + SetTextColor(hdc, _textColor); //@@ + SelectFont(hdc, _hfont); + SetBkMode(hdc, TRANSPARENT); + return (LRESULT)GetStockObject(HOLLOW_BRUSH); + } + + case WM_SETCURSOR: + if (!_crsr_link) + _crsr_link = LoadCursor(0, IDC_HAND); + + if (_crsr_link) + SetCursor(_crsr_link); + return 0; + + case WM_NCHITTEST: + return HTCLIENT; // Aktivierung von Maus-Botschaften + + case WM_LBUTTONDOWN: + if (LaunchLink()) { + _textColor = _colorVisited; + InvalidateRect(_hwnd, NULL, FALSE); + } else + MessageBeep(0); + return 0; + + default: + return super::WndProc(nmsg, wparam, lparam); + } +} + + +ToolTip::ToolTip(HWND owner) + : super(CreateWindowEx(WS_EX_TOPMOST|WS_EX_NOPARENTNOTIFY, TOOLTIPS_CLASS, 0, + WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, + owner, 0, g_hInstance, 0)) +{ + activate(); +} + + +ListSort::ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct) + : WindowHandle(hwndListview), + _compare_fct(compare_fct) +{ + _sort_crit = 0; + _direction = false; +} + +void ListSort::toggle_sort(int idx) +{ + if (_sort_crit == idx) + _direction = !_direction; + else { + _sort_crit = idx; + _direction = false; + } +} + +void ListSort::sort() +{ + int idx = ListView_GetSelectionMark(_hwnd); + LPARAM param = ListView_GetItemData(_hwnd, idx); + + ListView_SortItems(_hwnd, _compare_fct, (LPARAM)this); + + if (idx >= 0) { + idx = ListView_FindItemPara(_hwnd, param); + ListView_EnsureVisible(_hwnd, idx, FALSE); + } +} + + +PropSheetPage::PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator) + : _dlg_creator(dlg_creator) +{ + PROPSHEETPAGE::dwSize = sizeof(PROPSHEETPAGE); + PROPSHEETPAGE::dwFlags = 0; + PROPSHEETPAGE::hInstance = g_hInstance; + PROPSHEETPAGE::pszTemplate = MAKEINTRESOURCE(nid); + PROPSHEETPAGE::pfnDlgProc = PropSheetPageDlg::DialogProc; + PROPSHEETPAGE::lParam = (LPARAM) this; +} + + +#ifndef PSM_GETRESULT // currently (as of 18.01.2004) missing in MinGW headers +#define PSM_GETRESULT (WM_USER + 135) +#define PropSheet_GetResult(hDlg) SNDMSG(hDlg, PSM_GETRESULT, 0, 0) +#endif + + +PropertySheetDialog::PropertySheetDialog(HWND owner) + : _hwnd(0) +{ + PROPSHEETHEADER::dwSize = sizeof(PROPSHEETHEADER); + PROPSHEETHEADER::dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + PROPSHEETHEADER::hwndParent = owner; + PROPSHEETHEADER::hInstance = g_hInstance; +} + +void PropertySheetDialog::add(PropSheetPage& psp) +{ + _pages.push_back(psp); +} + +int PropertySheetDialog::DoModal(int start_page) +{ + PROPSHEETHEADER::ppsp = (LPCPROPSHEETPAGE) &_pages[0]; + PROPSHEETHEADER::nPages = _pages.size(); + PROPSHEETHEADER::nStartPage = start_page; +/* + Window* pwnd = Window::create_property_sheet(this, WINDOW_CREATOR(PropertySheetDlg), NULL); + if (!pwnd) + return -1; + + HWND hwndPropSheet = *pwnd; +*/ + int ret = PropertySheet(this); + if (ret == -1) + return -1; + + HWND hwndPropSheet = (HWND) ret; + HWND hwndparent = GetParent(hwndPropSheet); + + if (hwndparent) + EnableWindow(hwndparent, FALSE); + + ret = 0; + MSG msg; + + while(GetMessage(&msg, 0, 0, 0)) { + try { + if (Window::pretranslate_msg(&msg)) + continue; + + if (PropSheet_IsDialogMessage(hwndPropSheet, &msg)) + continue; + + if (Window::dispatch_dialog_msg(&msg)) + continue; + + TranslateMessage(&msg); + + try { + DispatchMessage(&msg); + } catch(COMException& e) { + HandleException(e, 0); + } + + if (!PropSheet_GetCurrentPageHwnd(hwndPropSheet)) { + ret = PropSheet_GetResult(hwndPropSheet); + break; + } + } catch(COMException& e) { + HandleException(e, 0); + } + } + + if (hwndparent) + EnableWindow(hwndparent, TRUE); + + DestroyWindow(hwndPropSheet); + + return ret; +} + +HWND PropertySheetDialog::GetCurrentPage() +{ + HWND hdlg = PropSheet_GetCurrentPageHwnd(_hwnd); + return hdlg; +} + + +PropSheetPageDlg::PropSheetPageDlg(HWND hwnd) + : super(hwnd) +{ +} + +INT_PTR CALLBACK PropSheetPageDlg::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + PropSheetPageDlg* pThis = GET_WINDOW(PropSheetPageDlg, hwnd); + + if (pThis) { + switch(nmsg) { + case WM_COMMAND: + pThis->Command(LOWORD(wparam), HIWORD(wparam)); + return TRUE; // message has been processed + + case WM_NOTIFY: + pThis->Notify(wparam, (NMHDR*)lparam); + return TRUE; // message has been processed + + case WM_NOTIFYFORMAT: + SetWindowLong(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT + return TRUE; // message has been processed + + case WM_NCDESTROY: + delete pThis; + return TRUE; // message has been processed + + default: + return pThis->WndProc(nmsg, wparam, lparam); + } + } else if (nmsg == WM_INITDIALOG) { + PROPSHEETPAGE* psp = (PROPSHEETPAGE*) lparam; + PropSheetPage* ppsp = (PropSheetPage*) psp->lParam; + + if (ppsp->_dlg_creator) { + pThis = static_cast(ppsp->_dlg_creator(hwnd)); + + if (pThis) + return pThis->Init(NULL); + } + } + + return FALSE; // message has not been processed +} + +int PropSheetPageDlg::Command(int id, int code) +{ + // override call to EndDialog in Dialog::Command(); + + return FALSE; +} diff --git a/reactos/subsys/system/ibrowser/utility/window.h b/reactos/subsys/system/ibrowser/utility/window.h new file mode 100644 index 00000000000..bd568797aaf --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/window.h @@ -0,0 +1,1100 @@ +/* + * Copyright 2003, 2004, 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // window.h + // + // Martin Fuchs, 23.07.2003 + // + + +typedef set WindowSet; + + + /* + Classes are declared using "struct", not "class" because the default + access mode is "public". This way we can list the member functions in a + natural order without explicitly specifying any access mode at the begin + of the definition. + First are public constructors and destructor, then public member functions. + After that we list protected member varibables and functions. If needed, + private implemenation varibales and functions are positioned at the end. + */ + + + /// information structure for creation of a child window +struct ChildWndInfo +{ + ChildWndInfo(HWND hwndFrame) + : _hwndFrame(hwndFrame) {} + + HWND _hwndFrame; +}; + + + /** + Class Window is the base class for several C++ window wrapper classes. + Window objects are allocated from the heap. They are automatically freed + when the window gets destroyed. + */ +struct Window : public WindowHandle +{ + Window(HWND hwnd); + virtual ~Window(); + + + typedef map WindowMap; + + typedef Window* (*CREATORFUNC)(HWND); + typedef Window* (*CREATORFUNC_INFO)(HWND, const void*); + + static HWND Create(CREATORFUNC creator, DWORD dwExStyle, + LPCTSTR lpClassName, LPCTSTR lpWindowName, + DWORD dwStyle, int x, int y, int w, int h, + HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/); + + static HWND Create(CREATORFUNC_INFO creator, const void* info, + DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, + DWORD dwStyle, int x, int y, int w, int h, + HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/); + + static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); + static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); + + static Window* get_window(HWND hwnd); +#ifndef _MSC_VER + template static CLASS* get_window(HWND hwnd) {return static_cast(get_window(hwnd));} +#define GET_WINDOW(CLASS, hwnd) Window::get_window(hwnd) +#endif + + static void register_pretranslate(HWND hwnd); + static void unregister_pretranslate(HWND hwnd); + static BOOL pretranslate_msg(LPMSG pmsg); + + static void register_dialog(HWND hwnd); + static void unregister_dialog(HWND hwnd); + static BOOL dispatch_dialog_msg(LPMSG pmsg); + + static int MessageLoop(); + + + LRESULT SendParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0); + LRESULT PostParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0); + + static void CancelModes(HWND hwnd=0); + + +protected: + virtual LRESULT Init(LPCREATESTRUCT pcs); // WM_CREATE processing + virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + virtual int Command(int id, int code); // WM_COMMAND processing + virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing + + static Window* create_controller(HWND hwnd); + + + static WindowMap s_wnd_map; + + static const void* s_new_info; + static CREATORFUNC s_window_creator; + + + /// structure for managing critical sections as static class information in struct Window + struct StaticWindowData { + CritSect _map_crit_sect; + CritSect _create_crit_sect; + }; + + static StaticWindowData& GetStaticWindowData(); + + + static WindowSet s_pretranslate_windows; + static WindowSet s_dialogs; +}; + +#ifdef UNICODE +#define NFR_CURRENT NFR_UNICODE +#else +#define NFR_CURRENT NFR_ANSI +#endif + + +#ifdef _MSC_VER +template struct GetWindowHelper +{ + static CLASS* get_window(HWND hwnd) { + return static_cast(Window::get_window(hwnd)); + } +}; +#define GET_WINDOW(CLASS, hwnd) GetWindowHelper::get_window(hwnd) +#endif + + + /// dynamic casting of Window pointers +template struct TypeCheck +{ + static CLASS* dyn_cast(Window* wnd) + {return dynamic_cast(wnd);} +}; + +#define WINDOW_DYNAMIC_CAST(CLASS, hwnd) \ + TypeCheck::dyn_cast(Window::get_window(hwnd)) + + + /** + SubclassedWindow is used to wrap already existing window handles + into C++ Window objects. To construct a object, use the "new" operator + to put it in the heap. It is automatically freed, when the window + gets destroyed. + */ +struct SubclassedWindow : public Window +{ + typedef Window super; + + SubclassedWindow(HWND); + +protected: + WNDPROC _orgWndProc; + + static LRESULT CALLBACK SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); + + virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + virtual int Command(int id, int code); + virtual int Notify(int id, NMHDR* pnmh); +}; + + + /// template class used in macro WINDOW_CREATOR to define the creater functions for Window objects +template struct WindowCreator +{ + static WND_CLASS* window_creator(HWND hwnd) + { + return new WND_CLASS(hwnd); + } +}; + +#define WINDOW_CREATOR(WND_CLASS) \ + ((Window::CREATORFUNC) WindowCreator::window_creator) + + + /// template class used in macro WINDOW_CREATOR_INFO to the define creater functions for Window objects with additional creation information +template struct WindowCreatorInfo +{ + static WND_CLASS* window_creator(HWND hwnd, const void* info) + { + return new WND_CLASS(hwnd, *static_cast(info)); + } +}; + +#define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \ + ((Window::CREATORFUNC_INFO) WindowCreatorInfo::window_creator) + + + /** + WindowClass is a neat wrapper for RegisterClassEx(). + Just construct a WindowClass object, override the attributes you want + to change, then call Register() or simply request the ATOM value to + register the window class. You don't have to worry calling Register() + more than once. It checks if, the class has already been registered. + */ +struct WindowClass : public WNDCLASSEX +{ + WindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc); + + ATOM Register() + { + if (!_atomClass) + _atomClass = RegisterClassEx(this); + + return _atomClass; + } + + operator ATOM() {return Register();} + + // return LPCTSTR for the CreateWindowEx() parameter + operator LPCTSTR() {return (LPCTSTR)(int)Register();} + +protected: + ATOM _atomClass; +}; + + /// window class with gray background color +struct BtnWindowClass : public WindowClass +{ + BtnWindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc) + : WindowClass(classname, style, wndproc) + { + hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); + } +}; + + /// window class with specified icon from resources +struct IconWindowClass : public WindowClass +{ + IconWindowClass(LPCTSTR classname, UINT nid, UINT style=0, WNDPROC wndproc=Window::WindowWndProc); +}; + + + // private message constants +#define PM_DISPATCH_COMMAND (WM_APP+0x00) +#define PM_TRANSLATE_MSG (WM_APP+0x01) + + +#define SPLIT_WIDTH 5 +#define DEFAULT_SPLIT_POS 300 +#define COLOR_SPLITBAR LTGRAY_BRUSH + + + /// menu info structure +struct MenuInfo +{ + HMENU _hMenuView; +}; + +#define PM_FRM_GET_MENUINFO (WM_APP+0x02) + +#define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0)) + + + /** + Class ChildWindow is used with class MainFrame. + */ +struct ChildWindow : public Window +{ + typedef Window super; + + ChildWindow(HWND hwnd, HWND hwndFrame); + + static ChildWindow* create(const ChildWndInfo& info, CREATORFUNC_INFO creator, + LPCTSTR classname, LPCTSTR title=NULL, DWORD style=0); + + bool go_to(LPCTSTR url); + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + + virtual String jump_to_int(LPCTSTR url) = 0; + +protected: + MenuInfo*_menu_info; + + HWND _hwndFrame; + String _statusText; + String _url; + + stack _url_history; + + void set_url(LPCTSTR url); +}; + +#define PM_SETSTATUSTEXT (WM_APP+0x1E) + + + /** + PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg(). + This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages. + You can then for example use TranslateAccelerator() to implement key shortcuts. + */ +struct PreTranslateWindow : public Window +{ + typedef Window super; + + PreTranslateWindow(HWND); + ~PreTranslateWindow(); +}; + + + /** + The class DialogWindow implements modeless dialogs, which are managed by + Window::dispatch_dialog_msg() in Window::MessageLoop(). + A DialogWindow object should be constructed by calling Window::Create() + and specifying the class using the WINDOW_CREATOR() macro. + */ +struct DialogWindow : public Window +{ + typedef Window super; + + DialogWindow(HWND hwnd) + : super(hwnd) + { + register_dialog(hwnd); + } + + ~DialogWindow() + { + unregister_dialog(_hwnd); + } +}; + + + /** + The class Dialog implements modal dialogs. + A Dialog object should be constructed by calling Dialog::DoModal() + and specifying the class using the WINDOW_CREATOR() macro. + */ +struct Dialog : public Window +{ + typedef Window super; + + Dialog(HWND); + ~Dialog(); + + static int DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent=0); + static int DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent=0); + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + int Command(int id, int code); +}; + + +#define PM_FRM_CALC_CLIENT (WM_APP+0x03) +#define Frame_CalcFrameClient(hwnd, prt) ((BOOL)SNDMSG(hwnd, PM_FRM_CALC_CLIENT, 0, (LPARAM)(PRECT)prt)) + +#define PM_JUMP_TO_URL (WM_APP+0x25) +#define PM_URL_CHANGED (WM_APP+0x26) + + +struct PropSheetPage : public PROPSHEETPAGE +{ + PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator); + + void init(struct PropertySheetDialog*); + +protected: + friend struct PropSheetPageDlg; + + Window::CREATORFUNC _dlg_creator; +}; + + + /// Property Sheet dialog +struct PropertySheetDialog : public PROPSHEETHEADER +{ + PropertySheetDialog(HWND owner); + + void add(PropSheetPage& psp); + int DoModal(int start_page=0); + + HWND GetCurrentPage(); + +protected: + typedef vector Vector; + Vector _pages; + HWND _hwnd; +}; + + + /// Property Sheet Page (inner dialog) +struct PropSheetPageDlg : public Dialog +{ + typedef Dialog super; + + PropSheetPageDlg(HWND); + +protected: + friend struct PropertySheetDialog; + friend struct PropSheetPage; + + static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); + + int Command(int id, int code); +}; + + +/* + /// Property Sheet Dialog (outer dialog) +struct PropertySheetDlg : public SubclassedWindow +{ + typedef SubclassedWindow super; + + PropertySheetDlg(HWND hwnd) : super(hwnd) {} +}; +*/ + + + // Layouting of resizable windows + + /// Flags to specify how to move and resize controls when resizing their parent window +enum RESIZE_FLAGS { + MOVE_LEFT = 0x1, + MOVE_RIGHT = 0x2, + MOVE_TOP = 0x4, + MOVE_BOTTOM = 0x8, + + MOVE_X = MOVE_LEFT | MOVE_RIGHT, + MOVE_Y = MOVE_TOP | MOVE_BOTTOM, + RESIZE_X= MOVE_RIGHT, + RESIZE_Y= MOVE_BOTTOM, + + MOVE = MOVE_X | MOVE_Y, + RESIZE = RESIZE_X | RESIZE_Y +}; + + /// structure to assign RESIZE_FLAGS to dialogs control +struct ResizeEntry +{ + ResizeEntry(UINT id, int flags) + : _id(id), _flags(flags) {} + + ResizeEntry(HWND hwnd, int flags) + : _id(GetDlgCtrlID(hwnd)), _flags(flags) {} + + UINT _id; + int _flags; +}; + + + /// Management of controls in resizable dialogs +struct ResizeManager : public std::list +{ + typedef std::list super; + + ResizeManager(HWND hwnd); + + void Add(UINT id, int flags) + {push_back(ResizeEntry(id, flags));} + + void Add(HWND hwnd, int flags) + {push_back(ResizeEntry(hwnd, flags));} + + void HandleSize(int cx, int cy); + void Resize(int dx, int dy); + + void SetMinMaxInfo(LPMINMAXINFO lpmmi) + { + lpmmi->ptMinTrackSize.x = _min_wnd_size.cx; + lpmmi->ptMinTrackSize.y = _min_wnd_size.cy; + } + + SIZE _min_wnd_size; + +protected: + HWND _hwnd; + SIZE _last_size; +}; + + + /// Controller base template class for resizable dialogs +template struct ResizeController : public BASE +{ + typedef BASE super; + + ResizeController(HWND hwnd) + : super(hwnd), + _resize_mgr(hwnd) + { + } + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case PM_FRM_CALC_CLIENT: + GetClientSpace((PRECT)lparam); + return TRUE; + + case WM_SIZE: + if (wparam != SIZE_MINIMIZED) + _resize_mgr.HandleSize(LOWORD(lparam), HIWORD(lparam)); + goto def; + + case WM_GETMINMAXINFO: + _resize_mgr.SetMinMaxInfo((LPMINMAXINFO)lparam); + goto def; + + default: def: + return super::WndProc(nmsg, wparam, lparam); + } + } + + virtual void GetClientSpace(PRECT prect) + { + if (!IsIconic(this->_hwnd)) { + GetClientRect(this->_hwnd, prect); + } else { + WINDOWPLACEMENT wp; + GetWindowPlacement(this->_hwnd, &wp); + prect->left = prect->top = 0; + prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left- + 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE)); + prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top- + 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))- + GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE); + } + } + +protected: + ResizeManager _resize_mgr; +}; + + + /** + This class constructs button controls. + The button will remain existent when the C++ Button object is destroyed. + There is no conjunction between C++ object and windows control life time. + */ +struct Button : public WindowHandle +{ + Button(HWND parent, LPCTSTR text, int left, int top, int width, int height, + int id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD exStyle=0); +}; + + + /** + This class constructs static controls. + The control will remain existent when the C++ object is destroyed. + There is no conjunction between C++ object and windows control life time. + */ +struct Static : public WindowHandle +{ + Static(HWND parent, LPCTSTR text, int left, int top, int width, int height, + int id, DWORD flags=WS_VISIBLE|WS_CHILD|SS_SIMPLE, DWORD ex_flags=0); +}; + + + // control color message routing for ColorStatic and HyperlinkCtrl + +#define PM_DISPATCH_CTLCOLOR (WM_APP+0x08) + +template struct CtlColorParent : public BASE +{ + typedef BASE super; + + CtlColorParent(HWND hwnd) + : super(hwnd) {} + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case WM_CTLCOLOR: + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: { + HWND hctl = (HWND) lparam; + return SendMessage(hctl, PM_DISPATCH_CTLCOLOR, wparam, nmsg); + } + + default: + return super::WndProc(nmsg, wparam, lparam); + } + } +}; + + +#define PM_DISPATCH_DRAWITEM (WM_APP+0x09) + + /// draw message routing for ColorButton and PictureButton +template struct OwnerDrawParent : public BASE +{ + typedef BASE super; + + OwnerDrawParent(HWND hwnd) + : super(hwnd) {} + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case WM_DRAWITEM: + if (wparam) { // should there be drawn a control? + HWND hctl = GetDlgItem(this->_hwnd, wparam); + + if (hctl) + return SendMessage(hctl, PM_DISPATCH_DRAWITEM, wparam, lparam); + } /*else // or is it a menu entry? + ; */ + + return 0; + + default: + return super::WndProc(nmsg, wparam, lparam); + } + } +}; + + + /** + Subclass button controls to draw them by using PM_DISPATCH_DRAWITEM + The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. + */ +struct OwnerdrawnButton : public SubclassedWindow +{ + typedef SubclassedWindow super; + + OwnerdrawnButton(HWND hwnd) + : super(hwnd) {} + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + + virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0; +}; + +extern void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR text, int dt_flags); + + + /** + Subclass button controls to paint colored text labels. + The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. + */ +/* not yet used +struct ColorButton : public OwnerdrawnButton +{ + typedef OwnerdrawnButton super; + + ColorButton(HWND hwnd, COLORREF textColor) + : super(hwnd), _textColor(textColor) {} + +protected: + virtual void DrawItem(LPDRAWITEMSTRUCT dis); + + COLORREF _textColor; +}; +*/ + + +struct FlatButton : public OwnerdrawnButton +{ + typedef OwnerdrawnButton super; + + FlatButton(HWND hwnd) + : super(hwnd), _active(false) {} + + FlatButton(HWND owner, int id) + : super(GetDlgItem(owner, IDOK)), _active(false) {} + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + virtual void DrawItem(LPDRAWITEMSTRUCT dis); + + COLORREF _textColor; + COLORREF _activeColor; + bool _active; +}; + + + /** + Subclass button controls to paint pictures left to the labels. + The buttons should have set the style bit BS_OWNERDRAW. + The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. + */ +struct PictureButton : public OwnerdrawnButton +{ + typedef OwnerdrawnButton super; + + PictureButton(HWND hwnd, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) + : super(hwnd), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat) + { + _cx = 16; + _cy = 16; + } + + PictureButton(HWND hparent, int id, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) + : super(GetDlgItem(hparent, id)), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat) + { + _cx = 16; + _cy = 16; + } + + PictureButton(HWND hwnd, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) + : super(hwnd), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat) + { + BITMAP bmp; + GetObject(hBmp, sizeof(bmp), &bmp); + _cx = bmp.bmWidth; + _cy = bmp.bmHeight; + } + + PictureButton(HWND hparent, int id, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) + : super(GetDlgItem(hparent, id)), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat) + { + BITMAP bmp; + GetObject(hBmp, sizeof(bmp), &bmp); + _cx = bmp.bmWidth; + _cy = bmp.bmHeight; + } + +protected: + virtual void DrawItem(LPDRAWITEMSTRUCT dis); + + HICON _hIcon; + HBITMAP _hBmp; + HBRUSH _hBrush; + + int _cx; + int _cy; + + bool _flat; +}; + + +struct ColorStatic : public SubclassedWindow +{ + typedef SubclassedWindow super; + + ColorStatic(HWND hwnd, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) + : super(hwnd), + _textColor(textColor), + _hbrush_bkgnd(hbrush_bkgnd), + _hfont(hfont) + { + } + + ColorStatic(HWND owner, int id, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) + : super(GetDlgItem(owner, id)), + _textColor(textColor), + _hbrush_bkgnd(hbrush_bkgnd), + _hfont(hfont) + { + } + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + if (nmsg == PM_DISPATCH_CTLCOLOR) { + HDC hdc = (HDC) wparam; + + SetTextColor(hdc, _textColor); + + if (_hfont) + SelectFont(hdc, _hfont); + + if (_hbrush_bkgnd) + return (LRESULT)_hbrush_bkgnd; + else { + SetBkMode(hdc, TRANSPARENT); + return (LRESULT)GetStockBrush(HOLLOW_BRUSH); + } + } else + return super::WndProc(nmsg, wparam, lparam); + } + + COLORREF _textColor; + HBRUSH _hbrush_bkgnd; + HFONT _hfont; +}; + + + /// Hyperlink Controls + +struct HyperlinkCtrl : public SubclassedWindow +{ + typedef SubclassedWindow super; + + HyperlinkCtrl(HWND hwnd, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); + HyperlinkCtrl(HWND owner, int id, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); + + ~HyperlinkCtrl(); + + String _cmd; + +protected: + COLORREF _textColor; + COLORREF _colorVisited; + HFONT _hfont; + HCURSOR _crsr_link; + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + + void init(); + + bool LaunchLink() + { + if (!_cmd.empty()) { + HINSTANCE hinst = ShellExecute(GetParent(_hwnd), _T("open"), _cmd, 0, 0, SW_SHOWNORMAL); + return (int)hinst > HINSTANCE_ERROR; + } + + return true; + } +}; + + + /// encapsulation of tool tip controls +struct ToolTip : public WindowHandle +{ + typedef WindowHandle super; + + ToolTip(HWND owner); + + void activate(BOOL active=TRUE) + { + SendMessage(_hwnd, TTM_ACTIVATE, active, 0); + } + + void add(HWND hparent, HWND htool, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0) + { + TOOLINFO ti = { + sizeof(TOOLINFO), TTF_SUBCLASS|TTF_IDISHWND|TTF_TRANSPARENT, hparent, (UINT)htool, + {0,0,0,0}, 0, (LPTSTR)txt, lparam + }; + +#ifdef UNICODE ///@todo Why is it neccesary to try both TTM_ADDTOOLW and TTM_ADDTOOLW ?! + if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti)) + SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); +#else + if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti)) + SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti); +#endif + } + + void add(HWND hparent, UINT id, const RECT& rect, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0) + { + TOOLINFO ti = { + sizeof(TOOLINFO), TTF_SUBCLASS|TTF_TRANSPARENT, hparent, id, + {rect.left,rect.top,rect.right,rect.bottom}, 0, (LPTSTR)txt, lparam + }; + +#ifdef UNICODE + if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti)) + SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); +#else + if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti)) + SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti); +#endif + } + + void remove(HWND hparent, HWND htool) + { + TOOLINFO ti = { + sizeof(TOOLINFO), TTF_IDISHWND, hparent, (UINT)htool, + {0,0,0,0}, 0, 0, 0 + }; + + SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti); + } + + void remove(HWND hparent, UINT id) + { + TOOLINFO ti = { + sizeof(TOOLINFO), 0, hparent, id, + {0,0,0,0}, 0, 0, 0 + }; + + SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti); + } +}; + + +inline int ListView_GetItemData(HWND list_ctrl, int idx) +{ + LV_ITEM item; + + item.mask = LVIF_PARAM; + item.iItem = idx; + + if (!ListView_GetItem(list_ctrl, &item)) + return 0; + + return item.lParam; +} + +inline int ListView_FindItemPara(HWND list_ctrl, LPARAM param) +{ + LVFINDINFO fi; + + fi.flags = LVFI_PARAM; + fi.lParam = param; + + return ListView_FindItem(list_ctrl, (unsigned)-1, &fi); +} + +inline int ListView_GetFocusedItem(HWND list_ctrl) +{ + int idx = ListView_GetItemCount(list_ctrl); + + while(--idx >= 0) + if (ListView_GetItemState(list_ctrl, idx, LVIS_FOCUSED)) + break; + + return idx; +} + + + /// sorting of list controls +struct ListSort : public WindowHandle +{ + ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct); + + void toggle_sort(int idx); + void sort(); + + int _sort_crit; + bool _direction; + +protected: + PFNLVCOMPARE _compare_fct; + + static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort); +}; + + +inline LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem) +{ + TVITEM tvItem; + + tvItem.mask = TVIF_PARAM; + tvItem.hItem = hItem; + + if (!TreeView_GetItem(hwndTreeView, &tvItem)) + return 0; + + return tvItem.lParam; +} + + +enum {TRAYBUTTON_LEFT=0, TRAYBUTTON_RIGHT, TRAYBUTTON_MIDDLE}; + +#define PM_TRAYICON (WM_APP+0x20) + +#define WINMSG_TASKBARCREATED TEXT("TaskbarCreated") + + +struct TrayIcon +{ + TrayIcon(HWND hparent, UINT id) + : _hparent(hparent), _id(id) {} + + ~TrayIcon() + {Remove();} + + void Add(HICON hIcon, LPCTSTR tooltip=NULL) + {Set(NIM_ADD, _id, hIcon, tooltip);} + + void Modify(HICON hIcon, LPCTSTR tooltip=NULL) + {Set(NIM_MODIFY, _id, hIcon, tooltip);} + + void Remove() + { + NOTIFYICONDATA nid = { + sizeof(NOTIFYICONDATA), // cbSize + _hparent, // hWnd + _id, // uID + }; + + Shell_NotifyIcon(NIM_DELETE, &nid); + } + +protected: + HWND _hparent; + UINT _id; + + void Set(DWORD dwMessage, UINT id, HICON hIcon, LPCTSTR tooltip=NULL) + { + NOTIFYICONDATA nid = { + sizeof(NOTIFYICONDATA), // cbSize + _hparent, // hWnd + id, // uID + NIF_MESSAGE|NIF_ICON, // uFlags + PM_TRAYICON, // uCallbackMessage + hIcon // hIcon + }; + + if (tooltip) + lstrcpyn(nid.szTip, tooltip, COUNTOF(nid.szTip)); + + if (nid.szTip[0]) + nid.uFlags |= NIF_TIP; + + Shell_NotifyIcon(dwMessage, &nid); + } +}; + + +template struct TrayIconControllerTemplate : public BASE +{ + typedef BASE super; + + TrayIconControllerTemplate(HWND hwnd) : BASE(hwnd), + WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED)) + { + } + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + if (nmsg == PM_TRAYICON) { + switch(lparam) { + case WM_MOUSEMOVE: + TrayMouseOver(wparam); + break; + + case WM_LBUTTONDOWN: + TrayClick(wparam, TRAYBUTTON_LEFT); + break; + + case WM_LBUTTONDBLCLK: + TrayDblClick(wparam, TRAYBUTTON_LEFT); + break; + + case WM_RBUTTONDOWN: + TrayClick(wparam, TRAYBUTTON_RIGHT); + break; + + case WM_RBUTTONDBLCLK: + TrayDblClick(wparam, TRAYBUTTON_RIGHT); + break; + + case WM_MBUTTONDOWN: + TrayClick(wparam, TRAYBUTTON_MIDDLE); + break; + + case WM_MBUTTONDBLCLK: + TrayDblClick(wparam, TRAYBUTTON_MIDDLE); + break; + } + + return 0; + } else if (nmsg == WM_TASKBARCREATED) { + AddTrayIcons(); + return 0; + } else + return super::WndProc(nmsg, wparam, lparam); + } + + virtual void AddTrayIcons() = 0; + virtual void TrayMouseOver(UINT id) {} + virtual void TrayClick(UINT id, int btn) {} + virtual void TrayDblClick(UINT id, int btn) {} + +protected: + const UINT WM_TASKBARCREATED; +}; + + +struct EditController : public SubclassedWindow +{ + typedef SubclassedWindow super; + + EditController(HWND hwnd) + : super(hwnd) + { + } + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + if (nmsg==WM_KEYDOWN && wparam==VK_RETURN) { + SendParent(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(_hwnd),1), (LPARAM)_hwnd); + return 0; + } else + return super::WndProc(nmsg, wparam, lparam); + } +}; diff --git a/reactos/subsys/system/ibrowser/utility/xmlstorage.cpp b/reactos/subsys/system/ibrowser/utility/xmlstorage.cpp new file mode 100644 index 00000000000..51019f3ebab --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/xmlstorage.cpp @@ -0,0 +1,612 @@ + + // + // XML storage classes + // + // xmlstorage.cpp + // + // Copyright (c) 2004, Martin Fuchs + // + + +/* + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +//#include "xmlstorage.h" +#include "precomp.h" + + + // work around GCC's wide string constant bug +#ifdef __GNUC__ +const LPCXSSTR XMLStorage::XS_TRUE = XS_TEXT("true"); +const LPCXSSTR XMLStorage::XS_FALSE = XS_TEXT("false"); +const LPCXSSTR XMLStorage::XS_NUMBERFMT = XS_TEXT("%d"); +#endif + + +namespace XMLStorage { + + +static std::string unescape(const char* s, char b='"', char e='"') +{ + const char* end = s + strlen(s); + +// if (*s == b) +// ++s; +// +// if (end>s && end[-1]==e) +// --end; + + if (*s == b) + if (end>s && end[-1]==e) + ++s, --end; + + return std::string(s, end-s); +} + +static std::string unescape(const char* s, int l, char b='"', char e='"') +{ + const char* end = s + l; + +// if (*s == b) +// ++s; +// +// if (end>s && end[-1]==e) +// --end; + + if (*s == b) + if (end>s && end[-1]==e) + ++s, --end; + + return std::string(s, end-s); +} + + + /// move XPath like to position in XML tree +bool XMLPos::go(const char* path) +{ + XMLNode* node = _cur; + + // Is this an absolute path? + if (*path == '/') { + node = _root; + ++path; + } + + node = node->find_relative(path); + + if (node) { + go_to(node); + return true; + } else + return false; +} + + /// move XPath like to position in XML tree +bool const_XMLPos::go(const char* path) +{ + const XMLNode* node = _cur; + + // Is this an absolute path? + if (*path == '/') { + node = _root; + ++path; + } + + node = node->find_relative(path); + + if (node) { + go_to(node); + return true; + } else + return false; +} + + +const XMLNode* XMLNode::find_relative(const char* path) const +{ + const XMLNode* node = this; + + // parse relative path + while(*path) { + const char* slash = strchr(path, '/'); + if (slash == path) + return NULL; + + int l = slash? slash-path: strlen(path); + std::string comp(path, l); + path += l; + + // look for [n] and [@attr_name="attr_value"] expressions in path components + const char* bracket = strchr(comp.c_str(), '['); + l = bracket? bracket-comp.c_str(): comp.length(); + std::string child_name(comp.c_str(), l); + std::string attr_name, attr_value; + + int n = 0; + if (bracket) { + std::string expr = unescape(bracket, '[', ']'); + const char* p = expr.c_str(); + + n = atoi(p); // read index number + + if (n) + n = n - 1; // convert into zero based index + + const char* at = strchr(p, '@'); + + if (at) { + p = at + 1; + const char* equal = strchr(p, '='); + + // read attribute name and value + if (equal) { + attr_name = unescape(p, equal-p); + attr_value = unescape(equal+1); + } + } + } + + if (attr_name.empty()) + // search n.th child node with specified name + node = node->find(child_name, n); + else + // search n.th child node with specified name and matching attribute value + node = node->find(child_name, attr_name, attr_value, n); + + if (!node) + return NULL; + + if (*path == '/') + ++path; + } + + return node; +} + +XMLNode* XMLNode::create_relative(const char* path) +{ + XMLNode* node = this; + + // parse relative path + while(*path) { + const char* slash = strchr(path, '/'); + if (slash == path) + return NULL; + + int l = slash? slash-path: strlen(path); + std::string comp(path, l); + path += l; + + // look for [n] and [@attr_name="attr_value"] expressions in path components + const char* bracket = strchr(comp.c_str(), '['); + l = bracket? bracket-comp.c_str(): comp.length(); + std::string child_name(comp.c_str(), l); + std::string attr_name, attr_value; + + int n = 0; + if (bracket) { + std::string expr = unescape(bracket, '[', ']'); + const char* p = expr.c_str(); + + n = atoi(p); // read index number + + if (n) + n = n - 1; // convert into zero based index + + const char* at = strchr(p, '@'); + + if (at) { + p = at + 1; + const char* equal = strchr(p, '='); + + // read attribute name and value + if (equal) { + attr_name = unescape(p, equal-p); + attr_value = unescape(equal+1); + } + } + } + + XMLNode* child; + + if (attr_name.empty()) + // search n.th child node with specified name + child = node->find(child_name, n); + else + // search n.th child node with specified name and matching attribute value + child = node->find(child_name, attr_name, attr_value, n); + + if (!child) { + child = new XMLNode(child_name); + node->add_child(child); + + if (!attr_name.empty()) + (*node)[attr_name] = attr_value; + } + + node = child; + + if (*path == '/') + ++path; + } + + return node; +} + + + /// read XML stream into XML tree below _pos +XML_Status XMLReaderBase::read() +{ + XML_Status status = XML_STATUS_OK; + + while(status == XML_STATUS_OK) { + char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN); + + int l = read_buffer(buffer, BUFFER_LEN); + if (l < 0) + break; + + status = XML_ParseBuffer(_parser, l, false); + } + + if (status != XML_STATUS_ERROR) + status = XML_ParseBuffer(_parser, 0, true); + + if (_pos->_children.empty()) + _pos->_trailing.append(_content); + else + _pos->_children.back()->_trailing.append(_content); + + _content.erase(); + + return status; +} + + + /// store XML version and encoding into XML reader +void XMLCALL XMLReaderBase::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone) +{ + XMLReaderBase* pReader = (XMLReaderBase*) userData; + + if (version) + pReader->_xml_version = version; + + if (encoding) + pReader->_encoding = encoding; +} + + /// notifications about XML start tag +void XMLCALL XMLReaderBase::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts) +{ + XMLReaderBase* pReader = (XMLReaderBase*) userData; + XMLPos& pos = pReader->_pos; + + // search for end of first line + const char* s = pReader->_content.c_str(); + const char* p = s; + const char* e = p + pReader->_content.length(); + + for(; p_children.empty()) { // no children in last node? + if (pReader->_last_tag == TAG_START) + pos->_content.append(s, p-s); + else if (pReader->_last_tag == TAG_END) + pos->_trailing.append(s, p-s); + // else TAG_NONE -> don't store white space in root node + } else + pos->_children.back()->_trailing.append(s, p-s); + + std::string leading; + + if (p != e) + leading.assign(p, e-p); + + XMLNode* node = new XMLNode(String_from_XML_Char(name), leading); + + pos.add_down(node); + + while(*atts) { + const XML_Char* attr_name = *atts++; + const XML_Char* attr_value = *atts++; + + (*node)[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value); + } + + pReader->_last_tag = TAG_START; + pReader->_content.erase(); +} + + /// notifications about XML end tag +void XMLCALL XMLReaderBase::XML_EndElementHandler(void* userData, const XML_Char* name) +{ + XMLReaderBase* pReader = (XMLReaderBase*) userData; + XMLPos& pos = pReader->_pos; + + // search for end of first line + const char* s = pReader->_content.c_str(); + const char* p = s; + const char* e = p + pReader->_content.length(); + + for(; p_children.empty()) // no children in current node? + pos->_content.append(s, p-s); + else + if (pReader->_last_tag == TAG_START) + pos->_content.append(s, p-s); + else + pos->_children.back()->_trailing.append(s, p-s); + + if (p != e) + pos->_end_leading.assign(p, e-p); + + pos.back(); + + pReader->_last_tag = TAG_END; + pReader->_content.erase(); +} + + /// store content, white space and comments +void XMLCALL XMLReaderBase::XML_DefaultHandler(void* userData, const XML_Char* s, int len) +{ + XMLReaderBase* pReader = (XMLReaderBase*) userData; + + pReader->_content.append(s, len); +} + + +std::string XMLReaderBase::get_error_string() const +{ + XML_Error error = XML_GetErrorCode(_parser); + + switch(error) { + case XML_ERROR_NONE: return "XML_ERROR_NONE"; + case XML_ERROR_NO_MEMORY: return "XML_ERROR_NO_MEMORY"; + case XML_ERROR_SYNTAX: return "XML_ERROR_SYNTAX"; + case XML_ERROR_NO_ELEMENTS: return "XML_ERROR_NO_ELEMENTS"; + case XML_ERROR_INVALID_TOKEN: return "XML_ERROR_INVALID_TOKEN"; + case XML_ERROR_UNCLOSED_TOKEN: return "XML_ERROR_UNCLOSED_TOKEN"; + case XML_ERROR_PARTIAL_CHAR: return "XML_ERROR_PARTIAL_CHAR"; + case XML_ERROR_TAG_MISMATCH: return "XML_ERROR_TAG_MISMATCH"; + case XML_ERROR_DUPLICATE_ATTRIBUTE: return "XML_ERROR_DUPLICATE_ATTRIBUTE"; + case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: return "XML_ERROR_JUNK_AFTER_DOC_ELEMENT"; + case XML_ERROR_PARAM_ENTITY_REF: return "XML_ERROR_PARAM_ENTITY_REF"; + case XML_ERROR_UNDEFINED_ENTITY: return "XML_ERROR_UNDEFINED_ENTITY"; + case XML_ERROR_RECURSIVE_ENTITY_REF: return "XML_ERROR_RECURSIVE_ENTITY_REF"; + case XML_ERROR_ASYNC_ENTITY: return "XML_ERROR_ASYNC_ENTITY"; + case XML_ERROR_BAD_CHAR_REF: return "XML_ERROR_BAD_CHAR_REF"; + case XML_ERROR_BINARY_ENTITY_REF: return "XML_ERROR_BINARY_ENTITY_REF"; + case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: return "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF"; + case XML_ERROR_MISPLACED_XML_PI: return "XML_ERROR_MISPLACED_XML_PI"; + case XML_ERROR_UNKNOWN_ENCODING: return "XML_ERROR_UNKNOWN_ENCODING"; + case XML_ERROR_INCORRECT_ENCODING: return "XML_ERROR_INCORRECT_ENCODING"; + case XML_ERROR_UNCLOSED_CDATA_SECTION: return "XML_ERROR_UNCLOSED_CDATA_SECTION"; + case XML_ERROR_EXTERNAL_ENTITY_HANDLING: return "XML_ERROR_EXTERNAL_ENTITY_HANDLING"; + case XML_ERROR_NOT_STANDALONE: return "XML_ERROR_NOT_STANDALONE"; + case XML_ERROR_UNEXPECTED_STATE: return "XML_ERROR_UNEXPECTED_STATE"; + case XML_ERROR_ENTITY_DECLARED_IN_PE: return "XML_ERROR_ENTITY_DECLARED_IN_PE"; + case XML_ERROR_FEATURE_REQUIRES_XML_DTD: return "XML_ERROR_FEATURE_REQUIRES_XML_DTD"; + case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING: return "XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING"; + case XML_ERROR_UNBOUND_PREFIX: return "XML_ERROR_UNBOUND_PREFIX"; + // EXPAT version >= 1.95.8 +#if XML_MAJOR_VERSION>1 || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION>95) || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION==95 && XML_MICRO_VERSION>7) + case XML_ERROR_SUSPENDED: return "XML_ERROR_SUSPENDED"; + case XML_ERROR_NOT_SUSPENDED: return "XML_ERROR_NOT_SUSPENDED"; + case XML_ERROR_ABORTED: return "XML_ERROR_ABORTED"; + case XML_ERROR_FINISHED: return "XML_ERROR_FINISHED"; + case XML_ERROR_SUSPEND_PE: return "XML_ERROR_SUSPEND_PE"; +#endif + } + + std::ostringstream out; + + out << "XML parser error #" << error; + + return out.str(); +} + + +std::string EncodeXMLString(const XS_String& str) +{ + LPCXSSTR s = str.c_str(); + LPXSSTR buffer = (LPXSSTR)alloca(5*sizeof(XS_CHAR)*XS_len(s)); // worst case. "&" + LPXSSTR o = buffer; + + for(LPCXSSTR p=s; *p; ++p) + switch(*p) { + case '&': + *o++ = '&'; *o++ = 'a'; *o++ = 'm'; *o++ = 'p'; *o++ = ';'; + break; + + case '<': + *o++ = '&'; *o++ = 'l'; *o++ = 't'; *o++ = ';'; + break; + + case '>': + *o++ = '&'; *o++ = 'g'; *o++ = 't'; *o++ = ';'; + break; + + case '"': + *o++ = '&'; *o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't'; *o++ = ';'; + break; + + case '\'': + *o++ = '&'; *o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's'; *o++ = ';'; + break; + + default: + *o++ = *p; + } + +#ifdef XS_STRING_UTF8 + return XS_String(buffer, o-buffer); +#else + return get_utf8(buffer, o-buffer); +#endif +} + +XS_String DecodeXMLString(const XS_String& str) +{ + LPCXSSTR s = str.c_str(); + LPXSSTR buffer = (LPXSSTR)alloca(sizeof(XS_CHAR)*XS_len(s)); + LPXSSTR o = buffer; + + for(LPCXSSTR p=s; *p; ++p) + if (*p == '&') { + if (!XS_nicmp(p+1, XS_TEXT("lt;"), 3)) { + *o++ = '<'; + p += 3; + } else if (!XS_nicmp(p+1, XS_TEXT("gt;"), 3)) { + *o++ = '>'; + p += 3; + } else if (!XS_nicmp(p+1, XS_TEXT("amp;"), 4)) { + *o++ = '&'; + p += 4; + } else if (!XS_nicmp(p+1, XS_TEXT("quot;"), 5)) { + *o++ = '"'; + p += 5; + } else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) { + *o++ = '\''; + p += 5; + } else + *o++ = *p; + } else + *o++ = *p; + + return XS_String(buffer, o-buffer); +} + + + /// write node with children tree to output stream using original white space +void XMLNode::write_worker(std::ostream& out, int indent) const +{ + out << _leading << '<' << EncodeXMLString(*this); + + for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it) + out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\""; + + if (!_children.empty() || !_content.empty()) { + out << '>' << _content; + + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) + (*it)->write_worker(out, indent+1); + + out << _end_leading << "'; + } else + out << "/>"; + + out << _trailing; +} + + + /// pretty print node with children tree to output stream +void XMLNode::pretty_write_worker(std::ostream& out, int indent) const +{ + for(int i=indent; i--; ) + out << XML_INDENT_SPACE; + + out << '<' << EncodeXMLString(*this); + + for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it) + out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\""; + + if (!_children.empty() || !_content.empty()) { + out << ">\n"; + + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) + (*it)->pretty_write_worker(out, indent+1); + + for(int i=indent; i--; ) + out << XML_INDENT_SPACE; + + out << "\n"; + } else + out << "/>\n"; +} + + + /// write node with children tree to output stream using smart formating +void XMLNode::smart_write_worker(std::ostream& out, int indent) const +{ + if (_leading.empty()) + for(int i=indent; i--; ) + out << XML_INDENT_SPACE; + else + out << _leading; + + out << '<' << EncodeXMLString(*this); + + for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it) + out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\""; + + if (_children.empty() && _content.empty()) + out << "/>"; + else { + out << '>'; + + if (_content.empty()) + out << '\n'; + else + out << _content; + + Children::const_iterator it = _children.begin(); + + if (it != _children.end()) { + for(; it!=_children.end(); ++it) + (*it)->smart_write_worker(out, indent+1); + + if (_end_leading.empty()) + for(int i=indent; i--; ) + out << XML_INDENT_SPACE; + else + out << _end_leading; + } else + out << _end_leading; + + out << "'; + } + + if (_trailing.empty()) + out << '\n'; + else + out << _trailing; +} + + +} // namespace XMLStorage diff --git a/reactos/subsys/system/ibrowser/utility/xmlstorage.h b/reactos/subsys/system/ibrowser/utility/xmlstorage.h new file mode 100644 index 00000000000..60b5fab1daf --- /dev/null +++ b/reactos/subsys/system/ibrowser/utility/xmlstorage.h @@ -0,0 +1,1722 @@ + + // + // XML storage classes + // + // xmlstorage.h + // + // Copyright (c) 2004, Martin Fuchs + // + + +/* + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _XMLSTORAGE_H + +#include "expat.h" + +#ifdef _MSC_VER +#pragma comment(lib, "libexpat.lib") +#pragma warning(disable: 4786) +#endif + + +#include // for LPCTSTR + +#ifdef UNICODE +#define _UNICODE +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + + +#ifndef BUFFER_LEN +#define BUFFER_LEN 2048 +#endif + + +namespace XMLStorage { + + +#ifndef XS_String + +#ifdef XS_STRING_UTF8 +#define XS_CHAR char +#define XS_TEXT(x) x +#define LPXSSTR LPSTR +#define LPCXSSTR LPCSTR +#define XS_icmp stricmp +#define XS_nicmp strnicmp +#define XS_toi atoi +#define XS_len strlen +#define XS_sprintf sprintf +#define XS_vsprintf vsprintf +#else +#define XS_CHAR TCHAR +#define XS_TEXT(x) TEXT(x) +#define LPXSSTR LPTSTR +#define LPCXSSTR LPCTSTR +#define XS_icmp _tcsicmp +#define XS_nicmp _tcsnicmp +#define XS_toi _ttoi +#define XS_len _tcslen +#define XS_sprintf _stprintf +#define XS_vsprintf _vstprintf +#endif + +#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) + +#define XS_String String + +#else // _STRING_DEFINED, !XS_STRING_UTF8 + + /// string class for TCHAR strings + +struct XS_String +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + : public std::wstring +#else + : public std::string +#endif +{ +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + typedef std::wstring super; +#else + typedef std::string super; +#endif + + XS_String() {} + + XS_String(LPCXSSTR s) {if (s) super::assign(s);} + XS_String(LPCXSSTR s, int l) : super(s, l) {} + + XS_String(const super& other) : super(other) {} + XS_String(const XS_String& other) : super(other) {} + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + XS_String(LPCSTR s) {assign(s);} + XS_String(LPCSTR s, int l) {assign(s, l);} + XS_String(const std::string& other) {assign(other.c_str());} + XS_String& operator=(LPCSTR s) {assign(s); return *this;} + void assign(LPCSTR s) {if (s) {int bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();} + void assign(LPCSTR s, int l) {if (s) {int bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();} +#else + XS_String(LPCWSTR s) {assign(s);} + XS_String(LPCWSTR s, int l) {assign(s, l);} + XS_String(const std::wstring& other) {assign(other.c_str());} + XS_String& operator=(LPCWSTR s) {assign(s); return *this;} +#ifdef XS_STRING_UTF8 + void assign(const XS_String& s) {assign(s.c_str());} + void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, bl, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, l, b, bl, 0, 0));} else erase();} +#else // if !UNICODE && !XS_STRING_UTF8 + void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, bl, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, bl, 0, 0));} else erase();} +#endif +#endif + + XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;} + XS_String& operator=(const super& s) {super::assign(s); return *this;} + void assign(LPCXSSTR s) {super::assign(s);} + void assign(LPCXSSTR s, int l) {super::assign(s, l);} + + operator LPCXSSTR() const {return c_str();} + +#ifdef XS_STRING_UTF8 + operator std::wstring() const {int bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));} +#elif defined(UNICODE) + operator std::string() const {int bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));} +#else + operator std::wstring() const {int bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), bl, b, bl));} +#endif + + XS_String& printf(LPCXSSTR fmt, ...) + { + va_list l; + XS_CHAR b[BUFFER_LEN]; + + va_start(l, fmt); + super::assign(b, XS_vsprintf(b, fmt, l)); + va_end(l); + + return *this; + } + + XS_String& vprintf(LPCXSSTR fmt, va_list l) + { + XS_CHAR b[BUFFER_LEN]; + + super::assign(b, XS_vsprintf(b, fmt, l)); + + return *this; + } + + XS_String& appendf(LPCXSSTR fmt, ...) + { + va_list l; + XS_CHAR b[BUFFER_LEN]; + + va_start(l, fmt); + super::append(b, XS_vsprintf(b, fmt, l)); + va_end(l); + + return *this; + } + + XS_String& vappendf(LPCXSSTR fmt, va_list l) + { + XS_CHAR b[BUFFER_LEN]; + + super::append(b, XS_vsprintf(b, fmt, l)); + + return *this; + } +}; + +#endif // _STRING_DEFINED, !XS_STRING_UTF8 + +#endif // XS_String + + +#ifndef XS_STRING_UTF8 + +inline void assign_utf8(XS_String& s, const char* str) +{ + int lutf8 = strlen(str); + +#ifdef UNICODE + LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8); + int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, buffer, lutf8); +#else + LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8); + int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, wbuffer, lutf8); + + int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0); +#endif + + s.assign(buffer, l); +} + +inline std::string get_utf8(LPCTSTR s, int l) +{ +#ifdef UNICODE + int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_UTF8, 0, s, l, buffer, bl, 0, 0); +#else + LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l); + l = MultiByteToWideChar(CP_ACP, 0, s, l, wbuffer, l); + + int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, l, buffer, bl, 0, 0); +#endif + + return std::string(buffer, l); +} + +inline std::string get_utf8(const XS_String& s) +{ + return get_utf8(s.c_str(), s.length()); +} + +#endif // XS_STRING_UTF8 + +extern std::string EncodeXMLString(const XS_String& str); +extern XS_String DecodeXMLString(const XS_String& str); + + +#ifdef __GNUC__ +#include +typedef __gnu_cxx::stdio_filebuf STDIO_FILEBUF; +#else +typedef std::filebuf STDIO_FILEBUF; +#endif + + /// input file stream with ANSI/UNICODE file names +struct tifstream : public std::istream +{ + typedef std::istream super; + + tifstream(LPCTSTR path) + : super(&_buf), + _pfile(_tfopen(path, TEXT("r"))), +#ifdef __GNUC__ + _buf(_pfile, ios::in) +#else + _buf(_pfile) +#endif + { + } + + ~tifstream() + { + if (_pfile) + fclose(_pfile); + } + +protected: + FILE* _pfile; + STDIO_FILEBUF _buf; +}; + + /// output file stream with ANSI/UNICODE file names +struct tofstream : public std::ostream +{ + typedef std::ostream super; + + tofstream(LPCTSTR path) + : super(&_buf), + _pfile(_tfopen(path, TEXT("w"))), +#ifdef __GNUC__ + _buf(_pfile, ios::out) +#else + _buf(_pfile) +#endif + { + } + + ~tofstream() + { + flush(); + + if (_pfile) + fclose(_pfile); + } + +protected: + FILE* _pfile; + STDIO_FILEBUF _buf; +}; + + + // write XML files with 2 spaces indenting +#define XML_INDENT_SPACE " " + + +#ifdef XML_UNICODE // Are XML_Char strings UTF-16 encoded? + +typedef XS_String String_from_XML_Char; + +#elif defined(XS_STRING_UTF8) + +typedef XS_String String_from_XML_Char; + +#else + +struct String_from_XML_Char : public XS_String +{ + String_from_XML_Char(const XML_Char* str) + { + assign_utf8(*this, str); + } +}; + +#endif + + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + + // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion +inline bool operator==(const XS_String& s1, const char* s2) +{ + LPCWSTR p = s1; + const unsigned char* q = (const unsigned char*)s2; + + while(*p && *q) + if (*p++ != *q++) + return false; + + return *p == *q; +}; + +#endif + + + /// in memory representation of an XML node +struct XMLNode : public XS_String +{ +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + // optimized read access without temporary A/U conversion when using ASCII attribute names + struct AttributeMap : public std::map + { + typedef std::map super; + + const_iterator find(const char* x) const + { + for(const_iterator it=begin(); it!=end(); ++it) + if (it->first == x) + return it; + + return end(); + } + + const_iterator find(const key_type& x) const + { + return super::find(x); + } + + iterator find(const key_type& x) + { + return super::find(x); + } + }; +#else + typedef std::map AttributeMap; +#endif + + struct Children : public std::list + { + void assign(const Children& other) + { + clear(); + + for(Children::const_iterator it=other.begin(); it!=other.end(); ++it) + push_back(new XMLNode(**it)); + } + + void clear() + { + while(!empty()) { + XMLNode* node = back(); + pop_back(); + + node->clear(); + delete node; + } + } + }; + + // access to protected class members for XMLPos and XMLReader + friend struct XMLPos; + friend struct const_XMLPos; + friend struct XMLReaderBase; + + XMLNode(const XS_String& name) + : XS_String(name) + { + } + + XMLNode(const XS_String& name, const std::string& leading) + : XS_String(name), + _leading(leading) + { + } + + XMLNode(const XMLNode& other) + : _attributes(other._attributes), + _leading(other._leading), + _content(other._content), + _end_leading(other._end_leading), + _trailing(other._trailing) + { + for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it) + _children.push_back(new XMLNode(**it)); + } + + ~XMLNode() + { + while(!_children.empty()) { + delete _children.back(); + _children.pop_back(); + } + } + + void clear() + { + _leading.erase(); + _content.erase(); + _end_leading.erase(); + _trailing.erase(); + + _attributes.clear(); + _children.clear(); + + XS_String::erase(); + } + + XMLNode& operator=(const XMLNode& other) + { + _children.assign(other._children); + + _attributes = other._attributes; + + _leading = other._leading; + _content = other._content; + _end_leading = other._end_leading; + _trailing = other._trailing; + + return *this; + } + + /// add a new child node + void add_child(XMLNode* child) + { + _children.push_back(child); + } + + /// write access to an attribute + void put(const XS_String& attr_name, const XS_String& value) + { + _attributes[attr_name] = value; + } + + /// C++ write access to an attribute + XS_String& operator[](const XS_String& attr_name) + { + return _attributes[attr_name]; + } + + /// read only access to an attribute + template XS_String get(const T& attr_name) const + { + AttributeMap::const_iterator found = _attributes.find(attr_name); + + if (found != _attributes.end()) + return found->second; + else + return XS_String(); + } + + /// convenient value access in children node + XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const + { + const XMLNode* node = find(name, n); + + if (node) + return node->get(attr_name); + else + return XS_String(); + } + + /// convenient storage of distinct values in children node + XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0) + { + XMLNode* node = find(name, n); + + if (!node) { + node = new XMLNode(name); + add_child(node); + } + + return (*node)[attr_name]; + } + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + /// convenient value access in children node + XS_String subvalue(const char* name, const char* attr_name, int n=0) const + { + const XMLNode* node = find(name, n); + + if (node) + return node->get(attr_name); + else + return XS_String(); + } + + /// convenient storage of distinct values in children node + XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0) + { + XMLNode* node = find(name, n); + + if (!node) { + node = new XMLNode(name); + add_child(node); + } + + return (*node)[attr_name]; + } +#endif + + const Children& get_children() const + { + return _children; + } + + Children& get_children() + { + return _children; + } + + XS_String get_content() const + { +#ifdef XS_STRING_UTF8 + const XS_String& ret = _content; +#else + XS_String ret; + assign_utf8(ret, _content.c_str()); +#endif + + return DecodeXMLString(ret.c_str()); + } + + void set_content(const XS_String& s) + { + _content.assign(EncodeXMLString(s.c_str())); + } + + enum WRITE_MODE { + FORMAT_SMART = 0, /// preserve original white space and comments if present; pretty print otherwise + FORMAT_ORIGINAL = 1, /// write XML stream preserving original white space and comments + FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space + }; + + /// write node with children tree to output stream + std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, int indent=0) const + { + switch(mode) { + case FORMAT_PRETTY: + pretty_write_worker(out, indent); + break; + + case FORMAT_ORIGINAL: + write_worker(out, indent); + break; + + default: // FORMAT_SMART + smart_write_worker(out, indent); + } + + return out; + } + + XMLNode* find(const XS_String& name, int n=0) const + { + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) + if (**it == name) + if (!n--) + return *it; + + return NULL; + } + + XMLNode* find(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value, int n=0) const + { + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) { + const XMLNode& node = **it; + + if (node==name && node.get(attr_name)==attr_value) + if (!n--) + return *it; + } + + return NULL; + } + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + XMLNode* find(const char* name, int n=0) const + { + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) + if (**it == name) + if (!n--) + return *it; + + return NULL; + } + + template + XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int n=0) const + { + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) { + const XMLNode& node = **it; + + if (node==name && node.get(attr_name)==attr_value) + if (!n--) + return *it; + } + + return NULL; + } +#endif + + /// XPath find functions + const XMLNode* find_relative(const char* path) const; + + XMLNode* find_relative(const char* path) + {return const_cast(const_cast(this)->find_relative(path));} + + /// relative XPath create function + XMLNode* create_relative(const char* path); + +protected: + Children _children; + AttributeMap _attributes; + + std::string _leading; + std::string _content; + std::string _end_leading; + std::string _trailing; + + XMLNode* get_first_child() const + { + if (!_children.empty()) + return _children.front(); + else + return NULL; + } + + void write_worker(std::ostream& out, int indent) const; + void pretty_write_worker(std::ostream& out, int indent) const; + void smart_write_worker(std::ostream& out, int indent) const; +}; + + + /// iterator access to children nodes with name filtering +struct XMLChildrenFilter +{ + XMLChildrenFilter(XMLNode::Children& children, const XS_String& name) + : _begin(children.begin(), children.end(), name), + _end(children.end(), children.end(), name) + { + } + + XMLChildrenFilter(XMLNode* node, const XS_String& name) + : _begin(node->get_children().begin(), node->get_children().end(), name), + _end(node->get_children().end(), node->get_children().end(), name) + { + } + + struct iterator + { + typedef XMLNode::Children::iterator BaseIterator; + + iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name) + : _cur(begin), + _end(end), + _filter_name(filter_name) + { + search_next(); + } + + operator BaseIterator() + { + return _cur; + } + + const XMLNode* operator*() const + { + return *_cur; + } + + XMLNode* operator*() + { + return *_cur; + } + + iterator& operator++() + { + ++_cur; + search_next(); + + return *this; + } + + iterator operator++(int) + { + iterator ret = *this; + + ++_cur; + search_next(); + + return ret; + } + + bool operator==(const BaseIterator& other) const + { + return _cur == other; + } + + bool operator!=(const BaseIterator& other) const + { + return _cur != other; + } + + protected: + BaseIterator _cur; + BaseIterator _end; + XS_String _filter_name; + + void search_next() + { + while(_cur!=_end && **_cur!=_filter_name) + ++_cur; + } + }; + + iterator begin() + { + return _begin; + } + + iterator end() + { + return _end; + } + +protected: + iterator _begin; + iterator _end; +}; + + + /// read only iterator access to children nodes with name filtering +struct const_XMLChildrenFilter +{ + const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name) + : _begin(children.begin(), children.end(), name), + _end(children.end(), children.end(), name) + { + } + + const_XMLChildrenFilter(const XMLNode* node, const XS_String& name) + : _begin(node->get_children().begin(), node->get_children().end(), name), + _end(node->get_children().end(), node->get_children().end(), name) + { + } + + struct const_iterator + { + typedef XMLNode::Children::const_iterator BaseIterator; + + const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name) + : _cur(begin), + _end(end), + _filter_name(filter_name) + { + search_next(); + } + + operator BaseIterator() + { + return _cur; + } + + const XMLNode* operator*() const + { + return *_cur; + } + + const_iterator& operator++() + { + ++_cur; + search_next(); + + return *this; + } + + const_iterator operator++(int) + { + const_iterator ret = *this; + + ++_cur; + search_next(); + + return ret; + } + + bool operator==(const BaseIterator& other) const + { + return _cur == other; + } + + bool operator!=(const BaseIterator& other) const + { + return _cur != other; + } + + protected: + BaseIterator _cur; + BaseIterator _end; + XS_String _filter_name; + + void search_next() + { + while(_cur!=_end && **_cur!=_filter_name) + ++_cur; + } + }; + + const_iterator begin() + { + return _begin; + } + + const_iterator end() + { + return _end; + } + +protected: + const_iterator _begin; + const_iterator _end; +}; + + + /// iterator for XML trees +struct XMLPos +{ + XMLPos(XMLNode* root) + : _root(root), + _cur(root) + { + } + + XMLPos(const XMLPos& other) + : _root(other._root), + _cur(other._cur) + { // don't copy _stack + } + + XMLPos(XMLNode* node, const XS_String& name) + : _root(node), + _cur(node) + { + smart_create(name); + } + + XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) + : _root(node), + _cur(node) + { + smart_create(name, attr_name, attr_value); + } + + XMLPos(const XMLPos& other, const XS_String& name) + : _root(other._root), + _cur(other._cur) + { + smart_create(name); + } + + XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) + : _root(other._root), + _cur(other._cur) + { + smart_create(name, attr_name, attr_value); + } + + /// access to current node + XMLNode& cur() + { + return *_cur; + } + + const XMLNode& cur() const + { + return *_cur; + } + + /// C++ access to current node + operator const XMLNode*() const {return _cur;} + operator XMLNode*() {return _cur;} + + const XMLNode* operator->() const {return _cur;} + XMLNode* operator->() {return _cur;} + + const XMLNode& operator*() const {return *_cur;} + XMLNode& operator*() {return *_cur;} + + /// attribute access + XS_String get(const XS_String& attr_name) const + { + return _cur->get(attr_name); + } + + void put(const XS_String& attr_name, const XS_String& value) + { + _cur->put(attr_name, value); + } + + /// C++ attribute access + template XS_String get(const T& attr_name) const {return (*_cur)[attr_name];} + XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];} + + /// insert children when building tree + void add_down(XMLNode* child) + { + _cur->add_child(child); + go_to(child); + } + + /// go back to previous position + bool back() + { + if (!_stack.empty()) { + _cur = _stack.top(); + _stack.pop(); + return true; + } else + return false; + } + + /// go down to first child + bool go_down() + { + XMLNode* node = _cur->get_first_child(); + + if (node) { + go_to(node); + return true; + } else + return false; + } + + /// search for child and go down + bool go_down(const XS_String& name, int n=0) + { + XMLNode* node = _cur->find(name, n); + + if (node) { + go_to(node); + return true; + } else + return false; + } + + /// move XPath like to position in XML tree + bool go(const char* path); + + /// create child nodes using XPath notation and move to the deepest child + bool create_relative(const char* path) + { + XMLNode* node = _cur->create_relative(path); + if (!node) + return false; // invalid path specified + + go_to(node); + return true; + } + + /// create node and move to it + void create(const XS_String& name) + { + add_down(new XMLNode(name)); + } + + /// create node if not already existing and move to it + void smart_create(const XS_String& name) + { + XMLNode* node = _cur->find(name); + + if (node) + go_to(node); + else + add_down(new XMLNode(name)); + } + + /// search matching child node identified by key name and an attribute value + void smart_create(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) + { + XMLNode* node = _cur->find(name, attr_name, attr_value); + + if (node) + go_to(node); + else { + node = new XMLNode(name); + add_down(node); + (*node)[attr_name] = attr_value; + } + } + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + /// search for child and go down + bool go_down(const char* name, int n=0) + { + XMLNode* node = _cur->find(name, n); + + if (node) { + go_to(node); + return true; + } else + return false; + } + + /// create node and move to it + void create(const char* name) + { + add_down(new XMLNode(name)); + } + + /// create node if not already existing and move to it + void smart_create(const char* name) + { + XMLNode* node = _cur->find(name); + + if (node) + go_to(node); + else + add_down(new XMLNode(name)); + } + + /// search matching child node identified by key name and an attribute value + template + void smart_create(const char* name, const T& attr_name, const U& attr_value) + { + XMLNode* node = _cur->find(name, attr_name, attr_value); + + if (node) + go_to(node); + else { + XMLNode* node = new XMLNode(name); + add_down(node); + (*node)[attr_name] = attr_value; + } + } +#endif + + XS_String& str() {return *_cur;} + const XS_String& str() const {return *_cur;} + +protected: + XMLNode* _root; + XMLNode* _cur; + std::stack _stack; + + /// go to specified node + void go_to(XMLNode* child) + { + _stack.push(_cur); + _cur = child; + } +}; + + + /// iterator for XML trees +struct const_XMLPos +{ + const_XMLPos(const XMLNode* root) + : _root(root), + _cur(root) + { + } + + const_XMLPos(const const_XMLPos& other) + : _root(other._root), + _cur(other._cur) + { // don't copy _stack + } + + /// access to current node + const XMLNode& cur() const + { + return *_cur; + } + + /// C++ access to current node + operator const XMLNode*() const {return _cur;} + + const XMLNode* operator->() const {return _cur;} + + const XMLNode& operator*() const {return *_cur;} + + /// attribute access + XS_String get(const XS_String& attr_name) const + { + return _cur->get(attr_name); + } + + /// C++ attribute access + template XS_String get(const T& attr_name) const {return _cur->get(attr_name);} + + /// go back to previous position + bool back() + { + if (!_stack.empty()) { + _cur = _stack.top(); + _stack.pop(); + return true; + } else + return false; + } + + /// go down to first child + bool go_down() + { + const XMLNode* node = _cur->get_first_child(); + + if (node) { + go_to(node); + return true; + } else + return false; + } + + /// search for child and go down + bool go_down(const XS_String& name, int n=0) + { + XMLNode* node = _cur->find(name, n); + + if (node) { + go_to(node); + return true; + } else + return false; + } + + /// move XPath like to position in XML tree + bool go(const char* path); + +#if defined(UNICODE) && !defined(XS_STRING_UTF8) + /// search for child and go down + bool go_down(const char* name, int n=0) + { + XMLNode* node = _cur->find(name, n); + + if (node) { + go_to(node); + return true; + } else + return false; + } +#endif + + const XS_String& str() const {return *_cur;} + +protected: + const XMLNode* _root; + const XMLNode* _cur; + std::stack _stack; + + /// go to specified node + void go_to(const XMLNode* child) + { + _stack.push(_cur); + _cur = child; + } +}; + + + // work around GCC's wide string constant bug +#ifdef __GNUC__ +extern const LPCXSSTR XS_TRUE; +extern const LPCXSSTR XS_FALSE; +extern const LPCXSSTR XS_NUMBERFMT; +#else +#define XS_TRUE XS_TEXT("true") +#define XS_FALSE XS_TEXT("false") +#define XS_NUMBERFMT XS_TEXT("%d") +#endif + + +struct XMLBool +{ + XMLBool(bool value=false) + : _value(value) + { + } + + XMLBool(LPCXSSTR value, bool def=false) + { + if (value && *value) + _value = !XS_icmp(value, XS_TRUE); + else + _value = def; + } + + XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false) + { + const XS_String& value = node->get(attr_name); + + if (!value.empty()) + _value = !XS_icmp(value.c_str(), XS_TRUE); + else + _value = def; + } + + operator bool() const + { + return _value; + } + + bool operator!() const + { + return !_value; + } + + operator LPCXSSTR() const + { + return _value? XS_TRUE: XS_FALSE; + } + +protected: + bool _value; + +private: + void operator=(const XMLBool&); // disallow assignment operations +}; + +struct XMLBoolRef +{ + XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false) + : _ref((*node)[attr_name]) + { + if (_ref.empty()) + assign(def); + } + + operator bool() const + { + return !XS_icmp(_ref.c_str(), XS_TRUE); + } + + bool operator!() const + { + return XS_icmp(_ref.c_str(), XS_TRUE)? true: false; + } + + XMLBoolRef& operator=(bool value) + { + assign(value); + + return *this; + } + + void assign(bool value) + { + _ref.assign(value? XS_TRUE: XS_FALSE); + } + + void toggle() + { + assign(!operator bool()); + } + +protected: + XS_String& _ref; +}; + + +struct XMLInt +{ + XMLInt(int value) + : _value(value) + { + } + + XMLInt(LPCXSSTR value, int def=0) + { + if (value && *value) + _value = XS_toi(value); + else + _value = def; + } + + XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0) + { + const XS_String& value = node->get(attr_name); + + if (!value.empty()) + _value = XS_toi(value.c_str()); + else + _value = def; + } + + operator int() const + { + return _value; + } + + operator XS_String() const + { + XS_CHAR buffer[32]; + XS_sprintf(buffer, XS_NUMBERFMT, _value); + return buffer; + } + +protected: + int _value; + +private: + void operator=(const XMLInt&); // disallow assignment operations +}; + +struct XMLIntRef +{ + XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0) + : _ref((*node)[attr_name]) + { + if (_ref.empty()) + assign(def); + } + + XMLIntRef& operator=(int value) + { + assign(value); + + return *this; + } + + operator int() const + { + return XS_toi(_ref.c_str()); + } + + void assign(int value) + { + XS_CHAR buffer[32]; + XS_sprintf(buffer, XS_NUMBERFMT, value); + _ref.assign(buffer); + } + +protected: + XS_String& _ref; +}; + + +struct XMLString +{ + XMLString(const XS_String& value) + : _value(value) + { + } + + XMLString(LPCXSSTR value, LPCXSSTR def=XS_TEXT("")) + { + if (value && *value) + _value = value; + else + _value = def; + } + + XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + { + const XS_String& value = node->get(attr_name); + + if (!value.empty()) + _value = value; + else + _value = def; + } + + operator const XS_String&() const + { + return _value; + } + + const XS_String& c_str() const + { + return _value; + } + +protected: + XS_String _value; + +private: + void operator=(const XMLString&); // disallow assignment operations +}; + +struct XMStringRef +{ + XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + : _ref((*node)[attr_name]) + { + if (_ref.empty()) + assign(def); + } + + XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + : _ref(node->subvalue(node_name, attr_name)) + { + if (_ref.empty()) + assign(def); + } + + XMStringRef& operator=(const XS_String& value) + { + assign(value); + + return *this; + } + + operator const XS_String&() const + { + return _ref; + } + + void assign(const XS_String& value) + { + _ref.assign(value); + } + +protected: + XS_String& _ref; +}; + + +template + inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key) + { + const XS_String& val = cfg.get(key); + + if (!val.empty()) + var = val; + } + +template<> + inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key) + { + const XS_String& val = cfg.get(key); + + if (!val.empty()) + var = XS_toi(val.c_str()); + } + + +#ifdef _MSC_VER +#pragma warning(disable: 4355) +#endif + + /// XML reader base class +struct XMLReaderBase +{ + XMLReaderBase(XMLNode* node) + : _pos(node), + _parser(XML_ParserCreate(NULL)) + { + XML_SetUserData(_parser, this); + XML_SetXmlDeclHandler(_parser, XML_XmlDeclHandler); + XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler); + XML_SetDefaultHandler(_parser, XML_DefaultHandler); + + _last_tag = TAG_NONE; + } + + virtual ~XMLReaderBase() + { + XML_ParserFree(_parser); + } + + XML_Status read(); + + virtual int read_buffer(char* buffer, int len) = 0; + + std::string get_position() const + { + int line = XML_GetCurrentLineNumber(_parser); + int column = XML_GetCurrentColumnNumber(_parser); + + std::ostringstream out; + out << "(" << line << ") : [column " << column << "]"; + + return out.str(); + } + + XML_Error get_error_code() {return XML_GetErrorCode(_parser);} + std::string get_error_string() const; + +protected: + XMLPos _pos; + XML_Parser _parser; + std::string _xml_version; + std::string _encoding; + + std::string _content; + enum {TAG_NONE, TAG_START, TAG_END} _last_tag; + + static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone); + static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts); + static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name); + static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len); +}; + + + /// XML file reader +struct XMLReader : public XMLReaderBase +{ + XMLReader(XMLNode* node, std::istream& in) + : XMLReaderBase(node), + _in(in) + { + } + + /// read XML stream into XML tree below _pos + int read_buffer(char* buffer, int len) + { + if (!_in.good()) + return -1; + + _in.read(buffer, len); + + return _in.gcount(); + } + +protected: + std::istream& _in; +}; + + +struct XMLHeader +{ + XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="") + : _version(xml_version), + _encoding(encoding), + _doctype(doctype) + { + } + + void print(std::ostream& out) const + { + out << "\n"; + + if (!_doctype.empty()) + out << _doctype << '\n'; + } + + std::string _version; + std::string _encoding; + std::string _doctype; +}; + + +struct XMLDoc : public XMLNode +{ + XMLDoc() + : XMLNode(""), + _last_error(XML_ERROR_NONE) + { + } + + XMLDoc(LPCTSTR path) + : XMLNode(""), + _last_error(XML_ERROR_NONE) + { + read(path); + } + + std::istream& read(std::istream& in) + { + XMLReader reader(this, in); + + read(reader); + + return in; + } + + bool read(LPCTSTR path) + { + tifstream in(path); + XMLReader reader(this, in); + +//#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) +// return read(reader, std::string(ANS(path))); +//#else + return read(reader, XS_String(path)); +//#endif + } + + bool read(XMLReaderBase& reader) + { + XML_Status status = reader.read(); + + if (status == XML_STATUS_ERROR) { + std::ostringstream out; + + out << "input stream" << reader.get_position() << " " << reader.get_error_string(); + + _last_error = reader.get_error_code(); + _last_error_msg = out.str(); + } + + return status != XML_STATUS_ERROR; + } + + bool read(XMLReaderBase& reader, const std::string& display_path) + { + XML_Status status = reader.read(); + + if (status == XML_STATUS_ERROR) { + std::ostringstream out; + + out << display_path << reader.get_position() << " " << reader.get_error_string(); + + _last_error = reader.get_error_code(); + _last_error_msg = out.str(); + } + + return status != XML_STATUS_ERROR; + } + + /// write XML stream preserving previous white space and comments + std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const + { + header.print(out); + + if (!_children.empty()) + _children.front()->write(out); + + return out; + } + + /// write XML stream with formating + std::ostream& write_formating(std::ostream& out) const + { + return write(out, FORMAT_PRETTY); + } + + void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const + { + tofstream out(path); + + write(out, mode, header); + } + + void write_formating(LPCTSTR path) const + { + tofstream out(path); + + write_formating(out); + } + + XML_Error _last_error; + std::string _last_error_msg; +}; + + +struct XMLMessage : public XMLDoc +{ + XMLMessage(const char* name) + : _pos(this) + { + _pos.create(name); + } + + XMLPos _pos; +}; + + +} // namespace XMLStorage + +#define _XMLSTORAGE_H +#endif // _XMLSTORAGE_H diff --git a/reactos/subsys/system/ibrowser/webchild.cpp b/reactos/subsys/system/ibrowser/webchild.cpp new file mode 100644 index 00000000000..4b4bb484b4c --- /dev/null +++ b/reactos/subsys/system/ibrowser/webchild.cpp @@ -0,0 +1,309 @@ +/* + * Copyright 2004, 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // webchild.cpp + // + // Martin Fuchs, 25.01.2005 + // + + +#include "precomp.h" + +#include "ibrowser_intres.h" + +#include "webchild.h" + + +#ifdef _MSC_VER + +#if _MSC_VER>=1300 // vtMissing for VS.Net +#include +#pragma comment(lib, "comsupp") +#endif + +#else + +#ifdef __MINGW32__ // MinGW is lacking vtMissing (as of 07.02.2004) +static Variant vtMissing; +#endif + +#endif + +//#include + + +Variant::Variant(const VARIANT& var) +{ + VariantInit(this); + CheckError(VariantCopy(this, const_cast(&var))); +} + +Variant::Variant(const VARIANT* var) +{ + VariantInit(this); + CheckError(VariantCopy(this, const_cast(var))); +} + +Variant::~Variant() +{ + VariantClear(this); +} + + +Variant::operator long() const +{ + Variant v; + CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_I4)); + return V_I4(&v); +} + +Variant::operator bool() const +{ + Variant v; + CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL)); + return V_BOOL(&v)? true: false; +} + +Variant::operator IDispatch*() const +{ + Variant v; + CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_DISPATCH)); + return V_DISPATCH(&v); +} + +Variant::operator VARIANT_BOOL() const +{ + Variant v; + CheckError(VariantChangeType(&v, (VARIANT*)this, 0, VT_BOOL)); + return V_BOOL(&v); +} + + +void BStr::assign(BSTR s) +{ + if (!SysReAllocString(&_p, s)) + THROW_EXCEPTION(E_OUTOFMEMORY); +} + +void BStr::assign(const VARIANT& var) +{ + if (V_VT(&var) == VT_BSTR) + assign(V_BSTR(&var)); + else { + Variant v; + CheckError(VariantChangeType(&v, const_cast(&var), 0, VT_BSTR)); + assign(V_BSTR(&v)); + } +} + + +BrowserNavigator::BrowserNavigator() + : _browser_initialized(false) +{ +} + +void BrowserNavigator::attach(IWebBrowser* browser) +{ + _browser = browser; +} + +void BrowserNavigator::goto_url(LPCTSTR url) +{ + if (_browser_initialized) + _browser->Navigate(BStr(url), NULL, NULL, NULL, NULL); + else { + _new_url = url; + + _browser->Navigate(L"about:blank", NULL, NULL, NULL, NULL); + } +} + +void BrowserNavigator::set_html_page(const String& html_txt) +{ + _new_html_txt = html_txt; + + goto_url(TEXT("about:blank")); +} + +void T2nA_binary(LPCTSTR s, LPSTR d, int len) +{ + while(len-- > 0) + *d++ = (unsigned char)*s++; +} + +void BrowserNavigator::navigated(LPCTSTR url) +{ + _browser_initialized = true; + + bool nav = false; + + if (!_new_url.empty()) { + if (!_tcscmp(url,TEXT("about:blank")) && _new_url!=TEXT("about:blank")) { + _browser->Navigate(BStr(_new_url), NULL, NULL, NULL, NULL); + ++nav; + } + + _new_url.erase(); + } + + if (!nav && !_new_html_txt.empty()) { ///@todo move this into DocumentComplete() ? + int len = _new_html_txt.length(); + HGLOBAL hHtmlText = GlobalAlloc(GPTR, len); + + if (!hHtmlText) { + T2nA_binary(_new_html_txt, (char*)hHtmlText, len); + _new_html_txt.erase(); + + SIfacePtr pStream; + HRESULT hr = CreateStreamOnHGlobal(hHtmlText, TRUE, &pStream); + + if (SUCCEEDED(hr)) { + SIfacePtr pHtmlDoc; + CheckError(_browser->get_Document(&pHtmlDoc)); + + SIfacePtr pPersistStreamInit; + pHtmlDoc.QueryInterface(IID_IPersistStreamInit, &pPersistStreamInit); + + CheckError(pPersistStreamInit->InitNew()); + CheckError(pPersistStreamInit->Load(pStream)); + } else + GlobalFree(hHtmlText); + } + } +} + + +HWND create_webchildwindow(const WebChildWndInfo& info) +{ + WebChildWindow* pWnd = WebChildWindow::create(info); + + if (!pWnd) + return 0; + + return *pWnd; +} + +static const CLSID CLSID_MozillaBrowser = + {0x1339B54C, 0x3453, 0x11D2, {0x93, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + +WebChildWindow::WebChildWindow(HWND hwnd, const WebChildWndInfo& info) + : super(hwnd, info._hwndFrame), + web_super(_navigator) +{ + // first try to create a web control with MS IE's CLASSID + HRESULT hr = create_control(hwnd, CLSID_WebBrowser, IID_IWebBrowser2); + + // If this failed, try to use Mozilla's web control + if (FAILED(hr)) + hr = create_control(hwnd, CLSID_MozillaBrowser, IID_IWebBrowser2); + + if (SUCCEEDED(hr)) { + _navigator.attach(_control); + + _connector = auto_ptr(new EventConnector(_control, DIID_DWebBrowserEvents2, this)); + + // We need to call Navigate() here to initialize the browser control (see _browser_initialized) + _control->Navigate(BStr(info._url), &vtMissing, &vtMissing, &vtMissing, &vtMissing); + } +} + +LRESULT WebChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + try { + switch(nmsg) { + case WM_ERASEBKGND: + if (!_control) { + HDC hdc = (HDC)wparam; + ClientRect rect(_hwnd); + + HBRUSH hbrush = CreateSolidBrush(RGB(200,200,235)); + BkMode mode(hdc, TRANSPARENT); + TextColor color(hdc, RGB(200,40,40)); + FillRect(hdc, &rect, hbrush); + DrawText(hdc, TEXT("Sorry - no web browser control could be loaded."), -1, &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE); + DeleteObject(hbrush); + } + + return TRUE; + + + case PM_DISPATCH_COMMAND: { + if (_control) { + HRESULT hr = E_FAIL; + + switch(LOWORD(wparam)) { + case ID_GO_BACK: + hr = _control->GoBack(); + break; + + case ID_GO_FORWARD: + hr = _control->GoForward(); + break; + + case ID_GO_UP: + ///@todo + break; + + case ID_GO_HOME: + hr = _control->GoHome(); + break; + + case ID_GO_SEARCH: + hr = _control->GoSearch(); + break; + + case ID_REFRESH: + hr = _control->Refresh(); + break; + + case ID_STOP: + hr = _control->Stop(); + break; + + default: + return super::WndProc(nmsg, wparam, lparam); + } + + if (FAILED(hr) && hr!=E_FAIL) + THROW_EXCEPTION(hr); + } + + return TRUE;} + + default: + return super::WndProc(nmsg, wparam, lparam); + } + } catch(COMException& e) { + HandleException(e, _hwnd); + } + + return 0; +} + + +String WebChildWindow::jump_to_int(LPCTSTR url) +{ + _navigator.goto_url(url); + + return url; +} diff --git a/reactos/subsys/system/ibrowser/webchild.h b/reactos/subsys/system/ibrowser/webchild.h new file mode 100644 index 00000000000..3ffc2a36316 --- /dev/null +++ b/reactos/subsys/system/ibrowser/webchild.h @@ -0,0 +1,1079 @@ +/* + * Copyright 2004, 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // ROS Internet Web Browser + // + // webchild.h + // + // Martin Fuchs, 25.01.2005 + // + + +#ifndef _MSC_VER +#include // for IConnectionPointContainer +#include // for DWebBrowserEvents2 IDs +#endif + +#ifndef DISPID_BEFORENAVIGATE // missing in MinGW (as of 07.02.2004) +#define DISPID_BEFORENAVIGATE 100 +#define DISPID_NAVIGATECOMPLETE 101 +#define DISPID_STATUSTEXTCHANGE 102 +#define DISPID_QUIT 103 +#define DISPID_DOWNLOADCOMPLETE 104 +#define DISPID_COMMANDSTATECHANGE 105 +#define DISPID_DOWNLOADBEGIN 106 +#define DISPID_NEWWINDOW 107 +#define DISPID_PROGRESSCHANGE 108 +#define DISPID_WINDOWMOVE 109 +#define DISPID_WINDOWRESIZE 110 +#define DISPID_WINDOWACTIVATE 111 +#define DISPID_PROPERTYCHANGE 112 +#define DISPID_TITLECHANGE 113 +#define DISPID_TITLEICONCHANGE 114 +#define DISPID_FRAMEBEFORENAVIGATE 200 +#define DISPID_FRAMENAVIGATECOMPLETE 201 +#define DISPID_FRAMENEWWINDOW 204 + +#define DISPID_NAVIGATECOMPLETE2 252 +#define DISPID_ONQUIT 253 +#define DISPID_ONVISIBLE 254 +#define DISPID_ONTOOLBAR 255 +#define DISPID_ONMENUBAR 256 +#define DISPID_ONSTATUSBAR 257 +#define DISPID_ONFULLSCREEN 258 +#define DISPID_DOCUMENTCOMPLETE 259 +#define DISPID_ONTHEATERMODE 260 +#define DISPID_ONADDRESSBAR 261 +#define DISPID_WINDOWSETRESIZABLE 262 +#define DISPID_WINDOWCLOSING 263 +#define DISPID_WINDOWSETLEFT 264 +#define DISPID_WINDOWSETTOP 265 +#define DISPID_WINDOWSETWIDTH 266 +#define DISPID_WINDOWSETHEIGHT 267 +#define DISPID_CLIENTTOHOSTWINDOW 268 +#define DISPID_SETSECURELOCKICON 269 +#define DISPID_FILEDOWNLOAD 270 +#define DISPID_NAVIGATEERROR 271 +#define DISPID_PRIVACYIMPACTEDSTATECHANGE 272 +#endif + +#ifndef V_INT // missing in MinGW (as of 07.02.2004) +#define V_INT(x) V_UNION(x, intVal) +#endif + +#ifdef _MSC_VER +#define NOVTABLE __declspec(novtable) +#else +#define NOVTABLE +#endif +#define ANSUNC + +#ifdef _MSC_VER +#pragma warning(disable: 4355) // use of 'this' for initialization of _connector +#endif + + +struct NOVTABLE ComSrvObject // NOVTABLE erlaubt, da protected Destruktor +{ +protected: + ComSrvObject() : _ref(1) {} + virtual ~ComSrvObject() {} + + ULONG _ref; +}; + +struct SimpleComObject : public ComSrvObject +{ + ULONG IncRef() {return ++_ref;} + ULONG DecRef() {ULONG ref=--_ref; if (!ref) {_ref++; delete this;} return ref;} +}; + + + // server object interfaces + +template struct IComSrvQI : public BASE +{ + IComSrvQI(REFIID uuid_base) + : _uuid_base(uuid_base) + { + } + + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv) {*ppv=0; + if (IsEqualIID(riid, _uuid_base) || + IsEqualIID(riid, IID_IUnknown)) {*ppv=static_cast(this); this->AddRef(); return S_OK;} + return E_NOINTERFACE;} + +protected: + IComSrvQI() {} + + REFIID _uuid_base; +}; + +template<> struct IComSrvQI : public IUnknown +{ + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv) {*ppv=0; + if (IsEqualIID(riid, IID_IUnknown)) {*ppv=this; AddRef(); return S_OK;} + return E_NOINTERFACE;} + +protected: + IComSrvQI() {} +}; + + +template + class IComSrvBase : public IComSrvQI +{ + typedef IComSrvQI super; + +protected: + IComSrvBase(REFIID uuid_base) + : super(uuid_base) + { + } + +public: + STDMETHODIMP_(ULONG) AddRef() {return static_cast(this)->IncRef();} + STDMETHODIMP_(ULONG) Release() {return static_cast(this)->DecRef();} +}; + + +template struct ConnectionPoint : public SIfacePtr +{ + ConnectionPoint(IConnectionPointContainer* pCPC, REFIID riid) + { + CheckError(pCPC->FindConnectionPoint(riid, &this->_p)); + } +}; + +struct EventConnection +{ + EventConnection(IConnectionPoint* connectionpoint, IUnknown* sink) + { + CheckError(connectionpoint->Advise(sink, &_cookie)); + _connectionpoint = connectionpoint; + } + + template EventConnection(T& connectionpoint, IUnknown* sink) + { + CheckError(connectionpoint->Advise(sink, &_cookie)); + _connectionpoint = connectionpoint; + } + +/* template EventConnection(SIfacePtr& connectionpoint, IUnknown* sink) + { + CheckError(connectionpoint->Advise(sink, &_cookie)); + _connectionpoint = connectionpoint.GetPtr(); + } */ + +/* template EventConnection(T& connectionpoint, IUnknown* sink) + { + CheckError(connectionpoint->Advise(sink, &_cookie)); + _connectionpoint = connectionpoint; + } */ + + ~EventConnection() + { + if (_connectionpoint) + _connectionpoint->Unadvise(_cookie); + } + +protected: + SIfacePtr _connectionpoint; + DWORD _cookie; +}; + +struct EventConnector : public EventConnection +{ + EventConnector(IUnknown* unknown, REFIID riid, IUnknown* sink) + : EventConnection(ConnectionPoint( + SIfacePtr(unknown, IID_IConnectionPointContainer), riid), sink) + { + } +}; + + +struct OleInPlaceClient : public SimpleComObject, + public IOleClientSite, + public IOleInPlaceSite +{ +protected: + HWND _hwnd; + +public: + OleInPlaceClient(HWND hwnd=0) + : _hwnd(hwnd) + { + } + + void attach(HWND hwnd) + { + _hwnd = hwnd; + } + + HRESULT attach_control(IOleObject* ole_obj, LONG iVerb=OLEIVERB_INPLACEACTIVATE, HWND hwndParent=0, LPCRECT pRect=NULL) + { + HRESULT hr = ole_obj->SetClientSite(this); + if (FAILED(hr)) + return hr; + +// hr = ole_obj->SetHostNames(app, doc)); + + hr = ole_obj->DoVerb(iVerb, NULL, this, 0, 0/*hwnd*/, NULL/*&rcPos*/); + + return hr; + } + + HRESULT detach(IOleObject* ole_obj, DWORD dwSaveOption=OLECLOSE_SAVEIFDIRTY) + { + HRESULT hr = ole_obj->Close(dwSaveOption); + + _hwnd = 0; + + return hr; + } + + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv) + { + if (IsEqualIID(riid, IID_IOleClientSite)) + {*ppv=static_cast(this); IncRef(); return S_OK;} + + if (IsEqualIID(riid, IID_IOleInPlaceSite)) + {*ppv=static_cast(this); IncRef(); return S_OK;} + + if (IsEqualIID(riid, IID_IUnknown)) + {*ppv=static_cast(this); IncRef(); return S_OK;} + + return E_NOINTERFACE; + } + + STDMETHODIMP_(ULONG) AddRef() {return IncRef();} + STDMETHODIMP_(ULONG) Release() {return DecRef();} + + + // IOleWindow: + + virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow(/* [out] */ HWND __RPC_FAR *phwnd) + { + *phwnd = _hwnd; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(/* [in] */ BOOL fEnterMode) + { + return E_NOTIMPL; + } + + + // IOleClientSite: + + virtual HRESULT STDMETHODCALLTYPE SaveObject() + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker __RPC_FAR *__RPC_FAR *ppmk) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer __RPC_FAR *__RPC_FAR *ppContainer) + { + ppContainer = 0; + return E_NOINTERFACE; + } + + virtual HRESULT STDMETHODCALLTYPE ShowObject() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() + { + return S_OK; + } + + + // IOleInPlaceSite: + + virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnUIActivate() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetWindowContext( + /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame, + /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc, + /* [out] */ LPRECT lprcPosRect, + /* [out] */ LPRECT lprcClipRect, + /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo) + { + ClientRect rect(_hwnd); + + ppFrame = 0; + ppDoc = 0; + *lprcPosRect = rect; + *lprcClipRect = rect; + + assert(lpFrameInfo->cb>=sizeof(OLEINPLACEFRAMEINFO)); + lpFrameInfo->fMDIApp = FALSE; + lpFrameInfo->hwndFrame = 0; + lpFrameInfo->haccel = 0; + lpFrameInfo->cAccelEntries = 0; + + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE Scroll(/* [in] */ SIZE scrollExtant) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate(/* [in] */ BOOL fUndoable) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE DiscardUndoState() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo() + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnPosRectChange(/* [in] */ LPCRECT lprcPosRect) + { + return S_OK; + } +}; + + + // window with in place activates Active-X Control + +template struct IPCtrlWindow : public BASE +{ + typedef BASE super; + + IPCtrlWindow(HWND hwnd) + : super(hwnd) + { + } + + template IPCtrlWindow(HWND hwnd, T& info) + : super(hwnd, info) + { + } + + HRESULT create_control(HWND hwnd, REFIID clsid, REFIID riid) + { + // Erzeugen einer Instanz des Controls + HRESULT hr = _control.CreateInstance(clsid, riid); + if (FAILED(hr)) + return hr; + + _client_side.attach(hwnd); + + hr = _client_side.attach_control(SIfacePtr(_control, IID_IOleObject)/*, OLEIVERB_INPLACEACTIVATE, + hwnd, &Rect(10, 10, 500, 500)*/); + if (FAILED(hr)) + return hr; + + // try to get a IOleInPlaceObject interface for window resizing + return _control.QueryInterface(IID_IOleInPlaceObject, &_in_place_object); // _in_place_object = _control + } + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + if (nmsg == WM_SIZE) { + if (_in_place_object) { + RECT rect = {0, 0, LOWORD(lparam), HIWORD(lparam)}; + + _in_place_object->SetObjectRects(&rect, &rect); + } + } else if (nmsg == WM_CLOSE) { + _in_place_object = NULL; + + if (_control) { + _client_side.detach(SIfacePtr(_control, IID_IOleObject), OLECLOSE_NOSAVE); + _control = NULL; + } + } + + return super::WndProc(nmsg, wparam, lparam); + } + + ComInit _usingCOM; + SMARTPTR _control; + OleInPlaceClient _client_side; + SIfacePtr _in_place_object; +}; + + + +#include "exdispid.h" + + +struct DWebBrowserEvents2IF +{ + virtual void StatusTextChange(const BStr& text) + {} + + virtual void ProgressChange(long progress, long progressMax) + {} + + virtual void WindowMove() + {} + + virtual void WindowResize() + {} + + virtual void WindowActivate() + {} + + virtual void PropertyChange(const BStr& property) + {} + + virtual void DownloadComplete() + {} + + virtual void CommandStateChange(long command, bool enable) + {} + + virtual void DownloadBegin() + {} + + virtual void NewWindow2(IDispatch** ppDisp, VARIANT_BOOL& cancel) + {} + + virtual void TitleChange(const BStr& text) + {} + + virtual void TitleIconChange(const BStr& text) + {} + + virtual void FrameBeforeNavigate(const BStr& url, long flags, const BStr& targetFrameName, VARIANT* postData, const BStr& headers, VARIANT_BOOL& cancel) + {} + + virtual void FrameNavigateComplete(const BStr& url) + {} + + virtual void FrameNewWindow(const BStr&url, long flags, const BStr& targetFrameName, VARIANT* postData, const BStr& headers, VARIANT_BOOL& processed) + {} + + virtual void BeforeNavigate2(IDispatch* pDisp, const Variant& url, const Variant& flags, + const Variant& targetFrameName, const Variant& postData, + const Variant& headers, VARIANT_BOOL& cancel) + {} + + virtual void NavigateComplete2(IDispatch* pDisp, const Variant& url) + {} + + virtual void OnQuit() + {} + + virtual void OnVisible(bool Visible) + {} + + virtual void OnToolbar(bool Visible) + {} + + virtual void OnMenubar(bool Visible) + {} + + virtual void OnStatusbar(bool Visible) + {} + + virtual void OnFullscreen(bool Visible) + {} + + virtual void DocumentComplete() + {} + + virtual void OnTheatermode(bool Visible) + {} + + virtual void OnAddressbar(bool Visible) + {} + + virtual void WindowSetResizable(bool Visible) + {} + + virtual void WindowClosing(VARIANT_BOOL IsChildWindow, VARIANT_BOOL& cancel) + {} + + virtual void WindowSetLeft(long Left) + {} + + virtual void WindowSetTop(long Top) + {} + + virtual void WindowSetWidth(long Width) + {} + + virtual void WindowSetHeight(long Height) + {} + + virtual void ClientToHostWindow(long& CX, long& CY) + {} + + virtual void SetSecureLockIcon(long SecureLockIcon) + {} + + virtual void FileDownload(Variant& cancel) + {} + + virtual void NavigateError(IDispatch* pDisp, const Variant& url, const Variant& Frame, const Variant& StatusCode, VARIANT_BOOL& cancel) + {} + + virtual void PrivacyImpactedStateChange(bool bImpacted) + {} +}; + + + // The web browser control has to be initialized completely before being able, + // to display a page, that does not access internet. +struct ANSUNC BrowserNavigator +{ + BrowserNavigator(); + + void attach(IWebBrowser* browser); + void goto_url(LPCTSTR url); + void set_html_page(const String& html_txt); + void navigated(LPCTSTR url); + + IWebBrowser* get_browser() {return _browser.get();} + +protected: + SIfacePtr _browser; + String _new_url; + String _new_html_txt; + bool _browser_initialized; +}; + + + // MinGW defines a wrong FixedDWebBrowserEvents2 interface with virtual functions for DISPID calls, so we use our own, corrected version: +interface FixedDWebBrowserEvents2 : public IDispatch +{ +}; + +struct ANSUNC DWebBrowserEvents2Impl : public SimpleComObject, + public IComSrvBase, + public DWebBrowserEvents2IF +{ + typedef IComSrvBase super; + + + DWebBrowserEvents2IF* _callback; + + + DWebBrowserEvents2Impl(BrowserNavigator& navigator) + : super(DIID_DWebBrowserEvents2), + _navigator(navigator) + { + _callback = this; + } + + +/* // IUnknown + STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv) + { + *ppv = NULL; + + if (SUCCEEDED(super::QueryInterface(riid, ppv))) + return S_OK; + + return E_NOINTERFACE; + } */ + + + // IDispatch + STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) + {return E_NOTIMPL;} + + STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) + {return E_NOTIMPL;} + + STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) + {return E_NOTIMPL;} + + STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr) + { + switch(dispIdMember) { + case DISPID_STATUSTEXTCHANGE: + _callback->StatusTextChange((BStr)Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_COMMANDSTATECHANGE: + _callback->CommandStateChange(Variant(pDispParams->rgvarg[1]), Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_DOWNLOADBEGIN: + _callback->DownloadBegin(); + break; + + case DISPID_PROGRESSCHANGE: // sent when download progress is updated + _callback->ProgressChange(Variant(pDispParams->rgvarg[1]), Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWMOVE: // sent when main window has been moved + _callback->WindowMove(); + break; + + case DISPID_WINDOWRESIZE: // sent when main window has been sized + _callback->WindowResize(); + break; + + case DISPID_WINDOWACTIVATE: // sent when main window has been activated + _callback->WindowActivate(); + break; + + case DISPID_PROPERTYCHANGE: // sent when the PutProperty method is called + _callback->PropertyChange((BStr)Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_TITLECHANGE: // sent when the document title changes + _callback->TitleChange((BStr)Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_TITLEICONCHANGE: // sent when the top level window icon may have changed. + _callback->TitleIconChange((BStr)Variant(pDispParams->rgvarg[0])); + break; + + + // anything below here is not present in DWebBrowserEvents, only in DWebBrowserEvents2: -> + + case DISPID_FRAMEBEFORENAVIGATE: + if (pDispParams->cArgs != 6) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + _callback->FrameBeforeNavigate( + (BStr)Variant(&pDispParams->rgvarg[5]), Variant(&pDispParams->rgvarg[4]), + (BStr)Variant(&pDispParams->rgvarg[3]), &pDispParams->rgvarg[2], + (BStr)Variant(&pDispParams->rgvarg[1]), *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_FRAMENAVIGATECOMPLETE: + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->FrameNavigateComplete((BStr)Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_FRAMENEWWINDOW: + if (pDispParams->cArgs != 6) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + _callback->FrameNewWindow((BStr)Variant(&pDispParams->rgvarg[5]), Variant(&pDispParams->rgvarg[4]), + (BStr)Variant(&pDispParams->rgvarg[3]), &pDispParams->rgvarg[2], + (BStr)Variant(&pDispParams->rgvarg[1]), *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_BEFORENAVIGATE2: // hyperlink clicked on + if (pDispParams->cArgs != 7) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + _callback->BeforeNavigate2(Variant(pDispParams->rgvarg[6]), + pDispParams->rgvarg[5], &pDispParams->rgvarg[4], + pDispParams->rgvarg[3], &pDispParams->rgvarg[2], + pDispParams->rgvarg[1], *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_NEWWINDOW2: // sent when a new window should be created + if (pDispParams->cArgs != 2) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[1]) != (VT_DISPATCH|VT_BYREF)) + return E_INVALIDARG; + _callback->NewWindow2(V_DISPATCHREF(&pDispParams->rgvarg[1]), *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_NAVIGATECOMPLETE2:// UIActivate new document + if (pDispParams->cArgs != 2) + return E_INVALIDARG; + + // notify the navigator + NavigateComplete2(Variant(pDispParams->rgvarg[1]), Variant(pDispParams->rgvarg[0])); + + _callback->NavigateComplete2(Variant(pDispParams->rgvarg[1]), Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONQUIT: + _callback->OnQuit(); + break; + + case DISPID_ONVISIBLE: // sent when the window goes visible/hidden + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnVisible(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONTOOLBAR: // sent when the toolbar should be shown/hidden + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnToolbar(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONMENUBAR: // sent when the menubar should be shown/hidden + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnMenubar(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONSTATUSBAR: // sent when the statusbar should be shown/hidden + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnStatusbar(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONFULLSCREEN: // sent when kiosk mode should be on/off + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnFullscreen(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_DOCUMENTCOMPLETE:// new document goes ReadyState_Complete + _callback->DocumentComplete(); + break; + + case DISPID_DOWNLOADCOMPLETE: + _callback->DownloadComplete(); + break; + + case DISPID_ONTHEATERMODE: // sent when theater mode should be on/off + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnTheatermode(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_ONADDRESSBAR: // sent when the address bar should be shown/hidden + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->OnAddressbar(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWSETRESIZABLE:// sent to set the style of the host window frame + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->WindowSetResizable(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWCLOSING: // sent before script window.close closes the window + if (pDispParams->cArgs != 2) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + _callback->WindowClosing(Variant(pDispParams->rgvarg[1]), *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWSETLEFT: // sent when the put_left method is called on the WebOC + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->WindowSetLeft(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWSETTOP: // sent when the put_top method is called on the WebOC + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->WindowSetTop(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWSETWIDTH: // sent when the put_width method is called on the WebOC + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->WindowSetWidth(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_WINDOWSETHEIGHT: // sent when the put_height method is called on the WebOC + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->WindowSetHeight(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_CLIENTTOHOSTWINDOW:// sent during window.open to request conversion of dimensions + if (pDispParams->cArgs != 2) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_I4|VT_BYREF)) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[1]) != (VT_I4|VT_BYREF)) + return E_INVALIDARG; + _callback->ClientToHostWindow(*V_I4REF(&pDispParams->rgvarg[1]), *V_I4REF(&pDispParams->rgvarg[0])); + break; + + case DISPID_SETSECURELOCKICON:// sent to suggest the appropriate security icon to show + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->SetSecureLockIcon(Variant(pDispParams->rgvarg[0])); + break; + + case DISPID_FILEDOWNLOAD: { // Fired to indicate the File Download dialog is opening + if (pDispParams->cArgs != 1) //@@ every time 2 ?! + return E_INVALIDARG; + Variant var(pDispParams->rgvarg[0]); + _callback->FileDownload(var);} + break; + + case DISPID_NAVIGATEERROR: // Fired to indicate the a binding error has occured + if (pDispParams->cArgs != 5) + return E_INVALIDARG; + if (V_VT(&pDispParams->rgvarg[0]) != (VT_BOOL|VT_BYREF)) + return E_INVALIDARG; + _callback->NavigateError(Variant(pDispParams->rgvarg[4]), Variant(pDispParams->rgvarg[3]), + Variant(pDispParams->rgvarg[2]), Variant(pDispParams->rgvarg[1]), + *V_BOOLREF(&pDispParams->rgvarg[0])); + break; + + case DISPID_PRIVACYIMPACTEDSTATECHANGE:// Fired when the user's browsing experience is impacted + if (pDispParams->cArgs != 1) + return E_INVALIDARG; + _callback->PrivacyImpactedStateChange(Variant(pDispParams->rgvarg[0])); + break; + + default: + return NOERROR; + } + + return S_OK; + } + +protected: + BrowserNavigator& _navigator; + + void NavigateComplete2(IDispatch* pDisp, const Variant& url) + { + String adr = (BStr)url; + + _navigator.navigated(adr); + } +}; + + + /// encapsulation of the Web control +struct WebChildWindow : public IPCtrlWindow >, + public DWebBrowserEvents2Impl +{ + typedef IPCtrlWindow > super; + typedef DWebBrowserEvents2Impl web_super; + + WebChildWindow(HWND hwnd, const WebChildWndInfo& info); + + static WebChildWindow* create(const WebChildWndInfo& info) + { + ChildWindow* child = ChildWindow::create(info, + WINDOW_CREATOR_INFO(WebChildWindow,WebChildWndInfo), CLASSNAME_CHILDWND, NULL, WS_CHILD|WS_VISIBLE); + + return static_cast(child); + } + + + // DWebBrowserEvents2Impl overides -> + + void BeforeNavigate2(IDispatch* pDisp, const Variant& url, const Variant& flags, + const Variant& targetFrameName, const Variant& postData, + const Variant& headers, VARIANT_BOOL& cancel) + { + //String adr = (BStr)url; + } + + void NavigateComplete2(IDispatch* pDisp, const Variant& url) + { + web_super::NavigateComplete2(pDisp, url); + + set_url(String(BStr(url))); + } + + void StatusTextChange(const BStr& text) + { + _statusText = text; + SendMessage(_hwndFrame, PM_SETSTATUSTEXT, 0, (LPARAM)_statusText.c_str()); + } + + void ProgressChange(long Progress, long ProgressMax) + { + } + + void WindowMove() + { + } + + void WindowResize() + { + } + + void WindowActivate() + { + } + + void PropertyChange(const BStr& Property) + { + Variant value; + _control->GetProperty(Property, &value); + } + + void CommandStateChange(long command/*CSC_NAVIGATEFORWARD, CSC_NAVIGATEBACK*/, bool enable) + { + } + + void DownloadBegin() + { + } + + void NewWindow2(IDispatch** ppDisp, VARIANT_BOOL& cancel) + { + //*ppDisp = ; + //cancel = TRUE; + } + + void TitleChange(const BStr& text) + { + SetWindowText(_hwnd, String(text)); + } + + void TitleIconChange(const BStr& text) + { + } + + void FrameBeforeNavigate(const BStr& url, long flags, const BStr& targetFrameName, VARIANT* postData, const BStr& headers, VARIANT_BOOL& cancel) + { + } + + void FrameNavigateComplete(const BStr& url) + { + } + + void FrameNewWindow(const BStr& url, long flags, const BStr& targetFrameName, VARIANT* postData, const BStr& headers, VARIANT_BOOL& processed) + { + } + + void OnQuit() + { + } + + void OnVisible(bool Visible) + { + } + + void OnToolbar(bool Visible) + { + } + + void OnMenubar(bool Visible) + { + } + + void OnStatusbar(bool Visible) + { + } + + void OnFullscreen(bool Visible) + { + } + + void DocumentComplete() + { + } + + void OnTheatermode(bool Visible) + { + } + + void OnAddressbar(bool Visible) + { + } + + void WindowSetResizable(bool Visible) + { + } + + void WindowClosing(VARIANT_BOOL IsChildWindow, VARIANT_BOOL& cancel) + { + } + + void WindowSetLeft(long Left) + { + } + + void WindowSetTop(long Top) + { + } + + void WindowSetWidth(long Width) + { + } + + void WindowSetHeight(long Height) + { + } + + void ClientToHostWindow(long& CX, long& CY) + { + } + + void SetSecureLockIcon(long SecureLockIcon) + { + } + + void FileDownload(Variant& cancel) + { + } + + void NavigateError(IDispatch* pDisp, const Variant& url, const Variant& Frame, const Variant& StatusCode, VARIANT_BOOL& cancel) + { + } + + void PrivacyImpactedStateChange(bool bImpacted) + { + } + + +protected: + BrowserNavigator _navigator; + auto_ptr _connector; + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + + virtual String jump_to_int(LPCTSTR url); +}; diff --git a/reactos/subsys/system/regedit/De.rc b/reactos/subsys/system/regedit/De.rc index ffef207a04c..72bf036b38a 100644 --- a/reactos/subsys/system/regedit/De.rc +++ b/reactos/subsys/system/regedit/De.rc @@ -255,6 +255,7 @@ END STRINGTABLE DISCARDABLE BEGIN IDS_ERROR "Fehler" + IDS_WARNING "Warnung" IDS_BAD_VALUE "Kann den Wert '%s' nicht lesen" IDS_UNSUPPORTED_TYPE "Kann den Schlüssel des Typen (%ld) nicht ändern" IDS_TOO_BIG_VALUE "Der Wert (%ld) ist zu groß" diff --git a/reactos/subsys/system/services/database.c b/reactos/subsys/system/services/database.c index c03c68aba32..033e01916e1 100644 --- a/reactos/subsys/system/services/database.c +++ b/reactos/subsys/system/services/database.c @@ -32,6 +32,7 @@ #include #include +#include #include "services.h" #define NDEBUG @@ -81,7 +82,7 @@ LIST_ENTRY ServiceListHead; /* FUNCTIONS *****************************************************************/ -static NTSTATUS STDCALL +static NTSTATUS STDCALL CreateGroupOrderListRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, @@ -127,6 +128,7 @@ CreateGroupOrderListRoutine(PWSTR ValueName, return STATUS_SUCCESS; } + static NTSTATUS STDCALL CreateGroupListRoutine(PWSTR ValueName, ULONG ValueType, @@ -148,15 +150,15 @@ CreateGroupListRoutine(PWSTR ValueName, sizeof(SERVICE_GROUP)); if (Group == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData)) { - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } - + RtlZeroMemory(&QueryTable, sizeof(QueryTable)); QueryTable[0].Name = (PWSTR)ValueData; QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine; @@ -173,7 +175,7 @@ CreateGroupListRoutine(PWSTR ValueName, &Group->GroupListEntry); } - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -191,7 +193,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) sizeof(SERVICE)); if (Service == NULL) { - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } /* Copy service name */ @@ -202,8 +204,9 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) if (Service->ServiceName.Buffer == NULL) { HeapFree(GetProcessHeap(), 0, Service); - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } + RtlCopyMemory(Service->ServiceName.Buffer, ServiceName->Buffer, ServiceName->Length); @@ -217,8 +220,9 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) { HeapFree(GetProcessHeap(), 0, Service->ServiceName.Buffer); HeapFree(GetProcessHeap(), 0, Service); - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } + wcscpy(Service->RegistryPath.Buffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); wcscat(Service->RegistryPath.Buffer, @@ -260,7 +264,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) RtlFreeUnicodeString(&Service->RegistryPath); RtlFreeUnicodeString(&Service->ServiceName); HeapFree(GetProcessHeap(), 0, Service); - return(Status); + return Status; } DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); @@ -273,7 +277,7 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) InsertTailList(&ServiceListHead, &Service->ServiceListEntry); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -311,7 +315,7 @@ ScmCreateServiceDataBase(VOID) NULL, NULL); if (!NT_SUCCESS(Status)) - return(Status); + return Status; RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"); @@ -327,7 +331,7 @@ ScmCreateServiceDataBase(VOID) &ObjectAttributes, 0); if (!NT_SUCCESS(Status)) - return(Status); + return Status; /* Allocate key info buffer */ KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR); @@ -335,7 +339,7 @@ ScmCreateServiceDataBase(VOID) if (KeyInfo == NULL) { NtClose(ServicesKey); - return(STATUS_INSUFFICIENT_RESOURCES); + return STATUS_INSUFFICIENT_RESOURCES; } Index = 0; @@ -379,7 +383,7 @@ ScmCreateServiceDataBase(VOID) DPRINT("ScmCreateServiceDataBase() done\n"); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -390,7 +394,7 @@ ScmCheckDriver(PSERVICE Service) UNICODE_STRING DirName; HANDLE DirHandle; NTSTATUS Status; - PDIRECTORY_BASIC_INFORMATION DirInfo; + POBJECT_DIRECTORY_INFORMATION DirInfo; ULONG BufferLength; ULONG DataLength; ULONG Index; @@ -421,10 +425,10 @@ ScmCheckDriver(PSERVICE Service) &ObjectAttributes); if (!NT_SUCCESS(Status)) { - return(Status); + return Status; } - BufferLength = sizeof(DIRECTORY_BASIC_INFORMATION) + + BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) + 2 * MAX_PATH * sizeof(WCHAR); DirInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -485,7 +489,7 @@ ScmCheckDriver(PSERVICE Service) DirInfo); NtClose(DirHandle); - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -518,17 +522,222 @@ ScmGetBootAndSystemDriverState(VOID) static NTSTATUS -ScmStartService(PSERVICE Service, - PSERVICE_GROUP Group) +ScmSendStartCommand(PSERVICE Service, LPWSTR Arguments) { + PSCM_START_PACKET StartPacket; + DWORD TotalLength; #if 0 + DWORD Length; +#endif + PWSTR Ptr; + DWORD Count; + + DPRINT("ScmSendStartCommand() called\n"); + + /* Calculate the total length of the start command line */ + TotalLength = wcslen(Service->ServiceName.Buffer) + 1; +#if 0 + if (Arguments != NULL) + { + Ptr = Arguments; + while (*Ptr) + { + Length = wcslen(Ptr) + 1; + TotalLength += Length; + Ptr += Length; + } + } +#endif + TotalLength++; + + /* Allocate start command packet */ + StartPacket = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR)); + if (StartPacket == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + StartPacket->Command = SCM_START_COMMAND; + StartPacket->Size = TotalLength; + Ptr = &StartPacket->Arguments[0]; + wcscpy(Ptr, Service->ServiceName.Buffer); + Ptr += (wcslen(Service->ServiceName.Buffer) + 1); + + /* FIXME: Copy argument list */ + + *Ptr = 0; + + /* Send the start command */ + WriteFile(Service->ControlPipeHandle, + StartPacket, + sizeof(SCM_START_PACKET) + (TotalLength - 1) * sizeof(WCHAR), + &Count, + NULL); + + /* FIXME: Read the reply */ + + HeapFree(GetProcessHeap(), + 0, + StartPacket); + + DPRINT("ScmSendStartCommand() done\n"); + + return STATUS_SUCCESS; +} + + +static NTSTATUS +ScmStartUserModeService(PSERVICE Service) +{ RTL_QUERY_REGISTRY_TABLE QueryTable[3]; PROCESS_INFORMATION ProcessInformation; STARTUPINFOW StartupInfo; UNICODE_STRING ImagePath; ULONG Type; BOOL Result; -#endif + NTSTATUS Status; + + RtlInitUnicodeString(&ImagePath, NULL); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Type"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &Type; + + QueryTable[1].Name = L"ImagePath"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[1].EntryContext = &ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + Service->ServiceName.Buffer, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + return Status; + } + DPRINT("ImagePath: '%S'\n", ImagePath.Buffer); + DPRINT("Type: %lx\n", Type); + + /* Create '\\.\pipe\net\NtControlPipe' instance */ + Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 100, + 8000, + 4, + 30000, + NULL); + DPRINT("CreateNamedPipeW() done\n"); + if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE) + { + DPRINT1("Failed to create control pipe!\n"); + return STATUS_UNSUCCESSFUL; + } + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcessW(ImagePath.Buffer, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS | CREATE_SUSPENDED, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + RtlFreeUnicodeString(&ImagePath); + + if (!Result) + { + /* Close control pipe */ + CloseHandle(Service->ControlPipeHandle); + Service->ControlPipeHandle = INVALID_HANDLE_VALUE; + + DPRINT1("Starting '%S' failed!\n", Service->ServiceName.Buffer); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("Process Id: %lu Handle %lx\n", + ProcessInformation.dwProcessId, + ProcessInformation.hProcess); + DPRINT("Thread Id: %lu Handle %lx\n", + ProcessInformation.dwThreadId, + ProcessInformation.hThread); + + /* Get process and thread ids */ + Service->ProcessId = ProcessInformation.dwProcessId; + Service->ThreadId = ProcessInformation.dwThreadId; + + /* Resume Thread */ + ResumeThread(ProcessInformation.hThread); + + /* Connect control pipe */ + if (ConnectNamedPipe(Service->ControlPipeHandle, NULL)) + { + DWORD dwProcessId = 0; + DWORD dwRead = 0; + + DPRINT("Control pipe connected!\n"); + + /* Read thread id from pipe */ + if (!ReadFile(Service->ControlPipeHandle, + (LPVOID)&dwProcessId, + sizeof(DWORD), + &dwRead, + NULL)) + { + DPRINT1("Reading the service control pipe failed (Error %lu)\n", + GetLastError()); + Status = STATUS_UNSUCCESSFUL; + } + else + { + DPRINT("Received process id %lu\n", dwProcessId); + + /* FIXME: Send start command */ + + Status = STATUS_SUCCESS; + } + } + else + { + DPRINT("Connecting control pipe failed!\n"); + + /* Close control pipe */ + CloseHandle(Service->ControlPipeHandle); + Service->ControlPipeHandle = INVALID_HANDLE_VALUE; + Service->ProcessId = 0; + Service->ThreadId = 0; + Status = STATUS_UNSUCCESSFUL; + } + + ScmSendStartCommand(Service, NULL); + + /* Close process and thread handle */ + CloseHandle(ProcessInformation.hThread); + CloseHandle(ProcessInformation.hProcess); + + return Status; +} + + +static NTSTATUS +ScmStartService(PSERVICE Service, + PSERVICE_GROUP Group) +{ NTSTATUS Status; DPRINT("ScmStartService() called\n"); @@ -546,123 +755,12 @@ ScmStartService(PSERVICE Service, } else { -#if 0 - RtlInitUnicodeString(&ImagePath, NULL); - - /* Get service data */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"Type"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &Type; - - QueryTable[1].Name = L"ImagePath"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[1].EntryContext = &ImagePath; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - Service->ServiceName.Buffer, - QueryTable, - NULL, - NULL); - if (NT_SUCCESS(Status)) - { - DPRINT("ImagePath: '%S'\n", ImagePath.Buffer); - DPRINT("Type: %lx\n", Type); - - /* FIXME: create '\\.\pipe\net\NtControlPipe' instance */ - Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", - PIPE_ACCESS_DUPLEX, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, - 100, - 8000, - 4, - 30000, - NULL); - DPRINT("CreateNamedPipeW() done\n"); - if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE) - { - DPRINT1("Failed to create control pipe!\n"); - Status = STATUS_UNSUCCESSFUL; - goto Done; - } - - StartupInfo.cb = sizeof(StartupInfo); - StartupInfo.lpReserved = NULL; - StartupInfo.lpDesktop = NULL; - StartupInfo.lpTitle = NULL; - StartupInfo.dwFlags = 0; - StartupInfo.cbReserved2 = 0; - StartupInfo.lpReserved2 = 0; - - Result = CreateProcessW(ImagePath.Buffer, - NULL, - NULL, - NULL, - FALSE, - DETACHED_PROCESS | CREATE_SUSPENDED, - NULL, - NULL, - &StartupInfo, - &ProcessInformation); - RtlFreeUnicodeString(&ImagePath); - - if (!Result) - { - /* Close control pipe */ - CloseHandle(Service->ControlPipeHandle); - Service->ControlPipeHandle = INVALID_HANDLE_VALUE; - - DPRINT("Starting '%S' failed!\n", Service->ServiceName.Buffer); - Status = STATUS_UNSUCCESSFUL; - } - else - { - DPRINT("Process Id: %lu Handle %lx\n", - ProcessInformation.dwProcessId, - ProcessInformation.hProcess); - DPRINT("Thread Id: %lu Handle %lx\n", - ProcessInformation.dwThreadId, - ProcessInformation.hThread); - - /* Get process and thread ids */ - Service->ProcessId = ProcessInformation.dwProcessId; - Service->ThreadId = ProcessInformation.dwThreadId; - - /* Resume Thread */ - ResumeThread(ProcessInformation.hThread); - - /* FIXME: connect control pipe */ - if (ConnectNamedPipe(Service->ControlPipeHandle, NULL)) - { - DPRINT("Control pipe connected!\n"); - Status = STATUS_SUCCESS; - } - else - { - DPRINT1("Connecting control pipe failed!\n"); - - /* Close control pipe */ - CloseHandle(Service->ControlPipeHandle); - Service->ControlPipeHandle = INVALID_HANDLE_VALUE; - Service->ProcessId = 0; - Service->ThreadId = 0; - Status = STATUS_UNSUCCESSFUL; - } - - /* Close process and thread handle */ - CloseHandle(ProcessInformation.hThread); - CloseHandle(ProcessInformation.hProcess); - } - } -#endif - Status = STATUS_SUCCESS; + /* Start user-mode service */ + Status = ScmStartUserModeService(Service); } -#if 0 -Done: -#endif + DPRINT("ScmStartService() done (Status %lx)\n", Status); + if (NT_SUCCESS(Status)) { if (Group != NULL) @@ -674,36 +772,34 @@ Done: #if 0 else { - if (CurrentService->ErrorControl == 1) + switch (Service->ErrorControl) { - /* Log error */ + case SERVICE_ERROR_NORMAL: + /* FIXME: Log error */ + break; - } - else if (CurrentService->ErrorControl == 2) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ + case SERVICE_ERROR_SEVERE: + if (IsLastKnownGood == FALSE) + { + /* FIXME: Boot last known good configuration */ + } + break; - } - } - else if (CurrentService->ErrorControl == 3) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ - - } - else - { - /* BSOD! */ - - } + case SERVICE_ERROR_CRITICAL: + if (IsLastKnownGood == FALSE) + { + /* FIXME: Boot last known good configuration */ + } + else + { + /* FIXME: BSOD! */ + } + break; } } #endif - return(STATUS_SUCCESS); + return Status; } diff --git a/reactos/subsys/system/taskmgr/De.rc b/reactos/subsys/system/taskmgr/De.rc index 1a4dd28e75b..9120c2e91aa 100644 --- a/reactos/subsys/system/taskmgr/De.rc +++ b/reactos/subsys/system/taskmgr/De.rc @@ -597,8 +597,8 @@ BEGIN ID_VIEW_SMALL "Zeigt Tasks als kleine Symbole an." ID_VIEW_DETAILS "Zeigt Informationen über jeden Task an." ID_VIEW_UPDATESPEED_HIGH "Aktualisiert die Anzeige zweimal pro Sekunde." - ID_VIEW_UPDATESPEED_NORMAL "Aktualisiert die Anzeige alle zwei Sekunde." - ID_VIEW_UPDATESPEED_LOW "Aktualisiert die Anzeige alle vier Sekunde." + ID_VIEW_UPDATESPEED_NORMAL "Aktualisiert die Anzeige alle zwei Sekunden." + ID_VIEW_UPDATESPEED_LOW "Aktualisiert die Anzeige alle vier Sekunden." END STRINGTABLE DISCARDABLE @@ -616,10 +616,10 @@ BEGIN ID_FILE_EXIT "Beendet den Task-Manager." ID_OPTIONS_SHOW16BITTASKS "Zeigt die 16-Bit Tasks unter der zugehörigen ntvdm.exe an." - ID_VIEW_SELECTCOLUMNS "Legt fest welche Spaletn auf der Registerkarte Prozesse angezeigt werden." + ID_VIEW_SELECTCOLUMNS "Legt fest welche Spalten auf der Registerkarte Prozesse angezeigt werden." ID_VIEW_SHOWKERNELTIMES "Zeigt die Kernel-Zeiten in den Systemmonitordiagrammen an." ID_VIEW_CPUHISTORY_ONEGRAPHALL - "Zeigt für jede CPU-Auslastung ein Verlausdiagramm an." + "Zeigt für jede CPU-Auslastung ein Verlaufsdiagramm an." ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Zeigt die gesamte CPU-Auslastung in einem Verlaufdiagramm an." ID_APPLICATION_PAGE_SWITCHTO "Zeigt das Fenster im Vordergrund an und wechselt zu diesem Task." diff --git a/reactos/subsys/system/taskmgr/procpage.c b/reactos/subsys/system/taskmgr/procpage.c index ff2d0cd6336..7d872f9ca40 100644 --- a/reactos/subsys/system/taskmgr/procpage.c +++ b/reactos/subsys/system/taskmgr/procpage.c @@ -34,6 +34,7 @@ #include "column.h" #include "proclist.h" #include "dbgchnl.h" +#include "endproc.h" #include HWND hProcessPage; /* Process List Property Page */ @@ -110,6 +111,12 @@ ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_COMMAND: + /* Handle the button clicks */ + switch (LOWORD(wParam)) + { + case IDC_ENDPROCESS: + ProcessPage_OnEndProcess(); + } break; case WM_SIZE: diff --git a/reactos/subsys/system/usetup/usetup.c b/reactos/subsys/system/usetup/usetup.c index cbfc2213a30..fc15bc73acf 100644 --- a/reactos/subsys/system/usetup/usetup.c +++ b/reactos/subsys/system/usetup/usetup.c @@ -31,6 +31,7 @@ #include #include +#include #include "usetup.h" #include "console.h" @@ -1709,8 +1710,8 @@ ShowPartitionSizeInputBox(SHORT Left, strlen (Buffer), coPos); - Buffer[0] = 0; - Index = 0; + sprintf(Buffer, "%d", MaxSize); + Index = strlen(Buffer); DrawInputField (PARTITION_SIZE_INPUT_FIELD_LENGTH, iLeft, iTop, @@ -3691,6 +3692,43 @@ FlushPage(PINPUT_RECORD Ir) } +static VOID +SignalInitEvent() +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeString; + HANDLE ReactOSInitEvent; + + RtlRosInitUnicodeStringFromLiteral(&UnicodeString, L"\\ReactOSInitDone"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + EVENT_ALL_ACCESS, + 0, + NULL); + Status = NtOpenEvent(&ReactOSInitEvent, + EVENT_ALL_ACCESS, + &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + LARGE_INTEGER Timeout; + /* This will cause the boot screen image to go away (if displayed) */ + NtPulseEvent(ReactOSInitEvent, NULL); + + /* Wait for the display mode to be changed (if in graphics mode) */ + Timeout.QuadPart = -50000000LL; /* 5 second timeout */ + NtWaitForSingleObject(ReactOSInitEvent, FALSE, &Timeout); + + NtClose(ReactOSInitEvent); + } + else + { + /* We don't really care if this fails */ + DPRINT1("USETUP: Failed to open ReactOS init notification event\n"); + } +} + + VOID STDCALL NtProcessStartup(PPEB Peb) { @@ -3702,6 +3740,8 @@ NtProcessStartup(PPEB Peb) ProcessHeap = Peb->ProcessHeap; + SignalInitEvent(); + Status = AllocConsole(); if (!NT_SUCCESS(Status)) { diff --git a/reactos/subsys/system/vmwinst/De.rc b/reactos/subsys/system/vmwinst/De.rc index 39432b4bf59..5a7443e6aa4 100644 --- a/reactos/subsys/system/vmwinst/De.rc +++ b/reactos/subsys/system/vmwinst/De.rc @@ -64,7 +64,7 @@ BEGIN PUSHBUTTON "Die Bildeinstellungen ändern", IDC_CONFIGSETTINGS, 25, 40, 200, 15, BS_AUTORADIOBUTTON PUSHBUTTON "Einen anderen Grafiktreiber benutzen", IDC_USEOTHERDRIVER, 25, 55, 200, 15, BS_AUTORADIOBUTTON PUSHBUTTON "Den VMware(r) SVGA entfernen", IDC_UNINSTALL, 25, 70, 200, 15, BS_AUTORADIOBUTTON - LTEXT "Klichen Sie auf 'Weiter' um fortzufahren oder 'Abbrechen' und en Asssistenten zu beenden.", -1, 25, 93, 225, 12 + LTEXT "Klichen Sie auf 'Weiter' um fortzufahren oder 'Abbrechen' und den Asssistenten zu beenden.", -1, 25, 93, 225, 12 END IDD_SELECTDRIVER DIALOGEX 0, 0, PROPSHEETWIDTH, PROPSHEETHEIGHT @@ -72,7 +72,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Grafikreiberinstallation" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "Wählen Sie bitte den Grafiktreiber aus,d en Sie verwenden wollen:",-1,25,25,225,15 + LTEXT "Wählen Sie bitte den Grafiktreiber aus, den Sie verwenden wollen:",-1,25,25,225,15 PUSHBUTTON "ReactOS VGA Treiber", IDC_VGA, 25, 40, 225, 15, BS_AUTORADIOBUTTON PUSHBUTTON "ReactOS VBE Treiber (SVGA)", IDC_VBE, 25, 55, 225, 15, BS_AUTORADIOBUTTON LTEXT "Klicken Sie auf 'Fertigstellen' um die Installation fertigzustellen oder auf 'Abbrechen' um das Setup ohne Veränderungen zu beenden.", -1, 25, 93, 225, 20 @@ -83,7 +83,7 @@ STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION CAPTION "Grafikreiberinstallation" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - LTEXT "The ReactOS Setup wird Ihren VMware(r) SVGA Treiber entfernen!!!\n\n\nKlicken Sie auf 'Fertigstellen' um den Treiber zu entfernen oder auf 'Abbrechen' um ihn zu lassen.",-1,25,25,225,85 + LTEXT "The ReactOS Setup wird Ihren VMware(r) SVGA Treiber entfernen!!!\n\n\nKlicken Sie auf 'Fertigstellen' um den Treiber zu entfernen oder auf 'Abbrechen' um ihn weiterhin zu verwenden.",-1,25,25,225,85 END STRINGTABLE diff --git a/reactos/subsys/system/vmwinst/vmwinst.c b/reactos/subsys/system/vmwinst/vmwinst.c index 1797548ad19..3af6cbdc0a2 100644 --- a/reactos/subsys/system/vmwinst/vmwinst.c +++ b/reactos/subsys/system/vmwinst/vmwinst.c @@ -280,6 +280,8 @@ IsVmwSVGAEnabled(VOID) return (Value == 1); } + + BOOL SaveResolutionSettings(DWORD ResX, DWORD ResY, DWORD ColDepth) { diff --git a/reactos/subsys/system/winlogon/De.rc b/reactos/subsys/system/winlogon/De.rc index 0bde4622ec9..51118ccff19 100644 --- a/reactos/subsys/system/winlogon/De.rc +++ b/reactos/subsys/system/winlogon/De.rc @@ -7,7 +7,7 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTIO CAPTION "Computer herunterfahren" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "It is now safe to turn off your computer.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8 + LTEXT "Sie können den Computer jetzt ausschalten.", IDC_SHUTDOWNCOMPUTER, 31, 13, 132, 8 ICON IDI_WINLOGON, IDC_SHTDOWNICON, 6, 7, 18, 20 DEFPUSHBUTTON "Neusta&rt", IDC_BTNSHTDOWNCOMPUTER, 62, 32, 40, 14 END @@ -28,7 +28,7 @@ BEGIN IDS_APPLYINGCOMPUTERSETTINGS "Computereinstellungen laden..." IDS_RUNNINGSTARTUPSCRIPTS "Startscripts ausführen..." IDS_RUNNINGSHUTDOWNSCRIPTS "Scripte um den Computer herunterzufahren ausführen..." - IDS_APPLYINGYOURPERSONALSETTINGS "Ihr persönlichen Einstellungen setzen..." + IDS_APPLYINGYOURPERSONALSETTINGS "Ihre persönlichen Einstellungen setzen..." IDS_RUNNINGLOGOFFSCRIPTS "Scripts um auszuloggen ausführen..." IDS_RUNNINGLOGONSCRIPTS "Scripts um einzuloggen ausführen..." IDS_LOADINGYOURPERSONALSETTINGS "Ihr persönlichen Einstellungen laden..." diff --git a/reactos/subsys/win32k/dib/dib.c b/reactos/subsys/win32k/dib/dib.c index 97f0d691a79..7b6e6547df1 100644 --- a/reactos/subsys/win32k/dib/dib.c +++ b/reactos/subsys/win32k/dib/dib.c @@ -156,25 +156,25 @@ DIB_DoRop(ULONG Rop, ULONG Dest, ULONG Source, ULONG Pattern) /* Optimized code for the various named rop codes. */ switch (Rop) { - case BLACKNESS: return(0); - case NOTSRCERASE: return(~(Dest | Source)); - case NOTSRCCOPY: return(~Source); - case SRCERASE: return((~Dest) & Source); - case DSTINVERT: return(~Dest); - case PATINVERT: return(Dest ^ Pattern); - case SRCINVERT: return(Dest ^ Source); - case SRCAND: return(Dest & Source); - case MERGEPAINT: return(Dest & (~Source)); - case SRCPAINT: return(Dest | Source); - case MERGECOPY: return(Source & Pattern); - case SRCCOPY: return(Source); - case PATCOPY: return(Pattern); - case PATPAINT: return(Dest | (~Source) | Pattern); - case WHITENESS: return(0xFFFFFFFF); + case ROP3_TO_ROP4(BLACKNESS): return(0); + case ROP3_TO_ROP4(NOTSRCERASE): return(~(Dest | Source)); + case ROP3_TO_ROP4(NOTSRCCOPY): return(~Source); + case ROP3_TO_ROP4(SRCERASE): return((~Dest) & Source); + case ROP3_TO_ROP4(DSTINVERT): return(~Dest); + case ROP3_TO_ROP4(PATINVERT): return(Dest ^ Pattern); + case ROP3_TO_ROP4(SRCINVERT): return(Dest ^ Source); + case ROP3_TO_ROP4(SRCAND): return(Dest & Source); + case ROP3_TO_ROP4(MERGEPAINT): return(Dest & (~Source)); + case ROP3_TO_ROP4(SRCPAINT): return(Dest | Source); + case ROP3_TO_ROP4(MERGECOPY): return(Source & Pattern); + case ROP3_TO_ROP4(SRCCOPY): return(Source); + case ROP3_TO_ROP4(PATCOPY): return(Pattern); + case ROP3_TO_ROP4(PATPAINT): return(Dest | (~Source) | Pattern); + case ROP3_TO_ROP4(WHITENESS): return(0xFFFFFFFF); } /* Expand the ROP operation to all four bytes */ - Rop &= 0x00FF0000; - Rop = (Rop << 8) | (Rop) | (Rop >> 8) | (Rop >> 16); + Rop &= 0xFF; + Rop |= (Rop << 24) | (Rop << 16) | (Rop << 8); /* Do the operation on four bits simultaneously. */ Result = 0; for (i = 0; i < 8; i++) diff --git a/reactos/subsys/win32k/dib/dib.h b/reactos/subsys/win32k/dib/dib.h index 909c779fa2d..bb61a0f8b47 100644 --- a/reactos/subsys/win32k/dib/dib.h +++ b/reactos/subsys/win32k/dib/dib.h @@ -99,9 +99,6 @@ BOOLEAN DIB_32BPP_BitBltSrcCopy(PBLTINFO); BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,POINTL,CLIPOBJ*,XLATEOBJ*,ULONG); BOOLEAN DIB_32BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,POINTL*,XLATEOBJ*,ULONG); -#define ROP_USES_SOURCE(Rop4) (((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000)) -#define ROP_USES_PATTERN(Rop4) (((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000)) - extern unsigned char notmask[2]; extern unsigned char altnotmask[2]; #define MASK1BPP(x) (1<<(7-((x)&7))) diff --git a/reactos/subsys/win32k/dib/dib16bpp.c b/reactos/subsys/win32k/dib/dib16bpp.c index 279f3c47ac7..8b496f86057 100644 --- a/reactos/subsys/win32k/dib/dib16bpp.c +++ b/reactos/subsys/win32k/dib/dib16bpp.c @@ -40,15 +40,52 @@ DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y) VOID DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c) { - PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta; - PWORD addr = (PWORD)byteaddr + x1; - LONG cx = x1; + PDWORD addr = (PDWORD)((PWORD)(SurfObj->pvScan0 + y * SurfObj->lDelta) + x1); - while(cx < x2) { - *addr = (WORD)c; - ++addr; - ++cx; +#ifdef _M_IX86 + /* This is about 10% faster than the generic C code below */ + LONG Count = x2 - x1; + + __asm__( +" cld\n" +" andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */ +" mov %0, %%eax\n" +" shl $16, %%eax\n" +" or %0, %%eax\n" +" test $0x01, %%edi\n" /* Align to fullword boundary */ +" jz .L1\n" +" stosw\n" +" dec %1\n" +" jz .L2\n" +".L1:\n" +" mov %1,%%ecx\n" /* Setup count of fullwords to fill */ +" shr $1,%%ecx\n" +" rep stosl\n" /* The actual fill */ +" test $0x01, %1\n" /* One left to do at the right side? */ +" jz .L2\n" +" stosw\n" +".L2:\n" + : /* no output */ + : "r"(c), "r"(Count), "D"(addr) + : "%eax", "%ecx"); +#else /* _M_IX86 */ + LONG cx = x1; + DWORD cc; + + if (0 != (cx & 0x01)) { + *((PWORD) addr) = c; + cx++; + addr = (PDWORD)((PWORD)(addr) + 1); } + cc = ((c & 0xffff) << 16) | (c & 0xffff); + while(cx + 1 < x2) { + *addr++ = cc; + cx += 2; + } + if (cx < x2) { + *((PWORD) addr) = c; + } +#endif /* _M_IX86 */ } VOID @@ -272,8 +309,8 @@ DIB_16BPP_BitBlt(PBLTINFO BltInfo) PULONG DestBits; ULONG RoundedRight; - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); RoundedRight = BltInfo->DestRect.right - ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 0x1); diff --git a/reactos/subsys/win32k/dib/dib1bpp.c b/reactos/subsys/win32k/dib/dib1bpp.c index 620e86474b9..8a762e94de6 100644 --- a/reactos/subsys/win32k/dib/dib1bpp.c +++ b/reactos/subsys/win32k/dib/dib1bpp.c @@ -349,8 +349,8 @@ DIB_1BPP_BitBlt(PBLTINFO BltInfo) ULONG RoundedRight; /* BYTE NoBits;*/ - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); RoundedRight = BltInfo->DestRect.right - ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 31); diff --git a/reactos/subsys/win32k/dib/dib24bpp.c b/reactos/subsys/win32k/dib/dib24bpp.c index 30a0197bd33..c14dd8230c7 100644 --- a/reactos/subsys/win32k/dib/dib24bpp.c +++ b/reactos/subsys/win32k/dib/dib24bpp.c @@ -244,8 +244,8 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo) BOOL UsesPattern; PBYTE DestBits; - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); SourceY = BltInfo->SourcePoint.y; DestBits = (PBYTE)( diff --git a/reactos/subsys/win32k/dib/dib32bpp.c b/reactos/subsys/win32k/dib/dib32bpp.c index 1f8f553a815..35a79815b6d 100644 --- a/reactos/subsys/win32k/dib/dib32bpp.c +++ b/reactos/subsys/win32k/dib/dib32bpp.c @@ -293,8 +293,8 @@ DIB_32BPP_BitBlt(PBLTINFO BltInfo) BOOL UsesPattern; PULONG DestBits; - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); SourceY = BltInfo->SourcePoint.y; DestBits = (PULONG)( diff --git a/reactos/subsys/win32k/dib/dib4bpp.c b/reactos/subsys/win32k/dib/dib4bpp.c index c49ad5b089f..db5d57c3c29 100644 --- a/reactos/subsys/win32k/dib/dib4bpp.c +++ b/reactos/subsys/win32k/dib/dib4bpp.c @@ -251,8 +251,8 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo) 0xFFFFFFFF /* 15 */, }; - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); SourceY = BltInfo->SourcePoint.y; RoundedRight = BltInfo->DestRect.right - diff --git a/reactos/subsys/win32k/dib/dib8bpp.c b/reactos/subsys/win32k/dib/dib8bpp.c index 1236cca9c9b..d480c7dea6c 100644 --- a/reactos/subsys/win32k/dib/dib8bpp.c +++ b/reactos/subsys/win32k/dib/dib8bpp.c @@ -38,15 +38,7 @@ DIB_8BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y) VOID DIB_8BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c) { - PBYTE byteaddr = SurfObj->pvScan0 + y * SurfObj->lDelta; - PBYTE addr = byteaddr + x1; - LONG cx = x1; - - while(cx < x2) { - *addr = c; - ++addr; - ++cx; - } + memset(SurfObj->pvScan0 + y * SurfObj->lDelta + x1, (BYTE) c, x2 - x1); } VOID @@ -268,8 +260,8 @@ DIB_8BPP_BitBlt(PBLTINFO BltInfo) PULONG DestBits; LONG RoundedRight; - UsesSource = ROP_USES_SOURCE(BltInfo->Rop4); - UsesPattern = ROP_USES_PATTERN(BltInfo->Rop4); + UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4); + UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4); SourceY = BltInfo->SourcePoint.y; RoundedRight = BltInfo->DestRect.right - diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index c25f97d2976..f3014db5875 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -213,7 +213,7 @@ CallDibBitBlt(SURFOBJ* OutputObj, BltInfo.DestRect = *OutputRect; BltInfo.SourcePoint = *InputPoint; - if (Rop4 == SRCCOPY) + if (ROP3_TO_ROP4(SRCCOPY) == Rop4) return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); BltInfo.XlatePatternToDest = NULL; @@ -222,7 +222,7 @@ CallDibBitBlt(SURFOBJ* OutputObj, BltInfo.Rop4 = Rop4; /* Pattern brush */ - if (ROP_USES_PATTERN(Rop4) && Brush->iSolidColor == 0xFFFFFFFF) + if (ROP4_USES_PATTERN(Rop4) && Brush->iSolidColor == 0xFFFFFFFF) { GdiBrush = CONTAINING_RECORD(Brush, GDIBRUSHINST, BrushObject); if((bmPattern = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern))) @@ -291,9 +291,9 @@ EngBitBlt(SURFOBJ *DestObj, BOOL UsesPattern; POINTL AdjustedBrushOrigin; - UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000); - UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000); - if (ROP_NOOP == Rop4) + UsesSource = ROP4_USES_SOURCE(Rop4); + UsesPattern = ROP4_USES_PATTERN(Rop4); + if (R4_NOOP == Rop4) { /* Copy destination onto itself: nop */ return TRUE; @@ -392,20 +392,16 @@ EngBitBlt(SURFOBJ *DestObj, clippingType = ClipRegion->iDComplexity; } - if (0xaacc == Rop4) + if (R4_MASK == Rop4) { BltRectFunc = BltMask; } - else if (PATCOPY == Rop4) + else if (ROP3_TO_ROP4(PATCOPY) == Rop4) { -#if 0 - BltRectFunc = BltPatCopy; -#else if (Brush->iSolidColor == 0xFFFFFFFF) BltRectFunc = CallDibBitBlt; else BltRectFunc = BltPatCopy; -#endif } else { @@ -515,7 +511,7 @@ IntEngBitBlt(BITMAPOBJ *DestObj, InputClippedRect.top = DestRect->bottom; InputClippedRect.bottom = DestRect->top; } - UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000); + UsesSource = ROP4_USES_SOURCE(Rop4); if (UsesSource) { if (NULL == SourcePoint || NULL == SourceSurf) @@ -833,40 +829,41 @@ AlphaBltMask(SURFOBJ* Dest, tMask = Mask->pvScan0 + (SourcePoint->y * Mask->lDelta) + SourcePoint->x; for (j = 0; j < dy; j++) - { - lMask = tMask; - for (i = 0; i < dx; i++) - { - if (*lMask > 0) - { - if(*lMask == 0xff) - { - DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel( - Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor); - } - else - { - Background = DIB_GetSource(Dest, DestRect->left + i, DestRect->top + j, SrcColorTranslation); + { + lMask = tMask; + for (i = 0; i < dx; i++) + { + if (*lMask > 0) + { + if (*lMask == 0xff) + { + DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel( + Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor); + } + else + { + Background = DIB_GetSource(Dest, DestRect->left + i, DestRect->top + j, + SrcColorTranslation); - NewColor = - RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background), - (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background), - (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background)); - - Background = XLATEOBJ_iXlate(ColorTranslation, NewColor); - DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel( - Dest, DestRect->left + i, DestRect->top + j, Background); - } - } - lMask++; - } - tMask += Mask->lDelta; - } + NewColor = + RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background), + (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background), + (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background)); + + Background = XLATEOBJ_iXlate(ColorTranslation, NewColor); + DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel( + Dest, DestRect->left + i, DestRect->top + j, Background); + } + } + lMask++; + } + tMask += Mask->lDelta; + } return TRUE; } else { - return FALSE; + return FALSE; } } @@ -918,7 +915,7 @@ EngMaskBitBlt(SURFOBJ *DestObj, InputRect.bottom = DestRect->bottom - DestRect->top; } - if (! IntEngEnter(&EnterLeaveSource, NULL, &InputRect, TRUE, &Translate, &InputObj)) + if (! IntEngEnter(&EnterLeaveSource, DestObj, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } @@ -1004,7 +1001,8 @@ EngMaskBitBlt(SURFOBJ *DestObj, &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin); else Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation, - &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC); + &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin, + R4_MASK); break; case DC_RECT: // Clip the blt to the clip rectangle @@ -1020,7 +1018,7 @@ EngMaskBitBlt(SURFOBJ *DestObj, &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin); else Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation, - &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC); + &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, R4_MASK); break; case DC_COMPLEX: Ret = TRUE; @@ -1058,7 +1056,7 @@ EngMaskBitBlt(SURFOBJ *DestObj, &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin) && Ret; else Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation, - &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, 0xAACC) && Ret; + &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, R4_MASK) && Ret; } } while(EnumMore); @@ -1069,26 +1067,20 @@ EngMaskBitBlt(SURFOBJ *DestObj, IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); - /* Dummy BitBlt to let driver know that something has changed. - 0x00AA0029 is the Rop for D (no-op) */ - /* FIXME: Remove the typecast! */ - IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation, - DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, ROP_NOOP); - return Ret; } BOOL STDCALL IntEngMaskBlt(SURFOBJ *DestObj, - SURFOBJ *Mask, - CLIPOBJ *ClipRegion, - XLATEOBJ *DestColorTranslation, - XLATEOBJ *SourceColorTranslation, - RECTL *DestRect, - POINTL *SourcePoint, - POINTL *MaskOrigin, - BRUSHOBJ *Brush, - POINTL *BrushOrigin) + SURFOBJ *Mask, + CLIPOBJ *ClipRegion, + XLATEOBJ *DestColorTranslation, + XLATEOBJ *SourceColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskOrigin, + BRUSHOBJ *Brush, + POINTL *BrushOrigin) { BOOLEAN ret; RECTL OutputRect; @@ -1123,9 +1115,21 @@ IntEngMaskBlt(SURFOBJ *DestObj, MouseSafetyOnDrawStart(DestObj, OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom); + /* Dummy BitBlt to let driver know that it should flush its changes. + This should really be done using a call to DrvSynchronizeSurface, + but the VMware driver doesn't hook that call. */ + /* FIXME: Remove the typecast! */ + IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation, + DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, R4_NOOP); + ret = EngMaskBitBlt(DestObj, Mask, ClipRegion, DestColorTranslation, SourceColorTranslation, &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin); + /* Dummy BitBlt to let driver know that something has changed. */ + /* FIXME: Remove the typecast! */ + IntEngBitBlt((BITMAPOBJ*)DestObj, NULL, (BITMAPOBJ*)Mask, ClipRegion, DestColorTranslation, + DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, R4_NOOP); + MouseSafetyOnDrawEnd(DestObj); return ret; diff --git a/reactos/subsys/win32k/eng/copybits.c b/reactos/subsys/win32k/eng/copybits.c index cfc4266aea4..d1f9b0767a1 100644 --- a/reactos/subsys/win32k/eng/copybits.c +++ b/reactos/subsys/win32k/eng/copybits.c @@ -98,7 +98,7 @@ EngCopyBits(SURFOBJ *Dest, /* FIXME: Remove the typecast! */ ret = IntEngBitBlt((BITMAPOBJ*)Dest, (BITMAPOBJ*)Source, NULL, Clip, ColorTranslation, DestRect, SourcePoint, - NULL, NULL, NULL, 0); + NULL, NULL, NULL, ROP3_TO_ROP4(SRCCOPY)); MouseSafetyOnDrawEnd(Dest); MouseSafetyOnDrawEnd(Source); diff --git a/reactos/subsys/win32k/eng/driverobj.c b/reactos/subsys/win32k/eng/driverobj.c new file mode 100644 index 00000000000..b597fee71f4 --- /dev/null +++ b/reactos/subsys/win32k/eng/driverobj.c @@ -0,0 +1,171 @@ +/* + * ReactOS W32 Subsystem + * Copyright (C) 2005 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI DRIVEROBJ Functions + * FILE: subsys/win32k/eng/driverobj.c + * PROGRAMER: Gregor Anich + * REVISION HISTORY: + * 04/01/2005: Created + */ +#include + + +/*!\brief Called when the process is terminated. + * + * Calls the free-proc for each existing DRIVEROBJ. + * + * \param Process Pointer to the EPROCESS struct for the process beeing terminated. + * \param Win32Process Pointer to the W32PROCESS + */ +VOID FASTCALL +IntEngCleanupDriverObjs(struct _EPROCESS *Process, + PW32PROCESS Win32Process) +{ + PDRIVERGDI DrvObjInt; + + IntEngLockProcessDriverObjs(PsGetWin32Process()); + while (!IsListEmpty(&Win32Process->DriverObjListHead)) + { + DrvObjInt = CONTAINING_RECORD(Win32Process->DriverObjListHead.Flink, + DRIVERGDI, ListEntry); + IntEngUnLockProcessDriverObjs(PsGetWin32Process()); + EngDeleteDriverObj((HDRVOBJ)(&DrvObjInt->DriverObj), TRUE, FALSE); + IntEngLockProcessDriverObjs(PsGetWin32Process()); + } + IntEngUnLockProcessDriverObjs(PsGetWin32Process()); +} + + +/* + * @implemented + */ +HDRVOBJ +STDCALL +EngCreateDriverObj( + IN PVOID pvObj, + IN FREEOBJPROC pFreeObjProc, + IN HDEV hdev + ) +{ + PDRIVERGDI DrvObjInt; + PDRIVEROBJ DrvObjUser; + + /* Create DRIVEROBJ */ + DrvObjInt = EngAllocMem(0, sizeof (DRIVERGDI), TAG_DRIVEROBJ); + if (DrvObjInt == NULL) + { + DPRINT1("Failed to allocate memory for a DRIVERGDI structure!\n"); + return NULL; + } + + /* fill user object */ + DrvObjUser = GDIToObj(DrvObjInt, DRIVER); + DrvObjUser->pvObj = pvObj; + DrvObjUser->pFreeProc = pFreeObjProc; + DrvObjUser->hdev = hdev; + DrvObjUser->dhpdev = ((GDIDEVICE*)hdev)->PDev; + + /* fill internal object */ + ExInitializeFastMutex(&DrvObjInt->Lock); + IntEngLockProcessDriverObjs(PsGetWin32Process()); + InsertTailList(&PsGetWin32Process()->DriverObjListHead, &DrvObjInt->ListEntry); + IntEngUnLockProcessDriverObjs(PsGetWin32Process()); + + return (HDRVOBJ)DrvObjUser; +} + + +/* + * @implemented + */ +BOOL +STDCALL +EngDeleteDriverObj( + IN HDRVOBJ hdo, + IN BOOL bCallBack, + IN BOOL bLocked + ) +{ + PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; + PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); + + /* Make sure the obj is locked */ + if (!bLocked) + { + if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) + { + return FALSE; + } + } + + /* Call the free-proc */ + if (bCallBack) + { + if (!DrvObjUser->pFreeProc(DrvObjUser)) + { + return FALSE; + } + } + + /* Free the DRIVEROBJ */ + IntEngLockProcessDriverObjs(PsGetWin32Process()); + RemoveEntryList(&DrvObjInt->ListEntry); + IntEngUnLockProcessDriverObjs(PsGetWin32Process()); + EngFreeMem(DrvObjInt); + + return TRUE; +} + + +/* + * @implemented + */ +PDRIVEROBJ +STDCALL +EngLockDriverObj( IN HDRVOBJ hdo ) +{ + PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; + PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); + + if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) + { + return NULL; + } + + return DrvObjUser; +} + + +/* + * @implemented + */ +BOOL +STDCALL +EngUnlockDriverObj ( IN HDRVOBJ hdo ) +{ + PDRIVERGDI DrvObjInt = ObjToGDI((PDRIVEROBJ)hdo, DRIVER); + + ExReleaseFastMutex(&DrvObjInt->Lock); + return TRUE; +} + +/* EOF */ + diff --git a/reactos/subsys/win32k/eng/gradient.c b/reactos/subsys/win32k/eng/gradient.c index 9ccbe20de3f..471a4d50e1f 100644 --- a/reactos/subsys/win32k/eng/gradient.c +++ b/reactos/subsys/win32k/eng/gradient.c @@ -541,7 +541,7 @@ IntEngGradientFill( pco->rclBounds.top, pco->rclBounds.right, pco->rclBounds.bottom); - if((psoDest->iType != STYPE_BITMAP) && (pboDest->flHooks & HOOK_GRADIENTFILL)) + if(pboDest->flHooks & HOOK_GRADIENTFILL) { Ret = GDIDEVFUNCS(psoDest).GradientFill( psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, @@ -551,19 +551,6 @@ IntEngGradientFill( } Ret = EngGradientFill(psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents, pptlDitherOrg, ulMode); - if(Ret) - { - /* Dummy BitBlt to let driver know that something has changed. - 0x00AA0029 is the Rop for D (no-op) */ - if(pboDest->flHooks & HOOK_BITBLT) - { - GDIDEVFUNCS(psoDest).BitBlt( - psoDest, NULL, NULL, pco, pxlo, - prclExtents, pptlDitherOrg, NULL, NULL, NULL, ROP_NOOP); - MouseSafetyOnDrawEnd(psoDest); - return TRUE; - } - } MouseSafetyOnDrawEnd(psoDest); return Ret; } diff --git a/reactos/subsys/win32k/eng/lineto.c b/reactos/subsys/win32k/eng/lineto.c index dd473ec49ef..27785358a2d 100644 --- a/reactos/subsys/win32k/eng/lineto.c +++ b/reactos/subsys/win32k/eng/lineto.c @@ -488,7 +488,7 @@ IntEngLineTo(BITMAPOBJ *DestObj, LONG x2, LONG y2, RECTL *RectBounds, - MIX mix) + MIX Mix) { BOOLEAN ret; SURFOBJ *DestSurf; @@ -524,7 +524,7 @@ IntEngLineTo(BITMAPOBJ *DestObj, { /* Call the driver's DrvLineTo */ ret = GDIDEVFUNCS(DestSurf).LineTo( - DestSurf, Clip, Brush, x1, y1, x2, y2, /*RectBounds*/&b, mix); + DestSurf, Clip, Brush, x1, y1, x2, y2, /*RectBounds*/&b, Mix); } #if 0 @@ -536,7 +536,7 @@ IntEngLineTo(BITMAPOBJ *DestObj, if (! ret) { - ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, Mix); } MouseSafetyOnDrawEnd(DestSurf); @@ -550,7 +550,7 @@ IntEngPolyline(BITMAPOBJ *DestObj, BRUSHOBJ *Brush, CONST LPPOINT pt, LONG dCount, - MIX mix) + MIX Mix) { LONG i; RECTL rect; @@ -571,7 +571,7 @@ IntEngPolyline(BITMAPOBJ *DestObj, pt[i].x, pt[i].y, &rect, - mix); + Mix); if (!ret) { break; diff --git a/reactos/subsys/win32k/eng/misc.c b/reactos/subsys/win32k/eng/misc.c index 7fea4feecf0..2fcba3b633a 100644 --- a/reactos/subsys/win32k/eng/misc.c +++ b/reactos/subsys/win32k/eng/misc.c @@ -123,6 +123,20 @@ IntEngEnter(PINTENG_ENTER_LEAVE EnterLeave, *OutputObj = DestObj; } + if (NULL != *OutputObj + && 0 != (((BITMAPOBJ*) *OutputObj)->flHooks & HOOK_SYNCHRONIZE)) + { + if (NULL != GDIDEVFUNCS(*OutputObj).SynchronizeSurface) + { + GDIDEVFUNCS(*OutputObj).SynchronizeSurface(*OutputObj, DestRect, 0); + } + else if (STYPE_BITMAP == (*OutputObj)->iType + && NULL != GDIDEVFUNCS(*OutputObj).Synchronize) + { + GDIDEVFUNCS(*OutputObj).Synchronize((*OutputObj)->dhpdev, DestRect); + } + } + EnterLeave->DestObj = DestObj; EnterLeave->OutputObj = *OutputObj; EnterLeave->ReadOnly = ReadOnly; diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index 71d05dba377..57c7c7d1801 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -68,16 +68,20 @@ MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1, tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp; } + ppdev->SafetyRemoveCount++; + + if (ppdev->SafetyRemoveLevel) + { + /* already hidden */ + return FALSE; + } + if (pgp->Exclude.right >= HazardX1 && pgp->Exclude.left <= HazardX2 && pgp->Exclude.bottom >= HazardY1 && pgp->Exclude.top <= HazardY2) { - if (0 != pgp->SafetyRemoveCount++) - { - return FALSE; - } - pgp->SafetySwitch = TRUE; + ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount; if (pgp->MovePointer) pgp->MovePointer(SurfObj, -1, -1, NULL); else @@ -113,25 +117,16 @@ MouseSafetyOnDrawEnd(SURFOBJ *SurfObj) return FALSE; } - if (pgp->SafetySwitch) - { - if (1 < pgp->SafetyRemoveCount--) - { - /* Someone else removed it too, let them restore it */ - return FALSE; - } - /* FIXME - this is wrong!!!!!! we must NOT access pgp->Pos from here, it's - a private field for ENG/driver. This will paint the cursor to the - wrong screen coordinates when a driver overrides DrvMovePointer()! - We should store the coordinates before calling Drv/EngMovePointer() - and Drv/EngSetPointerShape() separately in the GDIDEVICE structure - or somewhere where ntuser can access it! */ - if (pgp->MovePointer) - pgp->MovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude); - else - EngMovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude); - pgp->SafetySwitch = FALSE; - } + if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel) + { + return FALSE; + } + if (pgp->MovePointer) + pgp->MovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude); + else + EngMovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude); + + ppdev->SafetyRemoveLevel = 0; return(TRUE); } @@ -183,7 +178,7 @@ IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface) if((MaskSurface = EngLockSurface(pgp->MaskSurface))) { EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL, - &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY); + &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, ROP3_TO_ROP4(SRCCOPY)); EngUnlockSurface(MaskSurface); } EngUnlockSurface(SaveSurface); @@ -236,7 +231,7 @@ IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface) DestSurface->sizlBitmap.cy - pt.y); EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL, - &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY); + &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCCOPY)); EngUnlockSurface(SaveSurface); } @@ -270,17 +265,17 @@ IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface) if((ColorSurf = EngLockSurface(pgp->ColorSurface))) { EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, pgp->XlateObject, - &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC); + &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, R4_MASK); EngUnlockSurface(ColorSurf); } } else { EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject, - &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND); + &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCAND)); SrcPoint.y += pgp->Size.cy; EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject, - &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT); + &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCINVERT)); } EngUnlockSurface(MaskSurf); } @@ -367,6 +362,8 @@ EngSetPointerShape( pgp->HotSpot.x = xHot; pgp->HotSpot.y = yHot; + /* Actually this should be set by 'the other side', but it would be + * done right after this. It helps IntShowMousePointer. */ if (x != -1) { pgp->Pos.x = x; @@ -471,14 +468,13 @@ EngSetPointerShape( if (prcl != NULL) { - prcl->left = pgp->Pos.x - pgp->HotSpot.x; - prcl->top = pgp->Pos.y - pgp->HotSpot.x; + prcl->left = x - pgp->HotSpot.x; + prcl->top = y - pgp->HotSpot.x; prcl->right = prcl->left + pgp->Size.cx; prcl->bottom = prcl->top + pgp->Size.cy; } - } - - /* FIXME - touch prcl when x == -1? */ + } else if (prcl != NULL) + prcl->left = prcl->top = prcl->right = prcl->bottom = -1; return SPS_ACCEPT_EXCLUDE; } @@ -508,19 +504,21 @@ EngMovePointer( IntHideMousePointer(ppdev, pso); if (x != -1) { + /* Actually this should be set by 'the other side', but it would be + * done right after this. It helps IntShowMousePointer. */ pgp->Pos.x = x; pgp->Pos.y = y; IntShowMousePointer(ppdev, pso); if (prcl != NULL) { - prcl->left = pgp->Pos.x - pgp->HotSpot.x; - prcl->top = pgp->Pos.y - pgp->HotSpot.x; + prcl->left = x - pgp->HotSpot.x; + prcl->top = y - pgp->HotSpot.x; prcl->right = prcl->left + pgp->Size.cx; prcl->bottom = prcl->top + pgp->Size.cy; } - } + } else if (prcl != NULL) + prcl->left = prcl->top = prcl->right = prcl->bottom = -1; - /* FIXME - touch prcl when x == -1? */ } /* EOF */ diff --git a/reactos/subsys/win32k/eng/objects.h b/reactos/subsys/win32k/eng/objects.h index c6202bfc78e..bf10f1c4cf5 100644 --- a/reactos/subsys/win32k/eng/objects.h +++ b/reactos/subsys/win32k/eng/objects.h @@ -51,6 +51,12 @@ typedef struct _CLIPGDI { ENUMRECTS EnumRects; } CLIPGDI, *PCLIPGDI; +typedef struct _DRIVERGDI { + DRIVEROBJ DriverObj; + LIST_ENTRY ListEntry; + FAST_MUTEX Lock; +} DRIVERGDI, *PDRIVERGDI; + /*ei What is this for? */ typedef struct _DRVFUNCTIONSGDI { HDEV hdev; @@ -122,6 +128,14 @@ typedef BOOL STDCALL (*PFN_SetPalette)(DHPDEV, PALOBJ*, ULONG, ULONG, ULONG); typedef BOOL STDCALL (*PFN_GradientFill)(SURFOBJ*, CLIPOBJ*, XLATEOBJ*, TRIVERTEX*, ULONG, PVOID, ULONG, RECTL*, POINTL*, ULONG); +typedef struct _WNDGDI { + WNDOBJ WndObj; + CLIPOBJ *ClientClipObj; + WNDOBJCHANGEPROC ChangeProc; + FLONG Flags; + int PixelFormat; +} WNDGDI, *PWNDGDI; + typedef struct _XFORMGDI { ULONG Dummy; /* XFORMOBJ has no public members */ diff --git a/reactos/subsys/win32k/eng/semaphor.c b/reactos/subsys/win32k/eng/semaphor.c index 3f93da7148c..5fc0940ae43 100644 --- a/reactos/subsys/win32k/eng/semaphor.c +++ b/reactos/subsys/win32k/eng/semaphor.c @@ -80,3 +80,50 @@ EngIsSemaphoreOwnedByCurrentThread ( IN HSEMAPHORE hsem ) ASSERT(hsem); return ExIsResourceAcquiredExclusiveLite ( (PERESOURCE)hsem ); } + +/* + * @implemented + */ +BOOL STDCALL +EngInitializeSafeSemaphore( + OUT ENGSAFESEMAPHORE *Semaphore) +{ + HSEMAPHORE hSem; + + if (InterlockedIncrement(&Semaphore->lCount) == 1) + { + /* Create the semaphore */ + hSem = EngCreateSemaphore(); + if (hSem == 0) + { + InterlockedDecrement(&Semaphore->lCount); + return FALSE; + } + InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, hSem); + } + else + { + /* Wait for the other thread to create the semaphore */ + ASSERT(Semaphore->lCount > 1); + ASSERT_IRQL(PASSIVE_LEVEL); + while (Semaphore->hsem == NULL); + } + + return TRUE; +} + +/* + * @implemented + */ +VOID STDCALL +EngDeleteSafeSemaphore( + IN OUT ENGSAFESEMAPHORE *Semaphore) +{ + if (InterlockedDecrement(&Semaphore->lCount) == 0) + { + EngDeleteSemaphore(Semaphore->hsem); + InterlockedExchangePointer((volatile PVOID *)&Semaphore->hsem, NULL); + } +} + + diff --git a/reactos/subsys/win32k/eng/transblt.c b/reactos/subsys/win32k/eng/transblt.c index 3bc46c2a7d1..ede7a478f74 100644 --- a/reactos/subsys/win32k/eng/transblt.c +++ b/reactos/subsys/win32k/eng/transblt.c @@ -270,18 +270,6 @@ IntEngTransparentBlt(BITMAPOBJ *DestObj, &OutputRect, SourceRect, iTransColor, Reserved); } - if(Ret) - { - /* Dummy BitBlt to let driver know that something has changed. - 0x00AA0029 is the Rop for D (no-op) */ - if (DestObj->flHooks & HOOK_BITBLT) - { - GDIDEVFUNCS(DestSurf).BitBlt( - DestSurf, NULL, NULL, Clip, ColorTranslation, - &OutputRect, NULL, NULL, NULL, NULL, ROP_NOOP); - } - } - MouseSafetyOnDrawEnd(DestSurf); if(SourceSurf != DestSurf) { diff --git a/reactos/subsys/win32k/eng/window.c b/reactos/subsys/win32k/eng/window.c new file mode 100644 index 00000000000..4831da45563 --- /dev/null +++ b/reactos/subsys/win32k/eng/window.c @@ -0,0 +1,224 @@ +/* + * ReactOS W32 Subsystem + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI WNDOBJ Functions + * FILE: subsys/win32k/eng/window.c + * PROGRAMER: Gregor Anich + * REVISION HISTORY: + * 16/11/2004: Created + */ +#include + +/* + * Calls the WNDOBJCHANGEPROC of the given WNDOBJ + */ +VOID +FASTCALL +IntEngWndChanged( + IN WNDOBJ *pwo, + IN FLONG flChanged) +{ + WNDGDI *WndObjInt = ObjToGDI(pwo, WND); + + if (WndObjInt->ChangeProc == NULL) + { + return; + } + + /* check flags of the WNDOBJ */ + flChanged &= WndObjInt->Flags; + if (flChanged == 0) + { + return; + } + + /* Call the WNDOBJCHANGEPROC */ + if (flChanged == WOC_CHANGED) + { + pwo = NULL; + } + + DPRINT("Calling WNDOBJCHANGEPROC (0x%x), Changed = 0x%x\n", + WndObjInt->ChangeProc, flChanged); + WndObjInt->ChangeProc(pwo, flChanged); +} + +/* + * @implemented + */ +WNDOBJ* +STDCALL +EngCreateWnd( + SURFOBJ *pso, + HWND hwnd, + WNDOBJCHANGEPROC pfn, + FLONG fl, + int iPixelFormat + ) +{ + WNDGDI *WndObjInt = NULL; + WNDOBJ *WndObjUser = NULL; + PWINDOW_OBJECT Window; + CLIPOBJ *ClientClipObj; + + DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n", + pso, hwnd, pfn, fl, iPixelFormat); + + /* Get window object */ + Window = IntGetWindowObject(hwnd); + if (Window == NULL) + { + return NULL; + } + + /* Create WNDOBJ */ + WndObjInt = EngAllocMem(0, sizeof (WNDGDI), TAG_WNDOBJ); + if (WndObjInt == NULL) + { + IntReleaseWindowObject(Window); + DPRINT1("Failed to allocate memory for a WND structure!\n"); + return NULL; + } + + ClientClipObj = IntEngCreateClipRegion(1, (PRECTL)&Window->ClientRect, + (PRECTL)&Window->ClientRect); + if (ClientClipObj == NULL) + { + IntReleaseWindowObject(Window); + EngFreeMem(WndObjInt); + return NULL; + } + + /* fill user object */ + WndObjUser = GDIToObj(WndObjInt, WND); + WndObjUser->psoOwner = pso; + WndObjUser->pvConsumer = NULL; + RtlCopyMemory(&WndObjUser->rclClient, &Window->ClientRect, sizeof (RECT)); + RtlCopyMemory(&WndObjUser->coClient, ClientClipObj, sizeof (CLIPOBJ)); + + /* fill internal object */ + WndObjInt->ChangeProc = pfn; + WndObjInt->Flags = fl; + WndObjInt->PixelFormat = iPixelFormat; + WndObjInt->ClientClipObj = ClientClipObj; + + /* release resources */ + IntReleaseWindowObject(Window); + + DPRINT("EngCreateWnd: SUCCESS!\n"); + + return WndObjUser; +} + + +/* + * @implemented + */ +VOID +STDCALL +EngDeleteWnd ( IN WNDOBJ *pwo ) +{ + WNDGDI *WndObjInt = ObjToGDI(pwo, WND); + + DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo); + + IntEngDeleteClipRegion(WndObjInt->ClientClipObj); + EngFreeMem(WndObjInt); +} + + +/* + * @implemented + */ +BOOL +STDCALL +WNDOBJ_bEnum( + IN WNDOBJ *pwo, + IN ULONG cj, + OUT ULONG *pul + ) +{ + WNDGDI *WndObjInt = ObjToGDI(pwo, WND); + BOOL Ret; + + DPRINT("WNDOBJ_bEnum: pwo = 0x%x, cj = %d, pul = 0x%x\n", pwo, cj, pul); + Ret = CLIPOBJ_bEnum(WndObjInt->ClientClipObj, cj, pul); + + DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret ? "True" : "False"); + return Ret; +} + + +/* + * @implemented + */ +ULONG +STDCALL +WNDOBJ_cEnumStart( + IN WNDOBJ *pwo, + IN ULONG iType, + IN ULONG iDirection, + IN ULONG cLimit + ) +{ + WNDGDI *WndObjInt = ObjToGDI(pwo, WND); + ULONG Ret; + + DPRINT("WNDOBJ_cEnumStart: pwo = 0x%x, iType = %d, iDirection = %d, cLimit = %d\n", + pwo, iType, iDirection, cLimit); + + /* FIXME: Should we enumerate all rectangles or not? */ + Ret = CLIPOBJ_cEnumStart(WndObjInt->ClientClipObj, FALSE, iType, iDirection, cLimit); + + DPRINT("WNDOBJ_cEnumStart: Returning 0x%x\n", Ret); + return Ret; +} + + +/* + * @implemented + */ +VOID +STDCALL +WNDOBJ_vSetConsumer( + IN WNDOBJ *pwo, + IN PVOID pvConsumer + ) +{ + BOOL Hack; + + DPRINT("WNDOBJ_vSetConsumer: pwo = 0x%x, pvConsumer = 0x%x\n", pwo, pvConsumer); + + Hack = (pwo->pvConsumer == NULL); + pwo->pvConsumer = pvConsumer; + + /* HACKHACKHACK */ + if (Hack) + { + IntEngWndChanged(pwo, WOC_RGN_CLIENT); + IntEngWndChanged(pwo, WOC_CHANGED); + IntEngWndChanged(pwo, WOC_DRAWN); + } +} + +/* EOF */ + diff --git a/reactos/subsys/win32k/include/cursoricon.h b/reactos/subsys/win32k/include/cursoricon.h index 620799c4cbd..29dca570731 100644 --- a/reactos/subsys/win32k/include/cursoricon.h +++ b/reactos/subsys/win32k/include/cursoricon.h @@ -3,11 +3,18 @@ #define MAXCURICONHANDLES 4096 -typedef struct _CURICON_OBJECT +typedef struct tagCURICON_PROCESS { - HANDLE Self; LIST_ENTRY ListEntry; PW32PROCESS Process; +} CURICON_PROCESS, *PCURICON_PROCESS; + +typedef struct _CURICON_OBJECT +{ + LIST_ENTRY ListEntry; + HANDLE Self; + FAST_MUTEX Lock; + LIST_ENTRY ProcessList; HMODULE hModule; HRSRC hRsrc; HRSRC hGroupRsrc; @@ -30,7 +37,6 @@ typedef struct _SYSTEM_CURSORINFO BOOL Enabled; BOOL SwapButtons; UINT ButtonsDown; - LONG x, y; FAST_MUTEX CursorMutex; CURSORCLIP_INFO CursorClipInfo; PCURICON_OBJECT CurrentCursorObject; @@ -50,6 +56,8 @@ PCURICON_OBJECT FASTCALL IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HA PCURICON_OBJECT FASTCALL IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject); VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process); +BOOL FASTCALL IntGetCursorLocation(PWINSTATION_OBJECT WinStaObject, POINT *loc); + #define IntGetSysCursorInfo(WinStaObj) \ (PSYSTEM_CURSORINFO)((WinStaObj)->SystemCursor) diff --git a/reactos/subsys/win32k/include/inteng.h b/reactos/subsys/win32k/include/inteng.h index 8272371ac21..11d1875f9b9 100644 --- a/reactos/subsys/win32k/include/inteng.h +++ b/reactos/subsys/win32k/include/inteng.h @@ -18,10 +18,30 @@ typedef struct tagSPAN ULONG Width; } SPAN, *PSPAN; -#define ROP_NOOP 0x00AA0029 +#define R3_OPINDEX_SRCCOPY 0xcc +#define R3_OPINDEX_NOOP 0xaa +#define R4_NOOP ((R3_OPINDEX_NOOP << 8) | R3_OPINDEX_NOOP) +#define R4_MASK ((R3_OPINDEX_NOOP << 8) | R3_OPINDEX_SRCCOPY) + +#define ROP2_TO_MIX(Rop2) (((Rop2) << 8) | (Rop2)) +#define ROP3_USES_SOURCE(Rop3) ((((Rop3) & 0xCC0000) >> 2) != ((Rop3) & 0x330000)) +#define ROP4_USES_SOURCE(Rop4) (((((Rop4) & 0xCC) >> 2) != ((Rop4) & 0x33)) || ((((Rop4) & 0xCC00) >> 2) != ((Rop4) & 0x3300))) +#define ROP3_USES_PATTERN(Rop3) ((((Rop3) & 0xF00000) >> 4) != ((Rop3) & 0x0F0000)) +#define ROP4_USES_PATTERN(Rop4) (((((Rop4) & 0xF0) >> 4) != ((Rop4) & 0x0F)) || ((((Rop4) & 0xF000) >> 4) != ((Rop4) & 0x0F00))) +#define ROP3_TO_ROP4(Rop3) ((((Rop3) >> 8) & 0xff00) | (((Rop3) >> 16) & 0x00ff)) /* Definitions of IntEngXxx functions */ +#define IntEngLockProcessDriverObjs(W32Process) \ + ExAcquireFastMutex(&(W32Process)->DriverObjListLock) + +#define IntEngUnLockProcessDriverObjs(W32Process) \ + ExReleaseFastMutex(&(W32Process)->DriverObjListLock) + +VOID FASTCALL +IntEngCleanupDriverObjs(struct _EPROCESS *Process, + PW32PROCESS Win32Process); + BOOL STDCALL IntEngLineTo(BITMAPOBJ *Surface, CLIPOBJ *Clip, diff --git a/reactos/subsys/win32k/include/menu.h b/reactos/subsys/win32k/include/menu.h index 3a25fa3e2ca..1e30b703897 100644 --- a/reactos/subsys/win32k/include/menu.h +++ b/reactos/subsys/win32k/include/menu.h @@ -45,16 +45,16 @@ PMENU_OBJECT FASTCALL IntGetMenuObject(HMENU hMenu); #define IntLockMenuItems(MenuObj) \ - ExAcquireFastMutex(&MenuObj->MenuItemsLock) + ExAcquireFastMutex(&(MenuObj)->MenuItemsLock) #define IntUnLockMenuItems(MenuObj) \ - ExReleaseFastMutex(&MenuObj->MenuItemsLock) + ExReleaseFastMutex(&(MenuObj)->MenuItemsLock) #define IntLockProcessMenus(W32Process) \ - ExAcquireFastMutex(&W32Process->MenuListLock) + ExAcquireFastMutex(&(W32Process)->MenuListLock) #define IntUnLockProcessMenus(W32Process) \ - ExReleaseFastMutex(&W32Process->MenuListLock) + ExReleaseFastMutex(&(W32Process)->MenuListLock) #define IntReleaseMenuObject(MenuObj) \ ObmDereferenceObject(MenuObj) diff --git a/reactos/subsys/win32k/include/tags.h b/reactos/subsys/win32k/include/tags.h index bd5eb541d75..628d72829e1 100644 --- a/reactos/subsys/win32k/include/tags.h +++ b/reactos/subsys/win32k/include/tags.h @@ -45,9 +45,11 @@ /* Eng objects */ #define TAG_CLIPOBJ TAG('C', 'L', 'P', 'O') /* clip object */ -#define TAG_XLATEOBJ TAG('X', 'L', 'A', 'O') /* xlate object */ +#define TAG_DRIVEROBJ TAG('D', 'R', 'V', 'O') /* driver object */ #define TAG_FONT TAG('F', 'N', 'T', 'E') /* font entry */ #define TAG_FONTOBJ TAG('F', 'N', 'T', 'O') /* font object */ +#define TAG_WNDOBJ TAG('W', 'N', 'D', 'O') /* window object */ +#define TAG_XLATEOBJ TAG('X', 'L', 'A', 'O') /* xlate object */ /* misc */ #define TAG_DRIVER TAG('G', 'D', 'R', 'V') /* video drivers */ diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index f6410dcbf70..645a7379d1c 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -1,6 +1,6 @@ /* * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -71,8 +71,8 @@ Win32kProcessCallback (struct _EPROCESS *Process, InitializeListHead(&Win32Process->PrivateFontListHead); ExInitializeFastMutex(&Win32Process->PrivateFontListLock); - InitializeListHead(&Win32Process->CursorIconListHead); - ExInitializeFastMutex(&Win32Process->CursorIconListLock); + InitializeListHead(&Win32Process->DriverObjListHead); + ExInitializeFastMutex(&Win32Process->DriverObjListLock); Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout(); @@ -85,8 +85,10 @@ Win32kProcessCallback (struct _EPROCESS *Process, IntRemoveProcessWndProcHandles((HANDLE)Process->UniqueProcessId); IntCleanupMenus(Process, Win32Process); IntCleanupCurIcons(Process, Win32Process); + IntEngCleanupDriverObjs(Process, Win32Process); CleanupMonitorImpl(); + GDI_CleanupForProcess(Process); IntGraphicsCheck(FALSE); diff --git a/reactos/subsys/win32k/makefile b/reactos/subsys/win32k/makefile index 4efa142ea4f..e27e70b05f0 100644 --- a/reactos/subsys/win32k/makefile +++ b/reactos/subsys/win32k/makefile @@ -29,12 +29,6 @@ else CFLAGS_DBG := endif -ifeq ($(OPTIMIZED), 1) -CFLAGS_OPT := -O2 -Wno-strict-aliasing -else -CFLAGS_OPT := -endif - TARGET_CFLAGS =\ $(CFLAGS_DBG) \ -I. \ @@ -55,7 +49,7 @@ ENG_OBJECTS= eng/debug.o eng/error.o eng/mem.o eng/brush.o eng/bitblt.o \ eng/clip.o eng/copybits.o eng/device.o eng/lineto.o \ eng/paint.o eng/palette.o eng/perfcnt.o eng/semaphor.o eng/surface.o \ eng/xlate.o eng/transblt.o eng/mouse.o eng/misc.o eng/sort.o \ - eng/gradient.o eng/event.o eng/float.o + eng/gradient.o eng/event.o eng/float.o eng/driverobj.o eng/window.o MAIN_OBJECTS = main/dllmain.o main/svctabm.o diff --git a/reactos/subsys/win32k/misc/driver.c b/reactos/subsys/win32k/misc/driver.c index 5ce41fd4ed4..67618a1400e 100644 --- a/reactos/subsys/win32k/misc/driver.c +++ b/reactos/subsys/win32k/misc/driver.c @@ -239,6 +239,7 @@ BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED, DRIVER_FUNCTION(DisableDirectDraw); DRIVER_FUNCTION(QuerySpoolType); DRIVER_FUNCTION(GradientFill); + DRIVER_FUNCTION(SynchronizeSurface); END_FUNCTION_MAP(); diff --git a/reactos/subsys/win32k/ntuser/clipboard.c b/reactos/subsys/win32k/ntuser/clipboard.c index 596779f90e4..090efbe6b29 100644 --- a/reactos/subsys/win32k/ntuser/clipboard.c +++ b/reactos/subsys/win32k/ntuser/clipboard.c @@ -308,8 +308,9 @@ NtUserSetClipboardData(UINT uFormat, HANDLE hMem, DWORD Unknown2) HWND STDCALL NtUserSetClipboardViewer(HWND hWndNewViewer) { - UNIMPLEMENTED - return 0; + HWND hwndPrev = 0; + DbgPrint("NtUserSetClipboardViewer is UNIMPLEMENTED (%p): returning %p\n", hWndNewViewer, hwndPrev); + return hwndPrev; } /* EOF */ diff --git a/reactos/subsys/win32k/ntuser/cursoricon.c b/reactos/subsys/win32k/ntuser/cursoricon.c index 41d069e44ac..65fe5467d3b 100644 --- a/reactos/subsys/win32k/ntuser/cursoricon.c +++ b/reactos/subsys/win32k/ntuser/cursoricon.c @@ -16,9 +16,66 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id$ */ + +/* + * We handle two types of cursors/icons: + * - Private + * Loaded without LR_SHARED flag + * Private to a process + * Can be deleted by calling NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL + * - Shared + * Loaded with LR_SHARED flag + * Possibly shared by multiple processes + * Immune to NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid + * There's a M:N relationship between processes and (shared) cursor/icons. + * A process can have multiple cursor/icons and a cursor/icon can be used + * by multiple processes. To keep track of this we keep a list of all + * cursor/icons (CurIconList) and per cursor/icon we keep a list of + * CURICON_PROCESS structs starting at CurIcon->ProcessList. + */ + #include +static PAGED_LOOKASIDE_LIST ProcessLookasideList; +static LIST_ENTRY CurIconList; +static FAST_MUTEX CurIconListLock; + +/* Look up the location of the cursor in the GDIDEVICE structure + * when all we know is the window station object + * Actually doesn't use the window station, but should... */ +BOOL FASTCALL +IntGetCursorLocation(PWINSTATION_OBJECT WinStaObject, POINT *loc) +{ + HDC hDC; + PDC dc; + HBITMAP hBitmap; + BITMAPOBJ *BitmapObj; + SURFOBJ *SurfObj; + +#if 1 + /* FIXME - get the screen dc from the window station or desktop */ + if (!(hDC = IntGetScreenDC())) + return FALSE; +#endif + + if (!(dc = DC_LockDc(hDC))) + return FALSE; + + hBitmap = dc->w.hBitmap; + DC_UnlockDc(hDC); + if (!(BitmapObj = BITMAPOBJ_LockBitmap(hBitmap))) + return FALSE; + + SurfObj = &BitmapObj->SurfObj; + loc->x = GDIDEV(SurfObj)->Pointer.Pos.x; + loc->y = GDIDEV(SurfObj)->Pointer.Pos.y; + + BITMAPOBJ_UnlockBitmap(hBitmap); + return TRUE; +} + PCURICON_OBJECT FASTCALL IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle) { @@ -93,10 +150,9 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor, { /* Remove the cursor if it was displayed */ if (GDIDEV(SurfObj)->Pointer.MovePointer) - GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, -1, -1, NULL); + GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, -1, -1, &GDIDEV(SurfObj)->Pointer.Exclude); else - EngMovePointer(SurfObj, -1, -1, NULL); - GDIDEV(SurfObj)->Pointer.Exclude.right = -1; + EngMovePointer(SurfObj, -1, -1, &GDIDEV(SurfObj)->Pointer.Exclude); } GDIDEV(SurfObj)->Pointer.Status = SPS_ACCEPT_NOEXCLUDE; @@ -195,9 +251,9 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor, SurfObj, soMask, soColor, XlateObj, NewCursor->IconInfo.xHotspot, NewCursor->IconInfo.yHotspot, - CurInfo->x, - CurInfo->y, - NULL, + GDIDEV(SurfObj)->Pointer.Pos.x, + GDIDEV(SurfObj)->Pointer.Pos.y, + &(GDIDEV(SurfObj)->Pointer.Exclude), SPS_CHANGE); DPRINT("SetCursor: DrvSetPointerShape() returned %x\n", GDIDEV(SurfObj)->Pointer.Status); @@ -213,9 +269,9 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor, SurfObj, soMask, soColor, XlateObj, NewCursor->IconInfo.xHotspot, NewCursor->IconInfo.yHotspot, - CurInfo->x, - CurInfo->y, - NULL, + GDIDEV(SurfObj)->Pointer.Pos.x, + GDIDEV(SurfObj)->Pointer.Pos.y, + &(GDIDEV(SurfObj)->Pointer.Exclude), SPS_CHANGE); GDIDEV(SurfObj)->Pointer.MovePointer = EngMovePointer; } @@ -248,6 +304,61 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor, BOOL FASTCALL IntSetupCurIconHandles(PWINSTATION_OBJECT WinStaObject) { + ExInitializePagedLookasideList(&ProcessLookasideList, + NULL, + NULL, + 0, + sizeof(CURICON_PROCESS), + 0, + 128); + InitializeListHead(&CurIconList); + ExInitializeFastMutex(&CurIconListLock); + + return TRUE; +} + +/* + * We have to register that this object is in use by the current + * process. The only way to do that seems to be to walk the list + * of cursor/icon objects starting at W32Process->CursorIconListHead. + * If the object is already present in the list, we don't have to do + * anything, if it's not present we add it and inc the ProcessCount + * in the object. Having to walk the list kind of sucks, but that's + * life... + */ +static BOOLEAN FASTCALL +ReferenceCurIconByProcess(PCURICON_OBJECT Object) +{ + PW32PROCESS Win32Process; + PLIST_ENTRY Search; + PCURICON_PROCESS Current; + + Win32Process = PsGetWin32Process(); + + ExAcquireFastMutex(&Object->Lock); + Search = Object->ProcessList.Flink; + while (Search != &Object->ProcessList) + { + Current = CONTAINING_RECORD(Search, CURICON_PROCESS, ListEntry); + if (Current->Process == Win32Process) + { + /* Already registered for this process */ + ExReleaseFastMutex(&Object->Lock); + return TRUE; + } + Search = Search->Flink; + } + + /* Not registered yet */ + Current = ExAllocateFromPagedLookasideList(&ProcessLookasideList); + if (NULL == Current) + { + return FALSE; + } + InsertHeadList(&Object->ProcessList, &Current->ListEntry); + Current->Process = Win32Process; + + ExReleaseFastMutex(&Object->Lock); return TRUE; } @@ -255,41 +366,39 @@ PCURICON_OBJECT FASTCALL IntFindExistingCurIconObject(PWINSTATION_OBJECT WinStaObject, HMODULE hModule, HRSRC hRsrc, LONG cx, LONG cy) { - PUSER_HANDLE_TABLE HandleTable; PLIST_ENTRY CurrentEntry; - PUSER_HANDLE_BLOCK Current; PCURICON_OBJECT Object; - ULONG i; - - HandleTable = (PUSER_HANDLE_TABLE)WinStaObject->HandleTable; - ObmpLockHandleTable(HandleTable); - - CurrentEntry = HandleTable->ListHead.Flink; - while(CurrentEntry != &HandleTable->ListHead) + + ExAcquireFastMutex(&CurIconListLock); + + CurrentEntry = CurIconList.Flink; + while (CurrentEntry != &CurIconList) { - Current = CONTAINING_RECORD(CurrentEntry, USER_HANDLE_BLOCK, ListEntry); - for(i = 0; i < HANDLE_BLOCK_ENTRIES; i++) + Object = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); + CurrentEntry = CurrentEntry->Flink; + if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon))) { - Object = (PCURICON_OBJECT)Current->Handles[i].ObjectBody; - if(Object && (ObmReferenceObjectByPointer(Object, otCursorIcon) == STATUS_SUCCESS)) + if((Object->hModule == hModule) && (Object->hRsrc == hRsrc)) { - if((Object->hModule == hModule) && (Object->hRsrc == hRsrc)) + if(cx && ((cx != Object->Size.cx) || (cy != Object->Size.cy))) { - if(cx && ((cx != Object->Size.cx) || (cy != Object->Size.cy))) - { - ObmDereferenceObject(Object); - continue; - } - ObmpUnlockHandleTable(HandleTable); - return Object; + ObmDereferenceObject(Object); + continue; } - ObmDereferenceObject(Object); + if (! ReferenceCurIconByProcess(Object)) + { + ExReleaseFastMutex(&CurIconListLock); + return NULL; + } + ExReleaseFastMutex(&CurIconListLock); + return Object; } } - CurrentEntry = CurrentEntry->Flink; + ObmDereferenceObject(Object); } - ObmpUnlockHandleTable(HandleTable); + ExReleaseFastMutex(&CurIconListLock); + return NULL; } @@ -298,7 +407,6 @@ IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject) { PCURICON_OBJECT Object; HANDLE Handle; - PW32PROCESS Win32Process; Object = ObmCreateObject(WinStaObject->HandleTable, &Handle, otCursorIcon, sizeof(CURICON_OBJECT)); @@ -308,38 +416,89 @@ IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject) return FALSE; } - Win32Process = PsGetWin32Process(); - - IntLockProcessCursorIcons(Win32Process); - InsertTailList(&Win32Process->CursorIconListHead, &Object->ListEntry); - IntUnLockProcessCursorIcons(Win32Process); - Object->Self = Handle; - Object->Process = PsGetWin32Process(); - + ExInitializeFastMutex(&Object->Lock); + InitializeListHead(&Object->ProcessList); + + if (! ReferenceCurIconByProcess(Object)) + { + DPRINT1("Failed to add process\n"); + ObmCloseHandle(WinStaObject->HandleTable, Handle); + ObmDereferenceObject(Object); + return NULL; + } + + ExAcquireFastMutex(&CurIconListLock); + InsertHeadList(&CurIconList, &Object->ListEntry); + ExReleaseFastMutex(&CurIconListLock); + + ObmDereferenceObject(Object); + return Object; } -BOOL FASTCALL -IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL RemoveFromProcess) +BOOLEAN FASTCALL +IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT Object, BOOL ProcessCleanup) { PSYSTEM_CURSORINFO CurInfo; - PCURICON_OBJECT Object; HBITMAP bmpMask, bmpColor; - NTSTATUS Status; - BOOL Ret; - - Status = ObmReferenceObjectByHandle(WinStaObject->HandleTable, Handle, otCursorIcon, (PVOID*)&Object); - if(!NT_SUCCESS(Status)) - { - return FALSE; - } - - if (Object->Process != PsGetWin32Process()) - { - ObmDereferenceObject(Object); - return FALSE; - } + BOOLEAN Ret; + PLIST_ENTRY Search; + PCURICON_PROCESS Current = NULL; + PW32PROCESS W32Process = PsGetWin32Process(); + + ExAcquireFastMutex(&Object->Lock); + + /* Private objects can only be destroyed by their own process */ + if (NULL == Object->hModule) + { + ASSERT(Object->ProcessList.Flink->Flink == &Object->ProcessList); + Current = CONTAINING_RECORD(Object->ProcessList.Flink, CURICON_PROCESS, ListEntry); + if (Current->Process != W32Process) + { + ExReleaseFastMutex(&Object->Lock); + DPRINT1("Trying to destroy private icon/cursor of another process\n"); + return FALSE; + } + } + else if (! ProcessCleanup) + { + ExReleaseFastMutex(&Object->Lock); + DPRINT("Trying to destroy shared icon/cursor\n"); + return FALSE; + } + + /* Now find this process in the list of processes referencing this object and + remove it from that list */ + Search = Object->ProcessList.Flink; + while (Search != &Object->ProcessList) + { + Current = CONTAINING_RECORD(Search, CURICON_PROCESS, ListEntry); + if (Current->Process == W32Process) + { + break; + } + Search = Search->Flink; + } + ASSERT(Search != &Object->ProcessList); + RemoveEntryList(Search); + ExFreeToPagedLookasideList(&ProcessLookasideList, Current); + + /* If there are still processes referencing this object we can't destroy it yet */ + if (! IsListEmpty(&Object->ProcessList)) + { + ExReleaseFastMutex(&Object->Lock); + return TRUE; + } + + ExReleaseFastMutex(&Object->Lock); + + if (! ProcessCleanup) + { + ExAcquireFastMutex(&CurIconListLock); + RemoveEntryList(&Object->ListEntry); + ExReleaseFastMutex(&CurIconListLock); + } CurInfo = IntGetSysCursorInfo(WinStaObject); @@ -351,15 +510,8 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL Rem bmpMask = Object->IconInfo.hbmMask; bmpColor = Object->IconInfo.hbmColor; - - if (Object->Process && RemoveFromProcess) - { - IntLockProcessCursorIcons(Object->Process); - RemoveEntryList(&Object->ListEntry); - IntUnLockProcessCursorIcons(Object->Process); - } - Ret = NT_SUCCESS(ObmCloseHandle(WinStaObject->HandleTable, Handle)); + Ret = NT_SUCCESS(ObmCloseHandle(WinStaObject->HandleTable, Object->Self)); /* delete bitmaps */ if(bmpMask) @@ -372,8 +524,6 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL Rem GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess()); NtGdiDeleteObject(bmpColor); } - - ObmDereferenceObject(Object); return Ret; } @@ -382,23 +532,50 @@ VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process) { PWINSTATION_OBJECT WinStaObject; - PCURICON_OBJECT Current; - PLIST_ENTRY CurrentEntry, NextEntry; - + PLIST_ENTRY CurrentEntry; + PCURICON_OBJECT Object; + PLIST_ENTRY ProcessEntry; + PCURICON_PROCESS ProcessData; + WinStaObject = IntGetWinStaObj(); - if(WinStaObject != NULL) + if(WinStaObject == NULL) { - CurrentEntry = Win32Process->CursorIconListHead.Flink; - while(CurrentEntry != &Win32Process->CursorIconListHead) - { - NextEntry = CurrentEntry->Flink; - Current = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); - RemoveEntryList(&Current->ListEntry); - IntDestroyCurIconObject(WinStaObject, Current->Self, FALSE); - CurrentEntry = NextEntry; - } - ObDereferenceObject(WinStaObject); + return; } + + ExAcquireFastMutex(&CurIconListLock); + + CurrentEntry = CurIconList.Flink; + while (CurrentEntry != &CurIconList) + { + Object = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); + CurrentEntry = CurrentEntry->Flink; + if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon))) + { + ExAcquireFastMutex(&Object->Lock); + ProcessEntry = Object->ProcessList.Flink; + while (ProcessEntry != &Object->ProcessList) + { + ProcessData = CONTAINING_RECORD(ProcessEntry, CURICON_PROCESS, ListEntry); + if (Win32Process == ProcessData->Process) + { + ExReleaseFastMutex(&Object->Lock); + RemoveEntryList(&Object->ListEntry); + IntDestroyCurIconObject(WinStaObject, Object, TRUE); + break; + } + ProcessEntry = ProcessEntry->Flink; + } + if (ProcessEntry == &Object->ProcessList) + { + ExReleaseFastMutex(&Object->Lock); + } + ObmDereferenceObject(Object); + } + } + + ExReleaseFastMutex(&CurIconListLock); + ObDereferenceObject(WinStaObject); } /* @@ -616,6 +793,16 @@ NtUserGetCursorInfo( PWINSTATION_OBJECT WinStaObject; NTSTATUS Status; PCURICON_OBJECT CursorObject; + +#if 1 + HDC hDC; + + /* FIXME - get the screen dc from the window station or desktop */ + if (!(hDC = IntGetScreenDC())) + { + return FALSE; + } +#endif Status = MmCopyFromCaller(&SafeCi.cbSize, pci, sizeof(DWORD)); if(!NT_SUCCESS(Status)) @@ -641,9 +828,9 @@ NtUserGetCursorInfo( SafeCi.flags = ((CurInfo->ShowingCursor && CursorObject) ? CURSOR_SHOWING : 0); SafeCi.hCursor = (CursorObject ? (HCURSOR)CursorObject->Self : (HCURSOR)0); - SafeCi.ptScreenPos.x = CurInfo->x; - SafeCi.ptScreenPos.y = CurInfo->y; - + + IntGetCursorLocation(WinStaObject, &SafeCi.ptScreenPos); + Status = MmCopyToCaller(pci, &SafeCi, sizeof(CURSORINFO)); if(!NT_SUCCESS(Status)) { @@ -671,6 +858,7 @@ NtUserClipCursor( PSYSTEM_CURSORINFO CurInfo; RECT Rect; PWINDOW_OBJECT DesktopWindow = NULL; + POINT MousePos; WinStaObject = IntGetWinStaObj(); if (WinStaObject == NULL) @@ -686,6 +874,8 @@ NtUserClipCursor( } CurInfo = IntGetSysCursorInfo(WinStaObject); + IntGetCursorLocation(WinStaObject, &MousePos); + if(WinStaObject->ActiveDesktop) DesktopWindow = IntGetWindowObject(WinStaObject->ActiveDesktop->DesktopWindow); @@ -701,8 +891,8 @@ NtUserClipCursor( CurInfo->CursorClipInfo.Bottom = min(Rect.bottom - 1, DesktopWindow->WindowRect.bottom - 1); IntReleaseWindowObject(DesktopWindow); - mi.dx = CurInfo->x; - mi.dy = CurInfo->y; + mi.dx = MousePos.x; + mi.dy = MousePos.y; mi.mouseData = 0; mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; mi.time = 0; @@ -729,6 +919,8 @@ NtUserDestroyCursorIcon( DWORD Unknown) { PWINSTATION_OBJECT WinStaObject; + PCURICON_OBJECT Object; + NTSTATUS Status; WinStaObject = IntGetWinStaObj(); if(WinStaObject == NULL) @@ -736,14 +928,24 @@ NtUserDestroyCursorIcon( return FALSE; } - if(IntDestroyCurIconObject(WinStaObject, Handle, TRUE)) + Status = ObmReferenceObjectByHandle(WinStaObject->HandleTable, Handle, otCursorIcon, (PVOID*)&Object); + if(!NT_SUCCESS(Status)) { + ObDereferenceObject(WinStaObject); + SetLastNtError(Status); + return FALSE; + } + + if(IntDestroyCurIconObject(WinStaObject, Object, FALSE)) + { + ObmDereferenceObject(Object); ObDereferenceObject(WinStaObject); return TRUE; } - SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE); + ObmDereferenceObject(Object); ObDereferenceObject(WinStaObject); + SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE); return FALSE; } @@ -805,8 +1007,6 @@ NtUserGetClipCursor( WinStaObject = IntGetWinStaObj(); if (WinStaObject == NULL) { - DPRINT("Validation of window station handle (0x%X) failed\n", - PROCESS_WINDOW_STATION()); return FALSE; } diff --git a/reactos/subsys/win32k/ntuser/desktop.c b/reactos/subsys/win32k/ntuser/desktop.c index 57e595fbc79..2de3f2369f4 100644 --- a/reactos/subsys/win32k/ntuser/desktop.c +++ b/reactos/subsys/win32k/ntuser/desktop.c @@ -596,7 +596,7 @@ NtUserCreateDesktop( */ Status = ObCreateObject( - ExGetPreviousMode(), + KernelMode, ExDesktopObjectType, &ObjectAttributes, ExGetPreviousMode(), diff --git a/reactos/subsys/win32k/ntuser/input.c b/reactos/subsys/win32k/ntuser/input.c index 1544141599d..735f789e994 100644 --- a/reactos/subsys/win32k/ntuser/input.c +++ b/reactos/subsys/win32k/ntuser/input.c @@ -540,7 +540,7 @@ IntMouseInput(MOUSEINPUT *mi) const UINT SwapBtnMsg[2][2] = {{WM_LBUTTONDOWN, WM_RBUTTONDOWN}, {WM_LBUTTONUP, WM_RBUTTONUP}}; const WPARAM SwapBtn[2] = {MK_LBUTTON, MK_RBUTTON}; - POINT MousePos; + POINT MousePos, OrgPos; PSYSTEM_CURSORINFO CurInfo; PWINSTATION_OBJECT WinSta; BOOL DoMove, SwapButtons; @@ -586,8 +586,10 @@ IntMouseInput(MOUSEINPUT *mi) DoMove = FALSE; ExAcquireFastMutex(&CurInfo->CursorMutex); - MousePos.x = CurInfo->x; - MousePos.y = CurInfo->y; + IntGetCursorLocation(WinSta, &MousePos); + OrgPos.x = MousePos.x; + OrgPos.y = MousePos.y; + if(mi->dwFlags & MOUSEEVENTF_MOVE) { if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE) @@ -631,12 +633,7 @@ IntMouseInput(MOUSEINPUT *mi) MousePos.y = (LONG)CurInfo->CursorClipInfo.Top; } - DoMove = (MousePos.x != CurInfo->x || MousePos.y != CurInfo->y); - if(DoMove) - { - CurInfo->x = MousePos.x; - CurInfo->y = MousePos.y; - } + DoMove = (MousePos.x != OrgPos.x || MousePos.y != OrgPos.y); } ExReleaseFastMutex(&CurInfo->CursorMutex); @@ -657,12 +654,13 @@ IntMouseInput(MOUSEINPUT *mi) if (GDIDEV(SurfObj)->Pointer.MovePointer) { GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude)); - } - /* FIXME - That's a bad thing! We should't access private gdi pointer fields - from here. However it is required so MouseSafetyOnDrawEnd() can - properly paint the mouse cursor to the screen again. See the - comment in MouseSafetyOnDrawEnd() to fix this problem! */ - GDIDEV(SurfObj)->Pointer.Pos = MousePos; + } else { + EngMovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude)); + } + /* Only now, update the info in the GDIDEVICE, so EngMovePointer can + * use the old values to move the pointer image */ + GDIDEV(SurfObj)->Pointer.Pos.x = MousePos.x; + GDIDEV(SurfObj)->Pointer.Pos.y = MousePos.y; BITMAPOBJ_UnlockBitmap(hBitmap); } diff --git a/reactos/subsys/win32k/ntuser/keyboard.c b/reactos/subsys/win32k/ntuser/keyboard.c index 50a4a2c1008..835a5b88697 100644 --- a/reactos/subsys/win32k/ntuser/keyboard.c +++ b/reactos/subsys/win32k/ntuser/keyboard.c @@ -16,8 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Messages diff --git a/reactos/subsys/win32k/ntuser/menu.c b/reactos/subsys/win32k/ntuser/menu.c index 81d757c158b..b59b7032f3a 100644 --- a/reactos/subsys/win32k/ntuser/menu.c +++ b/reactos/subsys/win32k/ntuser/menu.c @@ -1353,7 +1353,7 @@ NtUserCreateMenu(BOOL PopupMenu) if (!NT_SUCCESS(Status)) { DPRINT("Validation of window station handle (0x%X) failed\n", - PROCESS_WINDOW_STATION()); + PsGetCurrentProcess()->Win32WindowStation); SetLastNtError(Status); return (HMENU)0; } diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index c3f4482bbd8..3ec02fa815a 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -835,7 +835,7 @@ NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo, } Info.Msg.lParam = (LPARAM) UserMem; } - if (Msg.FreeLParam && 0 != Msg.Msg.lParam) + if (RemoveMsg && Msg.FreeLParam && 0 != Msg.Msg.lParam) { ExFreePool((void *) Msg.Msg.lParam); } @@ -1123,7 +1123,6 @@ NtUserPostMessage(HWND Wnd, } else { - PSYSTEM_CURSORINFO CurInfo; Window = IntGetWindowObject(Wnd); if (NULL == Window) { @@ -1149,9 +1148,8 @@ NtUserPostMessage(HWND Wnd, SetLastWin32Error(ERROR_INVALID_PARAMETER); return FALSE; } - CurInfo = IntGetSysCursorInfo(PsGetWin32Thread()->Desktop->WindowStation); - KernelModeMsg.pt.x = CurInfo->x; - KernelModeMsg.pt.y = CurInfo->y; + IntGetCursorLocation(PsGetWin32Thread()->Desktop->WindowStation, + &KernelModeMsg.pt); KeQueryTickCount(&LargeTickCount); KernelModeMsg.time = LargeTickCount.u.LowPart; MsqPostMessage(Window->MessageQueue, &KernelModeMsg, diff --git a/reactos/subsys/win32k/ntuser/misc.c b/reactos/subsys/win32k/ntuser/misc.c index 7910397f12f..b8acc8802d1 100644 --- a/reactos/subsys/win32k/ntuser/misc.c +++ b/reactos/subsys/win32k/ntuser/misc.c @@ -37,14 +37,14 @@ PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue() { } BOOL FASTCALL -IntRegisterLogonProcess(DWORD ProcessId, BOOL Register) +IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register) { PEPROCESS Process; NTSTATUS Status; CSRSS_API_REQUEST Request; CSRSS_API_REPLY Reply; - Status = PsLookupProcessByProcessId((PVOID)ProcessId, + Status = PsLookupProcessByProcessId(ProcessId, &Process); if (!NT_SUCCESS(Status)) { @@ -263,7 +263,6 @@ NtUserCallOneParam( case ONEPARAM_ROUTINE_GETCURSORPOSITION: { - PSYSTEM_CURSORINFO CurInfo; PWINSTATION_OBJECT WinStaObject; NTSTATUS Status; POINT Pos; @@ -277,10 +276,8 @@ NtUserCallOneParam( if (!NT_SUCCESS(Status)) return (DWORD)FALSE; - CurInfo = IntGetSysCursorInfo(WinStaObject); /* FIXME - check if process has WINSTA_READATTRIBUTES */ - Pos.x = CurInfo->x; - Pos.y = CurInfo->y; + IntGetCursorLocation(WinStaObject, &Pos); Status = MmCopyToCaller((PPOINT)Param, &Pos, sizeof(POINT)); if(!NT_SUCCESS(Status)) @@ -519,7 +516,7 @@ NtUserCallTwoParam( } case TWOPARAM_ROUTINE_REGISTERLOGONPROC: - return (DWORD)IntRegisterLogonProcess(Param1, (BOOL)Param2); + return (DWORD)IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2); case TWOPARAM_ROUTINE_SETSYSCOLORS: { diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index 18a1637fbbc..900f3b9b6b3 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -1679,7 +1679,7 @@ MsqGetTimerMessage(PUSER_MESSAGE_QUEUE MessageQueue, { Timer = CONTAINING_RECORD(MessageQueue->TimerListHead.Flink, TIMER_ENTRY, ListEntry); - DPRINT("Checking timer %p wnd %x expiry %I64d\n", Timer, Timer->wnd, + DPRINT("Checking timer %p wnd %x expiry %I64d\n", Timer, Timer->Wnd, Timer->ExpiryTime.QuadPart); EnumEntry = EnumEntry->Flink; if ((NULL == WndFilter || Timer->Wnd == WndFilter) && diff --git a/reactos/subsys/win32k/ntuser/painting.c b/reactos/subsys/win32k/ntuser/painting.c index 3dd765ba674..9fb5e70aecd 100644 --- a/reactos/subsys/win32k/ntuser/painting.c +++ b/reactos/subsys/win32k/ntuser/painting.c @@ -105,6 +105,11 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) MsqDecPaintCountQueue(Window->MessageQueue); IntUnLockWindowUpdate(Window); IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0); + if ((HANDLE) 1 != TempRegion && NULL != TempRegion) + { + /* NOTE: The region can already be deleted! */ + GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT); + } } if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) @@ -630,29 +635,9 @@ IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, if (Window != NULL) { IntLockWindowUpdate(Window); - if (0 != (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) - && ((0 == MsgFilterMin && 0 == MsgFilterMax) || - (MsgFilterMin <= WM_NCPAINT && - WM_NCPAINT <= MsgFilterMax))) - { - Message->message = WM_NCPAINT; - Message->wParam = (WPARAM)Window->NCUpdateRegion; - Message->lParam = 0; - if (Remove) - { - if ((HANDLE) 1 != Window->NCUpdateRegion && - NULL != Window->NCUpdateRegion) - { - GDIOBJ_SetOwnership(Window->NCUpdateRegion, PsGetCurrentProcess()); - } - IntValidateParent(Window, Window->NCUpdateRegion); - Window->NCUpdateRegion = NULL; - Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; - MsqDecPaintCountQueue(Window->MessageQueue); - } - } else if ((0 == MsgFilterMin && 0 == MsgFilterMax) || - (MsgFilterMin <= WM_PAINT && - WM_PAINT <= MsgFilterMax)) + + if ((MsgFilterMin == 0 && MsgFilterMax == 0) || + (MsgFilterMin <= WM_PAINT && WM_PAINT <= MsgFilterMax)) { Message->message = WM_PAINT; Message->wParam = Message->lParam = 0; @@ -737,6 +722,28 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) NtUserHideCaret(hWnd); + if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) + { + HRGN hRgn; + + if (Window->NCUpdateRegion != (HANDLE)1 && + Window->NCUpdateRegion != NULL) + { + GDIOBJ_SetOwnership(Window->NCUpdateRegion, PsGetCurrentProcess()); + } + hRgn = Window->NCUpdateRegion; + IntValidateParent(Window, Window->NCUpdateRegion); + Window->NCUpdateRegion = NULL; + Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; + MsqDecPaintCountQueue(Window->MessageQueue); + IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0); + if (hRgn != (HANDLE)1 && hRgn != NULL) + { + /* NOTE: The region can already by deleted! */ + GDIOBJ_FreeObj(hRgn, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT); + } + } + RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT)); Ps.hdc = NtUserGetDCEx(hWnd, 0, DCX_INTERSECTUPDATE | DCX_WINDOWPAINT | DCX_USESTYLE); @@ -754,17 +761,17 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) IntValidateParent(Window, Window->UpdateRegion); Rgn = RGNDATA_LockRgn(Window->UpdateRegion); if (NULL != Rgn) - { - UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint); - RGNDATA_UnlockRgn(Window->UpdateRegion); - IntGdiOffsetRect(&Ps.rcPaint, - Window->WindowRect.left - Window->ClientRect.left, - Window->WindowRect.top - Window->ClientRect.top); - } + { + UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint); + RGNDATA_UnlockRgn(Window->UpdateRegion); + IntGdiOffsetRect(&Ps.rcPaint, + Window->WindowRect.left - Window->ClientRect.left, + Window->WindowRect.top - Window->ClientRect.top); + } else - { - IntGetClientRect(Window, &Ps.rcPaint); - } + { + IntGetClientRect(Window, &Ps.rcPaint); + } GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess()); NtGdiDeleteObject(Window->UpdateRegion); Window->UpdateRegion = NULL; diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index 12bca2c942d..76755d5ff30 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -324,7 +324,7 @@ NtUserCreateWindowStation( DPRINT("Creating window station (%wZ)\n", &WindowStationName); Status = ObCreateObject( - ExGetPreviousMode(), + KernelMode, ExWindowStationObjectType, &ObjectAttributes, ExGetPreviousMode(), @@ -336,7 +336,7 @@ NtUserCreateWindowStation( if (!NT_SUCCESS(Status)) { - DPRINT("Failed creating window station (%wZ)\n", &WindowStationName); + DPRINT1("Failed creating window station (%wZ)\n", &WindowStationName); ExFreePool(WindowStationName.Buffer); SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); return 0; @@ -389,8 +389,6 @@ NtUserCreateWindowStation( ExInitializeFastMutex(&CurInfo->CursorMutex); CurInfo->Enabled = FALSE; CurInfo->ButtonsDown = 0; - CurInfo->x = (LONG)0; - CurInfo->y = (LONG)0; CurInfo->CursorClipInfo.IsClipped = FALSE; CurInfo->LastBtnDown = 0; CurInfo->CurrentCursorObject = NULL; @@ -1004,7 +1002,7 @@ BuildWindowStationNameList( char InitialBuffer[256], *Buffer; ULONG Context, ReturnLength, BufferSize; DWORD EntryCount; - PDIRECTORY_BASIC_INFORMATION DirEntry; + POBJECT_DIRECTORY_INFORMATION DirEntry; WCHAR NullWchar; /* @@ -1090,7 +1088,7 @@ BuildWindowStationNameList( */ ReturnLength = sizeof(DWORD); EntryCount = 0; - for (DirEntry = (PDIRECTORY_BASIC_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length; + for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length; DirEntry++) { ReturnLength += DirEntry->ObjectName.Length + sizeof(WCHAR); @@ -1137,7 +1135,7 @@ BuildWindowStationNameList( lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD)); NullWchar = L'\0'; - for (DirEntry = (PDIRECTORY_BASIC_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length; + for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length; DirEntry++) { Status = MmCopyToCaller(lpBuffer, DirEntry->ObjectName.Buffer, DirEntry->ObjectName.Length); diff --git a/reactos/subsys/win32k/objects/bitmaps.c b/reactos/subsys/win32k/objects/bitmaps.c index 74490b93c1a..31b7ff80f36 100644 --- a/reactos/subsys/win32k/objects/bitmaps.c +++ b/reactos/subsys/win32k/objects/bitmaps.c @@ -49,8 +49,8 @@ NtGdiBitBlt( HPALETTE SourcePalette = 0, DestPalette = 0; PGDIBRUSHOBJ BrushObj; GDIBRUSHINST BrushInst; - BOOL UsesSource = ROP_USES_SOURCE(ROP); - BOOL UsesPattern = ROP_USES_PATTERN(ROP); + BOOL UsesSource = ROP3_USES_SOURCE(ROP); + BOOL UsesPattern = ROP3_USES_PATTERN(ROP); DCDest = DC_LockDc(hDCDest); if (NULL == DCDest) @@ -201,7 +201,8 @@ NtGdiBitBlt( /* Perform the bitblt operation */ Status = IntEngBitBlt(BitmapDest, BitmapSrc, NULL, DCDest->CombinedClip, XlateObj, - &DestRect, &SourcePoint, NULL, BrushObj ? &BrushInst.BrushObject : NULL, &BrushOrigin, ROP); + &DestRect, &SourcePoint, NULL, BrushObj ? &BrushInst.BrushObject : NULL, + &BrushOrigin, ROP3_TO_ROP4(ROP)); if (UsesSource && XlateObj != NULL) EngDeleteXlate(XlateObj); diff --git a/reactos/subsys/win32k/objects/brush.c b/reactos/subsys/win32k/objects/brush.c index 5d9011fd1dd..a14fb5a1efa 100644 --- a/reactos/subsys/win32k/objects/brush.c +++ b/reactos/subsys/win32k/objects/brush.c @@ -239,7 +239,7 @@ IntPatBlt( NULL, &BrushInst.BrushObject, &BrushOrigin, - ROP); + ROP3_TO_ROP4(ROP)); } BITMAPOBJ_UnlockBitmap(dc->w.hBitmap); diff --git a/reactos/subsys/win32k/objects/dc.c b/reactos/subsys/win32k/objects/dc.c index 3f5139af4b8..ad19cee6efd 100644 --- a/reactos/subsys/win32k/objects/dc.c +++ b/reactos/subsys/win32k/objects/dc.c @@ -212,6 +212,7 @@ NtGdiCreateCompatableDC(HDC hDC) NewDC->w.textAlign = OrigDC->w.textAlign; NewDC->w.backgroundColor = OrigDC->w.backgroundColor; NewDC->w.backgroundMode = OrigDC->w.backgroundMode; + NewDC->w.ROPmode = OrigDC->w.ROPmode; DC_UnlockDc( hDC ); if (NULL != DisplayDC) { @@ -727,7 +728,7 @@ IntGdiCreateDC(PUNICODE_STRING Driver, if (Driver != NULL && Driver->Buffer != NULL) { - DPRINT("NAME: %S\n", Driver->Buffer); // FIXME: Should not crash if NULL + DPRINT("NAME: %ws\n", Driver); // FIXME: Should not crash if NULL } /* Allocate a DC object */ @@ -774,8 +775,8 @@ IntGdiCreateDC(PUNICODE_STRING Driver, NewDC->DMW.dmDisplayFrequency = 0; NewDC->w.bitsPerPixel = NewDC->DMW.dmBitsPerPel; // FIXME: set this here?? - NewDC->w.hPalette = NewDC->DevInfo->hpalDefault; + NewDC->w.ROPmode = R2_COPYPEN; DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel); diff --git a/reactos/subsys/win32k/objects/fillshap.c b/reactos/subsys/win32k/objects/fillshap.c index 7f0bd87dff9..066cf2204fe 100644 --- a/reactos/subsys/win32k/objects/fillshap.c +++ b/reactos/subsys/win32k/objects/fillshap.c @@ -28,7 +28,7 @@ &BrushInst.BrushObject, \ x, y, (x)+1, y, \ &RectBounds, \ - dc->w.ROPmode); + ROP2_TO_MIX(dc->w.ROPmode)); #define PUTLINE(x1,y1,x2,y2,BrushInst) \ ret = ret && IntEngLineTo(BitmapObj, \ @@ -36,7 +36,7 @@ &BrushInst.BrushObject, \ x1, y1, x2, y2, \ &RectBounds, \ - dc->w.ROPmode); + ROP2_TO_MIX(dc->w.ROPmode)); BOOL FASTCALL IntGdiPolygon(PDC dc, @@ -93,7 +93,7 @@ IntGdiPolygon(PDC dc, if (!(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)) { IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush); - ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, dc->w.ROPmode, UnsafePoints, Count, DestRect ); + ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(dc->w.ROPmode), UnsafePoints, Count, DestRect ); } BRUSHOBJ_UnlockBrush(dc->w.hBrush); @@ -128,7 +128,7 @@ IntGdiPolygon(PDC dc, To.x, To.y, &DestRect, - dc->w.ROPmode); /* MIX */ + ROP2_TO_MIX(dc->w.ROPmode)); /* MIX */ } } PENOBJ_UnlockPen( dc->w.hPen ); @@ -939,6 +939,7 @@ IntRectangle(PDC dc, GDIBRUSHINST PenBrushInst, FillBrushInst; BOOL ret = FALSE; // default to failure RECTL DestRect; + MIX Mix; ASSERT ( dc ); // caller's responsibility to set this up /* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */ @@ -978,7 +979,7 @@ IntRectangle(PDC dc, NULL, &FillBrushInst.BrushObject, NULL, - PATCOPY); + ROP3_TO_ROP4(PATCOPY)); } } @@ -1001,33 +1002,34 @@ IntRectangle(PDC dc, if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL)) { + Mix = ROP2_TO_MIX(dc->w.ROPmode); ret = ret && IntEngLineTo(BitmapObj, dc->CombinedClip, &PenBrushInst.BrushObject, LeftRect, TopRect, RightRect, TopRect, &DestRect, // Bounding rectangle - dc->w.ROPmode); // MIX + Mix); ret = ret && IntEngLineTo(BitmapObj, dc->CombinedClip, &PenBrushInst.BrushObject, RightRect, TopRect, RightRect, BottomRect, &DestRect, // Bounding rectangle - dc->w.ROPmode); // MIX + Mix); ret = ret && IntEngLineTo(BitmapObj, dc->CombinedClip, &PenBrushInst.BrushObject, RightRect, BottomRect, LeftRect, BottomRect, &DestRect, // Bounding rectangle - dc->w.ROPmode); // MIX + Mix); ret = ret && IntEngLineTo(BitmapObj, dc->CombinedClip, &PenBrushInst.BrushObject, LeftRect, BottomRect, LeftRect, TopRect, &DestRect, // Bounding rectangle - dc->w.ROPmode); // MIX */ + Mix); } PENOBJ_UnlockPen(dc->w.hPen); diff --git a/reactos/subsys/win32k/objects/gdiobj.c b/reactos/subsys/win32k/objects/gdiobj.c index 4b30364d506..79902d92b1e 100644 --- a/reactos/subsys/win32k/objects/gdiobj.c +++ b/reactos/subsys/win32k/objects/gdiobj.c @@ -327,7 +327,7 @@ GDIOBJ_AllocObj(ULONG ObjectType) PW32PROCESS W32Process; PGDIOBJHDR newObject; PPAGED_LOOKASIDE_LIST LookasideList; - LONG CurrentProcessId, LockedProcessId; + HANDLE CurrentProcessId, LockedProcessId; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif @@ -351,11 +351,8 @@ GDIOBJ_AllocObj(ULONG ObjectType) PGDIOBJ ObjectBody; LONG TypeInfo; - /* shift the process id to the left so we can use the first bit to lock - the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - CurrentProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = CurrentProcessId | 0x1; + CurrentProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)CurrentProcessId | 0x1); newObject->LockingThread = NULL; newObject->Locks = 0; @@ -376,7 +373,7 @@ GDIOBJ_AllocObj(ULONG ObjectType) FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead); if(FreeEntry != NULL) { - LONG PrevProcId; + HANDLE PrevProcId; UINT Index; HGDIOBJ Handle; @@ -387,8 +384,8 @@ GDIOBJ_AllocObj(ULONG ObjectType) Handle = (HGDIOBJ)((Index & 0xFFFF) | (ObjectType & 0xFFFF0000)); LockHandle: - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, 0); - if(PrevProcId == 0) + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0); + if(PrevProcId == NULL) { ASSERT(Entry->KernelData == NULL); @@ -399,7 +396,7 @@ LockHandle: Entry->Type = TypeInfo; /* unlock the entry */ - InterlockedExchange(&Entry->ProcessId, CurrentProcessId); + InterlockedExchangePointer(&Entry->ProcessId, CurrentProcessId); #ifdef GDI_DEBUG memset ( GDIHandleAllocator[Index], 0xcd, GDI_STACK_LEVELS * sizeof(ULONG) ); @@ -468,7 +465,9 @@ GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType) { PGDI_TABLE_ENTRY Entry; PPAGED_LOOKASIDE_LIST LookasideList; - LONG ProcessId, LockedProcessId, PrevProcId, ExpectedType; + HANDLE ProcessId, LockedProcessId, PrevProcId; + LONG ExpectedType; + BOOL Silent; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif @@ -484,10 +483,11 @@ GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType) return FALSE; } - /* shift the process id to the left so we can use the first bit to lock the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - ProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = ProcessId | 0x1; + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); + + Silent = (ObjectType & GDI_OBJECT_TYPE_SILENT); + ObjectType &= ~GDI_OBJECT_TYPE_SILENT; ExpectedType = ((ObjectType != GDI_OBJECT_TYPE_DONTCARE) ? ObjectType : 0); @@ -496,7 +496,7 @@ GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType) LockHandle: /* lock the object, we must not delete global objects, so don't exchange the locking process ID to zero when attempting to lock a global object... */ - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { if(Entry->Type != 0 && Entry->KernelData != NULL && (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType))) @@ -516,7 +516,7 @@ LockHandle: Entry->KernelData = NULL; /* unlock the handle slot */ - InterlockedExchange(&Entry->ProcessId, 0); + InterlockedExchangePointer(&Entry->ProcessId, NULL); /* push this entry to the free list */ InterlockedPushEntrySList(&HandleTable->FreeEntriesHead, @@ -546,7 +546,7 @@ LockHandle: Entry->Type = 0; /* unlock the handle slot */ - InterlockedExchange(&Entry->ProcessId, 0); + InterlockedExchangePointer(&Entry->ProcessId, NULL); /* report a successful deletion as the object is actually removed from the table */ return TRUE; @@ -562,7 +562,7 @@ LockHandle: { DPRINT1("Attempted to delete object 0x%x which was already deleted!\n", hObj); } - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); } } else if(PrevProcId == LockedProcessId) @@ -581,17 +581,20 @@ LockHandle: } else { - if((PrevProcId >> 1) == 0) + if(!Silent) { - DPRINT1("Attempted to free global gdi handle 0x%x, caller needs to get ownership first!!!", hObj); - } - else - { - DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, PrevProcId >> 1, ProcessId >> 1); - } + if(((ULONG_PTR)PrevProcId & ~0x1) == 0) + { + DPRINT1("Attempted to free global gdi handle 0x%x, caller needs to get ownership first!!!\n", hObj); + } + else + { + DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)ProcessId & ~0x1); + } #ifdef GDI_DEBUG - DPRINT1("-> called from %s:%i\n", file, line); + DPRINT1("-> called from %s:%i\n", file, line); #endif + } } return FALSE; @@ -712,10 +715,10 @@ GDI_CleanupForProcess (struct _EPROCESS *Process) PGDI_TABLE_ENTRY Entry, End; PEPROCESS CurrentProcess; PW32PROCESS W32Process; - LONG ProcId; + HANDLE ProcId; ULONG Index = RESERVE_ENTRIES_COUNT; - DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Pid); + DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Process->UniqueProcessId); CurrentProcess = PsGetCurrentProcess(); if (CurrentProcess != Process) { @@ -728,7 +731,7 @@ GDI_CleanupForProcess (struct _EPROCESS *Process) { /* FIXME - Instead of building the handle here and delete it using GDIOBJ_FreeObj we should delete it directly here! */ - ProcId = ((LONG)Process->UniqueProcessId << 1); + ProcId = Process->UniqueProcessId; End = &HandleTable->Entries[GDI_HANDLE_COUNT]; for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT]; @@ -736,7 +739,7 @@ GDI_CleanupForProcess (struct _EPROCESS *Process) Entry++, Index++) { /* ignore the lock bit */ - if((Entry->ProcessId & ~0x1) == ProcId && Entry->Type != 0) + if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && Entry->Type != 0) { HGDIOBJ ObjectHandle; @@ -761,7 +764,7 @@ GDI_CleanupForProcess (struct _EPROCESS *Process) KeDetachProcess(); } - DPRINT("Completed cleanup for process %d\n", Pid); + DPRINT("Completed cleanup for process %d\n", Process->UniqueProcessId); return TRUE; } @@ -785,7 +788,8 @@ GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType) { PGDI_TABLE_ENTRY Entry; PETHREAD Thread; - LONG ProcessId, LockedProcessId, PrevProcId, ExpectedType; + HANDLE ProcessId, LockedProcessId, PrevProcId; + LONG ExpectedType; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif @@ -794,10 +798,8 @@ GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType) Thread = PsGetCurrentThread(); - /* shift the process id to the left so we can use the first bit to lock the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - ProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = ProcessId | 0x1; + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); ExpectedType = ((ObjectType != GDI_OBJECT_TYPE_DONTCARE) ? ObjectType : 0); @@ -805,7 +807,7 @@ GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType) LockHandle: /* lock the object, we must not delete stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { LONG EntryType = Entry->Type << 16; @@ -835,14 +837,14 @@ LockHandle: #endif } - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); /* we're done, return the object body */ return GDIHdrToBdy(GdiHdr); } else { - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); #ifdef GDI_DEBUG if(++Attempts > 20) @@ -857,7 +859,7 @@ LockHandle: } else { - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); if(EntryType == 0) { @@ -888,17 +890,17 @@ LockHandle: /* try again */ goto LockHandle; } - else if((PrevProcId & ~0x1) == 0) + else if(((ULONG_PTR)PrevProcId & ~0x1) == 0) { /* we're trying to lock a global object, change the ProcessId to 0 and try again */ - ProcessId = 0x0; - LockedProcessId = ProcessId |0x1; + ProcessId = NULL; + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); goto LockHandle; } else { - DPRINT1("Attempted to lock foreign handle: 0x%x, Owner: 0x%x locked: 0x%x Caller: 0x%x, stockobj: 0x%x\n", hObj, PrevProcId >> 1, PrevProcId & 0x1, PsGetCurrentProcessId(), GDI_HANDLE_IS_STOCKOBJ(hObj)); + DPRINT1("Attempted to lock foreign handle: 0x%x, Owner: 0x%x locked: 0x%x Caller: 0x%x, stockobj: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)PrevProcId & 0x1, PsGetCurrentProcessId(), GDI_HANDLE_IS_STOCKOBJ(hObj)); KeRosDumpStackFrames ( NULL, 20 ); #ifdef GDI_DEBUG DPRINT1("-> called from %s:%i\n", file, line); @@ -927,7 +929,7 @@ GDIOBJ_UnlockObj (HGDIOBJ hObj) { PGDI_TABLE_ENTRY Entry; PETHREAD Thread; - LONG ProcessId, LockedProcessId, PrevProcId; + HANDLE ProcessId, LockedProcessId, PrevProcId; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif @@ -935,16 +937,14 @@ GDIOBJ_UnlockObj (HGDIOBJ hObj) DPRINT("GDIOBJ_UnlockObj: hObj: 0x%08x\n", hObj); Thread = PsGetCurrentThread(); - /* shift the process id to the left so we can use the first bit to lock the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - ProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = ProcessId | 0x1; + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); Entry = GDI_HANDLE_GET_ENTRY(HandleTable, hObj); LockHandle: /* lock the handle, we must not delete stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { /* we're unlocking an object that belongs to our process or it's a global @@ -982,7 +982,7 @@ LockHandle: /* we should delete the handle */ Entry->KernelData = NULL; - InterlockedExchange(&Entry->ProcessId, 0); + InterlockedExchangePointer(&Entry->ProcessId, 0); InterlockedPushEntrySList(&HandleTable->FreeEntriesHead, &HandleTable->FreeEntries[GDI_ENTRY_TO_INDEX(HandleTable, Entry)]); @@ -1005,7 +1005,7 @@ LockHandle: else { /* remove the handle slot lock */ - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); Ret = TRUE; } @@ -1017,7 +1017,7 @@ LockHandle: { DPRINT1("Attempted to unlock object 0x%x, previously locked by other thread (0x%x) from %s:%i (called from %s:%i)\n", hObj, PrevThread, GdiHdr->lockfile, GdiHdr->lockline, file, line); - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); } #endif else @@ -1029,7 +1029,7 @@ LockHandle: } #endif /* FIXME - we should give up after some time unless we want to wait forever! */ - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); DelayExecution(); goto LockHandle; @@ -1037,7 +1037,7 @@ LockHandle: } else { - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); DPRINT1("Attempted to unlock object 0x%x that is deleted!\n", hObj); } } @@ -1055,17 +1055,17 @@ LockHandle: /* try again */ goto LockHandle; } - else if((PrevProcId & ~0x1) == 0) + else if(((ULONG_PTR)PrevProcId & ~0x1) == 0) { /* we're trying to unlock a global object, change the ProcessId to 0 and try again */ - ProcessId = 0x0; - LockedProcessId = ProcessId |0x1; + ProcessId = NULL; + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); goto LockHandle; } else { - DPRINT1("Attempted to unlock foreign handle: 0x%x, Owner: 0x%x locked: 0x%x Caller: 0x%x, stockobj: 0x%x\n", hObj, PrevProcId >> 1, PrevProcId & 0x1, PsGetCurrentProcessId(), GDI_HANDLE_IS_STOCKOBJ(hObj)); + DPRINT1("Attempted to unlock foreign handle: 0x%x, Owner: 0x%x locked: 0x%x Caller: 0x%x, stockobj: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)PrevProcId & 0x1, PsGetCurrentProcessId(), GDI_HANDLE_IS_STOCKOBJ(hObj)); } return FALSE; @@ -1075,19 +1075,19 @@ BOOL INTERNAL_CALL GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle) { PGDI_TABLE_ENTRY Entry; - LONG ProcessId; + HANDLE ProcessId; BOOL Ret; DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle); if(!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle)) { - ProcessId = (LONG)PsGetCurrentProcessId() << 1; + ProcessId = PsGetCurrentProcessId(); Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle); Ret = Entry->KernelData != NULL && Entry->Type != 0 && - (Entry->ProcessId & ~0x1) == ProcessId; + (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId; return Ret; } @@ -1103,7 +1103,7 @@ GDIOBJ_ConvertToStockObj(HGDIOBJ *hObj) * MIGHT ATTEMPT TO LOCK THE OBJECT DURING THIS CALL!!! */ PGDI_TABLE_ENTRY Entry; - LONG ProcessId, LockedProcessId, PrevProcId; + HANDLE ProcessId, LockedProcessId, PrevProcId; PETHREAD Thread; #ifdef GDI_DEBUG ULONG Attempts = 0; @@ -1117,16 +1117,14 @@ GDIOBJ_ConvertToStockObj(HGDIOBJ *hObj) if(!GDI_HANDLE_IS_STOCKOBJ(*hObj)) { - /* shift the process id to the left so we can use the first bit to lock the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - ProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = ProcessId | 0x1; + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); Entry = GDI_HANDLE_GET_ENTRY(HandleTable, *hObj); LockHandle: /* lock the object, we must not convert stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, ProcessId); + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId); if(PrevProcId == ProcessId) { LONG NewType, PrevType, OldType; @@ -1165,7 +1163,7 @@ LockHandle: NTSTATUS Status; /* FIXME */ - Status = PsLookupProcessByProcessId((PVOID)(PrevProcId >> 1), &OldProcess); + Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess); if(NT_SUCCESS(Status)) { W32Process = OldProcess->Win32Process; @@ -1178,7 +1176,7 @@ LockHandle: } /* remove the process id lock and make it global */ - InterlockedExchange(&Entry->ProcessId, GDI_GLOBAL_PROCESS); + InterlockedExchangePointer(&Entry->ProcessId, GDI_GLOBAL_PROCESS); *hObj = (HGDIOBJ)((ULONG)(*hObj) | GDI_HANDLE_STOCK_MASK); @@ -1199,7 +1197,7 @@ LockHandle: /* WTF?! The object is already locked by a different thread! Release the lock, wait a bit and try again! FIXME - we should give up after some time unless we want to wait forever! */ - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); DelayExecution(); goto LockHandle; @@ -1237,7 +1235,7 @@ void INTERNAL_CALL GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner) { PGDI_TABLE_ENTRY Entry; - LONG ProcessId, LockedProcessId, PrevProcId; + HANDLE ProcessId, LockedProcessId, PrevProcId; PETHREAD Thread; #ifdef GDI_DEBUG ULONG Attempts = 0; @@ -1249,16 +1247,14 @@ GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner) if(!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle)) { - /* shift the process id to the left so we can use the first bit to lock the object. - FIXME - don't shift once ROS' PIDs match with nt! */ - ProcessId = (LONG)PsGetCurrentProcessId() << 1; - LockedProcessId = ProcessId | 0x1; + ProcessId = PsGetCurrentProcessId(); + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle); LockHandle: /* lock the object, we must not convert stock objects, so don't check!!! */ - PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, ProcessId, LockedProcessId); + PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, ProcessId, LockedProcessId); if(PrevProcId == ProcessId) { PETHREAD PrevThread; @@ -1276,7 +1272,7 @@ LockHandle: /* dereference the process' object counter */ /* FIXME */ - Status = PsLookupProcessByProcessId((PVOID)(PrevProcId >> 1), &OldProcess); + Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess); if(NT_SUCCESS(Status)) { W32Process = OldProcess->Win32Process; @@ -1289,8 +1285,7 @@ LockHandle: if(NewOwner != NULL) { - /* FIXME */ - ProcessId = (LONG)PsGetProcessId(NewOwner) << 1; + ProcessId = PsGetProcessId(NewOwner); /* Increase the new process' object counter */ W32Process = NewOwner->Win32Process; @@ -1303,7 +1298,7 @@ LockHandle: ProcessId = 0; /* remove the process id lock and change it to the new process id */ - InterlockedExchange(&Entry->ProcessId, ProcessId); + InterlockedExchangePointer(&Entry->ProcessId, ProcessId); /* we're done! */ return; @@ -1325,7 +1320,7 @@ LockHandle: being deleted in the meantime (because we don't have aquired a reference at this point). FIXME - we should give up after some time unless we want to wait forever! */ - InterlockedExchange(&Entry->ProcessId, PrevProcId); + InterlockedExchangePointer(&Entry->ProcessId, PrevProcId); DelayExecution(); goto LockHandle; @@ -1350,16 +1345,16 @@ LockHandle: /* try again */ goto LockHandle; } - else if((PrevProcId >> 1) == 0) + else if(((ULONG_PTR)PrevProcId & ~0x1) == 0) { /* allow changing ownership of global objects */ - ProcessId = 0; - LockedProcessId = ProcessId | 0x1; + ProcessId = NULL; + LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1); goto LockHandle; } - else if((PrevProcId >> 1) != (LONG)PsGetCurrentProcessId()) + else if((HANDLE)((ULONG_PTR)PrevProcId & ~0x1) != PsGetCurrentProcessId()) { - DPRINT1("Attempted to change ownership of object 0x%x (pid: 0x%x) from pid 0x%x!!!\n", ObjectHandle, PrevProcId >> 1, PsGetCurrentProcessId()); + DPRINT1("Attempted to change ownership of object 0x%x (pid: 0x%x) from pid 0x%x!!!\n", ObjectHandle, (ULONG_PTR)PrevProcId & ~0x1, PsGetCurrentProcessId()); } else { @@ -1373,7 +1368,7 @@ GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo) { PGDI_TABLE_ENTRY FromEntry; PETHREAD Thread; - LONG FromProcessId, FromLockedProcessId, FromPrevProcId; + HANDLE FromProcessId, FromLockedProcessId, FromPrevProcId; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif @@ -1386,12 +1381,12 @@ GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo) { FromEntry = GDI_HANDLE_GET_ENTRY(HandleTable, CopyFrom); - FromProcessId = FromEntry->ProcessId & ~0x1; - FromLockedProcessId = FromProcessId | 0x1; + FromProcessId = (HANDLE)((ULONG_PTR)FromEntry->ProcessId & ~0x1); + FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1); LockHandleFrom: /* lock the object, we must not convert stock objects, so don't check!!! */ - FromPrevProcId = InterlockedCompareExchange(&FromEntry->ProcessId, FromProcessId, FromLockedProcessId); + FromPrevProcId = InterlockedCompareExchangePointer(&FromEntry->ProcessId, FromProcessId, FromLockedProcessId); if(FromPrevProcId == FromProcessId) { PETHREAD PrevThread; @@ -1408,11 +1403,11 @@ LockHandleFrom: { /* now let's change the ownership of the target object */ - if((FromPrevProcId & ~0x1) != 0) + if(((ULONG_PTR)FromPrevProcId & ~0x1) != 0) { PEPROCESS ProcessTo; /* FIXME */ - if(NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(FromPrevProcId >> 1), &ProcessTo))) + if(NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1), &ProcessTo))) { GDIOBJ_SetOwnership(CopyTo, ProcessTo); ObDereferenceObject(ProcessTo); @@ -1424,7 +1419,7 @@ LockHandleFrom: GDIOBJ_SetOwnership(CopyTo, NULL); } - InterlockedExchange(&FromEntry->ProcessId, FromPrevProcId); + InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId); } else { @@ -1443,7 +1438,7 @@ LockHandleFrom: being deleted in the meantime (because we don't have aquired a reference at this point). FIXME - we should give up after some time unless we want to wait forever! */ - InterlockedExchange(&FromEntry->ProcessId, FromPrevProcId); + InterlockedExchangePointer(&FromEntry->ProcessId, FromPrevProcId); DelayExecution(); goto LockHandleFrom; @@ -1468,12 +1463,12 @@ LockHandleFrom: /* try again */ goto LockHandleFrom; } - else if((FromPrevProcId >> 1) != (LONG)PsGetCurrentProcessId()) + else if((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1) != PsGetCurrentProcessId()) { /* FIXME - should we really allow copying ownership from objects that we don't even own? */ - DPRINT1("WARNING! Changing copying ownership of object 0x%x (pid: 0x%x) to pid 0x%x!!!\n", CopyFrom, FromPrevProcId >> 1, PsGetCurrentProcessId()); - FromProcessId = FromPrevProcId & ~0x1; - FromLockedProcessId = FromProcessId | 0x1; + DPRINT1("WARNING! Changing copying ownership of object 0x%x (pid: 0x%x) to pid 0x%x!!!\n", CopyFrom, (ULONG_PTR)FromPrevProcId & ~0x1, PsGetCurrentProcessId()); + FromProcessId = (HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1); + FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1); goto LockHandleFrom; } else diff --git a/reactos/subsys/win32k/objects/line.c b/reactos/subsys/win32k/objects/line.c index 05b71b734ff..866e04ff0cb 100644 --- a/reactos/subsys/win32k/objects/line.c +++ b/reactos/subsys/win32k/objects/line.c @@ -110,7 +110,7 @@ IntGdiLineTo(DC *dc, Points[0].x, Points[0].y, Points[1].x, Points[1].y, &Bounds, - dc->w.ROPmode); + ROP2_TO_MIX(dc->w.ROPmode)); } BITMAPOBJ_UnlockBitmap ( dc->w.hBitmap ); @@ -228,7 +228,7 @@ IntGdiPolyline(DC *dc, IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen); Ret = IntEngPolyline(BitmapObj, dc->CombinedClip, &PenBrushInst.BrushObject, Points, Count, - dc->w.ROPmode); + ROP2_TO_MIX(dc->w.ROPmode)); BITMAPOBJ_UnlockBitmap(dc->w.hBitmap); EngFreeMem(Points); diff --git a/reactos/subsys/win32k/objects/print.c b/reactos/subsys/win32k/objects/print.c index ded76b90b20..29dd8beca4c 100644 --- a/reactos/subsys/win32k/objects/print.c +++ b/reactos/subsys/win32k/objects/print.c @@ -93,7 +93,7 @@ IntEngExtEscape( if (Escape == 0x1101) return 0; - UNIMPLEMENTED; + DPRINT1("IntEngExtEscape is nimplemented. - Keep going and have a nice day\n"); return -1; } diff --git a/reactos/subsys/win32k/objects/text.c b/reactos/subsys/win32k/objects/text.c index d3977d7b2be..02f7c13cb45 100644 --- a/reactos/subsys/win32k/objects/text.c +++ b/reactos/subsys/win32k/objects/text.c @@ -1493,7 +1493,7 @@ NtGdiExtTextOut( LONGLONG TextLeft, RealXStart; ULONG TextTop, pitch, previous, BackgroundLeft; FT_Bool use_kerning; - RECTL DestRect, MaskRect; + RECTL DestRect, MaskRect, SpecifiedDestRect; POINTL SourcePoint, BrushOrigin; HBRUSH hBrushFg = NULL; PGDIBRUSHOBJ BrushFg = NULL; @@ -1517,6 +1517,20 @@ NtGdiExtTextOut( NTSTATUS Status; INT *Dx = NULL; POINT Start; + BOOL DoBreak = FALSE; + + // TODO: Write test-cases to exactly match real Windows in different + // bad parameters (e.g. does Windows check the DC or the RECT first?). + if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) + { + // At least one of the two flags were specified. Copy lprc. Once. + Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT)); + if (!NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + } dc = DC_LockDc(hDC); if (!dc) @@ -1607,11 +1621,10 @@ NtGdiExtTextOut( if ((fuOptions & ETO_OPAQUE) && lprc) { - MmCopyFromCaller(&DestRect, lprc, sizeof(RECT)); - DestRect.left += dc->w.DCOrgX; - DestRect.top += dc->w.DCOrgY; - DestRect.right += dc->w.DCOrgX; - DestRect.bottom += dc->w.DCOrgY; + DestRect.left = SpecifiedDestRect.left + dc->w.DCOrgX; + DestRect.top = SpecifiedDestRect.top + dc->w.DCOrgY; + DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX; + DestRect.bottom = SpecifiedDestRect.bottom + dc->w.DCOrgY; IntEngBitBlt( BitmapObj, NULL, @@ -1623,7 +1636,7 @@ NtGdiExtTextOut( &SourcePoint, &BrushBgInst.BrushObject, &BrushOrigin, - PATCOPY); + ROP3_TO_ROP4(PATCOPY)); fuOptions &= ~ETO_OPAQUE; } else @@ -1841,7 +1854,7 @@ NtGdiExtTextOut( &SourcePoint, &BrushBgInst.BrushObject, &BrushOrigin, - PATCOPY); + ROP3_TO_ROP4(PATCOPY)); BackgroundLeft = DestRect.right; } @@ -1880,6 +1893,17 @@ NtGdiExtTextOut( * brush. */ + if (lprc && + (fuOptions & ETO_CLIPPED) && + DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX) + { + // We do the check '>=' instead of '>' to possibly save an iteration + // through this loop, since it's breaking after the drawing is done, + // and x is always incremented. + DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX; + DoBreak = TRUE; + } + IntEngMaskBlt( SurfObj, SourceGlyphSurf, @@ -1895,6 +1919,11 @@ NtGdiExtTextOut( EngUnlockSurface(SourceGlyphSurf); EngDeleteSurface((HSURF)HSourceGlyph); + if (DoBreak) + { + break; + } + if (NULL == Dx) { TextLeft += glyph->advance.x; @@ -2661,7 +2690,7 @@ BOOL STDCALL NtGdiRemoveFontResource(LPCWSTR FileName) { - UNIMPLEMENTED; + DPRINT1("NtGdiRemoveFontResource is UNIMPLEMENTED\n"); return FALSE; } diff --git a/reactos/subsys/win32k/stubs/stubs.c b/reactos/subsys/win32k/stubs/stubs.c index 0106c62a764..70385edf8f3 100644 --- a/reactos/subsys/win32k/stubs/stubs.c +++ b/reactos/subsys/win32k/stubs/stubs.c @@ -126,22 +126,6 @@ EngComputeGlyphSet( return NULL; } -/* - * @unimplemented - */ -HDRVOBJ -STDCALL -EngCreateDriverObj( - PVOID pvObj, - FREEOBJPROC pFreeObjProc, - HDEV hdev - ) -{ - // www.osr.com/ddk/graphics/gdifncs_8svb.htm - UNIMPLEMENTED; - return NULL; -} - /* * @unimplemented */ @@ -154,40 +138,6 @@ EngCreatePath ( VOID ) return NULL; } -/* - * @unimplemented - */ -WNDOBJ* -STDCALL -EngCreateWnd( - SURFOBJ *pso, - HWND hwnd, - WNDOBJCHANGEPROC pfn, - FLONG fl, - int iPixelFormat - ) -{ - // www.osr.com/ddk/graphics/gdifncs_2ip3.htm - UNIMPLEMENTED; - return NULL; -} - -/* - * @unimplemented - */ -BOOL -STDCALL -EngDeleteDriverObj( - IN HDRVOBJ hdo, - IN BOOL bCallBack, - IN BOOL bLocked - ) -{ - // www.osr.com/ddk/graphics/gdifncs_0qlj.htm - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ @@ -199,17 +149,6 @@ EngDeletePath ( IN PATHOBJ *ppo ) UNIMPLEMENTED; } -/* - * @unimplemented - */ -VOID -STDCALL -EngDeleteWnd ( IN WNDOBJ *pwo ) -{ - // www.osr.com/ddk/graphics/gdifncs_2z3b.htm - UNIMPLEMENTED; -} - /* * @unimplemented */ @@ -422,18 +361,6 @@ EngLoadModuleForWrite( return NULL; } -/* - * @unimplemented - */ -DRIVEROBJ* -STDCALL -EngLockDriverObj ( IN HDRVOBJ hdo ) -{ - // www.osr.com/ddk/graphics/gdifncs_41if.htm - UNIMPLEMENTED; - return NULL; -} - /* * @unimplemented */ @@ -575,15 +502,6 @@ EngUnloadImage ( IN HANDLE hModule ) UNIMPLEMENTED; } -BOOL -STDCALL -EngUnlockDriverObj ( IN HDRVOBJ hdo ) -{ - // www.osr.com/ddk/graphics/gdifncs_0l5z.htm - UNIMPLEMENTED; - return FALSE; -} - INT STDCALL EngWideCharToMultiByte( @@ -1108,44 +1026,6 @@ STROBJ_vEnumStart ( IN STROBJ *pstro ) UNIMPLEMENTED; } -BOOL -STDCALL -WNDOBJ_bEnum( - IN WNDOBJ *pwo, - IN ULONG cj, - OUT ULONG *pul - ) -{ - // www.osr.com/ddk/graphics/gdifncs_3jqf.htm - UNIMPLEMENTED; - return FALSE; -} - -ULONG -STDCALL -WNDOBJ_cEnumStart( - IN WNDOBJ *pwo, - IN ULONG iType, - IN ULONG iDirection, - IN ULONG cLimit - ) -{ - // www.osr.com/ddk/graphics/gdifncs_18o7.htm - UNIMPLEMENTED; - return 0; -} - -VOID -STDCALL -WNDOBJ_vSetConsumer( - IN WNDOBJ *pwo, - IN PVOID pvConsumer - ) -{ - // www.osr.com/ddk/graphics/gdifncs_484n.htm - UNIMPLEMENTED; -} - BOOL STDCALL XFORMOBJ_bApplyXform( @@ -1267,6 +1147,19 @@ BRUSHOBJ_hGetColorTransform( return NULL; } +/* + * @unimplemented + */ +PVOID STDCALL +EngAllocPrivateUserMem( + IN PDD_SURFACE_LOCAL psl, + IN SIZE_T cj, + IN ULONG tag) +{ + UNIMPLEMENTED; + return NULL; +} + /* * @unimplemented */ @@ -1292,8 +1185,9 @@ EngDeleteFile( * @unimplemented */ VOID STDCALL -EngDeleteSafeSemaphore( - IN OUT ENGSAFESEMAPHORE *Semaphore) +EngFreePrivateUserMem( + IN PDD_SURFACE_LOCAL psl, + IN PVOID pv) { UNIMPLEMENTED; } @@ -1326,17 +1220,6 @@ EngHangNotification( return EHN_ERROR; } -/* - * @unimplemented - */ -BOOL STDCALL -EngInitializeSafeSemaphore( - OUT ENGSAFESEMAPHORE *Semaphore) -{ - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ diff --git a/reactos/subsys/win32k/win32k.def b/reactos/subsys/win32k/win32k.def index 69bddd031d2..684c2ecff30 100644 --- a/reactos/subsys/win32k/win32k.def +++ b/reactos/subsys/win32k/win32k.def @@ -15,6 +15,7 @@ CLIPOBJ_ppoGetPath@4 EngAlphaBlend@28 EngAcquireSemaphore@4 EngAllocMem@12 +EngAllocPrivateUserMem@12 EngAllocUserMem@8 EngAssociateSurface@12 EngBitBlt@44 @@ -39,6 +40,7 @@ EngDeleteDriverObj@12 EngDeleteEvent@4 EngDeletePalette@4 EngDeletePath@4 +EngDeleteSafeSemaphore@4 EngDeleteSemaphore@4 EngDeleteSurface@4 EngDeleteWnd@4 @@ -51,6 +53,7 @@ EngFindImageProcAddress@8 EngFindResource@16 EngFreeMem@4 EngFreeModule@4 +EngFreePrivateUserMem@8 EngFreeUserMem@4 EngGetCurrentCodePage@8=ntoskrnl.RtlGetCurrentCodePage EngGetCurrentProcessId@0 @@ -66,6 +69,7 @@ EngGetPrinterDataFileName@4 EngGetProcessHandle@0 EngGetType1FontList@24 EngGradientFill@40 +EngInitializeSafeSemaphore@4 EngLineTo@36 EngLoadImage@4 EngLoadModule@4 diff --git a/reactos/subsys/win32k/win32k.xml b/reactos/subsys/win32k/win32k.xml index caaa62e9ea5..3a8a6a1c6bd 100644 --- a/reactos/subsys/win32k/win32k.xml +++ b/reactos/subsys/win32k/win32k.xml @@ -30,6 +30,7 @@ copybits.c debug.c device.c + driverobj.c error.c event.c float.c @@ -45,6 +46,7 @@ sort.c surface.c transblt.c + window.c xlate.c diff --git a/reactos/tools/Makefile b/reactos/tools/Makefile index 438e3b60ebd..956cb1ee1d4 100644 --- a/reactos/tools/Makefile +++ b/reactos/tools/Makefile @@ -9,7 +9,7 @@ RMKDIR_SOURCES = \ RMKDIR_OBJECTS = \ $(RMKDIR_SOURCES:.c=.o) -RMKDIR_HOST_CXXFLAGS = -g -Werror -Wall +RMKDIR_HOST_CFLAGS = -g -Werror -Wall RMKDIR_HOST_LFLAGS = -g @@ -17,12 +17,7 @@ $(RMKDIR_TARGET): $(RMKDIR_OBJECTS) ${host_gcc} $(RMKDIR_OBJECTS) $(RMKDIR_HOST_LFLAGS) -o $(RMKDIR_TARGET) $(RMKDIR_OBJECTS): %.o : %.c - ${host_gcc} $(RMKDIR_HOST_CXXFLAGS) -c $< -o $@ - -.PHONY: rmkdir - -rmkdir: $(RMKDIR_TARGET) - - + ${host_gcc} $(RMKDIR_HOST_CFLAGS) -c $< -o $@ @@ -37,7 +32,7 @@ BUILDNO_SOURCES = \ BUILDNO_OBJECTS = \ $(BUILDNO_SOURCES:.c=.o) -BUILDNO_HOST_CXXFLAGS = -g -Werror -Wall +BUILDNO_HOST_CFLAGS = -g -Werror -Wall BUILDNO_HOST_LFLAGS = -g @@ -45,13 +40,11 @@ $(BUILDNO_TARGET): $(BUILDNO_OBJECTS) ${host_gcc} $(BUILDNO_OBJECTS) $(BUILDNO_HOST_LFLAGS) -o $(BUILDNO_TARGET) $(BUILDNO_OBJECTS): %.o : %.c - ${host_gcc} $(BUILDNO_HOST_CXXFLAGS) -c $< -o $@ + ${host_gcc} $(BUILDNO_HOST_CFLAGS) -c $< -o $@ include$(SEP)reactos$(SEP)buildno.h: $(BUILDNO_TARGET) $(EXEPREFIX)$(BUILDNO_TARGET) include$(SEP)reactos$(SEP)buildno.h -.PHONY: buildno - -buildno: $(BUILDNO_TARGET) - +include tools/nci/makefile +include tools/rbuild/makefile include tools/wmc/makefile diff --git a/reactos/tools/cabman/cabinet.cxx b/reactos/tools/cabman/cabinet.cxx index 827555ca2c8..ef350631327 100755 --- a/reactos/tools/cabman/cabinet.cxx +++ b/reactos/tools/cabman/cabinet.cxx @@ -188,7 +188,7 @@ unsigned long CCFDATAStorage::Truncate() return CAB_STATUS_FAILURE; #else /* !WIN32 */ fclose(FileHandle); - FileHandle = fopen(FullName, "w+b"); + FileHandle = tmpfile(); if (FileHandle == NULL) { DPRINT(MID_TRACE, ("ERROR '%d'.\n", (unsigned int)errno)); return CAB_STATUS_FAILURE; @@ -532,6 +532,7 @@ bool CCabinet::SetCabinetReservedFile(char* FileName) return false; } #else /* !WIN32 */ + FileHandle = fopen(ConvertPath(FileName, true), "rb"); if (FileHandle == NULL) { DPRINT(MID_TRACE, ("Cannot open cabinet reserved file.\n")); diff --git a/reactos/tools/cabman/dfp.cxx b/reactos/tools/cabman/dfp.cxx index dfb33a0ebc2..a7ca2d81147 100755 --- a/reactos/tools/cabman/dfp.cxx +++ b/reactos/tools/cabman/dfp.cxx @@ -1089,7 +1089,7 @@ void CDFParser::SkipSpaces() } -bool CDFParser::IsNextToken(TOKEN Token, bool NoSpaces) +bool CDFParser::IsNextToken(DFP_TOKEN Token, bool NoSpaces) /* * FUNCTION: Checks if next token equals Token * ARGUMENTS: diff --git a/reactos/tools/cabman/dfp.h b/reactos/tools/cabman/dfp.h index 8a127bcc199..8bd70d93335 100755 --- a/reactos/tools/cabman/dfp.h +++ b/reactos/tools/cabman/dfp.h @@ -32,7 +32,7 @@ typedef enum { TokenPeriod, TokenBackslash, TokenEnd, -} TOKEN; +} DFP_TOKEN; typedef enum { @@ -86,7 +86,7 @@ private: unsigned long PerformCommand(); unsigned long PerformFileCopy(); void SkipSpaces(); - bool IsNextToken(TOKEN Token, bool NoSpaces); + bool IsNextToken(DFP_TOKEN Token, bool NoSpaces); bool ReadLine(); void NextToken(); /* Parsing */ @@ -100,7 +100,7 @@ private: unsigned long CurrentLine; unsigned long CurrentChar; /* Token */ - TOKEN CurrentToken; + DFP_TOKEN CurrentToken; unsigned long CurrentInteger; char CurrentString[256]; diff --git a/reactos/tools/config.mk b/reactos/tools/config.mk index f95ae01664f..26ecb208a68 100644 --- a/reactos/tools/config.mk +++ b/reactos/tools/config.mk @@ -15,10 +15,8 @@ ifeq ($(KDBG), 1) CONFIG += KDBG endif -ifeq ($(MP), 1) -CONFIG += MP -else -CONFIG += UP +ifeq ($(CONFIG_SMP), 1) +CONFIG += CONFIG_SMP endif ifeq ($(ACPI), 1) diff --git a/reactos/tools/helper.mk b/reactos/tools/helper.mk index 1021d413617..da8365b05dd 100644 --- a/reactos/tools/helper.mk +++ b/reactos/tools/helper.mk @@ -51,6 +51,7 @@ # $TARGET_BOOTSTRAP = Whether this file is needed to bootstrap the installation (no,yes) (optional) # $TARGET_BOOTSTRAP_NAME = Name on the installation medium (optional) # $TARGET_REGTESTS = This module has regression tests (no,yes) (optional) +# $TARGET_WINETESTS = This module Wine regression tests (no,yes) (optional) # $TARGET_INSTALL = Install the file (no,yes) (optional) # $SUBDIRS = Subdirs in which to run make (optional) @@ -611,6 +612,15 @@ ifneq ($(TARGET_TYPE),kernel) endif endif +# +# Enable Tree-Wide Optimization. +# Protect uncompatible files here with an ifneq +# if needed, until their problems can be found +# +ifeq ($(OPTIMIZED), 1) + MK_CFLAGS += -O2 -Wno-strict-aliasing + MK_CPPFLAGS += -O2 -Wno-strict-aliasing +endif ifneq ($(TARGET_LIBS),) MK_LIBS := $(TARGET_LIBS) $(MK_LIBS) @@ -632,22 +642,17 @@ endif include $(PATH_TO_TOP)/config -TARGET_CFLAGS += $(MK_CFLAGS) $(STD_CFLAGS) -ifeq ($(DBG),1) -TARGET_ASFLAGS += -g -TARGET_CFLAGS += -g -TARGET_LFLAGS += -g -endif +TARGET_CFLAGS += $(MK_CFLAGS) $(STD_CFLAGS) -g -TARGET_CPPFLAGS += $(MK_CPPFLAGS) $(STD_CPPFLAGS) +TARGET_CPPFLAGS += $(MK_CPPFLAGS) $(STD_CPPFLAGS) -g TARGET_RCFLAGS += $(MK_RCFLAGS) $(STD_RCFLAGS) -TARGET_ASFLAGS += $(MK_ASFLAGS) $(STD_ASFLAGS) +TARGET_ASFLAGS += $(MK_ASFLAGS) $(STD_ASFLAGS) -g TARGET_NFLAGS += $(MK_NFLAGS) $(STD_NFLAGS) -TARGET_LFLAGS += $(MK_LFLAGS) $(STD_LFLAGS) +TARGET_LFLAGS += $(MK_LFLAGS) $(STD_LFLAGS) -g MK_GCCLIBS := $(addprefix -l, $(TARGET_GCCLIBS)) @@ -692,6 +697,12 @@ else MK_REGTESTS_CLEAN := endif +ifeq ($(TARGET_WINETESTS),yes) +all: + - $(MAKE) -C winetests + MK_REGTESTS_CLEAN := clean_winetests +endif + ifeq ($(TARGET_INSTALL),) MK_INSTALL := yes else @@ -709,7 +720,7 @@ ifeq ($(MK_IMPLIBONLY),yes) TARGET_CLEAN += $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME) -all: $(REGTEST_TARGETS) $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME) +all: $(WINETEST_TARGETS) $(REGTEST_TARGETS) $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME) $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME): $(MK_OBJECTS) $(MK_DEFNAME) $(HALFVERBOSEECHO) [DLLTOOL] $(MK_IMPLIB_FULLNAME) @@ -776,10 +787,6 @@ endif -o $(MK_NOSTRIPNAME) \ $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) - $(RM) temp.exp -ifeq ($(BUILD_SYM),yes) - $(HALFVERBOSEECHO) [RSYM] $(MK_BASENAME).sym - - $(RSYM) $(MK_NOSTRIPNAME) $(MK_BASENAME).sym -endif ifeq ($(BUILD_MAP),full) $(HALFVERBOSEECHO) [OBJDUMP] $(MK_BASENAME).map $(OBJDUMP) -d -S $(MK_NOSTRIPNAME) > $(MK_BASENAME).map @@ -791,47 +798,8 @@ endif endif $(MK_FULLNAME): $(MK_NOSTRIPNAME) $(MK_EXTRADEP) - $(HALFVERBOSEECHO) [LD] $(MK_FULLNAME) - - -ifneq ($(TARGET_CPPAPP),yes) - $(LD) --strip-debug -r -o $(MK_STRIPPED_OBJECT) $(MK_OBJECTS) -endif -ifeq ($(MK_EXETYPE),dll) - $(LD_CC) -Wl,--base-file,base.tmp \ - -Wl,--entry,$(TARGET_ENTRY) \ - -Wl,--strip-debug \ - $(TARGET_LFLAGS) \ - -o junk.tmp \ - $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) - - $(RM) junk.tmp - $(DLLTOOL) --dllname $(MK_FULLNAME) \ - --base-file base.tmp \ - --output-exp temp.exp $(MK_EXTRACMD) - - $(RM) base.tmp - $(LD_CC) -Wl,--base-file,base.tmp \ - -Wl,--entry,$(TARGET_ENTRY) \ - -Wl,--strip-debug \ - $(TARGET_LFLAGS) \ - temp.exp \ - -o junk.tmp \ - $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) - - $(RM) junk.tmp - $(DLLTOOL) --dllname $(MK_FULLNAME) \ - --base-file base.tmp \ - --output-exp temp.exp $(MK_KILLAT) $(MK_EXTRACMD) - - $(RM) base.tmp -endif - $(LD_CC) $(TARGET_LFLAGS) \ - -Wl,--entry,$(TARGET_ENTRY) \ - -Wl,--strip-debug \ - $(MK_EXTRACMD2) \ - -o $(MK_FULLNAME) \ - $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) -ifneq ($(TARGET_CPPAPP),yes) - - $(RM) temp.exp $(MK_STRIPPED_OBJECT) -else - - $(RM) temp.exp -endif + $(HALFVERBOSEECHO) [RSYM] $(MK_FULLNAME) + $(RSYM) $(MK_NOSTRIPNAME) $(MK_FULLNAME) @echo $(MK_FULLNAME) was successfully built. endif # KM_MODE @@ -871,10 +839,6 @@ $(MK_NOSTRIPNAME): $(MK_EXTRADEP) $(MK_FULLRES) $(MK_BASENAME).a $(MK_LIBS) -o $(MK_NOSTRIPNAME) \ $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) - $(RM) temp.exp -ifeq ($(BUILD_SYM),yes) - $(HALFVERBOSEECHO) [RSYM] $(MK_BASENAME).sym - $(RSYM) $(MK_NOSTRIPNAME) $(MK_BASENAME).sym -endif ifeq ($(BUILD_MAP),full) $(HALFVERBOSEECHO) [OBJDUMP] $(MK_BASENAME).map $(OBJDUMP) -d -S $(MK_NOSTRIPNAME) > $(MK_BASENAME).map @@ -885,36 +849,9 @@ ifeq ($(BUILD_MAP),yes) endif endif -$(MK_FULLNAME): $(MK_EXTRADEP) $(MK_FULLRES) $(MK_BASENAME).a $(MK_LIBS) $(MK_NOSTRIPNAME) - - - $(HALFVERBOSEECHO) [LD] $(MK_FULLNAME) -ifneq ($(TARGET_CPPAPP),yes) - $(LD) --strip-debug -r -o $(MK_STRIPPED_OBJECT) $(MK_OBJECTS) -endif - $(LD_CC) -Wl,--base-file,base.tmp \ - -Wl,--entry,$(TARGET_ENTRY) \ - $(TARGET_LFLAGS) \ - -o junk.tmp \ - $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) - - $(RM) junk.tmp - $(DLLTOOL) --dllname $(MK_FULLNAME) \ - --base-file base.tmp \ - --output-exp temp.exp $(MK_EXTRACMD) $(MK_KILLAT) - - $(RM) base.tmp - $(LD_CC) $(TARGET_LFLAGS) \ - -Wl,--subsystem,native \ - -Wl,--image-base,$(TARGET_BASE) \ - -Wl,--file-alignment,0x1000 \ - -Wl,--section-alignment,0x1000 \ - -Wl,--entry,$(TARGET_ENTRY) \ - -Wl,temp.exp -mdll \ - -o $(MK_FULLNAME) \ - $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) -ifneq ($(TARGET_CPPAPP),yes) - - $(RM) temp.exp $(MK_STRIPPED_OBJECT) -else - - $(RM) temp.exp -endif +$(MK_FULLNAME): $(MK_NOSTRIPNAME) + $(HALFVERBOSEECHO) [RSYM] $(MK_FULLNAME) + $(RSYM) $(MK_NOSTRIPNAME) $(MK_FULLNAME) @echo $(MK_FULLNAME) was successfully built. endif # MK_MODE @@ -963,31 +900,36 @@ endif # Precompiled header support # When using PCHs, use dependency tracking to keep the .gch files up-to-date. +# When TARGET_PCH is defined, we always want to clean the .gch file, even if +# ROS_USE_PCH is not active. This prevents problems when switching between +# PCH and non-PCH builds. -MK_PCHNAME = -ifeq ($(ROS_USE_PCH),yes) ifneq ($(TARGET_PCH),) +MK_PCHCLEAN = $(TARGET_PCH).gch +ifeq ($(ROS_USE_PCH),yes) MK_PCHNAME = $(TARGET_PCH).gch - ifeq ($(TARGET_CPPAPP),yes) PCH_CC := $(CXX) -else +else # TARGET_CPPAPP PCH_CC := $(CC) -endif - - -endif # TARGET_PCH -else # +endif # TARGET_CPPAPP +else # ROS_USE_PCH MK_PCHNAME = endif # ROS_USE_PCH +else # TARGET_PCH +MK_PCHCLEAN = +MK_PCHNAME = +endif # TARGET_PCH # Be carefull not to clean non-object files MK_CLEANFILES := $(filter %.o,$(MK_OBJECTS)) MK_CLEANFILTERED := $(MK_OBJECTS:.o=.d) $(TARGET_PCH:.h=.d) MK_CLEANDEPS := $(join $(dir $(MK_CLEANFILTERED)), $(addprefix ., $(notdir $(MK_CLEANFILTERED)))) +# FIXME: The $(MK_BASENAME).sym can be removed around 15 Feb 2005 clean: $(MK_REGTESTS_CLEAN) $(SUBDIRS:%=%_clean) - - $(RM) *.o $(MK_PCHNAME) $(MK_BASENAME).sym $(MK_BASENAME).a $(MK_RESOURCE) \ + $(HALFVERBOSEECHO) [CLEAN] + - $(RM) *.o $(MK_PCHCLEAN) $(MK_BASENAME).sym $(MK_BASENAME).a $(MK_RESOURCE) \ $(MK_FULLNAME) $(MK_NOSTRIPNAME) $(MK_CLEANFILES) $(MK_CLEANDEPS) $(MK_BASENAME).map \ junk.tmp base.tmp temp.exp $(MK_RC_BINARIES) $(MK_SPECDEF) $(MK_STUBS_SRC) \ $(MK_GENERATED_MAKEFILE) $(TARGET_CLEAN) @@ -1032,24 +974,10 @@ install: endif # MK_INSTALL -ifeq ($(INSTALL_SYMBOLS),yes) - -forceinstall: $(SUBDIRS:%=%_install) $(MK_FULLNAME) $(MK_BASENAME).sym - $(HALFVERBOSEECHO) [INSTALL] $(MK_FULLNAME) to $(MK_INSTALLDIR)/$(MK_INSTALL_FULLNAME) - $(HALFVERBOSEECHO) [INSTALL] $(MK_BASENAME).sym to symbols/$(MK_INSTALL_BASENAME).sym - -$(CP) $(MK_FULLNAME) $(INSTALL_DIR)/$(MK_INSTALLDIR)/$(MK_INSTALL_FULLNAME) - -$(CP) $(MK_BASENAME).sym $(INSTALL_DIR)/symbols/$(MK_INSTALL_BASENAME).sym - @echo $(MK_FULLNAME) was successfully installed. - -else # INSTALL_SYMBOLS - forceinstall: $(SUBDIRS:%=%_install) $(MK_FULLNAME) $(HALFVERBOSEECHO) [INSTALL] $(MK_FULLNAME) to $(MK_INSTALLDIR)/$(MK_INSTALL_FULLNAME) -$(CP) $(MK_FULLNAME) $(INSTALL_DIR)/$(MK_INSTALLDIR)/$(MK_INSTALL_FULLNAME) -endif # INSTALL_SYMBOLS - - # Bootstrap files for the bootable CD ifeq ($(TARGET_BOOTSTRAP),yes) @@ -1092,7 +1020,10 @@ clean_regtests: - $(MAKE) -C tests TARGET_REGTESTS=no clean - $(RM) ./tests/_rtstub.c ./tests/_hooks.c ./tests/_regtests.c ./tests/_stubs.S ./tests/Makefile.tests -.PHONY: all depends implib clean install dist bootcd depends gen_regtests clean_regtests +clean_winetests: + - $(MAKE) -C winetests clean + +.PHONY: all depends implib clean install dist bootcd depends gen_regtests clean_regtests clean_winetests ifneq ($(SUBDIRS),) $(SUBDIRS:%=%_all): %_all: diff --git a/reactos/tools/mkconfig.c b/reactos/tools/mkconfig.c index 3d8cf14dd8c..3ab1631c6c0 100644 --- a/reactos/tools/mkconfig.c +++ b/reactos/tools/mkconfig.c @@ -106,12 +106,6 @@ main(int argc, char* argv[]) { include_tests = 1; } - if (strcmp(argv[i], "MP") == 0 || strcmp(argv[i], "UP") == 0) - { - s = s + sprintf(s, "#if ! defined(MP) && ! defined(UP)\n"); - s = s + sprintf(s, "#define %s\n", argv[i]); - s = s + sprintf(s, "#endif /* ! defined(MP) && ! defined(UP) */\n"); - } else { s = s + sprintf(s, "#define %s\n", argv[i]); diff --git a/reactos/tools/nci/makefile b/reactos/tools/nci/makefile new file mode 100644 index 00000000000..9f0123fc7ca --- /dev/null +++ b/reactos/tools/nci/makefile @@ -0,0 +1,51 @@ +NCI_BASE = tools$(SEP)nci + +NCI_TARGET = \ + $(ROS_INTERMEDIATE)$(NCI_BASE)$(SEP)nci$(EXEPOSTFIX) + +NCI_SOURCES = \ + $(NCI_BASE)$(SEP)ncitool.c + +NCI_OBJECTS = \ + $(NCI_SOURCES:.c=.o) + +NCI_HOST_CFLAGS = -Iinclude -g -Werror -Wall + +NCI_HOST_LFLAGS = -g + +$(NCI_TARGET): $(NCI_OBJECTS) + ${host_gcc} $(NCI_OBJECTS) $(NCI_HOST_CFLAGS) -o $(NCI_TARGET) + +$(NCI_OBJECTS): %.o : %.c + ${host_gcc} $(NCI_HOST_CFLAGS) -c $< -o $@ + +# WIN32K.SYS +WIN32K_SVC_DB = $(NCI_BASE)$(SEP)w32ksvc.db +WIN32K_SERVICE_TABLE = subsys$(SEP)win32k$(SEP)main$(SEP)svctab.c +WIN32K_GDI_STUBS = lib$(SEP)gdi32$(SEP)misc$(SEP)win32k.S +WIN32K_USER_STUBS = lib$(SEP)user32$(SEP)misc$(SEP)win32k.S + +# NTOSKRNL.EXE +KERNEL_SVC_DB = $(NCI_BASE)$(SEP)sysfuncs.lst +KERNEL_SERVICE_TABLE = include$(SEP)ntdll$(SEP)napi.h +NTDLL_STUBS = lib$(SEP)ntdll$(SEP)napi.S +KERNEL_STUBS = ntoskrnl$(SEP)ex$(SEP)zw.S + +NCI_SERVICE_FILES = \ + $(KERNEL_SERVICE_TABLE) \ + $(WIN32K_SERVICE_TABLE) \ + $(NTDLL_STUBS) \ + $(KERNEL_STUBS) \ + $(WIN32K_GDI_STUBS) \ + $(WIN32K_USER_STUBS) + +$(NCI_SERVICE_FILES): $(NCI_TARGET) + @$(EXEPREFIX)$(NCI_TARGET) \ + $(KERNEL_SVC_DB) \ + $(WIN32K_SVC_DB) \ + $(KERNEL_SERVICE_TABLE) \ + $(WIN32K_SERVICE_TABLE) \ + $(NTDLL_STUBS) \ + $(KERNEL_STUBS) \ + $(WIN32K_GDI_STUBS) \ + $(WIN32K_USER_STUBS) diff --git a/reactos/tools/nci/ncitool.c b/reactos/tools/nci/ncitool.c new file mode 100644 index 00000000000..5b2b99ca5ed --- /dev/null +++ b/reactos/tools/nci/ncitool.c @@ -0,0 +1,581 @@ +/* + * FILE: tools/nci/ncitool.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Native Call Interface Support Tool + * PURPOSE: Generates NCI Tables and Stubs. + * PROGRAMMER; Alex Ionescu (alex@relsoft.net) + * CHANGE HISTORY: 14/01/05 - Created. Based on original code by + * KJK::Hyperion and Emanuelle Aliberti. + * + */ + +/* INCLUDE ******************************************************************/ + +#include +#include +#include +#include + +/* DEFINES ****************************************************************/ + +#define INPUT_BUFFER_SIZE 255 +#define Arguments 8 + +/******* Table Indexes ************/ +#define MAIN_INDEX 0x0 +#define WIN32K_INDEX 0x1000 + +/******* Argument List ************/ +/* First, define the Databases */ +#define NativeSystemDb 0 +#define NativeGuiDb 1 + +/* Now the Service Tables */ +#define NtosServiceTable 2 +#define Win32kServiceTable 3 + +/* And finally, the stub files. */ +#define NtosUserStubs 4 +#define NtosKernelStubs 5 +#define Win32kGdiStubs 6 +#define Win32kUserStubs 7 + +/********** Stub Code ************/ + +/* + * This stubs calls into KUSER_SHARED_DATA where either a + * sysenter or interrupt is performed, depending on CPU support. + */ +#if defined(__GNUC__) +#define UserModeStub_x86 " movl $0x%x, %%eax\n" \ + " movl $KUSER_SHARED_SYSCALL, %%ecx\n" \ + " call *%%ecx\n" \ + " ret $0x%x\n\n" +#elif defined(_MSC_VER) +#define UserModeStub_x86 " asm { \n" \ + " mov eax, %xh\n" \ + " mov ecx, KUSER_SHARED_SYSCALL\n" \ + " call [ecx]\n" \ + " ret %xh\n" \ + " }\n" +#else +#error Unknown compiler for inline assembler +#endif + +/* + * This stub calls KiSystemService directly with a fake INT2E stack. + * Because EIP is pushed during the call, the handler will return here. + */ +#if defined(__GNUC__) +#define KernelModeStub_x86 " movl $0x%x, %%eax\n" \ + " leal 4(%%esp), %%edx\n" \ + " pushfl\n" \ + " pushl $KERNEL_CS\n" \ + " call _KiSystemService\n" \ + " ret $0x%x\n\n" +#elif defined(_MSC_VER) +#define KernelModeStub_x86 " asm { \n" \ + " mov eax, %xh\n" \ + " lea edx, [esp+4]\n" \ + " pushf\n" \ + " push KERNEL_CS\n" \ + " call _KiSystemService\n" \ + " ret %xh\n" \ + " }\n" +#else +#error Unknown compiler for inline assembler +#endif + +/***** Arch Dependent Stuff ******/ +//#ifdef _M_IX86 +#define ARGS_TO_BYTES(x) x*4 +#define UserModeStub UserModeStub_x86 +#define KernelModeStub KernelModeStub_x86 + +//#elseif +//#error Unsupported Architecture +//#endif + +/* FUNCTIONS ****************************************************************/ + +/*++ + * WriteFileHeader + * + * Prints out the File Header for a Stub File. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * FileDescription - Description of the Stub file to which to write the header. + * + * FileLocation - Name of the Stub file to which to write the header. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for printing the header. + * + *--*/ +void +WriteFileHeader(FILE * StubFile, + char* FileDescription, + char* FileLocation) +{ + /* This prints out the file header */ + fprintf(StubFile, + "/* FILE: %s\n" + " * COPYRIGHT: See COPYING in the top level directory\n" + " * PURPOSE: %s\n" + " * PROGRAMMER: Computer Generated File. See tools/nci/ncitool.c\n" + " * REMARK: DO NOT EDIT OR COMMIT MODIFICATIONS TO THIS FILE\n" + " */\n\n\n" + "#include \n\n", + FileDescription, + FileLocation); +} + +/*++ + * WriteFileHeader + * + * Prints out the File Header for a Stub File. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * FileDescription - Description of the Stub file to which to write the header. + * + * FileLocation - Name of the Stub file to which to write the header. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for printing the header. + * + *--*/ +void +WriteStubHeader(FILE* StubFile, + char* SyscallName, + unsigned StackBytes) +{ + /* Export the function */ + fprintf(StubFile, ".global _%s@%d\n", SyscallName, StackBytes); + + /* Define it */ + fprintf(StubFile, "_%s@%d:\n\n", SyscallName, StackBytes); +} + + +/*++ + * WriteKernelModeStub + * + * Prints out the Kernel Mode Stub for a System Call. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * SyscallName - Name of System Call for which to add the stub. + * + * StackBytes - Number of bytes on the stack to return after doing the system call. + * + * SyscallId - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +WriteKernelModeStub(FILE* StubFile, + char* SyscallName, + unsigned StackBytes, + unsigned int SyscallId) +{ + /* Write the Stub Header and export the Function */ + WriteStubHeader(StubFile, SyscallName, StackBytes); + + /* Write the Stub Code */ + fprintf(StubFile, KernelModeStub, SyscallId, StackBytes); +} + +/*++ + * WriteUserModeStub + * + * Prints out the User Mode Stub for a System Call. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * SyscallName - Name of System Call for which to add the stub. + * + * StackBytes - Number of bytes on the stack to return after doing the system call. + * + * SyscallId - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +WriteUserModeStub(FILE* StubFile, + char* SyscallName, + unsigned StackBytes, + unsigned int SyscallId) +{ + /* Write the Stub Header and export the Function */ + WriteStubHeader(StubFile, SyscallName, StackBytes); + + /* Write the Stub Code */ + fprintf(StubFile, UserModeStub, SyscallId, StackBytes); +} + +/*++ + * GetNameAndArgumentsFromDb + * + * Parses an entry from a System Call Database, extracting + * the function's name and arguments that it takes. + * + * Params: + * Line - Entry from the Database to parse. + * + * NtSyscallName - Output string to which to save the Function Name + * + * SyscallArguments - Output string to which to save the number of + * arguments that the function takes. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +GetNameAndArgumentsFromDb(char Line[], + char ** NtSyscallName, + char ** SyscallArguments) +{ + char *s; + char *stmp; + + /* Remove new line */ + if ((s = (char *) strchr(Line,'\r')) != NULL) { + *s = '\0'; + } + + /* Skip comments (#) and empty lines */ + s = &Line[0]; + if ((*s) != '#' && (*s) != '\0') { + + /* Extract the NtXXX name */ + *NtSyscallName = (char *)strtok(s," \t"); + + /* Extract the argument count */ + *SyscallArguments = (char *)strtok(NULL," \t"); + + /* Remove, if present, the trailing LF */ + if ((stmp = strchr(*SyscallArguments, '\n')) != NULL) { + *stmp = '\0'; + } + + } else { + + /* Skip this entry */ + *NtSyscallName = NULL; + } +} + +/*++ + * CreateStubs + * + * Parses a System Call Database and creates stubs for all the entries. + * + * Params: + * SyscallDb - System Call Database to parse. + * + * UserModeFiles - Array of Usermode Stub Files to which to write the stubs. + * + * KernelModeFile - Kernelmode Stub Files to which to write the stubs. + * + * Index - Name of System Call for which to add the stub. + * + * UserFiles - Number of bytes on the stack to return after doing the system call. + * + * NeedsZw - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * None. + * + *--*/ +void +CreateStubs(FILE * SyscallDb, + FILE * UserModeFiles[], + FILE * KernelModeFile, + unsigned Index, + unsigned UserFiles, + unsigned NeedsZw) +{ + char Line[INPUT_BUFFER_SIZE]; + char *NtSyscallName; + char *ZwSyscallName = NULL; + char *SyscallArguments; + int SyscallId; + unsigned StackBytes; + + /* We loop, incrementing the System Call Index, until the end of the file */ + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + StackBytes = ARGS_TO_BYTES(strtoul(SyscallArguments, NULL, 0)); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Create the ZwXXX name, if requested */ + if (NeedsZw) { + ZwSyscallName = alloca(strlen(NtSyscallName)); + strcpy(ZwSyscallName, NtSyscallName); + ZwSyscallName[0] = 'Z'; + ZwSyscallName[1] = 'w'; + } + + /* Create Usermode Stubs for Nt/Zw syscalls in each Usermode file */ + int i; + for (i= 0; i < UserFiles; i++) { + + /* Write the Nt Version */ + WriteUserModeStub(UserModeFiles[i], + NtSyscallName, + StackBytes, + SyscallId | Index); + + /* If a Zw Version is needed (was specified), write it too */ + if (ZwSyscallName) WriteUserModeStub(UserModeFiles[i], + ZwSyscallName, + StackBytes, + SyscallId | Index); + + } + + /* Create the Kernel coutnerparts (only Zw*, Nt* are the real functions!) */ + if (KernelModeFile) WriteKernelModeStub(KernelModeFile, + ZwSyscallName, + StackBytes, + SyscallId | Index); + + /* Only increase if we actually added something */ + SyscallId++; + } + } +} + +/*++ + * CreateSystemServiceTable + * + * Parses a System Call Database and creates a System Call Service Table for it. + * + * Params: + * SyscallDb - System Call Database to parse. + * + * SyscallTable - File in where to create System Call Service Table. + * + * Name - Name of the Service Table. + * + * FileLocation - Filename containing the Table. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for the header generation. + * + *--*/ +void +CreateSystemServiceTable(FILE *SyscallDb, + FILE *SyscallTable, + char * Name, + char * FileLocation) +{ + char Line[INPUT_BUFFER_SIZE]; + char *NtSyscallName; + char *SyscallArguments; + int SyscallId; + + /* Print the Header */ + WriteFileHeader(SyscallTable, "System Call Table for Native API", FileLocation); + + /* First we build the SSDT */ + fprintf(SyscallTable,"\n\n\n"); + fprintf(SyscallTable,"SSDT %sSSDT[] = {\n", Name); + + /* We loop, incrementing the System Call Index, until the end of the file */ + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Add a new line */ + if (SyscallId > 0) fprintf(SyscallTable,",\n"); + + /* Write the syscall name in the service table. */ + fprintf(SyscallTable,"\t\t(PVOID (NTAPI *)(VOID))%s", NtSyscallName); + + /* Only increase if we actually added something */ + SyscallId++; + } + } + + /* Close the service table (C syntax) */ + fprintf(SyscallTable,"\n};\n"); + + /* Now we build the SSPT */ + rewind(SyscallDb); + fprintf(SyscallTable,"\n\n\n"); + fprintf(SyscallTable,"SSPT %sSSPT[] = {\n", Name); + + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Add a new line */ + if (SyscallId > 0) fprintf(SyscallTable,",\n"); + + /* Write the syscall arguments in the argument table. */ + fprintf(SyscallTable,"\t\t%lu * sizeof(void *)",strtoul(SyscallArguments, NULL, 0)); + + /* Only increase if we actually added something */ + SyscallId++; + } + } + + /* Close the service table (C syntax) */ + fprintf(SyscallTable,"\n};\n"); + + /* + * We write some useful defines + */ + fprintf(SyscallTable, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); + fprintf(SyscallTable, "#define MAX_SYSCALL_NUMBER %d\n", SyscallId - 1); + fprintf(SyscallTable, "#define NUMBER_OF_SYSCALLS %d\n", SyscallId); + fprintf(SyscallTable, "ULONG %sNumberOfSysCalls = %d;\n", Name, SyscallId); +} + +void usage(char * argv0) +{ + printf("Usage: %s sysfuncs.lst w32ksvc.db napi.h ssdt.h napi.S zw.S win32k.S win32k.S\n" + " sysfuncs.lst native system functions database\n" + " w32ksvc.db native graphic functions database\n" + " napi.h NTOSKRNL service table\n" + " ssdt.h WIN32K service table\n" + " napi.S NTDLL stubs\n" + " zw.S NTOSKRNL Zw stubs\n" + " win32k.S GDI32 stubs\n" + " win32k.S USER32 stubs\n", + argv0 + ); +} + +int main(int argc, char* argv[]) +{ + FILE * Files[Arguments]; + int FileNumber; + char * OpenType = "r"; + + /* Make sure all arguments all there */ + if (argc != Arguments + 1) { + usage(argv[0]); + return(1); + } + + /* Open all Output and bail out if any fail */ + for (FileNumber = 0; FileNumber < Arguments; FileNumber++) { + + /* Open the File */ + if (FileNumber == 2) OpenType = "wb"; + Files[FileNumber] = fopen(argv[FileNumber + 1], OpenType); + + /* Check for failure and error out if so */ + if (!Files[FileNumber]) { + perror(argv[FileNumber + 1]); + return (1); + } + + } + + /* Write the File Headers */ + WriteFileHeader(Files[NtosUserStubs], + "System Call Stubs for Native API", + argv[NtosUserStubs + 1]); + + WriteFileHeader(Files[NtosKernelStubs], + "System Call Stubs for Native API", + argv[NtosKernelStubs + 1]); + fputs("#include \n\n", Files[NtosKernelStubs]); + + WriteFileHeader(Files[Win32kGdiStubs], + "System Call Stubs for Native API", + argv[Win32kGdiStubs + 1]); + + WriteFileHeader(Files[Win32kUserStubs], + "System Call Stubs for Native API", + argv[Win32kUserStubs + 1]); + + + /* Create the System Stubs */ + CreateStubs(Files[NativeSystemDb], + &Files[NtosUserStubs], + Files[NtosKernelStubs], + MAIN_INDEX, + 1, + 1); + + /* Create the Graphics Stubs */ + CreateStubs(Files[NativeGuiDb], + &Files[Win32kGdiStubs], + NULL, + WIN32K_INDEX, + 2, + 0); + + /* Rewind the databases */ + rewind(Files[NativeSystemDb]); + rewind(Files[NativeGuiDb]); + + /* Create the Service Tables */ + CreateSystemServiceTable(Files[NativeSystemDb], + Files[NtosServiceTable], + "Main", + argv[NtosServiceTable + 1]); + + CreateSystemServiceTable(Files[NativeGuiDb], + Files[Win32kServiceTable], + "Win32k", + argv[Win32kServiceTable + 1]); + + /* Close all files */ + for (FileNumber = 0; FileNumber < Arguments; FileNumber++) { + + /* Close the File */ + fclose(Files[FileNumber]); + + } + + return(0); +} diff --git a/reactos/tools/nci/sysfuncs.lst b/reactos/tools/nci/sysfuncs.lst new file mode 100644 index 00000000000..f52329eb239 --- /dev/null +++ b/reactos/tools/nci/sysfuncs.lst @@ -0,0 +1,234 @@ +NtAcceptConnectPort 6 +NtAccessCheck 8 +NtAccessCheckAndAuditAlarm 11 +NtAddAtom 3 +NtAddBootEntry 2 +NtAdjustGroupsToken 6 +NtAdjustPrivilegesToken 6 +NtAlertResumeThread 2 +NtAlertThread 1 +NtAllocateLocallyUniqueId 1 +NtAllocateUuids 4 +NtAllocateVirtualMemory 6 +NtAssignProcessToJobObject 2 +NtCallbackReturn 3 +NtCancelIoFile 2 +NtCancelTimer 2 +NtClearEvent 1 +NtClose 1 +NtCloseObjectAuditAlarm 3 +NtCompleteConnectPort 1 +NtConnectPort 8 +NtContinue 2 +NtCreateDirectoryObject 3 +NtCreateEvent 5 +NtCreateEventPair 3 +NtCreateFile 11 +NtCreateIoCompletion 4 +NtCreateJobObject 3 +NtCreateKey 7 +NtCreateMailslotFile 8 +NtCreateMutant 4 +NtCreateNamedPipeFile 14 +NtCreatePagingFile 4 +NtCreatePort 5 +NtCreateProcess 8 +NtCreateProfile 9 +NtCreateSection 7 +NtCreateSemaphore 5 +NtCreateSymbolicLinkObject 4 +NtCreateThread 8 +NtCreateTimer 4 +NtCreateToken 13 +NtCreateWaitablePort 5 +NtDelayExecution 2 +NtDeleteAtom 1 +NtDeleteBootEntry 2 +NtDeleteFile 1 +NtDeleteKey 1 +NtDeleteObjectAuditAlarm 3 +NtDeleteValueKey 2 +NtDeviceIoControlFile 10 +NtDisplayString 1 +NtDuplicateObject 7 +NtDuplicateToken 6 +NtEnumerateBootEntries 2 +NtEnumerateKey 6 +NtEnumerateValueKey 6 +NtExtendSection 2 +NtFindAtom 3 +NtFlushBuffersFile 2 +NtFlushInstructionCache 3 +NtFlushKey 1 +NtFlushVirtualMemory 4 +NtFlushWriteBuffer 0 +NtFreeVirtualMemory 4 +NtFsControlFile 10 +NtGetContextThread 2 +NtGetPlugPlayEvent 4 +NtGetTickCount 0 +NtImpersonateClientOfPort 2 +NtImpersonateThread 3 +NtInitializeRegistry 1 +NtInitiatePowerAction 4 +NtIsProcessInJob 2 +NtListenPort 2 +NtLoadDriver 1 +NtLoadKey 2 +NtLoadKey2 3 +NtLockFile 10 +NtLockVirtualMemory 4 +NtMakePermanentObject 1 +NtMakeTemporaryObject 1 +NtMapViewOfSection 10 +NtNotifyChangeDirectoryFile 9 +NtNotifyChangeKey 10 +NtOpenDirectoryObject 3 +NtOpenEvent 3 +NtOpenEventPair 3 +NtOpenFile 6 +NtOpenIoCompletion 3 +NtOpenJobObject 3 +NtOpenKey 3 +NtOpenMutant 3 +NtOpenObjectAuditAlarm 12 +NtOpenProcess 4 +NtOpenProcessToken 3 +NtOpenProcessTokenEx 4 +NtOpenSection 3 +NtOpenSemaphore 3 +NtOpenSymbolicLinkObject 3 +NtOpenThread 4 +NtOpenThreadToken 4 +NtOpenThreadTokenEx 5 +NtOpenTimer 3 +NtPlugPlayControl 3 +NtPowerInformation 5 +NtPrivilegeCheck 3 +NtPrivilegedServiceAuditAlarm 5 +NtPrivilegeObjectAuditAlarm 6 +NtProtectVirtualMemory 5 +NtPulseEvent 2 +NtQueryInformationAtom 5 +NtQueryAttributesFile 2 +NtQueryBootEntryOrder 2 +NtQueryBootOptions 2 +NtQueryDefaultLocale 2 +NtQueryDefaultUILanguage 1 +NtQueryDirectoryFile 11 +NtQueryDirectoryObject 7 +NtQueryEaFile 9 +NtQueryEvent 5 +NtQueryFullAttributesFile 2 +NtQueryInformationFile 5 +NtQueryInformationJobObject 5 +NtQueryInformationPort 5 +NtQueryInformationProcess 5 +NtQueryInformationThread 5 +NtQueryInformationToken 5 +NtQueryInstallUILanguage 1 +NtQueryIntervalProfile 2 +NtQueryIoCompletion 5 +NtQueryKey 5 +NtQueryMultipleValueKey 6 +NtQueryMutant 5 +NtQueryObject 5 +NtQueryPerformanceCounter 2 +NtQueryQuotaInformationFile 9 +NtQuerySection 5 +NtQuerySecurityObject 5 +NtQuerySemaphore 5 +NtQuerySymbolicLinkObject 3 +NtQuerySystemEnvironmentValue 4 +NtQuerySystemInformation 4 +NtQuerySystemTime 1 +NtQueryTimer 5 +NtQueryTimerResolution 3 +NtQueryValueKey 6 +NtQueryVirtualMemory 6 +NtQueryVolumeInformationFile 5 +NtQueueApcThread 5 +NtRaiseException 3 +NtRaiseHardError 6 +NtReadFile 9 +NtReadFileScatter 9 +NtReadRequestData 6 +NtReadVirtualMemory 5 +NtRegisterThreadTerminatePort 1 +NtReleaseMutant 2 +NtReleaseSemaphore 3 +NtRemoveIoCompletion 5 +NtReplaceKey 3 +NtReplyPort 2 +NtReplyWaitReceivePort 4 +NtReplyWaitReplyPort 2 +NtRequestPort 2 +NtRequestWaitReplyPort 3 +NtResetEvent 2 +NtRestoreKey 3 +NtResumeThread 2 +NtSaveKey 2 +NtSaveKeyEx 3 +NtSetBootEntryOrder 2 +NtSetBootOptions 2 +NtSetIoCompletion 5 +NtSetContextThread 2 +NtSetDefaultHardErrorPort 1 +NtSetDefaultLocale 2 +NtSetDefaultUILanguage 1 +NtSetEaFile 4 +NtSetEvent 2 +NtSetHighEventPair 1 +NtSetHighWaitLowEventPair 1 +NtSetHighWaitLowThread 0 +NtSetInformationFile 5 +NtSetInformationKey 4 +NtSetInformationJobObject 4 +NtSetInformationObject 4 +NtSetInformationProcess 4 +NtSetInformationThread 4 +NtSetInformationToken 4 +NtSetIntervalProfile 2 +NtSetLdtEntries 6 +NtSetLowEventPair 1 +NtSetLowWaitHighEventPair 1 +NtSetLowWaitHighThread 0 +NtSetQuotaInformationFile 4 +NtSetSecurityObject 3 +NtSetSystemEnvironmentValue 2 +NtSetSystemInformation 3 +NtSetSystemPowerState 3 +NtSetSystemTime 2 +NtSetTimer 7 +NtSetTimerResolution 3 +NtSetUuidSeed 1 +NtSetValueKey 6 +NtSetVolumeInformationFile 5 +NtShutdownSystem 1 +NtSignalAndWaitForSingleObject 4 +NtStartProfile 1 +NtStopProfile 1 +NtSuspendThread 2 +NtSystemDebugControl 6 +NtTerminateJobObject 2 +NtTerminateProcess 2 +NtTerminateThread 2 +NtTestAlert 0 +NtTraceEvent 4 +NtTranslateFilePath 3 +NtUnloadDriver 1 +NtUnloadKey 1 +NtUnlockFile 5 +NtUnlockVirtualMemory 4 +NtUnmapViewOfSection 2 +NtVdmControl 2 +NtWaitForMultipleObjects 5 +NtWaitForSingleObject 3 +NtWaitHighEventPair 1 +NtWaitLowEventPair 1 +NtWriteFile 9 +NtWriteFileGather 9 +NtWriteRequestData 6 +NtWriteVirtualMemory 5 +NtW32Call 5 +NtYieldExecution 0 diff --git a/reactos/iface/addsys/w32ksvc.db b/reactos/tools/nci/w32ksvc.db similarity index 100% rename from reactos/iface/addsys/w32ksvc.db rename to reactos/tools/nci/w32ksvc.db diff --git a/reactos/tools/rbuild/makefile b/reactos/tools/rbuild/makefile index b789fe149ac..222c7860449 100644 --- a/reactos/tools/rbuild/makefile +++ b/reactos/tools/rbuild/makefile @@ -90,11 +90,6 @@ $(RBUILD_COMMON_OBJECTS): %.o: %.cpp $(RBUILD_SPECIAL_OBJECTS): %.o: %.cpp ${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@ -.PHONY: rbuild - -rbuild: $(RBUILD_TARGET) - - - $(RBUILD_TEST_TARGET): $(RBUILD_TEST_OBJECTS) ${host_gpp} $(RBUILD_TEST_OBJECTS) $(RBUILD_HOST_LFLAGS) -o $(RBUILD_TEST_TARGET) diff --git a/reactos/tools/rsym.c b/reactos/tools/rsym.c index 9b0ba1fc523..968c03a4c1c 100644 --- a/reactos/tools/rsym.c +++ b/reactos/tools/rsym.c @@ -1,6 +1,25 @@ /* * Usage: rsym input-file output-file + * + * There are two sources of information: the .stab/.stabstr + * sections of the executable and the COFF symbol table. Most + * of the information is in the .stab/.stabstr sections. + * However, most of our asm files don't contain .stab directives, + * so routines implemented in assembler won't show up in the + * .stab section. They are present in the COFF symbol table. + * So, we mostly use the .stab/.stabstr sections, but we augment + * the info there with info from the COFF symbol table when + * possible. + * + * This is a tool and is compiled using the host compiler, + * i.e. on Linux gcc and not mingw-gcc (cross-compiler). + * Therefore we can't include SDK headers and we have to + * duplicate some definitions here. + * Also note that the internal functions are "old C-style", + * returning an int, where a return of 0 means success and + * non-zero is failure. */ + #include #include #include @@ -12,105 +31,153 @@ #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 -typedef void* PVOID; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef signed long LONG; typedef unsigned long ULONG; +#if defined(_WIN64) +typedef unsigned __int64 ULONG_PTR; +#else +typedef unsigned long ULONG_PTR; +#endif #pragma pack(push,2) typedef struct _IMAGE_DOS_HEADER { - WORD e_magic; - WORD e_cblp; - WORD e_cp; - WORD e_crlc; - WORD e_cparhdr; - WORD e_minalloc; - WORD e_maxalloc; - WORD e_ss; - WORD e_sp; - WORD e_csum; - WORD e_ip; - WORD e_cs; - WORD e_lfarlc; - WORD e_ovno; - WORD e_res[4]; - WORD e_oemid; - WORD e_oeminfo; - WORD e_res2[10]; - LONG e_lfanew; + WORD e_magic; + WORD e_cblp; + WORD e_cp; + WORD e_crlc; + WORD e_cparhdr; + WORD e_minalloc; + WORD e_maxalloc; + WORD e_ss; + WORD e_sp; + WORD e_csum; + WORD e_ip; + WORD e_cs; + WORD e_lfarlc; + WORD e_ovno; + WORD e_res[4]; + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; + LONG e_lfanew; } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; #pragma pack(pop) + +#define IMAGE_FILE_LINE_NUMS_STRIPPED 4 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 8 +#define IMAGE_FILE_DEBUG_STRIPPED 512 + #pragma pack(push,4) -typedef struct _IMAGE_DATA_DIRECTORY { - DWORD VirtualAddress; - DWORD Size; -} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; -typedef struct _IMAGE_OPTIONAL_HEADER { - WORD Magic; - BYTE MajorLinkerVersion; - BYTE MinorLinkerVersion; - DWORD SizeOfCode; - DWORD SizeOfInitializedData; - DWORD SizeOfUninitializedData; - DWORD AddressOfEntryPoint; - DWORD BaseOfCode; - DWORD BaseOfData; - DWORD ImageBase; - DWORD SectionAlignment; - DWORD FileAlignment; - WORD MajorOperatingSystemVersion; - WORD MinorOperatingSystemVersion; - WORD MajorImageVersion; - WORD MinorImageVersion; - WORD MajorSubsystemVersion; - WORD MinorSubsystemVersion; - DWORD Reserved1; - DWORD SizeOfImage; - DWORD SizeOfHeaders; - DWORD CheckSum; - WORD Subsystem; - WORD DllCharacteristics; - DWORD SizeOfStackReserve; - DWORD SizeOfStackCommit; - DWORD SizeOfHeapReserve; - DWORD SizeOfHeapCommit; - DWORD LoaderFlags; - DWORD NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; -} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; typedef struct _IMAGE_FILE_HEADER { - WORD Machine; - WORD NumberOfSections; - DWORD TimeDateStamp; - DWORD PointerToSymbolTable; - DWORD NumberOfSymbols; - WORD SizeOfOptionalHeader; - WORD Characteristics; + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; + +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 + +typedef struct _IMAGE_OPTIONAL_HEADER { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Reserved1; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; + +#define IMAGE_SCN_TYPE_NOLOAD 0x00000002 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 + typedef struct _IMAGE_SECTION_HEADER { - BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; - union { - DWORD PhysicalAddress; - DWORD VirtualSize; - } Misc; - DWORD VirtualAddress; - DWORD SizeOfRawData; - DWORD PointerToRawData; - DWORD PointerToRelocations; - DWORD PointerToLinenumbers; - WORD NumberOfRelocations; - WORD NumberOfLinenumbers; - DWORD Characteristics; + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; } IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; + +typedef struct _IMAGE_BASE_RELOCATION { + DWORD VirtualAddress; + DWORD SizeOfBlock; +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; + + +typedef struct { + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + unsigned long f_timdat; /* time & date stamp */ + unsigned long f_symptr; /* file pointer to symtab */ + unsigned long f_nsyms; /* number of symtab entries */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +} FILHDR; + +typedef struct { + char s_name[8]; /* section name */ + unsigned long s_paddr; /* physical address, aliased s_nlib */ + unsigned long s_vaddr; /* virtual address */ + unsigned long s_size; /* section size */ + unsigned long s_scnptr; /* file ptr to raw data for section */ + unsigned long s_relptr; /* file ptr to relocation */ + unsigned long s_lnnoptr; /* file ptr to line numbers */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of line number entries */ + unsigned long s_flags; /* flags */ +} SCNHDR; #pragma pack(pop) typedef struct _SYMBOLFILE_HEADER { - unsigned long StabsOffset; - unsigned long StabsLength; - unsigned long StabstrOffset; - unsigned long StabstrLength; + unsigned long SymbolsOffset; + unsigned long SymbolsLength; + unsigned long StringsOffset; + unsigned long StringsLength; } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; typedef struct _STAB_ENTRY { @@ -125,13 +192,91 @@ typedef struct _STAB_ENTRY { #define N_SLINE 0x44 #define N_SO 0x64 -typedef struct +/* COFF symbol table */ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +#define N_BTMASK (0xf) +#define N_TMASK (0x30) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + +/* derived types, in e_type */ +#define DT_NON (0) /* no derived type */ +#define DT_PTR (1) /* pointer */ +#define DT_FCN (2) /* function */ +#define DT_ARY (3) /* array */ + +#define BTYPE(x) ((x) & N_BTMASK) + +#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) +#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) +#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) +#define ISTAG(x) ((x)==C_STRTAG||(x)==C_UNTAG||(x)==C_ENTAG) +#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) + +#define C_EFCN 0xff /* physical end of function */ +#define C_NULL 0 +#define C_AUTO 1 /* automatic variable */ +#define C_EXT 2 /* external symbol */ +#define C_STAT 3 /* static */ +#define C_REG 4 /* register variable */ +#define C_EXTDEF 5 /* external definition */ +#define C_LABEL 6 /* label */ +#define C_ULABEL 7 /* undefined label */ +#define C_MOS 8 /* member of structure */ +#define C_ARG 9 /* function argument */ +#define C_STRTAG 10 /* structure tag */ +#define C_MOU 11 /* member of union */ +#define C_UNTAG 12 /* union tag */ +#define C_TPDEF 13 /* type definition */ +#define C_USTATIC 14 /* undefined static */ +#define C_ENTAG 15 /* enumeration tag */ +#define C_MOE 16 /* member of enumeration */ +#define C_REGPARM 17 /* register parameter */ +#define C_FIELD 18 /* bit field */ +#define C_AUTOARG 19 /* auto argument */ +#define C_LASTENT 20 /* dummy entry (end of block) */ +#define C_BLOCK 100 /* ".bb" or ".eb" */ +#define C_FCN 101 /* ".bf" or ".ef" */ +#define C_EOS 102 /* end of structure */ +#define C_FILE 103 /* file name */ +#define C_LINE 104 /* line # reformatted as symbol table entry */ +#define C_ALIAS 105 /* duplicate tag */ +#define C_HIDDEN 106 /* ext symbol in dmert public lib */ + +#pragma pack(push,1) +typedef struct _COFF_SYMENT { - unsigned long OldOffset; - unsigned long NewOffset; - char* Name; - unsigned long Length; -} STR_ENTRY, *PSTR_ENTRY; + union + { + char e_name[E_SYMNMLEN]; + struct + { + unsigned long e_zeroes; + unsigned long e_offset; + } + e; + } + e; + unsigned long e_value; + short e_scnum; + unsigned short e_type; + unsigned char e_sclass; + unsigned char e_numaux; +} COFF_SYMENT, *PCOFF_SYMENT; +#pragma pack(pop) + +typedef struct _ROSSYM_ENTRY { + ULONG_PTR Address; + ULONG FunctionOffset; + ULONG FileOffset; + ULONG SourceLine; +} ROSSYM_ENTRY, *PROSSYM_ENTRY; + +#define ROUND_UP(N, S) (((N) + (S) - 1) & ~((S) - 1)) char* convert_path(char* origpath) { @@ -161,185 +306,902 @@ char* convert_path(char* origpath) return(newpath); } -#define TRANSFER_SIZE (65536) +static int +CompareSymEntry(const PROSSYM_ENTRY SymEntry1, const PROSSYM_ENTRY SymEntry2) +{ + if (SymEntry1->Address < SymEntry2->Address) + { + return -1; + } + + if (SymEntry2->Address < SymEntry1->Address) + { + return +1; + } + + return 0; +} + +static int +GetStabInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders, + ULONG *StabSymbolsLength, void **StabSymbolsBase, + ULONG *StabStringsLength, void **StabStringsBase) +{ + ULONG Idx; + + /* Load .stab and .stabstr sections if available */ + *StabSymbolsBase = NULL; + *StabSymbolsLength = 0; + *StabStringsBase = NULL; + *StabStringsLength = 0; + + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */ + if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0) + && (PESectionHeaders[Idx].Name[5] == 0)) + { + /* printf(".stab section found. Size %d\n", + PESectionHeaders[Idx].SizeOfRawData); */ + + *StabSymbolsLength = PESectionHeaders[Idx].SizeOfRawData; + *StabSymbolsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); + } + + if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) + { + /* printf(".stabstr section found. Size %d\n", + PESectionHeaders[Idx].SizeOfRawData); */ + + *StabStringsLength = PESectionHeaders[Idx].SizeOfRawData; + *StabStringsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); + } + } + + return 0; +} + +static int +GetCoffInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders, + ULONG *CoffSymbolsLength, void **CoffSymbolsBase, + ULONG *CoffStringsLength, void **CoffStringsBase) +{ + + if (0 == PEFileHeader->PointerToSymbolTable || 0 == PEFileHeader->NumberOfSymbols) + { + /* No COFF symbol table */ + *CoffSymbolsLength = 0; + *CoffStringsLength = 0; + } + else + { + *CoffSymbolsLength = PEFileHeader->NumberOfSymbols * sizeof(COFF_SYMENT); + *CoffSymbolsBase = (void *)((char *) FileData + PEFileHeader->PointerToSymbolTable); + *CoffStringsLength = *((ULONG *) ((char *) *CoffSymbolsBase + *CoffSymbolsLength)); + *CoffStringsBase = (void *)((char *) *CoffSymbolsBase + *CoffSymbolsLength); + } + + return 0; +} + +static ULONG +FindOrAddString(char *StringToFind, ULONG *StringsLength, void *StringsBase) +{ + char *Search, *End; + + Search = (char *) StringsBase; + End = Search + *StringsLength; + + while (Search < End) + { + if (0 == strcmp(Search, StringToFind)) + { + return Search - (char *) StringsBase; + } + Search += strlen(Search) + 1; + } + + strcpy(Search, StringToFind); + *StringsLength += strlen(StringToFind) + 1; + + return Search - (char *) StringsBase; +} + +static int +ConvertStabs(ULONG *SymbolsCount, PROSSYM_ENTRY *SymbolsBase, + ULONG *StringsLength, void *StringsBase, + ULONG StabSymbolsLength, void *StabSymbolsBase, + ULONG StabStringsLength, void *StabStringsBase, + ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders) +{ + PSTAB_ENTRY StabEntry; + ULONG Count, i; + ULONG_PTR Address, LastFunctionAddress; + int First; + char *Name; + char FuncName[256]; + + StabEntry = StabSymbolsBase; + Count = StabSymbolsLength / sizeof(STAB_ENTRY); + *SymbolsBase = malloc(Count * sizeof(ROSSYM_ENTRY)); + if (NULL == *SymbolsBase) + { + fprintf(stderr, "Failed to allocate memory for converted .stab symbols\n"); + return 1; + } + *SymbolsCount = 0; + + LastFunctionAddress = 0; + First = 1; + for (i = 0; i < Count; i++) + { + switch (StabEntry[i].n_type) + { + case N_SO: + Name = (char *) StabStringsBase + StabEntry[i].n_strx; + if ('\0' == *Name || '/' == Name[strlen(Name) - 1] + || '\\' == Name[strlen(Name) - 1] + || StabEntry[i].n_value < ImageBase) + { + continue; + } + Address = StabEntry[i].n_value - ImageBase; + if (Address != (*SymbolsBase)[*SymbolsCount].Address && ! First) + { + (*SymbolsCount)++; + } + (*SymbolsBase)[*SymbolsCount].Address = Address; + (*SymbolsBase)[*SymbolsCount].FileOffset = FindOrAddString((char *) StabStringsBase + + StabEntry[i].n_strx, + StringsLength, + StringsBase); + (*SymbolsBase)[*SymbolsCount].FunctionOffset = 0; + (*SymbolsBase)[*SymbolsCount].SourceLine = 0; + LastFunctionAddress = 0; + break; + case N_FUN: + if (0 == StabEntry[i].n_desc || StabEntry[i].n_value < ImageBase) /* line # 0 isn't valid */ + { + continue; + } + Address = StabEntry[i].n_value - ImageBase; + if (Address != (*SymbolsBase)[*SymbolsCount].Address && ! First) + { + (*SymbolsCount)++; + (*SymbolsBase)[*SymbolsCount].FileOffset = (*SymbolsBase)[*SymbolsCount - 1].FileOffset; + } + (*SymbolsBase)[*SymbolsCount].Address = Address; + if (sizeof(FuncName) <= strlen((char *) StabStringsBase + StabEntry[i].n_strx)) + { + free(*SymbolsBase); + fprintf(stderr, "Function name too long\n"); + return 1; + } + strcpy(FuncName, (char *) StabStringsBase + StabEntry[i].n_strx); + Name = strchr(FuncName, ':'); + if (NULL != Name) + { + *Name = '\0'; + } + (*SymbolsBase)[*SymbolsCount].FunctionOffset = FindOrAddString(FuncName, + StringsLength, + StringsBase); + (*SymbolsBase)[*SymbolsCount].SourceLine = 0; + LastFunctionAddress = Address; + break; + case N_SLINE: + if (0 == LastFunctionAddress) + { + Address = StabEntry[i].n_value - ImageBase; + } + else + { + Address = LastFunctionAddress + StabEntry[i].n_value; + } + if (Address != (*SymbolsBase)[*SymbolsCount].Address && ! First) + { + (*SymbolsCount)++; + (*SymbolsBase)[*SymbolsCount].FileOffset = (*SymbolsBase)[*SymbolsCount - 1].FileOffset; + (*SymbolsBase)[*SymbolsCount].FunctionOffset = (*SymbolsBase)[*SymbolsCount - 1].FunctionOffset; + } + (*SymbolsBase)[*SymbolsCount].Address = Address; + (*SymbolsBase)[*SymbolsCount].SourceLine = StabEntry[i].n_desc; + break; + default: + continue; + } + First = 0; + } + (*SymbolsCount)++; + + qsort(*SymbolsBase, *SymbolsCount, sizeof(ROSSYM_ENTRY), (int (*)(const void *, const void *)) CompareSymEntry); + + return 0; +} + +static int +ConvertCoffs(ULONG *SymbolsCount, PROSSYM_ENTRY *SymbolsBase, + ULONG *StringsLength, void *StringsBase, + ULONG CoffSymbolsLength, void *CoffSymbolsBase, + ULONG CoffStringsLength, void *CoffStringsBase, + ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders) +{ + ULONG Count, i; + PCOFF_SYMENT CoffEntry; + char FuncName[256]; + char *p; + + CoffEntry = (PCOFF_SYMENT) CoffSymbolsBase; + Count = CoffSymbolsLength / sizeof(COFF_SYMENT); + *SymbolsBase = malloc(Count * sizeof(ROSSYM_ENTRY)); + if (NULL == *SymbolsBase) + { + fprintf(stderr, "Unable to allocate memory for converted COFF symbols\n"); + return 1; + } + *SymbolsCount = 0; + + for (i = 0; i < Count; i++) + { + if (ISFCN(CoffEntry[i].e_type) || C_EXT == CoffEntry[i].e_sclass) + { + (*SymbolsBase)[*SymbolsCount].Address = CoffEntry[i].e_value; + if (0 < CoffEntry[i].e_scnum) + { + if (PEFileHeader->NumberOfSections < CoffEntry[i].e_scnum) + { + free(*SymbolsBase); + fprintf(stderr, "Invalid section number %d in COFF symbols (only %d sections present)\n", + CoffEntry[i].e_scnum, PEFileHeader->NumberOfSections); + return 1; + } + (*SymbolsBase)[*SymbolsCount].Address += PESectionHeaders[CoffEntry[i].e_scnum - 1].VirtualAddress; + } + (*SymbolsBase)[*SymbolsCount].FileOffset = 0; + if (0 == CoffEntry[i].e.e.e_zeroes) + { + if (sizeof(FuncName) <= strlen((char *) CoffStringsBase + CoffEntry[i].e.e.e_offset)) + { + free(*SymbolsBase); + fprintf(stderr, "Function name too long\n"); + return 1; + } + strcpy(FuncName, (char *) CoffStringsBase + CoffEntry[i].e.e.e_offset); + } + else + { + memcpy(FuncName, CoffEntry[i].e.e_name, E_SYMNMLEN); + FuncName[E_SYMNMLEN] = '\0'; + } + + /* Name demangling: stdcall */ + p = strrchr(FuncName, '@'); + if (NULL != p) + { + *p = '\0'; + } + p = ('_' == FuncName[0] || '@' == FuncName[0] ? FuncName + 1 : FuncName); + (*SymbolsBase)[*SymbolsCount].FunctionOffset = FindOrAddString(p, + StringsLength, + StringsBase); + (*SymbolsBase)[*SymbolsCount].SourceLine = 0; + (*SymbolsCount)++; + } + i += CoffEntry[i].e_numaux; + } + + qsort(*SymbolsBase, *SymbolsCount, sizeof(ROSSYM_ENTRY), (int (*)(const void *, const void *)) CompareSymEntry); + + return 0; +} + +static int +MergeStabsAndCoffs(ULONG *MergedSymbolCount, PROSSYM_ENTRY *MergedSymbols, + ULONG StabSymbolsCount, PROSSYM_ENTRY StabSymbols, + ULONG CoffSymbolsCount, PROSSYM_ENTRY CoffSymbols) +{ + ULONG StabIndex, j; + ULONG CoffIndex; + ULONG_PTR StabFunctionStartAddress; + ULONG StabFunctionStringOffset, NewStabFunctionStringOffset; + + *MergedSymbols = malloc(StabSymbolsCount * sizeof(ROSSYM_ENTRY)); + if (NULL == *MergedSymbols) + { + fprintf(stderr, "Unable to allocate memory for merged symbols\n"); + return 1; + } + *MergedSymbolCount = 0; + + StabFunctionStartAddress = 0; + StabFunctionStringOffset = 0; + CoffIndex = 0; + for (StabIndex = 0; StabIndex < StabSymbolsCount; StabIndex++) + { + (*MergedSymbols)[*MergedSymbolCount] = StabSymbols[StabIndex]; + for (j = StabIndex + 1; + j < StabSymbolsCount && StabSymbols[j].Address == StabSymbols[StabIndex].Address; + j++) + { + if (0 != StabSymbols[j].FileOffset && 0 == (*MergedSymbols)[*MergedSymbolCount].FileOffset) + { + (*MergedSymbols)[*MergedSymbolCount].FileOffset = StabSymbols[j].FileOffset; + } + if (0 != StabSymbols[j].FunctionOffset && 0 == (*MergedSymbols)[*MergedSymbolCount].FunctionOffset) + { + (*MergedSymbols)[*MergedSymbolCount].FunctionOffset = StabSymbols[j].FunctionOffset; + } + if (0 != StabSymbols[j].SourceLine && 0 == (*MergedSymbols)[*MergedSymbolCount].SourceLine) + { + (*MergedSymbols)[*MergedSymbolCount].SourceLine = StabSymbols[j].SourceLine; + } + } + StabIndex = j - 1; + while (CoffIndex < CoffSymbolsCount + && CoffSymbols[CoffIndex + 1].Address <= (*MergedSymbols)[*MergedSymbolCount].Address) + { + CoffIndex++; + } + NewStabFunctionStringOffset = (*MergedSymbols)[*MergedSymbolCount].FunctionOffset; + if (CoffSymbols[CoffIndex].Address < (*MergedSymbols)[*MergedSymbolCount].Address + && StabFunctionStartAddress < CoffSymbols[CoffIndex].Address + && 0 != CoffSymbols[CoffIndex].FunctionOffset) + { + (*MergedSymbols)[*MergedSymbolCount].FunctionOffset = CoffSymbols[CoffIndex].FunctionOffset; + } + if (StabFunctionStringOffset != NewStabFunctionStringOffset) + { + StabFunctionStartAddress = (*MergedSymbols)[*MergedSymbolCount].Address; + } + StabFunctionStringOffset = NewStabFunctionStringOffset; + (*MergedSymbolCount)++; + } + + return 0; +} + +static PIMAGE_SECTION_HEADER +FindSectionForRVA(DWORD RVA, unsigned NumberOfSections, PIMAGE_SECTION_HEADER SectionHeaders) +{ + unsigned Section; + + for (Section = 0; Section < NumberOfSections; Section++) + { + if (SectionHeaders[Section].VirtualAddress <= RVA && + RVA < SectionHeaders[Section].VirtualAddress + SectionHeaders[Section].Misc.VirtualSize) + { + return SectionHeaders + Section; + } + } + + return NULL; +} + +static int +IncludeRelocationsForSection(PIMAGE_SECTION_HEADER SectionHeader) +{ + static char *BlacklistedSections[] = + { + ".idata", + ".reloc" + }; + char SectionName[IMAGE_SIZEOF_SHORT_NAME]; + unsigned i; + + if (0 != (SectionHeader->Characteristics & IMAGE_SCN_LNK_REMOVE)) + { + return 0; + } + + for (i = 0; i < sizeof(BlacklistedSections) / sizeof(BlacklistedSections[0]); i++) + { + strncpy(SectionName, BlacklistedSections[i], IMAGE_SIZEOF_SHORT_NAME); + if (0 == memcmp(SectionName, SectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME)) + { + return 0; + } + } + + return 1; +} + +static int +ProcessRelocations(ULONG *ProcessedRelocsLength, void **ProcessedRelocs, + void *RawData, PIMAGE_OPTIONAL_HEADER OptHeader, + unsigned NumberOfSections, PIMAGE_SECTION_HEADER SectionHeaders) +{ + PIMAGE_SECTION_HEADER RelocSectionHeader, TargetSectionHeader; + PIMAGE_BASE_RELOCATION BaseReloc, End, AcceptedRelocs; + int Found; + + if (OptHeader->NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_BASERELOC + || 0 == OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) + { + /* No relocation entries */ + *ProcessedRelocsLength = 0; + *ProcessedRelocs = NULL; + return 0; + } + + RelocSectionHeader = FindSectionForRVA(OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, + NumberOfSections, SectionHeaders); + if (NULL == RelocSectionHeader) + { + fprintf(stderr, "Can't find section header for relocation data\n"); + return 1; + } + + *ProcessedRelocs = malloc(RelocSectionHeader->SizeOfRawData); + if (NULL == *ProcessedRelocs) + { + fprintf(stderr, "Failed to allocate %lu bytes for relocations\n", RelocSectionHeader->SizeOfRawData); + return 1; + } + *ProcessedRelocsLength = 0; + + BaseReloc = (PIMAGE_BASE_RELOCATION) ((char *) RawData + + RelocSectionHeader->PointerToRawData + + (OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress - + RelocSectionHeader->VirtualAddress)); + End = (PIMAGE_BASE_RELOCATION) ((char *) BaseReloc + + OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); + + while (BaseReloc < End && 0 < BaseReloc->SizeOfBlock) + { + TargetSectionHeader = FindSectionForRVA(BaseReloc->VirtualAddress, NumberOfSections, + SectionHeaders); + if (NULL != TargetSectionHeader && IncludeRelocationsForSection(TargetSectionHeader)) + { + AcceptedRelocs = *ProcessedRelocs; + Found = 0; + while (AcceptedRelocs < (PIMAGE_BASE_RELOCATION) ((char *) *ProcessedRelocs + + *ProcessedRelocsLength) + && ! Found) + { + Found = BaseReloc->SizeOfBlock == AcceptedRelocs->SizeOfBlock + && 0 == memcmp(BaseReloc, AcceptedRelocs, AcceptedRelocs->SizeOfBlock); + AcceptedRelocs= (PIMAGE_BASE_RELOCATION) ((char *) AcceptedRelocs + + AcceptedRelocs->SizeOfBlock); + } + if (! Found) + { + memcpy((char *) *ProcessedRelocs + *ProcessedRelocsLength, + BaseReloc, BaseReloc->SizeOfBlock); + *ProcessedRelocsLength += BaseReloc->SizeOfBlock; + } + } + BaseReloc = (PIMAGE_BASE_RELOCATION)((char *) BaseReloc + BaseReloc->SizeOfBlock); + } + + return 0; +} + +static int +CreateOutputFile(FILE *OutFile, void *InData, + PIMAGE_DOS_HEADER InDosHeader, PIMAGE_FILE_HEADER InFileHeader, + PIMAGE_OPTIONAL_HEADER InOptHeader, PIMAGE_SECTION_HEADER InSectionHeaders, + ULONG RosSymLength, void *RosSymSection) +{ + ULONG StartOfRawData; + unsigned Section; + void *OutHeader, *ProcessedRelocs, *PaddedRosSym, *Data; + PIMAGE_DOS_HEADER OutDosHeader; + PIMAGE_FILE_HEADER OutFileHeader; + PIMAGE_OPTIONAL_HEADER OutOptHeader; + PIMAGE_SECTION_HEADER OutSectionHeaders, CurrentSectionHeader; + DWORD CheckSum; + ULONG Length, i; + ULONG ProcessedRelocsLength; + ULONG RosSymOffset, RosSymFileLength; + int InRelocSectionIndex; + PIMAGE_SECTION_HEADER OutRelocSection; + + StartOfRawData = 0; + for (Section = 0; Section < InFileHeader->NumberOfSections; Section++) + { + if ((0 == StartOfRawData + || InSectionHeaders[Section].PointerToRawData < StartOfRawData) + && 0 != InSectionHeaders[Section].PointerToRawData + && 0 == (InSectionHeaders[Section].Characteristics & IMAGE_SCN_LNK_REMOVE)) + { + StartOfRawData = InSectionHeaders[Section].PointerToRawData; + } + } + OutHeader = malloc(StartOfRawData); + if (NULL == OutHeader) + { + fprintf(stderr, "Failed to allocate %lu bytes for output file header\n", StartOfRawData); + return 1; + } + memset(OutHeader, '\0', StartOfRawData); + + OutDosHeader = (PIMAGE_DOS_HEADER) OutHeader; + memcpy(OutDosHeader, InDosHeader, InDosHeader->e_lfanew + sizeof(ULONG)); + + OutFileHeader = (PIMAGE_FILE_HEADER)((char *) OutHeader + OutDosHeader->e_lfanew + sizeof(ULONG)); + memcpy(OutFileHeader, InFileHeader, sizeof(IMAGE_FILE_HEADER)); + OutFileHeader->PointerToSymbolTable = 0; + OutFileHeader->NumberOfSymbols = 0; + OutFileHeader->Characteristics &= ~(IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED | + IMAGE_FILE_DEBUG_STRIPPED); + + OutOptHeader = (PIMAGE_OPTIONAL_HEADER)(OutFileHeader + 1); + memcpy(OutOptHeader, InOptHeader, sizeof(IMAGE_OPTIONAL_HEADER)); + OutOptHeader->CheckSum = 0; + + OutSectionHeaders = (PIMAGE_SECTION_HEADER)((char *) OutOptHeader + OutFileHeader->SizeOfOptionalHeader); + + if (ProcessRelocations(&ProcessedRelocsLength, &ProcessedRelocs, InData, InOptHeader, + InFileHeader->NumberOfSections, InSectionHeaders)) + { + return 1; + } + if (InOptHeader->NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_BASERELOC + || 0 == InOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) + { + InRelocSectionIndex = -1; + } + else + { + InRelocSectionIndex = FindSectionForRVA(InOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, + InFileHeader->NumberOfSections, InSectionHeaders) - InSectionHeaders; + } + + OutFileHeader->NumberOfSections = 0; + CurrentSectionHeader = OutSectionHeaders; + OutOptHeader->SizeOfImage = 0; + RosSymOffset = 0; + OutRelocSection = NULL; + for (Section = 0; Section < InFileHeader->NumberOfSections; Section++) + { + if (0 == (InSectionHeaders[Section].Characteristics & IMAGE_SCN_LNK_REMOVE)) + { + *CurrentSectionHeader = InSectionHeaders[Section]; + CurrentSectionHeader->PointerToLinenumbers = 0; + CurrentSectionHeader->NumberOfLinenumbers = 0; + if (OutOptHeader->SizeOfImage < CurrentSectionHeader->VirtualAddress + + CurrentSectionHeader->Misc.VirtualSize) + { + OutOptHeader->SizeOfImage = ROUND_UP(CurrentSectionHeader->VirtualAddress + + CurrentSectionHeader->Misc.VirtualSize, + OutOptHeader->SectionAlignment); + } + if (RosSymOffset < CurrentSectionHeader->PointerToRawData + CurrentSectionHeader->SizeOfRawData) + { + RosSymOffset = CurrentSectionHeader->PointerToRawData + CurrentSectionHeader->SizeOfRawData; + } + if (Section == InRelocSectionIndex) + { + OutRelocSection = CurrentSectionHeader; + } + (OutFileHeader->NumberOfSections) ++; + CurrentSectionHeader++; + } + } + + if (OutRelocSection == CurrentSectionHeader - 1) + { + OutOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = ProcessedRelocsLength; + if (OutOptHeader->SizeOfImage == OutRelocSection->VirtualAddress + + ROUND_UP(OutRelocSection->Misc.VirtualSize, + OutOptHeader->SectionAlignment)) + { + OutOptHeader->SizeOfImage = OutRelocSection->VirtualAddress + + ROUND_UP(ProcessedRelocsLength, + OutOptHeader->SectionAlignment); + } + OutRelocSection->Misc.VirtualSize = ProcessedRelocsLength; + if (RosSymOffset == OutRelocSection->PointerToRawData + + OutRelocSection->SizeOfRawData) + { + RosSymOffset = OutRelocSection->PointerToRawData + + ROUND_UP(ProcessedRelocsLength, OutOptHeader->FileAlignment); + } + OutRelocSection->SizeOfRawData = ROUND_UP(ProcessedRelocsLength, + OutOptHeader->FileAlignment); + } + + RosSymFileLength = ROUND_UP(RosSymLength, OutOptHeader->FileAlignment); + memcpy(CurrentSectionHeader->Name, ".rossym", 8); /* We're lucky: string is exactly 8 bytes long */ + CurrentSectionHeader->Misc.VirtualSize = RosSymLength; + CurrentSectionHeader->VirtualAddress = OutOptHeader->SizeOfImage; + CurrentSectionHeader->SizeOfRawData = RosSymFileLength; + CurrentSectionHeader->PointerToRawData = RosSymOffset; + CurrentSectionHeader->PointerToRelocations = 0; + CurrentSectionHeader->PointerToLinenumbers = 0; + CurrentSectionHeader->NumberOfRelocations = 0; + CurrentSectionHeader->NumberOfLinenumbers = 0; + CurrentSectionHeader->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE + | IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_TYPE_NOLOAD; + OutOptHeader->SizeOfImage = ROUND_UP(CurrentSectionHeader->VirtualAddress + + CurrentSectionHeader->Misc.VirtualSize, + OutOptHeader->SectionAlignment); + (OutFileHeader->NumberOfSections)++; + + PaddedRosSym = malloc(RosSymFileLength); + if (NULL == PaddedRosSym) + { + fprintf(stderr, "Failed to allocate %lu bytes for padded .rossym\n", RosSymFileLength); + return 1; + } + memcpy(PaddedRosSym, RosSymSection, RosSymLength); + memset((char *) PaddedRosSym + RosSymLength, '\0', RosSymFileLength - RosSymLength); + + CheckSum = 0; + for (i = 0; i < StartOfRawData / 2; i++) + { + CheckSum += ((unsigned short*) OutHeader)[i]; + CheckSum = 0xffff & (CheckSum + (CheckSum >> 16)); + } + Length = StartOfRawData; + for (Section = 0; Section < OutFileHeader->NumberOfSections; Section++) + { + if (OutRelocSection == OutSectionHeaders + Section) + { + Data = (void *) ProcessedRelocs; + } + else if (Section + 1 == OutFileHeader->NumberOfSections) + { + Data = (void *) PaddedRosSym; + } + else + { + Data = (void *) ((char *) InData + OutSectionHeaders[Section].PointerToRawData); + } + for (i = 0; i < OutSectionHeaders[Section].SizeOfRawData / 2; i++) + { + CheckSum += ((unsigned short*) Data)[i]; + CheckSum = 0xffff & (CheckSum + (CheckSum >> 16)); + } + Length += OutSectionHeaders[Section].SizeOfRawData; + } + CheckSum += Length; + OutOptHeader->CheckSum = CheckSum; + + if (fwrite(OutHeader, 1, StartOfRawData, OutFile) != StartOfRawData) + { + perror("Error writing output header\n"); + free(OutHeader); + return 1; + } + + for (Section = 0; Section < OutFileHeader->NumberOfSections; Section++) + { + if (0 != OutSectionHeaders[Section].SizeOfRawData) + { + fseek(OutFile, OutSectionHeaders[Section].PointerToRawData, SEEK_SET); + if (OutRelocSection == OutSectionHeaders + Section) + { + Data = (void *) ProcessedRelocs; + } + else if (Section + 1 == OutFileHeader->NumberOfSections) + { + Data = (void *) PaddedRosSym; + } + else + { + Data = (void *) ((char *) InData + OutSectionHeaders[Section].PointerToRawData); + } + if (fwrite(Data, 1, OutSectionHeaders[Section].SizeOfRawData, OutFile) != + OutSectionHeaders[Section].SizeOfRawData) + { + perror("Error writing section data\n"); + free(PaddedRosSym); + free(OutHeader); + return 1; + } + } + } + + free(PaddedRosSym); + free(OutHeader); + + return 0; +} int main(int argc, char* argv[]) { - SYMBOLFILE_HEADER SymbolFileHeader; - IMAGE_DOS_HEADER PEDosHeader; - IMAGE_FILE_HEADER PEFileHeader; + PSYMBOLFILE_HEADER SymbolFileHeader; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_FILE_HEADER PEFileHeader; PIMAGE_OPTIONAL_HEADER PEOptHeader; PIMAGE_SECTION_HEADER PESectionHeaders; ULONG ImageBase; - PVOID SymbolsBase; - ULONG SymbolsLength; - PVOID SymbolStringsBase; - ULONG SymbolStringsLength; - ULONG Idx; + void *StabBase; + ULONG StabsLength; + void *StabStringBase; + ULONG StabStringsLength; + void *CoffBase; + ULONG CoffsLength; + void *CoffStringBase; + ULONG CoffStringsLength; char* path1; char* path2; FILE* in; FILE* out; int n_in; - int n_out; - PSTAB_ENTRY StabEntry; - ULONG Count; - ULONG i; - ULONG SymbolsCount; - PSTR_ENTRY StrEntry; - ULONG StrCount; - ULONG j; + void *StringBase; + ULONG StringsLength; + ULONG StabSymbolsCount; + PROSSYM_ENTRY StabSymbols; + ULONG CoffSymbolsCount; + PROSSYM_ENTRY CoffSymbols; + ULONG MergedSymbolsCount; + PROSSYM_ENTRY MergedSymbols; + long FileSize; + void *FileData; + ULONG RosSymLength; + void *RosSymSection; - if (argc != 3) - { - fprintf(stderr, "Too many arguments\n"); - exit(1); - } + if (3 != argc) + { + fprintf(stderr, "Usage: rsym \n"); + exit(1); + } - path1 = convert_path(argv[1]); - path2 = convert_path(argv[2]); + path1 = convert_path(argv[1]); + path2 = convert_path(argv[2]); - in = fopen(path1, "rb"); - if (in == NULL) - { - perror("Cannot open input file"); - exit(1); - } - - out = fopen(path2, "wb"); - if (out == NULL) - { - perror("Cannot open output file"); - fclose(in); - exit(1); - } + in = fopen(path1, "rb"); + if (in == NULL) + { + perror("Cannot open input file"); + exit(1); + } + fseek(in, 0L, SEEK_END); + FileSize = ftell(in); + fseek(in, 0L, SEEK_SET); + FileData = malloc(FileSize); + if (NULL == FileData) + { + fclose(in); + fprintf(stderr, "Can't allocate %ld bytes to read input file\n", FileSize); + exit(1); + } + n_in = fread(FileData, 1, FileSize, in); + if (n_in != FileSize) + { + perror("Error reading from input file"); + free(FileData); + fclose(in); + exit(1); + } + fclose(in); /* Check if MZ header exists */ - n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in); - if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L) + PEDosHeader = (PIMAGE_DOS_HEADER) FileData; + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L) { perror("Input file is not a PE image.\n"); + free(FileData); + exit(1); } - /* Read PE file header */ + /* Locate PE file header */ /* sizeof(ULONG) = sizeof(MAGIC) */ - fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET); - n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in); + PEFileHeader = (PIMAGE_FILE_HEADER)((char *) FileData + PEDosHeader->e_lfanew + sizeof(ULONG)); - /* Read optional header */ - PEOptHeader = malloc(PEFileHeader.SizeOfOptionalHeader); - fread ( PEOptHeader, 1, PEFileHeader.SizeOfOptionalHeader, in ); + /* Locate optional header */ + PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); ImageBase = PEOptHeader->ImageBase; - /* Read PE section headers */ - PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); - fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET); - n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in); + /* Locate PE section headers */ + PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader); - /* Copy .stab and .stabstr sections if available */ - SymbolsBase = NULL; - SymbolsLength = 0; - SymbolStringsBase = NULL; - SymbolStringsLength = 0; - - for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++) + if (GetStabInfo(FileData, PEFileHeader, PESectionHeaders, &StabsLength, &StabBase, + &StabStringsLength, &StabStringBase)) { - //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); - if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0) - && (PESectionHeaders[Idx].Name[5] == 0)) - { - //printf(".stab section found. Size %d\n", - // PESectionHeaders[Idx].SizeOfRawData); - - SymbolsLength = PESectionHeaders[Idx].SizeOfRawData; - SymbolsBase = malloc(SymbolsLength); - - fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); - n_in = fread(SymbolsBase, 1, SymbolsLength, in); - } - - if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) - { - //printf(".stabstr section found. Size %d\n", - // PESectionHeaders[Idx].SizeOfRawData); - - SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData; - SymbolStringsBase = malloc(SymbolStringsLength); - - fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); - n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in); - } + free(FileData); + exit(1); } - StabEntry = SymbolsBase; - SymbolsCount = SymbolsLength / sizeof(STAB_ENTRY); - Count = 0; - - for (i = 0; i < SymbolsCount; i++) + if (GetCoffInfo(FileData, PEFileHeader, PESectionHeaders, &CoffsLength, &CoffBase, + &CoffStringsLength, &CoffStringBase)) { - switch ( StabEntry[i].n_type ) - { - case N_FUN: - if ( StabEntry[i].n_desc == 0 ) // line # 0 isn't valid - continue; - break; - case N_SLINE: - break; - case N_SO: - break; - default: - continue; - } - memmove(&StabEntry[Count], &StabEntry[i], sizeof(STAB_ENTRY)); - if ( StabEntry[Count].n_value >= ImageBase ) - StabEntry[Count].n_value -= ImageBase; - Count++; + free(FileData); + exit(1); } - StrEntry = malloc(sizeof(STR_ENTRY) * Count); - StrCount = 0; - - for (i = 0; i < Count; i++) + StringBase = malloc(1 + StabStringsLength + CoffStringsLength + + (CoffsLength / sizeof(ROSSYM_ENTRY)) * (E_SYMNMLEN + 1)); + if (NULL == StringBase) { - for (j = 0; j < StrCount; j++) - { - if (StabEntry[i].n_strx == StrEntry[j].OldOffset) - { - StabEntry[i].n_strx = StrEntry[j].NewOffset; - break; - } - } - if (j >= StrCount) - { - StrEntry[StrCount].OldOffset = StabEntry[i].n_strx; - StrEntry[StrCount].Name = (char*)SymbolStringsBase + StrEntry[StrCount].OldOffset; - StrEntry[StrCount].Length = strlen(StrEntry[StrCount].Name) + 1; - if (StrCount == 0) - { - StrEntry[StrCount].NewOffset = 0; - } - else - { - StrEntry[StrCount].NewOffset = StrEntry[StrCount-1].NewOffset + StrEntry[StrCount-1].Length; - } - StabEntry[i].n_strx = StrEntry[StrCount].NewOffset; - StrCount++; - } + free(FileData); + fprintf(stderr, "Failed to allocate memory for strings table\n"); + exit(1); + } + /* Make offset 0 into an empty string */ + *((char *) StringBase) = '\0'; + StringsLength = 1; + + if (ConvertStabs(&StabSymbolsCount, &StabSymbols, &StringsLength, StringBase, + StabsLength, StabBase, StabStringsLength, StabStringBase, + ImageBase, PEFileHeader, PESectionHeaders)) + { + free(StringBase); + free(FileData); + fprintf(stderr, "Failed to allocate memory for strings table\n"); + exit(1); } - SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER); - SymbolFileHeader.StabsLength = Count * sizeof(STAB_ENTRY); - SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolFileHeader.StabsLength; - SymbolFileHeader.StabstrLength = StrEntry[StrCount-1].NewOffset + StrEntry[StrCount-1].Length; - - n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out); - n_out = fwrite(SymbolsBase, 1, SymbolFileHeader.StabsLength, out); - for (i = 0; i < StrCount; i++) + if (ConvertCoffs(&CoffSymbolsCount, &CoffSymbols, &StringsLength, StringBase, + CoffsLength, CoffBase, CoffStringsLength, CoffStringBase, + ImageBase, PEFileHeader, PESectionHeaders)) { - fwrite(StrEntry[i].Name, 1, StrEntry[i].Length, out); + free(StabSymbols); + free(StringBase); + free(FileData); + exit(1); + } + + if (MergeStabsAndCoffs(&MergedSymbolsCount, &MergedSymbols, + StabSymbolsCount, StabSymbols, + CoffSymbolsCount, CoffSymbols)) + { + free(CoffSymbols); + free(StabSymbols); + free(StringBase); + free(FileData); + exit(1); + } + + free(CoffSymbols); + free(StabSymbols); + + RosSymLength = sizeof(SYMBOLFILE_HEADER) + MergedSymbolsCount * sizeof(ROSSYM_ENTRY) + + StringsLength; + RosSymSection = malloc(RosSymLength); + if (NULL == RosSymSection) + { + free(MergedSymbols); + free(StringBase); + free(FileData); + fprintf(stderr, "Unable to allocate memory for .rossym section\n"); + exit(1); + } + memset(RosSymSection, '\0', RosSymLength); + + SymbolFileHeader = (PSYMBOLFILE_HEADER) RosSymSection; + SymbolFileHeader->SymbolsOffset = sizeof(SYMBOLFILE_HEADER); + SymbolFileHeader->SymbolsLength = MergedSymbolsCount * sizeof(ROSSYM_ENTRY); + SymbolFileHeader->StringsOffset = SymbolFileHeader->SymbolsOffset + SymbolFileHeader->SymbolsLength; + SymbolFileHeader->StringsLength = StringsLength; + + memcpy((char *) RosSymSection + SymbolFileHeader->SymbolsOffset, MergedSymbols, + SymbolFileHeader->SymbolsLength); + memcpy((char *) RosSymSection + SymbolFileHeader->StringsOffset, StringBase, + SymbolFileHeader->StringsLength); + + free(MergedSymbols); + free(StringBase); + + out = fopen(path2, "wb"); + if (out == NULL) + { + perror("Cannot open output file"); + free(RosSymSection); + free(FileData); + exit(1); + } + + if (CreateOutputFile(out, FileData, PEDosHeader, PEFileHeader, PEOptHeader, + PESectionHeaders, RosSymLength, RosSymSection)) + { + fclose(out); + free(RosSymSection); + free(FileData); + exit(1); } fclose(out); - exit(0); + free(RosSymSection); + free(FileData); + + return 0; } + +/* EOF */ diff --git a/reactos/tools/wmc/makefile b/reactos/tools/wmc/makefile index 98dfc8cd8e4..679562a6338 100644 --- a/reactos/tools/wmc/makefile +++ b/reactos/tools/wmc/makefile @@ -25,8 +25,3 @@ $(WMC_TARGET): $(WMC_OBJECTS) $(WMC_OBJECTS): %.o : %.c ${host_gcc} $(WMC_HOST_CXXFLAGS) -c $< -o $@ - -.PHONY: wmc - -wmc: $(WMC_TARGET) - - diff --git a/reactos/w32api/include/ddk/ntagp.h b/reactos/w32api/include/ddk/ntagp.h new file mode 100644 index 00000000000..c507eae0372 --- /dev/null +++ b/reactos/w32api/include/ddk/ntagp.h @@ -0,0 +1,111 @@ +/* + * ntagp.h + * + * NT AGP bus driver interface + * + * This file is part of the w32api package. + * + * Contributors: + * Created by Gregor Anich + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTAGP_H +#define __NTAGP_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ntddk.h" +#include "video.h" + + +#define AGP_BUS_INTERFACE_V1 1L +#define AGP_BUS_INTERFACE_V2 2L + +/* Indicates wether the GART supports mapping of physical memory for the CPU */ +#define AGP_CAPABILITIES_MAP_PHYSICAL 0x00000001L + +typedef NTSTATUS +(DDKAPI *PAGP_BUS_COMMIT_MEMORY)( + IN PVOID AgpContext, + IN PVOID MapHandle, + IN ULONG NumberOfPages, + IN ULONG OffsetInPages, + IN OUT PMDL Mdl OPTIONAL, + OUT PHYSICAL_ADDRESS *MemoryBase); + +typedef NTSTATUS +(DDKAPI *PAGP_BUS_FREE_MEMORY)( + IN PVOID AgpContext, + IN PVOID MapHandle, + IN ULONG NumberOfPages, + IN ULONG OffsetInPages); + +typedef NTSTATUS +(DDKAPI *PAGP_BUS_RELEASE_MEMORY)( + IN PVOID AgpContext, + IN PVOID MapHandle); + +typedef NTSTATUS +(DDKAPI *PAGP_BUS_RESERVE_MEMORY)( + IN PVOID AgpContext, + IN ULONG NumberOfPages, + IN MEMORY_CACHING_TYPE MemoryType, + OUT PVOID *MapHandle, + OUT PHYSICAL_ADDRESS *PhysicalAddress OPTIONAL); + +typedef NTSTATUS +(DDKAPI *PAGP_BUS_SET_RATE)( + IN PVOID AgpContext, + IN ULONG AgpRate); + +typedef NTSTATUS +(DDKAPI *PAGP_GET_MAPPED_PAGES)( + IN PVOID AgpContext, + IN PVOID MapHandle, + IN ULONG NumberOfPages, + IN ULONG OffsetInPages, + OUT PMDL Mdl); + +typedef struct _AGP_BUS_INTERFACE_STANDARD { + USHORT Size; + USHORT Version; + PVOID AgpContext; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; + + ULONG Capabilities; + PAGP_BUS_RESERVE_MEMORY ReserveMemory; + PAGP_BUS_RELEASE_MEMORY ReleaseMemory; + PAGP_BUS_COMMIT_MEMORY CommitMemory; + PAGP_BUS_FREE_MEMORY FreeMemory; + PAGP_GET_MAPPED_PAGES GetMappedPages; + PAGP_BUS_SET_RATE SetRate; +} AGP_BUS_INTERFACE_STANDARD, *PAGP_BUS_INTERFACE_STANDARD; + +#define AGP_BUS_INTERFACE_V2_SIZE sizeof(AGP_BUS_INTERFACE_STANDARD) +#define AGP_BUS_INTERFACE_V1_SIZE \ + (AGP_BUS_INTERFACE_V2_SIZE - sizeof(PAGP_BUS_SET_RATE)) + +#ifdef __cplusplus +} +#endif + +#endif /* __NTAGP_H */ + diff --git a/reactos/w32api/include/ddk/ntapi.h b/reactos/w32api/include/ddk/ntapi.h index 7b0812394bb..f2d8ac9e290 100644 --- a/reactos/w32api/include/ddk/ntapi.h +++ b/reactos/w32api/include/ddk/ntapi.h @@ -297,8 +297,8 @@ typedef struct _SYSTEM_PROCESSES { LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; + HANDLE ProcessId; + HANDLE InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; @@ -735,16 +735,16 @@ NTOSAPI NTSTATUS NTAPI ZwQuerySystemEnvironmentValue( - IN PUNICODE_STRING Name, - OUT PVOID Value, - IN ULONG ValueLength, - OUT PULONG ReturnLength OPTIONAL); + IN PUNICODE_STRING VariableName, + OUT PWSTR ValueBuffer, + IN ULONG ValueBufferLength, + OUT PULONG ReturnLength OPTIONAL); NTOSAPI NTSTATUS NTAPI ZwSetSystemEnvironmentValue( - IN PUNICODE_STRING Name, + IN PUNICODE_STRING VariableName, IN PUNICODE_STRING Value); typedef enum _SHUTDOWN_ACTION { @@ -943,10 +943,10 @@ ZwQueryDirectoryObject( IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL); -typedef struct _DIRECTORY_BASIC_INFORMATION { +typedef struct _OBJECT_DIRECTORY_INFORMATION { UNICODE_STRING ObjectName; UNICODE_STRING ObjectTypeName; -} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION; +} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; NTOSAPI NTSTATUS @@ -1461,8 +1461,8 @@ typedef struct _PROCESS_BASIC_INFORMATION { PPEB PebBaseAddress; KAFFINITY AffinityMask; KPRIORITY BasePriority; - ULONG UniqueProcessId; - ULONG InheritedFromUniqueProcessId; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; typedef struct _PROCESS_ACCESS_TOKEN { diff --git a/reactos/w32api/include/ddk/ntifs.h b/reactos/w32api/include/ddk/ntifs.h index d6922bcddb2..3d8b2ec1114 100644 --- a/reactos/w32api/include/ddk/ntifs.h +++ b/reactos/w32api/include/ddk/ntifs.h @@ -1406,6 +1406,7 @@ typedef struct _QUERY_PATH_RESPONSE { ULONG LengthAccepted; } QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE; +#pragma pack(push,8) typedef struct _RETRIEVAL_POINTERS_BUFFER { ULONG ExtentCount; LARGE_INTEGER StartingVcn; @@ -1414,6 +1415,7 @@ typedef struct _RETRIEVAL_POINTERS_BUFFER { LARGE_INTEGER Lcn; } Extents[1]; } RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; +#pragma pack(pop) typedef struct _RTL_SPLAY_LINKS { struct _RTL_SPLAY_LINKS *Parent; @@ -3287,7 +3289,7 @@ NTKERNELAPI NTSTATUS NTAPI PsLookupProcessByProcessId ( - IN PVOID ProcessId, + IN HANDLE ProcessId, OUT PEPROCESS *Process ); @@ -3345,9 +3347,9 @@ NTSYSAPI NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD ( - IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, - IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, - IN PULONG BufferLength + IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, + IN OUT PSECURITY_DESCRIPTOR_RELATIVE SelfRelativeSecurityDescriptor, + IN PULONG BufferLength ); NTSYSAPI @@ -3591,17 +3593,17 @@ NTSYSAPI NTSTATUS NTAPI RtlSelfRelativeToAbsoluteSD ( - IN PSECURITY_DESCRIPTOR SelfRelativeSD, - OUT PSECURITY_DESCRIPTOR AbsoluteSD, - IN PULONG AbsoluteSDSize, - IN PACL Dacl, - IN PULONG DaclSize, - IN PACL Sacl, - IN PULONG SaclSize, - IN PSID Owner, - IN PULONG OwnerSize, - IN PSID PrimaryGroup, - IN PULONG PrimaryGroupSize + IN PSECURITY_DESCRIPTOR_RELATIVE SelfRelativeSD, + OUT PSECURITY_DESCRIPTOR AbsoluteSD, + IN PULONG AbsoluteSDSize, + IN PACL Dacl, + IN PULONG DaclSize, + IN PACL Sacl, + IN PULONG SaclSize, + IN PSID Owner, + IN PULONG OwnerSize, + IN PSID PrimaryGroup, + IN PULONG PrimaryGroupSize ); #endif /* (VER_PRODUCTBUILD >= 2195) */ diff --git a/reactos/w32api/include/ddk/winddk.h b/reactos/w32api/include/ddk/winddk.h index 0fa70e5ee21..65b707d0dd5 100644 --- a/reactos/w32api/include/ddk/winddk.h +++ b/reactos/w32api/include/ddk/winddk.h @@ -5223,7 +5223,7 @@ NTOSAPI BOOLEAN DDKAPI RtlValidRelativeSecurityDescriptor( - IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, + IN PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptorInput, IN ULONG SecurityDescriptorLength, IN SECURITY_INFORMATION RequiredInformation); @@ -7607,7 +7607,7 @@ KeLeaveCriticalRegion( VOID); NTOSAPI -NTSTATUS +LONG DDKAPI KePulseEvent( IN PRKEVENT Event, diff --git a/reactos/w32api/include/mmsystem.h b/reactos/w32api/include/mmsystem.h index c001388fe52..423900fb540 100644 --- a/reactos/w32api/include/mmsystem.h +++ b/reactos/w32api/include/mmsystem.h @@ -190,6 +190,14 @@ extern "C" { #define WAVE_FORMAT_4S08 512 #define WAVE_FORMAT_4M16 1024 #define WAVE_FORMAT_4S16 2048 +#define WAVE_FORMAT_48M08 4096 +#define WAVE_FORMAT_48S08 8192 +#define WAVE_FORMAT_48M16 16384 +#define WAVE_FORMAT_48S16 32768 +#define WAVE_FORMAT_96M08 65536 +#define WAVE_FORMAT_96S08 131072 +#define WAVE_FORMAT_96M16 262144 +#define WAVE_FORMAT_96S16 524288 #define WAVE_FORMAT_PCM 1 #define MIDIERR_UNPREPARED MIDIERR_BASE #define MIDIERR_STILLPLAYING (MIDIERR_BASE+1) diff --git a/reactos/w32api/include/mswsock.h b/reactos/w32api/include/mswsock.h index 0cea0b84003..fa1e7307a18 100644 --- a/reactos/w32api/include/mswsock.h +++ b/reactos/w32api/include/mswsock.h @@ -54,6 +54,14 @@ BOOL PASCAL TransmitFile(SOCKET,HANDLE,DWORD,DWORD,LPOVERLAPPED,LPTRANSMIT_FILE_ BOOL PASCAL AcceptEx(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED); VOID PASCAL GetAcceptExSockaddrs(PVOID,DWORD,DWORD,DWORD,struct sockaddr**, LPINT, struct sockaddr**, LPINT); +#define WSAID_ACCEPTEX { 0xB5367DF0, 0xCBAC, 0x11CF, { 0x95, 0xCA, 0x00, 0x80, 0x5F, 0x48, 0xA1, 0x92 } } +#define WSAID_TRANSMITFILE { 0xB5367DF1, 0xCBAC, 0x11CF, { 0x95, 0xCA, 0x00, 0x80, 0x5F, 0x48, 0xA1, 0x92 } } +#define WSAID_GETACCEPTEXSOCKADDRS { 0xB5367DF2, 0xCBAC, 0x11CF, { 0x95, 0xCA, 0x00, 0x80, 0x5F, 0x48, 0xA1, 0x92 } } + +typedef BOOL (PASCAL *LPFN_TRANSMITFILE)(SOCKET,HANDLE,DWORD,DWORD,LPOVERLAPPED,LPTRANSMIT_FILE_BUFFERS,DWORD); +typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED); +typedef VOID (PASCAL *LPFN_GETACCEPTEXSOCKADDRS)(PVOID,DWORD,DWORD,DWORD,struct sockaddr**, LPINT, struct sockaddr**, LPINT); + #ifdef _WINSOCK2_H /* These require the winsock2 interface. */ #define TP_ELEMENT_FILE 1 diff --git a/reactos/w32api/include/ntdef.h b/reactos/w32api/include/ntdef.h index 0622cdd82ba..70cc41fe584 100644 --- a/reactos/w32api/include/ntdef.h +++ b/reactos/w32api/include/ntdef.h @@ -60,4 +60,5 @@ typedef struct _OBJECT_ATTRIBUTES { } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; #endif #define NOTHING +#define RTL_CONSTANT_STRING(s) { sizeof(s)-sizeof((s)[0]), sizeof(s), s } #endif /* _NTDEF_H */ diff --git a/reactos/w32api/include/shlobj.h b/reactos/w32api/include/shlobj.h index d100bc06abd..55308ffe07e 100644 --- a/reactos/w32api/include/shlobj.h +++ b/reactos/w32api/include/shlobj.h @@ -385,6 +385,9 @@ extern "C" { #define PCS_REMOVEDCHAR 0x00000002 #define PCS_TRUNCATED 0x00000004 #define PCS_PATHTOOLONG 0x00000008 +#define SHFMT_ERROR 0xFFFFFFFFL +#define SHFMT_CANCEL 0xFFFFFFFEL +#define SHFMT_NOFORMAT 0xFFFFFFFDL typedef ULONG SFGAOF; typedef DWORD SHGDNF; diff --git a/reactos/w32api/include/winbase.h b/reactos/w32api/include/winbase.h index a68cffb4def..ddeab7e1824 100644 --- a/reactos/w32api/include/winbase.h +++ b/reactos/w32api/include/winbase.h @@ -1457,6 +1457,7 @@ BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,LPBOOL,PACL*,LPBOOL); BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID*,LPBOOL); DWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR); BOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR,PSID*,LPBOOL); +DWORD WINAPI GetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR,PUCHAR); BOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,LPBOOL,PACL*,LPBOOL); DWORD WINAPI GetShortPathNameA(LPCSTR,LPSTR,DWORD); DWORD WINAPI GetShortPathNameW(LPCWSTR,LPWSTR,DWORD); @@ -1835,6 +1836,7 @@ BOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,SECURITY_DESCRIPTO BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,BOOL,PACL,BOOL); BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR,PSID,BOOL); BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR,PSID,BOOL); +DWORD WINAPI SetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR,PUCHAR); BOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,BOOL,PACL,BOOL); BOOL WINAPI SetStdHandle(DWORD,HANDLE); #define SetSwapAreaSize(w) (w) diff --git a/reactos/w32api/include/winerror.h b/reactos/w32api/include/winerror.h index 8d5b5f79b85..0ff2573a11b 100644 --- a/reactos/w32api/include/winerror.h +++ b/reactos/w32api/include/winerror.h @@ -2198,6 +2198,7 @@ #define RPC_E_CANTCALLOUT_ININPUTSYNCCALL ((HRESULT)0x8001010DL) #define RPC_E_WRONG_THREAD ((HRESULT)0x8001010EL) #define RPC_E_THREAD_NOT_INIT ((HRESULT)0x8001010FL) +#define RPC_E_INVALID_OBJREF ((HRESULT)0x8001011DL) #define RPC_E_UNEXPECTED ((HRESULT)0x8001FFFFL) #define NTE_BAD_UID ((HRESULT)0x80090001L) diff --git a/reactos/w32api/include/winnt.h b/reactos/w32api/include/winnt.h index 56f3ef0c540..3ad766c187b 100644 --- a/reactos/w32api/include/winnt.h +++ b/reactos/w32api/include/winnt.h @@ -2118,6 +2118,15 @@ typedef struct _SECURITY_DESCRIPTOR { PACL Sacl; PACL Dacl; } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; +typedef struct _SECURITY_DESCRIPTOR_RELATIVE { + UCHAR Revision; + UCHAR Sbz1; + SECURITY_DESCRIPTOR_CONTROL Control; + ULONG Owner; + ULONG Group; + ULONG Sacl; + ULONG Dacl; +} SECURITY_DESCRIPTOR_RELATIVE, *PSECURITY_DESCRIPTOR_RELATIVE, *PISECURITY_DESCRIPTOR_RELATIVE; typedef enum _TOKEN_INFORMATION_CLASS { TokenUser=1,TokenGroups,TokenPrivileges,TokenOwner, TokenPrimaryGroup,TokenDefaultDacl,TokenSource,TokenType,